1//===-- M68kInstrFormats.td - M68k Instruction Formats -----*- tablegen -*-===//
2//                     The LLVM Compiler Infrastructure
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//===----------------------------------------------------------------------===//
7///
8/// \file
9/// This file contains M68k instruction formats.
10///
11/// Since M68k has quite a lot memory addressing modes there are more
12/// instruction prefixes than just i, r and m:
13/// TSF  Since     Form                     Letter  Description
14///  00   M68000    Dn or An                 r       any register
15///  01   M68000    Dn                       d       data register direct
16///  02   M68000    An                       a       address register direct
17///  03   M68000    (An)                     j       address register indirect
18///  04   M68000    (An)+                    o       address register indirect with postincrement
19///  05   M68000    -(An)                    e       address register indirect with predecrement
20///  06   M68000    (d16,An)                 p       address register indirect with displacement
21///  10   M68000    (d8,An,Xn.L)             f       address register indirect with index and scale = 1
22///  07   M68000    (d8,An,Xn.W)             F       address register indirect with index and scale = 1
23///  12   M68020    (d8,An,Xn.L,SCALE)       g       address register indirect with index
24///  11   M68020    (d8,An,Xn.W,SCALE)       G       address register indirect with index
25///  14   M68020    ([bd,An],Xn.L,SCALE,od)  u       memory indirect postindexed mode
26///  13   M68020    ([bd,An],Xn.W,SCALE,od)  U       memory indirect postindexed mode
27///  16   M68020    ([bd,An,Xn.L,SCALE],od)  v       memory indirect preindexed mode
28///  15   M68020    ([bd,An,Xn.W,SCALE],od)  V       memory indirect preindexed mode
29///  20   M68000    abs.L                    b       absolute long address
30///  17   M68000    abs.W                    B       absolute short address
31///  21   M68000    (d16,PC)                 q       program counter with displacement
32///  23   M68000    (d8,PC,Xn.L)             k       program counter with index and scale = 1
33///  22   M68000    (d8,PC,Xn.W)             K       program counter with index and scale = 1
34///  25   M68020    (d8,PC,Xn.L,SCALE)       l       program counter with index
35///  24   M68020    (d8,PC,Xn.W,SCALE)       L       program counter with index
36///  27   M68020    ([bd,PC],Xn.L,SCALE,od)  x       program counter memory indirect postindexed mode
37///  26   M68020    ([bd,PC],Xn.W,SCALE,od)  X       program counter memory indirect postindexed mode
38///  31   M68020    ([bd,PC,Xn.L,SCALE],od)  y       program counter memory indirect preindexed mode
39///  30   M68020    ([bd,PC,Xn.W,SCALE],od)  Y       program counter memory indirect preindexed mode
40///  32   M68000    #immediate               i       immediate data
41///
42/// NOTE that long form is always lowercase, word variants are capitalized
43///
44/// Operand can be qualified with size where appropriate to force a particular
45/// instruction encoding, e.g.:
46///    (i8,An,Xn.W)             f8      1 extension word
47///    (i16,An,Xn.W)            f16     2 extension words
48///    (i32,An,Xn.W)            f32     3 extension words
49///
50/// Form without size qualifier will adapt to operand size automatically, e.g.:
51///    (i,An,Xn.W)              f       1, 2 or 3 extension words
52///
53/// Some forms already imply a particular size of their operands, e.g.:
54///    (i,An)                   p       1 extension word and i is 16bit
55///
56/// Operand order follows x86 Intel order(destination before source), e.g.:
57///    MOV8df                   MOVE (4,A0,D0), D1
58///
59/// Number after instruction mnemonics determines the size of the data
60///
61//===----------------------------------------------------------------------===//
62
63/// ??? Is it possible to use this stuff for disassembling?
64/// NOTE 1: In case of conditional beads(DA, DAReg), cond part is able to
65/// consume any bit, though a more general instructions must be chosen, e.g.
66/// d -> r, a -> r
67
68//===----------------------------------------------------------------------===//
69// Encoding primitives
70//===----------------------------------------------------------------------===//
71
72class MxEncMemOp {
73  dag EA = (ascend);
74  dag Supplement = (ascend);
75}
76
77class MxEncBriefExt<string reg_opnd, string disp_opnd,
78                    bit size_w_l = false, int scale = 1,
79                    string disp_encoder = ""> {
80  dag Value = (descend
81    // D/A + REGISTER
82    (operand "$"#reg_opnd, 4),
83    // W/L
84    size_w_l,
85    // SCALE
86    !cond(
87      !eq(scale, 1) : 0b00,
88      !eq(scale, 2) : 0b01,
89      !eq(scale, 4) : 0b10,
90      !eq(scale, 8) : 0b11
91    ),
92    0b0,
93    // Displacement
94    (operand "$"#disp_opnd, 8, (encoder disp_encoder))
95  );
96}
97
98class MxEncAddrMode_d<string reg_opnd> : MxEncMemOp {
99  let EA = (descend /*MODE*/0b000,
100                    /*REGISTER*/(operand "$"#reg_opnd, 3));
101}
102
103class MxEncAddrMode_a<string reg_opnd> : MxEncMemOp {
104  let EA = (descend /*MODE*/0b001,
105                    /*REGISTER*/(operand "$"#reg_opnd, 3));
106}
107
108class MxEncAddrMode_r<string reg_opnd> : MxEncMemOp {
109  let EA = (descend /*MODE without the last bit*/0b00,
110                    /*REGISTER with D/A bit*/(operand "$"#reg_opnd, 4));
111}
112
113class MxEncAddrMode_k<string opnd_name> : MxEncMemOp {
114  let EA = (descend /*MODE*/0b111,
115                    /*REGISTER*/0b011);
116
117  let Supplement = MxEncBriefExt<opnd_name#".index", opnd_name#".disp",
118                                 /*W/L*/true, /*SCALE*/1,
119                                 "encodePCRelImm<8>">.Value;
120}
121
122class MxEncAddrMode_q<string opnd_name> : MxEncMemOp {
123  let EA = (descend /*MODE*/0b111,
124                     /*REGISTER*/0b010);
125
126  // 16-bit Displacement
127  let Supplement = (operand "$"#opnd_name, 16,
128                            (encoder "encodePCRelImm<16>"));
129}
130
131class MxEncAddrMode_p<string opnd_name> : MxEncMemOp {
132  let EA = (descend /*MODE*/0b101,
133                     /*REGISTER*/(operand "$"#opnd_name#".reg", 3));
134
135  // 16-bit Displacement
136  let Supplement = (operand "$"#opnd_name#".disp", 16,
137                            (encoder "encodeRelocImm<16>"));
138}
139
140class MxEncAddrMode_f<string opnd_name> : MxEncMemOp {
141  let EA = (descend /*MODE*/0b110,
142                     /*REGISTER*/(operand "$"#opnd_name#".reg", 3));
143
144  let Supplement = MxEncBriefExt<opnd_name#".index", opnd_name#".disp",
145                                 /*W/L*/true, /*SCALE*/1,
146                                 "encodeRelocImm<8>">.Value;
147}
148
149class MxEncAddrMode_j<string reg_opnd> : MxEncMemOp {
150  let EA = (descend /*MODE*/0b010,
151                     /*REGISTER*/(operand "$"#reg_opnd, 3));
152}
153
154class MxEncAddrMode_i<string opnd_name, int size> : MxEncMemOp {
155  let EA = (descend /*MODE*/0b111,
156                     /*REGISTER*/0b100);
157
158  // Immediate
159  let Supplement =
160    !cond(
161      !eq(size, 8)  : (descend 0b00000000, (operand "$"#opnd_name, 8,
162	                   (encoder "encodeRelocImm<8>"))),
163      !eq(size, 16) : (operand "$"#opnd_name, 16,
164                           (encoder "encodeRelocImm<16>")),
165      !eq(size, 32) : (operand "$"#opnd_name, 32,
166                           (encoder "encodeRelocImm<32>"),
167                           (decoder "DecodeImm32"))
168    );
169}
170
171// abs.W -> size_w_l = false
172// abs.L -> size_w_l = true
173class MxEncAddrMode_abs<string opnd_name, bit size_w_l = false> : MxEncMemOp {
174  let EA = (descend /*MODE*/0b111,
175                    // Wrap the REGISTER part in another dag to make sure
176                    // the dag assigned to EA only has two arguments. Such
177                    // that it's easier for MOV instructions to reverse
178                    // on its destination part.
179                    /*REGISTER*/(descend 0b00, size_w_l));
180
181  // Absolute address
182  let Supplement = !if(size_w_l,
183    // abs.L
184    (operand "$"#opnd_name, 32, (encoder "encodeRelocImm<32>"),
185                                (decoder "DecodeImm32")),
186    // abs.W
187    (operand "$"#opnd_name, 16, (encoder "encodeRelocImm<16>"))
188  );
189}
190
191class MxEncAddrMode_o<string reg_opnd> : MxEncMemOp {
192  let EA = (descend /*MODE*/0b011,
193                    /*REGISTER*/(operand "$"#reg_opnd, 3));
194}
195
196class MxEncAddrMode_e<string reg_opnd> : MxEncMemOp {
197  let EA = (descend /*MODE*/0b100,
198                    /*REGISTER*/(operand "$"#reg_opnd, 3));
199}
200
201class MxEncSize<bits<2> value> {
202  bits<2> Value = value;
203}
204def MxEncSize8  : MxEncSize<0b00>;
205def MxEncSize16 : MxEncSize<0b01>;
206def MxEncSize32 : MxEncSize<0b10>;
207def MxEncSize64 : MxEncSize<0b11>;
208
209// M68k INSTRUCTION. Most instructions specify the location of an operand by
210// using the effective address field in the operation word. The effective address
211// is composed of two 3-bit fields: the mode field and the register field. The
212// value in the mode field selects the different address modes. The register
213// field contains the number of a register.  The effective address field may
214// require additional information to fully specify the operand. This additional
215// information, called the effective address extension, is contained in the
216// following word or words and is considered part of the instruction. The
217// effective address modes are grouped into three categories: register direct,
218// memory addressing, and special.
219class MxInst<dag outs, dag ins,
220             string asmStr = "",
221             list<dag> pattern = [],
222             InstrItinClass itin = NoItinerary>
223    : Instruction {
224  let Namespace      = "M68k";
225  let OutOperandList = outs;
226  let InOperandList  = ins;
227  let AsmString      = asmStr;
228  let Pattern        = pattern;
229  let Itinerary      = itin;
230
231  dag Inst = (ascend);
232
233  // Number of bytes
234  let Size = 0;
235
236  let UseLogicalOperandMappings = 1;
237}
238
239// M68k PSEUDO INSTRUCTION
240class MxPseudo<dag outs, dag ins, list<dag> pattern = []>
241    : MxInst<outs, ins, "; error: this should not be emitted", pattern> {
242  let isPseudo = 1;
243}
244