[llvm] 6b3eba7 - [ARC] Add disassembly for the conditioned move immediate instruction
Mark Schimmel via llvm-commits
llvm-commits at lists.llvm.org
Mon Jul 12 12:37:07 PDT 2021
Author: Thomas Johnson
Date: 2021-07-12T12:35:56-07:00
New Revision: 6b3eba7c285c9399f1a198d5490ac9522f2fd614
URL: https://github.com/llvm/llvm-project/commit/6b3eba7c285c9399f1a198d5490ac9522f2fd614
DIFF: https://github.com/llvm/llvm-project/commit/6b3eba7c285c9399f1a198d5490ac9522f2fd614.diff
LOG: [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
Added:
Modified:
llvm/lib/Target/ARC/ARCInstrFormats.td
llvm/lib/Target/ARC/ARCInstrInfo.td
llvm/lib/Target/ARC/Disassembler/ARCDisassembler.cpp
llvm/lib/Target/ARC/MCTargetDesc/ARCInstPrinter.cpp
llvm/lib/Target/ARC/MCTargetDesc/ARCInstPrinter.h
Removed:
################################################################################
diff --git a/llvm/lib/Target/ARC/ARCInstrFormats.td b/llvm/lib/Target/ARC/ARCInstrFormats.td
index 584844d495530..c95c71ff007bb 100644
--- a/llvm/lib/Target/ARC/ARCInstrFormats.td
+++ b/llvm/lib/Target/ARC/ARCInstrFormats.td
@@ -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;
}
+// 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
// for this format.
diff --git a/llvm/lib/Target/ARC/ARCInstrInfo.td b/llvm/lib/Target/ARC/ARCInstrInfo.td
index 1dc81dd76a523..23e2d57b625ec 100644
--- a/llvm/lib/Target/ARC/ARCInstrInfo.td
+++ b/llvm/lib/Target/ARC/ARCInstrInfo.td
@@ -12,6 +12,24 @@
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.
// ---------------------------------------------------------------------------
@@ -299,14 +317,24 @@ def MOV_ru6 : F32_DOP_RU6<0b00100, 0b001010, 0,
def cmov : PatFrag<(ops node:$op1, node:$op2, node:$cc),
(ARCcmov $op1, $op2, $cc)>;
let Uses = [STATUS32] in {
-def MOVcc : F32_DOP_CC_RR<0b00100, 0b001010, 0,
- (outs GPR32:$B),
- (ins GPR32:$C, GPR32:$fval, cmovpred:$cc),
- !strconcat("mov.", "$cc\t$B, $C"),
- [(set GPR32:$B, (cmov i32:$C, i32:$fval, cmovpred:$cc))]> {
- let Constraints = "$B = $fval";
-}
+ def MOVcc : F32_DOP_CC_RR<0b00100, 0b001010, 0,
+ (outs GPR32:$B),
+ (ins GPR32:$C, GPR32:$fval, cmovpred:$cc),
+ !strconcat("mov.", "$cc\t$B, $C"),
+ [(set GPR32:$B, (cmov i32:$C, i32:$fval, cmovpred:$cc))]> {
+ 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),
(MOV_rlimm tglobaladdr:$addr)>;
diff --git a/llvm/lib/Target/ARC/Disassembler/ARCDisassembler.cpp b/llvm/lib/Target/ARC/Disassembler/ARCDisassembler.cpp
index 611fd0e3e78dd..b7033d0972b9c 100644
--- a/llvm/lib/Target/ARC/Disassembler/ARCDisassembler.cpp
+++ b/llvm/lib/Target/ARC/Disassembler/ARCDisassembler.cpp
@@ -107,6 +107,9 @@ static DecodeStatus DecodeStLImmInstruction(MCInst &, uint64_t, uint64_t,
static DecodeStatus DecodeLdRLImmInstruction(MCInst &, uint64_t, uint64_t,
const void *);
+static DecodeStatus DecodeCCRU6Instruction(MCInst &, uint64_t, uint64_t,
+ const void *);
+
static DecodeStatus DecodeMoveHRegInstruction(MCInst &Inst, uint64_t, uint64_t,
const void *);
@@ -167,19 +170,19 @@ static DecodeStatus DecodeMEMrs9(MCInst &Inst, unsigned Insn, uint64_t Address,
static bool DecodeSymbolicOperand(MCInst &Inst, uint64_t Address,
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*.
auto Disassembler = static_cast<const MCDisassembler *>(Decoder);
return (nullptr != Disassembler &&
Disassembler->tryAddingSymbolicOperand(Inst, Value, Address, true, 0,
- atLeast));
+ AtLeast));
}
static void DecodeSymbolicOperandOff(MCInst &Inst, uint64_t Address,
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));
}
@@ -272,9 +275,9 @@ static DecodeStatus DecodeMoveHRegInstruction(MCInst &Inst, uint64_t Insn,
const void *Decoder) {
LLVM_DEBUG(dbgs() << "Decoding MOV_S h-register\n");
using Field = decltype(Insn);
- Field h = fieldFromInstruction(Insn, 5, 3) |
+ Field H = fieldFromInstruction(Insn, 5, 3) |
(fieldFromInstruction(Insn, 0, 2) << 3);
- Field g = fieldFromInstruction(Insn, 8, 3) |
+ Field G = fieldFromInstruction(Insn, 8, 3) |
(fieldFromInstruction(Insn, 3, 2) << 3);
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);
};
- if (MCDisassembler::Success != DecodeRegisterOrImm(g, 0))
+ if (MCDisassembler::Success != DecodeRegisterOrImm(G, 0))
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,
diff --git a/llvm/lib/Target/ARC/MCTargetDesc/ARCInstPrinter.cpp b/llvm/lib/Target/ARC/MCTargetDesc/ARCInstPrinter.cpp
index 8eefae5ee4911..f34b698e9af23 100644
--- a/llvm/lib/Target/ARC/MCTargetDesc/ARCInstPrinter.cpp
+++ b/llvm/lib/Target/ARC/MCTargetDesc/ARCInstPrinter.cpp
@@ -178,3 +178,30 @@ void ARCInstPrinter::printBRCCPredicateOperand(const MCInst *MI, unsigned OpNum,
assert(Op.isImm() && "Predicate operand is immediate.");
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);
+}
diff --git a/llvm/lib/Target/ARC/MCTargetDesc/ARCInstPrinter.h b/llvm/lib/Target/ARC/MCTargetDesc/ARCInstPrinter.h
index f6f8f9d089dfc..6f52e8faca3e9 100644
--- a/llvm/lib/Target/ARC/MCTargetDesc/ARCInstPrinter.h
+++ b/llvm/lib/Target/ARC/MCTargetDesc/ARCInstPrinter.h
@@ -33,6 +33,8 @@ class ARCInstPrinter : public MCInstPrinter {
void printRegName(raw_ostream &OS, unsigned RegNo) const override;
void printInst(const MCInst *MI, uint64_t Address, StringRef Annot,
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:
void printMemOperandRI(const MCInst *MI, unsigned OpNum, raw_ostream &O);
@@ -44,6 +46,8 @@ class ARCInstPrinter : public MCInstPrinter {
void printPredicateOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O);
void printBRCCPredicateOperand(const MCInst *MI, unsigned OpNum,
raw_ostream &O);
+ void printU6ShiftedBy(unsigned ShiftBy, const MCInst *MI, int OpNum,
+ raw_ostream &O);
};
} // end namespace llvm
More information about the llvm-commits
mailing list