//=== 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 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 b> : MxBead<0x1, b>; class MxBead2Bits b> : MxBead<0x2, b{0}, b{1}>; class MxBead3Bits b> : MxBead<0x3, b{0}, b{1}, b{2}>; class MxBead4Bits 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 o, bit a = 0> : MxBead<0x5, o{0}, o{1}, o{2}, a>; class MxBeadDA o, bit a = 0> : MxBead<0x6, o{0}, o{1}, o{2}, a>; class MxBeadReg o, bit a = 0> : MxBead<0x7, o{0}, o{1}, o{2}, a>; class MxBeadDReg o, bit a = 0> : MxBead<0x8, o{0}, o{1}, o{2}, a>; class MxBead8Disp 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 o, bit a = 0> : MxBead<0xA, o{0}, o{1}, o{2}, a>; class MxBead16Imm o, bit a = 0> : MxBead<0xB, o{0}, o{1}, o{2}, a>; class MxBead32Imm 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 o, bit a = 0> : MxBead<0xD, o{0}, o{1}, o{2}, a>; class MxEncoding { 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 value> : MxEncoding { let Value{7-0} = MxBead4Bits.Value; let Value{15-8} = MxBead4Bits.Value; let Value{23-16} = MxBead4Bits.Value; let Value{31-24} = MxBead4Bits.Value; } //===----------------------------------------------------------------------===// // Encoding composites // // These must be lowered to MxEncoding by instr specific wrappers // // HERE BE DRAGONS... //===----------------------------------------------------------------------===// class MxEncByte value> : MxEncoding { MxBead4Bits LO = MxBead4Bits; MxBead4Bits HI = MxBead4Bits; } 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 /// class MxEncEA { MxBead Reg = reg; MxBead Mode = mode; MxBead DA = da; } // 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, MxBead2Bits<0b00>>; def MxEncEAd_0: MxEncEA, MxBead2Bits<0b00>, MxBead1Bit<0>>; def MxEncEAa_0: MxEncEA, MxBead2Bits<0b00>, MxBead1Bit<1>>; def MxEncEAj_0: MxEncEA, MxBead2Bits<0b01>, MxBead1Bit<0>>; def MxEncEAo_0: MxEncEA, MxBead2Bits<0b01>, MxBead1Bit<1>>; def MxEncEAe_0: MxEncEA, MxBead2Bits<0b10>, MxBead1Bit<0>>; def MxEncEAp_0: MxEncEA, MxBead2Bits<0b10>, MxBead1Bit<1>>; def MxEncEAf_0: MxEncEA, MxBead2Bits<0b11>, MxBead1Bit<0>>; def MxEncEAa_0_reflected : MxEncEA, MxBead3Bits<0b001>>; def MxEncEAr_0_reflected : MxEncEA, MxBead2Bits<0b00>, MxBeadDA<0>>; def MxEncEAr_1: MxEncEA, MxBead2Bits<0b00>>; def MxEncEAd_1: MxEncEA, MxBead2Bits<0b00>, MxBead1Bit<0>>; def MxEncEAa_1: MxEncEA, MxBead2Bits<0b00>, MxBead1Bit<1>>; def MxEncEAj_1: MxEncEA, MxBead2Bits<0b01>, MxBead1Bit<0>>; def MxEncEAo_1: MxEncEA, MxBead2Bits<0b01>, MxBead1Bit<1>>; def MxEncEAe_1: MxEncEA, MxBead2Bits<0b10>, MxBead1Bit<0>>; def MxEncEAp_1: MxEncEA, MxBead2Bits<0b10>, MxBead1Bit<1>>; def MxEncEAf_1: MxEncEA, MxBead2Bits<0b11>, MxBead1Bit<0>>; def MxEncEAr_2: MxEncEA, MxBead2Bits<0b00>>; def MxEncEAd_2: MxEncEA, MxBead2Bits<0b00>, MxBead1Bit<0>>; def MxEncEAa_2: MxEncEA, MxBead2Bits<0b00>, MxBead1Bit<1>>; def MxEncEAj_2: MxEncEA, MxBead2Bits<0b01>, MxBead1Bit<0>>; def MxEncEAo_2: MxEncEA, MxBead2Bits<0b01>, MxBead1Bit<1>>; def MxEncEAe_2: MxEncEA, MxBead2Bits<0b10>, MxBead1Bit<0>>; def MxEncEAp_2: MxEncEA, MxBead2Bits<0b10>, MxBead1Bit<1>>; def MxEncEAf_2: MxEncEA, MxBead2Bits<0b11>, MxBead1Bit<0>>; def MxEncEAb : MxEncEA, MxBead2Bits<0b11>, MxBead1Bit<1>>; def MxEncEAq : MxEncEA, MxBead2Bits<0b11>, MxBead1Bit<1>>; def MxEncEAk : MxEncEA, MxBead2Bits<0b11>, MxBead1Bit<1>>; def MxEncEAi : MxEncEA, MxBead2Bits<0b11>, MxBead1Bit<1>>; // Allows you to specify each bit of opcode class MxEncOpMode { MxBead B0 = b0; MxBead B1 = b1; MxBead B2 = b2; } // op EA, Dn def MxOpMode8dEA : MxEncOpMode>; def MxOpMode16dEA : MxEncOpMode>; def MxOpMode32dEA : MxEncOpMode>; // op EA, An def MxOpMode16aEA : MxEncOpMode>; def MxOpMode32aEA : MxEncOpMode>; // 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, MxBeadDA<0>, MxBead1Bit<0>>; def MxOpMode32rEA : MxEncOpMode, MxBead1Bit<1>, MxBeadDA<0>>; // op Dn, EA def MxOpMode8EAd : MxEncOpMode>; def MxOpMode16EAd : MxEncOpMode>; def MxOpMode32EAd : MxEncOpMode>; // Represents two types of extension word: // - Imm extension word // - Brief extension word class MxEncExt { 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>; def MxExtI16_0 : MxEncExt>; def MxExtI32_0 : MxEncExt>; def MxExtI8_1 : MxEncExt>; def MxExtI16_1 : MxEncExt>; def MxExtI32_1 : MxEncExt>; def MxExtI8_2 : MxEncExt>; def MxExtI16_2 : MxEncExt>; def MxExtI32_2 : MxEncExt>; // NOTE They are all using Long Xn def MxExtBrief_0 : MxEncExt, MxBead1Bit<0b0>, MxBead2Bits<0b00>, MxBead1Bit<1>, MxBeadDAReg<0, 1>>; def MxExtBrief_1 : MxEncExt, MxBead1Bit<0b0>, MxBead2Bits<0b00>, MxBead1Bit<1>, MxBeadDAReg<1, 1>>; def MxExtBrief_2 : MxEncExt, MxBead1Bit<0b0>, MxBead2Bits<0b00>, MxBead1Bit<1>, MxBeadDAReg<2, 1>>; def MxExtBrief_3 : MxEncExt, MxBead1Bit<0b0>, MxBead2Bits<0b00>, MxBead1Bit<1>, MxBeadDAReg<3, 1>>; def MxExtBrief_4 : MxEncExt, MxBead1Bit<0b0>, MxBead2Bits<0b00>, MxBead1Bit<1>, MxBeadDAReg<4, 1>>; class MxEncSize value> : MxBead2Bits; def MxEncSize8 : MxEncSize<0b00>; def MxEncSize16 : MxEncSize<0b01>; def MxEncSize32 : MxEncSize<0b10>; def MxEncSize64 : MxEncSize<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 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; // Number of bytes let Size = 0; let UseLogicalOperandMappings = 1; } // M68k PSEUDO INSTRUCTION class MxPseudo pattern = []> : MxInst { let isPseudo = 1; }