mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2025-02-10 19:34:29 +00:00
![Min-Yih Hsu](/assets/img/avatar_default.png)
The new encoder directive can be used to specify custom encoder for a single operand or slice. This is different from the EncoderMethod field within an Operand, which affects every operands in the target. In addition, this patch also changes the function signature of the encoder method -- a new argument, InsertPost, is added to both the default one (i.e. getMachineValue) and the custom one. This argument provides the bit position where the operand will eventually be inserted. Differential Revision: https://reviews.llvm.org/D119100
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.zextOrSelf(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.zextOrSelf(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);
|