Skip to content
This repository was archived by the owner on Feb 5, 2019. It is now read-only.

Commit b9d744a

Browse files
author
Stefan Maksimovic
committed
[mips] Addition of the [d]rem and [d]remu instructions
Related to http://reviews.llvm.org/D15772 Depends on http://reviews.llvm.org/D16889 Adds [D]REM[U] instructions. Patch By: Srdjan Obucina Contributions from: Simon Dardis Differential Revision: https://reviews.llvm.org/D17036 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@336545 91177308-0d34-0410-b5e6-96231b3b80d8
1 parent 93fba7b commit b9d744a

File tree

8 files changed

+853
-28
lines changed

8 files changed

+853
-28
lines changed

lib/Target/Mips/AsmParser/MipsAsmParser.cpp

Lines changed: 54 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -257,9 +257,9 @@ class MipsAsmParser : public MCTargetAsmParser {
257257
bool expandCondBranches(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
258258
const MCSubtargetInfo *STI);
259259

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);
263263

264264
bool expandTrunc(MCInst &Inst, bool IsDouble, bool Is64FPU, SMLoc IDLoc,
265265
MCStreamer &Out, const MCSubtargetInfo *STI);
@@ -2431,20 +2431,28 @@ MipsAsmParser::tryExpandInstruction(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
24312431
return expandCondBranches(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
24322432
case Mips::SDivMacro:
24332433
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;
24362438
case Mips::DSDivMacro:
24372439
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;
24402444
case Mips::UDivMacro:
24412445
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;
24442450
case Mips::DUDivMacro:
24452451
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;
24482456
case Mips::PseudoTRUNC_W_S:
24492457
return expandTrunc(Inst, false, false, IDLoc, Out, STI) ? MER_Fail
24502458
: MER_Success;
@@ -3927,9 +3935,9 @@ bool MipsAsmParser::expandCondBranches(MCInst &Inst, SMLoc IDLoc,
39273935
// The destination register can only be $zero when expanding (S)DivIMacro or
39283936
// D(S)DivMacro.
39293937

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) {
39333941
MipsTargetStreamer &TOut = getTargetStreamer();
39343942

39353943
warnIfNoMacro(IDLoc);
@@ -3969,6 +3977,17 @@ bool MipsAsmParser::expandDiv(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
39693977

39703978
bool UseTraps = useTraps();
39713979

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+
39723991
if (RtOp.isImm()) {
39733992
unsigned ATReg = getATReg(IDLoc);
39743993
if (!ATReg)
@@ -3982,27 +4001,30 @@ bool MipsAsmParser::expandDiv(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
39824001
return false;
39834002
}
39844003

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) {
39864008
TOut.emitRRR(Mips::OR, RdReg, RsReg, Mips::ZERO, IDLoc, STI);
39874009
return false;
3988-
} else if (Signed && ImmValue == -1) {
4010+
} else if (isDiv && Signed && ImmValue == -1) {
39894011
TOut.emitRRR(SubOp, RdReg, ZeroReg, RsReg, IDLoc, STI);
39904012
return false;
39914013
} else {
39924014
if (loadImmediate(ImmValue, ATReg, Mips::NoRegister, isInt<32>(ImmValue),
39934015
false, Inst.getLoc(), Out, STI))
39944016
return true;
39954017
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);
39974019
return false;
39984020
}
39994021
return true;
40004022
}
40014023

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.
40064028
if (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64) {
40074029
if (UseTraps) {
40084030
TOut.emitRRI(Mips::TEQ, ZeroReg, ZeroReg, 0x7, IDLoc, STI);
@@ -4012,6 +4034,13 @@ bool MipsAsmParser::expandDiv(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
40124034
return false;
40134035
}
40144036

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+
40154044
// Temporary label for first branch traget
40164045
MCContext &Context = TOut.getStreamer().getContext();
40174046
MCSymbol *BrTarget;
@@ -4035,7 +4064,7 @@ bool MipsAsmParser::expandDiv(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
40354064
if (!UseTraps)
40364065
TOut.getStreamer().EmitLabel(BrTarget);
40374066

4038-
TOut.emitR(Mips::MFLO, RdReg, IDLoc, STI);
4067+
TOut.emitR(isDiv ? Mips::MFLO : Mips::MFHI, RdReg, IDLoc, STI);
40394068
return false;
40404069
}
40414070

@@ -4058,7 +4087,7 @@ bool MipsAsmParser::expandDiv(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
40584087

40594088
if (IsMips64) {
40604089
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);
40624091
} else {
40634092
TOut.emitRI(Mips::LUi, ATReg, (uint16_t)0x8000, IDLoc, STI);
40644093
}
@@ -4068,12 +4097,12 @@ bool MipsAsmParser::expandDiv(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
40684097
else {
40694098
// Branch to the mflo instruction.
40704099
TOut.emitRRX(Mips::BNE, RsReg, ATReg, LabelOpEnd, IDLoc, STI);
4071-
TOut.emitRRI(Mips::SLL, ZeroReg, ZeroReg, 0, IDLoc, STI);
4100+
TOut.emitNop(IDLoc, STI);
40724101
TOut.emitII(Mips::BREAK, 0x6, 0, IDLoc, STI);
40734102
}
40744103

40754104
TOut.getStreamer().EmitLabel(BrTargetEnd);
4076-
TOut.emitR(Mips::MFLO, RdReg, IDLoc, STI);
4105+
TOut.emitR(isDiv ? Mips::MFLO : Mips::MFHI, RdReg, IDLoc, STI);
40774106
return false;
40784107
}
40794108

lib/Target/Mips/Mips64InstrInfo.td

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1032,6 +1032,38 @@ let AdditionalPredicates = [NotInMicroMips] in {
10321032
GPR64Opnd:$rd,
10331033
imm64:$imm), 0>,
10341034
ISA_MIPS3_NOT_32R6_64R6;
1035+
def DSRemMacro : MipsAsmPseudoInst<(outs GPR64Opnd:$rd),
1036+
(ins GPR64Opnd:$rs, GPR64Opnd:$rt),
1037+
"drem\t$rd, $rs, $rt">,
1038+
ISA_MIPS3_NOT_32R6_64R6;
1039+
def DSRemIMacro : MipsAsmPseudoInst<(outs GPR64Opnd:$rd),
1040+
(ins GPR64Opnd:$rs, simm32_relaxed:$imm),
1041+
"drem\t$rd, $rs, $imm">,
1042+
ISA_MIPS3_NOT_32R6_64R6;
1043+
def DURemMacro : MipsAsmPseudoInst<(outs GPR64Opnd:$rd),
1044+
(ins GPR64Opnd:$rs, GPR64Opnd:$rt),
1045+
"dremu\t$rd, $rs, $rt">,
1046+
ISA_MIPS3_NOT_32R6_64R6;
1047+
def DURemIMacro : MipsAsmPseudoInst<(outs GPR64Opnd:$rd),
1048+
(ins GPR64Opnd:$rs, simm32_relaxed:$imm),
1049+
"dremu\t$rd, $rs, $imm">,
1050+
ISA_MIPS3_NOT_32R6_64R6;
1051+
def : MipsInstAlias<"drem $rt, $rs", (DSRemMacro GPR64Opnd:$rt,
1052+
GPR64Opnd:$rt,
1053+
GPR64Opnd:$rs), 0>,
1054+
ISA_MIPS3_NOT_32R6_64R6;
1055+
def : MipsInstAlias<"drem $rd, $imm", (DSRemIMacro GPR64Opnd:$rd,
1056+
GPR64Opnd:$rd,
1057+
simm32_relaxed:$imm), 0>,
1058+
ISA_MIPS3_NOT_32R6_64R6;
1059+
def : MipsInstAlias<"dremu $rt, $rs", (DURemMacro GPR64Opnd:$rt,
1060+
GPR64Opnd:$rt,
1061+
GPR64Opnd:$rs), 0>,
1062+
ISA_MIPS3_NOT_32R6_64R6;
1063+
def : MipsInstAlias<"dremu $rd, $imm", (DURemIMacro GPR64Opnd:$rd,
1064+
GPR64Opnd:$rd,
1065+
simm32_relaxed:$imm), 0>,
1066+
ISA_MIPS3_NOT_32R6_64R6;
10351067
}
10361068

10371069
def NORImm64 : NORIMM_DESC_BASE<GPR64Opnd, imm64>, GPR_64;

lib/Target/Mips/MipsInstrInfo.td

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2950,6 +2950,36 @@ def : MipsInstAlias<"divu $rd, $imm", (UDivIMacro GPR32Opnd:$rd, GPR32Opnd:$rd,
29502950
simm32:$imm), 0>,
29512951
ISA_MIPS1_NOT_32R6_64R6;
29522952

2953+
def SRemMacro : MipsAsmPseudoInst<(outs GPR32Opnd:$rd),
2954+
(ins GPR32Opnd:$rs, GPR32Opnd:$rt),
2955+
"rem\t$rd, $rs, $rt">,
2956+
ISA_MIPS1_NOT_32R6_64R6;
2957+
def SRemIMacro : MipsAsmPseudoInst<(outs GPR32Opnd:$rd),
2958+
(ins GPR32Opnd:$rs, simm32_relaxed:$imm),
2959+
"rem\t$rd, $rs, $imm">,
2960+
ISA_MIPS1_NOT_32R6_64R6;
2961+
def URemMacro : MipsAsmPseudoInst<(outs GPR32Opnd:$rd),
2962+
(ins GPR32Opnd:$rs, GPR32Opnd:$rt),
2963+
"remu\t$rd, $rs, $rt">,
2964+
ISA_MIPS1_NOT_32R6_64R6;
2965+
def URemIMacro : MipsAsmPseudoInst<(outs GPR32Opnd:$rd),
2966+
(ins GPR32Opnd:$rs, simm32_relaxed:$imm),
2967+
"remu\t$rd, $rs, $imm">,
2968+
ISA_MIPS1_NOT_32R6_64R6;
2969+
2970+
def : MipsInstAlias<"rem $rt, $rs", (SRemMacro GPR32Opnd:$rt, GPR32Opnd:$rt,
2971+
GPR32Opnd:$rs), 0>,
2972+
ISA_MIPS1_NOT_32R6_64R6;
2973+
def : MipsInstAlias<"rem $rd, $imm", (SRemIMacro GPR32Opnd:$rd, GPR32Opnd:$rd,
2974+
simm32_relaxed:$imm), 0>,
2975+
ISA_MIPS1_NOT_32R6_64R6;
2976+
def : MipsInstAlias<"remu $rt, $rs", (URemMacro GPR32Opnd:$rt, GPR32Opnd:$rt,
2977+
GPR32Opnd:$rs), 0>,
2978+
ISA_MIPS1_NOT_32R6_64R6;
2979+
def : MipsInstAlias<"remu $rd, $imm", (URemIMacro GPR32Opnd:$rd, GPR32Opnd:$rd,
2980+
simm32_relaxed:$imm), 0>,
2981+
ISA_MIPS1_NOT_32R6_64R6;
2982+
29532983
def Ulh : MipsAsmPseudoInst<(outs GPR32Opnd:$rt), (ins mem:$addr),
29542984
"ulh\t$rt, $addr">; //, ISA_MIPS1_NOT_32R6_64R6;
29552985

test/MC/Mips/macro-ddiv.s

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
# CHECK-NOTRAP: dsll32 $1, $1, 31 # encoding: [0x00,0x01,0x0f,0xfc]
1717
# CHECK-NOTRAP: bne $25, $1, .Ltmp1 # encoding: [0x17,0x21,A,A]
1818
# CHECK-NOTRAP: # fixup A - offset: 0, value: .Ltmp1-4, kind: fixup_Mips_PC16
19-
# CHECK-NOTRAP: sll $zero, $zero, 0 # encoding: [0x00,0x00,0x00,0x00]
19+
# CHECK-NOTRAP: nop # encoding: [0x00,0x00,0x00,0x00]
2020
# CHECK-NOTRAP: break 6 # encoding: [0x00,0x06,0x00,0x0d]
2121
# CHECK-NOTRAP: .Ltmp1
2222
# CHECK-NOTRAP: mflo $25 # encoding: [0x00,0x00,0xc8,0x12]
@@ -45,7 +45,7 @@
4545
# CHECK-NOTRAP: dsll32 $1, $1, 31 # encoding: [0x00,0x01,0x0f,0xfc]
4646
# CHECK-NOTRAP: bne $24, $1, .Ltmp3 # encoding: [0x17,0x01,A,A]
4747
# CHECK-NOTRAP: # fixup A - offset: 0, value: .Ltmp3-4, kind: fixup_Mips_PC16
48-
# CHECK-NOTRAP: sll $zero, $zero, 0 # encoding: [0x00,0x00,0x00,0x00]
48+
# CHECK-NOTRAP: nop # encoding: [0x00,0x00,0x00,0x00]
4949
# CHECK-NOTRAP: break 6 # encoding: [0x00,0x06,0x00,0x0d]
5050
# CHECK-NOTRAP: .Ltmp3
5151
# CHECK-NOTRAP: mflo $24 # encoding: [0x00,0x00,0xc0,0x12]
@@ -211,7 +211,7 @@
211211
# CHECK-NOTRAP: dsll32 $1, $1, 31 # encoding: [0x00,0x01,0x0f,0xfc]
212212
# CHECK-NOTRAP: bne $5, $1, .Ltmp7 # encoding: [0x14,0xa1,A,A]
213213
# CHECK-NOTRAP: # fixup A - offset: 0, value: .Ltmp7-4, kind: fixup_Mips_PC16
214-
# CHECK-NOTRAP: sll $zero, $zero, 0 # encoding: [0x00,0x00,0x00,0x00]
214+
# CHECK-NOTRAP: nop # encoding: [0x00,0x00,0x00,0x00]
215215
# CHECK-NOTRAP: break 6 # encoding: [0x00,0x06,0x00,0x0d]
216216
# CHECK-NOTRAP: .Ltmp7:
217217
# CHECK-NOTRAP: mflo $4 # encoding: [0x00,0x00,0x20,0x12]

0 commit comments

Comments
 (0)