1// RUN: llvm-tblgen -gen-disassembler -I %p/../../include %s | FileCheck %s
2
3include "llvm/Target/Target.td"
4
5def ArchInstrInfo : InstrInfo { }
6
7def Arch : Target {
8  let InstructionSet = ArchInstrInfo;
9}
10
11def Reg : Register<"reg">;
12
13def RegClass : RegisterClass<"foo", [i64], 0, (add Reg)>;
14
15def GR64 : RegisterOperand<RegClass>;
16
17class MyMemOperand<dag sub_ops> : Operand<iPTR> {
18  let MIOperandInfo = sub_ops;
19  dag Base;
20  dag Extension;
21}
22
23def MemOp16: MyMemOperand<(ops GR64:$reg, i16imm:$offset)>;
24
25def MemOp32: MyMemOperand<(ops GR64:$reg, i32imm:$offset)>;
26
27class MyVarInst<MyMemOperand memory_op> : Instruction {
28  dag Inst;
29
30  let OutOperandList = (outs GR64:$dst);
31  let InOperandList  = (ins memory_op:$src);
32}
33
34def FOO16 : MyVarInst<MemOp16> {
35  let Inst = (ascend
36      (descend (operand "$dst", 3), 0b01000, (operand "$src.reg", 3)),
37      (slice "$src.offset", 15, 0)
38  );
39}
40def FOO32 : MyVarInst<MemOp32> {
41  let Inst = (ascend
42      (descend (operand "$dst", 3), 0b01001, (operand "$src.reg", 3)),
43      (slice "$src.offset", 31, 16),
44      (slice "$src.offset", 15, 0)
45  );
46}
47
48// CHECK:      MCD::OPC_ExtractField, 3, 5,  // Inst{7-3} ...
49// CHECK-NEXT: MCD::OPC_FilterValue, 8, 4, 0, 0, // Skip to: 12
50// CHECK-NEXT: MCD::OPC_Decode, [[#OPCODE:]], 1, 0, // Opcode: FOO16
51// CHECK-NEXT: MCD::OPC_FilterValue, 9, 4, 0, 0, // Skip to: 21
52// CHECK-NEXT: MCD::OPC_Decode, [[#OPCODE+1]], 1, 1, // Opcode: FOO32
53// CHECK-NEXT: MCD::OPC_Fail,
54
55// Instruction length table
56// CHECK: 27,
57// CHECK-NEXT: 43,
58// CHECK-NEXT: };
59
60// CHECK:      case 0:
61// CHECK-NEXT: tmp = fieldFromInstruction(insn, 8, 3);
62// CHECK-NEXT: if (DecodeRegClassRegisterClass(MI, tmp, Address, Decoder) == MCDisassembler::Fail) { return MCDisassembler::Fail; }
63// CHECK-NEXT: tmp = fieldFromInstruction(insn, 0, 3);
64// CHECK-NEXT: if (DecodeRegClassRegisterClass(MI, tmp, Address, Decoder) == MCDisassembler::Fail) { return MCDisassembler::Fail; }
65// CHECK-NEXT: tmp = fieldFromInstruction(insn, 11, 16);
66// CHECK-NEXT: MI.addOperand(MCOperand::createImm(tmp));
67// CHECK-NEXT: return S;
68// CHECK-NEXT: case 1:
69// CHECK-NEXT: tmp = fieldFromInstruction(insn, 8, 3);
70// CHECK-NEXT: if (DecodeRegClassRegisterClass(MI, tmp, Address, Decoder) == MCDisassembler::Fail) { return MCDisassembler::Fail; }
71// CHECK-NEXT: tmp = fieldFromInstruction(insn, 0, 3);
72// CHECK-NEXT: if (DecodeRegClassRegisterClass(MI, tmp, Address, Decoder) == MCDisassembler::Fail) { return MCDisassembler::Fail; }
73// CHECK-NEXT: tmp = 0x0;
74// CHECK-NEXT: insertBits(tmp, fieldFromInstruction(insn, 11, 16), 16, 16);
75// CHECK-NEXT: insertBits(tmp, fieldFromInstruction(insn, 27, 16), 0, 16);
76// CHECK-NEXT: MI.addOperand(MCOperand::createImm(tmp));
77// CHECK-NEXT: return S;
78
79// CHECK-LABEL: case MCD::OPC_ExtractField: {
80// CHECK: makeUp(insn, Start + Len);
81
82// CHECK-LABEL: case MCD::OPC_CheckField: {
83// CHECK: makeUp(insn, Start + Len);
84
85// CHECK-LABEL: case MCD::OPC_Decode: {
86// CHECK: Len = InstrLenTable[Opc];
87// CHECK-NEXT: makeUp(insn, Len);
88