From dc5257364499064e2d337d653d0fac79da12087c Mon Sep 17 00:00:00 2001 From: LegendOfDragoon Date: Fri, 25 Sep 2015 03:50:47 -0700 Subject: [PATCH 1/5] Implement x86 instruction Bsr --- Source/RSP/X86.c | 30 ++++++++++++++++++++++++++++++ Source/RSP/X86.h | 1 + 2 files changed, 31 insertions(+) diff --git a/Source/RSP/X86.c b/Source/RSP/X86.c index 4716e359a..3abdf6c0e 100644 --- a/Source/RSP/X86.c +++ b/Source/RSP/X86.c @@ -427,6 +427,36 @@ void X86BreakPoint (LPCSTR FileName, int LineNumber) { PUTDST8(RecompPos,0xCC); } +void BsrX86RegToX86Reg(int Destination, int Source) { + BYTE x86Command = 0; + + CPU_Message(" bsr %s, %s", x86_Name(Destination), x86_Name(Source)); + + PUTDST16(RecompPos, 0xBD0F); + switch (Source) { + case x86_EAX: x86Command = 0x00; break; + case x86_EBX: x86Command = 0x03; break; + case x86_ECX: x86Command = 0x01; break; + case x86_EDX: x86Command = 0x02; break; + case x86_ESI: x86Command = 0x06; break; + case x86_EDI: x86Command = 0x07; break; + case x86_ESP: x86Command = 0x04; break; + case x86_EBP: x86Command = 0x05; break; + } + + switch (Destination) { + case x86_EAX: x86Command += 0xC0; break; + case x86_EBX: x86Command += 0xD8; break; + case x86_ECX: x86Command += 0xC8; break; + case x86_EDX: x86Command += 0xD0; break; + case x86_ESI: x86Command += 0xF0; break; + case x86_EDI: x86Command += 0xF8; break; + case x86_ESP: x86Command += 0xE0; break; + case x86_EBP: x86Command += 0xE8; break; + } + PUTDST8(RecompPos, x86Command); +} + void Call_Direct(void * FunctAddress, char * FunctName) { CPU_Message(" call offset %s",FunctName); PUTDST8(RecompPos,0xE8); diff --git a/Source/RSP/X86.h b/Source/RSP/X86.h index 4a260507e..6723fe11b 100644 --- a/Source/RSP/X86.h +++ b/Source/RSP/X86.h @@ -59,6 +59,7 @@ void AndX86RegToVariable ( void * Variable, char * VariableName, int x86Reg ); void AndX86RegToX86Reg ( int Destination, int Source ); void AndX86RegHalfToX86RegHalf ( int Destination, int Source ); void X86BreakPoint ( LPCSTR FileName, int LineNumber ); +void BsrX86RegToX86Reg ( int Destination, int Source ); void Call_Direct ( void * FunctAddress, char * FunctName ); void Call_Indirect ( void * FunctAddress, char * FunctName ); void CondMoveEqual ( int Destination, int Source ); From 97857ee3cdcef75f4fa4a8d612c668d299c67de7 Mon Sep 17 00:00:00 2001 From: LegendOfDragoon Date: Fri, 25 Sep 2015 04:11:49 -0700 Subject: [PATCH 2/5] Implement VRCP in RSP Recompiler --- Source/RSP/Recompiler Ops.c | 63 +++++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) diff --git a/Source/RSP/Recompiler Ops.c b/Source/RSP/Recompiler Ops.c index 86e8fe43f..4982355e8 100644 --- a/Source/RSP/Recompiler Ops.c +++ b/Source/RSP/Recompiler Ops.c @@ -74,6 +74,7 @@ DWORD BranchCompare = 0; # define CompileVmadn /* Verified 12/17/2000 - Jabo */ #endif #ifdef RSP_VectorMisc +# define CompileVrcp # define CompileVrsqh # define CompileVrcph # define CompileVsaw /* Verified 12/17/2000 - Jabo */ @@ -4478,7 +4479,69 @@ void Compile_Vector_VNXOR ( void ) { } void Compile_Vector_VRCP ( void ) { + char Reg[256]; + int count, el, last; + BOOL bWriteToAccum = WriteToAccum(Low16BitAccum, CompilePC); + DWORD *end = NULL; + +#ifndef CompileVrcp Cheat_r4300iOpcode(RSP_Vector_VRCP,"RSP_Vector_VRCP"); + return; +#endif + + CPU_Message(" %X %s", CompilePC, RSPOpcodeName(RSPOpC.Hex, CompilePC)); + + el = EleSpec[RSPOpC.rs].B[(RSPOpC.rd & 0x7)]; + sprintf(Reg, "RSP_Vect[%i].UHW[%i]", RSPOpC.rt, el); + MoveSxVariableToX86regHalf(&RSP_Vect[RSPOpC.rt].HW[el], Reg, x86_ESI); + MoveConstToX86reg(0x7FFFFFFF, x86_EAX); + TestX86RegToX86Reg(x86_ESI, x86_ESI); + MoveX86RegToX86Reg(x86_ESI, x86_EDI); + JeLabel32("Done", 0); + end = (DWORD*)(RecompPos - 4); + + MoveConstToX86reg(0xFFC0, x86_EBX); + ShiftRightSignImmed(x86_ESI, 31); + XorX86RegToX86Reg(x86_EDX, x86_EDX); + XorX86RegToX86Reg(x86_EDI, x86_ESI); + SubX86RegToX86Reg(x86_EDI, x86_ESI); + + BsrX86RegToX86Reg(x86_ECX, x86_EDI); + XorConstToX86Reg(x86_ECX, 15); + ShiftRightUnsign(x86_EBX); + AndX86RegToX86Reg(x86_EDI, x86_EBX); + + idivX86reg(x86_EDI); + + MoveConstToX86reg(0xFFFF8000, x86_EBX); + BsrX86RegToX86Reg(x86_ECX, x86_EAX); + XorConstToX86Reg(x86_ECX, 31); + ShiftRightUnsign(x86_EBX); + AndX86RegToX86Reg(x86_EAX, x86_EBX); + XorX86RegToX86Reg(x86_EAX, x86_ESI); + + x86_SetBranch32b(end, RecompPos); + + if (bWriteToAccum != FALSE){ + last = -1; + for (count = 0; count < 8; count++) { + el = EleSpec[RSPOpC.rs].B[count]; + + if (el != last) { + sprintf(Reg, "RSP_Vect[%i].UHW[%i]", RSPOpC.rt, el); + MoveVariableToX86regHalf(&RSP_Vect[RSPOpC.rt].UHW[el], Reg, x86_ECX); + last = el; + } + + sprintf(Reg, "RSP_ACCUM[%i].HW[1]", count); + MoveX86regHalfToVariable(x86_ECX, &RSP_ACCUM[count].HW[1], Reg); + } + } + + el = 7 - (RSPOpC.rd & 0x7); + sprintf(Reg, "RSP_Vect[%i].UHW[%i]", RSPOpC.sa, el); + MoveX86regHalfToVariable(x86_EAX, &RSP_Vect[RSPOpC.sa].HW[el], Reg); + MoveX86regToVariable(x86_EAX, &RecpResult.W, "RecpResult.W"); } void Compile_Vector_VRCPL ( void ) { From aebc9fa8b03d03191cf3e02e85a59ce376391cd9 Mon Sep 17 00:00:00 2001 From: LegendOfDragoon Date: Fri, 25 Sep 2015 04:26:42 -0700 Subject: [PATCH 3/5] Implement VRCPL in RSP Recompiler --- Source/RSP/Recompiler Ops.c | 70 +++++++++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) diff --git a/Source/RSP/Recompiler Ops.c b/Source/RSP/Recompiler Ops.c index 4982355e8..6a3975ff5 100644 --- a/Source/RSP/Recompiler Ops.c +++ b/Source/RSP/Recompiler Ops.c @@ -75,6 +75,7 @@ DWORD BranchCompare = 0; #endif #ifdef RSP_VectorMisc # define CompileVrcp +# define CompileVrcpl # define CompileVrsqh # define CompileVrcph # define CompileVsaw /* Verified 12/17/2000 - Jabo */ @@ -4545,7 +4546,76 @@ void Compile_Vector_VRCP ( void ) { } void Compile_Vector_VRCPL ( void ) { + char Reg[256]; + int count, el, last; + BOOL bWriteToAccum = WriteToAccum(Low16BitAccum, CompilePC); + DWORD *end = NULL; + +#ifndef CompileVrcpl Cheat_r4300iOpcode(RSP_Vector_VRCPL,"RSP_Vector_VRCPL"); + return; +#endif + + CPU_Message(" %X %s", CompilePC, RSPOpcodeName(RSPOpC.Hex, CompilePC)); + + el = EleSpec[RSPOpC.rs].B[(RSPOpC.rd & 0x7)]; + sprintf(Reg, "RSP_Vect[%i].UHW[%i]", RSPOpC.rt, el); + MoveVariableToX86reg(&Recp.W, "Recp.W", x86_ESI); + OrVariableToX86regHalf(&RSP_Vect[RSPOpC.rt].HW[el], Reg, x86_ESI); + + MoveConstToX86reg(0x7FFFFFFF, x86_EAX); + TestX86RegToX86Reg(x86_ESI, x86_ESI); + MoveX86RegToX86Reg(x86_ESI, x86_EDI); + JeLabel32("Done", 0); + end = (DWORD*)(RecompPos - 4); + + MoveConstToX86reg(0xFFC00000, x86_EBX); + ShiftRightSignImmed(x86_ESI, 31); + MoveX86RegToX86Reg(x86_EDI, x86_ECX); + MoveZxX86RegHalfToX86Reg(x86_EDI, x86_EDX); + OrConstToX86Reg(0xFFFF, x86_ECX); + ShiftRightUnsignImmed(x86_EDX, 15); + + XorX86RegToX86Reg(x86_EDI, x86_ESI); + AddX86RegToX86Reg(x86_ECX, x86_EDX); + AdcConstToX86reg(0, x86_EDI); + XorX86RegToX86Reg(x86_EDX, x86_EDX); + + BsrX86RegToX86Reg(x86_ECX, x86_EDI); + XorConstToX86Reg(x86_ECX, 31); + ShiftRightUnsign(x86_EBX); + AndX86RegToX86Reg(x86_EDI, x86_EBX); + + idivX86reg(x86_EDI); + MoveConstToX86reg(0xFFFF8000, x86_EBX); + BsrX86RegToX86Reg(x86_ECX, x86_EAX); + XorConstToX86Reg(x86_ECX, 31); + ShiftRightUnsign(x86_EBX); + AndX86RegToX86Reg(x86_EAX, x86_EBX); + XorX86RegToX86Reg(x86_EAX, x86_ESI); + + x86_SetBranch32b(end, RecompPos); + + if (bWriteToAccum != FALSE){ + last = -1; + for (count = 0; count < 8; count++) { + el = EleSpec[RSPOpC.rs].B[count]; + + if (el != last) { + sprintf(Reg, "RSP_Vect[%i].UHW[%i]", RSPOpC.rt, el); + MoveVariableToX86regHalf(&RSP_Vect[RSPOpC.rt].UHW[el], Reg, x86_ECX); + last = el; + } + + sprintf(Reg, "RSP_ACCUM[%i].HW[1]", count); + MoveX86regHalfToVariable(x86_ECX, &RSP_ACCUM[count].HW[1], Reg); + } + } + + el = 7 - (RSPOpC.rd & 0x7); + sprintf(Reg, "RSP_Vect[%i].UHW[%i]", RSPOpC.sa, el); + MoveX86regHalfToVariable(x86_EAX, &RSP_Vect[RSPOpC.sa].HW[el], Reg); + MoveX86regToVariable(x86_EAX, &RecpResult.W, "RecpResult.W"); } void Compile_Vector_VRCPH ( void ) { From 0102762456996c55e1acf3738abce30158901807 Mon Sep 17 00:00:00 2001 From: LegendOfDragoon Date: Fri, 25 Sep 2015 04:45:00 -0700 Subject: [PATCH 4/5] Improve Compile_Vector_VRCPH The issue is that it was writing to RSP_Vect before writing to accumulator. Also removed minor overhead, since Recp.UHW[0] always = 0. --- Source/RSP/Recompiler Ops.c | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/Source/RSP/Recompiler Ops.c b/Source/RSP/Recompiler Ops.c index 6a3975ff5..02443a5cd 100644 --- a/Source/RSP/Recompiler Ops.c +++ b/Source/RSP/Recompiler Ops.c @@ -4620,7 +4620,7 @@ void Compile_Vector_VRCPL ( void ) { void Compile_Vector_VRCPH ( void ) { char Reg[256]; - int count, el, last = -1; + int count, el, last; BOOL bWriteToAccum = WriteToAccum(Low16BitAccum, CompilePC); #ifndef CompileVrcph @@ -4634,27 +4634,27 @@ void Compile_Vector_VRCPH ( void ) { MoveVariableToX86regHalf(&RSP_Vect[RSPOpC.rt].UHW[el], Reg, x86_EDX); MoveX86regHalfToVariable(x86_EDX, &Recp.UHW[1], "Recp.UHW[1]"); - MoveConstHalfToVariable(0, &Recp.UHW[0], "Recp.UHW[0]"); - MoveVariableToX86regHalf(&RecpResult.UHW[1], "RecpResult.UHW[1]", x86_ECX); + + if (bWriteToAccum != FALSE) { + last = -1; + for (count = 0; count < 8; count++) { + el = EleSpec[RSPOpC.rs].B[count]; + + if (el != last) { + sprintf(Reg, "RSP_Vect[%i].UHW[%i]", RSPOpC.rt, el); + MoveVariableToX86regHalf(&RSP_Vect[RSPOpC.rt].UHW[el], Reg, x86_EAX); + last = el; + } + + sprintf(Reg, "RSP_ACCUM[%i].HW[1]", count); + MoveX86regHalfToVariable(x86_EAX, &RSP_ACCUM[count].HW[1], Reg); + } + } + el = 7 - (RSPOpC.rd & 0x7); sprintf(Reg, "RSP_Vect[%i].UHW[%i]", RSPOpC.sa, el); MoveX86regHalfToVariable(x86_ECX, &RSP_Vect[RSPOpC.sa].UHW[el], Reg); - - if (bWriteToAccum == FALSE) return; - - for (count = 0; count < 8; count++) { - el = EleSpec[RSPOpC.rs].B[count]; - - if (el != last) { - sprintf(Reg, "RSP_Vect[%i].UHW[%i]", RSPOpC.rt, el); - MoveVariableToX86regHalf(&RSP_Vect[RSPOpC.rt].UHW[el], Reg, x86_EAX); - last = el; - } - - sprintf(Reg, "RSP_ACCUM[%i].HW[1]", count); - MoveX86regHalfToVariable(x86_EAX, &RSP_ACCUM[count].HW[1], Reg); - } } void Compile_Vector_VMOV ( void ) { From 7ea0dd0311bc4c81524f5125e3816915cec5e2c1 Mon Sep 17 00:00:00 2001 From: LegendOfDragoon Date: Fri, 25 Sep 2015 05:00:41 -0700 Subject: [PATCH 5/5] Improve Compile_Vector_VRSQH RSP_ACCUM needs to be written to before RSP_Vect. Also optimized the code for writing to RSP_ACCUM. --- Source/RSP/Recompiler Ops.c | 29 +++++++++++++++++++---------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/Source/RSP/Recompiler Ops.c b/Source/RSP/Recompiler Ops.c index 02443a5cd..bd3f3b678 100644 --- a/Source/RSP/Recompiler Ops.c +++ b/Source/RSP/Recompiler Ops.c @@ -4699,7 +4699,8 @@ void Compile_Vector_VRSQL ( void ) { void Compile_Vector_VRSQH ( void ) { char Reg[256]; - int count, el; + int count, el, last; + BOOL bWriteToAccum = WriteToAccum(Low16BitAccum, CompilePC); #ifndef CompileVrsqh Cheat_r4300iOpcode(RSP_Vector_VRSQH,"RSP_Vector_VRSQH"); return; @@ -4713,18 +4714,26 @@ void Compile_Vector_VRSQH ( void ) { MoveX86regHalfToVariable(x86_EDX, &SQroot.UHW[1], "SQroot.UHW[1]"); MoveVariableToX86regHalf(&SQrootResult.UHW[1], "SQrootResult.UHW[1]", x86_ECX); + + if (bWriteToAccum != FALSE) { + last = -1; + for (count = 0; count < 8; count++) { + el = EleSpec[RSPOpC.rs].B[count]; + + if(el != last){ + sprintf(Reg, "RSP_Vect[%i].UHW[%i]", RSPOpC.rt, el); + MoveVariableToX86regHalf(&RSP_Vect[RSPOpC.rt].UHW[el], Reg, x86_EAX); + last = el; + } + + sprintf(Reg, "RSP_ACCUM[%i].HW[1]", count); + MoveX86regHalfToVariable(x86_EAX, &RSP_ACCUM[count].HW[1], Reg); + } + } + el = 7 - (RSPOpC.rd & 0x7); sprintf(Reg, "RSP_Vect[%i].UHW[%i]", RSPOpC.sa, el); MoveX86regHalfToVariable(x86_ECX, &RSP_Vect[RSPOpC.sa].UHW[el], Reg); - - for (count = 0; count < 8; count++) { - el = EleSpec[RSPOpC.rs].B[count]; - sprintf(Reg, "RSP_Vect[%i].UHW[%i]", RSPOpC.rt, el); - MoveVariableToX86regHalf(&RSP_Vect[RSPOpC.rt].UHW[el], Reg, x86_EAX); - - sprintf(Reg, "RSP_ACCUM[%i].HW[1]", count); - MoveX86regHalfToVariable(x86_EAX, &RSP_ACCUM[count].HW[1], Reg); - } } void Compile_Vector_VNOOP ( void ) {