@@ -257,9 +257,9 @@ class MipsAsmParser : public MCTargetAsmParser {
257
257
bool expandCondBranches (MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
258
258
const MCSubtargetInfo *STI);
259
259
260
- bool expandDiv (MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
261
- const MCSubtargetInfo *STI, const bool IsMips64,
262
- const bool Signed);
260
+ bool expandDivRem (MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
261
+ const MCSubtargetInfo *STI, const bool IsMips64,
262
+ const bool Signed);
263
263
264
264
bool expandTrunc (MCInst &Inst, bool IsDouble, bool Is64FPU, SMLoc IDLoc,
265
265
MCStreamer &Out, const MCSubtargetInfo *STI);
@@ -2431,20 +2431,28 @@ MipsAsmParser::tryExpandInstruction(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
2431
2431
return expandCondBranches (Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
2432
2432
case Mips::SDivMacro:
2433
2433
case Mips::SDivIMacro:
2434
- return expandDiv (Inst, IDLoc, Out, STI, false , true ) ? MER_Fail
2435
- : MER_Success;
2434
+ case Mips::SRemMacro:
2435
+ case Mips::SRemIMacro:
2436
+ return expandDivRem (Inst, IDLoc, Out, STI, false , true ) ? MER_Fail
2437
+ : MER_Success;
2436
2438
case Mips::DSDivMacro:
2437
2439
case Mips::DSDivIMacro:
2438
- return expandDiv (Inst, IDLoc, Out, STI, true , true ) ? MER_Fail
2439
- : MER_Success;
2440
+ case Mips::DSRemMacro:
2441
+ case Mips::DSRemIMacro:
2442
+ return expandDivRem (Inst, IDLoc, Out, STI, true , true ) ? MER_Fail
2443
+ : MER_Success;
2440
2444
case Mips::UDivMacro:
2441
2445
case Mips::UDivIMacro:
2442
- return expandDiv (Inst, IDLoc, Out, STI, false , false ) ? MER_Fail
2443
- : MER_Success;
2446
+ case Mips::URemMacro:
2447
+ case Mips::URemIMacro:
2448
+ return expandDivRem (Inst, IDLoc, Out, STI, false , false ) ? MER_Fail
2449
+ : MER_Success;
2444
2450
case Mips::DUDivMacro:
2445
2451
case Mips::DUDivIMacro:
2446
- return expandDiv (Inst, IDLoc, Out, STI, true , false ) ? MER_Fail
2447
- : MER_Success;
2452
+ case Mips::DURemMacro:
2453
+ case Mips::DURemIMacro:
2454
+ return expandDivRem (Inst, IDLoc, Out, STI, true , false ) ? MER_Fail
2455
+ : MER_Success;
2448
2456
case Mips::PseudoTRUNC_W_S:
2449
2457
return expandTrunc (Inst, false , false , IDLoc, Out, STI) ? MER_Fail
2450
2458
: MER_Success;
@@ -3927,9 +3935,9 @@ bool MipsAsmParser::expandCondBranches(MCInst &Inst, SMLoc IDLoc,
3927
3935
// The destination register can only be $zero when expanding (S)DivIMacro or
3928
3936
// D(S)DivMacro.
3929
3937
3930
- bool MipsAsmParser::expandDiv (MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3931
- const MCSubtargetInfo *STI, const bool IsMips64,
3932
- const bool Signed) {
3938
+ bool MipsAsmParser::expandDivRem (MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3939
+ const MCSubtargetInfo *STI, const bool IsMips64,
3940
+ const bool Signed) {
3933
3941
MipsTargetStreamer &TOut = getTargetStreamer ();
3934
3942
3935
3943
warnIfNoMacro (IDLoc);
@@ -3969,6 +3977,17 @@ bool MipsAsmParser::expandDiv(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3969
3977
3970
3978
bool UseTraps = useTraps ();
3971
3979
3980
+ unsigned Opcode = Inst.getOpcode ();
3981
+ bool isDiv = Opcode == Mips::SDivMacro || Opcode == Mips::SDivIMacro ||
3982
+ Opcode == Mips::UDivMacro || Opcode == Mips::UDivIMacro ||
3983
+ Opcode == Mips::DSDivMacro || Opcode == Mips::DSDivIMacro ||
3984
+ Opcode == Mips::DUDivMacro || Opcode == Mips::DUDivIMacro;
3985
+
3986
+ bool isRem = Opcode == Mips::SRemMacro || Opcode == Mips::SRemIMacro ||
3987
+ Opcode == Mips::URemMacro || Opcode == Mips::URemIMacro ||
3988
+ Opcode == Mips::DSRemMacro || Opcode == Mips::DSRemIMacro ||
3989
+ Opcode == Mips::DURemMacro || Opcode == Mips::DURemIMacro;
3990
+
3972
3991
if (RtOp.isImm ()) {
3973
3992
unsigned ATReg = getATReg (IDLoc);
3974
3993
if (!ATReg)
@@ -3982,27 +4001,30 @@ bool MipsAsmParser::expandDiv(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
3982
4001
return false ;
3983
4002
}
3984
4003
3985
- if (ImmValue == 1 ) {
4004
+ if (isRem && (ImmValue == 1 || (Signed && (ImmValue == -1 )))) {
4005
+ TOut.emitRRR (Mips::OR, RdReg, ZeroReg, ZeroReg, IDLoc, STI);
4006
+ return false ;
4007
+ } else if (isDiv && ImmValue == 1 ) {
3986
4008
TOut.emitRRR (Mips::OR, RdReg, RsReg, Mips::ZERO, IDLoc, STI);
3987
4009
return false ;
3988
- } else if (Signed && ImmValue == -1 ) {
4010
+ } else if (isDiv && Signed && ImmValue == -1 ) {
3989
4011
TOut.emitRRR (SubOp, RdReg, ZeroReg, RsReg, IDLoc, STI);
3990
4012
return false ;
3991
4013
} else {
3992
4014
if (loadImmediate (ImmValue, ATReg, Mips::NoRegister, isInt<32 >(ImmValue),
3993
4015
false , Inst.getLoc (), Out, STI))
3994
4016
return true ;
3995
4017
TOut.emitRR (DivOp, RsReg, ATReg, IDLoc, STI);
3996
- TOut.emitR (Mips::MFLO, RdReg, IDLoc, STI);
4018
+ TOut.emitR (isDiv ? Mips::MFLO : Mips::MFHI , RdReg, IDLoc, STI);
3997
4019
return false ;
3998
4020
}
3999
4021
return true ;
4000
4022
}
4001
4023
4002
- // If the macro expansion of (d)div(u) would always trap or break, insert
4003
- // the trap/break and exit. This gives a different result to GAS. GAS has
4004
- // an inconsistency/missed optimization in that not all cases are handled
4005
- // equivalently. As the observed behaviour is the same, we're ok.
4024
+ // If the macro expansion of (d)div(u) or (d)rem(u) would always trap or
4025
+ // break, insert the trap/break and exit. This gives a different result to
4026
+ // GAS. GAS has an inconsistency/missed optimization in that not all cases
4027
+ // are handled equivalently. As the observed behaviour is the same, we're ok.
4006
4028
if (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64) {
4007
4029
if (UseTraps) {
4008
4030
TOut.emitRRI (Mips::TEQ, ZeroReg, ZeroReg, 0x7 , IDLoc, STI);
@@ -4012,6 +4034,13 @@ bool MipsAsmParser::expandDiv(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4012
4034
return false ;
4013
4035
}
4014
4036
4037
+ // (d)rem(u) $0, $X, $Y is a special case. Like div $zero, $X, $Y, it does
4038
+ // not expand to macro sequence.
4039
+ if (isRem && (RdReg == Mips::ZERO || RdReg == Mips::ZERO_64)) {
4040
+ TOut.emitRR (DivOp, RsReg, RtReg, IDLoc, STI);
4041
+ return false ;
4042
+ }
4043
+
4015
4044
// Temporary label for first branch traget
4016
4045
MCContext &Context = TOut.getStreamer ().getContext ();
4017
4046
MCSymbol *BrTarget;
@@ -4035,7 +4064,7 @@ bool MipsAsmParser::expandDiv(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4035
4064
if (!UseTraps)
4036
4065
TOut.getStreamer ().EmitLabel (BrTarget);
4037
4066
4038
- TOut.emitR (Mips::MFLO, RdReg, IDLoc, STI);
4067
+ TOut.emitR (isDiv ? Mips::MFLO : Mips::MFHI , RdReg, IDLoc, STI);
4039
4068
return false ;
4040
4069
}
4041
4070
@@ -4058,7 +4087,7 @@ bool MipsAsmParser::expandDiv(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4058
4087
4059
4088
if (IsMips64) {
4060
4089
TOut.emitRRI (Mips::ADDiu, ATReg, ZeroReg, 1 , IDLoc, STI);
4061
- TOut.emitRRI (Mips::DSLL32, ATReg, ATReg, 0x1f , IDLoc, STI);
4090
+ TOut.emitDSLL ( ATReg, ATReg, 63 , IDLoc, STI);
4062
4091
} else {
4063
4092
TOut.emitRI (Mips::LUi, ATReg, (uint16_t )0x8000 , IDLoc, STI);
4064
4093
}
@@ -4068,12 +4097,12 @@ bool MipsAsmParser::expandDiv(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
4068
4097
else {
4069
4098
// Branch to the mflo instruction.
4070
4099
TOut.emitRRX (Mips::BNE, RsReg, ATReg, LabelOpEnd, IDLoc, STI);
4071
- TOut.emitRRI (Mips::SLL, ZeroReg, ZeroReg, 0 , IDLoc, STI);
4100
+ TOut.emitNop ( IDLoc, STI);
4072
4101
TOut.emitII (Mips::BREAK, 0x6 , 0 , IDLoc, STI);
4073
4102
}
4074
4103
4075
4104
TOut.getStreamer ().EmitLabel (BrTargetEnd);
4076
- TOut.emitR (Mips::MFLO, RdReg, IDLoc, STI);
4105
+ TOut.emitR (isDiv ? Mips::MFLO : Mips::MFHI , RdReg, IDLoc, STI);
4077
4106
return false ;
4078
4107
}
4079
4108
0 commit comments