summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp')
-rw-r--r--llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp79
1 files changed, 54 insertions, 25 deletions
diff --git a/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp b/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp
index 3150057fd43..a082b0f77f0 100644
--- a/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp
+++ b/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp
@@ -257,9 +257,9 @@ class MipsAsmParser : public MCTargetAsmParser {
bool expandCondBranches(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
const MCSubtargetInfo *STI);
- bool expandDiv(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
- const MCSubtargetInfo *STI, const bool IsMips64,
- const bool Signed);
+ bool expandDivRem(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
+ const MCSubtargetInfo *STI, const bool IsMips64,
+ const bool Signed);
bool expandTrunc(MCInst &Inst, bool IsDouble, bool Is64FPU, SMLoc IDLoc,
MCStreamer &Out, const MCSubtargetInfo *STI);
@@ -2431,20 +2431,28 @@ MipsAsmParser::tryExpandInstruction(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
return expandCondBranches(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
case Mips::SDivMacro:
case Mips::SDivIMacro:
- return expandDiv(Inst, IDLoc, Out, STI, false, true) ? MER_Fail
- : MER_Success;
+ case Mips::SRemMacro:
+ case Mips::SRemIMacro:
+ return expandDivRem(Inst, IDLoc, Out, STI, false, true) ? MER_Fail
+ : MER_Success;
case Mips::DSDivMacro:
case Mips::DSDivIMacro:
- return expandDiv(Inst, IDLoc, Out, STI, true, true) ? MER_Fail
- : MER_Success;
+ case Mips::DSRemMacro:
+ case Mips::DSRemIMacro:
+ return expandDivRem(Inst, IDLoc, Out, STI, true, true) ? MER_Fail
+ : MER_Success;
case Mips::UDivMacro:
case Mips::UDivIMacro:
- return expandDiv(Inst, IDLoc, Out, STI, false, false) ? MER_Fail
- : MER_Success;
+ case Mips::URemMacro:
+ case Mips::URemIMacro:
+ return expandDivRem(Inst, IDLoc, Out, STI, false, false) ? MER_Fail
+ : MER_Success;
case Mips::DUDivMacro:
case Mips::DUDivIMacro:
- return expandDiv(Inst, IDLoc, Out, STI, true, false) ? MER_Fail
- : MER_Success;
+ case Mips::DURemMacro:
+ case Mips::DURemIMacro:
+ return expandDivRem(Inst, IDLoc, Out, STI, true, false) ? MER_Fail
+ : MER_Success;
case Mips::PseudoTRUNC_W_S:
return expandTrunc(Inst, false, false, IDLoc, Out, STI) ? MER_Fail
: MER_Success;
@@ -3927,9 +3935,9 @@ bool MipsAsmParser::expandCondBranches(MCInst &Inst, SMLoc IDLoc,
// The destination register can only be $zero when expanding (S)DivIMacro or
// D(S)DivMacro.
-bool MipsAsmParser::expandDiv(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
- const MCSubtargetInfo *STI, const bool IsMips64,
- const bool Signed) {
+bool MipsAsmParser::expandDivRem(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
+ const MCSubtargetInfo *STI, const bool IsMips64,
+ const bool Signed) {
MipsTargetStreamer &TOut = getTargetStreamer();
warnIfNoMacro(IDLoc);
@@ -3969,6 +3977,17 @@ bool MipsAsmParser::expandDiv(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
bool UseTraps = useTraps();
+ unsigned Opcode = Inst.getOpcode();
+ bool isDiv = Opcode == Mips::SDivMacro || Opcode == Mips::SDivIMacro ||
+ Opcode == Mips::UDivMacro || Opcode == Mips::UDivIMacro ||
+ Opcode == Mips::DSDivMacro || Opcode == Mips::DSDivIMacro ||
+ Opcode == Mips::DUDivMacro || Opcode == Mips::DUDivIMacro;
+
+ bool isRem = Opcode == Mips::SRemMacro || Opcode == Mips::SRemIMacro ||
+ Opcode == Mips::URemMacro || Opcode == Mips::URemIMacro ||
+ Opcode == Mips::DSRemMacro || Opcode == Mips::DSRemIMacro ||
+ Opcode == Mips::DURemMacro || Opcode == Mips::DURemIMacro;
+
if (RtOp.isImm()) {
unsigned ATReg = getATReg(IDLoc);
if (!ATReg)
@@ -3982,10 +4001,13 @@ bool MipsAsmParser::expandDiv(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
return false;
}
- if (ImmValue == 1) {
+ if (isRem && (ImmValue == 1 || (Signed && (ImmValue == -1)))) {
+ TOut.emitRRR(Mips::OR, RdReg, ZeroReg, ZeroReg, IDLoc, STI);
+ return false;
+ } else if (isDiv && ImmValue == 1) {
TOut.emitRRR(Mips::OR, RdReg, RsReg, Mips::ZERO, IDLoc, STI);
return false;
- } else if (Signed && ImmValue == -1) {
+ } else if (isDiv && Signed && ImmValue == -1) {
TOut.emitRRR(SubOp, RdReg, ZeroReg, RsReg, IDLoc, STI);
return false;
} else {
@@ -3993,16 +4015,16 @@ bool MipsAsmParser::expandDiv(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
false, Inst.getLoc(), Out, STI))
return true;
TOut.emitRR(DivOp, RsReg, ATReg, IDLoc, STI);
- TOut.emitR(Mips::MFLO, RdReg, IDLoc, STI);
+ TOut.emitR(isDiv ? Mips::MFLO : Mips::MFHI, RdReg, IDLoc, STI);
return false;
}
return true;
}
- // If the macro expansion of (d)div(u) would always trap or break, insert
- // the trap/break and exit. This gives a different result to GAS. GAS has
- // an inconsistency/missed optimization in that not all cases are handled
- // equivalently. As the observed behaviour is the same, we're ok.
+ // If the macro expansion of (d)div(u) or (d)rem(u) would always trap or
+ // break, insert the trap/break and exit. This gives a different result to
+ // GAS. GAS has an inconsistency/missed optimization in that not all cases
+ // are handled equivalently. As the observed behaviour is the same, we're ok.
if (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64) {
if (UseTraps) {
TOut.emitRRI(Mips::TEQ, ZeroReg, ZeroReg, 0x7, IDLoc, STI);
@@ -4012,6 +4034,13 @@ bool MipsAsmParser::expandDiv(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
return false;
}
+ // (d)rem(u) $0, $X, $Y is a special case. Like div $zero, $X, $Y, it does
+ // not expand to macro sequence.
+ if (isRem && (RdReg == Mips::ZERO || RdReg == Mips::ZERO_64)) {
+ TOut.emitRR(DivOp, RsReg, RtReg, IDLoc, STI);
+ return false;
+ }
+
// Temporary label for first branch traget
MCContext &Context = TOut.getStreamer().getContext();
MCSymbol *BrTarget;
@@ -4035,7 +4064,7 @@ bool MipsAsmParser::expandDiv(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
if (!UseTraps)
TOut.getStreamer().EmitLabel(BrTarget);
- TOut.emitR(Mips::MFLO, RdReg, IDLoc, STI);
+ TOut.emitR(isDiv ? Mips::MFLO : Mips::MFHI, RdReg, IDLoc, STI);
return false;
}
@@ -4058,7 +4087,7 @@ bool MipsAsmParser::expandDiv(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
if (IsMips64) {
TOut.emitRRI(Mips::ADDiu, ATReg, ZeroReg, 1, IDLoc, STI);
- TOut.emitRRI(Mips::DSLL32, ATReg, ATReg, 0x1f, IDLoc, STI);
+ TOut.emitDSLL(ATReg, ATReg, 63, IDLoc, STI);
} else {
TOut.emitRI(Mips::LUi, ATReg, (uint16_t)0x8000, IDLoc, STI);
}
@@ -4068,12 +4097,12 @@ bool MipsAsmParser::expandDiv(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
else {
// Branch to the mflo instruction.
TOut.emitRRX(Mips::BNE, RsReg, ATReg, LabelOpEnd, IDLoc, STI);
- TOut.emitRRI(Mips::SLL, ZeroReg, ZeroReg, 0, IDLoc, STI);
+ TOut.emitNop(IDLoc, STI);
TOut.emitII(Mips::BREAK, 0x6, 0, IDLoc, STI);
}
TOut.getStreamer().EmitLabel(BrTargetEnd);
- TOut.emitR(Mips::MFLO, RdReg, IDLoc, STI);
+ TOut.emitR(isDiv ? Mips::MFLO : Mips::MFHI, RdReg, IDLoc, STI);
return false;
}
OpenPOWER on IntegriCloud