// RUN: llvm-tblgen -gen-disassembler -I %p/../../../include %s | FileCheck %s --check-prefix=CHECK-DEFAULT // RUN: llvm-tblgen -gen-disassembler -specialize-decoders-per-bitwidth -I %p/../../../include %s | FileCheck %s --check-prefix=CHECK-SPECIALIZE-NO-TABLE // 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-TABLE include "llvm/Target/Target.td" def archInstrInfo : InstrInfo { } def arch : Target { let InstructionSet = archInstrInfo; } let Namespace = "arch" in { def R0 : Register<"r0">; def R1 : Register<"r1">; def R2 : Register<"r2">; def R3 : Register<"r3">; } def Regs : RegisterClass<"Regs", [i32], 32, (add R0, R1, R2, R3)>; // Bit 0 of the encoding determines the size (8 or 16 bits). // Bits {3..1} define the number of operands encoded. class Instruction8Bit : Instruction { let Size = 1; let OutOperandList = (outs); field bits<8> Inst; let Inst{0} = 0; let Inst{3-1} = NumOps; } class Instruction16Bit : Instruction { let Size = 2; let OutOperandList = (outs); field bits<16> Inst; let Inst{0} = 1; let Inst{3-1} = NumOps; } // Define instructions to generate 4 cases in decodeToMCInst. // Each register operand needs 2 bits to encode. // An instruction with no inputs. def Inst0 : Instruction8Bit<0> { let Inst{7-4} = 0; let InOperandList = (ins); let AsmString = "Inst0"; } // An instruction with a single input. def Inst1 : Instruction8Bit<1> { bits<2> r0; let Inst{5-4} = r0; let Inst{7-6} = 0; let InOperandList = (ins Regs:$r0); let AsmString = "Inst1"; } // An instruction with two inputs. def Inst2 : Instruction16Bit<2> { bits<2> r0; bits<2> r1; let Inst{5-4} = r0; let Inst{7-6} = r1; let Inst{15-8} = 0; let InOperandList = (ins Regs:$r0, Regs:$r1); let AsmString = "Inst2"; } // An instruction with three inputs. . def Inst3 : Instruction16Bit<3> { bits<2> r0; bits<2> r1; bits<2> r2; let Inst{5-4} = r0; let Inst{7-6} = r1; let Inst{9-8} = r2; let Inst{15-10} = 0; let InOperandList = (ins Regs:$r0, Regs:$r1, Regs:$r2); let AsmString = "Inst3"; } // ----------------------------------------------------------------------------- // In the default case, we emit a single decodeToMCinst function and DecodeIdx // is shared across all bitwidths. // CHECK-DEFAULT-LABEL: DecoderTable8 // CHECK-DEFAULT: using decoder 0 // CHECK-DEFAULT: using decoder 1 // CHECK-DEFAULT: }; // CHECK-DEFAULT-LABEL: DecoderTable16 // CHECK-DEFAULT: using decoder 2 // CHECK-DEFAULT: using decoder 3 // CHECK-DEFAULT: }; // CHECK-DEFAULT-LABEL: template // CHECK-DEFAULT-NEXT: static DecodeStatus decodeToMCInst // CHECK-DEFAULT: case 0 // CHECK-DEFAULT: case 1 // CHECK-DEFAULT: case 2 // CHECK-DEFAULT: case 3 // ----------------------------------------------------------------------------- // When we specialize per bitwidth, we emit 2 decodeToMCInst functions and // DecodeIdx is assigned per bit width. // CHECK-SPECIALIZE-NO-TABLE-LABEL: DecoderTable8 // CHECK-SPECIALIZE-NO-TABLE: 8, // 0: BitWidth 8 // CHECK-SPECIALIZE-NO-TABLE: using decoder 0 // CHECK-SPECIALIZE-NO-TABLE: using decoder 1 // CHECK-SPECIALIZE-NO-TABLE: }; // CHECK-SPECIALIZE-NO-TABLE-LABEL: template // CHECK-SPECIALIZE-NO-TABLE-NEXT: static std::enable_if_t == 8, DecodeStatus> // CHECK-SPECIALIZE-NO-TABLE-NEXT: decodeToMCInst // CHECK-SPECIALIZE-NO-TABLE: case 0 // CHECK-SPECIALIZE-NO-TABLE: case 1 // CHECK-SPECIALIZE-NO-TABLE-LABEL: DecoderTable16 // CHECK-SPECIALIZE-NO-TABLE: 16, // 0: BitWidth 16 // CHECK-SPECIALIZE-NO-TABLE: using decoder 0 // CHECK-SPECIALIZE-NO-TABLE: using decoder 1 // CHECK-SPECIALIZE-NO-TABLE: }; // CHECK-SPECIALIZE-NO-TABLE-LABEL: template // CHECK-SPECIALIZE-NO-TABLE-NEXT: static std::enable_if_t == 16, DecodeStatus> // CHECK-SPECIALIZE-NO-TABLE-NEXT: decodeToMCInst // CHECK-SPECIALIZE-NO-TABLE: case 0 // CHECK-SPECIALIZE-NO-TABLE: case 1 // CHECK-SPECIALIZE-NO-TABLE-LABEL: template // CHECK-SPECIALIZE-NO-TABLE-NEXT: decodeInstruction // CHECK-SPECIALIZE-NO-TABLE: uint32_t BitWidth = decodeULEB128AndIncUnsafe(Ptr); // CHECK-SPECIALIZE-NO-TABLE-NEXT: assert(InsnBitWidth == BitWidth && // ----------------------------------------------------------------------------- // Per bitwidth specialization with function table. // 8 bit deccoder table, functions, and function table. // CHECK-SPECIALIZE-TABLE-LABEL: DecoderTable8 // CHECK-SPECIALIZE-TABLE: 8, // 0: BitWidth 8 // CHECK-SPECIALIZE-TABLE: using decoder 0 // CHECK-SPECIALIZE-TABLE: using decoder 1 // CHECK-SPECIALIZE-TABLE: }; // CHECK-SPECIALIZE-TABLE-LABEL: template // CHECK-SPECIALIZE-TABLE-NEXT: static std::enable_if_t == 8, DecodeStatus> // CHECK-SPECIALIZE-TABLE-NEXT: decodeFn_8bit_0 // CHECK-SPECIALIZE-TABLE-LABEL: template // CHECK-SPECIALIZE-TABLE-NEXT: static std::enable_if_t == 8, DecodeStatus> // CHECK-SPECIALIZE-TABLE-NEXT: decodeFn_8bit_1 // CHECK-SPECIALIZE-TABLE-LABEL: template // CHECK-SPECIALIZE-TABLE-NEXT: static std::enable_if_t == 8, DecodeStatus> // CHECK-SPECIALIZE-TABLE-NEXT: decodeToMCInst // CHECK-SPECIALIZE-TABLE-LABEL: static constexpr DecodeFnTy decodeFnTable[] = { // CHECK-SPECIALIZE-TABLE-NEXT: decodeFn_8bit_0, // CHECK-SPECIALIZE-TABLE-NEXT: decodeFn_8bit_1, // CHECK-SPECIALIZE-TABLE-NEXT: }; // 16 bit deccoder table, functions, and function table. // CHECK-SPECIALIZE-TABLE-LABEL: DecoderTable16 // CHECK-SPECIALIZE-TABLE: 16, // 0: BitWidth 16 // CHECK-SPECIALIZE-TABLE: using decoder 0 // CHECK-SPECIALIZE-TABLE: using decoder 1 // CHECK-SPECIALIZE-TABLE: }; // CHECK-SPECIALIZE-TABLE-LABEL: template // CHECK-SPECIALIZE-TABLE-NEXT: static std::enable_if_t == 16, DecodeStatus> // CHECK-SPECIALIZE-TABLE-NEXT: decodeFn_16bit_0 // CHECK-SPECIALIZE-TABLE-LABEL: template // CHECK-SPECIALIZE-TABLE-NEXT: static std::enable_if_t == 16, DecodeStatus> // CHECK-SPECIALIZE-TABLE-NEXT: decodeFn_16bit_1 // CHECK-SPECIALIZE-TABLE-LABEL: template // CHECK-SPECIALIZE-TABLE-NEXT: static std::enable_if_t == 16, DecodeStatus> // CHECK-SPECIALIZE-TABLE-NEXT: decodeToMCInst // CHECK-SPECIALIZE-TABLE-LABEL: static constexpr DecodeFnTy decodeFnTable[] = { // CHECK-SPECIALIZE-TABLE-NEXT: decodeFn_16bit_0, // CHECK-SPECIALIZE-TABLE-NEXT: decodeFn_16bit_1, // CHECK-SPECIALIZE-TABLE-NEXT: }; // CHECK-SPECIALIZE-TABLE-LABEL: template // CHECK-SPECIALIZE-TABLE-NEXT: decodeInstruction // CHECK-SPECIALIZE-TABLE: uint32_t BitWidth = decodeULEB128AndIncUnsafe(Ptr); // CHECK-SPECIALIZE-TABLE-NEXT: assert(InsnBitWidth == BitWidth &&