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