diff options
Diffstat (limited to 'llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp')
-rw-r--r-- | llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp | 104 |
1 files changed, 104 insertions, 0 deletions
diff --git a/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp b/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp index 928b8edd310..0d968674faa 100644 --- a/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp +++ b/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp @@ -275,6 +275,12 @@ class MipsAsmParser : public MCTargetAsmParser { bool expandUxw(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, const MCSubtargetInfo *STI); + bool expandSge(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, + const MCSubtargetInfo *STI); + + bool expandSgeImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, + const MCSubtargetInfo *STI); + bool expandSgtImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, const MCSubtargetInfo *STI); @@ -2476,6 +2482,14 @@ MipsAsmParser::tryExpandInstruction(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, case Mips::NORImm: case Mips::NORImm64: return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success; + case Mips::SGE: + case Mips::SGEU: + return expandSge(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success; + case Mips::SGEImm: + case Mips::SGEUImm: + case Mips::SGEImm64: + case Mips::SGEUImm64: + return expandSgeImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success; case Mips::SGTImm: case Mips::SGTUImm: case Mips::SGTImm64: @@ -4293,6 +4307,96 @@ bool MipsAsmParser::expandUxw(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, return false; } +bool MipsAsmParser::expandSge(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, + const MCSubtargetInfo *STI) { + MipsTargetStreamer &TOut = getTargetStreamer(); + + assert(Inst.getNumOperands() == 3 && "Invalid operand count"); + assert(Inst.getOperand(0).isReg() && + Inst.getOperand(1).isReg() && + Inst.getOperand(2).isReg() && "Invalid instruction operand."); + + unsigned DstReg = Inst.getOperand(0).getReg(); + unsigned SrcReg = Inst.getOperand(1).getReg(); + unsigned OpReg = Inst.getOperand(2).getReg(); + unsigned OpCode; + + warnIfNoMacro(IDLoc); + + switch (Inst.getOpcode()) { + case Mips::SGE: + OpCode = Mips::SLT; + break; + case Mips::SGEU: + OpCode = Mips::SLTu; + break; + default: + llvm_unreachable("unexpected 'sge' opcode"); + } + + // $SrcReg >= $OpReg is equal to (not ($SrcReg < $OpReg)) + TOut.emitRRR(OpCode, DstReg, SrcReg, OpReg, IDLoc, STI); + TOut.emitRRI(Mips::XORi, DstReg, DstReg, 1, IDLoc, STI); + + return false; +} + +bool MipsAsmParser::expandSgeImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, + const MCSubtargetInfo *STI) { + MipsTargetStreamer &TOut = getTargetStreamer(); + + assert(Inst.getNumOperands() == 3 && "Invalid operand count"); + assert(Inst.getOperand(0).isReg() && + Inst.getOperand(1).isReg() && + Inst.getOperand(2).isImm() && "Invalid instruction operand."); + + unsigned DstReg = Inst.getOperand(0).getReg(); + unsigned SrcReg = Inst.getOperand(1).getReg(); + int64_t ImmValue = Inst.getOperand(2).getImm(); + unsigned OpRegCode, OpImmCode; + + warnIfNoMacro(IDLoc); + + switch (Inst.getOpcode()) { + case Mips::SGEImm: + case Mips::SGEImm64: + OpRegCode = Mips::SLT; + OpImmCode = Mips::SLTi; + break; + case Mips::SGEUImm: + case Mips::SGEUImm64: + OpRegCode = Mips::SLTu; + OpImmCode = Mips::SLTiu; + break; + default: + llvm_unreachable("unexpected 'sge' opcode with immediate"); + } + + // $SrcReg >= Imm is equal to (not ($SrcReg < Imm)) + if (isInt<16>(ImmValue)) { + // Use immediate version of STL. + TOut.emitRRI(OpImmCode, DstReg, SrcReg, ImmValue, IDLoc, STI); + TOut.emitRRI(Mips::XORi, DstReg, DstReg, 1, IDLoc, STI); + } else { + unsigned ImmReg = DstReg; + if (DstReg == SrcReg) { + unsigned ATReg = getATReg(Inst.getLoc()); + if (!ATReg) + return true; + ImmReg = ATReg; + } + + if (loadImmediate(ImmValue, ImmReg, Mips::NoRegister, isInt<32>(ImmValue), + false, IDLoc, Out, STI)) + return true; + + TOut.emitRRR(OpRegCode, DstReg, SrcReg, ImmReg, IDLoc, STI); + TOut.emitRRI(Mips::XORi, DstReg, DstReg, 1, IDLoc, STI); + } + + return false; +} + bool MipsAsmParser::expandSgtImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, const MCSubtargetInfo *STI) { MipsTargetStreamer &TOut = getTargetStreamer(); |