diff options
Diffstat (limited to 'llvm/lib')
| -rw-r--r-- | llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp | 55 | ||||
| -rw-r--r-- | llvm/lib/Target/Mips/MipsInstrInfo.td | 28 |
2 files changed, 80 insertions, 3 deletions
diff --git a/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp b/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp index f40d33c8eaa..504a4983036 100644 --- a/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp +++ b/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp @@ -2252,15 +2252,19 @@ MipsAsmParser::tryExpandInstruction(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, case Mips::BGTULImmMacro: 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::DSDivMacro: + case Mips::DSDivIMacro: return expandDiv(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::DUDivMacro: + case Mips::DUDivIMacro: return expandDiv(Inst, IDLoc, Out, STI, true, false) ? MER_Fail : MER_Success; case Mips::PseudoTRUNC_W_S: @@ -3282,22 +3286,67 @@ bool MipsAsmParser::expandDiv(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, assert(RsRegOp.isReg() && "expected register operand kind"); unsigned RsReg = RsRegOp.getReg(); - const MCOperand &RtRegOp = Inst.getOperand(2); - assert(RtRegOp.isReg() && "expected register operand kind"); - unsigned RtReg = RtRegOp.getReg(); + unsigned RtReg; + int64_t ImmValue; + + const MCOperand &RtOp = Inst.getOperand(2); + assert((RtOp.isReg() || RtOp.isImm()) && + "expected register or immediate operand kind"); + if (RtOp.isReg()) + RtReg = RtOp.getReg(); + else + ImmValue = RtOp.getImm(); + unsigned DivOp; unsigned ZeroReg; + unsigned SubOp; if (IsMips64) { DivOp = Signed ? Mips::DSDIV : Mips::DUDIV; ZeroReg = Mips::ZERO_64; + SubOp = Mips::DSUB; } else { DivOp = Signed ? Mips::SDIV : Mips::UDIV; ZeroReg = Mips::ZERO; + SubOp = Mips::SUB; } bool UseTraps = useTraps(); + if (RtOp.isImm()) { + unsigned ATReg = getATReg(IDLoc); + if (!ATReg) + return true; + + if (ImmValue == 0) { + if (RsReg == Mips::ZERO || RsReg == Mips::ZERO_64) + Warning(IDLoc, "dividing zero by zero"); + else + Warning(IDLoc, "division by zero"); + if (UseTraps) + TOut.emitRRI(Mips::TEQ, ZeroReg, ZeroReg, 0x7, IDLoc, STI); + else + TOut.emitII(Mips::BREAK, 0x7, 0, IDLoc, STI); + return false; + } + + if (ImmValue == 1) { + TOut.emitRRR(Mips::ADDu, RdReg, RsReg, Mips::ZERO, IDLoc, STI); + return false; + } else if (Signed && ImmValue == -1) { + TOut.emitRRR(SubOp, RdReg, Mips::ZERO, RsReg, IDLoc, STI); + return false; + } else { + if (loadImmediate(ImmValue, ATReg, Mips::NoRegister, isInt<32>(ImmValue), + false, Inst.getLoc(), Out, STI)) + return true; + TOut.emitRR(DivOp, RsReg, ATReg, IDLoc, STI); + TOut.emitR(Mips::MFLO, RdReg, IDLoc, STI); + return false; + } + return true; + } + if (RsReg == Mips::ZERO || RsReg == Mips::ZERO_64) { if (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64) Warning(IDLoc, "dividing zero by zero"); diff --git a/llvm/lib/Target/Mips/MipsInstrInfo.td b/llvm/lib/Target/Mips/MipsInstrInfo.td index 883dac3549f..fc2586761f4 100644 --- a/llvm/lib/Target/Mips/MipsInstrInfo.td +++ b/llvm/lib/Target/Mips/MipsInstrInfo.td @@ -2561,30 +2561,58 @@ def SDivMacro : MipsAsmPseudoInst<(outs GPR32Opnd:$rd), (ins GPR32Opnd:$rs, GPR32Opnd:$rt), "div\t$rd, $rs, $rt">, ISA_MIPS1_NOT_32R6_64R6; +def SDivIMacro : MipsAsmPseudoInst<(outs GPR32Opnd:$rd), + (ins GPR32Opnd:$rs, simm32:$imm), + "div\t$rd, $rs, $imm">, + ISA_MIPS1_NOT_32R6_64R6; def UDivMacro : MipsAsmPseudoInst<(outs GPR32Opnd:$rd), (ins GPR32Opnd:$rs, GPR32Opnd:$rt), "divu\t$rd, $rs, $rt">, ISA_MIPS1_NOT_32R6_64R6; +def UDivIMacro : MipsAsmPseudoInst<(outs GPR32Opnd:$rd), + (ins GPR32Opnd:$rs, simm32:$imm), + "divu\t$rd, $rs, $imm">, + ISA_MIPS1_NOT_32R6_64R6; def : MipsInstAlias<"div $rt, $rs", (SDivMacro GPR32Opnd:$rt, GPR32Opnd:$rt, GPR32Opnd:$rs), 0>, ISA_MIPS1_NOT_32R6_64R6; +def : MipsInstAlias<"div $rd, $imm", (SDivIMacro GPR32Opnd:$rd, GPR32Opnd:$rd, + simm32:$imm), 0>, + ISA_MIPS1_NOT_32R6_64R6; def : MipsInstAlias<"divu $rt, $rs", (UDivMacro GPR32Opnd:$rt, GPR32Opnd:$rt, GPR32Opnd:$rs), 0>, ISA_MIPS1_NOT_32R6_64R6; +def : MipsInstAlias<"divu $rd, $imm", (UDivIMacro GPR32Opnd:$rd, GPR32Opnd:$rd, + simm32:$imm), 0>, + ISA_MIPS1_NOT_32R6_64R6; def DSDivMacro : MipsAsmPseudoInst<(outs GPR32Opnd:$rd), (ins GPR32Opnd:$rs, GPR32Opnd:$rt), "ddiv\t$rd, $rs, $rt">, ISA_MIPS64_NOT_64R6; +def DSDivIMacro : MipsAsmPseudoInst<(outs GPR32Opnd:$rd), + (ins GPR32Opnd:$rs, imm64:$imm), + "ddiv\t$rd, $rs, $imm">, + ISA_MIPS64_NOT_64R6; def DUDivMacro : MipsAsmPseudoInst<(outs GPR32Opnd:$rd), (ins GPR32Opnd:$rs, GPR32Opnd:$rt), "ddivu\t$rd, $rs, $rt">, ISA_MIPS64_NOT_64R6; +def DUDivIMacro : MipsAsmPseudoInst<(outs GPR32Opnd:$rd), + (ins GPR32Opnd:$rs, imm64:$imm), + "ddivu\t$rd, $rs, $imm">, + ISA_MIPS64_NOT_64R6; def : MipsInstAlias<"ddiv $rt, $rs", (DSDivMacro GPR32Opnd:$rt, GPR32Opnd:$rt, GPR32Opnd:$rs), 0>, ISA_MIPS64_NOT_64R6; +def : MipsInstAlias<"ddiv $rd, $imm", (DSDivIMacro GPR32Opnd:$rd, GPR32Opnd:$rd, + imm64:$imm), 0>, + ISA_MIPS64_NOT_64R6; def : MipsInstAlias<"ddivu $rt, $rs", (DUDivMacro GPR32Opnd:$rt, GPR32Opnd:$rt, GPR32Opnd:$rs), 0>, ISA_MIPS64_NOT_64R6; +def : MipsInstAlias<"ddivu $rd, $imm", (DUDivIMacro GPR32Opnd:$rd, + GPR32Opnd:$rd, imm64:$imm), + 0>, ISA_MIPS64_NOT_64R6; def Ulh : MipsAsmPseudoInst<(outs GPR32Opnd:$rt), (ins mem:$addr), "ulh\t$rt, $addr">; //, ISA_MIPS1_NOT_32R6_64R6; |

