xref: /freebsd-src/contrib/llvm-project/llvm/lib/Target/M68k/M68kInstrFormats.td (revision 647cbc5de815c5651677bf8582797f716ec7b48d)
104eeddc0SDimitry Andric//===-- M68kInstrFormats.td - M68k Instruction Formats -----*- tablegen -*-===//
2fe6060f1SDimitry Andric//                     The LLVM Compiler Infrastructure
3fe6060f1SDimitry Andric// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4fe6060f1SDimitry Andric// See https://llvm.org/LICENSE.txt for license information.
5fe6060f1SDimitry Andric// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6fe6060f1SDimitry Andric//===----------------------------------------------------------------------===//
7fe6060f1SDimitry Andric///
8fe6060f1SDimitry Andric/// \file
9fe6060f1SDimitry Andric/// This file contains M68k instruction formats.
10fe6060f1SDimitry Andric///
11fe6060f1SDimitry Andric/// Since M68k has quite a lot memory addressing modes there are more
12fe6060f1SDimitry Andric/// instruction prefixes than just i, r and m:
13fe6060f1SDimitry Andric/// TSF  Since     Form                     Letter  Description
14fe6060f1SDimitry Andric///  00   M68000    Dn or An                 r       any register
15fe6060f1SDimitry Andric///  01   M68000    Dn                       d       data register direct
16fe6060f1SDimitry Andric///  02   M68000    An                       a       address register direct
17fe6060f1SDimitry Andric///  03   M68000    (An)                     j       address register indirect
18fe6060f1SDimitry Andric///  04   M68000    (An)+                    o       address register indirect with postincrement
19fe6060f1SDimitry Andric///  05   M68000    -(An)                    e       address register indirect with predecrement
20*647cbc5dSDimitry Andric///  06   M68000    (d16,An)                 p       address register indirect with displacement
21*647cbc5dSDimitry Andric///  10   M68000    (d8,An,Xn.L)             f       address register indirect with index and scale = 1
22*647cbc5dSDimitry Andric///  07   M68000    (d8,An,Xn.W)             F       address register indirect with index and scale = 1
23*647cbc5dSDimitry Andric///  12   M68020    (d8,An,Xn.L,SCALE)       g       address register indirect with index
24*647cbc5dSDimitry Andric///  11   M68020    (d8,An,Xn.W,SCALE)       G       address register indirect with index
25fe6060f1SDimitry Andric///  14   M68020    ([bd,An],Xn.L,SCALE,od)  u       memory indirect postindexed mode
26fe6060f1SDimitry Andric///  13   M68020    ([bd,An],Xn.W,SCALE,od)  U       memory indirect postindexed mode
27fe6060f1SDimitry Andric///  16   M68020    ([bd,An,Xn.L,SCALE],od)  v       memory indirect preindexed mode
28fe6060f1SDimitry Andric///  15   M68020    ([bd,An,Xn.W,SCALE],od)  V       memory indirect preindexed mode
29fe6060f1SDimitry Andric///  20   M68000    abs.L                    b       absolute long address
30fe6060f1SDimitry Andric///  17   M68000    abs.W                    B       absolute short address
31*647cbc5dSDimitry Andric///  21   M68000    (d16,PC)                 q       program counter with displacement
32*647cbc5dSDimitry Andric///  23   M68000    (d8,PC,Xn.L)             k       program counter with index and scale = 1
33*647cbc5dSDimitry Andric///  22   M68000    (d8,PC,Xn.W)             K       program counter with index and scale = 1
34*647cbc5dSDimitry Andric///  25   M68020    (d8,PC,Xn.L,SCALE)       l       program counter with index
35*647cbc5dSDimitry Andric///  24   M68020    (d8,PC,Xn.W,SCALE)       L       program counter with index
36fe6060f1SDimitry Andric///  27   M68020    ([bd,PC],Xn.L,SCALE,od)  x       program counter memory indirect postindexed mode
37fe6060f1SDimitry Andric///  26   M68020    ([bd,PC],Xn.W,SCALE,od)  X       program counter memory indirect postindexed mode
38fe6060f1SDimitry Andric///  31   M68020    ([bd,PC,Xn.L,SCALE],od)  y       program counter memory indirect preindexed mode
39fe6060f1SDimitry Andric///  30   M68020    ([bd,PC,Xn.W,SCALE],od)  Y       program counter memory indirect preindexed mode
40fe6060f1SDimitry Andric///  32   M68000    #immediate               i       immediate data
41fe6060f1SDimitry Andric///
42fe6060f1SDimitry Andric/// NOTE that long form is always lowercase, word variants are capitalized
43fe6060f1SDimitry Andric///
44fe6060f1SDimitry Andric/// Operand can be qualified with size where appropriate to force a particular
45fe6060f1SDimitry Andric/// instruction encoding, e.g.:
46fe6060f1SDimitry Andric///    (i8,An,Xn.W)             f8      1 extension word
47fe6060f1SDimitry Andric///    (i16,An,Xn.W)            f16     2 extension words
48fe6060f1SDimitry Andric///    (i32,An,Xn.W)            f32     3 extension words
49fe6060f1SDimitry Andric///
50fe6060f1SDimitry Andric/// Form without size qualifier will adapt to operand size automatically, e.g.:
51fe6060f1SDimitry Andric///    (i,An,Xn.W)              f       1, 2 or 3 extension words
52fe6060f1SDimitry Andric///
53fe6060f1SDimitry Andric/// Some forms already imply a particular size of their operands, e.g.:
54fe6060f1SDimitry Andric///    (i,An)                   p       1 extension word and i is 16bit
55fe6060f1SDimitry Andric///
56fe6060f1SDimitry Andric/// Operand order follows x86 Intel order(destination before source), e.g.:
57fe6060f1SDimitry Andric///    MOV8df                   MOVE (4,A0,D0), D1
58fe6060f1SDimitry Andric///
59fe6060f1SDimitry Andric/// Number after instruction mnemonics determines the size of the data
60fe6060f1SDimitry Andric///
61fe6060f1SDimitry Andric//===----------------------------------------------------------------------===//
62fe6060f1SDimitry Andric
63fe6060f1SDimitry Andric/// ??? Is it possible to use this stuff for disassembling?
64fe6060f1SDimitry Andric/// NOTE 1: In case of conditional beads(DA, DAReg), cond part is able to
65fe6060f1SDimitry Andric/// consume any bit, though a more general instructions must be chosen, e.g.
66fe6060f1SDimitry Andric/// d -> r, a -> r
67fe6060f1SDimitry Andric
68fe6060f1SDimitry Andric//===----------------------------------------------------------------------===//
69fe6060f1SDimitry Andric// Encoding primitives
70fe6060f1SDimitry Andric//===----------------------------------------------------------------------===//
71fe6060f1SDimitry Andric
7281ad6265SDimitry Andricclass MxEncMemOp {
7381ad6265SDimitry Andric  dag EA = (ascend);
7481ad6265SDimitry Andric  dag Supplement = (ascend);
7581ad6265SDimitry Andric}
7681ad6265SDimitry Andric
7781ad6265SDimitry Andricclass MxEncBriefExt<string reg_opnd, string disp_opnd,
7881ad6265SDimitry Andric                    bit size_w_l = false, int scale = 1,
7981ad6265SDimitry Andric                    string disp_encoder = ""> {
8081ad6265SDimitry Andric  dag Value = (descend
8181ad6265SDimitry Andric    // D/A + REGISTER
8281ad6265SDimitry Andric    (operand "$"#reg_opnd, 4),
8381ad6265SDimitry Andric    // W/L
8481ad6265SDimitry Andric    size_w_l,
8581ad6265SDimitry Andric    // SCALE
8681ad6265SDimitry Andric    !cond(
8781ad6265SDimitry Andric      !eq(scale, 1) : 0b00,
8881ad6265SDimitry Andric      !eq(scale, 2) : 0b01,
8981ad6265SDimitry Andric      !eq(scale, 4) : 0b10,
9081ad6265SDimitry Andric      !eq(scale, 8) : 0b11
9181ad6265SDimitry Andric    ),
9281ad6265SDimitry Andric    0b0,
9381ad6265SDimitry Andric    // Displacement
9481ad6265SDimitry Andric    (operand "$"#disp_opnd, 8, (encoder disp_encoder))
9581ad6265SDimitry Andric  );
9681ad6265SDimitry Andric}
9781ad6265SDimitry Andric
9881ad6265SDimitry Andricclass MxEncAddrMode_d<string reg_opnd> : MxEncMemOp {
9981ad6265SDimitry Andric  let EA = (descend /*MODE*/0b000,
10081ad6265SDimitry Andric                    /*REGISTER*/(operand "$"#reg_opnd, 3));
10181ad6265SDimitry Andric}
10281ad6265SDimitry Andric
10381ad6265SDimitry Andricclass MxEncAddrMode_a<string reg_opnd> : MxEncMemOp {
10481ad6265SDimitry Andric  let EA = (descend /*MODE*/0b001,
10581ad6265SDimitry Andric                    /*REGISTER*/(operand "$"#reg_opnd, 3));
10681ad6265SDimitry Andric}
10781ad6265SDimitry Andric
10881ad6265SDimitry Andricclass MxEncAddrMode_r<string reg_opnd> : MxEncMemOp {
10981ad6265SDimitry Andric  let EA = (descend /*MODE without the last bit*/0b00,
11081ad6265SDimitry Andric                    /*REGISTER with D/A bit*/(operand "$"#reg_opnd, 4));
11181ad6265SDimitry Andric}
11281ad6265SDimitry Andric
11381ad6265SDimitry Andricclass MxEncAddrMode_k<string opnd_name> : MxEncMemOp {
11481ad6265SDimitry Andric  let EA = (descend /*MODE*/0b111,
11581ad6265SDimitry Andric                    /*REGISTER*/0b011);
11681ad6265SDimitry Andric
11781ad6265SDimitry Andric  let Supplement = MxEncBriefExt<opnd_name#".index", opnd_name#".disp",
11881ad6265SDimitry Andric                                 /*W/L*/true, /*SCALE*/1,
11981ad6265SDimitry Andric                                 "encodePCRelImm<8>">.Value;
12081ad6265SDimitry Andric}
12181ad6265SDimitry Andric
12281ad6265SDimitry Andricclass MxEncAddrMode_q<string opnd_name> : MxEncMemOp {
12381ad6265SDimitry Andric  let EA = (descend /*MODE*/0b111,
12481ad6265SDimitry Andric                     /*REGISTER*/0b010);
12581ad6265SDimitry Andric
12681ad6265SDimitry Andric  // 16-bit Displacement
12781ad6265SDimitry Andric  let Supplement = (operand "$"#opnd_name, 16,
12881ad6265SDimitry Andric                            (encoder "encodePCRelImm<16>"));
12981ad6265SDimitry Andric}
13081ad6265SDimitry Andric
13181ad6265SDimitry Andricclass MxEncAddrMode_p<string opnd_name> : MxEncMemOp {
13281ad6265SDimitry Andric  let EA = (descend /*MODE*/0b101,
13381ad6265SDimitry Andric                     /*REGISTER*/(operand "$"#opnd_name#".reg", 3));
13481ad6265SDimitry Andric
13581ad6265SDimitry Andric  // 16-bit Displacement
13681ad6265SDimitry Andric  let Supplement = (operand "$"#opnd_name#".disp", 16,
13781ad6265SDimitry Andric                            (encoder "encodeRelocImm<16>"));
13881ad6265SDimitry Andric}
13981ad6265SDimitry Andric
14081ad6265SDimitry Andricclass MxEncAddrMode_f<string opnd_name> : MxEncMemOp {
14181ad6265SDimitry Andric  let EA = (descend /*MODE*/0b110,
14281ad6265SDimitry Andric                     /*REGISTER*/(operand "$"#opnd_name#".reg", 3));
14381ad6265SDimitry Andric
14481ad6265SDimitry Andric  let Supplement = MxEncBriefExt<opnd_name#".index", opnd_name#".disp",
14581ad6265SDimitry Andric                                 /*W/L*/true, /*SCALE*/1,
14681ad6265SDimitry Andric                                 "encodeRelocImm<8>">.Value;
14781ad6265SDimitry Andric}
14881ad6265SDimitry Andric
14981ad6265SDimitry Andricclass MxEncAddrMode_j<string reg_opnd> : MxEncMemOp {
15081ad6265SDimitry Andric  let EA = (descend /*MODE*/0b010,
15181ad6265SDimitry Andric                     /*REGISTER*/(operand "$"#reg_opnd, 3));
15281ad6265SDimitry Andric}
15381ad6265SDimitry Andric
15481ad6265SDimitry Andricclass MxEncAddrMode_i<string opnd_name, int size> : MxEncMemOp {
15581ad6265SDimitry Andric  let EA = (descend /*MODE*/0b111,
15681ad6265SDimitry Andric                     /*REGISTER*/0b100);
15781ad6265SDimitry Andric
15881ad6265SDimitry Andric  // Immediate
15981ad6265SDimitry Andric  let Supplement =
16081ad6265SDimitry Andric    !cond(
161bdd1243dSDimitry Andric      !eq(size, 8)  : (descend 0b00000000, (operand "$"#opnd_name, 8,
162bdd1243dSDimitry Andric	                   (encoder "encodeRelocImm<8>"))),
163bdd1243dSDimitry Andric      !eq(size, 16) : (operand "$"#opnd_name, 16,
164bdd1243dSDimitry Andric                           (encoder "encodeRelocImm<16>")),
165bdd1243dSDimitry Andric      !eq(size, 32) : (operand "$"#opnd_name, 32,
166bdd1243dSDimitry Andric                           (encoder "encodeRelocImm<32>"),
167bdd1243dSDimitry Andric                           (decoder "DecodeImm32"))
16881ad6265SDimitry Andric    );
16981ad6265SDimitry Andric}
17081ad6265SDimitry Andric
17181ad6265SDimitry Andric// abs.W -> size_w_l = false
17281ad6265SDimitry Andric// abs.L -> size_w_l = true
17381ad6265SDimitry Andricclass MxEncAddrMode_abs<string opnd_name, bit size_w_l = false> : MxEncMemOp {
17481ad6265SDimitry Andric  let EA = (descend /*MODE*/0b111,
17581ad6265SDimitry Andric                    // Wrap the REGISTER part in another dag to make sure
17681ad6265SDimitry Andric                    // the dag assigned to EA only has two arguments. Such
17781ad6265SDimitry Andric                    // that it's easier for MOV instructions to reverse
17881ad6265SDimitry Andric                    // on its destination part.
17981ad6265SDimitry Andric                    /*REGISTER*/(descend 0b00, size_w_l));
18081ad6265SDimitry Andric
18181ad6265SDimitry Andric  // Absolute address
18281ad6265SDimitry Andric  let Supplement = !if(size_w_l,
18381ad6265SDimitry Andric    // abs.L
184bdd1243dSDimitry Andric    (operand "$"#opnd_name, 32, (encoder "encodeRelocImm<32>"),
185bdd1243dSDimitry Andric                                (decoder "DecodeImm32")),
18681ad6265SDimitry Andric    // abs.W
18781ad6265SDimitry Andric    (operand "$"#opnd_name, 16, (encoder "encodeRelocImm<16>"))
18881ad6265SDimitry Andric  );
18981ad6265SDimitry Andric}
19081ad6265SDimitry Andric
19181ad6265SDimitry Andricclass MxEncAddrMode_o<string reg_opnd> : MxEncMemOp {
19281ad6265SDimitry Andric  let EA = (descend /*MODE*/0b011,
19381ad6265SDimitry Andric                    /*REGISTER*/(operand "$"#reg_opnd, 3));
19481ad6265SDimitry Andric}
19581ad6265SDimitry Andric
19681ad6265SDimitry Andricclass MxEncAddrMode_e<string reg_opnd> : MxEncMemOp {
19781ad6265SDimitry Andric  let EA = (descend /*MODE*/0b100,
19881ad6265SDimitry Andric                    /*REGISTER*/(operand "$"#reg_opnd, 3));
19981ad6265SDimitry Andric}
20081ad6265SDimitry Andric
20106c3fb27SDimitry Andricclass MxEncSize<bits<2> value> {
20206c3fb27SDimitry Andric  bits<2> Value = value;
203fe6060f1SDimitry Andric}
204fe6060f1SDimitry Andricdef MxEncSize8  : MxEncSize<0b00>;
205fe6060f1SDimitry Andricdef MxEncSize16 : MxEncSize<0b01>;
206fe6060f1SDimitry Andricdef MxEncSize32 : MxEncSize<0b10>;
207fe6060f1SDimitry Andricdef MxEncSize64 : MxEncSize<0b11>;
208fe6060f1SDimitry Andric
209fe6060f1SDimitry Andric// M68k INSTRUCTION. Most instructions specify the location of an operand by
210fe6060f1SDimitry Andric// using the effective address field in the operation word. The effective address
211fe6060f1SDimitry Andric// is composed of two 3-bit fields: the mode field and the register field. The
212fe6060f1SDimitry Andric// value in the mode field selects the different address modes. The register
213fe6060f1SDimitry Andric// field contains the number of a register.  The effective address field may
214fe6060f1SDimitry Andric// require additional information to fully specify the operand. This additional
215fe6060f1SDimitry Andric// information, called the effective address extension, is contained in the
216fe6060f1SDimitry Andric// following word or words and is considered part of the instruction. The
217fe6060f1SDimitry Andric// effective address modes are grouped into three categories: register direct,
218fe6060f1SDimitry Andric// memory addressing, and special.
219fe6060f1SDimitry Andricclass MxInst<dag outs, dag ins,
220fe6060f1SDimitry Andric             string asmStr = "",
221fe6060f1SDimitry Andric             list<dag> pattern = [],
222fe6060f1SDimitry Andric             InstrItinClass itin = NoItinerary>
223fe6060f1SDimitry Andric    : Instruction {
224fe6060f1SDimitry Andric  let Namespace      = "M68k";
225fe6060f1SDimitry Andric  let OutOperandList = outs;
226fe6060f1SDimitry Andric  let InOperandList  = ins;
227fe6060f1SDimitry Andric  let AsmString      = asmStr;
228fe6060f1SDimitry Andric  let Pattern        = pattern;
229fe6060f1SDimitry Andric  let Itinerary      = itin;
230fe6060f1SDimitry Andric
23181ad6265SDimitry Andric  dag Inst = (ascend);
232fe6060f1SDimitry Andric
233fe6060f1SDimitry Andric  // Number of bytes
234fe6060f1SDimitry Andric  let Size = 0;
235fe6060f1SDimitry Andric
236fe6060f1SDimitry Andric  let UseLogicalOperandMappings = 1;
237fe6060f1SDimitry Andric}
238fe6060f1SDimitry Andric
239fe6060f1SDimitry Andric// M68k PSEUDO INSTRUCTION
240fe6060f1SDimitry Andricclass MxPseudo<dag outs, dag ins, list<dag> pattern = []>
241fe6060f1SDimitry Andric    : MxInst<outs, ins, "; error: this should not be emitted", pattern> {
242fe6060f1SDimitry Andric  let isPseudo = 1;
243fe6060f1SDimitry Andric}
244