From 36def4094a7d9635efa634e1d1774c9756060e74 Mon Sep 17 00:00:00 2001 From: zilmar <zilmar@pj64-emu.com> Date: Tue, 29 Jan 2013 22:29:50 +1100 Subject: [PATCH] RSP: Can exit after jump from MT/MF Cop 0 --- Source/RSP/Recompiler Ops.c | 117 ++++++++++++++++++++++++++++++------ 1 file changed, 97 insertions(+), 20 deletions(-) diff --git a/Source/RSP/Recompiler Ops.c b/Source/RSP/Recompiler Ops.c index 77d727f57..bb34d2d33 100644 --- a/Source/RSP/Recompiler Ops.c +++ b/Source/RSP/Recompiler Ops.c @@ -28,8 +28,9 @@ #include <stdio.h> #include "RSP.h" #include "CPU.h" -#include "Recompiler CPU.h" +#include "Interpreter CPU.h" #include "Interpreter Ops.h" +#include "Recompiler CPU.h" #include "RSP Command.h" #include "RSP Registers.h" #include "memory.h" @@ -145,6 +146,23 @@ void BreakPoint() { *(RecompPos++) = 0xCC; } +void CompileBranchExit(DWORD TargetPC, DWORD ContinuePC) +{ + DWORD * X86Loc = NULL; + + NextInstruction = FINISH_SUB_BLOCK; + CompConstToVariable(TRUE, &BranchCompare, "BranchCompare"); + JeLabel32("BranchEqual", 0); + X86Loc = (DWORD*)(RecompPos - 4); + MoveConstToVariable(ContinuePC,PrgCount,"RSP PC"); + Ret(); + + CPU_Message("BranchEqual:"); + x86_SetBranch32b(X86Loc, RecompPos); + MoveConstToVariable(TargetPC,PrgCount,"RSP PC"); + Ret(); +} + /************************* OpCode functions *************************/ void Compile_SPECIAL ( void ) { ((void (*)()) RSP_Special[ RSPOpC.funct ])(); @@ -244,6 +262,9 @@ void Compile_BEQ ( void ) { } Branch_AddRef(Target, (DWORD*)(RecompPos - 4)); NextInstruction = FINISH_SUB_BLOCK; + } else if ( NextInstruction == DELAY_SLOT_EXIT_DONE ) { + DWORD Target = (CompilePC + ((short)RSPOpC.offset << 2) + 4) & 0xFFC; + CompileBranchExit(Target, CompilePC + 8); } else { CompilerWarning("BEQ error\nWeird Delay Slot.\n\nNextInstruction = %X\nEmulation will now stop", NextInstruction); BreakPoint(); @@ -300,6 +321,9 @@ void Compile_BNE ( void ) { } Branch_AddRef(Target, (DWORD*)(RecompPos - 4)); NextInstruction = FINISH_SUB_BLOCK; + } else if ( NextInstruction == DELAY_SLOT_EXIT_DONE ) { + DWORD Target = (CompilePC + ((short)RSPOpC.offset << 2) + 4) & 0xFFC; + CompileBranchExit(Target, CompilePC + 8); } else { CompilerWarning("BNE error\nWeird Delay Slot.\n\nNextInstruction = %X\nEmulation will now stop", NextInstruction); BreakPoint(); @@ -343,6 +367,9 @@ void Compile_BLEZ ( void ) { Branch_AddRef(Target, (DWORD*)(RecompPos - 4)); NextInstruction = FINISH_SUB_BLOCK; + } else if ( NextInstruction == DELAY_SLOT_EXIT_DONE ) { + DWORD Target = (CompilePC + ((short)RSPOpC.offset << 2) + 4) & 0xFFC; + CompileBranchExit(Target, CompilePC + 8); } else { CompilerWarning("BLEZ error\nWeird Delay Slot.\n\nNextInstruction = %X\nEmulation will now stop", NextInstruction); BreakPoint(); @@ -383,6 +410,9 @@ void Compile_BGTZ ( void ) { } Branch_AddRef(Target, (DWORD*)(RecompPos - 4)); NextInstruction = FINISH_SUB_BLOCK; + } else if ( NextInstruction == DELAY_SLOT_EXIT_DONE ) { + DWORD Target = (CompilePC + ((short)RSPOpC.offset << 2) + 4) & 0xFFC; + CompileBranchExit(Target, CompilePC + 8); } else { CompilerWarning("BGTZ error\nWeird Delay Slot.\n\nNextInstruction = %X\nEmulation will now stop", NextInstruction); BreakPoint(); @@ -1035,6 +1065,9 @@ void Compile_Special_JR (void) { Ret(); ChangedPC = FALSE; NextInstruction = FINISH_SUB_BLOCK; + } else if ( NextInstruction == DELAY_SLOT_EXIT_DONE ) { + NextInstruction = FINISH_SUB_BLOCK; + Ret(); } else { CompilerWarning("WTF\n\nJR\nNextInstruction = %X", NextInstruction); BreakPoint(); @@ -1074,12 +1107,14 @@ void Compile_Special_JALR ( void ) { void Compile_Special_BREAK ( void ) { Cheat_r4300iOpcode(RSP_Special_BREAK,"RSP_Special_BREAK"); - if (NextInstruction != NORMAL) { - DisplayError("Compile_Special_BREAK: problem"); + if (NextInstruction == NORMAL) { + MoveConstToVariable(CompilePC + 4,PrgCount,"RSP PC"); + Ret(); + NextInstruction = FINISH_SUB_BLOCK; + } else { + CompilerWarning("WTF\n\nBREAK\nNextInstruction = %X", NextInstruction); + BreakPoint(); } - MoveConstToVariable(CompilePC + 4,PrgCount,"RSP PC"); - Ret(); - NextInstruction = FINISH_BLOCK; } void Compile_Special_ADD ( void ) { @@ -1337,6 +1372,9 @@ void Compile_RegImm_BLTZ ( void ) { } Branch_AddRef(Target, (DWORD*)(RecompPos - 4)); NextInstruction = FINISH_SUB_BLOCK; + } else if ( NextInstruction == DELAY_SLOT_EXIT_DONE ) { + DWORD Target = (CompilePC + ((short)RSPOpC.offset << 2) + 4) & 0xFFC; + CompileBranchExit(Target, CompilePC + 8); } else { CompilerWarning("BLTZ error\nWeird Delay Slot.\n\nNextInstruction = %X\nPC = %X\nEmulation will now stop", NextInstruction, CompilePC); BreakPoint(); @@ -1379,6 +1417,9 @@ void Compile_RegImm_BGEZ ( void ) { } Branch_AddRef(Target, (DWORD*)(RecompPos - 4)); NextInstruction = FINISH_SUB_BLOCK; + } else if ( NextInstruction == DELAY_SLOT_EXIT_DONE ) { + DWORD Target = (CompilePC + ((short)RSPOpC.offset << 2) + 4) & 0xFFC; + CompileBranchExit(Target, CompilePC + 8); } else { CompilerWarning("BGEZ error\nWeird Delay Slot.\n\nNextInstruction = %X\nEmulation will now stop", NextInstruction); BreakPoint(); @@ -1461,10 +1502,6 @@ void Compile_RegImm_BGEZAL ( void ) { /************************** Cop0 functions *************************/ void Compile_Cop0_MF ( void ) { - #ifndef Compile_Cop0 - Cheat_r4300iOpcode(RSP_Cop0_MF,"RSP_Cop0_MF"); return; - #endif - CPU_Message(" %X %s",CompilePC,RSPOpcodeName(RSPOpC.Hex,CompilePC)); if (LogRDP) { @@ -1478,6 +1515,21 @@ void Compile_Cop0_MF ( void ) { AddConstToX86Reg(x86_ESP, 8); } +#ifndef Compile_Cop0 + Cheat_r4300iOpcode(RSP_Cop0_MF,"RSP_Cop0_MF"); + if (NextInstruction == NORMAL) + { + MoveConstToVariable(CompilePC + 4,PrgCount,"RSP PC"); + Ret(); + NextInstruction = FINISH_SUB_BLOCK; + } else if (NextInstruction == DELAY_SLOT) { + NextInstruction = DELAY_SLOT_EXIT; + } else { + CompilerWarning("MF error\nWeird Delay Slot.\n\nNextInstruction = %X\nEmulation will now stop", NextInstruction); + BreakPoint(); + } + return; +#else switch (RSPOpC.rd) { case 4: MoveVariableToX86reg(RSPInfo.SP_STATUS_REG, "SP_STATUS_REG", x86_EAX); @@ -1493,9 +1545,17 @@ void Compile_Cop0_MF ( void ) { break; case 7: Cheat_r4300iOpcode(RSP_Cop0_MF,"RSP_Cop0_MF"); - MoveConstToVariable(CompilePC + 4,PrgCount,"RSP PC"); - Ret(); - NextInstruction = FINISH_BLOCK; + if (NextInstruction == NORMAL) + { + MoveConstToVariable(CompilePC + 4,PrgCount,"RSP PC"); + Ret(); + NextInstruction = FINISH_SUB_BLOCK; + } else if (NextInstruction == DELAY_SLOT) { + NextInstruction = DELAY_SLOT_EXIT; + } else { + CompilerWarning("MF error\nWeird Delay Slot.\n\nNextInstruction = %X\nEmulation will now stop", NextInstruction); + BreakPoint(); + } break; case 8: MoveVariableToX86reg(RSPInfo.DPC_START_REG, "DPC_START_REG", x86_EAX); @@ -1521,15 +1581,15 @@ void Compile_Cop0_MF ( void ) { default: CompilerWarning("have not implemented RSP MF CP0 reg %s (%d)",COP0_Name(RSPOpC.rd),RSPOpC.rd); } +#endif } -void Compile_Cop0_MT ( void ) { -#ifndef Compile_Cop0 - Cheat_r4300iOpcode(RSP_Cop0_MT,"RSP_Cop0_MT"); -#else +void Compile_Cop0_MT ( void ) +{ CPU_Message(" %X %s",CompilePC,RSPOpcodeName(RSPOpC.Hex,CompilePC)); + if (LogRDP) - { + { char str[40]; MoveVariableToX86reg(&RSP_GPR[RSPOpC.rt].UW, GPR_Name(RSPOpC.rt), x86_EAX); @@ -1542,6 +1602,23 @@ void Compile_Cop0_MT ( void ) { AddConstToX86Reg(x86_ESP, 12); } +#ifndef Compile_Cop0 + Cheat_r4300iOpcode(RSP_Cop0_MT,"RSP_Cop0_MT"); + if (RSPOpC.rd == 4) + { + if (NextInstruction == NORMAL) + { + MoveConstToVariable(CompilePC + 4,PrgCount,"RSP PC"); + Ret(); + NextInstruction = FINISH_BLOCK; + } else if (NextInstruction == DELAY_SLOT) { + NextInstruction = DELAY_SLOT_EXIT; + } else { + CompilerWarning("MF error\nWeird Delay Slot.\n\nNextInstruction = %X\nEmulation will now stop", NextInstruction); + BreakPoint(); + } + } +#else switch (RSPOpC.rd) { case 0: MoveVariableToX86reg(&RSP_GPR[RSPOpC.rt].UW, GPR_Name(RSPOpC.rt), x86_EAX); @@ -4010,7 +4087,7 @@ void Compile_Opcode_LLV ( void ) { CPU_Message(" %X %s",CompilePC,RSPOpcodeName(RSPOpC.Hex,CompilePC)); if ((RSPOpC.del & 0x3) != 0) { - rsp_UnknownOpcode(); + Cheat_r4300iOpcode(RSP_Opcode_LLV,"RSP_Opcode_LLV"); return; return; } @@ -4167,7 +4244,7 @@ void Compile_Opcode_LQV ( void ) { CPU_Message(" %X %s",CompilePC,RSPOpcodeName(RSPOpC.Hex,CompilePC)); if (RSPOpC.del != 0) { - rsp_UnknownOpcode(); + Cheat_r4300iOpcode(RSP_Opcode_LQV,"RSP_Opcode_LQV"); return; return; }