102 lines
3.4 KiB
TableGen
102 lines
3.4 KiB
TableGen
// 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 = Scratch.zext(41);
|
|
// 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 = Scratch.zext(57);
|
|
// 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);
|