From dc103ec59b9d332a17d15578e2a947c2a84a309d Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 8 Mar 2015 19:29:41 -0400 Subject: [PATCH 1/3] keep $zero overwrite prevention to a single location in CPU loop In both the 32- and the 64-bit interpreters, ADDI, LUI, LB, LW, LWU, LL, SLLV all check if the destination register specifier is 0, when none of the other interpreter ops do. Actually, none of these 7 need to really check it either, since handling $zero overwrite is already managed in a single location in the main interpreter loop. --- .../Project64/N64 System/Interpreter/Interpreter CPU.cpp | 2 +- .../N64 System/Interpreter/Interpreter Ops 32.cpp | 9 --------- .../Project64/N64 System/Interpreter/Interpreter Ops.cpp | 9 --------- 3 files changed, 1 insertion(+), 19 deletions(-) diff --git a/Source/Project64/N64 System/Interpreter/Interpreter CPU.cpp b/Source/Project64/N64 System/Interpreter/Interpreter CPU.cpp index 150ddb5a7..35bfbd6dd 100644 --- a/Source/Project64/N64 System/Interpreter/Interpreter CPU.cpp +++ b/Source/Project64/N64 System/Interpreter/Interpreter CPU.cpp @@ -337,7 +337,7 @@ void CInterpreterCPU::ExecuteOps ( int Cycles ) //WriteTraceF((TraceType)(TraceError | TraceNoHeader),"%X: %d %d",*_PROGRAM_COUNTER,*g_NextTimer,g_SystemTimer->CurrentType()); }*/ m_R4300i_Opcode[ Opcode.op ](); - _GPR[0].DW = 0; + _GPR[0].DW = 0; /* MIPS $zero hard-wired to 0 */ Cycles -= CountPerOp; *g_NextTimer -= CountPerOp; diff --git a/Source/Project64/N64 System/Interpreter/Interpreter Ops 32.cpp b/Source/Project64/N64 System/Interpreter/Interpreter Ops 32.cpp index 9cc1eff5f..55b4e8b5f 100644 --- a/Source/Project64/N64 System/Interpreter/Interpreter Ops 32.cpp +++ b/Source/Project64/N64 System/Interpreter/Interpreter Ops 32.cpp @@ -709,7 +709,6 @@ void R4300iOp32::ADDI (void) { StackValue += (short)m_Opcode.immediate; } #endif - if (m_Opcode.rt == 0) { return; } _GPR[m_Opcode.rt].W[0] = (_GPR[m_Opcode.rs].W[0] + ((short)m_Opcode.immediate)); #ifdef Interpreter_StackTest if (m_Opcode.rt == 29 && m_Opcode.rs != 29) { @@ -761,7 +760,6 @@ void R4300iOp32::XORI (void) { } void R4300iOp32::LUI (void) { - if (m_Opcode.rt == 0) { return; } _GPR[m_Opcode.rt].W[0] = (long)((short)m_Opcode.offset << 16); #ifdef Interpreter_StackTest if (m_Opcode.rt == 29) { @@ -840,7 +838,6 @@ void R4300iOp32::BGTZL (void) { void R4300iOp32::LB (void) { DWORD Address = _GPR[m_Opcode.base].UW[0] + (short)m_Opcode.offset; - if (m_Opcode.rt == 0) { return; } if (!g_MMU->LB_VAddr(Address,_GPR[m_Opcode.rt].UB[0])) { if (bShowTLBMisses()) { g_Notify->DisplayError(L"LB TLB: %X",Address); @@ -892,8 +889,6 @@ void R4300iOp32::LW (void) { Log_LW((*_PROGRAM_COUNTER),Address); } - if (m_Opcode.rt == 0) { return; } - if (!g_MMU->LW_VAddr(Address,_GPR[m_Opcode.rt].UW[0])) { if (bShowTLBMisses()) { g_Notify->DisplayError(L"LW TLB: %X",Address); @@ -952,7 +947,6 @@ void R4300iOp32::LWR (void) { void R4300iOp32::LWU (void) { DWORD Address = _GPR[m_Opcode.base].UW[0] + (short)m_Opcode.offset; if ((Address & 3) != 0) { ADDRESS_ERROR_EXCEPTION(Address,TRUE); } - if (m_Opcode.rt == 0) { return; } if (!g_MMU->LW_VAddr(Address,_GPR[m_Opcode.rt].UW[0])) { if (bShowTLBMisses()) { @@ -969,8 +963,6 @@ void R4300iOp32::LL (void) { DWORD Address = _GPR[m_Opcode.base].UW[0] + (short)m_Opcode.offset; if ((Address & 3) != 0) { ADDRESS_ERROR_EXCEPTION(Address,TRUE); } - if (m_Opcode.rt == 0) { return; } - if (!g_MMU->LW_VAddr(Address,_GPR[m_Opcode.rt].UW[0])) { if (bShowTLBMisses()) { g_Notify->DisplayError(L"LL TLB: %X",Address); @@ -996,7 +988,6 @@ void R4300iOp32::SPECIAL_SRA (void) { } void R4300iOp32::SPECIAL_SLLV (void) { - if (m_Opcode.rd == 0) { return; } _GPR[m_Opcode.rd].W[0] = (_GPR[m_Opcode.rt].W[0] << (_GPR[m_Opcode.rs].UW[0] & 0x1F)); } diff --git a/Source/Project64/N64 System/Interpreter/Interpreter Ops.cpp b/Source/Project64/N64 System/Interpreter/Interpreter Ops.cpp index b34179476..639325889 100644 --- a/Source/Project64/N64 System/Interpreter/Interpreter Ops.cpp +++ b/Source/Project64/N64 System/Interpreter/Interpreter Ops.cpp @@ -814,7 +814,6 @@ void R4300iOp::ADDI (void) StackValue += (short)m_Opcode.immediate; } #endif - if (m_Opcode.rt == 0) { return; } _GPR[m_Opcode.rt].DW = (_GPR[m_Opcode.rs].W[0] + ((short)m_Opcode.immediate)); #ifdef Interpreter_StackTest if (m_Opcode.rt == 29 && m_Opcode.rs != 29) { @@ -873,7 +872,6 @@ void R4300iOp::XORI (void) void R4300iOp::LUI (void) { - if (m_Opcode.rt == 0) { return; } _GPR[m_Opcode.rt].DW = (long)((short)m_Opcode.offset << 16); #ifdef Interpreter_StackTest if (m_Opcode.rt == 29) { @@ -1016,7 +1014,6 @@ void R4300iOp::LDR (void) void R4300iOp::LB (void) { DWORD Address = _GPR[m_Opcode.base].UW[0] + (short)m_Opcode.offset; - if (m_Opcode.rt == 0) { return; } if (!g_MMU->LB_VAddr(Address,_GPR[m_Opcode.rt].UB[0])) { if (bShowTLBMisses()) { g_Notify->DisplayError(L"LB TLB: %X",Address); @@ -1072,8 +1069,6 @@ void R4300iOp::LW (void) Log_LW((*_PROGRAM_COUNTER),Address); } - if (m_Opcode.rt == 0) { return; } - if (!g_MMU->LW_VAddr(Address,_GPR[m_Opcode.rt].UW[0])) { if (bShowTLBMisses()) { g_Notify->DisplayError(L"LW TLB: %X",Address); @@ -1136,7 +1131,6 @@ void R4300iOp::LWU (void) { DWORD Address = _GPR[m_Opcode.base].UW[0] + (short)m_Opcode.offset; if ((Address & 3) != 0) { ADDRESS_ERROR_EXCEPTION(Address,TRUE); } - if (m_Opcode.rt == 0) { return; } if (!g_MMU->LW_VAddr(Address,_GPR[m_Opcode.rt].UW[0])) { if (bShowTLBMisses()) { @@ -1381,8 +1375,6 @@ void R4300iOp::LL (void) DWORD Address = _GPR[m_Opcode.base].UW[0] + (short)m_Opcode.offset; if ((Address & 3) != 0) { ADDRESS_ERROR_EXCEPTION(Address,TRUE); } - if (m_Opcode.rt == 0) { return; } - if (!g_MMU->LW_VAddr(Address,_GPR[m_Opcode.rt].UW[0])) { if (bShowTLBMisses()) @@ -1543,7 +1535,6 @@ void R4300iOp::SPECIAL_SRA (void) void R4300iOp::SPECIAL_SLLV (void) { - if (m_Opcode.rd == 0) { return; } _GPR[m_Opcode.rd].DW = (_GPR[m_Opcode.rt].W[0] << (_GPR[m_Opcode.rs].UW[0] & 0x1F)); } From 1772f1467c9913ba618d938d3d40a2349fe4640d Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 8 Mar 2015 20:17:18 -0400 Subject: [PATCH 2/3] Prevent remaining possibilities of overwriting $zero in RSP. In the RSP, MFC0, MFC2, and CFC2 were all susceptible to overwriting $zero. Some of us have tried waiting for some games to use handcoded assembly in an attempt to purposely overwrite $zero in their microcode (to throw off emulators), but so far what few occurrences there have been of this have not included using those 3 opcodes. Since it was decided to centralize the security of register $zero in the main R4300 CPU, it was decided to do so in the RSP as well. --- Source/RSP/Interpreter CPU.c | 1 + 1 file changed, 1 insertion(+) diff --git a/Source/RSP/Interpreter CPU.c b/Source/RSP/Interpreter CPU.c index b8647093d..0849ef90d 100644 --- a/Source/RSP/Interpreter CPU.c +++ b/Source/RSP/Interpreter CPU.c @@ -444,6 +444,7 @@ DWORD RunInterpreterCPU(DWORD Cycles) { RSP_LW_IMEM(*PrgCount, &RSPOpC.Hex); RSP_Opcode[ RSPOpC.op ](); + RSP_GPR[0].W = 0x00000000; /* MIPS $zero hard-wired to 0 */ switch (RSP_NextInstruction) { case NORMAL: From cb9f9e2b5646c8a5ad387324caec8ab6c1b4b9f5 Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 8 Mar 2015 20:20:05 -0400 Subject: [PATCH 3/3] keeping $0 overwrite prevention to just the CPU interpreter loop Tried my best to make sure I didn't miss any op-codes. (Ctrl+F searching for "!= 0" and "== 0" throught the file shows me that I didn't.) If I did miss any op-codes, it's no bug, just remaining extra unnecessary checking for zero. --- Source/RSP/Interpreter Ops.c | 84 +++++++++--------------------------- 1 file changed, 20 insertions(+), 64 deletions(-) diff --git a/Source/RSP/Interpreter Ops.c b/Source/RSP/Interpreter Ops.c index f3003798f..5622a9d9a 100644 --- a/Source/RSP/Interpreter Ops.c +++ b/Source/RSP/Interpreter Ops.c @@ -98,19 +98,14 @@ void RSP_Opcode_BGTZ ( void ) { } void RSP_Opcode_ADDI ( void ) { - if (RSPOpC.rt != 0) { - RSP_GPR[RSPOpC.rt].W = RSP_GPR[RSPOpC.rs].W + (int16_t)RSPOpC.immediate; - } + RSP_GPR[RSPOpC.rt].W = RSP_GPR[RSPOpC.rs].W + (int16_t)RSPOpC.immediate; } void RSP_Opcode_ADDIU ( void ) { - if (RSPOpC.rt != 0) { - RSP_GPR[RSPOpC.rt].UW = RSP_GPR[RSPOpC.rs].UW + (uint32_t)((int16_t)RSPOpC.immediate); - } + RSP_GPR[RSPOpC.rt].UW = RSP_GPR[RSPOpC.rs].UW + (uint32_t)((int16_t)RSPOpC.immediate); } void RSP_Opcode_SLTI (void) { - if (RSPOpC.rt == 0) { return; } if (RSP_GPR[RSPOpC.rs].W < (int16_t)RSPOpC.immediate) { RSP_GPR[RSPOpC.rt].W = 1; } else { @@ -119,7 +114,6 @@ void RSP_Opcode_SLTI (void) { } void RSP_Opcode_SLTIU (void) { - if (RSPOpC.rt == 0) { return; } if (RSP_GPR[RSPOpC.rs].UW < (uint32_t)(int16_t)RSPOpC.immediate) { RSP_GPR[RSPOpC.rt].W = 1; } else { @@ -128,27 +122,19 @@ void RSP_Opcode_SLTIU (void) { } void RSP_Opcode_ANDI ( void ) { - if (RSPOpC.rt != 0) { - RSP_GPR[RSPOpC.rt].W = RSP_GPR[RSPOpC.rs].W & RSPOpC.immediate; - } + RSP_GPR[RSPOpC.rt].W = RSP_GPR[RSPOpC.rs].W & RSPOpC.immediate; } void RSP_Opcode_ORI ( void ) { - if (RSPOpC.rt != 0) { - RSP_GPR[RSPOpC.rt].W = RSP_GPR[RSPOpC.rs].W | RSPOpC.immediate; - } + RSP_GPR[RSPOpC.rt].W = RSP_GPR[RSPOpC.rs].W | RSPOpC.immediate; } void RSP_Opcode_XORI ( void ) { - if (RSPOpC.rt != 0) { - RSP_GPR[RSPOpC.rt].W = RSP_GPR[RSPOpC.rs].W ^ RSPOpC.immediate; - } + RSP_GPR[RSPOpC.rt].W = RSP_GPR[RSPOpC.rs].W ^ RSPOpC.immediate; } void RSP_Opcode_LUI (void) { - if (RSPOpC.rt != 0) { - RSP_GPR[RSPOpC.rt].W = RSPOpC.immediate << 16; - } + RSP_GPR[RSPOpC.rt].W = RSPOpC.immediate << 16; } void RSP_Opcode_COP0 (void) { @@ -213,39 +199,27 @@ void RSP_Opcode_SC2 (void) { /********************** R4300i OpCodes: Special **********************/ void RSP_Special_SLL ( void ) { - if (RSPOpC.rd != 0) { - RSP_GPR[RSPOpC.rd].W = RSP_GPR[RSPOpC.rt].W << RSPOpC.sa; - } + RSP_GPR[RSPOpC.rd].W = RSP_GPR[RSPOpC.rt].W << RSPOpC.sa; } void RSP_Special_SRL ( void ) { - if (RSPOpC.rd != 0) { - RSP_GPR[RSPOpC.rd].UW = RSP_GPR[RSPOpC.rt].UW >> RSPOpC.sa; - } + RSP_GPR[RSPOpC.rd].UW = RSP_GPR[RSPOpC.rt].UW >> RSPOpC.sa; } void RSP_Special_SRA ( void ) { - if (RSPOpC.rd != 0) { - RSP_GPR[RSPOpC.rd].W = RSP_GPR[RSPOpC.rt].W >> RSPOpC.sa; - } + RSP_GPR[RSPOpC.rd].W = RSP_GPR[RSPOpC.rt].W >> RSPOpC.sa; } void RSP_Special_SLLV (void) { - if (RSPOpC.rd != 0) { - RSP_GPR[RSPOpC.rd].W = RSP_GPR[RSPOpC.rt].W << (RSP_GPR[RSPOpC.rs].W & 0x1F); - } + RSP_GPR[RSPOpC.rd].W = RSP_GPR[RSPOpC.rt].W << (RSP_GPR[RSPOpC.rs].W & 0x1F); } void RSP_Special_SRLV (void) { - if (RSPOpC.rd != 0) { - RSP_GPR[RSPOpC.rd].UW = RSP_GPR[RSPOpC.rt].UW >> (RSP_GPR[RSPOpC.rs].W & 0x1F); - } + RSP_GPR[RSPOpC.rd].UW = RSP_GPR[RSPOpC.rt].UW >> (RSP_GPR[RSPOpC.rs].W & 0x1F); } void RSP_Special_SRAV (void) { - if (RSPOpC.rd != 0) { - RSP_GPR[RSPOpC.rd].W = RSP_GPR[RSPOpC.rt].W >> (RSP_GPR[RSPOpC.rs].W & 0x1F); - } + RSP_GPR[RSPOpC.rd].W = RSP_GPR[RSPOpC.rt].W >> (RSP_GPR[RSPOpC.rs].W & 0x1F); } void RSP_Special_JR (void) { @@ -269,55 +243,38 @@ void RSP_Special_BREAK ( void ) { } void RSP_Special_ADD (void) { - if (RSPOpC.rd != 0) { - RSP_GPR[RSPOpC.rd].W = RSP_GPR[RSPOpC.rs].W + RSP_GPR[RSPOpC.rt].W; - } + RSP_GPR[RSPOpC.rd].W = RSP_GPR[RSPOpC.rs].W + RSP_GPR[RSPOpC.rt].W; } void RSP_Special_ADDU (void) { - if (RSPOpC.rd != 0) { - RSP_GPR[RSPOpC.rd].UW = RSP_GPR[RSPOpC.rs].UW + RSP_GPR[RSPOpC.rt].UW; - } + RSP_GPR[RSPOpC.rd].UW = RSP_GPR[RSPOpC.rs].UW + RSP_GPR[RSPOpC.rt].UW; } void RSP_Special_SUB (void) { - if (RSPOpC.rd != 0) { - RSP_GPR[RSPOpC.rd].W = RSP_GPR[RSPOpC.rs].W - RSP_GPR[RSPOpC.rt].W; - } + RSP_GPR[RSPOpC.rd].W = RSP_GPR[RSPOpC.rs].W - RSP_GPR[RSPOpC.rt].W; } void RSP_Special_SUBU (void) { - if (RSPOpC.rd != 0) { - RSP_GPR[RSPOpC.rd].UW = RSP_GPR[RSPOpC.rs].UW - RSP_GPR[RSPOpC.rt].UW; - } + RSP_GPR[RSPOpC.rd].UW = RSP_GPR[RSPOpC.rs].UW - RSP_GPR[RSPOpC.rt].UW; } void RSP_Special_AND (void) { - if (RSPOpC.rd != 0) { - RSP_GPR[RSPOpC.rd].UW = RSP_GPR[RSPOpC.rs].UW & RSP_GPR[RSPOpC.rt].UW; - } + RSP_GPR[RSPOpC.rd].UW = RSP_GPR[RSPOpC.rs].UW & RSP_GPR[RSPOpC.rt].UW; } void RSP_Special_OR (void) { - if (RSPOpC.rd != 0) { - RSP_GPR[RSPOpC.rd].UW = RSP_GPR[RSPOpC.rs].UW | RSP_GPR[RSPOpC.rt].UW; - } + RSP_GPR[RSPOpC.rd].UW = RSP_GPR[RSPOpC.rs].UW | RSP_GPR[RSPOpC.rt].UW; } void RSP_Special_XOR (void) { - if (RSPOpC.rd != 0) { - RSP_GPR[RSPOpC.rd].UW = RSP_GPR[RSPOpC.rs].UW ^ RSP_GPR[RSPOpC.rt].UW; - } + RSP_GPR[RSPOpC.rd].UW = RSP_GPR[RSPOpC.rs].UW ^ RSP_GPR[RSPOpC.rt].UW; } void RSP_Special_NOR (void) { - if (RSPOpC.rd != 0) { - RSP_GPR[RSPOpC.rd].UW = ~(RSP_GPR[RSPOpC.rs].UW | RSP_GPR[RSPOpC.rt].UW); - } + RSP_GPR[RSPOpC.rd].UW = ~(RSP_GPR[RSPOpC.rs].UW | RSP_GPR[RSPOpC.rt].UW); } void RSP_Special_SLT (void) { - if (RSPOpC.rd == 0) { return; } if (RSP_GPR[RSPOpC.rs].W < RSP_GPR[RSPOpC.rt].W) { RSP_GPR[RSPOpC.rd].UW = 1; } else { @@ -326,7 +283,6 @@ void RSP_Special_SLT (void) { } void RSP_Special_SLTU (void) { - if (RSPOpC.rd == 0) { return; } if (RSP_GPR[RSPOpC.rs].UW < RSP_GPR[RSPOpC.rt].UW) { RSP_GPR[RSPOpC.rd].UW = 1; } else {