190 lines · plain
1// RUN: llvm-tblgen -gen-disassembler -I %p/../../../include %s | FileCheck %s --check-prefix=CHECK-DEFAULT2// RUN: llvm-tblgen -gen-disassembler -specialize-decoders-per-bitwidth -I %p/../../../include %s | FileCheck %s --check-prefix=CHECK-SPECIALIZE-NO-TABLE3// RUN: llvm-tblgen -gen-disassembler -specialize-decoders-per-bitwidth -use-fn-table-in-decode-to-mcinst -I %p/../../../include %s | FileCheck %s --check-prefix=CHECK-SPECIALIZE-TABLE4 5 6include "llvm/Target/Target.td"7 8def archInstrInfo : InstrInfo { }9 10def arch : Target {11 let InstructionSet = archInstrInfo;12}13 14let Namespace = "arch" in {15 def R0 : Register<"r0">;16 def R1 : Register<"r1">;17 def R2 : Register<"r2">;18 def R3 : Register<"r3">;19}20def Regs : RegisterClass<"Regs", [i32], 32, (add R0, R1, R2, R3)>;21 22// Bit 0 of the encoding determines the size (8 or 16 bits).23// Bits {3..1} define the number of operands encoded.24class Instruction8Bit<int NumOps> : Instruction {25 let Size = 1;26 let OutOperandList = (outs);27 field bits<8> Inst;28 let Inst{0} = 0;29 let Inst{3-1} = NumOps;30}31 32class Instruction16Bit<int NumOps> : Instruction {33 let Size = 2;34 let OutOperandList = (outs);35 field bits<16> Inst;36 let Inst{0} = 1;37 let Inst{3-1} = NumOps;38}39 40// Define instructions to generate 4 cases in decodeToMCInst.41// Each register operand needs 2 bits to encode.42 43// An instruction with no inputs.44def Inst0 : Instruction8Bit<0> {45 let Inst{7-4} = 0;46 let InOperandList = (ins);47 let AsmString = "Inst0";48}49 50// An instruction with a single input.51def Inst1 : Instruction8Bit<1> {52 bits<2> r0;53 let Inst{5-4} = r0;54 let Inst{7-6} = 0;55 let InOperandList = (ins Regs:$r0);56 let AsmString = "Inst1";57}58 59// An instruction with two inputs.60def Inst2 : Instruction16Bit<2> {61 bits<2> r0;62 bits<2> r1;63 let Inst{5-4} = r0;64 let Inst{7-6} = r1;65 let Inst{15-8} = 0;66 let InOperandList = (ins Regs:$r0, Regs:$r1);67 let AsmString = "Inst2";68}69 70// An instruction with three inputs. .71def Inst3 : Instruction16Bit<3> {72 bits<2> r0;73 bits<2> r1;74 bits<2> r2;75 let Inst{5-4} = r0;76 let Inst{7-6} = r1;77 let Inst{9-8} = r2;78 let Inst{15-10} = 0;79 let InOperandList = (ins Regs:$r0, Regs:$r1, Regs:$r2);80 let AsmString = "Inst3";81}82 83// -----------------------------------------------------------------------------84// In the default case, we emit a single decodeToMCinst function and DecodeIdx85// is shared across all bitwidths.86 87// CHECK-DEFAULT-LABEL: DecoderTable888// CHECK-DEFAULT: using decoder 089// CHECK-DEFAULT: using decoder 190// CHECK-DEFAULT: };91 92// CHECK-DEFAULT-LABEL: DecoderTable1693// CHECK-DEFAULT: using decoder 294// CHECK-DEFAULT: using decoder 395// CHECK-DEFAULT: };96 97// CHECK-DEFAULT-LABEL: template <typename InsnType>98// CHECK-DEFAULT-NEXT: static DecodeStatus decodeToMCInst99// CHECK-DEFAULT: case 0100// CHECK-DEFAULT: case 1101// CHECK-DEFAULT: case 2102// CHECK-DEFAULT: case 3103 104// -----------------------------------------------------------------------------105// When we specialize per bitwidth, we emit 2 decodeToMCInst functions and106// DecodeIdx is assigned per bit width.107 108// CHECK-SPECIALIZE-NO-TABLE-LABEL: DecoderTable8109// CHECK-SPECIALIZE-NO-TABLE: 8, // 0: BitWidth 8110// CHECK-SPECIALIZE-NO-TABLE: using decoder 0111// CHECK-SPECIALIZE-NO-TABLE: using decoder 1112// CHECK-SPECIALIZE-NO-TABLE: };113 114// CHECK-SPECIALIZE-NO-TABLE-LABEL: template <typename InsnType>115// CHECK-SPECIALIZE-NO-TABLE-NEXT: static std::enable_if_t<InsnBitWidth<InsnType> == 8, DecodeStatus>116// CHECK-SPECIALIZE-NO-TABLE-NEXT: decodeToMCInst117// CHECK-SPECIALIZE-NO-TABLE: case 0118// CHECK-SPECIALIZE-NO-TABLE: case 1119 120// CHECK-SPECIALIZE-NO-TABLE-LABEL: DecoderTable16121// CHECK-SPECIALIZE-NO-TABLE: 16, // 0: BitWidth 16122// CHECK-SPECIALIZE-NO-TABLE: using decoder 0123// CHECK-SPECIALIZE-NO-TABLE: using decoder 1124// CHECK-SPECIALIZE-NO-TABLE: };125 126// CHECK-SPECIALIZE-NO-TABLE-LABEL: template <typename InsnType>127// CHECK-SPECIALIZE-NO-TABLE-NEXT: static std::enable_if_t<InsnBitWidth<InsnType> == 16, DecodeStatus>128// CHECK-SPECIALIZE-NO-TABLE-NEXT: decodeToMCInst129// CHECK-SPECIALIZE-NO-TABLE: case 0130// CHECK-SPECIALIZE-NO-TABLE: case 1131 132// CHECK-SPECIALIZE-NO-TABLE-LABEL: template <typename InsnType>133// CHECK-SPECIALIZE-NO-TABLE-NEXT: decodeInstruction134// CHECK-SPECIALIZE-NO-TABLE: uint32_t BitWidth = decodeULEB128AndIncUnsafe(Ptr);135// CHECK-SPECIALIZE-NO-TABLE-NEXT: assert(InsnBitWidth<InsnType> == BitWidth &&136 137// -----------------------------------------------------------------------------138// Per bitwidth specialization with function table.139 140// 8 bit deccoder table, functions, and function table.141// CHECK-SPECIALIZE-TABLE-LABEL: DecoderTable8142// CHECK-SPECIALIZE-TABLE: 8, // 0: BitWidth 8143// CHECK-SPECIALIZE-TABLE: using decoder 0144// CHECK-SPECIALIZE-TABLE: using decoder 1145// CHECK-SPECIALIZE-TABLE: };146 147// CHECK-SPECIALIZE-TABLE-LABEL: template <typename InsnType>148// CHECK-SPECIALIZE-TABLE-NEXT: static std::enable_if_t<InsnBitWidth<InsnType> == 8, DecodeStatus>149// CHECK-SPECIALIZE-TABLE-NEXT: decodeFn_8bit_0150 151// CHECK-SPECIALIZE-TABLE-LABEL: template <typename InsnType>152// CHECK-SPECIALIZE-TABLE-NEXT: static std::enable_if_t<InsnBitWidth<InsnType> == 8, DecodeStatus>153// CHECK-SPECIALIZE-TABLE-NEXT: decodeFn_8bit_1154 155// CHECK-SPECIALIZE-TABLE-LABEL: template <typename InsnType>156// CHECK-SPECIALIZE-TABLE-NEXT: static std::enable_if_t<InsnBitWidth<InsnType> == 8, DecodeStatus>157// CHECK-SPECIALIZE-TABLE-NEXT: decodeToMCInst158// CHECK-SPECIALIZE-TABLE-LABEL: static constexpr DecodeFnTy decodeFnTable[] = {159// CHECK-SPECIALIZE-TABLE-NEXT: decodeFn_8bit_0,160// CHECK-SPECIALIZE-TABLE-NEXT: decodeFn_8bit_1,161// CHECK-SPECIALIZE-TABLE-NEXT: };162 163// 16 bit deccoder table, functions, and function table.164// CHECK-SPECIALIZE-TABLE-LABEL: DecoderTable16165// CHECK-SPECIALIZE-TABLE: 16, // 0: BitWidth 16166// CHECK-SPECIALIZE-TABLE: using decoder 0167// CHECK-SPECIALIZE-TABLE: using decoder 1168// CHECK-SPECIALIZE-TABLE: };169 170// CHECK-SPECIALIZE-TABLE-LABEL: template <typename InsnType>171// CHECK-SPECIALIZE-TABLE-NEXT: static std::enable_if_t<InsnBitWidth<InsnType> == 16, DecodeStatus>172// CHECK-SPECIALIZE-TABLE-NEXT: decodeFn_16bit_0173 174// CHECK-SPECIALIZE-TABLE-LABEL: template <typename InsnType>175// CHECK-SPECIALIZE-TABLE-NEXT: static std::enable_if_t<InsnBitWidth<InsnType> == 16, DecodeStatus>176// CHECK-SPECIALIZE-TABLE-NEXT: decodeFn_16bit_1177 178// CHECK-SPECIALIZE-TABLE-LABEL: template <typename InsnType>179// CHECK-SPECIALIZE-TABLE-NEXT: static std::enable_if_t<InsnBitWidth<InsnType> == 16, DecodeStatus>180// CHECK-SPECIALIZE-TABLE-NEXT: decodeToMCInst181// CHECK-SPECIALIZE-TABLE-LABEL: static constexpr DecodeFnTy decodeFnTable[] = {182// CHECK-SPECIALIZE-TABLE-NEXT: decodeFn_16bit_0,183// CHECK-SPECIALIZE-TABLE-NEXT: decodeFn_16bit_1,184// CHECK-SPECIALIZE-TABLE-NEXT: };185 186// CHECK-SPECIALIZE-TABLE-LABEL: template <typename InsnType>187// CHECK-SPECIALIZE-TABLE-NEXT: decodeInstruction188// CHECK-SPECIALIZE-TABLE: uint32_t BitWidth = decodeULEB128AndIncUnsafe(Ptr);189// CHECK-SPECIALIZE-TABLE-NEXT: assert(InsnBitWidth<InsnType> == BitWidth &&190