From 10260dbdc811aec0f7cf064e75654ebd46090f9a Mon Sep 17 00:00:00 2001 From: LegendOfDragoon Date: Mon, 22 Aug 2016 12:54:24 -0700 Subject: [PATCH 01/10] Optimize SLTI in RSP Recompiler Mia Hamm benefits from this optimization. --- Source/RSP/Recompiler Ops.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/Source/RSP/Recompiler Ops.c b/Source/RSP/Recompiler Ops.c index 4bbd066da..c5cbda3ef 100644 --- a/Source/RSP/Recompiler Ops.c +++ b/Source/RSP/Recompiler Ops.c @@ -517,9 +517,17 @@ void Compile_SLTI ( void ) { 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); + if (Immediate == 0) + { + MoveVariableToX86reg(&RSP_GPR[RSPOpC.rs].UW, GPR_Name(RSPOpC.rs), x86_ECX); + ShiftRightUnsignImmed(x86_ECX, 31); + } + else + { + 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)); } From c239d3b74ba618c8a3437872fd0a89a8d0fa5796 Mon Sep 17 00:00:00 2001 From: LegendOfDragoon Date: Mon, 22 Aug 2016 13:12:34 -0700 Subject: [PATCH 02/10] Optimize ANDI in RSP Recompiler Seems to be use often enough. --- Source/RSP/Recompiler Ops.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Source/RSP/Recompiler Ops.c b/Source/RSP/Recompiler Ops.c index c5cbda3ef..34166b5dd 100644 --- a/Source/RSP/Recompiler Ops.c +++ b/Source/RSP/Recompiler Ops.c @@ -563,6 +563,9 @@ void Compile_ANDI ( void ) { AndConstToVariable(Immediate, &RSP_GPR[RSPOpC.rt].UW, GPR_Name(RSPOpC.rt)); } else if (RSPOpC.rs == 0) { MoveConstToVariable(0, &RSP_GPR[RSPOpC.rt].UW, GPR_Name(RSPOpC.rt)); + } else if (Immediate == 0xFFFF) { + MoveZxVariableToX86reg(&RSP_GPR[RSPOpC.rs].UW, GPR_Name(RSPOpC.rs), x86_EAX); + MoveX86regToVariable(x86_EAX, &RSP_GPR[RSPOpC.rt].UW, GPR_Name(RSPOpC.rt)); } else { MoveVariableToX86reg(&RSP_GPR[RSPOpC.rs].UW, GPR_Name(RSPOpC.rs), x86_EAX); AndConstToX86Reg(x86_EAX, Immediate); From 7f468bd939a806e25f3c8462dc76fc4331b62b9e Mon Sep 17 00:00:00 2001 From: LegendOfDragoon Date: Mon, 22 Aug 2016 16:05:56 -0700 Subject: [PATCH 03/10] Implement MoveConstByteToN64Mem --- Source/RSP/X86.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/Source/RSP/X86.c b/Source/RSP/X86.c index c85ad3d1f..025be122a 100644 --- a/Source/RSP/X86.c +++ b/Source/RSP/X86.c @@ -1154,6 +1154,28 @@ void LeaSourceAndOffset(int x86DestReg, int x86SourceReg, size_t offset) { } } +void MoveConstByteToN64Mem(BYTE Const, int AddrReg) { + WORD x86Command = 0; + + CPU_Message(" mov byte ptr [%s+Dmem], %Xh", x86_Name(AddrReg), Const); + switch (AddrReg) { + case x86_EAX: x86Command = 0x80C6; break; + case x86_EBX: x86Command = 0x83C6; break; + case x86_ECX: x86Command = 0x81C6; break; + case x86_EDX: x86Command = 0x82C6; break; + case x86_ESI: x86Command = 0x86C6; break; + case x86_EDI: x86Command = 0x87C6; break; + case x86_ESP: x86Command = 0x84C6; break; + case x86_EBP: x86Command = 0x85C6; break; + default: + DisplayError("MoveConstByteToN64Mem\nUnknown x86 Register"); + } + + PUTDST16(RecompPos, x86Command); + PUTDST32(RecompPos, RSPInfo.DMEM); + PUTDST8(RecompPos, Const); +} + void MoveConstByteToVariable (BYTE Const,void *Variable, char *VariableName) { CPU_Message(" mov byte ptr [%s], %Xh",VariableName,Const); PUTDST16(RecompPos,0x05C6); From 6e99abb50ad6cb89f23ff62be6b5131b9cdc121d Mon Sep 17 00:00:00 2001 From: LegendOfDragoon Date: Mon, 22 Aug 2016 16:09:37 -0700 Subject: [PATCH 04/10] Optimize SB in RSP Recompiler --- Source/RSP/Recompiler Ops.c | 38 +++++++++++++++++++++++++++++++------ 1 file changed, 32 insertions(+), 6 deletions(-) diff --git a/Source/RSP/Recompiler Ops.c b/Source/RSP/Recompiler Ops.c index 34166b5dd..537b6e243 100644 --- a/Source/RSP/Recompiler Ops.c +++ b/Source/RSP/Recompiler Ops.c @@ -921,14 +921,40 @@ void Compile_SB ( void ) { CPU_Message(" %X %s",CompilePC,RSPOpcodeName(RSPOpC.Hex,CompilePC)); - MoveVariableToX86reg(&RSP_GPR[RSPOpC.base].UW, GPR_Name(RSPOpC.base), x86_EBX); - MoveVariableToX86regByte(&RSP_GPR[RSPOpC.rt].UW, GPR_Name(RSPOpC.rt), x86_EAX); + if (IsRegConst(RSPOpC.base) == TRUE) { + char Address[32]; + DWORD Addr = (MipsRegConst(RSPOpC.base) + Offset) ^ 3; + Addr &= 0xfff; + sprintf(Address, "Dmem + %Xh", Addr); - if (Offset != 0) AddConstToX86Reg(x86_EBX, Offset); - XorConstToX86Reg(x86_EBX, 3); - AndConstToX86Reg(x86_EBX, 0x0fff); + if (IsRegConst(RSPOpC.rt) == TRUE) { + MoveConstByteToVariable(MipsRegConst(RSPOpC.rt), RSPInfo.DMEM + Addr, Address); + return; + } else { + MoveVariableToX86regByte(&RSP_GPR[RSPOpC.rt].UW, GPR_Name(RSPOpC.rt), x86_EAX); + MoveX86regByteToVariable(x86_EAX, RSPInfo.DMEM + Addr, Address); + return; + } + } - MoveX86regByteToN64Mem(x86_EAX, x86_EBX); + if (IsRegConst(RSPOpC.rt) == TRUE) { + MoveVariableToX86reg(&RSP_GPR[RSPOpC.base].UW, GPR_Name(RSPOpC.base), x86_EBX); + + if (Offset != 0) AddConstToX86Reg(x86_EBX, Offset); + XorConstToX86Reg(x86_EBX, 3); + AndConstToX86Reg(x86_EBX, 0x0fff); + + MoveConstByteToN64Mem(MipsRegConst(RSPOpC.rt), x86_EBX); + } else { + MoveVariableToX86reg(&RSP_GPR[RSPOpC.base].UW, GPR_Name(RSPOpC.base), x86_EBX); + MoveVariableToX86regByte(&RSP_GPR[RSPOpC.rt].UW, GPR_Name(RSPOpC.rt), x86_EAX); + + if (Offset != 0) AddConstToX86Reg(x86_EBX, Offset); + XorConstToX86Reg(x86_EBX, 3); + AndConstToX86Reg(x86_EBX, 0x0fff); + + MoveX86regByteToN64Mem(x86_EAX, x86_EBX); + } } void Compile_SH ( void ) { From 22ae106c3a79e14c6a6f00214ddd9b83ec0f003d Mon Sep 17 00:00:00 2001 From: LegendOfDragoon Date: Mon, 22 Aug 2016 16:26:27 -0700 Subject: [PATCH 05/10] Implement MoveConstHalfToN64Mem --- Source/RSP/X86.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/Source/RSP/X86.c b/Source/RSP/X86.c index 025be122a..9589b9b5e 100644 --- a/Source/RSP/X86.c +++ b/Source/RSP/X86.c @@ -1176,6 +1176,29 @@ void MoveConstByteToN64Mem(BYTE Const, int AddrReg) { PUTDST8(RecompPos, Const); } +void MoveConstHalfToN64Mem(BYTE Const, int AddrReg) { + BYTE x86Command = 0; + + CPU_Message(" mov word ptr [%s+Dmem], %Xh", x86_Name(AddrReg), Const); + PUTDST16(RecompPos, 0xC766); + switch (AddrReg) { + case x86_EAX: x86Command = 0x80; break; + case x86_EBX: x86Command = 0x83; break; + case x86_ECX: x86Command = 0x81; break; + case x86_EDX: x86Command = 0x82; break; + case x86_ESI: x86Command = 0x86; break; + case x86_EDI: x86Command = 0x87; break; + case x86_ESP: x86Command = 0x84; break; + case x86_EBP: x86Command = 0x85; break; + default: + DisplayError("MoveConstHalfToN64Mem\nUnknown x86 Register"); + } + + PUTDST8(RecompPos, x86Command); + PUTDST32(RecompPos, RSPInfo.DMEM); + PUTDST8(RecompPos, Const); +} + void MoveConstByteToVariable (BYTE Const,void *Variable, char *VariableName) { CPU_Message(" mov byte ptr [%s], %Xh",VariableName,Const); PUTDST16(RecompPos,0x05C6); From d7eba5bde0c27314cfdb9ca845dcb88921817177 Mon Sep 17 00:00:00 2001 From: LegendOfDragoon Date: Mon, 22 Aug 2016 19:57:27 -0700 Subject: [PATCH 06/10] Optimize SH in RSP Recompiler --- Source/RSP/Recompiler Ops.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/Source/RSP/Recompiler Ops.c b/Source/RSP/Recompiler Ops.c index 537b6e243..9ba0d2e04 100644 --- a/Source/RSP/Recompiler Ops.c +++ b/Source/RSP/Recompiler Ops.c @@ -978,8 +978,12 @@ void Compile_SH ( void ) { } else { char Address[32]; sprintf(Address, "Dmem + %Xh", Addr); - MoveVariableToX86regHalf(&RSP_GPR[RSPOpC.rt].UW, GPR_Name(RSPOpC.rt), x86_EAX); - MoveX86regHalfToVariable(x86_EAX, RSPInfo.DMEM + Addr, Address); + if (IsRegConst(RSPOpC.rt) == TRUE) { + MoveConstHalfToVariable(MipsRegConst(RSPOpC.rt), RSPInfo.DMEM + Addr, Address); + } else { + MoveVariableToX86regHalf(&RSP_GPR[RSPOpC.rt].UW, GPR_Name(RSPOpC.rt), x86_EAX); + MoveX86regHalfToVariable(x86_EAX, RSPInfo.DMEM + Addr, Address); + } return; } } @@ -1005,8 +1009,12 @@ void Compile_SH ( void ) { XorConstToX86Reg(x86_EBX, 2); AndConstToX86Reg(x86_EBX, 0x0fff); - MoveVariableToX86regHalf(&RSP_GPR[RSPOpC.rt].UW, GPR_Name(RSPOpC.rt), x86_EAX); - MoveX86regHalfToN64Mem(x86_EAX, x86_EBX); + if (IsRegConst(RSPOpC.rt) == TRUE) { + MoveConstHalfToN64Mem(MipsRegConst(RSPOpC.rt), x86_EBX); + } else { + MoveVariableToX86regHalf(&RSP_GPR[RSPOpC.rt].UW, GPR_Name(RSPOpC.rt), x86_EAX); + MoveX86regHalfToN64Mem(x86_EAX, x86_EBX); + } CPU_Message(" Done:"); x86_SetBranch32b(Jump[1], RecompPos); From 3d8482f40219599e8d45cda01d60aa1ade92c10c Mon Sep 17 00:00:00 2001 From: LegendOfDragoon Date: Tue, 23 Aug 2016 01:15:18 -0700 Subject: [PATCH 07/10] Implement MoveConstToN64Mem Also fix typo in MoveConstHalfToN64Mem --- Source/RSP/X86.c | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/Source/RSP/X86.c b/Source/RSP/X86.c index 9589b9b5e..6be24a569 100644 --- a/Source/RSP/X86.c +++ b/Source/RSP/X86.c @@ -1176,7 +1176,7 @@ void MoveConstByteToN64Mem(BYTE Const, int AddrReg) { PUTDST8(RecompPos, Const); } -void MoveConstHalfToN64Mem(BYTE Const, int AddrReg) { +void MoveConstHalfToN64Mem(WORD Const, int AddrReg) { BYTE x86Command = 0; CPU_Message(" mov word ptr [%s+Dmem], %Xh", x86_Name(AddrReg), Const); @@ -1214,6 +1214,28 @@ void MoveConstHalfToVariable (WORD Const,void *Variable, char *VariableName) { PUTDST16(RecompPos,Const); } +void MoveConstToN64Mem(DWORD Const, int AddrReg) { + WORD x86Command = 0; + + CPU_Message(" mov dword ptr [%s+Dmem], %Xh", x86_Name(AddrReg), Const); + switch (AddrReg) { + case x86_EAX: x86Command = 0x80C7; break; + case x86_EBX: x86Command = 0x83C7; break; + case x86_ECX: x86Command = 0x81C7; break; + case x86_EDX: x86Command = 0x82C7; break; + case x86_ESI: x86Command = 0x86C7; break; + case x86_EDI: x86Command = 0x87C7; break; + case x86_ESP: x86Command = 0x84C7; break; + case x86_EBP: x86Command = 0x85C7; break; + default: + DisplayError("MoveConstToN64Mem\nUnknown x86 Register"); + } + + PUTDST16(RecompPos, x86Command); + PUTDST32(RecompPos, RSPInfo.DMEM); + PUTDST32(RecompPos, Const); +} + void MoveConstToVariable (DWORD Const,void *Variable, char *VariableName) { CPU_Message(" mov dword ptr [%s], %Xh",VariableName,Const); PUTDST16(RecompPos,0x05C7); From 7a5a0731bd9a89521fb6c65a7eae9d1e36e40e1d Mon Sep 17 00:00:00 2001 From: LegendOfDragoon Date: Tue, 23 Aug 2016 01:17:01 -0700 Subject: [PATCH 08/10] Optimize SW in RSP Recompiler --- Source/RSP/Recompiler Ops.c | 37 +++++++++++++++++++++++++++++-------- 1 file changed, 29 insertions(+), 8 deletions(-) diff --git a/Source/RSP/Recompiler Ops.c b/Source/RSP/Recompiler Ops.c index 9ba0d2e04..0523d5947 100644 --- a/Source/RSP/Recompiler Ops.c +++ b/Source/RSP/Recompiler Ops.c @@ -1031,17 +1031,38 @@ void Compile_SW ( void ) { CPU_Message(" %X %s",CompilePC,RSPOpcodeName(RSPOpC.Hex,CompilePC)); if (IsRegConst(RSPOpC.base) == TRUE) { + char Address[32]; DWORD Addr = (MipsRegConst(RSPOpC.base) + Offset) & 0xfff; if ((Addr & 3) != 0) { - CompilerWarning("Unaligned SW at constant address PC = %04X", CompilePC); - Cheat_r4300iOpcodeNoMessage(RSP_Opcode_SW,"RSP_Opcode_SW"); + if (Addr > 0xFFC) { + DisplayError("hmmmm.... Problem with:\nRSP_SW_DMEM"); + return; + } + if (IsRegConst(RSPOpC.rt) == TRUE) { + DWORD Value = MipsRegConst(RSPOpC.rt); + sprintf(Address, "Dmem + %Xh", (Addr + 0) ^ 3); + MoveConstByteToVariable((Value >> 24) & 0xFF, RSPInfo.DMEM + ((Addr + 0) ^ 3), Address); + sprintf(Address, "Dmem + %Xh", (Addr + 1) ^ 3); + MoveConstByteToVariable((Value >> 16) & 0xFF, RSPInfo.DMEM + ((Addr + 1) ^ 3), Address); + sprintf(Address, "Dmem + %Xh", (Addr + 2) ^ 3); + MoveConstByteToVariable((Value >> 8) & 0xFF, RSPInfo.DMEM + ((Addr + 2) ^ 3), Address); + sprintf(Address, "Dmem + %Xh", (Addr + 3) ^ 3); + MoveConstByteToVariable((Value >> 0) & 0xFF, RSPInfo.DMEM + ((Addr + 3) ^ 3), Address); + } else { + CompilerWarning("Unaligned SW at constant address PC = %04X", CompilePC); + Cheat_r4300iOpcodeNoMessage(RSP_Opcode_SW,"RSP_Opcode_SW"); + } return; } else { - char Address[32]; sprintf(Address, "Dmem + %Xh", Addr); - MoveVariableToX86reg(&RSP_GPR[RSPOpC.rt].UW, GPR_Name(RSPOpC.rt), x86_EAX); - MoveX86regToVariable(x86_EAX, RSPInfo.DMEM + Addr, Address); + + if (IsRegConst(RSPOpC.rt) == TRUE) { + MoveConstToVariable(MipsRegConst(RSPOpC.rt), RSPInfo.DMEM + Addr, Address); + } else { + MoveVariableToX86reg(&RSP_GPR[RSPOpC.rt].UW, GPR_Name(RSPOpC.rt), x86_EAX); + MoveX86regToVariable(x86_EAX, RSPInfo.DMEM + Addr, Address); + } return; } } @@ -1088,12 +1109,12 @@ void Compile_SW ( void ) { CompilerToggleBuffer(); - if (RSPOpC.rt == 0) { - XorX86RegToX86Reg(x86_EAX,x86_EAX); + if (IsRegConst(RSPOpC.rt) == TRUE) { + MoveConstToN64Mem(MipsRegConst(RSPOpC.rt), x86_EBX); } else { MoveVariableToX86reg(&RSP_GPR[RSPOpC.rt].UW, GPR_Name(RSPOpC.rt), x86_EAX); + MoveX86regToN64Mem(x86_EAX, x86_EBX); } - MoveX86regToN64Mem(x86_EAX, x86_EBX); CPU_Message(" Done:"); x86_SetBranch32b(Jump[1], RecompPos); From c29bff435349ff89b36f2b757cc065fb2c074cf7 Mon Sep 17 00:00:00 2001 From: LegendOfDragoon Date: Tue, 23 Aug 2016 11:40:24 -0700 Subject: [PATCH 09/10] Fix 2 typos I made in previous commits --- Source/RSP/Recompiler Ops.c | 2 +- Source/RSP/X86.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Source/RSP/Recompiler Ops.c b/Source/RSP/Recompiler Ops.c index 0523d5947..5f1ddc703 100644 --- a/Source/RSP/Recompiler Ops.c +++ b/Source/RSP/Recompiler Ops.c @@ -564,7 +564,7 @@ void Compile_ANDI ( void ) { } else if (RSPOpC.rs == 0) { MoveConstToVariable(0, &RSP_GPR[RSPOpC.rt].UW, GPR_Name(RSPOpC.rt)); } else if (Immediate == 0xFFFF) { - MoveZxVariableToX86reg(&RSP_GPR[RSPOpC.rs].UW, GPR_Name(RSPOpC.rs), x86_EAX); + MoveZxVariableToX86regHalf(&RSP_GPR[RSPOpC.rs].UW, GPR_Name(RSPOpC.rs), x86_EAX); MoveX86regToVariable(x86_EAX, &RSP_GPR[RSPOpC.rt].UW, GPR_Name(RSPOpC.rt)); } else { MoveVariableToX86reg(&RSP_GPR[RSPOpC.rs].UW, GPR_Name(RSPOpC.rs), x86_EAX); diff --git a/Source/RSP/X86.c b/Source/RSP/X86.c index 6be24a569..bf15021b0 100644 --- a/Source/RSP/X86.c +++ b/Source/RSP/X86.c @@ -1196,7 +1196,7 @@ void MoveConstHalfToN64Mem(WORD Const, int AddrReg) { PUTDST8(RecompPos, x86Command); PUTDST32(RecompPos, RSPInfo.DMEM); - PUTDST8(RecompPos, Const); + PUTDST16(RecompPos, Const); } void MoveConstByteToVariable (BYTE Const,void *Variable, char *VariableName) { From 400c466278103bc3d9b4f45c464c24528db485b0 Mon Sep 17 00:00:00 2001 From: LegendOfDragoon Date: Tue, 23 Aug 2016 12:12:55 -0700 Subject: [PATCH 10/10] Improve Compile_Special_SLT It is supposed to skip if rd = 0, not rt. Also optimized the code a bit. --- Source/RSP/Recompiler Ops.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Source/RSP/Recompiler Ops.c b/Source/RSP/Recompiler Ops.c index 5f1ddc703..34b1ba8b4 100644 --- a/Source/RSP/Recompiler Ops.c +++ b/Source/RSP/Recompiler Ops.c @@ -1498,26 +1498,26 @@ void Compile_Special_SLT ( void ) { #endif CPU_Message(" %X %s",CompilePC,RSPOpcodeName(RSPOpC.Hex,CompilePC)); - if (RSPOpC.rt == 0) { return; } + if (RSPOpC.rd == 0) { return; } if (RSPOpC.rt == RSPOpC.rs) { MoveConstToVariable(0, &RSP_GPR[RSPOpC.rd].UW, GPR_Name(RSPOpC.rd)); } else { - XorX86RegToX86Reg(x86_EBX, x86_EBX); if (RSPOpC.rs == 0) { MoveVariableToX86reg(&RSP_GPR[RSPOpC.rt].UW, GPR_Name(RSPOpC.rt), x86_EAX); + XorX86RegToX86Reg(x86_ECX, x86_ECX); CompConstToX86reg(x86_EAX, 0); - Setg(x86_EBX); + Setg(x86_ECX); } else if (RSPOpC.rt == 0) { - MoveVariableToX86reg(&RSP_GPR[RSPOpC.rs].UW, GPR_Name(RSPOpC.rs), x86_EAX); - CompConstToX86reg(x86_EAX, 0); - Setl(x86_EBX); + MoveVariableToX86reg(&RSP_GPR[RSPOpC.rs].UW, GPR_Name(RSPOpC.rs), x86_ECX); + ShiftRightUnsignImmed(x86_ECX, 31); } else { MoveVariableToX86reg(&RSP_GPR[RSPOpC.rs].UW, GPR_Name(RSPOpC.rs), x86_EAX); + XorX86RegToX86Reg(x86_ECX, x86_ECX); CompX86regToVariable(x86_EAX, &RSP_GPR[RSPOpC.rt].UW, GPR_Name(RSPOpC.rt)); - Setl(x86_EBX); + Setl(x86_ECX); } - MoveX86regToVariable(x86_EBX, &RSP_GPR[RSPOpC.rd].UW, GPR_Name(RSPOpC.rd)); + MoveX86regToVariable(x86_ECX, &RSP_GPR[RSPOpC.rd].UW, GPR_Name(RSPOpC.rd)); } }