1
0
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:
Thomas Johnson 2021-07-08 16:45:45 -07:00 committed by Mark Schimmel
parent 7664c93484
commit 76438a2e53
5 changed files with 117 additions and 15 deletions

View File

@ -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.

View File

@ -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)>;

View File

@ -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,

View File

@ -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);
}

View File

@ -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