Merge pull request #1187 from LegendOfDragoon/master

Improve RSP Recompiler
This commit is contained in:
zilmar 2016-08-24 10:08:56 +10:00 committed by GitHub
commit 721aadbd89
2 changed files with 162 additions and 29 deletions

View File

@ -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));
}
@ -555,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) {
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);
AndConstToX86Reg(x86_EAX, Immediate);
@ -910,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 ) {
@ -941,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;
}
}
@ -968,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);
@ -986,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;
}
}
@ -1043,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);
@ -1432,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));
}
}

View File

@ -1154,6 +1154,51 @@ 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 MoveConstHalfToN64Mem(WORD 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);
PUTDST16(RecompPos, Const);
}
void MoveConstByteToVariable (BYTE Const,void *Variable, char *VariableName) {
CPU_Message(" mov byte ptr [%s], %Xh",VariableName,Const);
PUTDST16(RecompPos,0x05C6);
@ -1169,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);