mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-22 10:42:39 +01:00
[ARC] Add disassembly for the conditioned move immediate instruction
This change is a step towards implementing codegen for __builtin_clz(). Full support for CLZ with a regression test will follow shortly. Differential Revision: https://reviews.llvm.org/D105560
This commit is contained in:
parent
7664c93484
commit
76438a2e53
@ -261,6 +261,31 @@ class F32_SOP_RR<bits<5> major, bits<6> subop, bit F, dag outs, dag ins,
|
|||||||
let Inst{5-0} = subop;
|
let Inst{5-0} = subop;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Single Operand Immediate Instructions.
|
||||||
|
// 1-register, unsigned 6-bit immediate Single Operand instruction.
|
||||||
|
// |26|25|24|23|22|21|20|19|18|17|16|15|14|13|12|11|10|9|8|7|6|5|4|3|2|1|0|
|
||||||
|
// |B[2-0] | 1| 1| subop| F|B[5-3] |U6 |1|cc |
|
||||||
|
class F32_SOP_CC_RU6<bits<5> major, bits<6> subop, bit F, dag outs, dag ins,
|
||||||
|
string asmstr, list<dag> pattern> :
|
||||||
|
InstARC<4, outs, ins, asmstr, pattern> {
|
||||||
|
|
||||||
|
bits<5> cc;
|
||||||
|
bits<6> U6;
|
||||||
|
bits<6> B;
|
||||||
|
|
||||||
|
let Inst{31-27} = major;
|
||||||
|
let Inst{26-24} = B{2-0};
|
||||||
|
let Inst{23-22} = 0b11;
|
||||||
|
let Inst{21-16} = subop;
|
||||||
|
let Inst{15} = F;
|
||||||
|
let Inst{14-12} = B{5-3};
|
||||||
|
let Inst{11-6} = U6;
|
||||||
|
let Inst{5} = 1;
|
||||||
|
let Inst{4-0} = cc;
|
||||||
|
|
||||||
|
let DecoderMethod = "DecodeCCRU6Instruction";
|
||||||
|
}
|
||||||
|
|
||||||
// Dual Operand Instructions. Inst[21-16] specifies the specific operation
|
// Dual Operand Instructions. Inst[21-16] specifies the specific operation
|
||||||
// for this format.
|
// for this format.
|
||||||
|
|
||||||
|
@ -12,6 +12,24 @@
|
|||||||
|
|
||||||
include "ARCInstrFormats.td"
|
include "ARCInstrFormats.td"
|
||||||
|
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
// Operand Pattern Stuff.
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
// Operand for printing out a condition code.
|
||||||
|
let PrintMethod = "printCCOperand" in
|
||||||
|
def CCOp : PredicateOperand<i32, (ops i32imm), (ops)>;
|
||||||
|
|
||||||
|
// The "u6" operand of a RRU6-type instruction
|
||||||
|
let PrintMethod = "printU6" in {
|
||||||
|
def u6 : Operand<i32>, ImmLeaf<i32, [{
|
||||||
|
return isUInt<6>(Imm);
|
||||||
|
}]>;
|
||||||
|
def wide_u6 : Operand<i64>, ImmLeaf<i64, [{
|
||||||
|
return isUInt<6>(Imm);
|
||||||
|
}]>;
|
||||||
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
// Selection DAG Nodes.
|
// Selection DAG Nodes.
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
@ -299,14 +317,24 @@ def MOV_ru6 : F32_DOP_RU6<0b00100, 0b001010, 0,
|
|||||||
def cmov : PatFrag<(ops node:$op1, node:$op2, node:$cc),
|
def cmov : PatFrag<(ops node:$op1, node:$op2, node:$cc),
|
||||||
(ARCcmov $op1, $op2, $cc)>;
|
(ARCcmov $op1, $op2, $cc)>;
|
||||||
let Uses = [STATUS32] in {
|
let Uses = [STATUS32] in {
|
||||||
def MOVcc : F32_DOP_CC_RR<0b00100, 0b001010, 0,
|
def MOVcc : F32_DOP_CC_RR<0b00100, 0b001010, 0,
|
||||||
(outs GPR32:$B),
|
(outs GPR32:$B),
|
||||||
(ins GPR32:$C, GPR32:$fval, cmovpred:$cc),
|
(ins GPR32:$C, GPR32:$fval, cmovpred:$cc),
|
||||||
!strconcat("mov.", "$cc\t$B, $C"),
|
!strconcat("mov.", "$cc\t$B, $C"),
|
||||||
[(set GPR32:$B, (cmov i32:$C, i32:$fval, cmovpred:$cc))]> {
|
[(set GPR32:$B, (cmov i32:$C, i32:$fval, cmovpred:$cc))]> {
|
||||||
let Constraints = "$B = $fval";
|
let Constraints = "$B = $fval";
|
||||||
|
}
|
||||||
|
|
||||||
|
def MOVcc_ru6 : F32_SOP_CC_RU6<0b00100, 0b001010, 0,
|
||||||
|
(outs GPR32:$b), (ins u6:$c, CCOp:$cc, GPR32:$b2),
|
||||||
|
"mov.$cc\t$b, $c", []> {
|
||||||
|
let isAsCheapAsAMove=0;
|
||||||
|
let isPredicable=1;
|
||||||
|
let isReMaterializable=0;
|
||||||
|
let Constraints="$b2 = $b";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
def : Pat<(ARCGAWrapper tglobaladdr:$addr),
|
def : Pat<(ARCGAWrapper tglobaladdr:$addr),
|
||||||
(MOV_rlimm tglobaladdr:$addr)>;
|
(MOV_rlimm tglobaladdr:$addr)>;
|
||||||
|
|
||||||
|
@ -107,6 +107,9 @@ static DecodeStatus DecodeStLImmInstruction(MCInst &, uint64_t, uint64_t,
|
|||||||
static DecodeStatus DecodeLdRLImmInstruction(MCInst &, uint64_t, uint64_t,
|
static DecodeStatus DecodeLdRLImmInstruction(MCInst &, uint64_t, uint64_t,
|
||||||
const void *);
|
const void *);
|
||||||
|
|
||||||
|
static DecodeStatus DecodeCCRU6Instruction(MCInst &, uint64_t, uint64_t,
|
||||||
|
const void *);
|
||||||
|
|
||||||
static DecodeStatus DecodeMoveHRegInstruction(MCInst &Inst, uint64_t, uint64_t,
|
static DecodeStatus DecodeMoveHRegInstruction(MCInst &Inst, uint64_t, uint64_t,
|
||||||
const void *);
|
const void *);
|
||||||
|
|
||||||
@ -167,19 +170,19 @@ static DecodeStatus DecodeMEMrs9(MCInst &Inst, unsigned Insn, uint64_t Address,
|
|||||||
|
|
||||||
static bool DecodeSymbolicOperand(MCInst &Inst, uint64_t Address,
|
static bool DecodeSymbolicOperand(MCInst &Inst, uint64_t Address,
|
||||||
uint64_t Value, const void *Decoder) {
|
uint64_t Value, const void *Decoder) {
|
||||||
static const uint64_t atLeast = 2;
|
static const uint64_t AtLeast = 2;
|
||||||
// TODO: Try to force emitter to use MCDisassembler* instead of void*.
|
// TODO: Try to force emitter to use MCDisassembler* instead of void*.
|
||||||
auto Disassembler = static_cast<const MCDisassembler *>(Decoder);
|
auto Disassembler = static_cast<const MCDisassembler *>(Decoder);
|
||||||
return (nullptr != Disassembler &&
|
return (nullptr != Disassembler &&
|
||||||
Disassembler->tryAddingSymbolicOperand(Inst, Value, Address, true, 0,
|
Disassembler->tryAddingSymbolicOperand(Inst, Value, Address, true, 0,
|
||||||
atLeast));
|
AtLeast));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void DecodeSymbolicOperandOff(MCInst &Inst, uint64_t Address,
|
static void DecodeSymbolicOperandOff(MCInst &Inst, uint64_t Address,
|
||||||
uint64_t Offset, const void *Decoder) {
|
uint64_t Offset, const void *Decoder) {
|
||||||
uint64_t nextAddress = Address + Offset;
|
uint64_t NextAddress = Address + Offset;
|
||||||
|
|
||||||
if (!DecodeSymbolicOperand(Inst, Address, nextAddress, Decoder))
|
if (!DecodeSymbolicOperand(Inst, Address, NextAddress, Decoder))
|
||||||
Inst.addOperand(MCOperand::createImm(Offset));
|
Inst.addOperand(MCOperand::createImm(Offset));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -272,9 +275,9 @@ static DecodeStatus DecodeMoveHRegInstruction(MCInst &Inst, uint64_t Insn,
|
|||||||
const void *Decoder) {
|
const void *Decoder) {
|
||||||
LLVM_DEBUG(dbgs() << "Decoding MOV_S h-register\n");
|
LLVM_DEBUG(dbgs() << "Decoding MOV_S h-register\n");
|
||||||
using Field = decltype(Insn);
|
using Field = decltype(Insn);
|
||||||
Field h = fieldFromInstruction(Insn, 5, 3) |
|
Field H = fieldFromInstruction(Insn, 5, 3) |
|
||||||
(fieldFromInstruction(Insn, 0, 2) << 3);
|
(fieldFromInstruction(Insn, 0, 2) << 3);
|
||||||
Field g = fieldFromInstruction(Insn, 8, 3) |
|
Field G = fieldFromInstruction(Insn, 8, 3) |
|
||||||
(fieldFromInstruction(Insn, 3, 2) << 3);
|
(fieldFromInstruction(Insn, 3, 2) << 3);
|
||||||
|
|
||||||
auto DecodeRegisterOrImm = [&Inst, Address, Decoder](Field RegNum,
|
auto DecodeRegisterOrImm = [&Inst, Address, Decoder](Field RegNum,
|
||||||
@ -287,10 +290,25 @@ static DecodeStatus DecodeMoveHRegInstruction(MCInst &Inst, uint64_t Insn,
|
|||||||
return DecodeGPR32RegisterClass(Inst, RegNum, Address, Decoder);
|
return DecodeGPR32RegisterClass(Inst, RegNum, Address, Decoder);
|
||||||
};
|
};
|
||||||
|
|
||||||
if (MCDisassembler::Success != DecodeRegisterOrImm(g, 0))
|
if (MCDisassembler::Success != DecodeRegisterOrImm(G, 0))
|
||||||
return MCDisassembler::Fail;
|
return MCDisassembler::Fail;
|
||||||
|
|
||||||
return DecodeRegisterOrImm(h, Insn >> 16u);
|
return DecodeRegisterOrImm(H, Insn >> 16u);
|
||||||
|
}
|
||||||
|
|
||||||
|
static DecodeStatus DecodeCCRU6Instruction(MCInst &Inst, uint64_t Insn,
|
||||||
|
uint64_t Address,
|
||||||
|
const void *Decoder) {
|
||||||
|
unsigned DstB;
|
||||||
|
LLVM_DEBUG(dbgs() << "Decoding CCRU6 instruction:\n");
|
||||||
|
DstB = decodeBField(Insn);
|
||||||
|
DecodeGPR32RegisterClass(Inst, DstB, Address, Decoder);
|
||||||
|
using Field = decltype(Insn);
|
||||||
|
Field U6Field = fieldFromInstruction(Insn, 6, 11);
|
||||||
|
Inst.addOperand(MCOperand::createImm(U6Field));
|
||||||
|
Field CCField = fieldFromInstruction(Insn, 0, 4);
|
||||||
|
Inst.addOperand(MCOperand::createImm(CCField));
|
||||||
|
return MCDisassembler::Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
DecodeStatus ARCDisassembler::getInstruction(MCInst &Instr, uint64_t &Size,
|
DecodeStatus ARCDisassembler::getInstruction(MCInst &Instr, uint64_t &Size,
|
||||||
|
@ -178,3 +178,30 @@ void ARCInstPrinter::printBRCCPredicateOperand(const MCInst *MI, unsigned OpNum,
|
|||||||
assert(Op.isImm() && "Predicate operand is immediate.");
|
assert(Op.isImm() && "Predicate operand is immediate.");
|
||||||
O << ARCBRCondCodeToString((ARCCC::BRCondCode)Op.getImm());
|
O << ARCBRCondCodeToString((ARCCC::BRCondCode)Op.getImm());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ARCInstPrinter::printCCOperand(const MCInst *MI, int OpNum,
|
||||||
|
raw_ostream &O) {
|
||||||
|
O << ARCCondCodeToString((ARCCC::CondCode)MI->getOperand(OpNum).getImm());
|
||||||
|
}
|
||||||
|
|
||||||
|
void ARCInstPrinter::printU6ShiftedBy(unsigned ShiftBy, const MCInst *MI,
|
||||||
|
int OpNum, raw_ostream &O) {
|
||||||
|
const MCOperand &MO = MI->getOperand(OpNum);
|
||||||
|
if (MO.isImm()) {
|
||||||
|
unsigned Value = MO.getImm();
|
||||||
|
unsigned Value2 = Value >> ShiftBy;
|
||||||
|
if (Value2 > 0x3F || (Value2 << ShiftBy != Value)) {
|
||||||
|
errs() << "!!! Instruction has out-of-range U6 immediate operand:\n"
|
||||||
|
<< " Opcode is " << MI->getOpcode() << "; operand value is "
|
||||||
|
<< Value;
|
||||||
|
if (ShiftBy)
|
||||||
|
errs() << " scaled by " << (1 << ShiftBy) << "\n";
|
||||||
|
assert(false && "instruction has wrong format");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
printOperand(MI, OpNum, O);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ARCInstPrinter::printU6(const MCInst *MI, int OpNum, raw_ostream &O) {
|
||||||
|
printU6ShiftedBy(0, MI, OpNum, O);
|
||||||
|
}
|
||||||
|
@ -33,6 +33,8 @@ public:
|
|||||||
void printRegName(raw_ostream &OS, unsigned RegNo) const override;
|
void printRegName(raw_ostream &OS, unsigned RegNo) const override;
|
||||||
void printInst(const MCInst *MI, uint64_t Address, StringRef Annot,
|
void printInst(const MCInst *MI, uint64_t Address, StringRef Annot,
|
||||||
const MCSubtargetInfo &STI, raw_ostream &O) override;
|
const MCSubtargetInfo &STI, raw_ostream &O) override;
|
||||||
|
void printCCOperand(const MCInst *MI, int OpNum, raw_ostream &O);
|
||||||
|
void printU6(const MCInst *MI, int OpNum, raw_ostream &O);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void printMemOperandRI(const MCInst *MI, unsigned OpNum, raw_ostream &O);
|
void printMemOperandRI(const MCInst *MI, unsigned OpNum, raw_ostream &O);
|
||||||
@ -44,6 +46,8 @@ private:
|
|||||||
void printPredicateOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O);
|
void printPredicateOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O);
|
||||||
void printBRCCPredicateOperand(const MCInst *MI, unsigned OpNum,
|
void printBRCCPredicateOperand(const MCInst *MI, unsigned OpNum,
|
||||||
raw_ostream &O);
|
raw_ostream &O);
|
||||||
|
void printU6ShiftedBy(unsigned ShiftBy, const MCInst *MI, int OpNum,
|
||||||
|
raw_ostream &O);
|
||||||
};
|
};
|
||||||
} // end namespace llvm
|
} // end namespace llvm
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user