aboutsummaryrefslogtreecommitdiff
path: root/lib/Target/Mips
diff options
context:
space:
mode:
authorPetar Jovanovic <petar.jovanovic@rt-rk.com>2013-10-11 02:58:15 +0200
committerPetar Jovanovic <petar.jovanovic@rt-rk.com>2013-10-11 02:58:15 +0200
commit1b783c13dd573e2611f7fde92e3e66475bdb8918 (patch)
tree66dc28910692ae2a59fc47b758cb477de3f20e55 /lib/Target/Mips
parent0588a8b5d075090adb3bd16fafd16a43d6125784 (diff)
Apply upstream: [mips] Trap on integer division by zero.
Cherry-pick r182306 from upstream. Original commit message: Author: Akira Hatanaka <ahatanaka@mips.com> Date: Mon May 20 18:07:43 2013 +0000 [mips] Trap on integer division by zero. By default, a teq instruction is inserted after integer divide. No divide-by-zero checks are performed if option "-mnocheck-zero-division" is used. TBR= mseaborn@chromium.org, dschuff@chromium.org BUG= missing trap for MIPS Review URL: https://codereview.chromium.org/26846007
Diffstat (limited to 'lib/Target/Mips')
-rw-r--r--lib/Target/Mips/Mips64InstrInfo.td4
-rw-r--r--lib/Target/Mips/MipsISelLowering.cpp31
-rw-r--r--lib/Target/Mips/MipsInstrFormats.td14
-rw-r--r--lib/Target/Mips/MipsInstrInfo.td15
4 files changed, 59 insertions, 5 deletions
diff --git a/lib/Target/Mips/Mips64InstrInfo.td b/lib/Target/Mips/Mips64InstrInfo.td
index fc533fb03f..ebc4c90101 100644
--- a/lib/Target/Mips/Mips64InstrInfo.td
+++ b/lib/Target/Mips/Mips64InstrInfo.td
@@ -192,9 +192,9 @@ def PseudoDMULTu : MultDivPseudo<DMULTu, ACRegs128, CPU64RegsOpnd, MipsMultu,
def DSDIV : Div<"ddiv", IIIdiv, CPU64RegsOpnd, [HI64, LO64]>, MULT_FM<0, 0x1e>;
def DUDIV : Div<"ddivu", IIIdiv, CPU64RegsOpnd, [HI64, LO64]>, MULT_FM<0, 0x1f>;
def PseudoDSDIV : MultDivPseudo<DSDIV, ACRegs128, CPU64RegsOpnd, MipsDivRem,
- IIIdiv, 0>;
+ IIIdiv, 0, 1, 1>;
def PseudoDUDIV : MultDivPseudo<DUDIV, ACRegs128, CPU64RegsOpnd, MipsDivRemU,
- IIIdiv, 0>;
+ IIIdiv, 0, 1, 1>;
def MTHI64 : MoveToLOHI<"mthi", CPU64Regs, [HI64]>, MTLO_FM<0x11>;
def MTLO64 : MoveToLOHI<"mtlo", CPU64Regs, [LO64]>, MTLO_FM<0x13>;
diff --git a/lib/Target/Mips/MipsISelLowering.cpp b/lib/Target/Mips/MipsISelLowering.cpp
index 69f060965c..5b898af6d6 100644
--- a/lib/Target/Mips/MipsISelLowering.cpp
+++ b/lib/Target/Mips/MipsISelLowering.cpp
@@ -43,6 +43,11 @@ static cl::opt<bool>
LargeGOT("mxgot", cl::Hidden,
cl::desc("MIPS: Enable GOT larger than 64k."), cl::init(false));
+static cl::opt<bool>
+NoZeroDivCheck("mnocheck-zero-division", cl::Hidden,
+ cl::desc("MIPS: Don't trap on integer division by zero."),
+ cl::init(false));
+
static const uint16_t O32IntRegs[4] = {
Mips::A0, Mips::A1, Mips::A2, Mips::A3
};
@@ -784,6 +789,26 @@ addLiveIn(MachineFunction &MF, unsigned PReg, const TargetRegisterClass *RC)
return VReg;
}
+static MachineBasicBlock *expandPseudoDIV(MachineInstr *MI,
+ MachineBasicBlock &MBB,
+ const TargetInstrInfo &TII,
+ bool Is64Bit) {
+ if (NoZeroDivCheck)
+ return &MBB;
+
+ // Insert instruction "teq $divisor_reg, $zero, 7".
+ MachineBasicBlock::iterator I(MI);
+ MachineInstrBuilder MIB;
+ MIB = BuildMI(MBB, llvm::next(I), MI->getDebugLoc(), TII.get(Mips::TEQ))
+ .addOperand(MI->getOperand(2)).addReg(Mips::ZERO).addImm(7);
+
+ // Use the 32-bit sub-register if this is a 64-bit division.
+ if (Is64Bit)
+ MIB->getOperand(0).setSubReg(Mips::sub_32);
+
+ return &MBB;
+}
+
MachineBasicBlock *
MipsTargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI,
MachineBasicBlock *BB) const {
@@ -893,6 +918,12 @@ MipsTargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI,
case Mips::ATOMIC_CMP_SWAP_I64:
case Mips::ATOMIC_CMP_SWAP_I64_P8:
return emitAtomicCmpSwap(MI, BB, 8);
+ case Mips::PseudoSDIV:
+ case Mips::PseudoUDIV:
+ return expandPseudoDIV(MI, *BB, *getTargetMachine().getInstrInfo(), false);
+ case Mips::PseudoDSDIV:
+ case Mips::PseudoDUDIV:
+ return expandPseudoDIV(MI, *BB, *getTargetMachine().getInstrInfo(), true);
}
}
diff --git a/lib/Target/Mips/MipsInstrFormats.td b/lib/Target/Mips/MipsInstrFormats.td
index ea07372221..14cfcf96d3 100644
--- a/lib/Target/Mips/MipsInstrFormats.td
+++ b/lib/Target/Mips/MipsInstrFormats.td
@@ -476,6 +476,20 @@ class RDHWR_FM {
let Inst{5-0} = 0x3b;
}
+class TEQ_FM<bits<6> funct> {
+ bits<5> rs;
+ bits<5> rt;
+ bits<10> code_;
+
+ bits<32> Inst;
+
+ let Inst{31-26} = 0;
+ let Inst{25-21} = rs;
+ let Inst{20-16} = rt;
+ let Inst{15-6} = code_;
+ let Inst{5-0} = funct;
+}
+
//===----------------------------------------------------------------------===//
//
// FLOATING POINT INSTRUCTION FORMATS
diff --git a/lib/Target/Mips/MipsInstrInfo.td b/lib/Target/Mips/MipsInstrInfo.td
index 10d11dd835..849544cf22 100644
--- a/lib/Target/Mips/MipsInstrInfo.td
+++ b/lib/Target/Mips/MipsInstrInfo.td
@@ -640,6 +640,11 @@ class SYNC_FT :
InstSE<(outs), (ins i32imm:$stype), "sync $stype", [(MipsSync imm:$stype)],
NoItinerary, FrmOther>;
+let hasSideEffects = 1 in
+class TEQ_FT<string opstr, RegisterOperand RO> :
+ InstSE<(outs), (ins RO:$rs, RO:$rt, uimm16:$code_),
+ !strconcat(opstr, "\t$rs, $rt, $code_"), [], NoItinerary, FrmI>;
+
// Mul, Div
class Mult<string opstr, InstrItinClass itin, RegisterOperand RO,
list<Register> DefRegs> :
@@ -654,12 +659,14 @@ class Mult<string opstr, InstrItinClass itin, RegisterOperand RO,
// operands.
class MultDivPseudo<Instruction RealInst, RegisterClass R0, RegisterOperand R1,
SDPatternOperator OpNode, InstrItinClass Itin,
- bit IsComm = 1, bit HasSideEffects = 0> :
+ bit IsComm = 1, bit HasSideEffects = 0,
+ bit UsesCustomInserter = 0> :
PseudoSE<(outs R0:$ac), (ins R1:$rs, R1:$rt),
[(set R0:$ac, (OpNode R1:$rs, R1:$rt))], Itin>,
PseudoInstExpansion<(RealInst R1:$rs, R1:$rt)> {
let isCommutable = IsComm;
let hasSideEffects = HasSideEffects;
+ let usesCustomInserter = UsesCustomInserter;
}
// Pseudo multiply add/sub instruction with explicit accumulator register
@@ -957,6 +964,7 @@ defm SWL : StoreLeftRightM<"swl", MipsSWL, CPURegs>, LW_FM<0x2a>;
defm SWR : StoreLeftRightM<"swr", MipsSWR, CPURegs>, LW_FM<0x2e>;
def SYNC : SYNC_FT, SYNC_FM;
+def TEQ : TEQ_FT<"teq", CPURegsOpnd>, TEQ_FM<0x34>;
/// Load-linked, Store-conditional
let Predicates = [NotN64, HasStdEnc] in {
@@ -1023,9 +1031,10 @@ def PseudoMULT : MultDivPseudo<MULT, ACRegs, CPURegsOpnd, MipsMult, IIImul>;
def PseudoMULTu : MultDivPseudo<MULTu, ACRegs, CPURegsOpnd, MipsMultu, IIImul>;
def SDIV : Div<"div", IIIdiv, CPURegsOpnd, [HI, LO]>, MULT_FM<0, 0x1a>;
def UDIV : Div<"divu", IIIdiv, CPURegsOpnd, [HI, LO]>, MULT_FM<0, 0x1b>;
-def PseudoSDIV : MultDivPseudo<SDIV, ACRegs, CPURegsOpnd, MipsDivRem, IIIdiv, 0>;
+def PseudoSDIV : MultDivPseudo<SDIV, ACRegs, CPURegsOpnd, MipsDivRem, IIIdiv,
+ 0, 1, 1>;
def PseudoUDIV : MultDivPseudo<UDIV, ACRegs, CPURegsOpnd, MipsDivRemU, IIIdiv,
- 0>;
+ 0, 1, 1>;
def MTHI : MoveToLOHI<"mthi", CPURegs, [HI]>, MTLO_FM<0x11>;
def MTLO : MoveToLOHI<"mtlo", CPURegs, [LO]>, MTLO_FM<0x13>;