diff --git a/Source/Android/Bridge/jniBridgeSettings.cpp b/Source/Android/Bridge/jniBridgeSettings.cpp index 71e12a4d9..64dfebe9a 100644 --- a/Source/Android/Bridge/jniBridgeSettings.cpp +++ b/Source/Android/Bridge/jniBridgeSettings.cpp @@ -250,7 +250,6 @@ CJniBridegSettings::CJniBridegSettings() ADD_SETTING(Debugger_BreakOnAddressError); ADD_SETTING(Debugger_StepOnBreakOpCode); ADD_SETTING(Debugger_ShowPifErrors); - ADD_SETTING(Debugger_ShowDivByZero); ADD_SETTING(Debugger_RecordRecompilerAsm); ADD_SETTING(Debugger_DisableGameFixes); ADD_SETTING(Debugger_AppLogLevel); diff --git a/Source/Project64-core/N64System/Interpreter/InterpreterOps.cpp b/Source/Project64-core/N64System/Interpreter/InterpreterOps.cpp index d1e5ff3d7..0284de802 100644 --- a/Source/Project64-core/N64System/Interpreter/InterpreterOps.cpp +++ b/Source/Project64-core/N64System/Interpreter/InterpreterOps.cpp @@ -1409,17 +1409,21 @@ void R4300iOp::SPECIAL_DIV() { if (_GPR[m_Opcode.rt].W[0] != 0) { - _RegLO->DW = _GPR[m_Opcode.rs].W[0] / _GPR[m_Opcode.rt].W[0]; - _RegHI->DW = _GPR[m_Opcode.rs].W[0] % _GPR[m_Opcode.rt].W[0]; + if (_GPR[m_Opcode.rs].W[0] != 0x80000000 || _GPR[m_Opcode.rt].W[0] != -1) + { + _RegLO->DW = _GPR[m_Opcode.rs].W[0] / _GPR[m_Opcode.rt].W[0]; + _RegHI->DW = _GPR[m_Opcode.rs].W[0] % _GPR[m_Opcode.rt].W[0]; + } + else + { + _RegLO->DW = 0xFFFFFFFF80000000; + _RegHI->DW = 0x0000000000000000; + } } else { - if (bShowDivByZero()) - { - g_Notify->DisplayError("DIV by 0"); - } - _RegLO->DW = 0; - _RegHI->DW = 0; + _RegLO->DW = _GPR[m_Opcode.rs].W[0] < 0 ? 0x0000000000000001 : 0xFFFFFFFFFFFFFFFF; + _RegHI->DW = _GPR[m_Opcode.rs].W[0]; } } @@ -1432,12 +1436,8 @@ void R4300iOp::SPECIAL_DIVU() } else { - if (bShowDivByZero()) - { - g_Notify->DisplayError("DIVU by 0"); - } - _RegLO->DW = 0; - _RegHI->DW = 0; + _RegLO->DW = 0xFFFFFFFFFFFFFFFF; + _RegHI->DW = _GPR[m_Opcode.rs].W[0]; } } @@ -1478,10 +1478,8 @@ void R4300iOp::SPECIAL_DDIV() } else { - if (HaveDebugger()) - { - g_Notify->DisplayError("DDIV by 0"); - } + _RegLO->DW = _GPR[m_Opcode.rs].DW < 0 ? 0x0000000000000001 : 0xFFFFFFFFFFFFFFFF; + _RegHI->DW = _GPR[m_Opcode.rs].DW; } } @@ -1494,10 +1492,8 @@ void R4300iOp::SPECIAL_DDIVU() } else { - if (HaveDebugger()) - { - g_Notify->DisplayError("DDIVU by 0"); - } + _RegLO->DW = 0xFFFFFFFFFFFFFFFF; + _RegHI->DW = _GPR[m_Opcode.rs].DW; } } diff --git a/Source/Project64-core/N64System/Recompiler/ExitInfo.h b/Source/Project64-core/N64System/Recompiler/ExitInfo.h index 74e62b495..d93070a8d 100644 --- a/Source/Project64-core/N64System/Recompiler/ExitInfo.h +++ b/Source/Project64-core/N64System/Recompiler/ExitInfo.h @@ -16,7 +16,6 @@ struct CExitInfo DoSysCall = 4, TLBReadMiss = 5, TLBWriteMiss = 6, - DivByZero = 7, ExitResetRecompCode = 8, }; diff --git a/Source/Project64-core/N64System/Recompiler/x86/x86RecompilerOps.cpp b/Source/Project64-core/N64System/Recompiler/x86/x86RecompilerOps.cpp index 85ba79b10..80638696f 100644 --- a/Source/Project64-core/N64System/Recompiler/x86/x86RecompilerOps.cpp +++ b/Source/Project64-core/N64System/Recompiler/x86/x86RecompilerOps.cpp @@ -4773,129 +4773,308 @@ void CX86RecompilerOps::SPECIAL_MULTU() void CX86RecompilerOps::SPECIAL_DIV() { - if (IsConst(m_Opcode.rt)) + CX86Ops::x86Reg RegRs = CX86Ops::x86_Unknown, RegRsHi = CX86Ops::x86_Unknown, DivReg = CX86Ops::x86_Unknown; + uint8_t * JumpNotDiv0 = nullptr; + uint8_t * JumpEnd = nullptr; + uint8_t * JumpEnd2 = nullptr; + + if (IsConst(m_Opcode.rt) && GetMipsRegLo(m_Opcode.rt) == 0) { - if (GetMipsRegLo(m_Opcode.rt) == 0) + if (IsConst(m_Opcode.rs)) { - m_Assembler.MoveConstToVariable(0, &_RegLO->UW[0], "_RegLO->UW[0]"); - m_Assembler.MoveConstToVariable(0, &_RegLO->UW[1], "_RegLO->UW[1]"); - m_Assembler.MoveConstToVariable(0, &_RegHI->UW[0], "_RegHI->UW[0]"); - m_Assembler.MoveConstToVariable(0, &_RegHI->UW[1], "_RegHI->UW[1]"); - return; - } - } - else - { - if (IsMapped(m_Opcode.rt)) - { - m_Assembler.CompConstToX86reg(GetMipsRegMapLo(m_Opcode.rt), 0); + m_Assembler.MoveConstToVariable(GetMipsRegLo_S(m_Opcode.rs) < 0 ? 0x00000001 : 0xFFFFFFFF, &_RegLO->UW[0], "_RegLO->UW[0]"); + m_Assembler.MoveConstToVariable(GetMipsRegLo_S(m_Opcode.rs) < 0 ? 0x00000000 : 0xFFFFFFFF, &_RegLO->UW[1], "_RegLO->UW[1]"); + m_Assembler.MoveConstToVariable(GetMipsRegLo(m_Opcode.rs), &_RegHI->UW[0], "_RegHI->UW[0]"); + m_Assembler.MoveConstToVariable(GetMipsRegLo_S(m_Opcode.rs) < 0 ? 0xFFFFFFFF : 0x00000000, &_RegHI->UW[1], "_RegHI->UW[1]"); } else { - m_Assembler.CompConstToVariable(0, &_GPR[m_Opcode.rt].W[0], CRegName::GPR_Lo[m_Opcode.rt]); + CX86Ops::x86Reg Reg = IsMapped(m_Opcode.rs) ? GetMipsRegMapLo(m_Opcode.rs) : Map_TempReg(CX86Ops::x86_Any, m_Opcode.rs, false); + m_Assembler.CompConstToX86reg(Reg, 0); + m_Assembler.JgeLabel8(stdstr_f("RsPositive_%08X", m_CompilePC).c_str(), 0); + uint8_t * JumpPositive = *g_RecompPos - 1; + m_Assembler.MoveConstToVariable(0x00000001, &_RegLO->UW[0], "_RegLO->UW[0]"); + m_Assembler.MoveConstToVariable(0x00000000, &_RegLO->UW[1], "_RegLO->UW[1]"); + m_Assembler.JmpLabel8(stdstr_f("LoSet_%08X", m_CompilePC).c_str(), 0); + uint8_t * JumpLoSet = *g_RecompPos - 1; + m_CodeBlock.Log(""); + m_CodeBlock.Log(" RsPositive_%08X:", m_CompilePC); + m_Assembler.SetJump8(JumpPositive, *g_RecompPos); + m_Assembler.MoveConstToVariable(0xFFFFFFFF, &_RegLO->UW[0], "_RegLO->UW[0]"); + m_Assembler.MoveConstToVariable(0xFFFFFFFF, &_RegLO->UW[1], "_RegLO->UW[1]"); + m_CodeBlock.Log(""); + m_CodeBlock.Log(" LoSet_%08X:", m_CompilePC); + m_Assembler.SetJump8(JumpLoSet, *g_RecompPos); + m_Assembler.MoveX86regToVariable(Reg, &_RegHI->UW[0], "_RegHI->UW[0]"); + if (IsMapped(m_Opcode.rs)) + { + Reg = Map_TempReg(CX86Ops::x86_Any, m_Opcode.rs, true); + } + else + { + m_Assembler.ShiftRightSignImmed(Reg, 31); + } + m_Assembler.MoveX86regToVariable(Reg, &_RegHI->UW[1], "_RegHI->UW[1]"); } - CompileExit(m_CompilePC, m_CompilePC, m_RegWorkingSet, CExitInfo::DivByZero, false, &CX86Ops::JeLabel32); + return; } - /* lo = (SD)rs / (SD)rt; - hi = (SD)rs % (SD)rt; */ - - m_RegWorkingSet.SetX86Protected(CX86Ops::x86_EDX, true); - Map_TempReg(CX86Ops::x86_EAX, m_Opcode.rs, false); - - // EDX is the signed portion to EAX - m_RegWorkingSet.SetX86Protected(CX86Ops::x86_EDX, false); - Map_TempReg(CX86Ops::x86_EDX, -1, false); - - m_Assembler.MoveX86RegToX86Reg(CX86Ops::x86_EAX, CX86Ops::x86_EDX); - m_Assembler.ShiftRightSignImmed(CX86Ops::x86_EDX, 31); - - if (IsMapped(m_Opcode.rt)) + else if (IsConst(m_Opcode.rt) && GetMipsRegLo(m_Opcode.rt) == -1) { - m_Assembler.idivX86reg(GetMipsRegMapLo(m_Opcode.rt)); + if (IsConst(m_Opcode.rs) && GetMipsRegLo(m_Opcode.rs) == 0x80000000) + { + m_Assembler.MoveConstToVariable(0x80000000, &_RegLO->UW[0], "_RegLO->UW[0]"); + m_Assembler.MoveConstToVariable(0xFFFFFFFF, &_RegLO->UW[1], "_RegLO->UW[1]"); + m_Assembler.MoveConstToVariable(0x00000000, &_RegHI->UW[0], "_RegHI->UW[0]"); + m_Assembler.MoveConstToVariable(0x00000000, &_RegHI->UW[1], "_RegHI->UW[1]"); + return; + } + + m_RegWorkingSet.SetX86Protected(CX86Ops::x86_EAX, true); + UnMap_X86reg(CX86Ops::x86_EDX); + m_RegWorkingSet.SetX86Protected(CX86Ops::x86_EAX, false); + m_RegWorkingSet.SetX86Protected(CX86Ops::x86_EDX, true); + UnMap_X86reg(CX86Ops::x86_EAX); + m_RegWorkingSet.SetX86Protected(CX86Ops::x86_EAX, true); + RegRs = IsMapped(m_Opcode.rs) ? GetMipsRegMapLo(m_Opcode.rs) : Map_TempReg(CX86Ops::x86_Any, m_Opcode.rs, false); + m_RegWorkingSet.SetX86Protected(RegRs, true); + RegRsHi = IsMapped(m_Opcode.rs) && Is64Bit(m_Opcode.rs) ? GetMipsRegMapHi(m_Opcode.rs) : Map_TempReg(CX86Ops::x86_Any, IsMapped(m_Opcode.rs) ? m_Opcode.rs : -1, true); + DivReg = IsMapped(m_Opcode.rt) ? GetMipsRegMapLo(m_Opcode.rt) : Map_TempReg(CX86Ops::x86_Any, m_Opcode.rt, false); + + if (!IsConst(m_Opcode.rs)) + { + m_Assembler.CompConstToX86reg(RegRs, 0x80000000); + m_Assembler.JneLabel8(stdstr_f("ValidDiv_%08X", m_CompilePC).c_str(), 0); + uint8_t * JumpValid = *g_RecompPos - 1; + m_Assembler.MoveConstToVariable(0x80000000, &_RegLO->UW[0], "_RegLO->UW[0]"); + m_Assembler.MoveConstToVariable(0xFFFFFFFF, &_RegLO->UW[1], "_RegLO->UW[1]"); + m_Assembler.MoveConstToVariable(0x00000000, &_RegHI->UW[0], "_RegHI->UW[0]"); + m_Assembler.MoveConstToVariable(0x00000000, &_RegHI->UW[1], "_RegHI->UW[1]"); + m_Assembler.JmpLabel8(stdstr_f("EndDiv_%08X", m_CompilePC).c_str(), 0); + JumpEnd = *g_RecompPos - 1; + m_CodeBlock.Log(""); + m_CodeBlock.Log(" ValidDiv_%08X:", m_CompilePC); + m_Assembler.SetJump8(JumpValid, *g_RecompPos); + } } else { - m_Assembler.idivX86reg(Map_TempReg(CX86Ops::x86_Any, m_Opcode.rt, false)); + m_RegWorkingSet.SetX86Protected(CX86Ops::x86_EAX, true); + UnMap_X86reg(CX86Ops::x86_EDX); + m_RegWorkingSet.SetX86Protected(CX86Ops::x86_EAX, false); + m_RegWorkingSet.SetX86Protected(CX86Ops::x86_EDX, true); + UnMap_X86reg(CX86Ops::x86_EAX); + m_RegWorkingSet.SetX86Protected(CX86Ops::x86_EAX, true); + RegRs = IsMapped(m_Opcode.rs) ? GetMipsRegMapLo(m_Opcode.rs) : Map_TempReg(CX86Ops::x86_Any, m_Opcode.rs, false); + m_RegWorkingSet.SetX86Protected(RegRs, true); + RegRsHi = IsMapped(m_Opcode.rs) && Is64Bit(m_Opcode.rs) ? GetMipsRegMapHi(m_Opcode.rs) : Map_TempReg(CX86Ops::x86_Any, IsMapped(m_Opcode.rs) ? m_Opcode.rs : -1, true); + DivReg = IsMapped(m_Opcode.rt) ? GetMipsRegMapLo(m_Opcode.rt) : Map_TempReg(CX86Ops::x86_Any, m_Opcode.rt, false); + + if (!IsConst(m_Opcode.rs)) + { + if (IsMapped(m_Opcode.rt)) + { + m_Assembler.CompConstToX86reg(GetMipsRegMapLo(m_Opcode.rt), 0); + } + else + { + m_Assembler.CompConstToVariable(0, &_GPR[m_Opcode.rt].W[0], CRegName::GPR_Lo[m_Opcode.rt]); + } + m_Assembler.JneLabel8(stdstr_f("NotDiv0_%08X", m_CompilePC).c_str(), 0); + JumpNotDiv0 = *g_RecompPos - 1; + + m_Assembler.CompConstToX86reg(RegRs, 0); + m_Assembler.JgeLabel8(stdstr_f("RsPositive_%08X", m_CompilePC).c_str(), 0); + uint8_t * JumpPositive = *g_RecompPos - 1; + m_Assembler.MoveConstToVariable(0x00000001, &_RegLO->UW[0], "_RegLO->UW[0]"); + m_Assembler.MoveConstToVariable(0x00000000, &_RegLO->UW[1], "_RegLO->UW[1]"); + m_Assembler.JmpLabel8(stdstr_f("LoSet_%08X", m_CompilePC).c_str(), 0); + uint8_t * JumpLoSet = *g_RecompPos - 1; + m_CodeBlock.Log(""); + m_CodeBlock.Log(" RsPositive_%08X:", m_CompilePC); + m_Assembler.SetJump8(JumpPositive, *g_RecompPos); + m_Assembler.MoveConstToVariable(0xFFFFFFFF, &_RegLO->UW[0], "_RegLO->UW[0]"); + m_Assembler.MoveConstToVariable(0xFFFFFFFF, &_RegLO->UW[1], "_RegLO->UW[1]"); + m_CodeBlock.Log(""); + m_CodeBlock.Log(" LoSet_%08X:", m_CompilePC); + m_Assembler.SetJump8(JumpLoSet, *g_RecompPos); + m_Assembler.MoveX86regToVariable(RegRs, &_RegHI->UW[0], "_RegHI->UW[0]"); + if (!IsMapped(m_Opcode.rs)) + { + m_Assembler.ShiftRightSignImmed(RegRsHi, 31); + } + m_Assembler.MoveX86regToVariable(RegRsHi, &_RegHI->UW[1], "_RegHI->UW[1]"); + m_Assembler.JmpLabel8(stdstr_f("EndDiv_%08X", m_CompilePC).c_str(), 0); + JumpEnd = *g_RecompPos - 1; + + m_CodeBlock.Log(""); + m_CodeBlock.Log(" NotDiv0_%08X:", m_CompilePC); + m_Assembler.SetJump8(JumpNotDiv0, *g_RecompPos); + if (IsMapped(m_Opcode.rt)) + { + m_Assembler.CompConstToX86reg(GetMipsRegMapLo(m_Opcode.rt), (uint32_t)-1); + } + else + { + m_Assembler.CompConstToVariable((uint32_t)-1, &_GPR[m_Opcode.rt].W[0], CRegName::GPR_Lo[m_Opcode.rt]); + } + m_Assembler.JneLabel8(stdstr_f("ValidDiv0_%08X", m_CompilePC).c_str(), 0); + uint8_t * JumpValidDiv0 = *g_RecompPos - 1; + + m_Assembler.MoveConstToVariable(0x80000000, &_RegLO->UW[0], "_RegLO->UW[0]"); + m_Assembler.MoveConstToVariable(0xFFFFFFFF, &_RegLO->UW[1], "_RegLO->UW[1]"); + m_Assembler.MoveConstToVariable(0x00000000, &_RegHI->UW[0], "_RegHI->UW[0]"); + m_Assembler.MoveConstToVariable(0x00000000, &_RegHI->UW[1], "_RegHI->UW[1]"); + m_Assembler.JmpLabel8(stdstr_f("EndDiv_%08X", m_CompilePC).c_str(), 0); + JumpEnd2 = *g_RecompPos - 1; + + m_CodeBlock.Log(""); + m_CodeBlock.Log(" ValidDiv0_%08X:", m_CompilePC); + m_Assembler.SetJump8(JumpValidDiv0, *g_RecompPos); + } } + m_RegWorkingSet.SetX86Protected(CX86Ops::x86_EAX, true); + UnMap_X86reg(CX86Ops::x86_EDX); + Map_TempReg(CX86Ops::x86_EDX, -1, false); + m_RegWorkingSet.SetX86Protected(CX86Ops::x86_EAX, false); + Map_TempReg(CX86Ops::x86_EAX, m_Opcode.rs, false); + + if (IsConst(m_Opcode.rs)) + { + m_Assembler.MoveConstToX86reg(GetMipsRegLo_S(m_Opcode.rs) >> 31, CX86Ops::x86_EDX); + } + else + { + m_Assembler.MoveX86RegToX86Reg(CX86Ops::x86_EAX, CX86Ops::x86_EDX); + m_Assembler.ShiftRightSignImmed(CX86Ops::x86_EDX, 31); + } + + m_Assembler.idivX86reg(DivReg); m_Assembler.MoveX86regToVariable(CX86Ops::x86_EAX, &_RegLO->UW[0], "_RegLO->UW[0]"); m_Assembler.MoveX86regToVariable(CX86Ops::x86_EDX, &_RegHI->UW[0], "_RegHI->UW[0]"); - m_Assembler.ShiftRightSignImmed(CX86Ops::x86_EAX, 31); // Paired + m_Assembler.ShiftRightSignImmed(CX86Ops::x86_EAX, 31); m_Assembler.ShiftRightSignImmed(CX86Ops::x86_EDX, 31); m_Assembler.MoveX86regToVariable(CX86Ops::x86_EAX, &_RegLO->UW[1], "_RegLO->UW[1]"); m_Assembler.MoveX86regToVariable(CX86Ops::x86_EDX, &_RegHI->UW[1], "_RegHI->UW[1]"); + + if (JumpEnd != nullptr || JumpEnd2 != nullptr) + { + m_CodeBlock.Log(""); + m_CodeBlock.Log(" EndDiv_%08X:", m_CompilePC); + if (JumpEnd != nullptr) + { + m_Assembler.SetJump8(JumpEnd, *g_RecompPos); + } + if (JumpEnd2 != nullptr) + { + m_Assembler.SetJump8(JumpEnd2, *g_RecompPos); + } + } } void CX86RecompilerOps::SPECIAL_DIVU() { - uint8_t *Jump[2]; - CX86Ops::x86Reg Reg; - - if (IsConst(m_Opcode.rt)) + uint8_t * JumpEndDivu = nullptr; + if (IsConst(m_Opcode.rt) && GetMipsRegLo(m_Opcode.rt) == 0) { - if (GetMipsRegLo(m_Opcode.rt) == 0) + if (IsConst(m_Opcode.rs)) { - m_Assembler.MoveConstToVariable(0, &_RegLO->UW[0], "_RegLO->UW[0]"); - m_Assembler.MoveConstToVariable(0, &_RegLO->UW[1], "_RegLO->UW[1]"); - m_Assembler.MoveConstToVariable(0, &_RegHI->UW[0], "_RegHI->UW[0]"); - m_Assembler.MoveConstToVariable(0, &_RegHI->UW[1], "_RegHI->UW[1]"); - return; - } - Jump[1] = nullptr; - } - else - { - if (IsMapped(m_Opcode.rt)) - { - m_Assembler.CompConstToX86reg(GetMipsRegMapLo(m_Opcode.rt), 0); + m_Assembler.MoveConstToVariable(0xFFFFFFFF, &_RegLO->UW[0], "_RegLO->UW[0]"); + m_Assembler.MoveConstToVariable(0xFFFFFFFF, &_RegLO->UW[1], "_RegLO->UW[1]"); + m_Assembler.MoveConstToVariable(GetMipsRegLo(m_Opcode.rs), &_RegHI->UW[0], "_RegHI->UW[0]"); + m_Assembler.MoveConstToVariable(GetMipsRegLo_S(m_Opcode.rs) < 0 ? 0xFFFFFFFF : 0x00000000, &_RegHI->UW[1], "_RegHI->UW[1]"); } else { - m_Assembler.CompConstToVariable(0, &_GPR[m_Opcode.rt].W[0], CRegName::GPR_Lo[m_Opcode.rt]); + CX86Ops::x86Reg RegRs = IsMapped(m_Opcode.rs) ? GetMipsRegMapLo(m_Opcode.rs) : Map_TempReg(CX86Ops::x86_Any, m_Opcode.rs, false); + m_Assembler.CompConstToX86reg(RegRs, 0); + m_Assembler.JgeLabel8(stdstr_f("RsPositive_%08X", m_CompilePC).c_str(), 0); + uint8_t * JumpPositive = *g_RecompPos - 1; + m_Assembler.MoveConstToVariable(0x00000001, &_RegLO->UW[0], "_RegLO->UW[0]"); + m_Assembler.MoveConstToVariable(0x00000000, &_RegLO->UW[1], "_RegLO->UW[1]"); + m_Assembler.JmpLabel8(stdstr_f("LoSet_%08X", m_CompilePC).c_str(), 0); + uint8_t * JumpLoSet = *g_RecompPos - 1; + m_CodeBlock.Log(""); + m_CodeBlock.Log(" RsPositive_%08X:", m_CompilePC); + m_Assembler.SetJump8(JumpPositive, *g_RecompPos); + m_Assembler.MoveConstToVariable(0xFFFFFFFF, &_RegLO->UW[0], "_RegLO->UW[0]"); + m_Assembler.MoveConstToVariable(0xFFFFFFFF, &_RegLO->UW[1], "_RegLO->UW[1]"); + m_CodeBlock.Log(""); + m_CodeBlock.Log(" LoSet_%08X:", m_CompilePC); + m_Assembler.SetJump8(JumpLoSet, *g_RecompPos); + m_Assembler.MoveX86regToVariable(RegRs, &_RegHI->UW[0], "_RegHI->UW[0]"); + if (IsMapped(m_Opcode.rs)) + { + RegRs = Map_TempReg(CX86Ops::x86_Any, m_Opcode.rs, true); + } + else + { + m_Assembler.ShiftRightSignImmed(RegRs, 31); + } + m_Assembler.MoveX86regToVariable(RegRs, &_RegHI->UW[1], "_RegHI->UW[1]"); } - m_Assembler.JneLabel8("NoExcept", 0); - Jump[0] = *g_RecompPos - 1; - - m_Assembler.MoveConstToVariable(0, &_RegLO->UW[0], "_RegLO->UW[0]"); - m_Assembler.MoveConstToVariable(0, &_RegLO->UW[1], "_RegLO->UW[1]"); - m_Assembler.MoveConstToVariable(0, &_RegHI->UW[0], "_RegHI->UW[0]"); - m_Assembler.MoveConstToVariable(0, &_RegHI->UW[1], "_RegHI->UW[1]"); - - m_Assembler.JmpLabel8("EndDivu", 0); - Jump[1] = *g_RecompPos - 1; - - m_CodeBlock.Log(""); - m_CodeBlock.Log(" NoExcept:"); - m_Assembler.SetJump8(Jump[0], *g_RecompPos); } - - /* lo = (UD)rs / (UD)rt; - hi = (UD)rs % (UD)rt; */ - - m_RegWorkingSet.SetX86Protected(CX86Ops::x86_EAX, true); - Map_TempReg(CX86Ops::x86_EDX, 0, false); - m_RegWorkingSet.SetX86Protected(CX86Ops::x86_EAX, false); - - Map_TempReg(CX86Ops::x86_EAX, m_Opcode.rs, false); - Reg = Map_TempReg(CX86Ops::x86_Any, m_Opcode.rt, false); - - m_Assembler.DivX86reg(Reg); - - m_Assembler.MoveX86regToVariable(CX86Ops::x86_EAX, &_RegLO->UW[0], "_RegLO->UW[0]"); - m_Assembler.MoveX86regToVariable(CX86Ops::x86_EDX, &_RegHI->UW[0], "_RegHI->UW[0]"); - - // Wouldn't these be zero? - - m_Assembler.ShiftRightSignImmed(CX86Ops::x86_EAX, 31); // Paired - m_Assembler.ShiftRightSignImmed(CX86Ops::x86_EDX, 31); - m_Assembler.MoveX86regToVariable(CX86Ops::x86_EAX, &_RegLO->UW[1], "_RegLO->UW[1]"); - m_Assembler.MoveX86regToVariable(CX86Ops::x86_EDX, &_RegHI->UW[1], "_RegHI->UW[1]"); - - if (Jump[1] != nullptr) + else { - m_CodeBlock.Log(""); - m_CodeBlock.Log(" EndDivu:"); - m_Assembler.SetJump8(Jump[1], *g_RecompPos); + m_RegWorkingSet.SetX86Protected(CX86Ops::x86_EAX, true); + UnMap_X86reg(CX86Ops::x86_EDX); + m_RegWorkingSet.SetX86Protected(CX86Ops::x86_EAX, false); + m_RegWorkingSet.SetX86Protected(CX86Ops::x86_EDX, true); + UnMap_X86reg(CX86Ops::x86_EAX); + m_RegWorkingSet.SetX86Protected(CX86Ops::x86_EAX, true); + CX86Ops::x86Reg RegRsLo = IsMapped(m_Opcode.rs) ? GetMipsRegMapLo(m_Opcode.rs) : Map_TempReg(CX86Ops::x86_Any, m_Opcode.rs, false); + CX86Ops::x86Reg RegRsHi = IsMapped(m_Opcode.rs) ? Map_TempReg(CX86Ops::x86_Any, IsMapped(m_Opcode.rs), true) : CX86Ops::x86_Unknown; + m_RegWorkingSet.SetX86Protected(CX86Ops::x86_EAX, true); + Map_TempReg(CX86Ops::x86_EDX, 0, false); + m_RegWorkingSet.SetX86Protected(CX86Ops::x86_EAX, false); + + Map_TempReg(CX86Ops::x86_EAX, m_Opcode.rs, false); + CX86Ops::x86Reg DivReg = Map_TempReg(CX86Ops::x86_Any, m_Opcode.rt, false); + + if (!IsConst(m_Opcode.rt)) + { + if (IsMapped(m_Opcode.rt)) + { + m_Assembler.CompConstToX86reg(GetMipsRegMapLo(m_Opcode.rt), 0); + } + else + { + m_Assembler.CompConstToVariable(0, &_GPR[m_Opcode.rt].W[0], CRegName::GPR_Lo[m_Opcode.rt]); + } + m_Assembler.JneLabel8("NoExcept", 0); + uint8_t * JumpNoExcept = *g_RecompPos - 1; + + m_Assembler.MoveConstToVariable(0xFFFFFFFF, &_RegLO->UW[0], "_RegLO->UW[0]"); + m_Assembler.MoveConstToVariable(0xFFFFFFFF, &_RegLO->UW[1], "_RegLO->UW[1]"); + m_Assembler.MoveX86regToVariable(RegRsLo, &_RegHI->UW[0], "_RegHI->UW[0]"); + if (!IsMapped(m_Opcode.rs)) + { + RegRsHi = RegRsLo; + m_Assembler.ShiftRightSignImmed(RegRsHi, 31); + } + m_Assembler.MoveX86regToVariable(RegRsHi, &_RegHI->UW[1], "_RegHI->UW[1]"); + + m_Assembler.JmpLabel8("EndDivu", 0); + JumpEndDivu = *g_RecompPos - 1; + m_CodeBlock.Log(""); + m_CodeBlock.Log(" NoExcept:"); + m_Assembler.SetJump8(JumpNoExcept, *g_RecompPos); + } + m_Assembler.DivX86reg(DivReg); + + m_Assembler.MoveX86regToVariable(CX86Ops::x86_EAX, &_RegLO->UW[0], "_RegLO->UW[0]"); + m_Assembler.MoveX86regToVariable(CX86Ops::x86_EDX, &_RegHI->UW[0], "_RegHI->UW[0]"); + m_Assembler.ShiftRightSignImmed(CX86Ops::x86_EAX, 31); + m_Assembler.ShiftRightSignImmed(CX86Ops::x86_EDX, 31); + m_Assembler.MoveX86regToVariable(CX86Ops::x86_EAX, &_RegLO->UW[1], "_RegLO->UW[1]"); + m_Assembler.MoveX86regToVariable(CX86Ops::x86_EDX, &_RegHI->UW[1], "_RegHI->UW[1]"); + + if (JumpEndDivu != nullptr) + { + m_CodeBlock.Log(""); + m_CodeBlock.Log(" EndDivu:"); + m_Assembler.SetJump8(JumpEndDivu, *g_RecompPos); + } } } @@ -9621,17 +9800,6 @@ void CX86RecompilerOps::CompileExit(uint32_t JumpPC, uint32_t TargetPC, CRegInfo m_Assembler.X86BreakPoint(__FILE__, __LINE__); ExitCodeBlock(); break; - case CExitInfo::DivByZero: - m_Assembler.AddConstToVariable(4, _PROGRAM_COUNTER, "PROGRAM_COUNTER"); - if (!g_System->b32BitCore()) - { - m_Assembler.MoveConstToVariable(0, &_RegHI->UW[1], "_RegHI->UW[1]"); - m_Assembler.MoveConstToVariable(0, &_RegLO->UW[1], "_RegLO->UW[1]"); - } - m_Assembler.MoveConstToVariable(0, &_RegHI->UW[0], "_RegHI->UW[0]"); - m_Assembler.MoveConstToVariable(0, &_RegLO->UW[0], "_RegLO->UW[0]"); - ExitCodeBlock(); - break; default: WriteTrace(TraceRecompiler, TraceError, "How did you want to exit on reason (%d) ???", reason); g_Notify->BreakPoint(__FILE__, __LINE__); diff --git a/Source/Project64-core/N64System/Recompiler/x86/x86ops.cpp b/Source/Project64-core/N64System/Recompiler/x86/x86ops.cpp index 65d57f8a4..2bb1921ca 100644 --- a/Source/Project64-core/N64System/Recompiler/x86/x86ops.cpp +++ b/Source/Project64-core/N64System/Recompiler/x86/x86ops.cpp @@ -467,6 +467,13 @@ void CX86Ops::JeLabel32(const char * Label, uint32_t Value) AddCode32(Value); } +void CX86Ops::JgeLabel8(const char * Label, uint8_t Value) +{ + CodeLog(" jge $%s", Label); + AddCode8(0x7D); + AddCode8(Value); +} + void CX86Ops::JgeLabel32(const char * Label, uint32_t Value) { CodeLog(" jge $%s", Label); diff --git a/Source/Project64-core/N64System/Recompiler/x86/x86ops.h b/Source/Project64-core/N64System/Recompiler/x86/x86ops.h index 6f4e7eaa4..46806f34b 100644 --- a/Source/Project64-core/N64System/Recompiler/x86/x86ops.h +++ b/Source/Project64-core/N64System/Recompiler/x86/x86ops.h @@ -97,6 +97,7 @@ public: void JecxzLabel8(const char * Label, uint8_t Value); void JeLabel8(const char * Label, uint8_t Value); void JeLabel32(const char * Label, uint32_t Value); + void JgeLabel8(const char * Label, uint8_t Value); void JgeLabel32(const char * Label, uint32_t Value); void JgLabel8(const char * Label, uint8_t Value); void JgLabel32(const char * Label, uint32_t Value); diff --git a/Source/Project64-core/Settings.cpp b/Source/Project64-core/Settings.cpp index f90dc24ba..0ab0187eb 100644 --- a/Source/Project64-core/Settings.cpp +++ b/Source/Project64-core/Settings.cpp @@ -342,7 +342,6 @@ void CSettings::AddHowToHandleSetting(const char * BaseDirectory) AddHandler(Debugger_IntrBreakpoints, new CSettingTypeApplication("Debugger", "Interrupt Breakpoints", (uint32_t)0)); AddHandler(Debugger_RcpIntrBreakpoints, new CSettingTypeApplication("Debugger", "RCP Interrupt Breakpoints", (uint32_t)0)); AddHandler(Debugger_DebugLanguage, new CSettingTypeApplication("Debugger", "Debug Language", false)); - AddHandler(Debugger_ShowDivByZero, new CSettingTypeApplication("Debugger", "Show Div by zero", false)); AddHandler(Debugger_AppLogFlush, new CSettingTypeApplication("Logging", "Log Auto Flush", (uint32_t)false)); AddHandler(Debugger_RecordRecompilerAsm, new CSettingTypeApplication("Debugger", "Record Recompiler Asm", false)); AddHandler(Debugger_AutorunScripts, new CSettingTypeApplication("Debugger", "Autorun Scripts", "")); diff --git a/Source/Project64-core/Settings/DebugSettings.cpp b/Source/Project64-core/Settings/DebugSettings.cpp index 041d88dc3..b41f1f9e4 100644 --- a/Source/Project64-core/Settings/DebugSettings.cpp +++ b/Source/Project64-core/Settings/DebugSettings.cpp @@ -12,7 +12,6 @@ bool CDebugSettings::m_SkipOp = false; bool CDebugSettings::m_WaitingForStep = false; bool CDebugSettings::m_bRecordRecompilerAsm = false; bool CDebugSettings::m_bShowTLBMisses = false; -bool CDebugSettings::m_bShowDivByZero = false; bool CDebugSettings::m_RecordExecutionTimes = false; bool CDebugSettings::m_HaveExecutionBP = false; bool CDebugSettings::m_HaveWriteBP = false; @@ -36,7 +35,6 @@ CDebugSettings::CDebugSettings() m_Registered = true; g_Settings->RegisterChangeCB(Debugger_Enabled, this, (CSettings::SettingChangedFunc)StaticRefreshSettings); g_Settings->RegisterChangeCB(Debugger_RecordRecompilerAsm, this, (CSettings::SettingChangedFunc)StaticRefreshSettings); - g_Settings->RegisterChangeCB(Debugger_ShowDivByZero, this, (CSettings::SettingChangedFunc)StaticRefreshSettings); g_Settings->RegisterChangeCB(Debugger_RecordExecutionTimes, this, (CSettings::SettingChangedFunc)StaticRefreshSettings); g_Settings->RegisterChangeCB(Debugger_SteppingOps, this, (CSettings::SettingChangedFunc)StaticRefreshSettings); g_Settings->RegisterChangeCB(Debugger_SkipOp, this, (CSettings::SettingChangedFunc)StaticRefreshSettings); @@ -66,7 +64,6 @@ CDebugSettings::~CDebugSettings() { g_Settings->UnregisterChangeCB(Debugger_Enabled, this, (CSettings::SettingChangedFunc)StaticRefreshSettings); g_Settings->UnregisterChangeCB(Debugger_RecordRecompilerAsm, this, (CSettings::SettingChangedFunc)StaticRefreshSettings); - g_Settings->UnregisterChangeCB(Debugger_ShowDivByZero, this, (CSettings::SettingChangedFunc)StaticRefreshSettings); g_Settings->UnregisterChangeCB(Debugger_RecordExecutionTimes, this, (CSettings::SettingChangedFunc)StaticRefreshSettings); g_Settings->UnregisterChangeCB(Debugger_SteppingOps, this, (CSettings::SettingChangedFunc)StaticRefreshSettings); g_Settings->UnregisterChangeCB(Debugger_SkipOp, this, (CSettings::SettingChangedFunc)StaticRefreshSettings); @@ -90,7 +87,6 @@ void CDebugSettings::RefreshSettings() { m_HaveDebugger = g_Settings->LoadBool(Debugger_Enabled); m_bRecordRecompilerAsm = m_HaveDebugger && g_Settings->LoadBool(Debugger_RecordRecompilerAsm); - m_bShowDivByZero = m_HaveDebugger && g_Settings->LoadBool(Debugger_ShowDivByZero); m_RecordExecutionTimes = m_HaveDebugger && g_Settings->LoadBool(Debugger_RecordExecutionTimes); m_Stepping = m_HaveDebugger && g_Settings->LoadBool(Debugger_SteppingOps); m_SkipOp = m_HaveDebugger && g_Settings->LoadBool(Debugger_SkipOp); diff --git a/Source/Project64-core/Settings/DebugSettings.h b/Source/Project64-core/Settings/DebugSettings.h index 06cde5bd8..289d0ca6f 100644 --- a/Source/Project64-core/Settings/DebugSettings.h +++ b/Source/Project64-core/Settings/DebugSettings.h @@ -15,7 +15,6 @@ public: static inline bool WaitingForStep(void) { return m_WaitingForStep; } static inline bool bRecordRecompilerAsm(void) { return m_bRecordRecompilerAsm; } static inline bool bShowTLBMisses(void) { return m_bShowTLBMisses; } - static inline bool bShowDivByZero(void) { return m_bShowDivByZero; } static inline bool bRecordExecutionTimes(void) { return m_RecordExecutionTimes; } static inline bool HaveExecutionBP(void) { return m_HaveExecutionBP; } static inline bool HaveWriteBP(void) { return m_HaveWriteBP; } @@ -46,7 +45,6 @@ private: static bool m_WaitingForStep; static bool m_bRecordRecompilerAsm; static bool m_bShowTLBMisses; - static bool m_bShowDivByZero; static bool m_RecordExecutionTimes; static bool m_HaveExecutionBP; static bool m_HaveWriteBP; diff --git a/Source/Project64-core/Settings/SettingsID.h b/Source/Project64-core/Settings/SettingsID.h index c0c4c78ce..ad17c75df 100644 --- a/Source/Project64-core/Settings/SettingsID.h +++ b/Source/Project64-core/Settings/SettingsID.h @@ -241,7 +241,6 @@ enum SettingID Debugger_BreakOnAddressError, Debugger_StepOnBreakOpCode, Debugger_ShowPifErrors, - Debugger_ShowDivByZero, Debugger_RecordRecompilerAsm, Debugger_DisableGameFixes, Debugger_AppLogLevel, diff --git a/Source/Project64/UserInterface/MainMenu.cpp b/Source/Project64/UserInterface/MainMenu.cpp index 05200193a..9d55bc3ae 100644 --- a/Source/Project64/UserInterface/MainMenu.cpp +++ b/Source/Project64/UserInterface/MainMenu.cpp @@ -32,7 +32,6 @@ CMainMenu::CMainMenu(CMainGui * hMainWindow) : m_ChangeSettingList.push_back(Debugger_ShowDListAListCount); m_ChangeSettingList.push_back(Debugger_DebugLanguage); m_ChangeSettingList.push_back(Debugger_ShowRecompMemSize); - m_ChangeSettingList.push_back(Debugger_ShowDivByZero); m_ChangeSettingList.push_back(Debugger_RecordRecompilerAsm); m_ChangeSettingList.push_back(Debugger_DisableGameFixes); m_ChangeSettingList.push_back(Debugger_TraceMD5); @@ -527,9 +526,6 @@ bool CMainMenu::ProcessMessage(HWND hWnd, DWORD /*FromAccelerator*/, DWORD MenuI g_Settings->SaveBool(Debugger_ShowRecompMemSize, !g_Settings->LoadBool(Debugger_ShowRecompMemSize)); g_Notify->DisplayMessage(0, EMPTY_STRING); break; - case ID_DEBUG_SHOW_DIV_BY_ZERO: - g_Settings->SaveBool(Debugger_ShowDivByZero, !g_Settings->LoadBool(Debugger_ShowDivByZero)); - break; case ID_DEBUG_RECORD_RECOMPILER_ASM: g_Settings->SaveBool(Debugger_RecordRecompilerAsm, !g_Settings->LoadBool(Debugger_RecordRecompilerAsm)); break; @@ -1257,12 +1253,6 @@ void CMainMenu::FillOutMenu(HMENU hMenu) Item.SetItemTicked(true); } DebugNotificationMenu.push_back(Item); - Item.Reset(ID_DEBUG_SHOW_DIV_BY_ZERO, EMPTY_STRING, EMPTY_STDSTR, nullptr, L"On division by zero errors"); - if (g_Settings->LoadBool(Debugger_ShowDivByZero)) - { - Item.SetItemTicked(true); - } - DebugNotificationMenu.push_back(Item); DebugMenu.push_back(MENU_ITEM(SPLITER)); Item.Reset(SUB_MENU, EMPTY_STRING, EMPTY_STDSTR, &DebugProfileMenu, L"Profile"); diff --git a/Source/Project64/UserInterface/MainMenu.h b/Source/Project64/UserInterface/MainMenu.h index d3cbe6b75..37d75e607 100644 --- a/Source/Project64/UserInterface/MainMenu.h +++ b/Source/Project64/UserInterface/MainMenu.h @@ -35,7 +35,7 @@ enum MainMenuID // Debugger menu ID_DEBUG_END_ON_PERM_LOOP, ID_DEBUG_STEP_ON_BREAK_OPCODE, ID_DEBUG_BREAK_ON_UNHANDLED_MEM, ID_DEBUG_BREAK_ON_ADDRESS_ERROR, ID_DEBUG_SHOW_PIF_ERRORS, - ID_DEBUG_SHOW_DLIST_COUNT, ID_DEBUG_SHOW_RECOMP_MEM_SIZE, ID_DEBUG_SHOW_DIV_BY_ZERO, + ID_DEBUG_SHOW_DLIST_COUNT, ID_DEBUG_SHOW_RECOMP_MEM_SIZE, ID_DEBUG_RECORD_RECOMPILER_ASM, ID_DEBUG_DISABLE_GAMEFIX, ID_DEBUG_LANGUAGE, ID_DEBUGGER_LOGOPTIONS, ID_DEBUGGER_GENERATELOG, ID_DEBUGGER_DUMPMEMORY, ID_DEBUGGER_SEARCHMEMORY, ID_DEBUGGER_TLBENTRIES, ID_DEBUGGER_BREAKPOINTS, ID_DEBUGGER_MEMORY, ID_DEBUGGER_R4300REGISTERS,