[CodeEmitter] Support instruction widths > 64 bits
Some VLIW instruction sets are Very Long Indeed. Using uint64_t constricts the Inst encoding to 64 bits (naturally).
This change switches CodeEmitter to a mode that uses APInts when Inst's bitwidth is > 64 bits (NFC for existing targets).
When Inst.BitWidth > 64 the prototype changes to:
void TargetMCCodeEmitter::getBinaryCodeForInstr(const MCInst &MI,
SmallVectorImpl<MCFixup> &Fixups,
APInt &Inst,
APInt &Scratch,
const MCSubtargetInfo &STI);
The Inst parameter returns the encoded instruction, the Scratch parameter is used internally for manipulating operands and is exposed so that the underlying storage can be reused between calls to getBinaryCodeForInstr. The goal is to elide any APInt constructions that we can.
Similarly the operand encoding prototype changes to:
getMachineOpValue(const MCInst &MI, const MCOperand &MO, APInt &op, SmallVectorImpl<MCFixup> &Fixups, const MCSubtargetInfo &STI);
That is, the operand is passed by reference as APInt rather than returned as uint64_t.
To reiterate, this APInt mode is enabled only when Inst.BitWidth > 64, so this change is NFC for existing targets.
llvm-svn: 371928
2019-09-15 10:35:08 +02:00
|
|
|
// RUN: llvm-tblgen -gen-emitter -I %p/../../include %s | FileCheck %s
|
|
|
|
|
|
|
|
include "llvm/Target/Target.td"
|
|
|
|
|
|
|
|
def archInstrInfo : InstrInfo { }
|
|
|
|
|
|
|
|
def arch : Target {
|
|
|
|
let InstructionSet = archInstrInfo;
|
|
|
|
}
|
|
|
|
|
|
|
|
def Myi32 : Operand<i32> {
|
|
|
|
let DecoderMethod = "DecodeMyi32";
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
let OutOperandList = (outs), Size = 2 in {
|
|
|
|
|
|
|
|
def foo : Instruction {
|
|
|
|
let InOperandList = (ins i32imm:$factor);
|
|
|
|
field bits<65> Inst;
|
|
|
|
bits<32> factor;
|
|
|
|
let Inst{7-0} = 0xAA;
|
|
|
|
let Inst{14-8} = factor{6-0}; // no offset
|
|
|
|
let AsmString = "foo $factor";
|
|
|
|
field bits<16> SoftFail = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
def bar : Instruction {
|
|
|
|
let InOperandList = (ins i32imm:$factor);
|
|
|
|
field bits<65> Inst;
|
|
|
|
bits<32> factor;
|
|
|
|
let Inst{7-0} = 0xBB;
|
|
|
|
let Inst{15-8} = factor{10-3}; // offset by 3
|
|
|
|
let AsmString = "bar $factor";
|
|
|
|
field bits<16> SoftFail = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
def biz : Instruction {
|
|
|
|
let InOperandList = (ins i32imm:$factor);
|
|
|
|
field bits<65> Inst;
|
|
|
|
bits<32> factor;
|
|
|
|
let Inst{7-0} = 0xCC;
|
|
|
|
let Inst{11-8,15-12} = factor{10-3}; // offset by 3, multipart
|
|
|
|
let AsmString = "biz $factor";
|
|
|
|
field bits<16> SoftFail = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
// CHECK-LABEL: case ::biz: {
|
2019-09-18 20:14:42 +02:00
|
|
|
// CHECK: Value.insertBits(op.extractBitsAsZExtValue(4, 3), 12, 4);
|
|
|
|
// CHECK-NEXT: Value.insertBits(op.extractBitsAsZExtValue(4, 7), 8, 4);
|
[CodeEmitter] Support instruction widths > 64 bits
Some VLIW instruction sets are Very Long Indeed. Using uint64_t constricts the Inst encoding to 64 bits (naturally).
This change switches CodeEmitter to a mode that uses APInts when Inst's bitwidth is > 64 bits (NFC for existing targets).
When Inst.BitWidth > 64 the prototype changes to:
void TargetMCCodeEmitter::getBinaryCodeForInstr(const MCInst &MI,
SmallVectorImpl<MCFixup> &Fixups,
APInt &Inst,
APInt &Scratch,
const MCSubtargetInfo &STI);
The Inst parameter returns the encoded instruction, the Scratch parameter is used internally for manipulating operands and is exposed so that the underlying storage can be reused between calls to getBinaryCodeForInstr. The goal is to elide any APInt constructions that we can.
Similarly the operand encoding prototype changes to:
getMachineOpValue(const MCInst &MI, const MCOperand &MO, APInt &op, SmallVectorImpl<MCFixup> &Fixups, const MCSubtargetInfo &STI);
That is, the operand is passed by reference as APInt rather than returned as uint64_t.
To reiterate, this APInt mode is enabled only when Inst.BitWidth > 64, so this change is NFC for existing targets.
llvm-svn: 371928
2019-09-15 10:35:08 +02:00
|
|
|
|
|
|
|
// CHECK-LABEL: case ::foo: {
|
2019-09-18 20:14:42 +02:00
|
|
|
// CHECK: Value.insertBits(op.extractBitsAsZExtValue(7, 0), 8, 7);
|
2019-09-15 10:44:40 +02:00
|
|
|
|
|
|
|
// CHECK-LABEL: case ::bar: {
|
2019-09-18 20:14:42 +02:00
|
|
|
// CHECK: Value.insertBits(op.extractBitsAsZExtValue(8, 3), 8, 8);
|