summaryrefslogtreecommitdiff
path: root/llvm/test/TableGen/DecoderEmitterBitwidthSpecialization.td
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/test/TableGen/DecoderEmitterBitwidthSpecialization.td')
-rw-r--r--llvm/test/TableGen/DecoderEmitterBitwidthSpecialization.td189
1 files changed, 189 insertions, 0 deletions
diff --git a/llvm/test/TableGen/DecoderEmitterBitwidthSpecialization.td b/llvm/test/TableGen/DecoderEmitterBitwidthSpecialization.td
new file mode 100644
index 000000000000..c656616a6245
--- /dev/null
+++ b/llvm/test/TableGen/DecoderEmitterBitwidthSpecialization.td
@@ -0,0 +1,189 @@
+// 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<int NumOps> : Instruction {
+ let Size = 1;
+ let OutOperandList = (outs);
+ field bits<8> Inst;
+ let Inst{0} = 0;
+ let Inst{3-1} = NumOps;
+}
+
+class Instruction16Bit<int NumOps> : 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[25]
+// CHECK-DEFAULT: DecodeIdx: 0
+// CHECK-DEFAULT: DecodeIdx: 1
+// CHECK-DEFAULT: };
+
+// CHECK-DEFAULT-LABEL: DecoderTable16[25]
+// CHECK-DEFAULT: DecodeIdx: 2
+// CHECK-DEFAULT: DecodeIdx: 3
+// CHECK-DEFAULT: };
+
+// CHECK-DEFAULT-LABEL: template <typename InsnType>
+// 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[26]
+// CHECK-SPECIALIZE-NO-TABLE: /* 0 */ 8, // Bitwidth 8
+// CHECK-SPECIALIZE-NO-TABLE: DecodeIdx: 0
+// CHECK-SPECIALIZE-NO-TABLE: DecodeIdx: 1
+// CHECK-SPECIALIZE-NO-TABLE: };
+
+// CHECK-SPECIALIZE-NO-TABLE-LABEL: template <typename InsnType>
+// CHECK-SPECIALIZE-NO-TABLE-NEXT: static std::enable_if_t<InsnBitWidth<InsnType> == 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[26]
+// CHECK-SPECIALIZE-NO-TABLE: /* 0 */ 16, // Bitwidth 16
+// CHECK-SPECIALIZE-NO-TABLE: DecodeIdx: 0
+// CHECK-SPECIALIZE-NO-TABLE: DecodeIdx: 1
+// CHECK-SPECIALIZE-NO-TABLE: };
+
+// CHECK-SPECIALIZE-NO-TABLE-LABEL: template <typename InsnType>
+// CHECK-SPECIALIZE-NO-TABLE-NEXT: static std::enable_if_t<InsnBitWidth<InsnType> == 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 <typename InsnType>
+// CHECK-SPECIALIZE-NO-TABLE-NEXT: decodeInstruction
+// CHECK-SPECIALIZE-NO-TABLE: uint32_t BitWidth = decodeULEB128AndIncUnsafe(Ptr);
+// CHECK-SPECIALIZE-NO-TABLE-NEXT: assert(InsnBitWidth<InsnType> == BitWidth &&
+
+// -----------------------------------------------------------------------------
+// Per bitwidth specialization with function table.
+
+// 8 bit deccoder table, functions, and function table.
+// CHECK-SPECIALIZE-TABLE-LABEL: DecoderTable8[26]
+// CHECK-SPECIALIZE-TABLE: /* 0 */ 8, // Bitwidth 8
+// CHECK-SPECIALIZE-TABLE: DecodeIdx: 0
+// CHECK-SPECIALIZE-TABLE: DecodeIdx: 1
+// CHECK-SPECIALIZE-TABLE: };
+
+// CHECK-SPECIALIZE-TABLE-LABEL: template <typename InsnType>
+// CHECK-SPECIALIZE-TABLE-NEXT: static std::enable_if_t<InsnBitWidth<InsnType> == 8, DecodeStatus>
+// CHECK-SPECIALIZE-TABLE-NEXT: decodeFn_8bit_0
+
+// CHECK-SPECIALIZE-TABLE-LABEL: template <typename InsnType>
+// CHECK-SPECIALIZE-TABLE-NEXT: static std::enable_if_t<InsnBitWidth<InsnType> == 8, DecodeStatus>
+// CHECK-SPECIALIZE-TABLE-NEXT: decodeFn_8bit_1
+
+// CHECK-SPECIALIZE-TABLE-LABEL: template <typename InsnType>
+// CHECK-SPECIALIZE-TABLE-NEXT: static std::enable_if_t<InsnBitWidth<InsnType> == 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[26]
+// CHECK-SPECIALIZE-TABLE: /* 0 */ 16, // Bitwidth 16
+// CHECK-SPECIALIZE-TABLE: DecodeIdx: 0
+// CHECK-SPECIALIZE-TABLE: DecodeIdx: 1
+// CHECK-SPECIALIZE-TABLE: };
+
+// CHECK-SPECIALIZE-TABLE-LABEL: template <typename InsnType>
+// CHECK-SPECIALIZE-TABLE-NEXT: static std::enable_if_t<InsnBitWidth<InsnType> == 16, DecodeStatus>
+// CHECK-SPECIALIZE-TABLE-NEXT: decodeFn_16bit_0
+
+// CHECK-SPECIALIZE-TABLE-LABEL: template <typename InsnType>
+// CHECK-SPECIALIZE-TABLE-NEXT: static std::enable_if_t<InsnBitWidth<InsnType> == 16, DecodeStatus>
+// CHECK-SPECIALIZE-TABLE-NEXT: decodeFn_16bit_1
+
+// CHECK-SPECIALIZE-TABLE-LABEL: template <typename InsnType>
+// CHECK-SPECIALIZE-TABLE-NEXT: static std::enable_if_t<InsnBitWidth<InsnType> == 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 <typename InsnType>
+// CHECK-SPECIALIZE-TABLE-NEXT: decodeInstruction
+// CHECK-SPECIALIZE-TABLE: uint32_t BitWidth = decodeULEB128AndIncUnsafe(Ptr);
+// CHECK-SPECIALIZE-TABLE-NEXT: assert(InsnBitWidth<InsnType> == BitWidth &&