forked from OSchip/llvm-project
508 lines
21 KiB
TableGen
508 lines
21 KiB
TableGen
//===-- M68kInstrFormats.td - M68k Instruction Formats -----*- tablegen -*-===//
|
|
// The LLVM Compiler Infrastructure
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//===----------------------------------------------------------------------===//
|
|
///
|
|
/// \file
|
|
/// This file contains M68k instruction formats.
|
|
///
|
|
/// Since M68k has quite a lot memory addressing modes there are more
|
|
/// instruction prefixes than just i, r and m:
|
|
/// TSF Since Form Letter Description
|
|
/// 00 M68000 Dn or An r any register
|
|
/// 01 M68000 Dn d data register direct
|
|
/// 02 M68000 An a address register direct
|
|
/// 03 M68000 (An) j address register indirect
|
|
/// 04 M68000 (An)+ o address register indirect with postincrement
|
|
/// 05 M68000 -(An) e address register indirect with predecrement
|
|
/// 06 M68000 (i,An) p address register indirect with displacement
|
|
/// 10 M68000 (i,An,Xn.L) f address register indirect with index and scale = 1
|
|
/// 07 M68000 (i,An,Xn.W) F address register indirect with index and scale = 1
|
|
/// 12 M68020 (i,An,Xn.L,SCALE) g address register indirect with index
|
|
/// 11 M68020 (i,An,Xn.W,SCALE) G address register indirect with index
|
|
/// 14 M68020 ([bd,An],Xn.L,SCALE,od) u memory indirect postindexed mode
|
|
/// 13 M68020 ([bd,An],Xn.W,SCALE,od) U memory indirect postindexed mode
|
|
/// 16 M68020 ([bd,An,Xn.L,SCALE],od) v memory indirect preindexed mode
|
|
/// 15 M68020 ([bd,An,Xn.W,SCALE],od) V memory indirect preindexed mode
|
|
/// 20 M68000 abs.L b absolute long address
|
|
/// 17 M68000 abs.W B absolute short address
|
|
/// 21 M68000 (i,PC) q program counter with displacement
|
|
/// 23 M68000 (i,PC,Xn.L) k program counter with index and scale = 1
|
|
/// 22 M68000 (i,PC,Xn.W) K program counter with index and scale = 1
|
|
/// 25 M68020 (i,PC,Xn.L,SCALE) l program counter with index
|
|
/// 24 M68020 (i,PC,Xn.W,SCALE) L program counter with index
|
|
/// 27 M68020 ([bd,PC],Xn.L,SCALE,od) x program counter memory indirect postindexed mode
|
|
/// 26 M68020 ([bd,PC],Xn.W,SCALE,od) X program counter memory indirect postindexed mode
|
|
/// 31 M68020 ([bd,PC,Xn.L,SCALE],od) y program counter memory indirect preindexed mode
|
|
/// 30 M68020 ([bd,PC,Xn.W,SCALE],od) Y program counter memory indirect preindexed mode
|
|
/// 32 M68000 #immediate i immediate data
|
|
///
|
|
/// NOTE that long form is always lowercase, word variants are capitalized
|
|
///
|
|
/// Operand can be qualified with size where appropriate to force a particular
|
|
/// instruction encoding, e.g.:
|
|
/// (i8,An,Xn.W) f8 1 extension word
|
|
/// (i16,An,Xn.W) f16 2 extension words
|
|
/// (i32,An,Xn.W) f32 3 extension words
|
|
///
|
|
/// Form without size qualifier will adapt to operand size automatically, e.g.:
|
|
/// (i,An,Xn.W) f 1, 2 or 3 extension words
|
|
///
|
|
/// Some forms already imply a particular size of their operands, e.g.:
|
|
/// (i,An) p 1 extension word and i is 16bit
|
|
///
|
|
/// Operand order follows x86 Intel order(destination before source), e.g.:
|
|
/// MOV8df MOVE (4,A0,D0), D1
|
|
///
|
|
/// Number after instruction mnemonics determines the size of the data
|
|
///
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
/// ??? Is it possible to use this stuff for disassembling?
|
|
/// NOTE 1: In case of conditional beads(DA, DAReg), cond part is able to
|
|
/// consume any bit, though a more general instructions must be chosen, e.g.
|
|
/// d -> r, a -> r
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// Encoding primitives
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
class MxBead<bits<4> type, bit b4 = 0, bit b5 = 0, bit b6 = 0, bit b7 = 0> {
|
|
bits<8> Value = 0b00000000;
|
|
let Value{3-0} = type;
|
|
let Value{4} = b4;
|
|
let Value{5} = b5;
|
|
let Value{6} = b6;
|
|
let Value{7} = b7;
|
|
}
|
|
|
|
/// System beads, allow to control beading flow
|
|
def MxBeadTerm : MxBead<0x0, 0, 0, 0, 0>;
|
|
def MxBeadIgnore : MxBead<0x0, 1, 0, 0, 0>;
|
|
|
|
/// Add plain bit to the instruction
|
|
class MxBead1Bit <bits<1> b> : MxBead<0x1, b>;
|
|
class MxBead2Bits <bits<2> b> : MxBead<0x2, b{0}, b{1}>;
|
|
class MxBead3Bits <bits<3> b> : MxBead<0x3, b{0}, b{1}, b{2}>;
|
|
class MxBead4Bits <bits<4> b> : MxBead<0x4, b{0}, b{1}, b{2}, b{3}>;
|
|
|
|
/// bits<3> o - operand number
|
|
/// bit a - use alternative, used to select index register or
|
|
/// outer displacement/immediate
|
|
/// suffix NP means non-padded
|
|
class MxBeadDAReg <bits<3> o, bit a = 0> : MxBead<0x5, o{0}, o{1}, o{2}, a>;
|
|
class MxBeadDA <bits<3> o, bit a = 0> : MxBead<0x6, o{0}, o{1}, o{2}, a>;
|
|
class MxBeadReg <bits<3> o, bit a = 0> : MxBead<0x7, o{0}, o{1}, o{2}, a>;
|
|
class MxBeadDReg <bits<3> o, bit a = 0> : MxBead<0x8, o{0}, o{1}, o{2}, a>;
|
|
class MxBead8Disp <bits<3> o, bit a = 0> : MxBead<0x9, o{0}, o{1}, o{2}, a>;
|
|
|
|
/// Add Immediate to the instruction. 8-bit version is padded with zeros to fit
|
|
/// the word.
|
|
class MxBead8Imm <bits<3> o, bit a = 0> : MxBead<0xA, o{0}, o{1}, o{2}, a>;
|
|
class MxBead16Imm <bits<3> o, bit a = 0> : MxBead<0xB, o{0}, o{1}, o{2}, a>;
|
|
class MxBead32Imm <bits<3> o, bit a = 0> : MxBead<0xC, o{0}, o{1}, o{2}, a>;
|
|
|
|
/// Encodes an immediate 0-7(alt. 1-8) into 3 bit field
|
|
class MxBead3Imm <bits<3> o, bit a = 0> : MxBead<0xD, o{0}, o{1}, o{2}, a>;
|
|
|
|
|
|
class MxEncoding<MxBead n0 = MxBeadTerm, MxBead n1 = MxBeadTerm,
|
|
MxBead n2 = MxBeadTerm, MxBead n3 = MxBeadTerm,
|
|
MxBead n4 = MxBeadTerm, MxBead n5 = MxBeadTerm,
|
|
MxBead n6 = MxBeadTerm, MxBead n7 = MxBeadTerm,
|
|
MxBead n8 = MxBeadTerm, MxBead n9 = MxBeadTerm,
|
|
MxBead n10 = MxBeadTerm, MxBead n11 = MxBeadTerm,
|
|
MxBead n12 = MxBeadTerm, MxBead n13 = MxBeadTerm,
|
|
MxBead n14 = MxBeadTerm, MxBead n15 = MxBeadTerm,
|
|
MxBead n16 = MxBeadTerm, MxBead n17 = MxBeadTerm,
|
|
MxBead n18 = MxBeadTerm, MxBead n19 = MxBeadTerm,
|
|
MxBead n20 = MxBeadTerm, MxBead n21 = MxBeadTerm,
|
|
MxBead n22 = MxBeadTerm, MxBead n23 = MxBeadTerm> {
|
|
bits <192> Value;
|
|
let Value{7-0} = n0.Value;
|
|
let Value{15-8} = n1.Value;
|
|
let Value{23-16} = n2.Value;
|
|
let Value{31-24} = n3.Value;
|
|
let Value{39-32} = n4.Value;
|
|
let Value{47-40} = n5.Value;
|
|
let Value{55-48} = n6.Value;
|
|
let Value{63-56} = n7.Value;
|
|
let Value{71-64} = n8.Value;
|
|
let Value{79-72} = n9.Value;
|
|
let Value{87-80} = n10.Value;
|
|
let Value{95-88} = n11.Value;
|
|
let Value{103-96} = n12.Value;
|
|
let Value{111-104} = n13.Value;
|
|
let Value{119-112} = n14.Value;
|
|
let Value{127-120} = n15.Value;
|
|
let Value{135-128} = n16.Value;
|
|
let Value{143-136} = n17.Value;
|
|
let Value{151-144} = n18.Value;
|
|
let Value{159-152} = n19.Value;
|
|
let Value{167-160} = n20.Value;
|
|
let Value{175-168} = n21.Value;
|
|
let Value{183-176} = n22.Value;
|
|
let Value{191-184} = n23.Value;
|
|
}
|
|
|
|
class MxEncFixed<bits<16> value> : MxEncoding {
|
|
let Value{7-0} = MxBead4Bits<value{3-0}>.Value;
|
|
let Value{15-8} = MxBead4Bits<value{7-4}>.Value;
|
|
let Value{23-16} = MxBead4Bits<value{11-8}>.Value;
|
|
let Value{31-24} = MxBead4Bits<value{15-12}>.Value;
|
|
}
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// Encoding composites
|
|
//
|
|
// These must be lowered to MxEncoding by instr specific wrappers
|
|
//
|
|
// HERE BE DRAGONS...
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
class MxEncByte<bits<8> value> : MxEncoding {
|
|
MxBead4Bits LO = MxBead4Bits<value{3-0}>;
|
|
MxBead4Bits HI = MxBead4Bits<value{7-4}>;
|
|
}
|
|
|
|
def MxEncEmpty : MxEncoding;
|
|
|
|
|
|
/// M68k Standard Effective Address layout:
|
|
///
|
|
/// :-------------------:
|
|
/// | 5 4 3 | 2 1 0 |
|
|
/// | mode | reg |
|
|
/// :-------------------:
|
|
///
|
|
/// If the EA is a direct register mode, bits 4 and 5 are 0, and the register
|
|
/// number will be encoded in bit 0 - 3. Since the first address register's
|
|
/// (A0) register number is 8, we can easily tell data registers from
|
|
/// address registers by only inspecting bit 3 (i.e. if bit 3 is set, it's an
|
|
/// address register).
|
|
///
|
|
///
|
|
/// But MOVE instruction uses reversed layout for destination EA:
|
|
///
|
|
/// :-------------------:
|
|
/// | 5 4 3 | 2 1 0 |
|
|
/// | reg | mode |
|
|
/// :-------------------:
|
|
///
|
|
/// And this complicates things a bit because the DA bit is now separated from
|
|
/// the register and we have to encode those separately using MxBeadDA<opN>
|
|
///
|
|
class MxEncEA<MxBead reg, MxBead mode, MxBead da = MxBeadIgnore> {
|
|
MxBead Reg = reg;
|
|
MxBead Mode = mode;
|
|
MxBead DA = da;
|
|
}
|
|
|
|
class MxEncMemOp {
|
|
dag EA = (ascend);
|
|
dag Supplement = (ascend);
|
|
}
|
|
|
|
// FIXME: Is there a way to factorize the addressing mode suffix (i.e.
|
|
// 'r', 'd', 'a' etc.) and use something like multiclass to replace?
|
|
def MxEncEAr_0: MxEncEA<MxBeadDAReg<0>, MxBead2Bits<0b00>>;
|
|
def MxEncEAd_0: MxEncEA<MxBeadDReg<0>, MxBead2Bits<0b00>, MxBead1Bit<0>>;
|
|
def MxEncEAa_0: MxEncEA<MxBeadReg<0>, MxBead2Bits<0b00>, MxBead1Bit<1>>;
|
|
def MxEncEAj_0: MxEncEA<MxBeadReg<0>, MxBead2Bits<0b01>, MxBead1Bit<0>>;
|
|
def MxEncEAo_0: MxEncEA<MxBeadReg<0>, MxBead2Bits<0b01>, MxBead1Bit<1>>;
|
|
def MxEncEAe_0: MxEncEA<MxBeadReg<0>, MxBead2Bits<0b10>, MxBead1Bit<0>>;
|
|
def MxEncEAp_0: MxEncEA<MxBeadReg<0>, MxBead2Bits<0b10>, MxBead1Bit<1>>;
|
|
def MxEncEAf_0: MxEncEA<MxBeadReg<0>, MxBead2Bits<0b11>, MxBead1Bit<0>>;
|
|
|
|
def MxEncEAa_0_reflected : MxEncEA<MxBeadReg<0>, MxBead3Bits<0b001>>;
|
|
def MxEncEAr_0_reflected : MxEncEA<MxBeadReg<0>, MxBead2Bits<0b00>, MxBeadDA<0>>;
|
|
|
|
def MxEncEAr_1: MxEncEA<MxBeadDAReg<1>, MxBead2Bits<0b00>>;
|
|
def MxEncEAd_1: MxEncEA<MxBeadDReg<1>, MxBead2Bits<0b00>, MxBead1Bit<0>>;
|
|
def MxEncEAa_1: MxEncEA<MxBeadReg<1>, MxBead2Bits<0b00>, MxBead1Bit<1>>;
|
|
def MxEncEAj_1: MxEncEA<MxBeadReg<1>, MxBead2Bits<0b01>, MxBead1Bit<0>>;
|
|
def MxEncEAo_1: MxEncEA<MxBeadReg<1>, MxBead2Bits<0b01>, MxBead1Bit<1>>;
|
|
def MxEncEAe_1: MxEncEA<MxBeadReg<1>, MxBead2Bits<0b10>, MxBead1Bit<0>>;
|
|
def MxEncEAp_1: MxEncEA<MxBeadReg<1>, MxBead2Bits<0b10>, MxBead1Bit<1>>;
|
|
def MxEncEAf_1: MxEncEA<MxBeadReg<1>, MxBead2Bits<0b11>, MxBead1Bit<0>>;
|
|
|
|
def MxEncEAr_2: MxEncEA<MxBeadDAReg<2>, MxBead2Bits<0b00>>;
|
|
def MxEncEAd_2: MxEncEA<MxBeadDReg<2>, MxBead2Bits<0b00>, MxBead1Bit<0>>;
|
|
def MxEncEAa_2: MxEncEA<MxBeadReg<2>, MxBead2Bits<0b00>, MxBead1Bit<1>>;
|
|
def MxEncEAj_2: MxEncEA<MxBeadReg<2>, MxBead2Bits<0b01>, MxBead1Bit<0>>;
|
|
def MxEncEAo_2: MxEncEA<MxBeadReg<2>, MxBead2Bits<0b01>, MxBead1Bit<1>>;
|
|
def MxEncEAe_2: MxEncEA<MxBeadReg<2>, MxBead2Bits<0b10>, MxBead1Bit<0>>;
|
|
def MxEncEAp_2: MxEncEA<MxBeadReg<2>, MxBead2Bits<0b10>, MxBead1Bit<1>>;
|
|
def MxEncEAf_2: MxEncEA<MxBeadReg<2>, MxBead2Bits<0b11>, MxBead1Bit<0>>;
|
|
|
|
def MxEncEAb : MxEncEA<MxBead3Bits<0b001>, MxBead2Bits<0b11>, MxBead1Bit<1>>;
|
|
def MxEncEAq : MxEncEA<MxBead3Bits<0b010>, MxBead2Bits<0b11>, MxBead1Bit<1>>;
|
|
def MxEncEAk : MxEncEA<MxBead3Bits<0b011>, MxBead2Bits<0b11>, MxBead1Bit<1>>;
|
|
def MxEncEAi : MxEncEA<MxBead3Bits<0b100>, MxBead2Bits<0b11>, MxBead1Bit<1>>;
|
|
|
|
class MxEncBriefExt<string reg_opnd, string disp_opnd,
|
|
bit size_w_l = false, int scale = 1,
|
|
string disp_encoder = ""> {
|
|
dag Value = (descend
|
|
// D/A + REGISTER
|
|
(operand "$"#reg_opnd, 4),
|
|
// W/L
|
|
size_w_l,
|
|
// SCALE
|
|
!cond(
|
|
!eq(scale, 1) : 0b00,
|
|
!eq(scale, 2) : 0b01,
|
|
!eq(scale, 4) : 0b10,
|
|
!eq(scale, 8) : 0b11
|
|
),
|
|
0b0,
|
|
// Displacement
|
|
(operand "$"#disp_opnd, 8, (encoder disp_encoder))
|
|
);
|
|
}
|
|
|
|
class MxEncAddrMode_d<string reg_opnd> : MxEncMemOp {
|
|
let EA = (descend /*MODE*/0b000,
|
|
/*REGISTER*/(operand "$"#reg_opnd, 3));
|
|
}
|
|
|
|
class MxEncAddrMode_a<string reg_opnd> : MxEncMemOp {
|
|
let EA = (descend /*MODE*/0b001,
|
|
/*REGISTER*/(operand "$"#reg_opnd, 3));
|
|
}
|
|
|
|
class MxEncAddrMode_r<string reg_opnd> : MxEncMemOp {
|
|
let EA = (descend /*MODE without the last bit*/0b00,
|
|
/*REGISTER with D/A bit*/(operand "$"#reg_opnd, 4));
|
|
}
|
|
|
|
class MxEncAddrMode_k<string opnd_name> : MxEncMemOp {
|
|
let EA = (descend /*MODE*/0b111,
|
|
/*REGISTER*/0b011);
|
|
|
|
let Supplement = MxEncBriefExt<opnd_name#".index", opnd_name#".disp",
|
|
/*W/L*/true, /*SCALE*/1,
|
|
"encodePCRelImm<8>">.Value;
|
|
}
|
|
|
|
class MxEncAddrMode_q<string opnd_name> : MxEncMemOp {
|
|
let EA = (descend /*MODE*/0b111,
|
|
/*REGISTER*/0b010);
|
|
|
|
// 16-bit Displacement
|
|
let Supplement = (operand "$"#opnd_name, 16,
|
|
(encoder "encodePCRelImm<16>"));
|
|
}
|
|
|
|
class MxEncAddrMode_p<string opnd_name> : MxEncMemOp {
|
|
let EA = (descend /*MODE*/0b101,
|
|
/*REGISTER*/(operand "$"#opnd_name#".reg", 3));
|
|
|
|
// 16-bit Displacement
|
|
let Supplement = (operand "$"#opnd_name#".disp", 16,
|
|
(encoder "encodeRelocImm<16>"));
|
|
}
|
|
|
|
class MxEncAddrMode_f<string opnd_name> : MxEncMemOp {
|
|
let EA = (descend /*MODE*/0b110,
|
|
/*REGISTER*/(operand "$"#opnd_name#".reg", 3));
|
|
|
|
let Supplement = MxEncBriefExt<opnd_name#".index", opnd_name#".disp",
|
|
/*W/L*/true, /*SCALE*/1,
|
|
"encodeRelocImm<8>">.Value;
|
|
}
|
|
|
|
class MxEncAddrMode_j<string reg_opnd> : MxEncMemOp {
|
|
let EA = (descend /*MODE*/0b010,
|
|
/*REGISTER*/(operand "$"#reg_opnd, 3));
|
|
}
|
|
|
|
class MxEncAddrMode_i<string opnd_name, int size> : MxEncMemOp {
|
|
let EA = (descend /*MODE*/0b111,
|
|
/*REGISTER*/0b100);
|
|
|
|
// Immediate
|
|
let Supplement =
|
|
!cond(
|
|
!eq(size, 8) : (descend 0b00000000, (operand "$"#opnd_name, 8)),
|
|
!eq(size, 16) : (operand "$"#opnd_name, 16),
|
|
!eq(size, 32) : (ascend (slice "$"#opnd_name, 31, 16),
|
|
(slice "$"#opnd_name, 15, 0))
|
|
);
|
|
}
|
|
|
|
// abs.W -> size_w_l = false
|
|
// abs.L -> size_w_l = true
|
|
class MxEncAddrMode_abs<string opnd_name, bit size_w_l = false> : MxEncMemOp {
|
|
let EA = (descend /*MODE*/0b111,
|
|
// Wrap the REGISTER part in another dag to make sure
|
|
// the dag assigned to EA only has two arguments. Such
|
|
// that it's easier for MOV instructions to reverse
|
|
// on its destination part.
|
|
/*REGISTER*/(descend 0b00, size_w_l));
|
|
|
|
// Absolute address
|
|
let Supplement = !if(size_w_l,
|
|
// abs.L
|
|
(operand "$"#opnd_name, 32, (encoder "encodeRelocImm<32>")),
|
|
// abs.W
|
|
(operand "$"#opnd_name, 16, (encoder "encodeRelocImm<16>"))
|
|
);
|
|
}
|
|
|
|
class MxEncAddrMode_o<string reg_opnd> : MxEncMemOp {
|
|
let EA = (descend /*MODE*/0b011,
|
|
/*REGISTER*/(operand "$"#reg_opnd, 3));
|
|
}
|
|
|
|
class MxEncAddrMode_e<string reg_opnd> : MxEncMemOp {
|
|
let EA = (descend /*MODE*/0b100,
|
|
/*REGISTER*/(operand "$"#reg_opnd, 3));
|
|
}
|
|
|
|
// Allows you to specify each bit of opcode
|
|
class MxEncOpMode<MxBead b0, MxBead b1 = MxBeadIgnore, MxBead b2 = MxBeadIgnore> {
|
|
MxBead B0 = b0;
|
|
MxBead B1 = b1;
|
|
MxBead B2 = b2;
|
|
}
|
|
|
|
// op EA, Dn
|
|
def MxOpMode8dEA : MxEncOpMode<MxBead3Bits<0b000>>;
|
|
def MxOpMode16dEA : MxEncOpMode<MxBead3Bits<0b001>>;
|
|
def MxOpMode32dEA : MxEncOpMode<MxBead3Bits<0b010>>;
|
|
|
|
// op EA, An
|
|
def MxOpMode16aEA : MxEncOpMode<MxBead3Bits<0b011>>;
|
|
def MxOpMode32aEA : MxEncOpMode<MxBead3Bits<0b111>>;
|
|
|
|
// op EA, Rn
|
|
// As you might noticed this guy is special... Since M68k differentiates
|
|
// between Data and Address registers we required to use different OPMODE codes
|
|
// for Address registers DST operands. One way of dealing with it is to use
|
|
// separate tablegen instructions, but in this case it would force Register
|
|
// Allocator to use specific Register Classes and eventually will lead to
|
|
// superfluous moves. Another approach is to use reg-variadic encoding which will
|
|
// change OPMODE base on Register Class used. Luckily, all the bits that differ go
|
|
// from 0 to 1 and can be encoded with MxBeadDA.
|
|
// Basically, if the register used is of Data type these encodings will be
|
|
// the same as MxOpMode{16,32}dEA above and used with regular instructions(e.g. ADD,
|
|
// SUB), but if the register is of Address type the appropriate bits will flip and
|
|
// the instructions become of *A type(e.g ADDA, SUBA).
|
|
def MxOpMode16rEA : MxEncOpMode<MxBead1Bit<1>, MxBeadDA<0>, MxBead1Bit<0>>;
|
|
def MxOpMode32rEA : MxEncOpMode<MxBeadDA<0>, MxBead1Bit<1>, MxBeadDA<0>>;
|
|
|
|
// op Dn, EA
|
|
def MxOpMode8EAd : MxEncOpMode<MxBead3Bits<0b100>>;
|
|
def MxOpMode16EAd : MxEncOpMode<MxBead3Bits<0b101>>;
|
|
def MxOpMode32EAd : MxEncOpMode<MxBead3Bits<0b110>>;
|
|
|
|
|
|
// Represents two types of extension word:
|
|
// - Imm extension word
|
|
// - Brief extension word
|
|
class MxEncExt<MxBead imm = MxBeadIgnore, MxBead b8 = MxBeadIgnore,
|
|
MxBead scale = MxBeadIgnore, MxBead wl = MxBeadIgnore,
|
|
MxBead daReg = MxBeadIgnore> {
|
|
MxBead Imm = imm;
|
|
MxBead B8 = b8;
|
|
MxBead Scale = scale;
|
|
MxBead WL = wl;
|
|
MxBead DAReg = daReg;
|
|
}
|
|
|
|
def MxExtEmpty : MxEncExt;
|
|
|
|
// These handle encoding of displacement fields, absolute addresses and
|
|
// immediate values, since encoding for these categories is mainly the same,
|
|
// with exception of some weird immediates.
|
|
def MxExtI8_0 : MxEncExt<MxBead8Imm<0>>;
|
|
def MxExtI16_0 : MxEncExt<MxBead16Imm<0>>;
|
|
def MxExtI32_0 : MxEncExt<MxBead32Imm<0>>;
|
|
|
|
def MxExtI8_1 : MxEncExt<MxBead8Imm<1>>;
|
|
def MxExtI16_1 : MxEncExt<MxBead16Imm<1>>;
|
|
def MxExtI32_1 : MxEncExt<MxBead32Imm<1>>;
|
|
|
|
def MxExtI8_2 : MxEncExt<MxBead8Imm<2>>;
|
|
def MxExtI16_2 : MxEncExt<MxBead16Imm<2>>;
|
|
def MxExtI32_2 : MxEncExt<MxBead32Imm<2>>;
|
|
|
|
// NOTE They are all using Long Xn
|
|
def MxExtBrief_0 : MxEncExt<MxBead8Disp<0>, MxBead1Bit<0b0>,
|
|
MxBead2Bits<0b00>, MxBead1Bit<1>,
|
|
MxBeadDAReg<0, 1>>;
|
|
|
|
def MxExtBrief_1 : MxEncExt<MxBead8Disp<1>, MxBead1Bit<0b0>,
|
|
MxBead2Bits<0b00>, MxBead1Bit<1>,
|
|
MxBeadDAReg<1, 1>>;
|
|
|
|
def MxExtBrief_2 : MxEncExt<MxBead8Disp<2>, MxBead1Bit<0b0>,
|
|
MxBead2Bits<0b00>, MxBead1Bit<1>,
|
|
MxBeadDAReg<2, 1>>;
|
|
|
|
def MxExtBrief_3 : MxEncExt<MxBead8Disp<3>, MxBead1Bit<0b0>,
|
|
MxBead2Bits<0b00>, MxBead1Bit<1>,
|
|
MxBeadDAReg<3, 1>>;
|
|
|
|
def MxExtBrief_4 : MxEncExt<MxBead8Disp<4>, MxBead1Bit<0b0>,
|
|
MxBead2Bits<0b00>, MxBead1Bit<1>,
|
|
MxBeadDAReg<4, 1>>;
|
|
|
|
class MxEncSize<bits<2> value> : MxBead2Bits<value>;
|
|
def MxEncSize8 : MxEncSize<0b00>;
|
|
def MxEncSize16 : MxEncSize<0b01>;
|
|
def MxEncSize32 : MxEncSize<0b10>;
|
|
def MxEncSize64 : MxEncSize<0b11>;
|
|
|
|
// TODO: Remove "New" in the name after the codebead-based
|
|
// representation is deprecated.
|
|
class MxNewEncSize<bits<2> value> {
|
|
bits<2> Value = value;
|
|
}
|
|
def MxNewEncSize8 : MxNewEncSize<0b00>;
|
|
def MxNewEncSize16 : MxNewEncSize<0b01>;
|
|
def MxNewEncSize32 : MxNewEncSize<0b10>;
|
|
def MxNewEncSize64 : MxNewEncSize<0b11>;
|
|
|
|
// M68k INSTRUCTION. Most instructions specify the location of an operand by
|
|
// using the effective address field in the operation word. The effective address
|
|
// is composed of two 3-bit fields: the mode field and the register field. The
|
|
// value in the mode field selects the different address modes. The register
|
|
// field contains the number of a register. The effective address field may
|
|
// require additional information to fully specify the operand. This additional
|
|
// information, called the effective address extension, is contained in the
|
|
// following word or words and is considered part of the instruction. The
|
|
// effective address modes are grouped into three categories: register direct,
|
|
// memory addressing, and special.
|
|
class MxInst<dag outs, dag ins,
|
|
string asmStr = "",
|
|
list<dag> pattern = [],
|
|
MxEncoding beads = MxEncEmpty,
|
|
InstrItinClass itin = NoItinerary>
|
|
: Instruction {
|
|
let Namespace = "M68k";
|
|
let OutOperandList = outs;
|
|
let InOperandList = ins;
|
|
let AsmString = asmStr;
|
|
let Pattern = pattern;
|
|
let Itinerary = itin;
|
|
|
|
// Byte stream
|
|
field bits<192> Beads = beads.Value;
|
|
dag Inst = (ascend);
|
|
|
|
// Number of bytes
|
|
let Size = 0;
|
|
|
|
let UseLogicalOperandMappings = 1;
|
|
}
|
|
|
|
// M68k PSEUDO INSTRUCTION
|
|
class MxPseudo<dag outs, dag ins, list<dag> pattern = []>
|
|
: MxInst<outs, ins, "; error: this should not be emitted", pattern> {
|
|
let isPseudo = 1;
|
|
}
|