From 19f34eed4e9791b876e90fb9d71254d404c37951 Mon Sep 17 00:00:00 2001 From: LegendOfDragoon Date: Mon, 7 Sep 2015 11:27:07 -0700 Subject: [PATCH 1/9] Implement SLTI in RSP Recompiler --- Source/RSP/Recompiler Ops.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/Source/RSP/Recompiler Ops.c b/Source/RSP/Recompiler Ops.c index b936c072d..cc72855db 100644 --- a/Source/RSP/Recompiler Ops.c +++ b/Source/RSP/Recompiler Ops.c @@ -481,8 +481,20 @@ void Compile_ADDIU ( void ) { } void Compile_SLTI ( void ) { +#ifndef Compile_Immediates Cheat_r4300iOpcode(RSP_Opcode_SLTI,"RSP_Opcode_SLTI"); +#endif + int Immediate; + + CPU_Message(" %X %s", CompilePC, RSPOpcodeName(RSPOpC.Hex, CompilePC)); + if (RSPOpC.rt == 0) return; + + Immediate = (short)RSPOpC.immediate; + XorX86RegToX86Reg(x86_ECX, x86_ECX); + CompConstToVariable(Immediate, &RSP_GPR[RSPOpC.rs].UW, GPR_Name(RSPOpC.rs)); + Setl(x86_ECX); + MoveX86regToVariable(x86_ECX, &RSP_GPR[RSPOpC.rt].UW, GPR_Name(RSPOpC.rt)); } void Compile_SLTIU ( void ) { From 720d8c8dd77a068b076c5656c041f8e0297b5e79 Mon Sep 17 00:00:00 2001 From: LegendOfDragoon Date: Mon, 7 Sep 2015 11:28:49 -0700 Subject: [PATCH 2/9] Implement SLTIU in RSP Recompiler --- Source/RSP/Recompiler Ops.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/Source/RSP/Recompiler Ops.c b/Source/RSP/Recompiler Ops.c index cc72855db..27ae3cc61 100644 --- a/Source/RSP/Recompiler Ops.c +++ b/Source/RSP/Recompiler Ops.c @@ -498,8 +498,20 @@ void Compile_SLTI ( void ) { } void Compile_SLTIU ( void ) { +#ifndef Compile_Immediates Cheat_r4300iOpcode(RSP_Opcode_SLTIU,"RSP_Opcode_SLTIU"); +#endif + int Immediate; + + CPU_Message(" %X %s", CompilePC, RSPOpcodeName(RSPOpC.Hex, CompilePC)); + if (RSPOpC.rt == 0) return; + + Immediate = (short)RSPOpC.immediate; + XorX86RegToX86Reg(x86_ECX, x86_ECX); + CompConstToVariable(Immediate, &RSP_GPR[RSPOpC.rs].UW, GPR_Name(RSPOpC.rs)); + Setb(x86_ECX); + MoveX86regToVariable(x86_ECX, &RSP_GPR[RSPOpC.rt].UW, GPR_Name(RSPOpC.rt)); } void Compile_ANDI ( void ) { From 2ff2165bd92cb89b8d4e79e356043d57699a0c75 Mon Sep 17 00:00:00 2001 From: LegendOfDragoon Date: Mon, 7 Sep 2015 11:49:37 -0700 Subject: [PATCH 3/9] Optimize ADDI in RSP Recompiler No need to add 0 to a variable. I've seen ADDI V0, V0, 0x0000 in Super Smash Bros audio microcode. --- Source/RSP/Recompiler Ops.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Source/RSP/Recompiler Ops.c b/Source/RSP/Recompiler Ops.c index 27ae3cc61..b46b1a3e4 100644 --- a/Source/RSP/Recompiler Ops.c +++ b/Source/RSP/Recompiler Ops.c @@ -444,7 +444,9 @@ void Compile_ADDI ( void ) { if (RSPOpC.rt == 0) return; if (RSPOpC.rt == RSPOpC.rs) { - AddConstToVariable(Immediate, &RSP_GPR[RSPOpC.rt].UW, GPR_Name(RSPOpC.rt)); + if(Immediate != 0) { + AddConstToVariable(Immediate, &RSP_GPR[RSPOpC.rt].UW, GPR_Name(RSPOpC.rt)); + } } else if (RSPOpC.rs == 0) { MoveConstToVariable(Immediate, &RSP_GPR[RSPOpC.rt].UW, GPR_Name(RSPOpC.rt)); } else if ((IsRegConst(RSPOpC.rs) & 1) != 0) { From 48fcced3bc51fcb6fa1ba8637199989bbcbcfe7e Mon Sep 17 00:00:00 2001 From: LegendOfDragoon Date: Mon, 7 Sep 2015 12:18:28 -0700 Subject: [PATCH 4/9] Optimize ADDIU in RSP Recompiler The second part happens in Hydro Thunder LLE audio. --- Source/RSP/Recompiler Ops.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/Source/RSP/Recompiler Ops.c b/Source/RSP/Recompiler Ops.c index b46b1a3e4..5b17818da 100644 --- a/Source/RSP/Recompiler Ops.c +++ b/Source/RSP/Recompiler Ops.c @@ -472,12 +472,16 @@ void Compile_ADDIU ( void ) { if (RSPOpC.rt == 0) return; if (RSPOpC.rt == RSPOpC.rs) { - AddConstToVariable(Immediate, &RSP_GPR[RSPOpC.rt].UW, GPR_Name(RSPOpC.rt)); + if(Immediate != 0) { + AddConstToVariable(Immediate, &RSP_GPR[RSPOpC.rt].UW, GPR_Name(RSPOpC.rt)); + } } else if (RSPOpC.rs == 0) { MoveConstToVariable(Immediate, &RSP_GPR[RSPOpC.rt].UW, GPR_Name(RSPOpC.rt)); } else { MoveVariableToX86reg(&RSP_GPR[RSPOpC.rs].UW, GPR_Name(RSPOpC.rs), x86_EAX); - AddConstToX86Reg(x86_EAX, Immediate); + if(Immediate != 0) { + AddConstToX86Reg(x86_EAX, Immediate); + } MoveX86regToVariable(x86_EAX, &RSP_GPR[RSPOpC.rt].UW, GPR_Name(RSPOpC.rt)); } } From e9c1c231207720fcea9b45d01f33d17994fb5402 Mon Sep 17 00:00:00 2001 From: LegendOfDragoon Date: Mon, 7 Sep 2015 13:39:41 -0700 Subject: [PATCH 5/9] Implement RegConst in Compile_LB --- Source/RSP/Recompiler Ops.c | 11 +++++++++++ Source/RSP/X86.c | 19 +++++++++++++++++++ Source/RSP/X86.h | 1 + 3 files changed, 31 insertions(+) diff --git a/Source/RSP/Recompiler Ops.c b/Source/RSP/Recompiler Ops.c index 5b17818da..a1803fed0 100644 --- a/Source/RSP/Recompiler Ops.c +++ b/Source/RSP/Recompiler Ops.c @@ -620,6 +620,17 @@ void Compile_LB ( void ) { CPU_Message(" %X %s",CompilePC,RSPOpcodeName(RSPOpC.Hex,CompilePC)); + if (IsRegConst(RSPOpC.base) == TRUE) { + char Address[32]; + DWORD Addr = (MipsRegConst(RSPOpC.base) + Offset) ^ 3; + Addr &= 0xfff; + + sprintf(Address, "Dmem + %Xh", Addr); + MoveSxVariableToX86regByte(RSPInfo.DMEM + Addr, Address, x86_EAX); + MoveX86regToVariable(x86_EAX, &RSP_GPR[RSPOpC.rt].UW, GPR_Name(RSPOpC.rt)); + return; + } + MoveVariableToX86reg(&RSP_GPR[RSPOpC.base].UW, GPR_Name(RSPOpC.base), x86_EBX); if (Offset != 0) AddConstToX86Reg(x86_EBX, Offset); XorConstToX86Reg(x86_EBX, 3); diff --git a/Source/RSP/X86.c b/Source/RSP/X86.c index b27d714d3..6344d4a01 100644 --- a/Source/RSP/X86.c +++ b/Source/RSP/X86.c @@ -1824,6 +1824,25 @@ void MoveSxX86RegPtrDispToX86RegHalf(int AddrReg, BYTE Disp, int Destination) { PUTDST8(RecompPos, Disp); } +void MoveSxVariableToX86regByte(void *Variable, char *VariableName, int x86reg) { + CPU_Message(" movsx %s, byte ptr [%s]",x86_Name(x86reg),VariableName); + + PUTDST16(RecompPos, 0xbe0f); + + switch (x86reg) { + case x86_EAX: PUTDST8(RecompPos,0x05); break; + case x86_EBX: PUTDST8(RecompPos,0x1D); break; + case x86_ECX: PUTDST8(RecompPos,0x0D); break; + case x86_EDX: PUTDST8(RecompPos,0x15); break; + case x86_ESI: PUTDST8(RecompPos,0x35); break; + case x86_EDI: PUTDST8(RecompPos,0x3D); break; + case x86_ESP: PUTDST8(RecompPos,0x25); break; + case x86_EBP: PUTDST8(RecompPos,0x2D); break; + default: DisplayError("MoveSxVariableToX86regByte\nUnknown x86 Register"); + } + PUTDST32(RecompPos,Variable); +} + void MoveSxVariableToX86regHalf(void *Variable, char *VariableName, int x86reg) { CPU_Message(" movsx %s, word ptr [%s]",x86_Name(x86reg),VariableName); diff --git a/Source/RSP/X86.h b/Source/RSP/X86.h index 9ce5950ae..8378073f2 100644 --- a/Source/RSP/X86.h +++ b/Source/RSP/X86.h @@ -141,6 +141,7 @@ void MoveSxX86RegHalfToX86Reg ( int Source, int Destination ); void MoveSxX86RegPtrDispToX86RegHalf( int AddrReg, BYTE Disp, int Destination ); void MoveSxN64MemToX86regByte ( int x86reg, int AddrReg ); void MoveSxN64MemToX86regHalf ( int x86reg, int AddrReg ); +void MoveSxVariableToX86regByte ( void *Variable, char *VariableName, int x86reg ); void MoveSxVariableToX86regHalf ( void *Variable, char *VariableName, int x86reg ); void MoveZxX86RegHalfToX86Reg ( int Source, int Destination ); void MoveZxX86RegPtrDispToX86RegHalf( int AddrReg, BYTE Disp, int Destination ); From 48baf1df7cda41c775c8ce9462322ce156647918 Mon Sep 17 00:00:00 2001 From: LegendOfDragoon Date: Mon, 7 Sep 2015 13:48:51 -0700 Subject: [PATCH 6/9] Optimize LH in RSP Recompiler Star Wars Battle For Naboo LLE graphics uses unaligned LH --- Source/RSP/Recompiler Ops.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/Source/RSP/Recompiler Ops.c b/Source/RSP/Recompiler Ops.c index a1803fed0..9701136af 100644 --- a/Source/RSP/Recompiler Ops.c +++ b/Source/RSP/Recompiler Ops.c @@ -655,8 +655,15 @@ void Compile_LH ( void ) { Addr &= 0xfff; if ((Addr & 1) != 0) { - CompilerWarning("Unaligned LH at constant address PC = %04X", CompilePC); - Cheat_r4300iOpcodeNoMessage(RSP_Opcode_LH,"RSP_Opcode_LH"); + if ((Addr & 2) == 0) { + CompilerWarning("Unaligned LH at constant address PC = %04X", CompilePC); + Cheat_r4300iOpcodeNoMessage(RSP_Opcode_LH,"RSP_Opcode_LH"); + } else { + char Address[32]; + sprintf(Address, "Dmem + %Xh", Addr); + MoveSxVariableToX86regHalf(RSPInfo.DMEM + (Addr ^ 2), Address, x86_EAX); + MoveX86regToVariable(x86_EAX, &RSP_GPR[RSPOpC.rt].UW, GPR_Name(RSPOpC.rt)); + } } else { char Address[32]; sprintf(Address, "Dmem + %Xh", Addr); From 237b21a5967fb31990d2400e90092b437e09b4b8 Mon Sep 17 00:00:00 2001 From: LegendOfDragoon Date: Mon, 7 Sep 2015 14:36:42 -0700 Subject: [PATCH 7/9] Optimize LW in RSP Recompiler --- Source/RSP/Recompiler Ops.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/Source/RSP/Recompiler Ops.c b/Source/RSP/Recompiler Ops.c index 9701136af..157fc6e2d 100644 --- a/Source/RSP/Recompiler Ops.c +++ b/Source/RSP/Recompiler Ops.c @@ -715,9 +715,18 @@ void Compile_LW ( void ) { if (IsRegConst(RSPOpC.base) == TRUE) { DWORD Addr = (MipsRegConst(RSPOpC.base) + Offset) & 0xfff; - if ((Addr & 3) != 0) { + if ((Addr & 1) != 0) { CompilerWarning("Unaligned LW at constant address PC = %04X", CompilePC); Cheat_r4300iOpcodeNoMessage(RSP_Opcode_LW,"RSP_Opcode_LW"); + } else if ((Addr & 2) != 0) { + char Address[32]; + sprintf(Address, "Dmem + %Xh", Addr - 2); + MoveVariableToX86regHalf(RSPInfo.DMEM + Addr - 2, Address, x86_EAX); + sprintf(Address, "Dmem + %Xh", Addr); + MoveVariableToX86regHalf(RSPInfo.DMEM + Addr + 4, Address, x86_ECX); + + MoveX86regHalfToVariable(x86_EAX, &RSP_GPR[RSPOpC.rt].UHW[1], GPR_Name(RSPOpC.rt)); + MoveX86regHalfToVariable(x86_ECX, &RSP_GPR[RSPOpC.rt].UHW[0], GPR_Name(RSPOpC.rt)); } else { char Address[32]; sprintf(Address, "Dmem + %Xh", Addr); From e0bd5442e4a0c0ed07dd88096015ac4234031b2e Mon Sep 17 00:00:00 2001 From: LegendOfDragoon Date: Mon, 7 Sep 2015 15:05:26 -0700 Subject: [PATCH 8/9] Implement RegConst in Compile_LBU --- Source/RSP/Recompiler Ops.c | 11 +++++++++++ Source/RSP/X86.c | 19 +++++++++++++++++++ Source/RSP/X86.h | 1 + 3 files changed, 31 insertions(+) diff --git a/Source/RSP/Recompiler Ops.c b/Source/RSP/Recompiler Ops.c index 157fc6e2d..7e3eec757 100644 --- a/Source/RSP/Recompiler Ops.c +++ b/Source/RSP/Recompiler Ops.c @@ -787,6 +787,17 @@ void Compile_LBU ( void ) { CPU_Message(" %X %s",CompilePC,RSPOpcodeName(RSPOpC.Hex,CompilePC)); + if (IsRegConst(RSPOpC.base) == TRUE) { + char Address[32]; + DWORD Addr = (MipsRegConst(RSPOpC.base) + Offset) ^ 3; + Addr &= 0xfff; + + sprintf(Address, "Dmem + %Xh", Addr); + MoveZxVariableToX86regByte(RSPInfo.DMEM + Addr, Address, x86_EAX); + MoveX86regToVariable(x86_EAX, &RSP_GPR[RSPOpC.rt].UW, GPR_Name(RSPOpC.rt)); + return; + } + MoveVariableToX86reg(&RSP_GPR[RSPOpC.base].UW, GPR_Name(RSPOpC.base), x86_EBX); XorX86RegToX86Reg(x86_EAX, x86_EAX); diff --git a/Source/RSP/X86.c b/Source/RSP/X86.c index 6344d4a01..4716e359a 100644 --- a/Source/RSP/X86.c +++ b/Source/RSP/X86.c @@ -1982,6 +1982,25 @@ void MoveZxX86RegPtrDispToX86RegHalf(int AddrReg, BYTE Disp, int Destination) { PUTDST8(RecompPos, Disp); } +void MoveZxVariableToX86regByte(void *Variable, char *VariableName, int x86reg) { + CPU_Message(" movzx %s, byte ptr [%s]",x86_Name(x86reg),VariableName); + + PUTDST16(RecompPos, 0xb60f); + + switch (x86reg) { + case x86_EAX: PUTDST8(RecompPos,0x05); break; + case x86_EBX: PUTDST8(RecompPos,0x1D); break; + case x86_ECX: PUTDST8(RecompPos,0x0D); break; + case x86_EDX: PUTDST8(RecompPos,0x15); break; + case x86_ESI: PUTDST8(RecompPos,0x35); break; + case x86_EDI: PUTDST8(RecompPos,0x3D); break; + case x86_ESP: PUTDST8(RecompPos,0x25); break; + case x86_EBP: PUTDST8(RecompPos,0x2D); break; + default: DisplayError("MoveZxVariableToX86regByte\nUnknown x86 Register"); + } + PUTDST32(RecompPos,Variable); +} + void MoveZxVariableToX86regHalf(void *Variable, char *VariableName, int x86reg) { CPU_Message(" movzx %s, word ptr [%s]",x86_Name(x86reg),VariableName); diff --git a/Source/RSP/X86.h b/Source/RSP/X86.h index 8378073f2..4a260507e 100644 --- a/Source/RSP/X86.h +++ b/Source/RSP/X86.h @@ -147,6 +147,7 @@ void MoveZxX86RegHalfToX86Reg ( int Source, int Destination ); void MoveZxX86RegPtrDispToX86RegHalf( int AddrReg, BYTE Disp, int Destination ); void MoveZxN64MemToX86regByte ( int x86reg, int AddrReg ); void MoveZxN64MemToX86regHalf ( int x86reg, int AddrReg ); +void MoveZxVariableToX86regByte ( void *Variable, char *VariableName, int x86reg ); void MoveZxVariableToX86regHalf ( void *Variable, char *VariableName, int x86reg ); void MulX86reg ( int x86reg ); void NegateX86reg ( int x86reg ); From 67d2fc95a3f8169928e55d2d6441d0142c5bf01a Mon Sep 17 00:00:00 2001 From: LegendOfDragoon Date: Mon, 7 Sep 2015 15:10:19 -0700 Subject: [PATCH 9/9] Optimize LHU in RSP Recompiler --- Source/RSP/Recompiler Ops.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/Source/RSP/Recompiler Ops.c b/Source/RSP/Recompiler Ops.c index 7e3eec757..e8b4107b1 100644 --- a/Source/RSP/Recompiler Ops.c +++ b/Source/RSP/Recompiler Ops.c @@ -824,8 +824,15 @@ void Compile_LHU ( void ) { Addr &= 0xfff; if ((Addr & 1) != 0) { - CompilerWarning("Unaligned LHU at constant address PC = %04X", CompilePC); - Cheat_r4300iOpcodeNoMessage(RSP_Opcode_LHU,"RSP_Opcode_LHU"); + if ((Addr & 2) == 0) { + CompilerWarning("Unaligned LHU at constant address PC = %04X", CompilePC); + Cheat_r4300iOpcodeNoMessage(RSP_Opcode_LHU, "RSP_Opcode_LHU"); + } else { + char Address[32]; + sprintf(Address, "Dmem + %Xh", Addr); + MoveZxVariableToX86regHalf(RSPInfo.DMEM + (Addr ^ 2), Address, x86_ECX); + MoveX86regToVariable(x86_ECX, &RSP_GPR[RSPOpC.rt].UW, GPR_Name(RSPOpC.rt)); + } return; } else { char Address[32];