diff --git a/llvm/lib/Target/ARC/ARCInstrFormats.td b/llvm/lib/Target/ARC/ARCInstrFormats.td --- a/llvm/lib/Target/ARC/ARCInstrFormats.td +++ b/llvm/lib/Target/ARC/ARCInstrFormats.td @@ -261,6 +261,31 @@ 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 major, bits<6> subop, bit F, dag outs, dag ins, + string asmstr, list 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 --- 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; + +// The "u6" operand of a RRU6-type instruction +let PrintMethod = "printU6" in { + def u6 : Operand, ImmLeaf(Imm); + }]>; + def wide_u6 : Operand, ImmLeaf(Imm); + }]>; +} + // --------------------------------------------------------------------------- // Selection DAG Nodes. // --------------------------------------------------------------------------- @@ -299,14 +317,24 @@ 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 --- a/llvm/lib/Target/ARC/Disassembler/ARCDisassembler.cpp +++ b/llvm/lib/Target/ARC/Disassembler/ARCDisassembler.cpp @@ -107,6 +107,9 @@ 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 *); @@ -293,6 +296,21 @@ 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, ArrayRef Bytes, uint64_t Address, diff --git a/llvm/lib/Target/ARC/MCTargetDesc/ARCInstPrinter.h b/llvm/lib/Target/ARC/MCTargetDesc/ARCInstPrinter.h --- a/llvm/lib/Target/ARC/MCTargetDesc/ARCInstPrinter.h +++ b/llvm/lib/Target/ARC/MCTargetDesc/ARCInstPrinter.h @@ -33,6 +33,8 @@ 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 @@ void printPredicateOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O); void printBRCCPredicateOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O); + void printU6_shiftedBy(unsigned shiftBy, const MCInst *MI, int opNum, + raw_ostream &O); }; } // end namespace llvm diff --git a/llvm/lib/Target/ARC/MCTargetDesc/ARCInstPrinter.cpp b/llvm/lib/Target/ARC/MCTargetDesc/ARCInstPrinter.cpp --- a/llvm/lib/Target/ARC/MCTargetDesc/ARCInstPrinter.cpp +++ b/llvm/lib/Target/ARC/MCTargetDesc/ARCInstPrinter.cpp @@ -178,3 +178,30 @@ 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::printU6_shiftedBy(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) { + printU6_shiftedBy(0, MI, opNum, O); +} diff --git a/llvm/test/MC/Disassembler/ARC/misc.txt b/llvm/test/MC/Disassembler/ARC/misc.txt --- a/llvm/test/MC/Disassembler/ARC/misc.txt +++ b/llvm/test/MC/Disassembler/ARC/misc.txt @@ -16,6 +16,12 @@ # CHECK: mov %r1, 20 0x4a 0x21 0x00 0x05 +# CHECK: mov.eq %r0, 32 +0xca 0x20 0x21 0x08 + +# CHECK: mov.ne %r0, 0 +0xca 0x20 0x22 0x00 + # CHECK: st.aw %fp, [%sp,-4] 0xfc 0x1c 0xc8 0xb6