From c50ab6d6aa2f55aa702ce4c8fac61fda7ae1331b Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Tue, 19 Nov 2013 13:24:15 -0800 Subject: [PATCH] armjit: Fix divu when divisor is a constant 1. Fixes #4539 and #4520. --- Common/ArmEmitter.cpp | 20 ++++++++++++++++---- Core/MIPS/ARM/ArmCompALU.cpp | 6 +++++- 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/Common/ArmEmitter.cpp b/Common/ArmEmitter.cpp index 4cffba4226..074aec2c8b 100644 --- a/Common/ArmEmitter.cpp +++ b/Common/ArmEmitter.cpp @@ -735,12 +735,24 @@ void ARMXEmitter::LSL (ARMReg dest, ARMReg src, Operand2 op2) { WriteShiftedData void ARMXEmitter::LSLS(ARMReg dest, ARMReg src, Operand2 op2) { WriteShiftedDataOp(0, true, dest, src, op2);} void ARMXEmitter::LSL (ARMReg dest, ARMReg src, ARMReg op2) { WriteShiftedDataOp(1, false, dest, src, op2);} void ARMXEmitter::LSLS(ARMReg dest, ARMReg src, ARMReg op2) { WriteShiftedDataOp(1, true, dest, src, op2);} -void ARMXEmitter::LSR (ARMReg dest, ARMReg src, Operand2 op2) { WriteShiftedDataOp(2, false, dest, src, op2);} -void ARMXEmitter::LSRS(ARMReg dest, ARMReg src, Operand2 op2) { WriteShiftedDataOp(2, true, dest, src, op2);} +void ARMXEmitter::LSR (ARMReg dest, ARMReg src, Operand2 op2) { + _assert_msg_(JIT, op2.GetType() != TYPE_IMM || op2.Imm5() != 0, "LSR must have a non-zero shift (use LSL.)"); + WriteShiftedDataOp(2, false, dest, src, op2); +} +void ARMXEmitter::LSRS(ARMReg dest, ARMReg src, Operand2 op2) { + _assert_msg_(JIT, op2.GetType() != TYPE_IMM || op2.Imm5() != 0, "LSRS must have a non-zero shift (use LSLS.)"); + WriteShiftedDataOp(2, true, dest, src, op2); +} void ARMXEmitter::LSR (ARMReg dest, ARMReg src, ARMReg op2) { WriteShiftedDataOp(3, false, dest, src, op2);} void ARMXEmitter::LSRS(ARMReg dest, ARMReg src, ARMReg op2) { WriteShiftedDataOp(3, true, dest, src, op2);} -void ARMXEmitter::ASR (ARMReg dest, ARMReg src, Operand2 op2) { WriteShiftedDataOp(4, false, dest, src, op2);} -void ARMXEmitter::ASRS(ARMReg dest, ARMReg src, Operand2 op2) { WriteShiftedDataOp(4, true, dest, src, op2);} +void ARMXEmitter::ASR (ARMReg dest, ARMReg src, Operand2 op2) { + _assert_msg_(JIT, op2.GetType() != TYPE_IMM || op2.Imm5() != 0, "ASR must have a non-zero shift (use LSL.)"); + WriteShiftedDataOp(4, false, dest, src, op2); +} +void ARMXEmitter::ASRS(ARMReg dest, ARMReg src, Operand2 op2) { + _assert_msg_(JIT, op2.GetType() != TYPE_IMM || op2.Imm5() != 0, "ASRS must have a non-zero shift (use LSLS.)"); + WriteShiftedDataOp(4, true, dest, src, op2); +} void ARMXEmitter::ASR (ARMReg dest, ARMReg src, ARMReg op2) { WriteShiftedDataOp(5, false, dest, src, op2);} void ARMXEmitter::ASRS(ARMReg dest, ARMReg src, ARMReg op2) { WriteShiftedDataOp(5, true, dest, src, op2);} diff --git a/Core/MIPS/ARM/ArmCompALU.cpp b/Core/MIPS/ARM/ArmCompALU.cpp index 30c3b3ffbb..aec546f944 100644 --- a/Core/MIPS/ARM/ArmCompALU.cpp +++ b/Core/MIPS/ARM/ArmCompALU.cpp @@ -763,7 +763,11 @@ namespace MIPSComp denominator >>= 1; } // The shift value is one too much for the divide by the same value. - LSR(gpr.R(MIPS_REG_LO), gpr.R(rs), shift - 1); + if (shift > 1) { + LSR(gpr.R(MIPS_REG_LO), gpr.R(rs), shift - 1); + } else { + MOV(gpr.R(MIPS_REG_LO), gpr.R(rs)); + } } } else if (cpu_info.bIDIVa) { // TODO: Does this handle INT_MAX, 0, etc. correctly?