| // RUN: llvm-tblgen -gen-emitter -I %p/../../include %s | FileCheck %s |
| |
| // Check if VarLenCodeEmitterGen works correctly. |
| |
| include "llvm/Target/Target.td" |
| |
| def ArchInstrInfo : InstrInfo { } |
| |
| def Arch : Target { |
| let InstructionSet = ArchInstrInfo; |
| } |
| |
| def Reg : Register<"reg">; |
| |
| def RegClass : RegisterClass<"foo", [i64], 0, (add Reg)>; |
| |
| def GR64 : RegisterOperand<RegClass>; |
| |
| class MyMemOperand<dag sub_ops> : Operand<iPTR> { |
| let MIOperandInfo = sub_ops; |
| dag Base; |
| dag Extension; |
| } |
| |
| class MyVarInst<MyMemOperand memory_op> : Instruction { |
| dag Inst; |
| |
| let OutOperandList = (outs GR64:$dst); |
| let InOperandList = (ins memory_op:$src); |
| |
| // Testing `ascend` and `descend` |
| let Inst = (ascend |
| (descend 0b10110111, memory_op.Base), |
| memory_op.Extension, |
| // Testing operand referencing. |
| (operand "$dst", 4), |
| // Testing operand referencing with a certain bit range. |
| (slice "$dst", 3, 1), |
| // Testing custom encoder |
| (operand "$dst", 2, (encoder "myCustomEncoder")) |
| ); |
| } |
| |
| class MemOp16<string op_name> : MyMemOperand<(ops GR64:$reg, i16imm:$offset)> { |
| // Testing sub-operand referencing. |
| let Base = (operand "$"#op_name#".reg", 8); |
| let Extension = (operand "$"#op_name#".offset", 16); |
| } |
| |
| class MemOp32<string op_name> : MyMemOperand<(ops GR64:$reg, i32imm:$offset)> { |
| let Base = (operand "$"#op_name#".reg", 8); |
| // Testing variable-length instruction encoding. |
| let Extension = (operand "$"#op_name#".offset", 32); |
| } |
| |
| def FOO16 : MyVarInst<MemOp16<"src">>; |
| def FOO32 : MyVarInst<MemOp32<"src">>; |
| |
| // The fixed bits part |
| // CHECK: {/*NumBits*/41, |
| // CHECK-SAME: // FOO16 |
| // CHECK: {/*NumBits*/57, |
| // CHECK-SAME: // FOO32 |
| // CHECK: UINT64_C(46848), // FOO16 |
| // CHECK: UINT64_C(46848), // FOO32 |
| |
| // CHECK-LABEL: case ::FOO16: { |
| // CHECK: Scratch.getBitWidth() < 16 |
| // src.reg |
| // CHECK: getMachineOpValue(MI, MI.getOperand(1), /*Pos=*/0, Scratch, Fixups, STI); |
| // CHECK: Inst.insertBits(Scratch.extractBits(8, 0), 0); |
| // src.offset |
| // CHECK: getMachineOpValue(MI, MI.getOperand(2), /*Pos=*/16, Scratch, Fixups, STI); |
| // CHECK: Inst.insertBits(Scratch.extractBits(16, 0), 16); |
| // 1st dst |
| // CHECK: getMachineOpValue(MI, MI.getOperand(0), /*Pos=*/32, Scratch, Fixups, STI); |
| // CHECK: Inst.insertBits(Scratch.extractBits(4, 0), 32); |
| // 2nd dst |
| // CHECK: getMachineOpValue(MI, MI.getOperand(0), /*Pos=*/36, Scratch, Fixups, STI); |
| // CHECK: Inst.insertBits(Scratch.extractBits(3, 1), 36); |
| // dst w/ custom encoder |
| // CHECK: myCustomEncoder(MI, /*OpIdx=*/0, /*Pos=*/39, Scratch, Fixups, STI); |
| // CHECK: Inst.insertBits(Scratch.extractBits(2, 0), 39); |
| |
| // CHECK-LABEL: case ::FOO32: { |
| // CHECK: Scratch.getBitWidth() < 32 |
| // src.reg |
| // CHECK: getMachineOpValue(MI, MI.getOperand(1), /*Pos=*/0, Scratch, Fixups, STI); |
| // CHECK: Inst.insertBits(Scratch.extractBits(8, 0), 0); |
| // src.offset |
| // CHECK: getMachineOpValue(MI, MI.getOperand(2), /*Pos=*/16, Scratch, Fixups, STI); |
| // CHECK: Inst.insertBits(Scratch.extractBits(32, 0), 16); |
| // 1st dst |
| // CHECK: getMachineOpValue(MI, MI.getOperand(0), /*Pos=*/48, Scratch, Fixups, STI); |
| // CHECK: Inst.insertBits(Scratch.extractBits(4, 0), 48); |
| // 2nd dst |
| // CHECK: getMachineOpValue(MI, MI.getOperand(0), /*Pos=*/52, Scratch, Fixups, STI); |
| // CHECK: Inst.insertBits(Scratch.extractBits(3, 1), 52); |
| // dst w/ custom encoder |
| // CHECK: myCustomEncoder(MI, /*OpIdx=*/0, /*Pos=*/55, Scratch, Fixups, STI); |
| // CHECK: Inst.insertBits(Scratch.extractBits(2, 0), 55); |