diff --git a/Source/7zip/Compress/vssver2.scc b/Source/7zip/Compress/vssver2.scc deleted file mode 100644 index 088054d2c..000000000 Binary files a/Source/7zip/Compress/vssver2.scc and /dev/null differ diff --git a/Source/7zip/Release/7zAlloc.obj b/Source/7zip/Release/7zAlloc.obj deleted file mode 100644 index aeb3d3819..000000000 Binary files a/Source/7zip/Release/7zAlloc.obj and /dev/null differ diff --git a/Source/7zip/Release/7zBuffer.obj b/Source/7zip/Release/7zBuffer.obj deleted file mode 100644 index dfdab0dff..000000000 Binary files a/Source/7zip/Release/7zBuffer.obj and /dev/null differ diff --git a/Source/7zip/Release/7zCrc.obj b/Source/7zip/Release/7zCrc.obj deleted file mode 100644 index 08086280e..000000000 Binary files a/Source/7zip/Release/7zCrc.obj and /dev/null differ diff --git a/Source/7zip/Release/7zDecode.obj b/Source/7zip/Release/7zDecode.obj deleted file mode 100644 index 485b8adc9..000000000 Binary files a/Source/7zip/Release/7zDecode.obj and /dev/null differ diff --git a/Source/7zip/Release/7zExtract.obj b/Source/7zip/Release/7zExtract.obj deleted file mode 100644 index 5f86420b9..000000000 Binary files a/Source/7zip/Release/7zExtract.obj and /dev/null differ diff --git a/Source/7zip/Release/7zHeader.obj b/Source/7zip/Release/7zHeader.obj deleted file mode 100644 index d0b82194e..000000000 Binary files a/Source/7zip/Release/7zHeader.obj and /dev/null differ diff --git a/Source/7zip/Release/7zIn.obj b/Source/7zip/Release/7zIn.obj deleted file mode 100644 index db2cdcaac..000000000 Binary files a/Source/7zip/Release/7zIn.obj and /dev/null differ diff --git a/Source/7zip/Release/7zItem.obj b/Source/7zip/Release/7zItem.obj deleted file mode 100644 index ef36d1755..000000000 Binary files a/Source/7zip/Release/7zItem.obj and /dev/null differ diff --git a/Source/7zip/Release/7zMethodID.obj b/Source/7zip/Release/7zMethodID.obj deleted file mode 100644 index e78f4afe9..000000000 Binary files a/Source/7zip/Release/7zMethodID.obj and /dev/null differ diff --git a/Source/7zip/Release/7zip.lib b/Source/7zip/Release/7zip.lib deleted file mode 100644 index 51a21a53c..000000000 Binary files a/Source/7zip/Release/7zip.lib and /dev/null differ diff --git a/Source/7zip/Release/7zip.pch b/Source/7zip/Release/7zip.pch deleted file mode 100644 index 37df76e9a..000000000 Binary files a/Source/7zip/Release/7zip.pch and /dev/null differ diff --git a/Source/7zip/Release/LzmaDecode.obj b/Source/7zip/Release/LzmaDecode.obj deleted file mode 100644 index df2494842..000000000 Binary files a/Source/7zip/Release/LzmaDecode.obj and /dev/null differ diff --git a/Source/7zip/Release/vc60.idb b/Source/7zip/Release/vc60.idb deleted file mode 100644 index 8567c8e05..000000000 Binary files a/Source/7zip/Release/vc60.idb and /dev/null differ diff --git a/Source/7zip/vssver2.scc b/Source/7zip/vssver2.scc deleted file mode 100644 index 7cfd9500d..000000000 Binary files a/Source/7zip/vssver2.scc and /dev/null differ diff --git a/Source/Common/Ini File Class.h b/Source/Common/Ini File Class.h index 0fd1a16aa..c52fe04bb 100644 --- a/Source/Common/Ini File Class.h +++ b/Source/Common/Ini File Class.h @@ -110,17 +110,16 @@ private: fInsertSpaces(WritePos,Newlen - OldLen); BytesMoved = Newlen - OldLen; } - - m_File.Seek(WritePos,CFileStorage::begin); - stdstr_f NewData(_T("%s=%s%s"),lpKeyName,lpString,m_LineFeed); + } + m_File.Seek(WritePos,CFileStorage::begin); + stdstr_f NewData(_T("%s=%s%s"),lpKeyName,lpString,m_LineFeed); - std::string strTmpString = stdstr::fromTString(NewData); + std::string strTmpString = stdstr::fromTString(NewData); - m_File.Write(strTmpString.c_str(),(DWORD)strTmpString.length()); - if (m_FlushFileOnWrite) - { - m_File.Flush(); - } + m_File.Write(strTmpString.c_str(),(DWORD)strTmpString.length()); + if (m_FlushFileOnWrite) + { + m_File.Flush(); } if (Input) { delete [] Input; Input = NULL; } if (Data) { delete [] Data; Data = NULL; } diff --git a/Source/Common/Release/Common.lib b/Source/Common/Release/Common.lib deleted file mode 100644 index 20385373e..000000000 Binary files a/Source/Common/Release/Common.lib and /dev/null differ diff --git a/Source/Common/Release/Common.pch b/Source/Common/Release/Common.pch deleted file mode 100644 index 7b067bccc..000000000 Binary files a/Source/Common/Release/Common.pch and /dev/null differ diff --git a/Source/Common/Release/File Class.obj b/Source/Common/Release/File Class.obj deleted file mode 100644 index 73f50d4f9..000000000 Binary files a/Source/Common/Release/File Class.obj and /dev/null differ diff --git a/Source/Common/Release/Log Class.obj b/Source/Common/Release/Log Class.obj deleted file mode 100644 index 686932b88..000000000 Binary files a/Source/Common/Release/Log Class.obj and /dev/null differ diff --git a/Source/Common/Release/MemTest.obj b/Source/Common/Release/MemTest.obj deleted file mode 100644 index ae83e6052..000000000 Binary files a/Source/Common/Release/MemTest.obj and /dev/null differ diff --git a/Source/Common/Release/Trace.obj b/Source/Common/Release/Trace.obj deleted file mode 100644 index ae58175c4..000000000 Binary files a/Source/Common/Release/Trace.obj and /dev/null differ diff --git a/Source/Common/Release/Version.obj b/Source/Common/Release/Version.obj deleted file mode 100644 index c91285b07..000000000 Binary files a/Source/Common/Release/Version.obj and /dev/null differ diff --git a/Source/Common/Release/md5.obj b/Source/Common/Release/md5.obj deleted file mode 100644 index 873eacd09..000000000 Binary files a/Source/Common/Release/md5.obj and /dev/null differ diff --git a/Source/Common/Release/osversion.obj b/Source/Common/Release/osversion.obj deleted file mode 100644 index 7e32d5573..000000000 Binary files a/Source/Common/Release/osversion.obj and /dev/null differ diff --git a/Source/Common/Release/path.obj b/Source/Common/Release/path.obj deleted file mode 100644 index abbf88022..000000000 Binary files a/Source/Common/Release/path.obj and /dev/null differ diff --git a/Source/Common/Release/registry.obj b/Source/Common/Release/registry.obj deleted file mode 100644 index 9456caf95..000000000 Binary files a/Source/Common/Release/registry.obj and /dev/null differ diff --git a/Source/Common/Release/std string.obj b/Source/Common/Release/std string.obj deleted file mode 100644 index bf8d09c18..000000000 Binary files a/Source/Common/Release/std string.obj and /dev/null differ diff --git a/Source/Common/Release/stdafx.obj b/Source/Common/Release/stdafx.obj deleted file mode 100644 index 3a0dab18e..000000000 Binary files a/Source/Common/Release/stdafx.obj and /dev/null differ diff --git a/Source/Common/Release/vc60.idb b/Source/Common/Release/vc60.idb deleted file mode 100644 index cc321efce..000000000 Binary files a/Source/Common/Release/vc60.idb and /dev/null differ diff --git a/Source/Common/path.cpp b/Source/Common/path.cpp index 6347bd601..fd76c77ba 100644 --- a/Source/Common/path.cpp +++ b/Source/Common/path.cpp @@ -119,6 +119,16 @@ CPath::CPath(LPCTSTR lpszPath) cleanPathString(m_strPath); } +//------------------------------------------------------------- +// Task : Constructs a path and points it 2 strPath +//------------------------------------------------------------- +CPath::CPath(LPCTSTR strPath, LPCTSTR NameExten ) +{ + Init(); + SetDriveDirectory(strPath); + SetNameExtension(NameExten); +} + //------------------------------------------------------------- // Task : Constructs a path and points it 2 strPath //------------------------------------------------------------- diff --git a/Source/RSP/Cpu.c b/Source/RSP/Cpu.c new file mode 100644 index 000000000..7d8bb7722 --- /dev/null +++ b/Source/RSP/Cpu.c @@ -0,0 +1,263 @@ +/* + * RSP Compiler plug in for Project 64 (A Nintendo 64 emulator). + * + * (c) Copyright 2001 jabo (jabo@emulation64.com) and + * zilmar (zilmar@emulation64.com) + * + * pj64 homepage: www.pj64.net + * + * Permission to use, copy, modify and distribute Project64 in both binary and + * source form, for non-commercial purposes, is hereby granted without fee, + * providing that this license information and copyright notice appear with + * all copies and any derived work. + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event shall the authors be held liable for any damages + * arising from the use of this software. + * + * Project64 is freeware for PERSONAL USE only. Commercial users should + * seek permission of the copyright holders first. Commercial use includes + * charging money for Project64 or software derived from Project64. + * + * The copyright holders request that bug fixes and improvements to the code + * should be forwarded to them so if they want them. + * + */ + +#include +#include +#include +#include "RSP.h" +#include "Cpu.h" +#include "RSP registers.h" +#include "RSP Command.h" +#include "Recompiler CPU.h" +#include "memory.h" +#include "opcode.h" +#include "log.h" +#include "Profiling.h" +#include "breakpoint.h" +#include "x86.h" + +UDWORD EleSpec[32], Indx[32]; +OPCODE RSPOpC; +DWORD *PrgCount, NextInstruction, RSP_Running; + +void * RSP_Opcode[64]; +void * RSP_RegImm[32]; +void * RSP_Special[64]; +void * RSP_Cop0[32]; +void * RSP_Cop2[32]; +void * RSP_Vector[64]; +void * RSP_Lc2[32]; +void * RSP_Sc2[32]; + +void BuildInterpreterCPU(void); +void BuildRecompilerCPU(void); + +extern HANDLE hMutex; + +void SetCPU(DWORD core) { + WaitForSingleObjectEx(hMutex, 1000 * 100, FALSE); + CPUCore = core; + switch (core) { + case RecompilerCPU: + BuildRecompilerCPU(); + break; + case InterpreterCPU: + BuildInterpreterCPU(); + break; + } + ReleaseMutex(hMutex); +} + +void Build_RSP ( void ) { + int i; + extern UWORD32 Recp, RecpResult, SQroot, SQrootResult; + + Recp.UW = 0; + RecpResult.UW = 0; + SQroot.UW = 0; + SQrootResult.UW = 0; + + SetCPU(CPUCore); + ResetTimerList(); + + EleSpec[ 0].DW = 0; + EleSpec[ 1].DW = 0; + EleSpec[ 2].DW = 0; + EleSpec[ 3].DW = 0; + EleSpec[ 4].DW = 0; + EleSpec[ 5].DW = 0; + EleSpec[ 6].DW = 0; + EleSpec[ 7].DW = 0; + EleSpec[ 8].DW = 0; + EleSpec[ 9].DW = 0; + EleSpec[10].DW = 0; + EleSpec[11].DW = 0; + EleSpec[12].DW = 0; + EleSpec[13].DW = 0; + EleSpec[14].DW = 0; + EleSpec[15].DW = 0; + EleSpec[16].DW = 0x0001020304050607; /* None */ + EleSpec[17].DW = 0x0001020304050607; /* None */ + EleSpec[18].DW = 0x0000020204040606; /* 0q */ + EleSpec[19].DW = 0x0101030305050707; /* 1q */ + EleSpec[20].DW = 0x0000000004040404; /* 0h */ + EleSpec[21].DW = 0x0101010105050505; /* 1h */ + EleSpec[22].DW = 0x0202020206060606; /* 2h */ + EleSpec[23].DW = 0x0303030307070707; /* 3h */ + EleSpec[24].DW = 0x0000000000000000; /* 0 */ + EleSpec[25].DW = 0x0101010101010101; /* 1 */ + EleSpec[26].DW = 0x0202020202020202; /* 2 */ + EleSpec[27].DW = 0x0303030303030303; /* 3 */ + EleSpec[28].DW = 0x0404040404040404; /* 4 */ + EleSpec[29].DW = 0x0505050505050505; /* 5 */ + EleSpec[30].DW = 0x0606060606060606; /* 6 */ + EleSpec[31].DW = 0x0707070707070707; /* 7 */ + + Indx[ 0].DW = 0; + Indx[ 1].DW = 0; + Indx[ 2].DW = 0; + Indx[ 3].DW = 0; + Indx[ 4].DW = 0; + Indx[ 5].DW = 0; + Indx[ 6].DW = 0; + Indx[ 7].DW = 0; + Indx[ 8].DW = 0; + Indx[ 9].DW = 0; + Indx[10].DW = 0; + Indx[11].DW = 0; + Indx[12].DW = 0; + Indx[13].DW = 0; + Indx[14].DW = 0; + Indx[15].DW = 0; + + Indx[16].DW = 0x0001020304050607; /* None */ + Indx[17].DW = 0x0001020304050607; /* None */ + Indx[18].DW = 0x0103050700020406; /* 0q */ + Indx[19].DW = 0x0002040601030507; /* 1q */ + Indx[20].DW = 0x0102030506070004; /* 0h */ + Indx[21].DW = 0x0002030406070105; /* 1h */ + Indx[22].DW = 0x0001030405070206; /* 2h */ + Indx[23].DW = 0x0001020405060307; /* 3h */ + Indx[24].DW = 0x0102030405060700; /* 0 */ + Indx[25].DW = 0x0002030405060701; /* 1 */ + Indx[26].DW = 0x0001030405060702; /* 2 */ + Indx[27].DW = 0x0001020405060703; /* 3 */ + Indx[28].DW = 0x0001020305060704; /* 4 */ + Indx[29].DW = 0x0001020304060705; /* 5 */ + Indx[30].DW = 0x0001020304050706; /* 6 */ + Indx[31].DW = 0x0001020304050607; /* 7 */ + + for (i = 16; i < 32; i ++) { + int count; + + for (count = 0; count < 8; count ++) { + Indx[i].B[count] = 7 - Indx[i].B[count]; + EleSpec[i].B[count] = 7 - EleSpec[i].B[count]; + } + for (count = 0; count < 4; count ++) { + BYTE Temp; + + Temp = Indx[i].B[count]; + Indx[i].B[count] = Indx[i].B[7 - count]; + Indx[i].B[7 - count] = Temp; + } + } + + PrgCount = RSPInfo.SP_PC_REG; +} + +/****************************************************************** + Function: DoRspCycles + Purpose: This function is to allow the RSP to run in parrel with + the r4300 switching control back to the r4300 once the + function ends. + input: The number of cylces that is meant to be executed + output: The number of cycles that was executed. This value can + be greater than the number of cycles that the RSP + should have performed. + (this value is ignored if the RSP is stoped) +*******************************************************************/ + +DWORD RunInterpreterCPU(DWORD Cycles); +DWORD RunRecompilerCPU ( DWORD Cycles ); + +#define MI_INTR_SP 0x01 /* Bit 0: SP intr */ + +__declspec(dllexport) DWORD DoRspCycles ( DWORD Cycles ) { + extern BOOL AudioHle, GraphicsHle; + DWORD TaskType = *(DWORD*)(RSPInfo.DMEM + 0xFC0); + +/* if (*RSPInfo.SP_STATUS_REG & SP_STATUS_SIG0) { + *RSPInfo.SP_STATUS_REG &= ~SP_STATUS_SIG0; + *RSPInfo.MI_INTR_REG |= MI_INTR_SP; + RSPInfo.CheckInterrupts(); + return Cycles; + } +*/ + if (TaskType == 1 && GraphicsHle && *(DWORD*)(RSPInfo.DMEM + 0x0ff0) != 0) { + if (RSPInfo.ProcessDList != NULL) { + RSPInfo.ProcessDList(); + } + *RSPInfo.SP_STATUS_REG |= (0x0203 ); + if ((*RSPInfo.SP_STATUS_REG & SP_STATUS_INTR_BREAK) != 0 ) { + *RSPInfo.MI_INTR_REG |= R4300i_SP_Intr; + RSPInfo.CheckInterrupts(); + } + + *RSPInfo.DPC_STATUS_REG &= ~0x0002; + return Cycles; + } else if (TaskType == 2 && AudioHle) { + if (RSPInfo.ProcessAList != NULL) { + RSPInfo.ProcessAList(); + } + *RSPInfo.SP_STATUS_REG |= (0x0203 ); + if ((*RSPInfo.SP_STATUS_REG & SP_STATUS_INTR_BREAK) != 0 ) { + *RSPInfo.MI_INTR_REG |= R4300i_SP_Intr; + RSPInfo.CheckInterrupts(); + } + return Cycles; + } else if (TaskType == 7) { + RSPInfo.ShowCFB(); + } + + Compiler.bAudioUcode = (TaskType == 2) ? TRUE : FALSE; + +/* + *RSPInfo.SP_STATUS_REG |= (0x0203 ); + if ((*RSPInfo.SP_STATUS_REG & SP_STATUS_INTR_BREAK) != 0 ) { + *RSPInfo.MI_INTR_REG |= R4300i_SP_Intr; + RSPInfo.CheckInterrupts(); + } + //return Cycles; +*/ + + if (Profiling && !IndvidualBlock) { + StartTimer(Timer_RSP_Running); + } + + WaitForSingleObjectEx(hMutex, 1000 * 100, FALSE); + + if (BreakOnStart) + { + Enter_RSP_Commands_Window(); + } + + switch (CPUCore) { + case RecompilerCPU: + RunRecompilerCPU(Cycles); + break; + case InterpreterCPU: + RunInterpreterCPU(Cycles); + break; + } + ReleaseMutex(hMutex); + + if (Profiling && !IndvidualBlock) { + StartTimer(Timer_R4300_Running); + } + + return Cycles; +} \ No newline at end of file diff --git a/Source/RSP/Cpu.h b/Source/RSP/Cpu.h new file mode 100644 index 000000000..8c345d225 --- /dev/null +++ b/Source/RSP/Cpu.h @@ -0,0 +1,43 @@ +/* + * RSP Compiler plug in for Project 64 (A Nintendo 64 emulator). + * + * (c) Copyright 2001 jabo (jabo@emulation64.com) and + * zilmar (zilmar@emulation64.com) + * + * pj64 homepage: www.pj64.net + * + * Permission to use, copy, modify and distribute Project64 in both binary and + * source form, for non-commercial purposes, is hereby granted without fee, + * providing that this license information and copyright notice appear with + * all copies and any derived work. + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event shall the authors be held liable for any damages + * arising from the use of this software. + * + * Project64 is freeware for PERSONAL USE only. Commercial users should + * seek permission of the copyright holders first. Commercial use includes + * charging money for Project64 or software derived from Project64. + * + * The copyright holders request that bug fixes and improvements to the code + * should be forwarded to them so if they want them. + * + */ + +#include "opcode.h" + +extern UDWORD EleSpec[32], Indx[32]; + +extern void * RSP_Opcode[64]; +extern void * RSP_RegImm[32]; +extern void * RSP_Special[64]; +extern void * RSP_Cop0[32]; +extern void * RSP_Cop2[32]; +extern void * RSP_Vector[64]; +extern void * RSP_Lc2[32]; +extern void * RSP_Sc2[32]; +extern DWORD * PrgCount, RSP_Running; +extern OPCODE RSPOpC; + +void SetCPU(DWORD core); +void Build_RSP (void); diff --git a/Source/RSP/Interpreter CPU.c b/Source/RSP/Interpreter CPU.c new file mode 100644 index 000000000..b4308c29f --- /dev/null +++ b/Source/RSP/Interpreter CPU.c @@ -0,0 +1,466 @@ +/* + * RSP Compiler plug in for Project 64 (A Nintendo 64 emulator). + * + * (c) Copyright 2001 jabo (jabo@emulation64.com) and + * zilmar (zilmar@emulation64.com) + * + * pj64 homepage: www.pj64.net + * + * Permission to use, copy, modify and distribute Project64 in both binary and + * source form, for non-commercial purposes, is hereby granted without fee, + * providing that this license information and copyright notice appear with + * all copies and any derived work. + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event shall the authors be held liable for any damages + * arising from the use of this software. + * + * Project64 is freeware for PERSONAL USE only. Commercial users should + * seek permission of the copyright holders first. Commercial use includes + * charging money for Project64 or software derived from Project64. + * + * The copyright holders request that bug fixes and improvements to the code + * should be forwarded to them so if they want them. + * + */ + +#include +#include +#include +#include "breakpoint.h" +#include "RSP.h" +#include "Cpu.h" +#include "Interpreter Ops.h" +#include "Interpreter CPU.h" +#include "RSP registers.h" +#include "RSP Command.h" +#include "memory.h" +#include "opcode.h" +#include "log.h" + +DWORD RSP_NextInstruction, RSP_JumpTo; + +void BuildInterpreterCPU(void) { + RSP_Opcode[ 0] = RSP_Opcode_SPECIAL; + RSP_Opcode[ 1] = RSP_Opcode_REGIMM; + RSP_Opcode[ 2] = RSP_Opcode_J; + RSP_Opcode[ 3] = RSP_Opcode_JAL; + RSP_Opcode[ 4] = RSP_Opcode_BEQ; + RSP_Opcode[ 5] = RSP_Opcode_BNE; + RSP_Opcode[ 6] = RSP_Opcode_BLEZ; + RSP_Opcode[ 7] = RSP_Opcode_BGTZ; + RSP_Opcode[ 8] = RSP_Opcode_ADDI; + RSP_Opcode[ 9] = RSP_Opcode_ADDIU; + RSP_Opcode[10] = RSP_Opcode_SLTI; + RSP_Opcode[11] = RSP_Opcode_SLTIU; + RSP_Opcode[12] = RSP_Opcode_ANDI; + RSP_Opcode[13] = RSP_Opcode_ORI; + RSP_Opcode[14] = RSP_Opcode_XORI; + RSP_Opcode[15] = RSP_Opcode_LUI; + RSP_Opcode[16] = RSP_Opcode_COP0; + RSP_Opcode[17] = rsp_UnknownOpcode; + RSP_Opcode[18] = RSP_Opcode_COP2; + RSP_Opcode[19] = rsp_UnknownOpcode; + RSP_Opcode[20] = rsp_UnknownOpcode; + RSP_Opcode[21] = rsp_UnknownOpcode; + RSP_Opcode[22] = rsp_UnknownOpcode; + RSP_Opcode[23] = rsp_UnknownOpcode; + RSP_Opcode[24] = rsp_UnknownOpcode; + RSP_Opcode[25] = rsp_UnknownOpcode; + RSP_Opcode[26] = rsp_UnknownOpcode; + RSP_Opcode[27] = rsp_UnknownOpcode; + RSP_Opcode[28] = rsp_UnknownOpcode; + RSP_Opcode[29] = rsp_UnknownOpcode; + RSP_Opcode[30] = rsp_UnknownOpcode; + RSP_Opcode[31] = rsp_UnknownOpcode; + RSP_Opcode[32] = RSP_Opcode_LB; + RSP_Opcode[33] = RSP_Opcode_LH; + RSP_Opcode[34] = rsp_UnknownOpcode; + RSP_Opcode[35] = RSP_Opcode_LW; + RSP_Opcode[36] = RSP_Opcode_LBU; + RSP_Opcode[37] = RSP_Opcode_LHU; + RSP_Opcode[38] = rsp_UnknownOpcode; + RSP_Opcode[39] = rsp_UnknownOpcode; + RSP_Opcode[40] = RSP_Opcode_SB; + RSP_Opcode[41] = RSP_Opcode_SH; + RSP_Opcode[42] = rsp_UnknownOpcode; + RSP_Opcode[43] = RSP_Opcode_SW; + RSP_Opcode[44] = rsp_UnknownOpcode; + RSP_Opcode[45] = rsp_UnknownOpcode; + RSP_Opcode[46] = rsp_UnknownOpcode; + RSP_Opcode[47] = rsp_UnknownOpcode; + RSP_Opcode[48] = rsp_UnknownOpcode; + RSP_Opcode[49] = rsp_UnknownOpcode; + RSP_Opcode[50] = RSP_Opcode_LC2; + RSP_Opcode[51] = rsp_UnknownOpcode; + RSP_Opcode[52] = rsp_UnknownOpcode; + RSP_Opcode[53] = rsp_UnknownOpcode; + RSP_Opcode[54] = rsp_UnknownOpcode; + RSP_Opcode[55] = rsp_UnknownOpcode; + RSP_Opcode[56] = rsp_UnknownOpcode; + RSP_Opcode[57] = rsp_UnknownOpcode; + RSP_Opcode[58] = RSP_Opcode_SC2; + RSP_Opcode[59] = rsp_UnknownOpcode; + RSP_Opcode[60] = rsp_UnknownOpcode; + RSP_Opcode[61] = rsp_UnknownOpcode; + RSP_Opcode[62] = rsp_UnknownOpcode; + RSP_Opcode[63] = rsp_UnknownOpcode; + + RSP_Special[ 0] = RSP_Special_SLL; + RSP_Special[ 1] = rsp_UnknownOpcode; + RSP_Special[ 2] = RSP_Special_SRL; + RSP_Special[ 3] = RSP_Special_SRA; + RSP_Special[ 4] = RSP_Special_SLLV; + RSP_Special[ 5] = rsp_UnknownOpcode; + RSP_Special[ 6] = RSP_Special_SRLV; + RSP_Special[ 7] = RSP_Special_SRAV; + RSP_Special[ 8] = RSP_Special_JR; + RSP_Special[ 9] = RSP_Special_JALR; + RSP_Special[10] = rsp_UnknownOpcode; + RSP_Special[11] = rsp_UnknownOpcode; + RSP_Special[12] = rsp_UnknownOpcode; + RSP_Special[13] = RSP_Special_BREAK; + RSP_Special[14] = rsp_UnknownOpcode; + RSP_Special[15] = rsp_UnknownOpcode; + RSP_Special[16] = rsp_UnknownOpcode; + RSP_Special[17] = rsp_UnknownOpcode; + RSP_Special[18] = rsp_UnknownOpcode; + RSP_Special[19] = rsp_UnknownOpcode; + RSP_Special[20] = rsp_UnknownOpcode; + RSP_Special[21] = rsp_UnknownOpcode; + RSP_Special[22] = rsp_UnknownOpcode; + RSP_Special[23] = rsp_UnknownOpcode; + RSP_Special[24] = rsp_UnknownOpcode; + RSP_Special[25] = rsp_UnknownOpcode; + RSP_Special[26] = rsp_UnknownOpcode; + RSP_Special[27] = rsp_UnknownOpcode; + RSP_Special[28] = rsp_UnknownOpcode; + RSP_Special[29] = rsp_UnknownOpcode; + RSP_Special[30] = rsp_UnknownOpcode; + RSP_Special[31] = rsp_UnknownOpcode; + RSP_Special[32] = RSP_Special_ADD; + RSP_Special[33] = RSP_Special_ADDU; + RSP_Special[34] = RSP_Special_SUB; + RSP_Special[35] = RSP_Special_SUBU; + RSP_Special[36] = RSP_Special_AND; + RSP_Special[37] = RSP_Special_OR; + RSP_Special[38] = RSP_Special_XOR; + RSP_Special[39] = RSP_Special_NOR; + RSP_Special[40] = rsp_UnknownOpcode; + RSP_Special[41] = rsp_UnknownOpcode; + RSP_Special[42] = RSP_Special_SLT; + RSP_Special[43] = RSP_Special_SLTU; + RSP_Special[44] = rsp_UnknownOpcode; + RSP_Special[45] = rsp_UnknownOpcode; + RSP_Special[46] = rsp_UnknownOpcode; + RSP_Special[47] = rsp_UnknownOpcode; + RSP_Special[48] = rsp_UnknownOpcode; + RSP_Special[49] = rsp_UnknownOpcode; + RSP_Special[50] = rsp_UnknownOpcode; + RSP_Special[51] = rsp_UnknownOpcode; + RSP_Special[52] = rsp_UnknownOpcode; + RSP_Special[53] = rsp_UnknownOpcode; + RSP_Special[54] = rsp_UnknownOpcode; + RSP_Special[55] = rsp_UnknownOpcode; + RSP_Special[56] = rsp_UnknownOpcode; + RSP_Special[57] = rsp_UnknownOpcode; + RSP_Special[58] = rsp_UnknownOpcode; + RSP_Special[59] = rsp_UnknownOpcode; + RSP_Special[60] = rsp_UnknownOpcode; + RSP_Special[61] = rsp_UnknownOpcode; + RSP_Special[62] = rsp_UnknownOpcode; + RSP_Special[63] = rsp_UnknownOpcode; + + RSP_RegImm[ 0] = RSP_Opcode_BLTZ; + RSP_RegImm[ 1] = RSP_Opcode_BGEZ; + RSP_RegImm[ 2] = rsp_UnknownOpcode; + RSP_RegImm[ 3] = rsp_UnknownOpcode; + RSP_RegImm[ 4] = rsp_UnknownOpcode; + RSP_RegImm[ 5] = rsp_UnknownOpcode; + RSP_RegImm[ 6] = rsp_UnknownOpcode; + RSP_RegImm[ 7] = rsp_UnknownOpcode; + RSP_RegImm[ 8] = rsp_UnknownOpcode; + RSP_RegImm[ 9] = rsp_UnknownOpcode; + RSP_RegImm[10] = rsp_UnknownOpcode; + RSP_RegImm[11] = rsp_UnknownOpcode; + RSP_RegImm[12] = rsp_UnknownOpcode; + RSP_RegImm[13] = rsp_UnknownOpcode; + RSP_RegImm[14] = rsp_UnknownOpcode; + RSP_RegImm[15] = rsp_UnknownOpcode; + RSP_RegImm[16] = RSP_Opcode_BLTZAL; + RSP_RegImm[17] = RSP_Opcode_BGEZAL; + RSP_RegImm[18] = rsp_UnknownOpcode; + RSP_RegImm[19] = rsp_UnknownOpcode; + RSP_RegImm[20] = rsp_UnknownOpcode; + RSP_RegImm[21] = rsp_UnknownOpcode; + RSP_RegImm[22] = rsp_UnknownOpcode; + RSP_RegImm[23] = rsp_UnknownOpcode; + RSP_RegImm[24] = rsp_UnknownOpcode; + RSP_RegImm[25] = rsp_UnknownOpcode; + RSP_RegImm[26] = rsp_UnknownOpcode; + RSP_RegImm[27] = rsp_UnknownOpcode; + RSP_RegImm[28] = rsp_UnknownOpcode; + RSP_RegImm[29] = rsp_UnknownOpcode; + RSP_RegImm[30] = rsp_UnknownOpcode; + RSP_RegImm[31] = rsp_UnknownOpcode; + + RSP_Cop0[ 0] = RSP_Cop0_MF; + RSP_Cop0[ 1] = rsp_UnknownOpcode; + RSP_Cop0[ 2] = rsp_UnknownOpcode; + RSP_Cop0[ 3] = rsp_UnknownOpcode; + RSP_Cop0[ 4] = RSP_Cop0_MT; + RSP_Cop0[ 5] = rsp_UnknownOpcode; + RSP_Cop0[ 6] = rsp_UnknownOpcode; + RSP_Cop0[ 7] = rsp_UnknownOpcode; + RSP_Cop0[ 8] = rsp_UnknownOpcode; + RSP_Cop0[ 9] = rsp_UnknownOpcode; + RSP_Cop0[10] = rsp_UnknownOpcode; + RSP_Cop0[11] = rsp_UnknownOpcode; + RSP_Cop0[12] = rsp_UnknownOpcode; + RSP_Cop0[13] = rsp_UnknownOpcode; + RSP_Cop0[14] = rsp_UnknownOpcode; + RSP_Cop0[15] = rsp_UnknownOpcode; + RSP_Cop0[16] = rsp_UnknownOpcode; + RSP_Cop0[17] = rsp_UnknownOpcode; + RSP_Cop0[18] = rsp_UnknownOpcode; + RSP_Cop0[19] = rsp_UnknownOpcode; + RSP_Cop0[20] = rsp_UnknownOpcode; + RSP_Cop0[21] = rsp_UnknownOpcode; + RSP_Cop0[22] = rsp_UnknownOpcode; + RSP_Cop0[23] = rsp_UnknownOpcode; + RSP_Cop0[24] = rsp_UnknownOpcode; + RSP_Cop0[25] = rsp_UnknownOpcode; + RSP_Cop0[26] = rsp_UnknownOpcode; + RSP_Cop0[27] = rsp_UnknownOpcode; + RSP_Cop0[28] = rsp_UnknownOpcode; + RSP_Cop0[29] = rsp_UnknownOpcode; + RSP_Cop0[30] = rsp_UnknownOpcode; + RSP_Cop0[31] = rsp_UnknownOpcode; + + RSP_Cop2[ 0] = RSP_Cop2_MF; + RSP_Cop2[ 1] = rsp_UnknownOpcode; + RSP_Cop2[ 2] = RSP_Cop2_CF; + RSP_Cop2[ 3] = rsp_UnknownOpcode; + RSP_Cop2[ 4] = RSP_Cop2_MT; + RSP_Cop2[ 5] = rsp_UnknownOpcode; + RSP_Cop2[ 6] = RSP_Cop2_CT; + RSP_Cop2[ 7] = rsp_UnknownOpcode; + RSP_Cop2[ 8] = rsp_UnknownOpcode; + RSP_Cop2[ 9] = rsp_UnknownOpcode; + RSP_Cop2[10] = rsp_UnknownOpcode; + RSP_Cop2[11] = rsp_UnknownOpcode; + RSP_Cop2[12] = rsp_UnknownOpcode; + RSP_Cop2[13] = rsp_UnknownOpcode; + RSP_Cop2[14] = rsp_UnknownOpcode; + RSP_Cop2[15] = rsp_UnknownOpcode; + RSP_Cop2[16] = RSP_COP2_VECTOR; + RSP_Cop2[17] = RSP_COP2_VECTOR; + RSP_Cop2[18] = RSP_COP2_VECTOR; + RSP_Cop2[19] = RSP_COP2_VECTOR; + RSP_Cop2[20] = RSP_COP2_VECTOR; + RSP_Cop2[21] = RSP_COP2_VECTOR; + RSP_Cop2[22] = RSP_COP2_VECTOR; + RSP_Cop2[23] = RSP_COP2_VECTOR; + RSP_Cop2[24] = RSP_COP2_VECTOR; + RSP_Cop2[25] = RSP_COP2_VECTOR; + RSP_Cop2[26] = RSP_COP2_VECTOR; + RSP_Cop2[27] = RSP_COP2_VECTOR; + RSP_Cop2[28] = RSP_COP2_VECTOR; + RSP_Cop2[29] = RSP_COP2_VECTOR; + RSP_Cop2[30] = RSP_COP2_VECTOR; + RSP_Cop2[31] = RSP_COP2_VECTOR; + + RSP_Vector[ 0] = RSP_Vector_VMULF; + RSP_Vector[ 1] = RSP_Vector_VMULU; + RSP_Vector[ 2] = rsp_UnknownOpcode; + RSP_Vector[ 3] = rsp_UnknownOpcode; + RSP_Vector[ 4] = RSP_Vector_VMUDL; + RSP_Vector[ 5] = RSP_Vector_VMUDM; + RSP_Vector[ 6] = RSP_Vector_VMUDN; + RSP_Vector[ 7] = RSP_Vector_VMUDH; + RSP_Vector[ 8] = RSP_Vector_VMACF; + RSP_Vector[ 9] = RSP_Vector_VMACU; + RSP_Vector[10] = rsp_UnknownOpcode; + RSP_Vector[11] = RSP_Vector_VMACQ; + RSP_Vector[12] = RSP_Vector_VMADL; + RSP_Vector[13] = RSP_Vector_VMADM; + RSP_Vector[14] = RSP_Vector_VMADN; + RSP_Vector[15] = RSP_Vector_VMADH; + RSP_Vector[16] = RSP_Vector_VADD; + RSP_Vector[17] = RSP_Vector_VSUB; + RSP_Vector[18] = rsp_UnknownOpcode; + RSP_Vector[19] = RSP_Vector_VABS; + RSP_Vector[20] = RSP_Vector_VADDC; + RSP_Vector[21] = RSP_Vector_VSUBC; + RSP_Vector[22] = rsp_UnknownOpcode; + RSP_Vector[23] = rsp_UnknownOpcode; + RSP_Vector[24] = rsp_UnknownOpcode; + RSP_Vector[25] = rsp_UnknownOpcode; + RSP_Vector[26] = rsp_UnknownOpcode; + RSP_Vector[27] = rsp_UnknownOpcode; + RSP_Vector[28] = rsp_UnknownOpcode; + RSP_Vector[29] = RSP_Vector_VSAW; + RSP_Vector[30] = rsp_UnknownOpcode; + RSP_Vector[31] = rsp_UnknownOpcode; + RSP_Vector[32] = RSP_Vector_VLT; + RSP_Vector[33] = RSP_Vector_VEQ; + RSP_Vector[34] = RSP_Vector_VNE; + RSP_Vector[35] = RSP_Vector_VGE; + RSP_Vector[36] = RSP_Vector_VCL; + RSP_Vector[37] = RSP_Vector_VCH; + RSP_Vector[38] = RSP_Vector_VCR; + RSP_Vector[39] = RSP_Vector_VMRG; + RSP_Vector[40] = RSP_Vector_VAND; + RSP_Vector[41] = RSP_Vector_VNAND; + RSP_Vector[42] = RSP_Vector_VOR; + RSP_Vector[43] = RSP_Vector_VNOR; + RSP_Vector[44] = RSP_Vector_VXOR; + RSP_Vector[45] = RSP_Vector_VNXOR; + RSP_Vector[46] = rsp_UnknownOpcode; + RSP_Vector[47] = rsp_UnknownOpcode; + RSP_Vector[48] = RSP_Vector_VRCP; + RSP_Vector[49] = RSP_Vector_VRCPL; + RSP_Vector[50] = RSP_Vector_VRCPH; + RSP_Vector[51] = RSP_Vector_VMOV; + RSP_Vector[52] = RSP_Vector_VRSQ; + RSP_Vector[53] = RSP_Vector_VRSQL; + RSP_Vector[54] = RSP_Vector_VRSQH; + RSP_Vector[55] = RSP_Vector_VNOOP; + RSP_Vector[56] = rsp_UnknownOpcode; + RSP_Vector[57] = rsp_UnknownOpcode; + RSP_Vector[58] = rsp_UnknownOpcode; + RSP_Vector[59] = rsp_UnknownOpcode; + RSP_Vector[60] = rsp_UnknownOpcode; + RSP_Vector[61] = rsp_UnknownOpcode; + RSP_Vector[62] = rsp_UnknownOpcode; + RSP_Vector[63] = rsp_UnknownOpcode; + + RSP_Lc2[ 0] = RSP_Opcode_LBV; + RSP_Lc2[ 1] = RSP_Opcode_LSV; + RSP_Lc2[ 2] = RSP_Opcode_LLV; + RSP_Lc2[ 3] = RSP_Opcode_LDV; + RSP_Lc2[ 4] = RSP_Opcode_LQV; + RSP_Lc2[ 5] = RSP_Opcode_LRV; + RSP_Lc2[ 6] = RSP_Opcode_LPV; + RSP_Lc2[ 7] = RSP_Opcode_LUV; + RSP_Lc2[ 8] = RSP_Opcode_LHV; + RSP_Lc2[ 9] = RSP_Opcode_LFV; + RSP_Lc2[10] = rsp_UnknownOpcode; + RSP_Lc2[11] = RSP_Opcode_LTV; + RSP_Lc2[12] = rsp_UnknownOpcode; + RSP_Lc2[13] = rsp_UnknownOpcode; + RSP_Lc2[14] = rsp_UnknownOpcode; + RSP_Lc2[15] = rsp_UnknownOpcode; + RSP_Lc2[16] = rsp_UnknownOpcode; + RSP_Lc2[17] = rsp_UnknownOpcode; + RSP_Lc2[18] = rsp_UnknownOpcode; + RSP_Lc2[19] = rsp_UnknownOpcode; + RSP_Lc2[20] = rsp_UnknownOpcode; + RSP_Lc2[21] = rsp_UnknownOpcode; + RSP_Lc2[22] = rsp_UnknownOpcode; + RSP_Lc2[23] = rsp_UnknownOpcode; + RSP_Lc2[24] = rsp_UnknownOpcode; + RSP_Lc2[25] = rsp_UnknownOpcode; + RSP_Lc2[26] = rsp_UnknownOpcode; + RSP_Lc2[27] = rsp_UnknownOpcode; + RSP_Lc2[28] = rsp_UnknownOpcode; + RSP_Lc2[29] = rsp_UnknownOpcode; + RSP_Lc2[30] = rsp_UnknownOpcode; + RSP_Lc2[31] = rsp_UnknownOpcode; + + RSP_Sc2[ 0] = RSP_Opcode_SBV; + RSP_Sc2[ 1] = RSP_Opcode_SSV; + RSP_Sc2[ 2] = RSP_Opcode_SLV; + RSP_Sc2[ 3] = RSP_Opcode_SDV; + RSP_Sc2[ 4] = RSP_Opcode_SQV; + RSP_Sc2[ 5] = RSP_Opcode_SRV; + RSP_Sc2[ 6] = RSP_Opcode_SPV; + RSP_Sc2[ 7] = RSP_Opcode_SUV; + RSP_Sc2[ 8] = RSP_Opcode_SHV; + RSP_Sc2[ 9] = RSP_Opcode_SFV; + RSP_Sc2[10] = RSP_Opcode_SWV; + RSP_Sc2[11] = RSP_Opcode_STV; + RSP_Sc2[12] = rsp_UnknownOpcode; + RSP_Sc2[13] = rsp_UnknownOpcode; + RSP_Sc2[14] = rsp_UnknownOpcode; + RSP_Sc2[15] = rsp_UnknownOpcode; + RSP_Sc2[16] = rsp_UnknownOpcode; + RSP_Sc2[17] = rsp_UnknownOpcode; + RSP_Sc2[18] = rsp_UnknownOpcode; + RSP_Sc2[19] = rsp_UnknownOpcode; + RSP_Sc2[20] = rsp_UnknownOpcode; + RSP_Sc2[21] = rsp_UnknownOpcode; + RSP_Sc2[22] = rsp_UnknownOpcode; + RSP_Sc2[23] = rsp_UnknownOpcode; + RSP_Sc2[24] = rsp_UnknownOpcode; + RSP_Sc2[25] = rsp_UnknownOpcode; + RSP_Sc2[26] = rsp_UnknownOpcode; + RSP_Sc2[27] = rsp_UnknownOpcode; + RSP_Sc2[28] = rsp_UnknownOpcode; + RSP_Sc2[29] = rsp_UnknownOpcode; + RSP_Sc2[30] = rsp_UnknownOpcode; + RSP_Sc2[31] = rsp_UnknownOpcode; +} + +DWORD RunInterpreterCPU(DWORD Cycles) { + DWORD CycleCount; + RSP_Running = TRUE; + Enable_RSP_Commands_Window(); + CycleCount = 0; + + while (RSP_Running) { + if (NoOfBpoints != 0) { + if (CheckForRSPBPoint(*PrgCount)) { + if (InRSPCommandsWindow) { + Enter_RSP_Commands_Window(); + if (Stepping_Commands) { + DisplayError ( "Encounted a R4300i Breakpoint" ); + } else { + DisplayError ( "Encounted a R4300i Breakpoint\n\nNow Stepping" ); + SetRSPCommandViewto( *PrgCount ); + SetRSPCommandToStepping(); + } + } else { + DisplayError ( "Encounted a RSP Breakpoint\n\nEntering Command Window" ); + Enter_RSP_Commands_Window(); + } + } + } + + if (Stepping_Commands) { + WaitingForStep = TRUE; + SetRSPCommandViewto( *PrgCount ); + UpdateRSPRegistersScreen(); + while ( WaitingForStep == TRUE ){ + Sleep(20); + if (!Stepping_Commands) { + WaitingForStep = FALSE; + } + } + } + + + RDP_LogLoc(*PrgCount); + + RSP_LW_IMEM(*PrgCount, &RSPOpC.Hex); + ((void (*)()) RSP_Opcode[ RSPOpC.op ])(); + + switch (RSP_NextInstruction) { + case NORMAL: + *PrgCount = (*PrgCount + 4) & 0xFFC; + break; + case DELAY_SLOT: + RSP_NextInstruction = JUMP; + *PrgCount = (*PrgCount + 4) & 0xFFC; + break; + case JUMP: + RSP_NextInstruction = NORMAL; + *PrgCount = RSP_JumpTo; + break; + } + } + *PrgCount -= 4; + + return Cycles; +} + diff --git a/Source/RSP/Interpreter CPU.h b/Source/RSP/Interpreter CPU.h new file mode 100644 index 000000000..7430dfa48 --- /dev/null +++ b/Source/RSP/Interpreter CPU.h @@ -0,0 +1,34 @@ +/* + * RSP Compiler plug in for Project 64 (A Nintendo 64 emulator). + * + * (c) Copyright 2001 jabo (jabo@emulation64.com) and + * zilmar (zilmar@emulation64.com) + * + * pj64 homepage: www.pj64.net + * + * Permission to use, copy, modify and distribute Project64 in both binary and + * source form, for non-commercial purposes, is hereby granted without fee, + * providing that this license information and copyright notice appear with + * all copies and any derived work. + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event shall the authors be held liable for any damages + * arising from the use of this software. + * + * Project64 is freeware for PERSONAL USE only. Commercial users should + * seek permission of the copyright holders first. Commercial use includes + * charging money for Project64 or software derived from Project64. + * + * The copyright holders request that bug fixes and improvements to the code + * should be forwarded to them so if they want them. + * + */ + +#define NORMAL 0 +#define DELAY_SLOT 1 +#define JUMP 2 + +extern DWORD RSP_NextInstruction, RSP_JumpTo; + +void BuildInterpreterCPU(void); +DWORD RunInterpreterCPU(DWORD Cycles); \ No newline at end of file diff --git a/Source/RSP/Interpreter Ops.c b/Source/RSP/Interpreter Ops.c new file mode 100644 index 000000000..59538d9eb --- /dev/null +++ b/Source/RSP/Interpreter Ops.c @@ -0,0 +1,1902 @@ +/* + * RSP Compiler plug in for Project 64 (A Nintendo 64 emulator). + * + * (c) Copyright 2001 jabo (jabo@emulation64.com) and + * zilmar (zilmar@emulation64.com) + * + * pj64 homepage: www.pj64.net + * + * Permission to use, copy, modify and distribute Project64 in both binary and + * source form, for non-commercial purposes, is hereby granted without fee, + * providing that this license information and copyright notice appear with + * all copies and any derived work. + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event shall the authors be held liable for any damages + * arising from the use of this software. + * + * Project64 is freeware for PERSONAL USE only. Commercial users should + * seek permission of the copyright holders first. Commercial use includes + * charging money for Project64 or software derived from Project64. + * + * The copyright holders request that bug fixes and improvements to the code + * should be forwarded to them so if they want them. + * + */ + +#include +#include +#include +#include +#include "RSP.h" +#include "CPU.h" +#include "RSP Command.h" +#include "RSP Registers.h" +#include "Interpreter CPU.h" +#include "memory.h" +#include "dma.h" +#include "log.h" +#include "x86.h" + +extern UWORD32 Recp, RecpResult, SQroot, SQrootResult; + +/************************* OpCode functions *************************/ +void RSP_Opcode_SPECIAL ( void ) { + ((void (*)()) RSP_Special[ RSPOpC.funct ])(); +} + +void RSP_Opcode_REGIMM ( void ) { + ((void (*)()) RSP_RegImm[ RSPOpC.rt ])(); +} + +void RSP_Opcode_J ( void ) { + RSP_NextInstruction = DELAY_SLOT; + RSP_JumpTo = (RSPOpC.target << 2) & 0xFFC; +} + +void RSP_Opcode_JAL ( void ) { + RSP_NextInstruction = DELAY_SLOT; + RSP_GPR[31].UW = ( *PrgCount + 8 ) & 0xFFC; + RSP_JumpTo = (RSPOpC.target << 2) & 0xFFC; +} + +void RSP_Opcode_BEQ ( void ) { + RSP_NextInstruction = DELAY_SLOT; + if (RSP_GPR[RSPOpC.rs].W == RSP_GPR[RSPOpC.rt].W) { + RSP_JumpTo = ( *PrgCount + ((short)RSPOpC.offset << 2) + 4 ) & 0xFFC; + } else { + RSP_JumpTo = ( *PrgCount + 8 ) & 0xFFC; + } +} + +void RSP_Opcode_BNE ( void ) { + RSP_NextInstruction = DELAY_SLOT; + if (RSP_GPR[RSPOpC.rs].W != RSP_GPR[RSPOpC.rt].W) { + RSP_JumpTo = ( *PrgCount + ((short)RSPOpC.offset << 2) + 4 ) & 0xFFC; + } else { + RSP_JumpTo = ( *PrgCount + 8 ) & 0xFFC; + } +} + +void RSP_Opcode_BLEZ ( void ) { + RSP_NextInstruction = DELAY_SLOT; + if (RSP_GPR[RSPOpC.rs].W <= 0) { + RSP_JumpTo = ( *PrgCount + ((short)RSPOpC.offset << 2) + 4 ) & 0xFFC; + } else { + RSP_JumpTo = ( *PrgCount + 8 ) & 0xFFC; + } +} + +void RSP_Opcode_BGTZ ( void ) { + RSP_NextInstruction = DELAY_SLOT; + if (RSP_GPR[RSPOpC.rs].W > 0) { + RSP_JumpTo = ( *PrgCount + ((short)RSPOpC.offset << 2) + 4 ) & 0xFFC; + } else { + RSP_JumpTo = ( *PrgCount + 8 ) & 0xFFC; + } +} + +void RSP_Opcode_ADDI ( void ) { + if (RSPOpC.rt != 0) { + RSP_GPR[RSPOpC.rt].W = RSP_GPR[RSPOpC.rs].W + (short)RSPOpC.immediate; + } +} + +void RSP_Opcode_ADDIU ( void ) { + if (RSPOpC.rt != 0) { + RSP_GPR[RSPOpC.rt].UW = RSP_GPR[RSPOpC.rs].UW + (DWORD)((short)RSPOpC.immediate); + } +} + +void RSP_Opcode_SLTI (void) { + if (RSPOpC.rt == 0) { return; } + if (RSP_GPR[RSPOpC.rs].W < (short)RSPOpC.immediate) { + RSP_GPR[RSPOpC.rt].W = 1; + } else { + RSP_GPR[RSPOpC.rt].W = 0; + } +} + +void RSP_Opcode_SLTIU (void) { + if (RSPOpC.rt == 0) { return; } + if (RSP_GPR[RSPOpC.rs].UW < (DWORD)(short)RSPOpC.immediate) { + RSP_GPR[RSPOpC.rt].W = 1; + } else { + RSP_GPR[RSPOpC.rt].W = 0; + } +} + +void RSP_Opcode_ANDI ( void ) { + if (RSPOpC.rt != 0) { + 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; + } +} + +void RSP_Opcode_XORI ( void ) { + if (RSPOpC.rt != 0) { + 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 = (short)RSPOpC.offset << 16; + } +} + +void RSP_Opcode_COP0 (void) { + ((void (*)()) RSP_Cop0[ RSPOpC.rs ])(); +} + +void RSP_Opcode_COP2 (void) { + ((void (*)()) RSP_Cop2[ RSPOpC.rs ])(); +} + +void RSP_Opcode_LB ( void ) { + DWORD Address = ((RSP_GPR[RSPOpC.base].UW + (short)RSPOpC.offset) & 0xFFF); + RSP_LB_DMEM( Address, &RSP_GPR[RSPOpC.rt].UB[0] ); + RSP_GPR[RSPOpC.rt].W = RSP_GPR[RSPOpC.rt].B[0]; +} + +void RSP_Opcode_LH ( void ) { + DWORD Address = ((RSP_GPR[RSPOpC.base].UW + (short)RSPOpC.offset) & 0xFFF); + RSP_LH_DMEM( Address, &RSP_GPR[RSPOpC.rt].UHW[0] ); + RSP_GPR[RSPOpC.rt].W = RSP_GPR[RSPOpC.rt].HW[0]; +} + +void RSP_Opcode_LW ( void ) { + DWORD Address = ((RSP_GPR[RSPOpC.base].UW + (short)RSPOpC.offset) & 0xFFF); + RSP_LW_DMEM( Address, &RSP_GPR[RSPOpC.rt].UW ); +} + +void RSP_Opcode_LBU ( void ) { + DWORD Address = ((RSP_GPR[RSPOpC.base].UW + (short)RSPOpC.offset) & 0xFFF); + RSP_LB_DMEM( Address, &RSP_GPR[RSPOpC.rt].UB[0] ); + RSP_GPR[RSPOpC.rt].UW = RSP_GPR[RSPOpC.rt].UB[0]; +} + +void RSP_Opcode_LHU ( void ) { + DWORD Address = ((RSP_GPR[RSPOpC.base].UW + (short)RSPOpC.offset) & 0xFFF); + RSP_LH_DMEM( Address, &RSP_GPR[RSPOpC.rt].UHW[0] ); + RSP_GPR[RSPOpC.rt].UW = RSP_GPR[RSPOpC.rt].UHW[0]; +} + +void RSP_Opcode_SB ( void ) { + DWORD Address = ((RSP_GPR[RSPOpC.base].UW + (short)RSPOpC.offset) & 0xFFF); + RSP_SB_DMEM( Address, RSP_GPR[RSPOpC.rt].UB[0] ); +} + +void RSP_Opcode_SH ( void ) { + DWORD Address = ((RSP_GPR[RSPOpC.base].UW + (short)RSPOpC.offset) & 0xFFF); + RSP_SH_DMEM( Address, RSP_GPR[RSPOpC.rt].UHW[0] ); +} + +void RSP_Opcode_SW ( void ) { + DWORD Address = ((RSP_GPR[RSPOpC.base].UW + (short)RSPOpC.offset) & 0xFFF); + RSP_SW_DMEM( Address, RSP_GPR[RSPOpC.rt].UW ); +} + +void RSP_Opcode_LC2 (void) { + ((void (*)()) RSP_Lc2 [ RSPOpC.rd ])(); +} + +void RSP_Opcode_SC2 (void) { + ((void (*)()) RSP_Sc2 [ RSPOpC.rd ])(); +} +/********************** R4300i OpCodes: Special **********************/ +void RSP_Special_SLL ( void ) { + if (RSPOpC.rd != 0) { + 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; + } +} + +void RSP_Special_SRA ( void ) { + if (RSPOpC.rd != 0) { + 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); + } +} + +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); + } +} + +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); + } +} + +void RSP_Special_JR (void) { + RSP_NextInstruction = DELAY_SLOT; + RSP_JumpTo = (RSP_GPR[RSPOpC.rs].W & 0xFFC); +} + +void RSP_Special_JALR (void) { + RSP_NextInstruction = DELAY_SLOT; + RSP_GPR[RSPOpC.rd].W = (*PrgCount + 8) & 0xFFC; + RSP_JumpTo = (RSP_GPR[RSPOpC.rs].W & 0xFFC); +} + +void RSP_Special_BREAK ( void ) { + RSP_Running = FALSE; + *RSPInfo.SP_STATUS_REG |= (SP_STATUS_HALT | SP_STATUS_BROKE ); + if ((*RSPInfo.SP_STATUS_REG & SP_STATUS_INTR_BREAK) != 0 ) { + *RSPInfo.MI_INTR_REG |= R4300i_SP_Intr; + RSPInfo.CheckInterrupts(); + } +} + +void RSP_Special_ADD (void) { + if (RSPOpC.rd != 0) { + 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; + } +} + +void RSP_Special_SUB (void) { + if (RSPOpC.rd != 0) { + 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; + } +} + +void RSP_Special_AND (void) { + if (RSPOpC.rd != 0) { + 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; + } +} + +void RSP_Special_XOR (void) { + if (RSPOpC.rd != 0) { + 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); + } +} + +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 { + RSP_GPR[RSPOpC.rd].UW = 0; + } +} + +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 { + RSP_GPR[RSPOpC.rd].UW = 0; + } +} +/********************** R4300i OpCodes: RegImm **********************/ +void RSP_Opcode_BLTZ ( void ) { + RSP_NextInstruction = DELAY_SLOT; + if (RSP_GPR[RSPOpC.rs].W < 0) { + RSP_JumpTo = ( *PrgCount + ((short)RSPOpC.offset << 2) + 4 ) & 0xFFC; + } else { + RSP_JumpTo = ( *PrgCount + 8 ) & 0xFFC; + } +} + +void RSP_Opcode_BGEZ ( void ) { + RSP_NextInstruction = DELAY_SLOT; + if (RSP_GPR[RSPOpC.rs].W >= 0) { + RSP_JumpTo = ( *PrgCount + ((short)RSPOpC.offset << 2) + 4 ) & 0xFFC; + } else { + RSP_JumpTo = ( *PrgCount + 8 ) & 0xFFC; + } +} + +void RSP_Opcode_BLTZAL ( void ) { + RSP_NextInstruction = DELAY_SLOT; + RSP_GPR[31].UW = ( *PrgCount + 8 ) & 0xFFC; + if (RSP_GPR[RSPOpC.rs].W < 0) { + RSP_JumpTo = ( *PrgCount + ((short)RSPOpC.offset << 2) + 4 ) & 0xFFC; + } else { + RSP_JumpTo = ( *PrgCount + 8 ) & 0xFFC; + } +} + +void RSP_Opcode_BGEZAL ( void ) { + RSP_NextInstruction = DELAY_SLOT; + RSP_GPR[31].UW = ( *PrgCount + 8 ) & 0xFFC; + if (RSP_GPR[RSPOpC.rs].W >= 0) { + RSP_JumpTo = ( *PrgCount + ((short)RSPOpC.offset << 2) + 4 ) & 0xFFC; + } else { + RSP_JumpTo = ( *PrgCount + 8 ) & 0xFFC; + } +} +/************************** Cop0 functions *************************/ +void RSP_Cop0_MF (void) { + if (LogRDP && CPUCore == InterpreterCPU) + { + RDP_LogMF0(*PrgCount,RSPOpC.rd); + } + switch (RSPOpC.rd) { + case 4: RSP_GPR[RSPOpC.rt].UW = *RSPInfo.SP_STATUS_REG; break; + case 5: RSP_GPR[RSPOpC.rt].UW = *RSPInfo.SP_DMA_FULL_REG; break; + case 6: RSP_GPR[RSPOpC.rt].UW = *RSPInfo.SP_DMA_BUSY_REG; break; + case 7: + RSP_GPR[RSPOpC.rt].W = 0; + //RSP_GPR[RSPOpC.rt].W = *RSPInfo.SP_SEMAPHORE_REG; + //*RSPInfo.SP_SEMAPHORE_REG = 1; + break; + case 8: RSP_GPR[RSPOpC.rt].UW = *RSPInfo.DPC_START_REG ; break; + case 9: RSP_GPR[RSPOpC.rt].UW = *RSPInfo.DPC_END_REG ; break; + case 10: RSP_GPR[RSPOpC.rt].UW = *RSPInfo.DPC_CURRENT_REG; break; + case 11: RSP_GPR[RSPOpC.rt].W = *RSPInfo.DPC_STATUS_REG; break; + case 12: RSP_GPR[RSPOpC.rt].W = *RSPInfo.DPC_CLOCK_REG; break; + default: + DisplayError("have not implemented RSP MF CP0 reg %s (%d)",COP0_Name(RSPOpC.rd),RSPOpC.rd); + } +} + +void RSP_Cop0_MT (void) { + if (LogRDP && CPUCore == InterpreterCPU) + { + RDP_LogMT0(*PrgCount,RSPOpC.rd, RSP_GPR[RSPOpC.rt].UW); + } + switch (RSPOpC.rd) { + case 0: *RSPInfo.SP_MEM_ADDR_REG = RSP_GPR[RSPOpC.rt].UW; break; + case 1: *RSPInfo.SP_DRAM_ADDR_REG = RSP_GPR[RSPOpC.rt].UW; break; + case 2: + *RSPInfo.SP_RD_LEN_REG = RSP_GPR[RSPOpC.rt].UW; + SP_DMA_READ(); + break; + case 3: + *RSPInfo.SP_WR_LEN_REG = RSP_GPR[RSPOpC.rt].UW; + SP_DMA_WRITE(); + break; + case 4: + if ( ( RSP_GPR[RSPOpC.rt].W & SP_CLR_HALT ) != 0) { *RSPInfo.SP_STATUS_REG &= ~SP_STATUS_HALT; } + if ( ( RSP_GPR[RSPOpC.rt].W & SP_SET_HALT ) != 0) { *RSPInfo.SP_STATUS_REG |= SP_STATUS_HALT; } + if ( ( RSP_GPR[RSPOpC.rt].W & SP_CLR_BROKE ) != 0) { *RSPInfo.SP_STATUS_REG &= ~SP_STATUS_BROKE; } + if ( ( RSP_GPR[RSPOpC.rt].W & SP_CLR_INTR ) != 0) { *RSPInfo.MI_INTR_REG &= ~R4300i_SP_Intr; } + if ( ( RSP_GPR[RSPOpC.rt].W & SP_SET_INTR ) != 0) { DisplayError("SP_SET_INTR"); } + if ( ( RSP_GPR[RSPOpC.rt].W & SP_CLR_SSTEP ) != 0) { *RSPInfo.SP_STATUS_REG &= ~SP_STATUS_SSTEP; } + if ( ( RSP_GPR[RSPOpC.rt].W & SP_SET_SSTEP ) != 0) { *RSPInfo.SP_STATUS_REG |= SP_STATUS_SSTEP; } + if ( ( RSP_GPR[RSPOpC.rt].W & SP_CLR_INTR_BREAK ) != 0) { *RSPInfo.SP_STATUS_REG &= ~SP_STATUS_INTR_BREAK; } + if ( ( RSP_GPR[RSPOpC.rt].W & SP_SET_INTR_BREAK ) != 0) { *RSPInfo.SP_STATUS_REG |= SP_STATUS_INTR_BREAK; } + if ( ( RSP_GPR[RSPOpC.rt].W & SP_CLR_SIG0 ) != 0) { *RSPInfo.SP_STATUS_REG &= ~SP_STATUS_SIG0; } + if ( ( RSP_GPR[RSPOpC.rt].W & SP_SET_SIG0 ) != 0) { *RSPInfo.SP_STATUS_REG |= SP_STATUS_SIG0; } + if ( ( RSP_GPR[RSPOpC.rt].W & SP_CLR_SIG1 ) != 0) { *RSPInfo.SP_STATUS_REG &= ~SP_STATUS_SIG1; } + if ( ( RSP_GPR[RSPOpC.rt].W & SP_SET_SIG1 ) != 0) { *RSPInfo.SP_STATUS_REG |= SP_STATUS_SIG1; } + if ( ( RSP_GPR[RSPOpC.rt].W & SP_CLR_SIG2 ) != 0) { *RSPInfo.SP_STATUS_REG &= ~SP_STATUS_SIG2; } + if ( ( RSP_GPR[RSPOpC.rt].W & SP_SET_SIG2 ) != 0) { *RSPInfo.SP_STATUS_REG |= SP_STATUS_SIG2; } + if ( ( RSP_GPR[RSPOpC.rt].W & SP_CLR_SIG3 ) != 0) { *RSPInfo.SP_STATUS_REG &= ~SP_STATUS_SIG3; } + if ( ( RSP_GPR[RSPOpC.rt].W & SP_SET_SIG3 ) != 0) { *RSPInfo.SP_STATUS_REG |= SP_STATUS_SIG3; } + if ( ( RSP_GPR[RSPOpC.rt].W & SP_CLR_SIG4 ) != 0) { *RSPInfo.SP_STATUS_REG &= ~SP_STATUS_SIG4; } + if ( ( RSP_GPR[RSPOpC.rt].W & SP_SET_SIG4 ) != 0) { *RSPInfo.SP_STATUS_REG |= SP_STATUS_SIG4; } + if ( ( RSP_GPR[RSPOpC.rt].W & SP_CLR_SIG5 ) != 0) { *RSPInfo.SP_STATUS_REG &= ~SP_STATUS_SIG5; } + if ( ( RSP_GPR[RSPOpC.rt].W & SP_SET_SIG5 ) != 0) { *RSPInfo.SP_STATUS_REG |= SP_STATUS_SIG5; } + if ( ( RSP_GPR[RSPOpC.rt].W & SP_CLR_SIG6 ) != 0) { *RSPInfo.SP_STATUS_REG &= ~SP_STATUS_SIG6; } + if ( ( RSP_GPR[RSPOpC.rt].W & SP_SET_SIG6 ) != 0) { *RSPInfo.SP_STATUS_REG |= SP_STATUS_SIG6; } + if ( ( RSP_GPR[RSPOpC.rt].W & SP_CLR_SIG7 ) != 0) { *RSPInfo.SP_STATUS_REG &= ~SP_STATUS_SIG7; } + if ( ( RSP_GPR[RSPOpC.rt].W & SP_SET_SIG7 ) != 0) { *RSPInfo.SP_STATUS_REG |= SP_STATUS_SIG7; } + break; + case 7: *RSPInfo.SP_SEMAPHORE_REG = 0; break; + case 8: + *RSPInfo.DPC_START_REG = RSP_GPR[RSPOpC.rt].UW; + *RSPInfo.DPC_CURRENT_REG = RSP_GPR[RSPOpC.rt].UW; + break; + case 9: + *RSPInfo.DPC_END_REG = RSP_GPR[RSPOpC.rt].UW; + RDP_LogDlist(); + if (RSPInfo.ProcessRdpList != NULL) { RSPInfo.ProcessRdpList(); } + break; + case 10: *RSPInfo.DPC_CURRENT_REG = RSP_GPR[RSPOpC.rt].UW; break; + case 11: + if ( ( RSP_GPR[RSPOpC.rt].W & DPC_CLR_XBUS_DMEM_DMA ) != 0) { *RSPInfo.DPC_STATUS_REG &= ~DPC_STATUS_XBUS_DMEM_DMA; } + if ( ( RSP_GPR[RSPOpC.rt].W & DPC_SET_XBUS_DMEM_DMA ) != 0) { *RSPInfo.DPC_STATUS_REG |= DPC_STATUS_XBUS_DMEM_DMA; } + if ( ( RSP_GPR[RSPOpC.rt].W & DPC_CLR_FREEZE ) != 0) { *RSPInfo.DPC_STATUS_REG &= ~DPC_STATUS_FREEZE; } + if ( ( RSP_GPR[RSPOpC.rt].W & DPC_SET_FREEZE ) != 0) { *RSPInfo.DPC_STATUS_REG |= DPC_STATUS_FREEZE; } + if ( ( RSP_GPR[RSPOpC.rt].W & DPC_CLR_FLUSH ) != 0) { *RSPInfo.DPC_STATUS_REG &= ~DPC_STATUS_FLUSH; } + if ( ( RSP_GPR[RSPOpC.rt].W & DPC_SET_FLUSH ) != 0) { *RSPInfo.DPC_STATUS_REG |= DPC_STATUS_FLUSH; } + if ( ( RSP_GPR[RSPOpC.rt].W & DPC_CLR_TMEM_CTR ) != 0) { /* DisplayError("RSP: DPC_STATUS_REG: DPC_CLR_TMEM_CTR"); */ } + if ( ( RSP_GPR[RSPOpC.rt].W & DPC_CLR_PIPE_CTR ) != 0) { DisplayError("RSP: DPC_STATUS_REG: DPC_CLR_PIPE_CTR"); } + if ( ( RSP_GPR[RSPOpC.rt].W & DPC_CLR_CMD_CTR ) != 0) { DisplayError("RSP: DPC_STATUS_REG: DPC_CLR_CMD_CTR"); } + if ( ( RSP_GPR[RSPOpC.rt].W & DPC_CLR_CLOCK_CTR ) != 0) { /* DisplayError("RSP: DPC_STATUS_REG: DPC_CLR_CLOCK_CTR"); */ } + break; + default: + DisplayError("have not implemented RSP MT CP0 reg %s (%d)",COP0_Name(RSPOpC.rd),RSPOpC.rd); + } +} + +/************************** Cop2 functions *************************/ +void RSP_Cop2_MF (void) { + int element = (RSPOpC.sa >> 1); + RSP_GPR[RSPOpC.rt].B[1] = RSP_Vect[RSPOpC.rd].B[15 - element]; + RSP_GPR[RSPOpC.rt].B[0] = RSP_Vect[RSPOpC.rd].B[15 - ((element + 1) % 16)]; + RSP_GPR[RSPOpC.rt].W = RSP_GPR[RSPOpC.rt].HW[0]; +} + +void RSP_Cop2_CF (void) { + switch ((RSPOpC.rd & 0x03)) { + case 0: RSP_GPR[RSPOpC.rt].W = RSP_Flags[0].HW[0]; break; + case 1: RSP_GPR[RSPOpC.rt].W = RSP_Flags[1].HW[0]; break; + case 2: RSP_GPR[RSPOpC.rt].W = RSP_Flags[2].HW[0]; break; + case 3: RSP_GPR[RSPOpC.rt].W = RSP_Flags[2].HW[0]; break; + } +} + +void RSP_Cop2_MT (void) { + int element = 15 - (RSPOpC.sa >> 1); + RSP_Vect[RSPOpC.rd].B[element] = RSP_GPR[RSPOpC.rt].B[1]; + if (element != 0) { + RSP_Vect[RSPOpC.rd].B[element - 1] = RSP_GPR[RSPOpC.rt].B[0]; + } +} + +void RSP_Cop2_CT (void) { + switch ((RSPOpC.rd & 0x03)) { + case 0: RSP_Flags[0].HW[0] = RSP_GPR[RSPOpC.rt].HW[0]; break; + case 1: RSP_Flags[1].HW[0] = RSP_GPR[RSPOpC.rt].HW[0]; break; + case 2: RSP_Flags[2].B[0] = RSP_GPR[RSPOpC.rt].B[0]; break; + case 3: RSP_Flags[2].B[0] = RSP_GPR[RSPOpC.rt].B[0]; break; + } +} + +void RSP_COP2_VECTOR (void) { + ((void (*)()) RSP_Vector[ RSPOpC.funct ])(); +} +/************************** Vect functions **************************/ +void RSP_Vector_VMULF (void) { + int count, el, del; + UWORD32 temp; + + for (count = 0; count < 8; count ++ ) { + el = Indx[RSPOpC.rs].B[count]; + del = EleSpec[RSPOpC.rs].B[el]; + + if (RSP_Vect[RSPOpC.rd].UHW[el] != 0x8000 || RSP_Vect[RSPOpC.rt].UHW[del] != 0x8000) { + temp.W = ((long)RSP_Vect[RSPOpC.rd].HW[el] * (long)RSP_Vect[RSPOpC.rt].HW[del]) << 1; + temp.UW += 0x8000; + RSP_ACCUM[el].HW[2] = temp.HW[1]; + RSP_ACCUM[el].HW[1] = temp.HW[0]; + if ( RSP_ACCUM[el].HW[2] < 0 ) { + RSP_ACCUM[el].HW[3] = -1; + } else { + RSP_ACCUM[el].HW[3] = 0; + } + RSP_Vect[RSPOpC.sa].HW[el] = RSP_ACCUM[el].HW[2]; + } else { + temp.W = 0x80000000; + RSP_ACCUM[el].UHW[3] = 0; + RSP_ACCUM[el].UHW[2] = 0x8000; + RSP_ACCUM[el].UHW[1] = 0x8000; + RSP_Vect[RSPOpC.sa].HW[el] = 0x7FFF; + } + } +} + +void RSP_Vector_VMULU (void) { + int count, el, del; + + for (count = 0; count < 8; count ++ ) { + el = Indx[RSPOpC.rs].B[count]; + del = EleSpec[RSPOpC.rs].B[el]; + RSP_ACCUM[el].DW = (__int64)(RSP_Vect[RSPOpC.rd].HW[el] * RSP_Vect[RSPOpC.rt].HW[del]) << 17; + RSP_ACCUM[el].DW += 0x80000000; + if (RSP_ACCUM[el].DW < 0) { + RSP_Vect[RSPOpC.sa].HW[el] = 0; + } else if ((short)(RSP_ACCUM[el].UHW[3] ^ RSP_ACCUM[el].UHW[2]) < 0) { + RSP_Vect[RSPOpC.sa].HW[el] = -1; + } else { + RSP_Vect[RSPOpC.sa].HW[el] = RSP_ACCUM[el].HW[2]; + } + } +} + +void RSP_Vector_VMUDL (void) { + int count, el, del; + UWORD32 temp; + + for (count = 0; count < 8; count ++ ) { + el = Indx[RSPOpC.rs].B[count]; + del = EleSpec[RSPOpC.rs].B[el]; + + temp.UW = (DWORD)RSP_Vect[RSPOpC.rd].UHW[el] * (DWORD)RSP_Vect[RSPOpC.rt].UHW[del]; + RSP_ACCUM[el].W[1] = 0; + RSP_ACCUM[el].HW[1] = temp.HW[1]; + RSP_Vect[RSPOpC.sa].HW[el] = RSP_ACCUM[el].HW[1]; + + } +} + +void RSP_Vector_VMUDM (void) { + int count, el, del; + UWORD32 temp; + + for (count = 0; count < 8; count ++ ) { + el = Indx[RSPOpC.rs].B[count]; + del = EleSpec[RSPOpC.rs].B[el]; + + temp.UW = (DWORD)((long)RSP_Vect[RSPOpC.rd].HW[el]) * (DWORD)RSP_Vect[RSPOpC.rt].UHW[del]; + if (temp.W < 0) { + RSP_ACCUM[el].HW[3] = -1; + } else { + RSP_ACCUM[el].HW[3] = 0; + } + RSP_ACCUM[el].HW[2] = temp.HW[1]; + RSP_ACCUM[el].HW[1] = temp.HW[0]; + RSP_Vect[RSPOpC.sa].HW[el] = RSP_ACCUM[el].HW[2]; + } +} + +void RSP_Vector_VMUDN (void) { + int count, el, del; + UWORD32 temp; + + for (count = 0; count < 8; count ++ ) { + el = Indx[RSPOpC.rs].B[count]; + del = EleSpec[RSPOpC.rs].B[el]; + + temp.UW = (DWORD)RSP_Vect[RSPOpC.rd].UHW[el] * (DWORD)(long)(RSP_Vect[RSPOpC.rt].HW[del]); + if (temp.W < 0) { + RSP_ACCUM[el].HW[3] = -1; + } else { + RSP_ACCUM[el].HW[3] = 0; + } + RSP_ACCUM[el].HW[2] = temp.HW[1]; + RSP_ACCUM[el].HW[1] = temp.HW[0]; + RSP_Vect[RSPOpC.sa].HW[el] = RSP_ACCUM[el].HW[1]; + } +} + +void RSP_Vector_VMUDH (void) { + int count, el, del; + + for (count = 0; count < 8; count ++ ) { + el = Indx[RSPOpC.rs].B[count]; + del = EleSpec[RSPOpC.rs].B[el]; + + RSP_ACCUM[el].W[1] = (long)RSP_Vect[RSPOpC.rd].HW[el] * (long)RSP_Vect[RSPOpC.rt].HW[del]; + RSP_ACCUM[el].HW[1] = 0; + if (RSP_ACCUM[el].HW[3] < 0) { + if (RSP_ACCUM[el].UHW[3] != 0xFFFF) { + RSP_Vect[RSPOpC.sa].HW[el] = (WORD)0x8000; + } else { + if (RSP_ACCUM[el].HW[2] >= 0) { + RSP_Vect[RSPOpC.sa].HW[el] = (WORD)0x8000; + } else { + RSP_Vect[RSPOpC.sa].HW[el] = RSP_ACCUM[el].HW[2]; + } + } + } else { + if (RSP_ACCUM[el].UHW[3] != 0) { + RSP_Vect[RSPOpC.sa].HW[el] = 0x7FFF; + } else { + if (RSP_ACCUM[el].HW[2] < 0) { + RSP_Vect[RSPOpC.sa].HW[el] = 0x7FFF; + } else { + RSP_Vect[RSPOpC.sa].HW[el] = RSP_ACCUM[el].HW[2]; + } + } + } + } +} + +void RSP_Vector_VMACF (void) { + int count, el, del; + //UWORD32 temp, temp2; + UWORD32 temp; + + for (count = 0; count < 8; count ++ ) { + el = Indx[RSPOpC.rs].B[count]; + del = EleSpec[RSPOpC.rs].B[el]; + + /*temp.W = (long)RSP_Vect[RSPOpC.rd].HW[el] * (long)(DWORD)RSP_Vect[RSPOpC.rt].HW[del]; + RSP_ACCUM[el].UHW[3] += (WORD)(temp.W >> 31); + temp.UW = temp.UW << 1; + temp2.UW = temp.UHW[0] + RSP_ACCUM[el].UHW[1]; + RSP_ACCUM[el].HW[1] = temp2.HW[0]; + temp2.UW = temp.UHW[1] + RSP_ACCUM[el].UHW[2] + temp2.UHW[1]; + RSP_ACCUM[el].HW[2] = temp2.HW[0]; + RSP_ACCUM[el].HW[3] += temp2.HW[1];*/ + temp.W = (long)RSP_Vect[RSPOpC.rd].HW[el] * (long)(DWORD)RSP_Vect[RSPOpC.rt].HW[del]; + RSP_ACCUM[el].DW += ((__int64)temp.W) << 17; + if (RSP_ACCUM[el].HW[3] < 0) { + if (RSP_ACCUM[el].UHW[3] != 0xFFFF) { + RSP_Vect[RSPOpC.sa].HW[el] = (WORD)0x8000; + } else { + if (RSP_ACCUM[el].HW[2] >= 0) { + RSP_Vect[RSPOpC.sa].HW[el] = (WORD)0x8000; + } else { + RSP_Vect[RSPOpC.sa].HW[el] = RSP_ACCUM[el].HW[2]; + } + } + } else { + if (RSP_ACCUM[el].UHW[3] != 0) { + RSP_Vect[RSPOpC.sa].HW[el] = 0x7FFF; + } else { + if (RSP_ACCUM[el].HW[2] < 0) { + RSP_Vect[RSPOpC.sa].HW[el] = 0x7FFF; + } else { + RSP_Vect[RSPOpC.sa].HW[el] = RSP_ACCUM[el].HW[2]; + } + } + } + } +} + +void RSP_Vector_VMACU (void) { + int count, el, del; + UWORD32 temp, temp2; + + for (count = 0; count < 8; count ++ ) { + el = Indx[RSPOpC.rs].B[count]; + del = EleSpec[RSPOpC.rs].B[el]; + + temp.W = (long)RSP_Vect[RSPOpC.rd].HW[el] * (long)(DWORD)RSP_Vect[RSPOpC.rt].HW[del]; + RSP_ACCUM[el].UHW[3] += (WORD)(temp.W >> 31); + temp.UW = temp.UW << 1; + temp2.UW = temp.UHW[0] + RSP_ACCUM[el].UHW[1]; + RSP_ACCUM[el].HW[1] = temp2.HW[0]; + temp2.UW = temp.UHW[1] + RSP_ACCUM[el].UHW[2] + temp2.UHW[1]; + RSP_ACCUM[el].HW[2] = temp2.HW[0]; + RSP_ACCUM[el].HW[3] += temp2.HW[1]; + if (RSP_ACCUM[el].HW[3] < 0) { + RSP_Vect[RSPOpC.sa].HW[el] = 0; + } else { + if (RSP_ACCUM[el].UHW[3] != 0) { + RSP_Vect[RSPOpC.sa].UHW[el] = 0xFFFF; + } else { + if (RSP_ACCUM[el].HW[2] < 0) { + RSP_Vect[RSPOpC.sa].UHW[el] = 0xFFFF; + } else { + RSP_Vect[RSPOpC.sa].HW[el] = RSP_ACCUM[el].HW[2]; + } + } + } + } +} + +void RSP_Vector_VMACQ (void) { + int count, el, del; + UWORD32 temp; + + for (count = 0; count < 8; count ++ ) { + el = Indx[RSPOpC.rs].B[count]; + del = EleSpec[RSPOpC.rs].B[el]; + + if (RSP_ACCUM[el].W[1] > 0x20) { + if ((RSP_ACCUM[el].W[1] & 0x20) == 0) { + RSP_ACCUM[el].W[1] -= 0x20; + } + } else if (RSP_ACCUM[el].W[1] < -0x20) { + if ((RSP_ACCUM[el].W[1] & 0x20) == 0) { + RSP_ACCUM[el].W[1] += 0x20; + } + } + temp.W = RSP_ACCUM[el].W[1] >> 1; + if (temp.HW[1] < 0) { + if (temp.UHW[1] != 0xFFFF) { + RSP_Vect[RSPOpC.sa].HW[el] = (WORD)0x8000; + } else { + if (temp.HW[0] >= 0) { + RSP_Vect[RSPOpC.sa].HW[el] = (WORD)0x8000; + } else { + RSP_Vect[RSPOpC.sa].HW[el] = (WORD)(temp.UW & 0xFFF0); + } + } + } else { + if (temp.UHW[1] != 0) { + RSP_Vect[RSPOpC.sa].HW[el] = 0x7FF0; + } else { + if (temp.HW[0] < 0) { + RSP_Vect[RSPOpC.sa].HW[el] = 0x7FF0; + } else { + RSP_Vect[RSPOpC.sa].HW[el] = (WORD)(temp.UW & 0xFFF0); + } + } + } + } +} + +void RSP_Vector_VMADL (void) { + int count, el, del; + UWORD32 temp, temp2; + + for (count = 0; count < 8; count ++ ) { + el = Indx[RSPOpC.rs].B[count]; + del = EleSpec[RSPOpC.rs].B[el]; + + temp.UW = (DWORD)RSP_Vect[RSPOpC.rd].UHW[el] * (DWORD)RSP_Vect[RSPOpC.rt].UHW[del]; + temp2.UW = temp.UHW[1] + RSP_ACCUM[el].UHW[1]; + RSP_ACCUM[el].HW[1] = temp2.HW[0]; + temp2.UW = RSP_ACCUM[el].UHW[2] + temp2.UHW[1]; + RSP_ACCUM[el].HW[2] = temp2.HW[0]; + RSP_ACCUM[el].HW[3] += temp2.HW[1]; + if (RSP_ACCUM[el].HW[3] < 0) { + if (RSP_ACCUM[el].UHW[3] != 0xFFFF) { + RSP_Vect[RSPOpC.sa].HW[el] = 0; + } else { + if (RSP_ACCUM[el].HW[2] >= 0) { + RSP_Vect[RSPOpC.sa].HW[el] = 0; + } else { + RSP_Vect[RSPOpC.sa].HW[el] = RSP_ACCUM[el].HW[1]; + } + } + } else { + if (RSP_ACCUM[el].UHW[3] != 0) { + RSP_Vect[RSPOpC.sa].UHW[el] = 0xFFFF; + } else { + if (RSP_ACCUM[el].HW[2] < 0) { + RSP_Vect[RSPOpC.sa].UHW[el] = 0xFFFF; + } else { + RSP_Vect[RSPOpC.sa].HW[el] = RSP_ACCUM[el].HW[1]; + } + } + } + } + +} + +void RSP_Vector_VMADM (void) { + int count, el, del; + UWORD32 temp, temp2; + + for (count = 0; count < 8; count ++ ) { + el = Indx[RSPOpC.rs].B[count]; + del = EleSpec[RSPOpC.rs].B[el]; + + temp.UW = (DWORD)((long)RSP_Vect[RSPOpC.rd].HW[el]) * (DWORD)RSP_Vect[RSPOpC.rt].UHW[del]; + temp2.UW = temp.UHW[0] + RSP_ACCUM[el].UHW[1]; + RSP_ACCUM[el].HW[1] = temp2.HW[0]; + temp2.UW = temp.UHW[1] + RSP_ACCUM[el].UHW[2] + temp2.UHW[1]; + RSP_ACCUM[el].HW[2] = temp2.HW[0]; + RSP_ACCUM[el].HW[3] += temp2.HW[1]; + if (temp.W < 0) { + RSP_ACCUM[el].HW[3] -= 1; + } + if (RSP_ACCUM[el].HW[3] < 0) { + if (RSP_ACCUM[el].UHW[3] != 0xFFFF) { + RSP_Vect[RSPOpC.sa].HW[el] = (WORD)0x8000; + } else { + if (RSP_ACCUM[el].HW[2] >= 0) { + RSP_Vect[RSPOpC.sa].HW[el] = (WORD)0x8000; + } else { + RSP_Vect[RSPOpC.sa].HW[el] = RSP_ACCUM[el].HW[2]; + } + } + } else { + if (RSP_ACCUM[el].UHW[3] != 0) { + RSP_Vect[RSPOpC.sa].HW[el] = 0x7FFF; + } else { + if (RSP_ACCUM[el].HW[2] < 0) { + RSP_Vect[RSPOpC.sa].HW[el] = 0x7FFF; + } else { + RSP_Vect[RSPOpC.sa].HW[el] = RSP_ACCUM[el].HW[2]; + } + } + } + //RSP_Vect[RSPOpC.sa].HW[el] = RSP_ACCUM[el].HW[2]; + } +} + +void RSP_Vector_VMADN (void) { + int count, el, del; + UWORD32 temp, temp2; + + for (count = 0; count < 8; count ++ ) { + el = Indx[RSPOpC.rs].B[count]; + del = EleSpec[RSPOpC.rs].B[el]; + + temp.UW = (DWORD)RSP_Vect[RSPOpC.rd].UHW[el] * (DWORD)((long)RSP_Vect[RSPOpC.rt].HW[del]); + temp2.UW = temp.UHW[0] + RSP_ACCUM[el].UHW[1]; + RSP_ACCUM[el].HW[1] = temp2.HW[0]; + temp2.UW = temp.UHW[1] + RSP_ACCUM[el].UHW[2] + temp2.UHW[1]; + RSP_ACCUM[el].HW[2] = temp2.HW[0]; + RSP_ACCUM[el].HW[3] += temp2.HW[1]; + if (temp.W < 0) { + RSP_ACCUM[el].HW[3] -= 1; + } + if (RSP_ACCUM[el].HW[3] < 0) { + if (RSP_ACCUM[el].UHW[3] != 0xFFFF) { + RSP_Vect[RSPOpC.sa].HW[el] = 0; + } else { + if (RSP_ACCUM[el].HW[2] >= 0) { + RSP_Vect[RSPOpC.sa].HW[el] = 0; + } else { + RSP_Vect[RSPOpC.sa].HW[el] = RSP_ACCUM[el].HW[1]; + } + } + } else { + if (RSP_ACCUM[el].UHW[3] != 0) { + RSP_Vect[RSPOpC.sa].UHW[el] = 0xFFFF; + } else { + if (RSP_ACCUM[el].HW[2] < 0) { + RSP_Vect[RSPOpC.sa].UHW[el] = 0xFFFF; + } else { + RSP_Vect[RSPOpC.sa].HW[el] = RSP_ACCUM[el].HW[1]; + } + } + } + } +} + +void RSP_Vector_VMADH (void) { + int count, el, del; + + for (count = 0; count < 8; count ++ ) { + el = Indx[RSPOpC.rs].B[count]; + del = EleSpec[RSPOpC.rs].B[el]; + + RSP_ACCUM[el].W[1] += (long)RSP_Vect[RSPOpC.rd].HW[el] * (long)RSP_Vect[RSPOpC.rt].HW[del]; + if (RSP_ACCUM[el].HW[3] < 0) { + if (RSP_ACCUM[el].UHW[3] != 0xFFFF) { + RSP_Vect[RSPOpC.sa].HW[el] = (WORD)0x8000; + } else { + if (RSP_ACCUM[el].HW[2] >= 0) { + RSP_Vect[RSPOpC.sa].HW[el] = (WORD)0x8000; + } else { + RSP_Vect[RSPOpC.sa].HW[el] = RSP_ACCUM[el].HW[2]; + } + } + } else { + if (RSP_ACCUM[el].UHW[3] != 0) { + RSP_Vect[RSPOpC.sa].HW[el] = 0x7FFF; + } else { + if (RSP_ACCUM[el].HW[2] < 0) { + RSP_Vect[RSPOpC.sa].HW[el] = 0x7FFF; + } else { + RSP_Vect[RSPOpC.sa].HW[el] = RSP_ACCUM[el].HW[2]; + } + } + } + } +} + +void RSP_Vector_VADD (void) { + int count, el, del; + UWORD32 temp; + + for ( count = 0; count < 8; count++ ) { + el = Indx[RSPOpC.rs].B[count]; + del = EleSpec[RSPOpC.rs].B[el]; + + temp.W = (int)RSP_Vect[RSPOpC.rd].HW[el] + (int)RSP_Vect[RSPOpC.rt].HW[del] + + ((RSP_Flags[0].UW >> (7 - el)) & 0x1); + RSP_ACCUM[el].HW[1] = temp.HW[0]; + if ((temp.HW[0] & 0x8000) == 0) { + if (temp.HW[1] != 0) { + RSP_Vect[RSPOpC.sa].HW[el] = (WORD)0x8000; + } else { + RSP_Vect[RSPOpC.sa].HW[el] = temp.HW[0]; + } + } else { + if (temp.HW[1] != -1 ) { + RSP_Vect[RSPOpC.sa].HW[el] = 0x7FFF; + } else { + RSP_Vect[RSPOpC.sa].HW[el] = temp.HW[0]; + } + } + } + RSP_Flags[0].UW = 0; +} + +void RSP_Vector_VSUB (void) { + int count, el, del; + UWORD32 temp; + + for ( count = 0; count < 8; count++ ) { + el = Indx[RSPOpC.rs].B[count]; + del = EleSpec[RSPOpC.rs].B[el]; + + temp.W = (int)RSP_Vect[RSPOpC.rd].HW[el] - (int)RSP_Vect[RSPOpC.rt].HW[del] - + ((RSP_Flags[0].UW >> (7 - el)) & 0x1); + RSP_ACCUM[el].HW[1] = temp.HW[0]; + if ((temp.HW[0] & 0x8000) == 0) { + if (temp.HW[1] != 0) { + RSP_Vect[RSPOpC.sa].HW[el] = (WORD)0x8000; + } else { + RSP_Vect[RSPOpC.sa].HW[el] = temp.HW[0]; + } + } else { + if (temp.HW[1] != -1 ) { + RSP_Vect[RSPOpC.sa].HW[el] = 0x7FFF; + } else { + RSP_Vect[RSPOpC.sa].HW[el] = temp.HW[0]; + } + } + } + RSP_Flags[0].UW = 0; +} + +void RSP_Vector_VABS (void) { + int count, el, del; + + for ( count = 0; count < 8; count++ ) { + el = Indx[RSPOpC.rs].B[count]; + del = EleSpec[RSPOpC.rs].B[el]; + + if (RSP_Vect[RSPOpC.rd].HW[el] > 0) { + RSP_Vect[RSPOpC.sa].HW[el] = RSP_Vect[RSPOpC.rt].UHW[del]; + } else if (RSP_Vect[RSPOpC.rd].HW[el] < 0) { + if (RSP_Vect[RSPOpC.rt].UHW[EleSpec[RSPOpC.rs].B[el]] == 0x8000) { + RSP_Vect[RSPOpC.sa].HW[el] = 0x7FFF; + } else { + RSP_Vect[RSPOpC.sa].HW[el] = RSP_Vect[RSPOpC.rt].HW[del] * -1; + } + } else { + RSP_Vect[RSPOpC.sa].HW[el] = 0; + } + RSP_ACCUM[el].HW[1] = RSP_Vect[RSPOpC.sa].HW[el]; + } +} + +void RSP_Vector_VADDC (void) { + int count, el, del; + UWORD32 temp; + + RSP_Flags[0].UW = 0; + for ( count = 0; count < 8; count++ ) { + el = Indx[RSPOpC.rs].B[count]; + del = EleSpec[RSPOpC.rs].B[el]; + + temp.UW = (int)RSP_Vect[RSPOpC.rd].UHW[el] + (int)RSP_Vect[RSPOpC.rt].UHW[del]; + RSP_ACCUM[el].HW[1] = temp.HW[0]; + RSP_Vect[RSPOpC.sa].HW[el] = temp.HW[0]; + if (temp.UW & 0xffff0000) { + RSP_Flags[0].UW |= ( 1 << (7 - el) ); + } + } +} + +void RSP_Vector_VSUBC (void) { + int count, el, del; + UWORD32 temp; + + RSP_Flags[0].UW = 0x0; + for ( count = 0; count < 8; count++ ) { + el = Indx[RSPOpC.rs].B[count]; + del = EleSpec[RSPOpC.rs].B[el]; + + temp.UW = (int)RSP_Vect[RSPOpC.rd].UHW[el] - (int)RSP_Vect[RSPOpC.rt].UHW[del]; + RSP_ACCUM[el].HW[1] = temp.HW[0]; + RSP_Vect[RSPOpC.sa].HW[el] = temp.HW[0]; + if (temp.HW[0] != 0) { + RSP_Flags[0].UW |= ( 0x1 << (15 - el) ); + } + if (temp.UW & 0xffff0000) { + RSP_Flags[0].UW |= ( 0x1 << (7 - el) ); + } + } +} + +void RSP_Vector_VSAW (void) { + switch ((RSPOpC.rs & 0xF)) { + case 8: + RSP_Vect[RSPOpC.sa].HW[0] = RSP_ACCUM[0].HW[3]; + RSP_Vect[RSPOpC.sa].HW[1] = RSP_ACCUM[1].HW[3]; + RSP_Vect[RSPOpC.sa].HW[2] = RSP_ACCUM[2].HW[3]; + RSP_Vect[RSPOpC.sa].HW[3] = RSP_ACCUM[3].HW[3]; + RSP_Vect[RSPOpC.sa].HW[4] = RSP_ACCUM[4].HW[3]; + RSP_Vect[RSPOpC.sa].HW[5] = RSP_ACCUM[5].HW[3]; + RSP_Vect[RSPOpC.sa].HW[6] = RSP_ACCUM[6].HW[3]; + RSP_Vect[RSPOpC.sa].HW[7] = RSP_ACCUM[7].HW[3]; + break; + case 9: + RSP_Vect[RSPOpC.sa].HW[0] = RSP_ACCUM[0].HW[2]; + RSP_Vect[RSPOpC.sa].HW[1] = RSP_ACCUM[1].HW[2]; + RSP_Vect[RSPOpC.sa].HW[2] = RSP_ACCUM[2].HW[2]; + RSP_Vect[RSPOpC.sa].HW[3] = RSP_ACCUM[3].HW[2]; + RSP_Vect[RSPOpC.sa].HW[4] = RSP_ACCUM[4].HW[2]; + RSP_Vect[RSPOpC.sa].HW[5] = RSP_ACCUM[5].HW[2]; + RSP_Vect[RSPOpC.sa].HW[6] = RSP_ACCUM[6].HW[2]; + RSP_Vect[RSPOpC.sa].HW[7] = RSP_ACCUM[7].HW[2]; + break; + case 10: + RSP_Vect[RSPOpC.sa].HW[0] = RSP_ACCUM[0].HW[1]; + RSP_Vect[RSPOpC.sa].HW[1] = RSP_ACCUM[1].HW[1]; + RSP_Vect[RSPOpC.sa].HW[2] = RSP_ACCUM[2].HW[1]; + RSP_Vect[RSPOpC.sa].HW[3] = RSP_ACCUM[3].HW[1]; + RSP_Vect[RSPOpC.sa].HW[4] = RSP_ACCUM[4].HW[1]; + RSP_Vect[RSPOpC.sa].HW[5] = RSP_ACCUM[5].HW[1]; + RSP_Vect[RSPOpC.sa].HW[6] = RSP_ACCUM[6].HW[1]; + RSP_Vect[RSPOpC.sa].HW[7] = RSP_ACCUM[7].HW[1]; + break; + default: + RSP_Vect[RSPOpC.sa].DW[1] = 0; + RSP_Vect[RSPOpC.sa].DW[0] = 0; + } +} + +void RSP_Vector_VLT (void) { + int count, el, del; + + RSP_Flags[1].UW = 0; + for ( count = 0; count < 8; count++ ) { + el = Indx[RSPOpC.rs].B[count]; + del = EleSpec[RSPOpC.rs].B[el]; + + if (RSP_Vect[RSPOpC.rd].HW[el] < RSP_Vect[RSPOpC.rt].HW[del]) { + RSP_Vect[RSPOpC.sa].HW[el] = RSP_Vect[RSPOpC.rd].UHW[el]; + RSP_Flags[1].UW |= ( 1 << (7 - el) ); + } else if (RSP_Vect[RSPOpC.rd].HW[el] != RSP_Vect[RSPOpC.rt].HW[del]) { + RSP_Vect[RSPOpC.sa].HW[el] = RSP_Vect[RSPOpC.rt].UHW[del]; + RSP_Flags[1].UW &= ~( 1 << (7 - el) ); + } else { + RSP_Vect[RSPOpC.sa].HW[el] = RSP_Vect[RSPOpC.rd].UHW[el]; + if ( (RSP_Flags[0].UW & (0x101 << (7 - el))) == (WORD)(0x101 << (7 - el))) { + RSP_Flags[1].UW |= ( 1 << (7 - el) ); + } else { + RSP_Flags[1].UW &= ~( 1 << (7 - el) ); + } + } + RSP_ACCUM[el].HW[1] = RSP_Vect[RSPOpC.sa].HW[el]; + } + RSP_Flags[0].UW = 0; +} + +void RSP_Vector_VEQ (void) { + int count, el, del; + + RSP_Flags[1].UW = 0; + for ( count = 0; count < 8; count++ ) { + el = Indx[RSPOpC.rs].B[count]; + del = EleSpec[RSPOpC.rs].B[el]; + + if (RSP_Vect[RSPOpC.rd].UHW[el] == RSP_Vect[RSPOpC.rt].UHW[del]) { + if ( (RSP_Flags[0].UW & (1 << (15 - el))) == 0) { + RSP_Flags[1].UW |= ( 1 << (7 - el)); + } + } + RSP_Vect[RSPOpC.sa].HW[el] = RSP_Vect[RSPOpC.rt].UHW[del]; + RSP_ACCUM[el].HW[1] = RSP_Vect[RSPOpC.rt].UHW[del]; + } + RSP_Flags[0].UW = 0; +} + +void RSP_Vector_VNE (void) { + int count, el, del; + + RSP_Flags[1].UW = 0; + for ( count = 0; count < 8; count++ ) { + el = Indx[RSPOpC.rs].B[count]; + del = EleSpec[RSPOpC.rs].B[el]; + + if (RSP_Vect[RSPOpC.rd].UHW[el] != RSP_Vect[RSPOpC.rt].UHW[del]) { + RSP_Flags[1].UW |= ( 1 << (7 - el) ); + } else { + if ( (RSP_Flags[0].UW & (1 << (15 - el))) != 0) { + RSP_Flags[1].UW |= ( 1 << (7 - el) ); + } + } + RSP_Vect[RSPOpC.sa].HW[el] = RSP_Vect[RSPOpC.rd].UHW[el]; + RSP_ACCUM[el].HW[1] = RSP_Vect[RSPOpC.rd].UHW[el]; + } + RSP_Flags[0].UW = 0; +} + +void RSP_Vector_VGE (void) { + int count, el, del; + + RSP_Flags[1].UW = 0; + for ( count = 0; count < 8; count++ ) { + el = Indx[RSPOpC.rs].B[count]; + del = EleSpec[RSPOpC.rs].B[el]; + + if (RSP_Vect[RSPOpC.rd].HW[el] == RSP_Vect[RSPOpC.rt].HW[del]) { + RSP_Vect[RSPOpC.sa].HW[el] = RSP_Vect[RSPOpC.rd].UHW[el]; + if ( (RSP_Flags[0].UW & (0x101 << (7 - el))) == (WORD)(0x101 << (7 - el))) { + RSP_Flags[1].UW &= ~( 1 << (7 - el) ); + } else { + RSP_Flags[1].UW |= ( 1 << (7 - el) ); + } + } else if (RSP_Vect[RSPOpC.rd].HW[el] > RSP_Vect[RSPOpC.rt].HW[del]) { + RSP_Vect[RSPOpC.sa].HW[el] = RSP_Vect[RSPOpC.rd].UHW[el]; + RSP_Flags[1].UW |= ( 1 << (7 - el) ); + } else { + RSP_Vect[RSPOpC.sa].HW[el] = RSP_Vect[RSPOpC.rt].UHW[del]; + RSP_Flags[1].UW &= ~( 1 << (7 - el) ); + } + RSP_ACCUM[el].HW[1] = RSP_Vect[RSPOpC.sa].HW[el]; + } + RSP_Flags[0].UW = 0; +} + +/*void RSP_Vector_VCL (void) { + int count, el, del; + + for ( count = 0; count < 8; count++ ) { + el = Indx[RSPOpC.rs].B[count]; + del = EleSpec[RSPOpC.rs].B[el]; + + if ((RSP_Flags[0].UW & ( 1 << (7 - el))) != 0 ) { + if ((RSP_Flags[0].UW & ( 1 << (15 - el))) != 0 ) { + if ((RSP_Flags[1].UW & ( 1 << (7 - el))) != 0 ) { + RSP_Vect[RSPOpC.sa].HW[el] = -RSP_Vect[RSPOpC.rt].UHW[del]; + } else { + RSP_Vect[RSPOpC.sa].HW[el] = RSP_Vect[RSPOpC.rd].HW[el]; + } + } else { + if ((RSP_Flags[2].UW & ( 1 << (7 - el)))) { + if (RSP_Vect[RSPOpC.rt].HW[del] == 0){ + RSP_Vect[RSPOpC.sa].HW[el] = -RSP_Vect[RSPOpC.rt].UHW[del]; + RSP_Flags[1].UW |= (1 << (7 - el)); + } else if ((WORD)(-RSP_Vect[RSPOpC.rt].HW[del]) >= RSP_Vect[RSPOpC.rd].UHW[el]) { + RSP_Vect[RSPOpC.sa].HW[el] = -RSP_Vect[RSPOpC.rt].UHW[del]; + RSP_Flags[1].UW |= (1 << (7 - el)); + } else { + RSP_Vect[RSPOpC.sa].HW[el] = RSP_Vect[RSPOpC.rd].HW[el]; + RSP_Flags[1].UW &= ~(1 << (7 - el)); + } + } else { + if (RSP_Vect[RSPOpC.rt].HW[del] == 0 && RSP_Vect[RSPOpC.rd].UHW[el] == 0) { + RSP_Flags[1].UW |= (1 << (7 - el)); + } else { + RSP_Flags[1].UW &= ~(1 << (7 - el)); + } + RSP_Vect[RSPOpC.sa].HW[el] = RSP_Vect[RSPOpC.rd].HW[el]; + } + + } + } else { + if ((RSP_Flags[0].UW & ( 1 << (15 - el))) != 0 ) { + if ((RSP_Flags[1].UW & ( 1 << (15 - el))) != 0 ) { + RSP_Vect[RSPOpC.sa].HW[el] = RSP_Vect[RSPOpC.rt].UHW[del]; + } else { + RSP_Vect[RSPOpC.sa].HW[el] = RSP_Vect[RSPOpC.rd].HW[el]; + } + } else { + if ( RSP_Vect[RSPOpC.rd].UHW[el] >= RSP_Vect[RSPOpC.rt].UHW[del]) { + RSP_Vect[RSPOpC.sa].HW[el] = RSP_Vect[RSPOpC.rt].UHW[del]; + RSP_Flags[1].UW |= (1 << (15 - el)); + } else { + RSP_Vect[RSPOpC.sa].HW[el] = RSP_Vect[RSPOpC.rd].HW[el]; + RSP_Flags[1].UW &= ~(1 << (15 - el)); + } + } + } + RSP_ACCUM[el].HW[1] = RSP_Vect[RSPOpC.sa].HW[el]; + } + RSP_Flags[0].UW = 0; + RSP_Flags[2].UW = 0; +} + +void RSP_Vector_VCH (void) { + int count, el, del; + + RSP_Flags[0].UW = 0; + RSP_Flags[1].UW = 0; + RSP_Flags[2].UW = 0; + for ( count = 0; count < 8; count++ ) { + el = Indx[RSPOpC.rs].B[count]; + del = EleSpec[RSPOpC.rs].B[el]; + + if (abs(RSP_Vect[RSPOpC.rd].HW[el]) != abs(RSP_Vect[RSPOpC.rt].HW[del])) { + if (RSP_Vect[RSPOpC.rd].HW[el] == ~RSP_Vect[RSPOpC.rt].HW[del]) { + RSP_Flags[2].UW |= ( 1 << (7 - el) ); + } else { + RSP_Flags[0].UW |= ( 1 << (15 - el)); + } + } + + if (RSP_Vect[RSPOpC.rd].HW[el] < 0) { + if (RSP_Vect[RSPOpC.rt].HW[del] >= 0) { + if (RSP_Vect[RSPOpC.rd].HW[el] > -RSP_Vect[RSPOpC.rt].HW[del]) { + RSP_Vect[RSPOpC.sa].HW[el] = RSP_Vect[RSPOpC.rd].HW[el]; + } else { + RSP_Vect[RSPOpC.sa].HW[el] = -RSP_Vect[RSPOpC.rt].UHW[del]; + } + RSP_Flags[0].UW |= ( 1 << (7 - el)); + } else { + if (RSP_Vect[RSPOpC.rd].HW[el] < RSP_Vect[RSPOpC.rt].HW[del]) { + RSP_Vect[RSPOpC.sa].HW[el] = RSP_Vect[RSPOpC.rd].HW[el]; + } else { + RSP_Vect[RSPOpC.sa].HW[el] = RSP_Vect[RSPOpC.rt].UHW[del]; + } + } + } else { + if (RSP_Vect[RSPOpC.rt].HW[del] < 0) { + if (RSP_Vect[RSPOpC.rd].HW[el] > -RSP_Vect[RSPOpC.rt].HW[del]) { + RSP_Vect[RSPOpC.sa].HW[el] = RSP_Vect[RSPOpC.rd].HW[el]; + } else { + RSP_Vect[RSPOpC.sa].HW[el] = -RSP_Vect[RSPOpC.rt].UHW[del]; + } + RSP_Flags[0].UW |= ( 1 << (7 - el)); + } else { + if (RSP_Vect[RSPOpC.rd].HW[el] < RSP_Vect[RSPOpC.rt].HW[del]) { + RSP_Vect[RSPOpC.sa].HW[el] = RSP_Vect[RSPOpC.rd].HW[el]; + } else { + RSP_Vect[RSPOpC.sa].HW[el] = RSP_Vect[RSPOpC.rt].UHW[del]; + } + } + } + + if (RSP_Vect[RSPOpC.rd].HW[el] >= RSP_Vect[RSPOpC.rt].HW[del]) { + RSP_Flags[1].UW |= ( 1 << (15 - el)); + } + + if (RSP_Vect[RSPOpC.rd].HW[el] <= -RSP_Vect[RSPOpC.rt].HW[del]) { + if (RSP_Vect[RSPOpC.rd].HW[el] != 0 || RSP_Vect[RSPOpC.rt].HW[del] != 0) { + RSP_Flags[1].UW |= ( 1 << (7 - el)); + } + } + RSP_ACCUM[el].HW[1] = RSP_Vect[RSPOpC.sa].HW[el]; + } +} + +void RSP_Vector_VCR (void) { + int count, el, del; + + for ( count = 0; count < 8; count++ ) { + el = Indx[RSPOpC.rs].B[count]; + del = EleSpec[RSPOpC.rs].B[el]; + + if (RSP_Vect[RSPOpC.rd].HW[el] < RSP_Vect[RSPOpC.rt].HW[del]) { + RSP_Flags[1].UW &= ~( 1 << (15 - el)); + } else { + RSP_Flags[1].UW |= ( 1 << (15 - el)); + } + + if (RSP_Vect[RSPOpC.rd].HW[el] + RSP_Vect[RSPOpC.rt].HW[del] < 0) { + RSP_Flags[1].UW |= ( 1 << (7 - el)); + } else { + RSP_Flags[1].UW &= ~( 1 << (7 - el)); + } + + if (RSP_Vect[RSPOpC.rd].HW[el] >= 0) { + if (RSP_Vect[RSPOpC.rt].HW[del] >= 0) { + if (RSP_Vect[RSPOpC.rd].HW[el] < RSP_Vect[RSPOpC.rt].HW[del]) { + RSP_Vect[RSPOpC.sa].HW[el] = RSP_Vect[RSPOpC.rd].HW[el]; + } else { + RSP_Vect[RSPOpC.sa].HW[el] = RSP_Vect[RSPOpC.rt].UHW[del]; + } + } else { + if (RSP_Vect[RSPOpC.rd].HW[el] + RSP_Vect[RSPOpC.rt].HW[del] < 0) { + RSP_Vect[RSPOpC.sa].HW[el] = ~RSP_Vect[RSPOpC.rt].UHW[del]; + } else { + RSP_Vect[RSPOpC.sa].HW[el] = RSP_Vect[RSPOpC.rd].HW[el]; + } + } + } else { + if (RSP_Vect[RSPOpC.rt].HW[del] < 0) { + if (RSP_Vect[RSPOpC.rd].HW[el] < RSP_Vect[RSPOpC.rt].HW[del]) { + RSP_Vect[RSPOpC.sa].HW[el] = RSP_Vect[RSPOpC.rd].HW[el]; + } else { + RSP_Vect[RSPOpC.sa].HW[el] = RSP_Vect[RSPOpC.rt].UHW[del]; + } + } else { + if (RSP_Vect[RSPOpC.rd].HW[el] + RSP_Vect[RSPOpC.rt].HW[del] < 0) { + RSP_Vect[RSPOpC.sa].HW[el] = ~RSP_Vect[RSPOpC.rt].UHW[del]; + } else { + RSP_Vect[RSPOpC.sa].HW[el] = RSP_Vect[RSPOpC.rd].HW[el]; + } + } + } + RSP_ACCUM[el].HW[1] = RSP_Vect[RSPOpC.sa].HW[el]; + } + RSP_Flags[0].UW = 0; + RSP_Flags[2].UW = 0; +}*/ + +void RSP_Vector_VCL (void) { + int count, el, del; + + for (count = 0;count < 8; count++) { + el = Indx[RSPOpC.rs].B[count]; + del = EleSpec[RSPOpC.rs].B[el]; + + if ((RSP_Flags[0].UW & ( 1 << (7 - el))) != 0 ) { + if ((RSP_Flags[0].UW & ( 1 << (15 - el))) != 0 ) { + if ((RSP_Flags[1].UW & ( 1 << (7 - el))) != 0 ) { + RSP_ACCUM[el].HW[1] = -RSP_Vect[RSPOpC.rt].UHW[del]; + } else { + RSP_ACCUM[el].HW[1] = RSP_Vect[RSPOpC.rd].HW[el]; + } + } else { + if ((RSP_Flags[2].UW & ( 1 << (7 - el)))) { + if ( RSP_Vect[RSPOpC.rd].UHW[el] + RSP_Vect[RSPOpC.rt].UHW[del] > 0x10000) { + RSP_ACCUM[el].HW[1] = RSP_Vect[RSPOpC.rd].HW[el]; + RSP_Flags[1].UW &= ~(1 << (7 - el)); + } else { + RSP_ACCUM[el].HW[1] = -RSP_Vect[RSPOpC.rt].UHW[del]; + RSP_Flags[1].UW |= (1 << (7 - el)); + } + } else { + if (RSP_Vect[RSPOpC.rt].UHW[del] + RSP_Vect[RSPOpC.rd].UHW[el] != 0) { + RSP_ACCUM[el].HW[1] = RSP_Vect[RSPOpC.rd].HW[el]; + RSP_Flags[1].UW &= ~(1 << (7 - el)); + } else { + RSP_ACCUM[el].HW[1] = -RSP_Vect[RSPOpC.rt].UHW[del]; + RSP_Flags[1].UW |= (1 << (7 - el)); + } + } + } + } else { + if ((RSP_Flags[0].UW & ( 1 << (15 - el))) != 0 ) { + if ((RSP_Flags[1].UW & ( 1 << (15 - el))) != 0 ) { + RSP_ACCUM[el].HW[1] = RSP_Vect[RSPOpC.rt].HW[del]; + } else { + RSP_ACCUM[el].HW[1] = RSP_Vect[RSPOpC.rd].HW[el]; + } + } else { + if ( RSP_Vect[RSPOpC.rd].UHW[el] - RSP_Vect[RSPOpC.rt].UHW[del] >= 0) { + RSP_ACCUM[el].HW[1] = RSP_Vect[RSPOpC.rt].UHW[del]; + RSP_Flags[1].UW |= (1 << (15 - el)); + } else { + RSP_ACCUM[el].HW[1] = RSP_Vect[RSPOpC.rd].HW[el]; + RSP_Flags[1].UW &= ~(1 << (15 - el)); + } + } + } + RSP_Vect[RSPOpC.sa].HW[el] = RSP_ACCUM[el].HW[1]; + } + RSP_Flags[0].UW = 0; + RSP_Flags[2].UW = 0; +} + +void RSP_Vector_VCH (void) { + int count, el, del; + + RSP_Flags[0].UW = 0; + RSP_Flags[1].UW = 0; + RSP_Flags[2].UW = 0; + + for (count = 0;count < 8; count++) { + el = Indx[RSPOpC.rs].B[count]; + del = EleSpec[RSPOpC.rs].B[el]; + + if ((RSP_Vect[RSPOpC.rd].HW[el] ^ RSP_Vect[RSPOpC.rt].HW[del]) < 0) { + RSP_Flags[0].UW |= ( 1 << (7 - el)); + if (RSP_Vect[RSPOpC.rt].HW[del] < 0) { + RSP_Flags[1].UW |= ( 1 << (15 - el)); + + } + if (RSP_Vect[RSPOpC.rd].HW[el] + RSP_Vect[RSPOpC.rt].HW[del] <= 0) { + if (RSP_Vect[RSPOpC.rd].HW[el] + RSP_Vect[RSPOpC.rt].HW[del] == -1) { + RSP_Flags[2].UW |= ( 1 << (7 - el)); + } + RSP_Flags[1].UW |= ( 1 << (7 - el)); + RSP_ACCUM[el].HW[1] = -RSP_Vect[RSPOpC.rt].UHW[del]; + } else { + RSP_ACCUM[el].HW[1] = RSP_Vect[RSPOpC.rd].HW[el]; + } + if (RSP_Vect[RSPOpC.rd].HW[el] + RSP_Vect[RSPOpC.rt].HW[del] != 0) { + if (RSP_Vect[RSPOpC.rd].HW[el] != ~RSP_Vect[RSPOpC.rt].HW[del]) { + RSP_Flags[0].UW |= ( 1 << (15 - el)); + } + } + } else { + if (RSP_Vect[RSPOpC.rt].HW[del] < 0) { + RSP_Flags[1].UW |= ( 1 << (7 - el)); + } + if (RSP_Vect[RSPOpC.rd].HW[el] - RSP_Vect[RSPOpC.rt].HW[del] >= 0) { + RSP_Flags[1].UW |= ( 1 << (15 - el)); + RSP_ACCUM[el].HW[1] = RSP_Vect[RSPOpC.rt].UHW[del]; + } else { + RSP_ACCUM[el].HW[1] = RSP_Vect[RSPOpC.rd].HW[el]; + } + if (RSP_Vect[RSPOpC.rd].HW[el] - RSP_Vect[RSPOpC.rt].HW[del] != 0) { + if (RSP_Vect[RSPOpC.rd].HW[el] != ~RSP_Vect[RSPOpC.rt].HW[del]) { + RSP_Flags[0].UW |= ( 1 << (15 - el)); + } + } + } + RSP_Vect[RSPOpC.sa].HW[el] = RSP_ACCUM[el].HW[1]; + } +} + +void RSP_Vector_VCR (void) { + int count, el, del; + + RSP_Flags[0].UW = 0; + RSP_Flags[1].UW = 0; + RSP_Flags[2].UW = 0; + for (count = 0;count < 8; count++) { + el = Indx[RSPOpC.rs].B[count]; + del = EleSpec[RSPOpC.rs].B[el]; + + if ((RSP_Vect[RSPOpC.rd].HW[el] ^ RSP_Vect[RSPOpC.rt].HW[del]) < 0) { + if (RSP_Vect[RSPOpC.rt].HW[del] < 0) { + RSP_Flags[1].UW |= ( 1 << (15 - el)); + } + if (RSP_Vect[RSPOpC.rd].HW[el] + RSP_Vect[RSPOpC.rt].HW[del] <= 0) { + RSP_ACCUM[el].HW[1] = ~RSP_Vect[RSPOpC.rt].UHW[del]; + RSP_Flags[1].UW |= ( 1 << (7 - el)); + } else { + RSP_ACCUM[el].HW[1] = RSP_Vect[RSPOpC.rd].HW[el]; + } + } else { + if (RSP_Vect[RSPOpC.rt].HW[del] < 0) { + RSP_Flags[1].UW |= ( 1 << (7 - el)); + } + if (RSP_Vect[RSPOpC.rd].HW[el] - RSP_Vect[RSPOpC.rt].HW[del] >= 0) { + RSP_ACCUM[el].HW[1] = RSP_Vect[RSPOpC.rt].UHW[del]; + RSP_Flags[1].UW |= ( 1 << (15 - el)); + } else { + RSP_ACCUM[el].HW[1] = RSP_Vect[RSPOpC.rd].HW[el]; + } + } + RSP_Vect[RSPOpC.sa].HW[el] = RSP_ACCUM[el].HW[1]; + } +} + +void RSP_Vector_VMRG (void) { + int count, el, del; + + for ( count = 0; count < 8; count ++ ){ + el = Indx[RSPOpC.rs].B[count]; + del = EleSpec[RSPOpC.rs].B[el]; + + if ((RSP_Flags[1].UW & ( 1 << (7 - el))) != 0) { + RSP_Vect[RSPOpC.sa].HW[el] = RSP_Vect[RSPOpC.rd].HW[el]; + } else { + RSP_Vect[RSPOpC.sa].HW[el] = RSP_Vect[RSPOpC.rt].HW[del]; + } + } +} + +void RSP_Vector_VAND (void) { + int count, el, del; + + for ( count = 0; count < 8; count ++ ){ + el = Indx[RSPOpC.rs].B[count]; + del = EleSpec[RSPOpC.rs].B[el]; + RSP_Vect[RSPOpC.sa].HW[el] = RSP_Vect[RSPOpC.rd].HW[el] & RSP_Vect[RSPOpC.rt].HW[del]; + RSP_ACCUM[el].HW[1] = RSP_Vect[RSPOpC.sa].HW[el]; + } +} + +void RSP_Vector_VNAND (void) { + int count, el, del; + + for ( count = 0; count < 8; count ++ ){ + el = 7 - count; + del = EleSpec[RSPOpC.rs].B[el]; + RSP_Vect[RSPOpC.sa].HW[el] = ~(RSP_Vect[RSPOpC.rd].HW[el] & RSP_Vect[RSPOpC.rt].HW[del]); + RSP_ACCUM[el].HW[1] = RSP_Vect[RSPOpC.sa].HW[el]; + } +} + +void RSP_Vector_VOR (void) { + int count, el, del; + + for ( count = 0; count < 8; count ++ ){ + el = Indx[RSPOpC.rs].B[count]; + del = EleSpec[RSPOpC.rs].B[el]; + RSP_Vect[RSPOpC.sa].HW[el] = RSP_Vect[RSPOpC.rd].HW[el] | RSP_Vect[RSPOpC.rt].HW[del]; + RSP_ACCUM[el].HW[1] = RSP_Vect[RSPOpC.sa].HW[el]; + } +} + +void RSP_Vector_VNOR (void) { + int count, el, del; + + for ( count = 0; count < 8; count ++ ){ + el = Indx[RSPOpC.rs].B[count]; + del = EleSpec[RSPOpC.rs].B[el]; + RSP_Vect[RSPOpC.sa].HW[el] = ~(RSP_Vect[RSPOpC.rd].HW[el] | RSP_Vect[RSPOpC.rt].HW[del]); + RSP_ACCUM[el].HW[1] = RSP_Vect[RSPOpC.sa].HW[el]; + } +} + +void RSP_Vector_VXOR (void) { + int count, el, del; + + for ( count = 0; count < 8; count ++ ){ + el = Indx[RSPOpC.rs].B[count]; + del = EleSpec[RSPOpC.rs].B[el]; + RSP_Vect[RSPOpC.sa].HW[el] = RSP_Vect[RSPOpC.rd].HW[el] ^ RSP_Vect[RSPOpC.rt].HW[del]; + RSP_ACCUM[el].HW[1] = RSP_Vect[RSPOpC.sa].HW[el]; + } +} + +void RSP_Vector_VNXOR (void) { + int count, el, del; + + for ( count = 0; count < 8; count ++ ){ + el = Indx[RSPOpC.rs].B[count]; + del = EleSpec[RSPOpC.rs].B[el]; + RSP_Vect[RSPOpC.sa].HW[el] = ~(RSP_Vect[RSPOpC.rd].HW[el] ^ RSP_Vect[RSPOpC.rt].HW[del]); + RSP_ACCUM[el].HW[1] = RSP_Vect[RSPOpC.sa].HW[el]; + } +} + +void RSP_Vector_VRCP (void) { + int count, neg; + + RecpResult.W = RSP_Vect[RSPOpC.rt].HW[EleSpec[RSPOpC.rs].B[(RSPOpC.rd & 0x7)]]; + if (RecpResult.UW == 0) { + RecpResult.UW = 0x7FFFFFFF; + } else { + if (RecpResult.W < 0) { + neg = TRUE; + RecpResult.W = ~RecpResult.W + 1; + } else { + neg = FALSE; + } + for (count = 15; count > 0; count--) { + if ((RecpResult.W & (1 << count))) { + RecpResult.W &= (0xFFC0 >> (15 - count) ); + count = 0; + } + } + { + DWORD RoundMethod = _RC_CHOP; + DWORD OldModel = _controlfp(RoundMethod, _MCW_RC); + RecpResult.W = (long)((0x7FFFFFFF / (double)RecpResult.W)); + OldModel = _controlfp(OldModel, _MCW_RC); + } + for (count = 31; count > 0; count--) { + if ((RecpResult.W & (1 << count))) { + RecpResult.W &= (0xFFFF8000 >> (31 - count) ); + count = 0; + } + } + if (neg == TRUE) { + RecpResult.W = ~RecpResult.W; + } + } + for ( count = 0; count < 8; count++ ) { + RSP_ACCUM[count].HW[1] = RSP_Vect[RSPOpC.rt].UHW[EleSpec[RSPOpC.rs].B[count]]; + } + RSP_Vect[RSPOpC.sa].HW[7 - (RSPOpC.rd & 0x7)] = RecpResult.UHW[0]; +} + +void RSP_Vector_VRCPL (void) { + int count, neg; + + RecpResult.UW = RSP_Vect[RSPOpC.rt].UHW[EleSpec[RSPOpC.rs].B[(RSPOpC.rd & 0x7)]] | Recp.W; + if (RecpResult.UW == 0) { + RecpResult.UW = 0x7FFFFFFF; + } else { + if (RecpResult.W < 0) { + neg = TRUE; + if (RecpResult.UHW[1] == 0xFFFF && RecpResult.HW[0] < 0) { + RecpResult.W = ~RecpResult.W + 1; + } else { + RecpResult.W = ~RecpResult.W; + } + } else { + neg = FALSE; + } + for (count = 31; count > 0; count--) { + if ((RecpResult.W & (1 << count))) { + RecpResult.W &= (0xFFC00000 >> (31 - count) ); + count = 0; + } + } + { + DWORD OldModel = _controlfp(_RC_CHOP, _MCW_RC); + //RecpResult.W = 0x7FFFFFFF / RecpResult.W; + RecpResult.W = (long)((0x7FFFFFFF / (double)RecpResult.W)); + OldModel = _controlfp(OldModel, _MCW_RC); + } + for (count = 31; count > 0; count--) { + if ((RecpResult.W & (1 << count))) { + RecpResult.W &= (0xFFFF8000 >> (31 - count) ); + count = 0; + } + } + if (neg == TRUE) { + RecpResult.W = ~RecpResult.W; + } + } + for ( count = 0; count < 8; count++ ) { + RSP_ACCUM[count].HW[1] = RSP_Vect[RSPOpC.rt].UHW[EleSpec[RSPOpC.rs].B[count]]; + } + RSP_Vect[RSPOpC.sa].HW[7 - (RSPOpC.rd & 0x7)] = RecpResult.UHW[0]; +} + +void RSP_Vector_VRCPH (void) { + int count; + + Recp.UHW[1] = RSP_Vect[RSPOpC.rt].UHW[EleSpec[RSPOpC.rs].B[(RSPOpC.rd & 0x7)]]; + for ( count = 0; count < 8; count++ ) { + RSP_ACCUM[count].HW[1] = RSP_Vect[RSPOpC.rt].UHW[EleSpec[RSPOpC.rs].B[count]]; + } + RSP_Vect[RSPOpC.sa].UHW[7 - (RSPOpC.rd & 0x7)] = RecpResult.UHW[1]; +} + +void RSP_Vector_VMOV (void) { + int count; + for ( count = 0; count < 8; count++ ) { + RSP_ACCUM[count].HW[1] = RSP_Vect[RSPOpC.rt].UHW[EleSpec[RSPOpC.rs].B[count]]; + } + + RSP_Vect[RSPOpC.sa].UHW[7 - (RSPOpC.rd & 0x7)] = + RSP_Vect[RSPOpC.rt].UHW[EleSpec[RSPOpC.rs].B[(RSPOpC.rd & 0x7)]]; +} + +void RSP_Vector_VRSQ (void) { + int count, neg; + + SQrootResult.W = RSP_Vect[RSPOpC.rt].HW[EleSpec[RSPOpC.rs].B[(RSPOpC.rd & 0x7)]]; + if (SQrootResult.UW == 0) { + SQrootResult.UW = 0x7FFFFFFF; + } else if (SQrootResult.UW == 0xFFFF8000) { + SQrootResult.UW = 0xFFFF0000; + } else { + if (SQrootResult.W < 0) { + neg = TRUE; + SQrootResult.W = ~SQrootResult.W + 1; + } else { + neg = FALSE; + } + for (count = 15; count > 0; count--) { + if ((SQrootResult.W & (1 << count))) { + SQrootResult.W &= (0xFF80 >> (15 - count) ); + count = 0; + } + } + { + DWORD RoundMethod = _RC_CHOP; + DWORD OldModel = _controlfp(RoundMethod, _MCW_RC); + SQrootResult.W = (long)(0x7FFFFFFF / sqrt(SQrootResult.W)); + OldModel = _controlfp(OldModel, _MCW_RC); + } + for (count = 31; count > 0; count--) { + if ((SQrootResult.W & (1 << count))) { + SQrootResult.W &= (0xFFFF8000 >> (31 - count) ); + count = 0; + } + } + if (neg == TRUE) { + SQrootResult.W = ~SQrootResult.W; + } + } + for ( count = 0; count < 8; count++ ) { + RSP_ACCUM[count].HW[1] = RSP_Vect[RSPOpC.rt].UHW[EleSpec[RSPOpC.rs].B[count]]; + } + RSP_Vect[RSPOpC.sa].HW[7 - (RSPOpC.rd & 0x7)] = SQrootResult.UHW[0]; +} + +void RSP_Vector_VRSQL (void) { + int count, neg; + + SQrootResult.UW = RSP_Vect[RSPOpC.rt].UHW[EleSpec[RSPOpC.rs].B[(RSPOpC.rd & 0x7)]] | SQroot.W; + if (SQrootResult.UW == 0) { + SQrootResult.UW = 0x7FFFFFFF; + } else if (SQrootResult.UW == 0xFFFF8000) { + SQrootResult.UW = 0xFFFF0000; + } else { + if (SQrootResult.W < 0) { + neg = TRUE; + if (SQrootResult.UHW[1] == 0xFFFF && SQrootResult.HW[0] < 0) { + SQrootResult.W = ~SQrootResult.W + 1; + } else { + SQrootResult.W = ~SQrootResult.W; + } + } else { + neg = FALSE; + } + for (count = 31; count > 0; count--) { + if ((SQrootResult.W & (1 << count))) { + SQrootResult.W &= (0xFF800000 >> (31 - count) ); + count = 0; + } + } + { + DWORD OldModel = _controlfp(_RC_CHOP, _MCW_RC); + SQrootResult.W = (long)(0x7FFFFFFF / sqrt(SQrootResult.W)); + OldModel = _controlfp(OldModel, _MCW_RC); + } + for (count = 31; count > 0; count--) { + if ((SQrootResult.W & (1 << count))) { + SQrootResult.W &= (0xFFFF8000 >> (31 - count) ); + count = 0; + } + } + if (neg == TRUE) { + SQrootResult.W = ~SQrootResult.W; + } + } + for ( count = 0; count < 8; count++ ) { + RSP_ACCUM[count].HW[1] = RSP_Vect[RSPOpC.rt].UHW[EleSpec[RSPOpC.rs].B[count]]; + } + RSP_Vect[RSPOpC.sa].HW[7 - (RSPOpC.rd & 0x7)] = SQrootResult.UHW[0]; +} + +void RSP_Vector_VRSQH (void) { + int count; + + SQroot.UHW[1] = RSP_Vect[RSPOpC.rt].UHW[EleSpec[RSPOpC.rs].B[(RSPOpC.rd & 0x7)]]; + for ( count = 0; count < 8; count++ ) { + RSP_ACCUM[count].HW[1] = RSP_Vect[RSPOpC.rt].UHW[EleSpec[RSPOpC.rs].B[count]]; + } + RSP_Vect[RSPOpC.sa].UHW[7 - (RSPOpC.rd & 0x7)] = SQrootResult.UHW[1]; +} + +void RSP_Vector_VNOOP (void) {} +/************************** lc2 functions **************************/ +void RSP_Opcode_LBV ( void ) { + DWORD Address = ((RSP_GPR[RSPOpC.base].UW + (DWORD)(RSPOpC.voffset)) &0xFFF); + RSP_LBV_DMEM( Address, RSPOpC.rt, RSPOpC.del); +} + +void RSP_Opcode_LSV ( void ) { + DWORD Address = ((RSP_GPR[RSPOpC.base].UW + (DWORD)(RSPOpC.voffset << 1)) &0xFFF); + RSP_LSV_DMEM( Address, RSPOpC.rt, RSPOpC.del); +} + +void RSP_Opcode_LLV ( void ) { + DWORD Address = ((RSP_GPR[RSPOpC.base].UW + (DWORD)(RSPOpC.voffset << 2)) &0xFFF); + RSP_LLV_DMEM( Address, RSPOpC.rt, RSPOpC.del); +} + +void RSP_Opcode_LDV ( void ) { + DWORD Address = ((RSP_GPR[RSPOpC.base].UW + (DWORD)(RSPOpC.voffset << 3)) &0xFFF); + RSP_LDV_DMEM( Address, RSPOpC.rt, RSPOpC.del); +} + +void RSP_Opcode_LQV ( void ) { + DWORD Address = ((RSP_GPR[RSPOpC.base].UW + (DWORD)(RSPOpC.voffset << 4)) &0xFFF); + RSP_LQV_DMEM( Address, RSPOpC.rt, RSPOpC.del); +} + +void RSP_Opcode_LRV ( void ) { + DWORD Address = ((RSP_GPR[RSPOpC.base].UW + (DWORD)(RSPOpC.voffset << 4)) &0xFFF); + RSP_LRV_DMEM( Address, RSPOpC.rt, RSPOpC.del); +} + +void RSP_Opcode_LPV ( void ) { + DWORD Address = ((RSP_GPR[RSPOpC.base].UW + (DWORD)(RSPOpC.voffset << 3)) &0xFFF); + RSP_LPV_DMEM( Address, RSPOpC.rt, RSPOpC.del); +} + +void RSP_Opcode_LUV ( void ) { + DWORD Address = ((RSP_GPR[RSPOpC.base].UW + (DWORD)(RSPOpC.voffset << 3)) &0xFFF); + RSP_LUV_DMEM( Address, RSPOpC.rt, RSPOpC.del); +} + +void RSP_Opcode_LHV ( void ) { + DWORD Address = ((RSP_GPR[RSPOpC.base].UW + (DWORD)(RSPOpC.voffset << 4)) &0xFFF); + RSP_LHV_DMEM( Address, RSPOpC.rt, RSPOpC.del); +} + +void RSP_Opcode_LFV ( void ) { + DWORD Address = ((RSP_GPR[RSPOpC.base].UW + (DWORD)(RSPOpC.voffset << 4)) &0xFFF); + RSP_LFV_DMEM( Address, RSPOpC.rt, RSPOpC.del); +} + +void RSP_Opcode_LTV ( void ) { + DWORD Address = ((RSP_GPR[RSPOpC.base].UW + (DWORD)(RSPOpC.voffset << 4)) &0xFFF); + RSP_LTV_DMEM( Address, RSPOpC.rt, RSPOpC.del); +} + +/************************** sc2 functions **************************/ +void RSP_Opcode_SBV ( void ) { + DWORD Address = ((RSP_GPR[RSPOpC.base].UW + (DWORD)(RSPOpC.voffset)) &0xFFF); + RSP_SBV_DMEM( Address, RSPOpC.rt, RSPOpC.del); +} + +void RSP_Opcode_SSV ( void ) { + DWORD Address = ((RSP_GPR[RSPOpC.base].UW + (DWORD)(RSPOpC.voffset << 1)) &0xFFF); + RSP_SSV_DMEM( Address, RSPOpC.rt, RSPOpC.del); +} + +void RSP_Opcode_SLV ( void ) { + DWORD Address = ((RSP_GPR[RSPOpC.base].UW + (DWORD)(RSPOpC.voffset << 2)) &0xFFF); + RSP_SLV_DMEM( Address, RSPOpC.rt, RSPOpC.del); +} + +void RSP_Opcode_SDV ( void ) { + DWORD Address = ((RSP_GPR[RSPOpC.base].UW + (DWORD)(RSPOpC.voffset << 3)) &0xFFF); + RSP_SDV_DMEM( Address, RSPOpC.rt, RSPOpC.del); +} + +void RSP_Opcode_SQV ( void ) { + DWORD Address = ((RSP_GPR[RSPOpC.base].UW + (DWORD)(RSPOpC.voffset << 4)) &0xFFF); + RSP_SQV_DMEM( Address, RSPOpC.rt, RSPOpC.del); +} + +void RSP_Opcode_SRV ( void ) { + DWORD Address = ((RSP_GPR[RSPOpC.base].UW + (DWORD)(RSPOpC.voffset << 4)) &0xFFF); + RSP_SRV_DMEM( Address, RSPOpC.rt, RSPOpC.del); +} + +void RSP_Opcode_SPV ( void ) { + DWORD Address = ((RSP_GPR[RSPOpC.base].UW + (DWORD)(RSPOpC.voffset << 3)) &0xFFF); + RSP_SPV_DMEM( Address, RSPOpC.rt, RSPOpC.del); +} + +void RSP_Opcode_SUV ( void ) { + DWORD Address = ((RSP_GPR[RSPOpC.base].UW + (DWORD)(RSPOpC.voffset << 3)) &0xFFF); + RSP_SUV_DMEM( Address, RSPOpC.rt, RSPOpC.del); +} + +void RSP_Opcode_SHV ( void ) { + DWORD Address = ((RSP_GPR[RSPOpC.base].UW + (DWORD)(RSPOpC.voffset << 4)) &0xFFF); + RSP_SHV_DMEM( Address, RSPOpC.rt, RSPOpC.del); +} + +void RSP_Opcode_SFV ( void ) { + DWORD Address = ((RSP_GPR[RSPOpC.base].UW + (DWORD)(RSPOpC.voffset << 4)) &0xFFF); + RSP_SFV_DMEM( Address, RSPOpC.rt, RSPOpC.del); +} + +void RSP_Opcode_STV ( void ) { + DWORD Address = ((RSP_GPR[RSPOpC.base].UW + (DWORD)(RSPOpC.voffset << 4)) &0xFFF); + RSP_STV_DMEM( Address, RSPOpC.rt, RSPOpC.del); +} + +void RSP_Opcode_SWV ( void ) { + DWORD Address = ((RSP_GPR[RSPOpC.base].UW + (DWORD)(RSPOpC.voffset << 4)) &0xFFF); + RSP_SWV_DMEM( Address, RSPOpC.rt, RSPOpC.del); +} + +/************************** Other functions **************************/ + +void rsp_UnknownOpcode (void) { + char Message[200]; + int response; + + if (InRSPCommandsWindow) { + SetRSPCommandViewto( *PrgCount ); + DisplayError("Unhandled Opcode\n%s\n\nStoping Emulation!", RSPOpcodeName(RSPOpC.Hex,*PrgCount)); + } else { + sprintf(Message,"Unhandled Opcode\n%s\n\nStoping Emulation!\n\nDo you wish to enter the debugger ?", + RSPOpcodeName(RSPOpC.Hex,*PrgCount)); + response = MessageBox(NULL,Message,"Error", MB_YESNO | MB_ICONERROR ); + if (response == IDYES) { + Enter_RSP_Commands_Window (); + } + } + ExitThread(0); +} \ No newline at end of file diff --git a/Source/RSP/Interpreter Ops.h b/Source/RSP/Interpreter Ops.h new file mode 100644 index 000000000..f684e5bc0 --- /dev/null +++ b/Source/RSP/Interpreter Ops.h @@ -0,0 +1,158 @@ +/* + * RSP Compiler plug in for Project 64 (A Nintendo 64 emulator). + * + * (c) Copyright 2001 jabo (jabo@emulation64.com) and + * zilmar (zilmar@emulation64.com) + * + * pj64 homepage: www.pj64.net + * + * Permission to use, copy, modify and distribute Project64 in both binary and + * source form, for non-commercial purposes, is hereby granted without fee, + * providing that this license information and copyright notice appear with + * all copies and any derived work. + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event shall the authors be held liable for any damages + * arising from the use of this software. + * + * Project64 is freeware for PERSONAL USE only. Commercial users should + * seek permission of the copyright holders first. Commercial use includes + * charging money for Project64 or software derived from Project64. + * + * The copyright holders request that bug fixes and improvements to the code + * should be forwarded to them so if they want them. + * + */ + +/************************* OpCode functions *************************/ +void RSP_Opcode_SPECIAL ( void ); +void RSP_Opcode_REGIMM ( void ); +void RSP_Opcode_J ( void ); +void RSP_Opcode_JAL ( void ); +void RSP_Opcode_BEQ ( void ); +void RSP_Opcode_BNE ( void ); +void RSP_Opcode_BLEZ ( void ); +void RSP_Opcode_BGTZ ( void ); +void RSP_Opcode_ADDI ( void ); +void RSP_Opcode_ADDIU ( void ); +void RSP_Opcode_SLTI ( void ); +void RSP_Opcode_SLTIU ( void ); +void RSP_Opcode_ANDI ( void ); +void RSP_Opcode_ORI ( void ); +void RSP_Opcode_XORI ( void ); +void RSP_Opcode_LUI ( void ); +void RSP_Opcode_COP0 ( void ); +void RSP_Opcode_COP2 ( void ); +void RSP_Opcode_LB ( void ); +void RSP_Opcode_LH ( void ); +void RSP_Opcode_LW ( void ); +void RSP_Opcode_LBU ( void ); +void RSP_Opcode_LHU ( void ); +void RSP_Opcode_SB ( void ); +void RSP_Opcode_SH ( void ); +void RSP_Opcode_SW ( void ); +void RSP_Opcode_LC2 ( void ); +void RSP_Opcode_SC2 ( void ); +/********************** R4300i OpCodes: Special **********************/ +void RSP_Special_SLL ( void ); +void RSP_Special_SRL ( void ); +void RSP_Special_SRA ( void ); +void RSP_Special_SLLV ( void ); +void RSP_Special_SRLV ( void ); +void RSP_Special_SRAV ( void ); +void RSP_Special_JR ( void ); +void RSP_Special_JALR ( void ); +void RSP_Special_BREAK ( void ); +void RSP_Special_ADD ( void ); +void RSP_Special_ADDU ( void ); +void RSP_Special_SUB ( void ); +void RSP_Special_SUBU ( void ); +void RSP_Special_AND ( void ); +void RSP_Special_OR ( void ); +void RSP_Special_XOR ( void ); +void RSP_Special_NOR ( void ); +void RSP_Special_SLT ( void ); +void RSP_Special_SLTU ( void ); +/********************** R4300i OpCodes: RegImm **********************/ +void RSP_Opcode_BLTZ ( void ); +void RSP_Opcode_BGEZ ( void ); +void RSP_Opcode_BLTZAL ( void ); +void RSP_Opcode_BGEZAL ( void ); +/************************** Cop0 functions *************************/ +void RSP_Cop0_MF ( void ); +void RSP_Cop0_MT ( void ); +/************************** Cop2 functions *************************/ +void RSP_Cop2_MF ( void ); +void RSP_Cop2_CF ( void ); +void RSP_Cop2_MT ( void ); +void RSP_Cop2_CT ( void ); +void RSP_COP2_VECTOR ( void ); +/************************** Vect functions **************************/ +void RSP_Vector_VMULF ( void ); +void RSP_Vector_VMULU ( void ); +void RSP_Vector_VMUDL ( void ); +void RSP_Vector_VMUDM ( void ); +void RSP_Vector_VMUDN ( void ); +void RSP_Vector_VMUDH ( void ); +void RSP_Vector_VMACF ( void ); +void RSP_Vector_VMACU ( void ); +void RSP_Vector_VMACQ ( void ); +void RSP_Vector_VMADL ( void ); +void RSP_Vector_VMADM ( void ); +void RSP_Vector_VMADN ( void ); +void RSP_Vector_VMADH ( void ); +void RSP_Vector_VADD ( void ); +void RSP_Vector_VSUB ( void ); +void RSP_Vector_VABS ( void ); +void RSP_Vector_VADDC ( void ); +void RSP_Vector_VSUBC ( void ); +void RSP_Vector_VSAW ( void ); +void RSP_Vector_VLT ( void ); +void RSP_Vector_VEQ ( void ); +void RSP_Vector_VNE ( void ); +void RSP_Vector_VGE ( void ); +void RSP_Vector_VCL ( void ); +void RSP_Vector_VCH ( void ); +void RSP_Vector_VCR ( void ); +void RSP_Vector_VMRG ( void ); +void RSP_Vector_VAND ( void ); +void RSP_Vector_VNAND ( void ); +void RSP_Vector_VOR ( void ); +void RSP_Vector_VNOR ( void ); +void RSP_Vector_VXOR ( void ); +void RSP_Vector_VNXOR ( void ); +void RSP_Vector_VRCP ( void ); +void RSP_Vector_VRCPL ( void ); +void RSP_Vector_VRCPH ( void ); +void RSP_Vector_VMOV ( void ); +void RSP_Vector_VRSQ ( void ); +void RSP_Vector_VRSQL ( void ); +void RSP_Vector_VRSQH ( void ); +void RSP_Vector_VNOOP ( void ); +/************************** lc2 functions **************************/ +void RSP_Opcode_LBV ( void ); +void RSP_Opcode_LSV ( void ); +void RSP_Opcode_LLV ( void ); +void RSP_Opcode_LDV ( void ); +void RSP_Opcode_LQV ( void ); +void RSP_Opcode_LRV ( void ); +void RSP_Opcode_LPV ( void ); +void RSP_Opcode_LUV ( void ); +void RSP_Opcode_LHV ( void ); +void RSP_Opcode_LFV ( void ); +void RSP_Opcode_LTV ( void ); +/************************** lc2 functions **************************/ +void RSP_Opcode_SBV ( void ); +void RSP_Opcode_SSV ( void ); +void RSP_Opcode_SLV ( void ); +void RSP_Opcode_SDV ( void ); +void RSP_Opcode_SQV ( void ); +void RSP_Opcode_SRV ( void ); +void RSP_Opcode_SPV ( void ); +void RSP_Opcode_SUV ( void ); +void RSP_Opcode_SHV ( void ); +void RSP_Opcode_SFV ( void ); +void RSP_Opcode_STV ( void ); +void RSP_Opcode_SWV ( void ); +/************************** Other functions **************************/ +void rsp_UnknownOpcode ( void ); diff --git a/Source/RSP/Main.cpp b/Source/RSP/Main.cpp new file mode 100644 index 000000000..ae44c81bf --- /dev/null +++ b/Source/RSP/Main.cpp @@ -0,0 +1,718 @@ +/* + * RSP Compiler plug in for Project 64 (A Nintendo 64 emulator). + * + * (c) Copyright 2001 jabo (jabo@emulation64.com) and + * zilmar (zilmar@emulation64.com) + * + * pj64 homepage: www.pj64.net + * + * Permission to use, copy, modify and distribute Project64 in both binary and + * source form, for non-commercial purposes, is hereby granted without fee, + * providing that this license information and copyright notice appear with + * all copies and any derived work. + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event shall the authors be held liable for any damages + * arising from the use of this software. + * + * Project64 is freeware for PERSONAL USE only. Commercial users should + * seek permission of the copyright holders first. Commercial use includes + * charging money for Project64 or software derived from Project64. + * + * The copyright holders request that bug fixes and improvements to the code + * should be forwarded to them so if they want them. + * + */ + +#include +#include +#include +#include + +#include +#include +#include "../Settings/Settings.h" + +extern "C" { +#include "Rsp.h" +#include "CPU.h" +#include "Recompiler CPU.h" +#include "Rsp Command.h" +#include "Rsp Registers.h" +#include "memory.h" +#include "breakpoint.h" +#include "profiling.h" +#include "log.h" +#include "resource.h" + +void ClearAllx86Code(void); +void ProcessMenuItem(int ID); +BOOL CALLBACK CompilerDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam); + +BOOL GraphicsHle = TRUE, AudioHle, ConditionalMove; +BOOL DebuggingEnabled = FALSE, + Profiling, + IndvidualBlock, + ShowErrors, + BreakOnStart = FALSE, + LogRDP = FALSE, + LogX86Code = FALSE; +DWORD CPUCore = RecompilerCPU; + +HANDLE hMutex = NULL; + +DEBUG_INFO DebugInfo; +RSP_INFO RSPInfo; +HINSTANCE hinstDLL; +HMENU hRSPMenu = NULL; + +extern BYTE * pLastSecondary; +} + +enum { + Set_BreakOnStart, Set_CPUCore, Set_LogRDP, Set_LogX86Code, Set_Profiling, Set_IndvidualBlock, + Set_AudioHle, Set_GraphicsHle, Set_ShowErrors, + + //Compiler settings + Set_CheckDest, Set_Accum, Set_Mmx, Set_Mmx2, Set_Sse, Set_Sections, + Set_ReOrdering, Set_GPRConstants, Set_Flags, Set_AlignVector, +}; + +/************ DLL info **************/ +const char * AppName ( void ) +{ + static stdstr_f Name("RSP %s",VersionInfo(VERSION_PRODUCT_VERSION,hinstDLL)); + return Name.c_str(); +} +const char * AboutMsg ( void ) +{ + static stdstr_f Msg("RSP emulation Plugin\nMade for Project64 (c)\nVersion %s\n\nby Jabo & Zilmar",VersionInfo(VERSION_PRODUCT_VERSION,hinstDLL)); + return Msg.c_str(); +} + +/************ Functions ***********/ +DWORD AsciiToHex (char * HexValue) { + DWORD Count, Finish, Value = 0; + + Finish = strlen(HexValue); + if (Finish > 8 ) { Finish = 8; } + + for (Count = 0; Count < Finish; Count++){ + Value = (Value << 4); + switch( HexValue[Count] ) { + case '0': break; + case '1': Value += 1; break; + case '2': Value += 2; break; + case '3': Value += 3; break; + case '4': Value += 4; break; + case '5': Value += 5; break; + case '6': Value += 6; break; + case '7': Value += 7; break; + case '8': Value += 8; break; + case '9': Value += 9; break; + case 'A': Value += 10; break; + case 'a': Value += 10; break; + case 'B': Value += 11; break; + case 'b': Value += 11; break; + case 'C': Value += 12; break; + case 'c': Value += 12; break; + case 'D': Value += 13; break; + case 'd': Value += 13; break; + case 'E': Value += 14; break; + case 'e': Value += 14; break; + case 'F': Value += 15; break; + case 'f': Value += 15; break; + default: + Value = (Value >> 4); + Count = Finish; + } + } + return Value; +} + +void DisplayError (char * Message, ...) { + char Msg[400]; + va_list ap; + + va_start( ap, Message ); + vsprintf( Msg, Message, ap ); + va_end( ap ); + MessageBox(NULL,Msg,"Error",MB_OK|MB_ICONERROR); +} + +/****************************************************************** + Function: CloseDLL + Purpose: This function is called when the emulator is closing + down allowing the dll to de-initialise. + input: none + output: none +*******************************************************************/ +__declspec(dllexport) void CloseDLL (void) { + FreeMemory(); +} + +/****************************************************************** + Function: DllAbout + Purpose: This function is optional function that is provided + to give further information about the DLL. + input: a handle to the window that calls this function + output: none +*******************************************************************/ +__declspec(dllexport) void DllAbout ( HWND hParent ) { + MessageBox(hParent,AboutMsg(),"About",MB_OK | MB_ICONINFORMATION ); +} + +BOOL WINAPI DllMain( HINSTANCE hinst, DWORD fdwReason, LPVOID lpvReserved ){ + hinstDLL = hinst; + if (strcmp(VersionInfo(VERSION_INTERNAL_NAME).c_str(),"Project64") != 0) + { + return FALSE; + } + return TRUE; +} +/****************************************************************** + Function: GetDllInfo + Purpose: This function allows the emulator to gather information + about the dll by filling in the PluginInfo structure. + input: a pointer to a PLUGIN_INFO stucture that needs to be + filled by the function. (see def above) + output: none +*******************************************************************/ +__declspec(dllexport) void GetDllInfo ( PLUGIN_INFO * PluginInfo ) { + PluginInfo->Version = 0x0102; + PluginInfo->Type = PLUGIN_TYPE_RSP; + sprintf(PluginInfo->Name,"RSP Plugin %s",VersionInfo(VERSION_PRODUCT_VERSION,hinstDLL)); + PluginInfo->NormalMemory = FALSE; + PluginInfo->MemoryBswaped = TRUE; +} + +/****************************************************************** + Function: GetRspDebugInfo + Purpose: This function allows the emulator to gather information + about the debug capabilities of the dll by filling in + the DebugInfo structure. + input: a pointer to a RSPDEBUG_INFO stucture that needs to be + filled by the function. (see def above) + output: none +*******************************************************************/ + +#if !defined(EXTERNAL_RELEASE) + +void FixMenuState (void) +{ + EnableMenuItem(hRSPMenu,ID_RSPCOMMANDS,MF_BYCOMMAND| (DebuggingEnabled ? MF_ENABLED : (MF_GRAYED | MF_DISABLED))); + EnableMenuItem(hRSPMenu,ID_RSPREGISTERS,MF_BYCOMMAND| (DebuggingEnabled ? MF_ENABLED : (MF_GRAYED | MF_DISABLED))); + EnableMenuItem(hRSPMenu,ID_PROFILING_RESETSTATS,MF_BYCOMMAND| (DebuggingEnabled ? MF_ENABLED : (MF_GRAYED | MF_DISABLED))); + EnableMenuItem(hRSPMenu,ID_PROFILING_GENERATELOG,MF_BYCOMMAND| (DebuggingEnabled ? MF_ENABLED : (MF_GRAYED | MF_DISABLED))); + EnableMenuItem(hRSPMenu,ID_DUMP_RSPCODE,MF_BYCOMMAND| (DebuggingEnabled ? MF_ENABLED : (MF_GRAYED | MF_DISABLED))); + EnableMenuItem(hRSPMenu,ID_DUMP_DMEM,MF_BYCOMMAND| (DebuggingEnabled ? MF_ENABLED : (MF_GRAYED | MF_DISABLED))); + + CheckMenuItem( hRSPMenu, ID_CPUMETHOD_RECOMPILER, MF_BYCOMMAND | (CPUCore == RecompilerCPU ? MFS_CHECKED : MF_UNCHECKED )); + CheckMenuItem( hRSPMenu, ID_CPUMETHOD_INTERPT, MF_BYCOMMAND | (CPUCore == InterpreterCPU ? MFS_CHECKED : MF_UNCHECKED )); + CheckMenuItem( hRSPMenu, ID_BREAKONSTARTOFTASK, MF_BYCOMMAND | (BreakOnStart ? MFS_CHECKED : MF_UNCHECKED )); + CheckMenuItem( hRSPMenu, ID_LOGRDPCOMMANDS, MF_BYCOMMAND | (LogRDP ? MFS_CHECKED : MF_UNCHECKED )); + CheckMenuItem( hRSPMenu, ID_SETTINGS_LOGX86CODE, MF_BYCOMMAND | (LogX86Code ? MFS_CHECKED : MF_UNCHECKED )); + CheckMenuItem( hRSPMenu, ID_PROFILING_ON, MF_BYCOMMAND | (Profiling ? MFS_CHECKED : MF_UNCHECKED )); + CheckMenuItem( hRSPMenu, ID_PROFILING_OFF, MF_BYCOMMAND | (Profiling ? MFS_UNCHECKED : MF_CHECKED )); + CheckMenuItem( hRSPMenu, ID_PROFILING_LOGINDIVIDUALBLOCKS, MF_BYCOMMAND | (IndvidualBlock ? MFS_CHECKED : MF_UNCHECKED )); + CheckMenuItem( hRSPMenu, ID_SHOWCOMPILERERRORS,MF_BYCOMMAND | (ShowErrors ? MFS_CHECKED : MF_UNCHECKED )); +} + +__declspec(dllexport) void GetRspDebugInfo ( RSPDEBUG_INFO * DebugInfo ) +{ + if (hRSPMenu == NULL) + { + hRSPMenu = LoadMenu(hinstDLL,MAKEINTRESOURCE(RspMenu)); + FixMenuState(); + } + DebugInfo->hRSPMenu = hRSPMenu; + DebugInfo->ProcessMenuItem = ProcessMenuItem; + + DebugInfo->UseBPoints = TRUE; + sprintf(DebugInfo->BPPanelName," RSP "); + DebugInfo->Add_BPoint = Add_BPoint; + DebugInfo->CreateBPPanel = CreateBPPanel; + DebugInfo->HideBPPanel = HideBPPanel; + DebugInfo->PaintBPPanel = PaintBPPanel; + DebugInfo->RefreshBpoints = RefreshBpoints; + DebugInfo->RemoveAllBpoint = RemoveAllBpoint; + DebugInfo->RemoveBpoint = RemoveBpoint; + DebugInfo->ShowBPPanel = ShowBPPanel; + + DebugInfo->Enter_RSP_Commands_Window = Enter_RSP_Commands_Window; +} + +#endif + +/****************************************************************** + Function: InitiateRSP + Purpose: This function is called when the DLL is started to give + information from the emulator that the n64 RSP + interface needs + input: Rsp_Info is passed to this function which is defined + above. + CycleCount is the number of cycles between switching + control between teh RSP and r4300i core. + output: none +*******************************************************************/ + +RSP_COMPILER Compiler; + +void DetectCpuSpecs(void) { + DWORD Intel_Features = 0; + DWORD AMD_Features = 0; + + __try { + _asm { + /* Intel features */ + mov eax, 1 + cpuid + mov [Intel_Features], edx + + /* AMD features */ + mov eax, 80000001h + cpuid + or [AMD_Features], edx + } + } __except ( EXCEPTION_EXECUTE_HANDLER) { + AMD_Features = Intel_Features = 0; + } + + if (Intel_Features & 0x02000000) { + Compiler.mmx2 = TRUE; + Compiler.sse = TRUE; + } + if (Intel_Features & 0x00800000) { + Compiler.mmx = TRUE; + } + if (AMD_Features & 0x40000000) { + Compiler.mmx2 = TRUE; + } + if (Intel_Features & 0x00008000) { + ConditionalMove = TRUE; + } else { + ConditionalMove = FALSE; + } +} + +__declspec(dllexport) void InitiateRSP ( RSP_INFO Rsp_Info, DWORD * CycleCount) { + RSPInfo = Rsp_Info; + AudioHle = GetSetting(Set_AudioHle); + GraphicsHle = GetSetting(Set_GraphicsHle); + + *CycleCount = 0; + AllocateMemory(); + InitilizeRSPRegisters(); + Build_RSP(); + #ifdef GenerateLog + Start_Log(); + #endif +} + +/****************************************************************** + Function: InitiateRSPDebugger + Purpose: This function is called when the DLL is started to give + information from the emulator that the n64 RSP + interface needs to intergrate the debugger with the + rest of the emulator. + input: DebugInfo is passed to this function which is defined + above. + output: none +*******************************************************************/ + +#if !defined(EXTERNAL_RELEASE) + +__declspec(dllexport) void InitiateRSPDebugger ( DEBUG_INFO Debug_Info) { + DebugInfo = Debug_Info; +} + +void ProcessMenuItem(int ID) { + UINT uState; + + switch (ID) { + case ID_RSPCOMMANDS: Enter_RSP_Commands_Window(); break; + case ID_RSPREGISTERS: Enter_RSP_Register_Window(); break; + case ID_DUMP_RSPCODE: DumpRSPCode(); break; + case ID_DUMP_DMEM: DumpRSPData(); break; + case ID_PROFILING_ON: + case ID_PROFILING_OFF: + { + uState = GetMenuState(hRSPMenu, ID_PROFILING_ON, MF_BYCOMMAND); + + if (uState & MFS_CHECKED) { + CheckMenuItem( hRSPMenu, ID_PROFILING_ON, MF_BYCOMMAND | MFS_UNCHECKED ); + CheckMenuItem( hRSPMenu, ID_PROFILING_OFF, MF_BYCOMMAND | MFS_CHECKED ); + SetSetting(Set_Profiling,FALSE); + if (DebuggingEnabled) { Profiling = FALSE; } + } else { + CheckMenuItem( hRSPMenu, ID_PROFILING_ON, MF_BYCOMMAND | MFS_CHECKED ); + CheckMenuItem( hRSPMenu, ID_PROFILING_OFF, MF_BYCOMMAND | MFS_UNCHECKED ); + SetSetting(Set_Profiling,TRUE); + if (DebuggingEnabled) { Profiling = TRUE; } + } + } + break; + case ID_PROFILING_RESETSTATS: ResetTimerList(); break; + case ID_PROFILING_GENERATELOG: GenerateTimerResults(); break; + case ID_PROFILING_LOGINDIVIDUALBLOCKS: + { + uState = GetMenuState(hRSPMenu, ID_PROFILING_LOGINDIVIDUALBLOCKS, MF_BYCOMMAND); + + if (uState & MFS_CHECKED) { + CheckMenuItem( hRSPMenu, ID_PROFILING_LOGINDIVIDUALBLOCKS, MF_BYCOMMAND | MFS_UNCHECKED ); + SetSetting(Set_IndvidualBlock,FALSE); + if (DebuggingEnabled) { IndvidualBlock = FALSE; } + } else { + CheckMenuItem( hRSPMenu, ID_PROFILING_LOGINDIVIDUALBLOCKS, MF_BYCOMMAND | MFS_CHECKED ); + SetSetting(Set_IndvidualBlock,TRUE); + if (DebuggingEnabled) { IndvidualBlock = TRUE; } + } + } + break; + case ID_SHOWCOMPILERERRORS: + { + uState = GetMenuState(hRSPMenu, ID_SHOWCOMPILERERRORS, MF_BYCOMMAND); + + if (uState & MFS_CHECKED) { + CheckMenuItem( hRSPMenu, ID_SHOWCOMPILERERRORS, MF_BYCOMMAND | MFS_UNCHECKED ); + SetSetting(Set_ShowErrors,FALSE); + if (DebuggingEnabled) { ShowErrors = FALSE; } + } else { + CheckMenuItem( hRSPMenu, ID_SHOWCOMPILERERRORS, MF_BYCOMMAND | MFS_CHECKED ); + SetSetting(Set_ShowErrors,TRUE); + if (DebuggingEnabled) { ShowErrors = TRUE; } + } + } + break; + case ID_COMPILER: + DialogBox(hinstDLL, "RSPCOMPILER", HWND_DESKTOP, CompilerDlgProc); + break; + case ID_BREAKONSTARTOFTASK: + { + uState = GetMenuState(hRSPMenu, ID_BREAKONSTARTOFTASK, MF_BYCOMMAND); + + if (uState & MFS_CHECKED) { + CheckMenuItem( hRSPMenu, ID_BREAKONSTARTOFTASK, MF_BYCOMMAND | MFS_UNCHECKED ); + SetSetting(Set_BreakOnStart,FALSE); + if (DebuggingEnabled) { BreakOnStart = FALSE; } + } else { + CheckMenuItem( hRSPMenu, ID_BREAKONSTARTOFTASK, MF_BYCOMMAND | MFS_CHECKED ); + SetSetting(Set_BreakOnStart,TRUE); + if (DebuggingEnabled) { BreakOnStart = TRUE; } + } + } + break; + case ID_LOGRDPCOMMANDS: + { + uState = GetMenuState(hRSPMenu, ID_LOGRDPCOMMANDS, MF_BYCOMMAND); + + if (uState & MFS_CHECKED) { + CheckMenuItem( hRSPMenu, ID_LOGRDPCOMMANDS, MF_BYCOMMAND | MFS_UNCHECKED ); + SetSetting(Set_LogRDP,FALSE); + if (DebuggingEnabled) + { + LogRDP = FALSE; + StopRDPLog(); + } + } else { + CheckMenuItem( hRSPMenu, ID_LOGRDPCOMMANDS, MF_BYCOMMAND | MFS_CHECKED ); + SetSetting(Set_LogRDP,TRUE); + if (DebuggingEnabled) + { + LogRDP = TRUE; + StartRDPLog(); + } + } + } + break; + case ID_SETTINGS_LOGX86CODE: + { + uState = GetMenuState(hRSPMenu, ID_SETTINGS_LOGX86CODE, MF_BYCOMMAND); + + if (uState & MFS_CHECKED) { + CheckMenuItem( hRSPMenu, ID_SETTINGS_LOGX86CODE, MF_BYCOMMAND | MFS_UNCHECKED ); + SetSetting(Set_LogX86Code,FALSE); + if (DebuggingEnabled) + { + LogX86Code = FALSE; + StopCPULog(); + } + } else { + CheckMenuItem( hRSPMenu, ID_SETTINGS_LOGX86CODE, MF_BYCOMMAND | MFS_CHECKED ); + SetSetting(Set_LogX86Code,TRUE); + if (DebuggingEnabled) + { + LogX86Code = TRUE; + StartCPULog(); + } + } + } + break; + case ID_CPUMETHOD_RECOMPILER: + { + SetSetting(Set_CPUCore,RecompilerCPU); + CPUCore = RecompilerCPU; + FixMenuState(); + SetCPU(RecompilerCPU); + } + break; + case ID_CPUMETHOD_INTERPT: + { + SetSetting(Set_CPUCore,InterpreterCPU); + CPUCore = InterpreterCPU; + FixMenuState(); + SetCPU(InterpreterCPU); + } + break; + } +} + +#endif + +/****************************************************************** + Function: RomClosed + Purpose: This function is called when a rom is closed. + input: none + output: none +*******************************************************************/ +__declspec(dllexport) void RomClosed (void) { + if (Profiling) { + StopTimer(); + GenerateTimerResults(); + } + InitilizeRSPRegisters(); + ClearAllx86Code(); + StopRDPLog(); + StopCPULog(); + +#ifdef GenerateLog + Stop_Log(); +#endif +} + +static BOOL GetBooleanCheck(HWND hDlg, DWORD DialogID) { + return (IsDlgButtonChecked(hDlg, DialogID) == BST_CHECKED) ? TRUE : FALSE; +} + +#if !defined(EXTERNAL_RELEASE) + +BOOL CALLBACK CompilerDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { + char Buffer[256]; + + switch (uMsg) { + case WM_INITDIALOG: + if (Compiler.bDest == TRUE) + CheckDlgButton(hDlg, IDC_COMPILER_DEST, BST_CHECKED); + if (Compiler.mmx == TRUE) + CheckDlgButton(hDlg, IDC_CHECK_MMX, BST_CHECKED); + if (Compiler.mmx2 == TRUE) + CheckDlgButton(hDlg, IDC_CHECK_MMX2, BST_CHECKED); + if (Compiler.sse == TRUE) + CheckDlgButton(hDlg, IDC_CHECK_SSE, BST_CHECKED); + + if (Compiler.bAlignVector == TRUE) + CheckDlgButton(hDlg, IDC_COMPILER_ALIGNVEC, BST_CHECKED); + + if (Compiler.bSections == TRUE) + CheckDlgButton(hDlg, IDC_COMPILER_SECTIONS, BST_CHECKED); + if (Compiler.bGPRConstants == TRUE) + CheckDlgButton(hDlg, IDC_COMPILER_GPRCONSTANTS, BST_CHECKED); + if (Compiler.bReOrdering == TRUE) + CheckDlgButton(hDlg, IDC_COMPILER_REORDER, BST_CHECKED); + if (Compiler.bFlags == TRUE) + CheckDlgButton(hDlg, IDC_COMPILER_FLAGS, BST_CHECKED); + if (Compiler.bAccum == TRUE) + CheckDlgButton(hDlg, IDC_COMPILER_ACCUM, BST_CHECKED); + + SetTimer(hDlg, 1, 250, NULL); + break; + + case WM_TIMER: + sprintf(Buffer, "x86: %2.2f KB / %2.2f KB", (float)(RecompPos - RecompCode) / 1024.0F, + pLastSecondary?(float)((pLastSecondary - RecompCodeSecondary) / 1024.0F):0); + + SetDlgItemText(hDlg, IDC_COMPILER_BUFFERS, Buffer); + break; + + case WM_COMMAND: + switch (GET_WM_COMMAND_ID(wParam, lParam)) { + case IDOK: + Compiler.bDest = GetBooleanCheck(hDlg, IDC_COMPILER_DEST); + Compiler.bAccum = GetBooleanCheck(hDlg, IDC_COMPILER_ACCUM); + Compiler.mmx = GetBooleanCheck(hDlg, IDC_CHECK_MMX); + Compiler.mmx2 = GetBooleanCheck(hDlg, IDC_CHECK_MMX2); + Compiler.sse = GetBooleanCheck(hDlg, IDC_CHECK_SSE); + Compiler.bSections = GetBooleanCheck(hDlg, IDC_COMPILER_SECTIONS); + Compiler.bReOrdering = GetBooleanCheck(hDlg, IDC_COMPILER_REORDER); + Compiler.bGPRConstants = GetBooleanCheck(hDlg, IDC_COMPILER_GPRCONSTANTS); + Compiler.bFlags = GetBooleanCheck(hDlg, IDC_COMPILER_FLAGS); + Compiler.bAlignVector = GetBooleanCheck(hDlg, IDC_COMPILER_ALIGNVEC); + SetSetting(Set_CheckDest,Compiler.bDest); + SetSetting(Set_Accum,Compiler.bAccum); + SetSetting(Set_Mmx,Compiler.mmx); + SetSetting(Set_Mmx2,Compiler.mmx2); + SetSetting(Set_Sse,Compiler.sse); + SetSetting(Set_Sections,Compiler.bSections); + SetSetting(Set_ReOrdering,Compiler.bReOrdering); + SetSetting(Set_GPRConstants,Compiler.bGPRConstants); + SetSetting(Set_Flags,Compiler.bFlags); + SetSetting(Set_AlignVector,Compiler.bAlignVector); + + KillTimer(hDlg, 1); + EndDialog(hDlg, TRUE); + break; + + case IDCANCEL: + KillTimer(hDlg, 1); + EndDialog(hDlg, TRUE); + break; + } + break; + + default: + return FALSE; + } + return TRUE; +} +#endif + +BOOL CALLBACK ConfigDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { + HWND hWndItem; + DWORD value; + + switch (uMsg) { + case WM_INITDIALOG: + if (AudioHle == TRUE) { + CheckDlgButton(hDlg, IDC_AUDIOHLE, BST_CHECKED); + } + + if (GraphicsHle == TRUE) { + CheckDlgButton(hDlg, IDC_GRAPHICSHLE, BST_CHECKED); + } + + hWndItem = GetDlgItem(hDlg, IDC_COMPILER_SELECT); + ComboBox_AddString(hWndItem, "Interpreter"); + ComboBox_AddString(hWndItem, "Recompiler"); + ComboBox_SetCurSel(hWndItem, CPUCore); + break; + + case WM_COMMAND: + switch (GET_WM_COMMAND_ID(wParam, lParam)) { + case IDOK: + hWndItem = GetDlgItem(hDlg, IDC_COMPILER_SELECT); + value = ComboBox_GetCurSel(hWndItem); + SetCPU(value); + + AudioHle = GetBooleanCheck(hDlg, IDC_AUDIOHLE); + GraphicsHle = GetBooleanCheck(hDlg, IDC_GRAPHICSHLE); + + EndDialog(hDlg, TRUE); + break; + case IDCANCEL: + EndDialog(hDlg, TRUE); + break; + } + break; + + default: + return FALSE; + } + return TRUE; +} + +/*__declspec(dllexport) void DllConfig (HWND hWnd) { + // DialogBox(hinstDLL, "RSPCONFIG", hWnd, ConfigDlgProc); + DialogBox(hinstDLL, "RSPCONFIG", GetForegroundWindow(), ConfigDlgProc); +}*/ + +__declspec(dllexport) void EnableDebugging (BOOL Enabled) { + DebuggingEnabled = Enabled; + if (DebuggingEnabled) + { + BreakOnStart = GetSetting(Set_BreakOnStart); + CPUCore = GetSetting(Set_CPUCore); + LogRDP = GetSetting(Set_LogRDP); + LogX86Code = GetSetting(Set_LogX86Code); + Profiling = GetSetting(Set_Profiling); + IndvidualBlock = GetSetting(Set_IndvidualBlock); + ShowErrors = GetSetting(Set_ShowErrors); + + Compiler.bDest = GetSetting(Set_CheckDest); + Compiler.bAccum = GetSetting(Set_Accum); + Compiler.mmx = GetSetting(Set_Mmx); + Compiler.mmx2 = GetSetting(Set_Mmx2); + Compiler.sse = GetSetting(Set_Sse); + Compiler.bSections = GetSetting(Set_Sections); + Compiler.bReOrdering = GetSetting(Set_ReOrdering); + Compiler.bGPRConstants = GetSetting(Set_GPRConstants); + Compiler.bFlags = GetSetting(Set_Flags); + Compiler.bAlignVector = GetSetting(Set_AlignVector); + SetCPU(CPUCore); + } + FixMenuState(); + if (LogRDP) + { + StartRDPLog(); + } + if (LogX86Code) + { + StartCPULog(); + } +} + +__declspec(dllexport) void PluginLoaded (void) +{ + BreakOnStart = false; + CPUCore = RecompilerCPU; + LogRDP = FALSE; + LogX86Code = FALSE; + Profiling = FALSE; + IndvidualBlock = FALSE; + ShowErrors = FALSE; + + memset(&Compiler, 0, sizeof(Compiler)); + + Compiler.bDest = TRUE; + Compiler.bAlignVector = FALSE; + Compiler.bFlags = TRUE; + Compiler.bReOrdering = TRUE; + Compiler.bSections = TRUE; + Compiler.bAccum = TRUE; + Compiler.bGPRConstants = TRUE; + DetectCpuSpecs(); + + SetModuleName("RSP"); + RegisterSetting(Set_BreakOnStart, Data_DWORD_General,"Break on Start", NULL,BreakOnStart,NULL); + RegisterSetting(Set_CPUCore, Data_DWORD_General,"CPU Method", NULL,CPUCore,NULL); + RegisterSetting(Set_LogRDP, Data_DWORD_General,"Log RDP", NULL,LogRDP,NULL); + RegisterSetting(Set_LogX86Code, Data_DWORD_General,"Log X86 Code", NULL,LogX86Code,NULL); + RegisterSetting(Set_Profiling, Data_DWORD_General,"Profiling", NULL,Profiling,NULL); + RegisterSetting(Set_IndvidualBlock, Data_DWORD_General,"Indvidual Block",NULL,IndvidualBlock,NULL); + RegisterSetting(Set_AudioHle, Data_DWORD_General,"HLE Audio", NULL,FALSE,NULL); + RegisterSetting(Set_GraphicsHle, Data_DWORD_General,"HLE GFX", NULL,TRUE,NULL); + RegisterSetting(Set_ShowErrors, Data_DWORD_General,"Show Errors", NULL,ShowErrors,NULL); + + //Compiler settings + RegisterSetting(Set_CheckDest, Data_DWORD_General,"Check Dest Vector", NULL,Compiler.bDest,NULL); + RegisterSetting(Set_Accum, Data_DWORD_General,"Check Dest Accum", NULL,Compiler.bAccum,NULL); + RegisterSetting(Set_Mmx, Data_DWORD_General,"Use MMX", NULL,Compiler.mmx,NULL); + RegisterSetting(Set_Mmx2, Data_DWORD_General,"Use MMX2", NULL,Compiler.mmx2,NULL); + RegisterSetting(Set_Sse, Data_DWORD_General,"Use SSE", NULL,Compiler.sse,NULL); + RegisterSetting(Set_Sections, Data_DWORD_General,"Use precompiled sections", NULL,Compiler.bSections,NULL); + RegisterSetting(Set_ReOrdering, Data_DWORD_General,"Reorder opcodes", NULL,Compiler.bReOrdering,NULL); + RegisterSetting(Set_GPRConstants, Data_DWORD_General,"Detect GPR Constants", NULL,Compiler.bGPRConstants,NULL); + RegisterSetting(Set_Flags, Data_DWORD_General,"Check Flag Usage", NULL,Compiler.bFlags,NULL); + RegisterSetting(Set_AlignVector, Data_DWORD_General,"Assume Vector loads align", NULL,Compiler.bAlignVector,NULL); + + AudioHle = GetSetting(Set_AudioHle); + GraphicsHle = GetSetting(Set_GraphicsHle); + + hMutex = CreateMutex(NULL, FALSE, NULL); + + SetCPU(CPUCore); +} + +void UseUnregisteredSetting (int SettingID) +{ + _asm int 3 +} diff --git a/Source/RSP/Mmx.c b/Source/RSP/Mmx.c new file mode 100644 index 000000000..9b695987e --- /dev/null +++ b/Source/RSP/Mmx.c @@ -0,0 +1,737 @@ +/* + * RSP Compiler plug in for Project 64 (A Nintendo 64 emulator). + * + * (c) Copyright 2001 jabo (jabo@emulation64.com) and + * zilmar (zilmar@emulation64.com) + * + * pj64 homepage: www.pj64.net + * + * Permission to use, copy, modify and distribute Project64 in both binary and + * source form, for non-commercial purposes, is hereby granted without fee, + * providing that this license information and copyright notice appear with + * all copies and any derived work. + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event shall the authors be held liable for any damages + * arising from the use of this software. + * + * Project64 is freeware for PERSONAL USE only. Commercial users should + * seek permission of the copyright holders first. Commercial use includes + * charging money for Project64 or software derived from Project64. + * + * The copyright holders request that bug fixes and improvements to the code + * should be forwarded to them so if they want them. + * + */ + +#include +#include +#include "rsp.h" +#include "x86.h" +#include "memory.h" +#include "RSP registers.h" +#include "log.h" + +#define PUTDST8(dest,value) (*((BYTE *)(dest))=(BYTE)(value)); dest += 1; +#define PUTDST16(dest,value) (*((WORD *)(dest))=(WORD)(value)); dest += 2; +#define PUTDST32(dest,value) (*((DWORD *)(dest))=(DWORD)(value)); dest += 4; + +char * mmx_Strings[8] = { + "mm0", "mm1", "mm2", "mm3", + "mm4", "mm5", "mm6", "mm7" +}; + +#define mmx_Name(Reg) (mmx_Strings[(Reg)]) + + +void MmxEmptyMultimediaState(void) { + CPU_Message(" emms"); + PUTDST16(RecompPos,0x770f); +} + +void MmxMoveRegToReg(int Dest, int Source) { + BYTE x86Command = 0; + + CPU_Message(" movq %s, %s", mmx_Name(Dest), mmx_Name(Source)); + + switch (Dest) { + case x86_MM0: x86Command = 0; break; + case x86_MM1: x86Command = 1; break; + case x86_MM2: x86Command = 2; break; + case x86_MM3: x86Command = 3; break; + case x86_MM4: x86Command = 4; break; + case x86_MM5: x86Command = 5; break; + case x86_MM6: x86Command = 6; break; + case x86_MM7: x86Command = 7; break; + } + switch (Source) { + case x86_MM0: x86Command |= 0 << 3; break; + case x86_MM1: x86Command |= 1 << 3; break; + case x86_MM2: x86Command |= 2 << 3; break; + case x86_MM3: x86Command |= 3 << 3; break; + case x86_MM4: x86Command |= 4 << 3; break; + case x86_MM5: x86Command |= 5 << 3; break; + case x86_MM6: x86Command |= 6 << 3; break; + case x86_MM7: x86Command |= 7 << 3; break; + } + PUTDST16(RecompPos,0x7f0f); + PUTDST8(RecompPos, 0xC0 | x86Command); +} + +void MmxMoveQwordVariableToReg(int Dest, void *Variable, char *VariableName) { + BYTE x86Command; + + CPU_Message(" movq %s, qword ptr [%s]",mmx_Name(Dest), VariableName); + + switch (Dest) { + case x86_MM0: x86Command = 0x05; break; + case x86_MM1: x86Command = 0x0D; break; + case x86_MM2: x86Command = 0x15; break; + case x86_MM3: x86Command = 0x1D; break; + case x86_MM4: x86Command = 0x25; break; + case x86_MM5: x86Command = 0x2D; break; + case x86_MM6: x86Command = 0x35; break; + case x86_MM7: x86Command = 0x3D; break; + } + + PUTDST16(RecompPos,0x6f0f); + PUTDST8(RecompPos, x86Command); + PUTDST32(RecompPos,Variable); +} + +void MmxMoveQwordRegToVariable(int Dest, void *Variable, char *VariableName) { + BYTE x86Command; + + CPU_Message(" movq qword ptr [%s], %s", VariableName, mmx_Name(Dest)); + + switch (Dest) { + case x86_MM0: x86Command = 0x05; break; + case x86_MM1: x86Command = 0x0D; break; + case x86_MM2: x86Command = 0x15; break; + case x86_MM3: x86Command = 0x1D; break; + case x86_MM4: x86Command = 0x25; break; + case x86_MM5: x86Command = 0x2D; break; + case x86_MM6: x86Command = 0x35; break; + case x86_MM7: x86Command = 0x3D; break; + } + + PUTDST16(RecompPos,0x7f0f); + PUTDST8(RecompPos, x86Command); + PUTDST32(RecompPos,Variable); +} + +void MmxPorRegToReg(int Dest, int Source) { + BYTE x86Command; + + CPU_Message(" por %s, %s", mmx_Name(Dest), mmx_Name(Source)); + + switch (Dest) { + case x86_MM0: x86Command = 0 << 3; break; + case x86_MM1: x86Command = 1 << 3; break; + case x86_MM2: x86Command = 2 << 3; break; + case x86_MM3: x86Command = 3 << 3; break; + case x86_MM4: x86Command = 4 << 3; break; + case x86_MM5: x86Command = 5 << 3; break; + case x86_MM6: x86Command = 6 << 3; break; + case x86_MM7: x86Command = 7 << 3; break; + } + switch (Source) { + case x86_MM0: x86Command |= 0; break; + case x86_MM1: x86Command |= 1; break; + case x86_MM2: x86Command |= 2; break; + case x86_MM3: x86Command |= 3; break; + case x86_MM4: x86Command |= 4; break; + case x86_MM5: x86Command |= 5; break; + case x86_MM6: x86Command |= 6; break; + case x86_MM7: x86Command |= 7; break; + } + PUTDST16(RecompPos,0xeb0f); + PUTDST8(RecompPos, 0xC0 | x86Command); +} + +void MmxPorVariableToReg(void * Variable, char * VariableName, int Dest) { + BYTE x86Command; + + CPU_Message(" por %s, qword ptr [%s]",mmx_Name(Dest), VariableName); + + switch (Dest) { + case x86_MM0: x86Command = 0x05; break; + case x86_MM1: x86Command = 0x0D; break; + case x86_MM2: x86Command = 0x15; break; + case x86_MM3: x86Command = 0x1D; break; + case x86_MM4: x86Command = 0x25; break; + case x86_MM5: x86Command = 0x2D; break; + case x86_MM6: x86Command = 0x35; break; + case x86_MM7: x86Command = 0x3D; break; + } + + PUTDST16(RecompPos,0xeb0f); + PUTDST8(RecompPos, x86Command); + PUTDST32(RecompPos,Variable); +} + +void MmxPandRegToReg(int Dest, int Source) { + BYTE x86Command; + + CPU_Message(" pand %s, %s", mmx_Name(Dest), mmx_Name(Source)); + + switch (Dest) { + case x86_MM0: x86Command = 0 << 3; break; + case x86_MM1: x86Command = 1 << 3; break; + case x86_MM2: x86Command = 2 << 3; break; + case x86_MM3: x86Command = 3 << 3; break; + case x86_MM4: x86Command = 4 << 3; break; + case x86_MM5: x86Command = 5 << 3; break; + case x86_MM6: x86Command = 6 << 3; break; + case x86_MM7: x86Command = 7 << 3; break; + } + switch (Source) { + case x86_MM0: x86Command |= 0; break; + case x86_MM1: x86Command |= 1; break; + case x86_MM2: x86Command |= 2; break; + case x86_MM3: x86Command |= 3; break; + case x86_MM4: x86Command |= 4; break; + case x86_MM5: x86Command |= 5; break; + case x86_MM6: x86Command |= 6; break; + case x86_MM7: x86Command |= 7; break; + } + PUTDST16(RecompPos,0xdb0f); + PUTDST8(RecompPos, 0xC0 | x86Command); +} + +void MmxPandVariableToReg(void * Variable, char * VariableName, int Dest) { + BYTE x86Command; + + CPU_Message(" pand %s, qword ptr [%s]",mmx_Name(Dest), VariableName); + + switch (Dest) { + case x86_MM0: x86Command = 0x05; break; + case x86_MM1: x86Command = 0x0D; break; + case x86_MM2: x86Command = 0x15; break; + case x86_MM3: x86Command = 0x1D; break; + case x86_MM4: x86Command = 0x25; break; + case x86_MM5: x86Command = 0x2D; break; + case x86_MM6: x86Command = 0x35; break; + case x86_MM7: x86Command = 0x3D; break; + } + + PUTDST16(RecompPos,0xdb0f); + PUTDST8(RecompPos, x86Command); + PUTDST32(RecompPos,Variable); +} + +void MmxPandnRegToReg(int Dest, int Source) { + BYTE x86Command; + + CPU_Message(" pandn %s, %s", mmx_Name(Dest), mmx_Name(Source)); + + switch (Dest) { + case x86_MM0: x86Command = 0 << 3; break; + case x86_MM1: x86Command = 1 << 3; break; + case x86_MM2: x86Command = 2 << 3; break; + case x86_MM3: x86Command = 3 << 3; break; + case x86_MM4: x86Command = 4 << 3; break; + case x86_MM5: x86Command = 5 << 3; break; + case x86_MM6: x86Command = 6 << 3; break; + case x86_MM7: x86Command = 7 << 3; break; + } + switch (Source) { + case x86_MM0: x86Command |= 0; break; + case x86_MM1: x86Command |= 1; break; + case x86_MM2: x86Command |= 2; break; + case x86_MM3: x86Command |= 3; break; + case x86_MM4: x86Command |= 4; break; + case x86_MM5: x86Command |= 5; break; + case x86_MM6: x86Command |= 6; break; + case x86_MM7: x86Command |= 7; break; + } + PUTDST16(RecompPos,0xdf0f); + PUTDST8(RecompPos, 0xC0 | x86Command); +} + +void MmxXorRegToReg(int Dest, int Source) { + BYTE x86Command; + + CPU_Message(" pxor %s, %s", mmx_Name(Dest), mmx_Name(Source)); + + switch (Dest) { + case x86_MM0: x86Command = 0x00; break; + case x86_MM1: x86Command = 0x08; break; + case x86_MM2: x86Command = 0x10; break; + case x86_MM3: x86Command = 0x18; break; + case x86_MM4: x86Command = 0x20; break; + case x86_MM5: x86Command = 0x28; break; + case x86_MM6: x86Command = 0x30; break; + case x86_MM7: x86Command = 0x38; break; + } + switch (Source) { + case x86_MM0: x86Command += 0x00; break; + case x86_MM1: x86Command += 0x01; break; + case x86_MM2: x86Command += 0x02; break; + case x86_MM3: x86Command += 0x03; break; + case x86_MM4: x86Command += 0x04; break; + case x86_MM5: x86Command += 0x05; break; + case x86_MM6: x86Command += 0x06; break; + case x86_MM7: x86Command += 0x07; break; + } + PUTDST16(RecompPos,0xef0f); + PUTDST8(RecompPos, 0xC0 | x86Command); +} + +void MmxShuffleMemoryToReg(int Dest, void * Variable, char * VariableName, BYTE Immed) { + BYTE x86Command; + + CPU_Message(" pshufw %s, [%s], %02X", mmx_Name(Dest), VariableName, Immed); + + switch (Dest) { + case x86_MM0: x86Command = 0x05; break; + case x86_MM1: x86Command = 0x0D; break; + case x86_MM2: x86Command = 0x15; break; + case x86_MM3: x86Command = 0x1D; break; + case x86_MM4: x86Command = 0x25; break; + case x86_MM5: x86Command = 0x2D; break; + case x86_MM6: x86Command = 0x35; break; + case x86_MM7: x86Command = 0x3D; break; + } + + PUTDST16(RecompPos,0x700f); + PUTDST8(RecompPos, x86Command); + PUTDST32(RecompPos,Variable); + PUTDST8(RecompPos, Immed); +} + +void MmxPmullwRegToReg(int Dest, int Source) { + BYTE x86Command; + + CPU_Message(" pmullw %s, %s", mmx_Name(Dest), mmx_Name(Source)); + + switch (Dest) { + case x86_MM0: x86Command = 0 << 3; break; + case x86_MM1: x86Command = 1 << 3; break; + case x86_MM2: x86Command = 2 << 3; break; + case x86_MM3: x86Command = 3 << 3; break; + case x86_MM4: x86Command = 4 << 3; break; + case x86_MM5: x86Command = 5 << 3; break; + case x86_MM6: x86Command = 6 << 3; break; + case x86_MM7: x86Command = 7 << 3; break; + } + switch (Source) { + case x86_MM0: x86Command |= 0; break; + case x86_MM1: x86Command |= 1; break; + case x86_MM2: x86Command |= 2; break; + case x86_MM3: x86Command |= 3; break; + case x86_MM4: x86Command |= 4; break; + case x86_MM5: x86Command |= 5; break; + case x86_MM6: x86Command |= 6; break; + case x86_MM7: x86Command |= 7; break; + } + PUTDST16(RecompPos,0xd50f); + PUTDST8(RecompPos, 0xC0 | x86Command); +} + +void MmxPmullwVariableToReg(int Dest, void * Variable, char * VariableName) { + BYTE x86Command; + + CPU_Message(" pmullw %s, [%s]", mmx_Name(Dest), VariableName); + + switch (Dest) { + case x86_MM0: x86Command = 0x05; break; + case x86_MM1: x86Command = 0x0D; break; + case x86_MM2: x86Command = 0x15; break; + case x86_MM3: x86Command = 0x1D; break; + case x86_MM4: x86Command = 0x25; break; + case x86_MM5: x86Command = 0x2D; break; + case x86_MM6: x86Command = 0x35; break; + case x86_MM7: x86Command = 0x3D; break; + } + PUTDST16(RecompPos,0xd50f); + PUTDST8(RecompPos, x86Command); + PUTDST32(RecompPos, Variable); +} + +void MmxPmulhuwRegToReg(int Dest, int Source) { + BYTE x86Command; + + CPU_Message(" pmulhuw %s, %s", mmx_Name(Dest), mmx_Name(Source)); + + switch (Dest) { + case x86_MM0: x86Command = 0 << 3; break; + case x86_MM1: x86Command = 1 << 3; break; + case x86_MM2: x86Command = 2 << 3; break; + case x86_MM3: x86Command = 3 << 3; break; + case x86_MM4: x86Command = 4 << 3; break; + case x86_MM5: x86Command = 5 << 3; break; + case x86_MM6: x86Command = 6 << 3; break; + case x86_MM7: x86Command = 7 << 3; break; + } + switch (Source) { + case x86_MM0: x86Command |= 0; break; + case x86_MM1: x86Command |= 1; break; + case x86_MM2: x86Command |= 2; break; + case x86_MM3: x86Command |= 3; break; + case x86_MM4: x86Command |= 4; break; + case x86_MM5: x86Command |= 5; break; + case x86_MM6: x86Command |= 6; break; + case x86_MM7: x86Command |= 7; break; + } + PUTDST16(RecompPos,0xe40f); + PUTDST8(RecompPos, 0xC0 | x86Command); +} + +void MmxPmulhwRegToReg(int Dest, int Source) { + BYTE x86Command; + + CPU_Message(" pmulhw %s, %s", mmx_Name(Dest), mmx_Name(Source)); + + switch (Dest) { + case x86_MM0: x86Command = 0 << 3; break; + case x86_MM1: x86Command = 1 << 3; break; + case x86_MM2: x86Command = 2 << 3; break; + case x86_MM3: x86Command = 3 << 3; break; + case x86_MM4: x86Command = 4 << 3; break; + case x86_MM5: x86Command = 5 << 3; break; + case x86_MM6: x86Command = 6 << 3; break; + case x86_MM7: x86Command = 7 << 3; break; + } + switch (Source) { + case x86_MM0: x86Command |= 0; break; + case x86_MM1: x86Command |= 1; break; + case x86_MM2: x86Command |= 2; break; + case x86_MM3: x86Command |= 3; break; + case x86_MM4: x86Command |= 4; break; + case x86_MM5: x86Command |= 5; break; + case x86_MM6: x86Command |= 6; break; + case x86_MM7: x86Command |= 7; break; + } + PUTDST16(RecompPos,0xe50f); + PUTDST8(RecompPos, 0xC0 | x86Command); +} + +void MmxPmulhwRegToVariable(int Dest, void * Variable, char * VariableName) { + BYTE x86Command; + + CPU_Message(" pmulhw %s, [%s]", mmx_Name(Dest), VariableName); + + switch (Dest) { + case x86_MM0: x86Command = 0x05; break; + case x86_MM1: x86Command = 0x0D; break; + case x86_MM2: x86Command = 0x15; break; + case x86_MM3: x86Command = 0x1D; break; + case x86_MM4: x86Command = 0x25; break; + case x86_MM5: x86Command = 0x2D; break; + case x86_MM6: x86Command = 0x35; break; + case x86_MM7: x86Command = 0x3D; break; + } + PUTDST16(RecompPos,0xe50f); + PUTDST8(RecompPos, x86Command); + PUTDST32(RecompPos, Variable); +} + + +void MmxPsrlwImmed(int Dest, BYTE Immed) { + BYTE x86Command; + + CPU_Message(" psrlw %s, %i", mmx_Name(Dest), Immed); + + switch (Dest) { + case x86_MM0: x86Command = 0xD0; break; + case x86_MM1: x86Command = 0xD1; break; + case x86_MM2: x86Command = 0xD2; break; + case x86_MM3: x86Command = 0xD3; break; + case x86_MM4: x86Command = 0xD4; break; + case x86_MM5: x86Command = 0xD5; break; + case x86_MM6: x86Command = 0xD6; break; + case x86_MM7: x86Command = 0xD7; break; + } + + PUTDST16(RecompPos,0x710f); + PUTDST8(RecompPos, x86Command); + PUTDST8(RecompPos, Immed); +} + +void MmxPsrawImmed(int Dest, BYTE Immed) { + BYTE x86Command; + + CPU_Message(" psraw %s, %i", mmx_Name(Dest), Immed); + + switch (Dest) { + case x86_MM0: x86Command = 0xE0; break; + case x86_MM1: x86Command = 0xE1; break; + case x86_MM2: x86Command = 0xE2; break; + case x86_MM3: x86Command = 0xE3; break; + case x86_MM4: x86Command = 0xE4; break; + case x86_MM5: x86Command = 0xE5; break; + case x86_MM6: x86Command = 0xE6; break; + case x86_MM7: x86Command = 0xE7; break; + } + + PUTDST16(RecompPos,0x710f); + PUTDST8(RecompPos, x86Command); + PUTDST8(RecompPos, Immed); +} + +void MmxPsllwImmed(int Dest, BYTE Immed) { + BYTE x86Command; + + CPU_Message(" psllw %s, %i", mmx_Name(Dest), Immed); + + switch (Dest) { + case x86_MM0: x86Command = 0xF0; break; + case x86_MM1: x86Command = 0xF1; break; + case x86_MM2: x86Command = 0xF2; break; + case x86_MM3: x86Command = 0xF3; break; + case x86_MM4: x86Command = 0xF4; break; + case x86_MM5: x86Command = 0xF5; break; + case x86_MM6: x86Command = 0xF6; break; + case x86_MM7: x86Command = 0xF7; break; + } + + PUTDST16(RecompPos,0x710f); + PUTDST8(RecompPos, x86Command); + PUTDST8(RecompPos, Immed); +} + +void MmxPaddswRegToReg(int Dest, int Source) { + BYTE x86Command; + + CPU_Message(" paddsw %s, %s", mmx_Name(Dest), mmx_Name(Source)); + + switch (Dest) { + case x86_MM0: x86Command = 0 << 3; break; + case x86_MM1: x86Command = 1 << 3; break; + case x86_MM2: x86Command = 2 << 3; break; + case x86_MM3: x86Command = 3 << 3; break; + case x86_MM4: x86Command = 4 << 3; break; + case x86_MM5: x86Command = 5 << 3; break; + case x86_MM6: x86Command = 6 << 3; break; + case x86_MM7: x86Command = 7 << 3; break; + } + switch (Source) { + case x86_MM0: x86Command |= 0; break; + case x86_MM1: x86Command |= 1; break; + case x86_MM2: x86Command |= 2; break; + case x86_MM3: x86Command |= 3; break; + case x86_MM4: x86Command |= 4; break; + case x86_MM5: x86Command |= 5; break; + case x86_MM6: x86Command |= 6; break; + case x86_MM7: x86Command |= 7; break; + } + PUTDST16(RecompPos,0xed0f); + PUTDST8(RecompPos, 0xC0 | x86Command); +} + +void MmxPsubswRegToReg(int Dest, int Source) { + BYTE x86Command; + + CPU_Message(" psubsw %s, %s", mmx_Name(Dest), mmx_Name(Source)); + + switch (Dest) { + case x86_MM0: x86Command = 0 << 3; break; + case x86_MM1: x86Command = 1 << 3; break; + case x86_MM2: x86Command = 2 << 3; break; + case x86_MM3: x86Command = 3 << 3; break; + case x86_MM4: x86Command = 4 << 3; break; + case x86_MM5: x86Command = 5 << 3; break; + case x86_MM6: x86Command = 6 << 3; break; + case x86_MM7: x86Command = 7 << 3; break; + } + switch (Source) { + case x86_MM0: x86Command |= 0; break; + case x86_MM1: x86Command |= 1; break; + case x86_MM2: x86Command |= 2; break; + case x86_MM3: x86Command |= 3; break; + case x86_MM4: x86Command |= 4; break; + case x86_MM5: x86Command |= 5; break; + case x86_MM6: x86Command |= 6; break; + case x86_MM7: x86Command |= 7; break; + } + PUTDST16(RecompPos,0xe90f); + PUTDST8(RecompPos, 0xC0 | x86Command); +} + +void MmxPaddswVariableToReg(int Dest, void * Variable, char * VariableName) { + BYTE x86Command; + + CPU_Message(" paddsw %s, [%s]", mmx_Name(Dest), VariableName); + + switch (Dest) { + case x86_MM0: x86Command = 0x05; break; + case x86_MM1: x86Command = 0x0D; break; + case x86_MM2: x86Command = 0x15; break; + case x86_MM3: x86Command = 0x1D; break; + case x86_MM4: x86Command = 0x25; break; + case x86_MM5: x86Command = 0x2D; break; + case x86_MM6: x86Command = 0x35; break; + case x86_MM7: x86Command = 0x3D; break; + } + + PUTDST16(RecompPos,0xed0f); + PUTDST8(RecompPos, x86Command); + PUTDST32(RecompPos, Variable); +} + +void MmxPsubswVariableToReg(int Dest, void * Variable, char * VariableName) { + BYTE x86Command; + + CPU_Message(" psubsw %s, [%s]", mmx_Name(Dest), VariableName); + + switch (Dest) { + case x86_MM0: x86Command = 0x05; break; + case x86_MM1: x86Command = 0x0D; break; + case x86_MM2: x86Command = 0x15; break; + case x86_MM3: x86Command = 0x1D; break; + case x86_MM4: x86Command = 0x25; break; + case x86_MM5: x86Command = 0x2D; break; + case x86_MM6: x86Command = 0x35; break; + case x86_MM7: x86Command = 0x3D; break; + } + + PUTDST16(RecompPos,0xe90f); + PUTDST8(RecompPos, x86Command); + PUTDST32(RecompPos, Variable); +} + +void MmxPaddwRegToReg(int Dest, int Source) { + BYTE x86Command; + + CPU_Message(" paddw %s, %s", mmx_Name(Dest), mmx_Name(Source)); + + switch (Dest) { + case x86_MM0: x86Command = 0 << 3; break; + case x86_MM1: x86Command = 1 << 3; break; + case x86_MM2: x86Command = 2 << 3; break; + case x86_MM3: x86Command = 3 << 3; break; + case x86_MM4: x86Command = 4 << 3; break; + case x86_MM5: x86Command = 5 << 3; break; + case x86_MM6: x86Command = 6 << 3; break; + case x86_MM7: x86Command = 7 << 3; break; + } + switch (Source) { + case x86_MM0: x86Command |= 0; break; + case x86_MM1: x86Command |= 1; break; + case x86_MM2: x86Command |= 2; break; + case x86_MM3: x86Command |= 3; break; + case x86_MM4: x86Command |= 4; break; + case x86_MM5: x86Command |= 5; break; + case x86_MM6: x86Command |= 6; break; + case x86_MM7: x86Command |= 7; break; + } + PUTDST16(RecompPos,0xfd0f); + PUTDST8(RecompPos, 0xC0 | x86Command); +} + +void MmxPackSignedDwords(int Dest, int Source) { + BYTE x86Command; + + CPU_Message(" packssdw %s, %s", mmx_Name(Dest), mmx_Name(Source)); + + switch (Dest) { + case x86_MM0: x86Command = 0 << 3; break; + case x86_MM1: x86Command = 1 << 3; break; + case x86_MM2: x86Command = 2 << 3; break; + case x86_MM3: x86Command = 3 << 3; break; + case x86_MM4: x86Command = 4 << 3; break; + case x86_MM5: x86Command = 5 << 3; break; + case x86_MM6: x86Command = 6 << 3; break; + case x86_MM7: x86Command = 7 << 3; break; + } + switch (Source) { + case x86_MM0: x86Command |= 0; break; + case x86_MM1: x86Command |= 1; break; + case x86_MM2: x86Command |= 2; break; + case x86_MM3: x86Command |= 3; break; + case x86_MM4: x86Command |= 4; break; + case x86_MM5: x86Command |= 5; break; + case x86_MM6: x86Command |= 6; break; + case x86_MM7: x86Command |= 7; break; + } + PUTDST16(RecompPos,0x6b0f); + PUTDST8(RecompPos, 0xC0 | x86Command); +} + +void MmxUnpackLowWord(int Dest, int Source) { + BYTE x86Command; + + CPU_Message(" punpcklwd %s, %s", mmx_Name(Dest), mmx_Name(Source)); + + switch (Dest) { + case x86_MM0: x86Command = 0 << 3; break; + case x86_MM1: x86Command = 1 << 3; break; + case x86_MM2: x86Command = 2 << 3; break; + case x86_MM3: x86Command = 3 << 3; break; + case x86_MM4: x86Command = 4 << 3; break; + case x86_MM5: x86Command = 5 << 3; break; + case x86_MM6: x86Command = 6 << 3; break; + case x86_MM7: x86Command = 7 << 3; break; + } + switch (Source) { + case x86_MM0: x86Command |= 0; break; + case x86_MM1: x86Command |= 1; break; + case x86_MM2: x86Command |= 2; break; + case x86_MM3: x86Command |= 3; break; + case x86_MM4: x86Command |= 4; break; + case x86_MM5: x86Command |= 5; break; + case x86_MM6: x86Command |= 6; break; + case x86_MM7: x86Command |= 7; break; + } + PUTDST16(RecompPos,0x610f); + PUTDST8(RecompPos, 0xC0 | x86Command); +} + +void MmxUnpackHighWord(int Dest, int Source) { + BYTE x86Command; + + CPU_Message(" punpckhwd %s, %s", mmx_Name(Dest), mmx_Name(Source)); + + switch (Dest) { + case x86_MM0: x86Command = 0 << 3; break; + case x86_MM1: x86Command = 1 << 3; break; + case x86_MM2: x86Command = 2 << 3; break; + case x86_MM3: x86Command = 3 << 3; break; + case x86_MM4: x86Command = 4 << 3; break; + case x86_MM5: x86Command = 5 << 3; break; + case x86_MM6: x86Command = 6 << 3; break; + case x86_MM7: x86Command = 7 << 3; break; + } + switch (Source) { + case x86_MM0: x86Command |= 0; break; + case x86_MM1: x86Command |= 1; break; + case x86_MM2: x86Command |= 2; break; + case x86_MM3: x86Command |= 3; break; + case x86_MM4: x86Command |= 4; break; + case x86_MM5: x86Command |= 5; break; + case x86_MM6: x86Command |= 6; break; + case x86_MM7: x86Command |= 7; break; + } + PUTDST16(RecompPos,0x690f); + PUTDST8(RecompPos, 0xC0 | x86Command); +} + +void MmxCompareGreaterWordRegToReg(int Dest, int Source) { + BYTE x86Command; + + CPU_Message(" pcmpgtw %s, %s", mmx_Name(Dest), mmx_Name(Source)); + + switch (Dest) { + case x86_MM0: x86Command = 0 << 3; break; + case x86_MM1: x86Command = 1 << 3; break; + case x86_MM2: x86Command = 2 << 3; break; + case x86_MM3: x86Command = 3 << 3; break; + case x86_MM4: x86Command = 4 << 3; break; + case x86_MM5: x86Command = 5 << 3; break; + case x86_MM6: x86Command = 6 << 3; break; + case x86_MM7: x86Command = 7 << 3; break; + } + switch (Source) { + case x86_MM0: x86Command |= 0; break; + case x86_MM1: x86Command |= 1; break; + case x86_MM2: x86Command |= 2; break; + case x86_MM3: x86Command |= 3; break; + case x86_MM4: x86Command |= 4; break; + case x86_MM5: x86Command |= 5; break; + case x86_MM6: x86Command |= 6; break; + case x86_MM7: x86Command |= 7; break; + } + PUTDST16(RecompPos,0x650f); + PUTDST8(RecompPos, 0xC0 | x86Command); +} diff --git a/Source/RSP/OpCode.h b/Source/RSP/OpCode.h new file mode 100644 index 000000000..8f26092af --- /dev/null +++ b/Source/RSP/OpCode.h @@ -0,0 +1,204 @@ +/* + * RSP Compiler plug in for Project 64 (A Nintendo 64 emulator). + * + * (c) Copyright 2001 jabo (jabo@emulation64.com) and + * zilmar (zilmar@emulation64.com) + * + * pj64 homepage: www.pj64.net + * + * Permission to use, copy, modify and distribute Project64 in both binary and + * source form, for non-commercial purposes, is hereby granted without fee, + * providing that this license information and copyright notice appear with + * all copies and any derived work. + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event shall the authors be held liable for any damages + * arising from the use of this software. + * + * Project64 is freeware for PERSONAL USE only. Commercial users should + * seek permission of the copyright holders first. Commercial use includes + * charging money for Project64 or software derived from Project64. + * + * The copyright holders request that bug fixes and improvements to the code + * should be forwarded to them so if they want them. + * + */ + +#ifndef __OpCode +#define __OpCode + +#include "Types.h" + +typedef struct tagOPCODE { + union { + + unsigned long Hex; + unsigned char Ascii[4]; + + struct { + unsigned offset : 16; + unsigned rt : 5; + unsigned rs : 5; + unsigned op : 6; + }; + + struct { + unsigned immediate : 16; + unsigned : 5; + unsigned base : 5; + unsigned : 6; + }; + + struct { + unsigned target : 26; + unsigned : 6; + }; + + struct { + unsigned funct : 6; + unsigned sa : 5; + unsigned rd : 5; + unsigned : 5; + unsigned : 5; + unsigned : 6; + }; + + struct { + signed voffset : 7; + unsigned del : 4; + unsigned : 5; + unsigned dest : 5; + unsigned : 5; + unsigned : 6; + }; + + }; +} OPCODE; + +//RSP OpCodes +#define RSP_SPECIAL 0 +#define RSP_REGIMM 1 +#define RSP_J 2 +#define RSP_JAL 3 +#define RSP_BEQ 4 +#define RSP_BNE 5 +#define RSP_BLEZ 6 +#define RSP_BGTZ 7 +#define RSP_ADDI 8 +#define RSP_ADDIU 9 +#define RSP_SLTI 10 +#define RSP_SLTIU 11 +#define RSP_ANDI 12 +#define RSP_ORI 13 +#define RSP_XORI 14 +#define RSP_LUI 15 +#define RSP_CP0 16 +#define RSP_CP2 18 +#define RSP_LB 32 +#define RSP_LH 33 +#define RSP_LW 35 +#define RSP_LBU 36 +#define RSP_LHU 37 +#define RSP_SB 40 +#define RSP_SH 41 +#define RSP_SW 43 +#define RSP_LC2 50 +#define RSP_SC2 58 + +/* RSP Special opcodes */ +#define RSP_SPECIAL_SLL 0 +#define RSP_SPECIAL_SRL 2 +#define RSP_SPECIAL_SRA 3 +#define RSP_SPECIAL_SLLV 4 +#define RSP_SPECIAL_SRLV 6 +#define RSP_SPECIAL_SRAV 7 +#define RSP_SPECIAL_JR 8 +#define RSP_SPECIAL_JALR 9 +#define RSP_SPECIAL_BREAK 13 +#define RSP_SPECIAL_ADD 32 +#define RSP_SPECIAL_ADDU 33 +#define RSP_SPECIAL_SUB 34 +#define RSP_SPECIAL_SUBU 35 +#define RSP_SPECIAL_AND 36 +#define RSP_SPECIAL_OR 37 +#define RSP_SPECIAL_XOR 38 +#define RSP_SPECIAL_NOR 39 +#define RSP_SPECIAL_SLT 42 +#define RSP_SPECIAL_SLTU 43 + +/* RSP RegImm opcodes */ +#define RSP_REGIMM_BLTZ 0 +#define RSP_REGIMM_BGEZ 1 +#define RSP_REGIMM_BLTZAL 16 +#define RSP_REGIMM_BGEZAL 17 + +/* RSP COP0 opcodes */ +#define RSP_COP0_MF 0 +#define RSP_COP0_MT 4 + +/* RSP COP2 opcodes */ +#define RSP_COP2_MF 0 +#define RSP_COP2_CF 2 +#define RSP_COP2_MT 4 +#define RSP_COP2_CT 6 + +/* RSP Vector opcodes */ +#define RSP_VECTOR_VMULF 0 +#define RSP_VECTOR_VMULU 1 +#define RSP_VECTOR_VRNDP 2 +#define RSP_VECTOR_VMULQ 3 +#define RSP_VECTOR_VMUDL 4 +#define RSP_VECTOR_VMUDM 5 +#define RSP_VECTOR_VMUDN 6 +#define RSP_VECTOR_VMUDH 7 +#define RSP_VECTOR_VMACF 8 +#define RSP_VECTOR_VMACU 9 +#define RSP_VECTOR_VRNDN 10 +#define RSP_VECTOR_VMACQ 11 +#define RSP_VECTOR_VMADL 12 +#define RSP_VECTOR_VMADM 13 +#define RSP_VECTOR_VMADN 14 +#define RSP_VECTOR_VMADH 15 +#define RSP_VECTOR_VADD 16 +#define RSP_VECTOR_VSUB 17 +#define RSP_VECTOR_VABS 19 +#define RSP_VECTOR_VADDC 20 +#define RSP_VECTOR_VSUBC 21 +#define RSP_VECTOR_VSAW 29 +#define RSP_VECTOR_VLT 32 +#define RSP_VECTOR_VEQ 33 +#define RSP_VECTOR_VNE 34 +#define RSP_VECTOR_VGE 35 +#define RSP_VECTOR_VCL 36 +#define RSP_VECTOR_VCH 37 +#define RSP_VECTOR_VCR 38 +#define RSP_VECTOR_VMRG 39 +#define RSP_VECTOR_VAND 40 +#define RSP_VECTOR_VNAND 41 +#define RSP_VECTOR_VOR 42 +#define RSP_VECTOR_VNOR 43 +#define RSP_VECTOR_VXOR 44 +#define RSP_VECTOR_VNXOR 45 +#define RSP_VECTOR_VRCP 48 +#define RSP_VECTOR_VRCPL 49 +#define RSP_VECTOR_VRCPH 50 +#define RSP_VECTOR_VMOV 51 +#define RSP_VECTOR_VRSQ 52 +#define RSP_VECTOR_VRSQL 53 +#define RSP_VECTOR_VRSQH 54 +#define RSP_VECTOR_VNOOP 55 + +/* RSP LSC2 opcodes */ +#define RSP_LSC2_BV 0 +#define RSP_LSC2_SV 1 +#define RSP_LSC2_LV 2 +#define RSP_LSC2_DV 3 +#define RSP_LSC2_QV 4 +#define RSP_LSC2_RV 5 +#define RSP_LSC2_PV 6 +#define RSP_LSC2_UV 7 +#define RSP_LSC2_HV 8 +#define RSP_LSC2_FV 9 +#define RSP_LSC2_WV 10 +#define RSP_LSC2_TV 11 +#endif \ No newline at end of file diff --git a/Source/RSP/Profiling.cpp b/Source/RSP/Profiling.cpp new file mode 100644 index 000000000..d5e5d7b6a --- /dev/null +++ b/Source/RSP/Profiling.cpp @@ -0,0 +1,307 @@ +/* + * RSP Compiler plug in for Project 64 (A Nintendo 64 emulator). + * + * (c) Copyright 2001 jabo (jabo@emulation64.com) and + * zilmar (zilmar@emulation64.com) + * + * pj64 homepage: www.pj64.net + * + * Permission to use, copy, modify and distribute Project64 in both binary and + * source form, for non-commercial purposes, is hereby granted without fee, + * providing that this license information and copyright notice appear with + * all copies and any derived work. + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event shall the authors be held liable for any damages + * arising from the use of this software. + * + * Project64 is freeware for PERSONAL USE only. Commercial users should + * seek permission of the copyright holders first. Commercial use includes + * charging money for Project64 or software derived from Project64. + * + * The copyright holders request that bug fixes and improvements to the code + * should be forwarded to them so if they want them. + * + */ + +#include +extern "C" { +#include "profiling.h" +} +#pragma warning(disable:4786) +#include +#include +#include +#include + +class CProfiling { +typedef std::map PROFILE_ENRTIES; +typedef PROFILE_ENRTIES::iterator PROFILE_ENRTY; +typedef PROFILE_ENRTIES::value_type PROFILE_VALUE; +typedef struct { SPECIAL_TIMERS Timer; char * Name; } TIMER_NAME; + + DWORD m_CurrentTimerAddr, CurrentDisplayCount; + DWORD m_StartTimeHi, m_StartTimeLo; //The Current Timer start time + PROFILE_ENRTIES m_Entries; + +public: + CProfiling () + { + m_CurrentTimerAddr = Timer_None; + } + + //recording timing against current timer, returns the address of the timer stoped + DWORD StartTimer ( DWORD Address ) + { + DWORD OldTimerAddr = StopTimer(); + m_CurrentTimerAddr = Address; + + DWORD HiValue, LoValue; + _asm { + pushad + rdtsc + mov HiValue, edx + mov LoValue, eax + popad + } + m_StartTimeHi = HiValue; + m_StartTimeLo = LoValue; + return OldTimerAddr; + } + DWORD StopTimer ( void ) + { + DWORD HiValue, LoValue; + + if (m_CurrentTimerAddr == Timer_None) { return m_CurrentTimerAddr; } + + _asm { + pushad + rdtsc + mov HiValue, edx + mov LoValue, eax + popad + } + + __int64 StopTime = ((unsigned __int64)HiValue << 32) + (unsigned __int64)LoValue; + __int64 StartTime = ((unsigned __int64)m_StartTimeHi << 32) + (unsigned __int64)m_StartTimeLo; + __int64 TimeTaken = StopTime - StartTime; + + PROFILE_ENRTY Entry = m_Entries.find(m_CurrentTimerAddr); + if (Entry != m_Entries.end()) { + Entry->second += TimeTaken; + } else { + m_Entries.insert(PROFILE_ENRTIES::value_type(m_CurrentTimerAddr,TimeTaken)); + } + + DWORD OldTimerAddr = m_CurrentTimerAddr; + m_CurrentTimerAddr = Timer_None; + return OldTimerAddr; + } + + //Reset all the counters back to 0 + void ResetCounters ( void ) + { + m_Entries.clear(); + } + + //Generate a log file with the current results, this will also reset the counters + void GenerateLog ( void ) + { + stdstr LogFileName; + { + CLog Log; + Log.Open("RSP Profiling.txt"); + LogFileName = Log.FileName(); + + //Get the total time + __int64 TotalTime = 0; + for (PROFILE_ENRTY itemTime = m_Entries.begin(); itemTime != m_Entries.end(); itemTime++ ) { + TotalTime += itemTime->second; + } + + //Create a sortable list of items + std::vector ItemList; + for (PROFILE_ENRTY Entry = m_Entries.begin(); Entry != m_Entries.end(); Entry++ ) { + ItemList.push_back(&(*Entry)); + } + + //sort the list with a basic bubble sort + if (ItemList.size() > 0) + { + for (int OuterPass = 0; OuterPass < (ItemList.size() - 1); OuterPass++ ) { + for (int InnerPass = 0; InnerPass < (ItemList.size() - 1); InnerPass++ ) { + if (ItemList[InnerPass]->second < ItemList[InnerPass + 1]->second) { + PROFILE_VALUE * TempPtr = ItemList[InnerPass]; + ItemList[InnerPass] = ItemList[InnerPass + 1]; + ItemList[InnerPass + 1] = TempPtr; + } + } + } + } + + TIMER_NAME TimerNames[] = { + {Timer_Compiling, "RSP: Compiling"}, + {Timer_RSP_Running, "RSP: Running"}, + {Timer_R4300_Running, "R4300: Running"}, + {Timer_RDP_Running, "RDP: Running"}, + }; + + for (int count =0; count < ItemList.size(); count++ ) { + char Buffer[255]; + float CpuUsage = ((double)ItemList[count]->second / (double)TotalTime) * 100; + if (CpuUsage <= 0.2) { continue; } + sprintf(Buffer,"Func 0x%08X",ItemList[count]->first); + for (int NameID = 0; NameID < (sizeof(TimerNames) / sizeof(TIMER_NAME)); NameID++) { + if (ItemList[count]->first == TimerNames[NameID].Timer) { + strcpy(Buffer,TimerNames[NameID].Name); + break; + } + } + Log.LogF("%s\t%2.2f",Buffer, CpuUsage); + } + } + + ShellExecute(NULL,"open",LogFileName.c_str(),NULL,NULL,SW_SHOW); + ResetCounters(); + + } +}; + + +CProfiling& GetProfiler ( void ) +{ + static CProfiling Profile; + return Profile; +} + +void ResetTimerList (void) { + GetProfiler().ResetCounters(); +} + +DWORD StartTimer (DWORD Address) { + return GetProfiler().StartTimer(Address); +} + +void StopTimer (void) { + GetProfiler().StopTimer(); +} + +void GenerateTimerResults (void) { + GetProfiler().GenerateLog(); +} + + +#ifdef todelete +#include +#include + +typedef struct { + char Label[100]; + _int64 TimeTotal; +} TIME_STAMP_ENTRY; + +DWORD StartTimeHi, StartTimeLo, StopTimeHi, StopTimeLo, TSE_Count, TSE_Max; +TIME_STAMP_ENTRY * TS_Entries = NULL; +char LastLabel[100]; + +void ResetTimerList (void) { + if (TS_Entries) { free(TS_Entries); } + TS_Entries = NULL; + TSE_Count = 0; + TSE_Max = 0; +} + +void StartTimer (char * Label) { + strcpy(LastLabel,Label); + _asm { + pushad + rdtsc + mov StartTimeHi, edx + mov StartTimeLo, eax + popad + } +} + +void StopTimer (void) { + _asm { + pushad + rdtsc + mov StopTimeHi, edx + mov StopTimeLo, eax + popad + } + if (strlen(LastLabel) == 0) { return; } + { + DWORD count; + + for (count = 0; count < TSE_Count; count ++) { + if (strcmp(LastLabel,TS_Entries[count].Label) == 0) { + _int64 Time = ((unsigned _int64)StopTimeHi << 32) + (unsigned _int64)StopTimeLo; + Time -= ((unsigned _int64)StartTimeHi << 32) + (unsigned _int64)StartTimeLo; + TS_Entries[count].TimeTotal += Time; + return; + } + } + } + if (TSE_Count == 0) { + TS_Entries = (TIME_STAMP_ENTRY *)malloc(sizeof(TIME_STAMP_ENTRY) * 100); + if (TS_Entries == NULL) { + MessageBox(NULL,"TIME_STAMP_ENTRY == NULL ??","ERROR",MB_OK|MB_ICONERROR|MB_SETFOREGROUND); + } + TSE_Max = 100; + } else if (TSE_Count == TSE_Max) { + TSE_Max += 100; + TS_Entries = (TIME_STAMP_ENTRY *)realloc(TS_Entries,sizeof(TIME_STAMP_ENTRY) * TSE_Max); + if (TS_Entries == NULL) { + MessageBox(NULL,"TIME_STAMP_ENTRY == NULL ??","ERROR",MB_OK|MB_ICONERROR|MB_SETFOREGROUND); + } + } + strcpy(TS_Entries[TSE_Count].Label,LastLabel); + TS_Entries[TSE_Count].TimeTotal = ((unsigned _int64)StopTimeHi << 32) + (unsigned _int64)StopTimeLo; + TS_Entries[TSE_Count].TimeTotal -= ((unsigned _int64)StartTimeHi << 32) + (unsigned _int64)StartTimeLo; + TSE_Count +=1; +} + +void GenerateTimerResults (void) { + char buffer[_MAX_PATH], drive[_MAX_DRIVE] ,dir[_MAX_DIR]; + char fname[_MAX_FNAME],ext[_MAX_EXT], LogFileName[_MAX_PATH]; + DWORD dwWritten, count, count2; + HANDLE hLogFile = NULL; + _int64 TotalTime; + + StopTimer(); + + GetModuleFileName(NULL,buffer,sizeof(buffer)); + _splitpath( buffer, drive, dir, fname, ext ); + _makepath( LogFileName, drive, dir, "RSP Profiling", "log" ); + + hLogFile = CreateFile(LogFileName,GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE,NULL, + CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL); + SetFilePointer(hLogFile,0,NULL,FILE_BEGIN); + + for (count = 0; count < TSE_Count; count ++) { + for (count2 = 0; count2 < (TSE_Count - 1); count2 ++) { + if (TS_Entries[count2].TimeTotal < TS_Entries[count2 + 1].TimeTotal) { + TIME_STAMP_ENTRY Temp; + memcpy(&Temp,&TS_Entries[count2],sizeof(TIME_STAMP_ENTRY)); + memcpy(&TS_Entries[count2],&TS_Entries[count2 + 1],sizeof(TIME_STAMP_ENTRY)); + memcpy(&TS_Entries[count2 + 1],&Temp,sizeof(TIME_STAMP_ENTRY)); + } + } + } + TotalTime = 0; + for (count = 0; count < TSE_Count; count ++) { + TotalTime += TS_Entries[count].TimeTotal; + } + for (count = 0; count < (TSE_Count < 50?TSE_Count:50); count ++) { + sprintf(buffer,"%s - %0.2f%c\r\n", + TS_Entries[count].Label, + (((double)TS_Entries[count].TimeTotal / (double)TotalTime) * 100),'%' + ); + WriteFile( hLogFile,buffer,strlen(buffer),&dwWritten,NULL ); + } + CloseHandle(hLogFile); + ResetTimerList(); +} + +#endif \ No newline at end of file diff --git a/Source/RSP/Profiling.h b/Source/RSP/Profiling.h new file mode 100644 index 000000000..ab70335fe --- /dev/null +++ b/Source/RSP/Profiling.h @@ -0,0 +1,37 @@ +/* + * RSP Compiler plug in for Project 64 (A Nintendo 64 emulator). + * + * (c) Copyright 2001 jabo (jabo@emulation64.com) and + * zilmar (zilmar@emulation64.com) + * + * pj64 homepage: www.pj64.net + * + * Permission to use, copy, modify and distribute Project64 in both binary and + * source form, for non-commercial purposes, is hereby granted without fee, + * providing that this license information and copyright notice appear with + * all copies and any derived work. + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event shall the authors be held liable for any damages + * arising from the use of this software. + * + * Project64 is freeware for PERSONAL USE only. Commercial users should + * seek permission of the copyright holders first. Commercial use includes + * charging money for Project64 or software derived from Project64. + * + * The copyright holders request that bug fixes and improvements to the code + * should be forwarded to them so if they want them. + * + */ + +enum SPECIAL_TIMERS { + Timer_None = 0, Timer_Compiling = -1, Timer_RSP_Running = -2, + Timer_R4300_Running = -3, Timer_RDP_Running = -5, Timer_RefreshScreen = -6, + Timer_UpdateScreen = -7, Timer_UpdateFPS = -9, Timer_Idel = -10, + Timer_FuncLookup = -11,Timer_Done = -13, +}; + +void ResetTimerList ( void ); +DWORD StartTimer ( DWORD Address ); +void StopTimer ( void ); +void GenerateTimerResults ( void ); \ No newline at end of file diff --git a/Source/RSP/RSP Command.c b/Source/RSP/RSP Command.c new file mode 100644 index 000000000..6c4b8ec2d --- /dev/null +++ b/Source/RSP/RSP Command.c @@ -0,0 +1,1337 @@ +/* + * RSP Compiler plug in for Project 64 (A Nintendo 64 emulator). + * + * (c) Copyright 2001 jabo (jabo@emulation64.com) and + * zilmar (zilmar@emulation64.com) + * + * pj64 homepage: www.pj64.net + * + * Permission to use, copy, modify and distribute Project64 in both binary and + * source form, for non-commercial purposes, is hereby granted without fee, + * providing that this license information and copyright notice appear with + * all copies and any derived work. + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event shall the authors be held liable for any damages + * arising from the use of this software. + * + * Project64 is freeware for PERSONAL USE only. Commercial users should + * seek permission of the copyright holders first. Commercial use includes + * charging money for Project64 or software derived from Project64. + * + * The copyright holders request that bug fixes and improvements to the code + * should be forwarded to them so if they want them. + * + */ + +#include +#include +#include "opcode.h" +#include "RSP.h" +#include "CPU.h" +#include "RSP Registers.h" +#include "RSP Command.h" +#include "memory.h" +#include "breakpoint.h" + +#define RSP_MaxCommandLines 30 + +#define RSP_Status_PC 1 +#define RSP_Status_BP 2 + +#define IDC_LIST 1000 +#define IDC_ADDRESS 1001 +#define IDC_FUNCTION_COMBO 1002 +#define IDC_GO_BUTTON 1003 +#define IDC_BREAK_BUTTON 1004 +#define IDC_STEP_BUTTON 1005 +#define IDC_SKIP_BUTTON 1006 +#define IDC_BP_BUTTON 1007 +#define IDC_R4300I_REGISTERS_BUTTON 1008 +#define IDC_R4300I_DEBUGGER_BUTTON 1009 +#define IDC_RSP_REGISTERS_BUTTON 1010 +#define IDC_MEMORY_BUTTON 1011 +#define IDC_SCRL_BAR 1012 + +void Paint_RSP_Commands (HWND hDlg); +void RSP_Commands_Setup ( HWND hDlg ); +LRESULT CALLBACK RSP_Commands_Proc (HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam); + +typedef struct { + DWORD Location; + DWORD opcode; + char String[150]; + DWORD status; +} RSPCOMMANDLINE; + +RSPCOMMANDLINE RSPCommandLine[30]; +HWND RSPCommandshWnd, hList, hAddress, hFunctionlist, hGoButton, hBreakButton, + hStepButton, hSkipButton, hBPButton, hR4300iRegisters, hR4300iDebugger, hRSPRegisters, + hMemory, hScrlBar; +BOOL InRSPCommandsWindow; +char CommandName[100]; +DWORD Stepping_Commands, WaitingForStep; + + +void Create_RSP_Commands_Window ( int Child ) { + DWORD ThreadID; + + if ( Child ) { + InRSPCommandsWindow = TRUE; + DialogBox( hinstDLL, "RSPCOMMAND", NULL,(DLGPROC)RSP_Commands_Proc ); + + InRSPCommandsWindow = FALSE; + memset(RSPCommandLine,0,sizeof(RSPCommandLine)); + SetRSPCommandToRunning(); + } else { + if (!InRSPCommandsWindow) { + Stepping_Commands = TRUE; + CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)Create_RSP_Commands_Window, + (LPVOID)TRUE,0, &ThreadID); + } else { + SetForegroundWindow(RSPCommandshWnd); + } + } +} + +void Disable_RSP_Commands_Window ( void ) { + SCROLLINFO si; + + if (!InRSPCommandsWindow) { return; } + EnableWindow(hList, FALSE); + EnableWindow(hAddress, FALSE); + EnableWindow(hScrlBar, FALSE); + EnableWindow(hGoButton, FALSE); + EnableWindow(hStepButton, FALSE); + EnableWindow(hSkipButton, FALSE); + EnableWindow(hR4300iRegisters, FALSE); + EnableWindow(hRSPRegisters, FALSE); + EnableWindow(hR4300iDebugger, FALSE); + EnableWindow(hMemory, FALSE); + + si.cbSize = sizeof(si); + si.fMask = SIF_RANGE | SIF_POS | SIF_PAGE; + si.nMin = 0; + si.nMax = 0; + si.nPos = 1; + si.nPage = 1; + SetScrollInfo(hScrlBar,SB_CTL,&si,TRUE); +} + +int DisplayRSPCommand (DWORD location, int InsertPos) { + DWORD OpCode, LinesUsed = 1, status; + BOOL Redraw = FALSE; + + RSP_LW_IMEM(location, &OpCode); + + status = 0; + if (location == *PrgCount) {status = RSP_Status_PC; } + if (CheckForRSPBPoint(location)) { status |= RSP_Status_BP; } + if (RSPCommandLine[InsertPos].opcode != OpCode) { Redraw = TRUE; } + if (RSPCommandLine[InsertPos].Location != location) { Redraw = TRUE; } + if (RSPCommandLine[InsertPos].status != status) { Redraw = TRUE; } + if (Redraw) { + RSPCommandLine[InsertPos].Location = location; + RSPCommandLine[InsertPos].status = status; + RSPCommandLine[InsertPos].opcode = OpCode; + sprintf(RSPCommandLine[InsertPos].String," 0x%03X\t%s",location, + RSPOpcodeName ( OpCode, location )); + if ( SendMessage(hList,LB_GETCOUNT,0,0) <= InsertPos) { + SendMessage(hList,LB_INSERTSTRING,(WPARAM)InsertPos, (LPARAM)location); + } else { + RECT ItemRC; + SendMessage(hList,LB_GETITEMRECT,(WPARAM)InsertPos, (LPARAM)&ItemRC); + RedrawWindow(hList,&ItemRC,NULL, RDW_INVALIDATE ); + } + } + return LinesUsed; +} + +void DumpRSPCode (void) { + char string[100], LogFileName[255], *p ; + DWORD location, OpCode, dwWritten; + HANDLE hLogFile = NULL; + + strcpy(LogFileName,GetCommandLine() + 1); + + if (strchr(LogFileName,'\"')) { + p = strchr(LogFileName,'\"'); + *p = '\0'; + } + + if (strchr(LogFileName,'\\')) { + p = LogFileName; + while (strchr(p,'\\')) { + p = strchr(p,'\\'); + p++; + } + p -= 1; + *p = '\0'; + } + + strcat(LogFileName,"\\RSP code.txt"); + + hLogFile = CreateFile(LogFileName,GENERIC_WRITE, FILE_SHARE_READ,NULL,CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL); + SetFilePointer(hLogFile,0,NULL,FILE_BEGIN); + + for (location = 0; location < 0x1000; location += 4) { + RSP_LW_IMEM(location, &OpCode); + sprintf(string," 0x%03X\t%s\r\n",location, RSPOpcodeName ( OpCode, location )); + WriteFile( hLogFile,string,strlen(string),&dwWritten,NULL ); + } + CloseHandle(hLogFile); +} + +void DumpRSPData (void) { + char string[100], LogFileName[255], *p ; + DWORD location, value, dwWritten; + HANDLE hLogFile = NULL; + + strcpy(LogFileName,GetCommandLine() + 1); + + if (strchr(LogFileName,'\"')) { + p = strchr(LogFileName,'\"'); + *p = '\0'; + } + + if (strchr(LogFileName,'\\')) { + p = LogFileName; + while (strchr(p,'\\')) { + p = strchr(p,'\\'); + p++; + } + p -= 1; + *p = '\0'; + } + + strcat(LogFileName,"\\RSP data.txt"); + + hLogFile = CreateFile(LogFileName,GENERIC_WRITE, FILE_SHARE_READ,NULL,CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL); + SetFilePointer(hLogFile,0,NULL,FILE_BEGIN); + + for (location = 0; location < 0x1000; location += 4) { + RSP_LW_DMEM(location, &value); + sprintf(string," 0x%03X\t0x%08X\r\n", location, value); + WriteFile( hLogFile,string,strlen(string),&dwWritten,NULL ); + } + CloseHandle(hLogFile); +} + +void DrawRSPCommand ( LPARAM lParam ) { + char Command[150], Offset[30], Instruction[30], Arguments[40]; + LPDRAWITEMSTRUCT ditem; + COLORREF oldColor; + int ResetColor; + HBRUSH hBrush; + RECT TextRect; + char *p1, *p2; + + ditem = (LPDRAWITEMSTRUCT)lParam; + strcpy(Command, RSPCommandLine[ditem->itemID].String); + + if (strchr(Command,'\t')) { + p1 = strchr(Command,'\t'); + sprintf(Offset,"%.*s",p1 - Command, Command); + p1++; + if (strchr(p1,'\t')) { + p2 = strchr(p1,'\t'); + sprintf(Instruction,"%.*s",p2 - p1, p1); + sprintf(Arguments,"%s",p2 + 1); + } else { + sprintf(Instruction,"%s",p1); + sprintf(Arguments,"\0"); + } + sprintf(Command,"\0"); + } else { + sprintf(Offset,"\0"); + sprintf(Instruction,"\0"); + sprintf(Arguments,"\0"); + } + + if (*PrgCount == RSPCommandLine[ditem->itemID].Location) { + ResetColor = TRUE; + hBrush = (HBRUSH)(COLOR_HIGHLIGHT + 1); + oldColor = SetTextColor(ditem->hDC,RGB(255,255,255)); + } else { + ResetColor = FALSE; + hBrush = (HBRUSH)GetStockObject(WHITE_BRUSH); + } + + if (CheckForRSPBPoint( RSPCommandLine[ditem->itemID].Location )) { + ResetColor = TRUE; + if (*PrgCount == RSPCommandLine[ditem->itemID].Location) { + SetTextColor(ditem->hDC,RGB(255,0,0)); + } else { + oldColor = SetTextColor(ditem->hDC,RGB(255,0,0)); + } + } + + FillRect( ditem->hDC, &ditem->rcItem,hBrush); + SetBkMode( ditem->hDC, TRANSPARENT ); + + if (strlen (Command) == 0 ) { + SetRect(&TextRect,ditem->rcItem.left,ditem->rcItem.top, ditem->rcItem.left + 83, + ditem->rcItem.bottom); + DrawText(ditem->hDC,Offset,strlen(Offset), &TextRect,DT_SINGLELINE | DT_VCENTER); + + SetRect(&TextRect,ditem->rcItem.left + 83,ditem->rcItem.top, ditem->rcItem.left + 165, + ditem->rcItem.bottom); + DrawText(ditem->hDC,Instruction,strlen(Instruction), &TextRect,DT_SINGLELINE | DT_VCENTER); + + SetRect(&TextRect,ditem->rcItem.left + 165,ditem->rcItem.top, ditem->rcItem.right, + ditem->rcItem.bottom); + DrawText(ditem->hDC,Arguments,strlen(Arguments), &TextRect,DT_SINGLELINE | DT_VCENTER); + } else { + DrawText(ditem->hDC,Command,strlen(Command), &ditem->rcItem,DT_SINGLELINE | DT_VCENTER); + } + + if (ResetColor == TRUE) { + SetTextColor( ditem->hDC, oldColor ); + } + +} + + +void Enable_RSP_Commands_Window ( void ) { + SCROLLINFO si; + + if (!InRSPCommandsWindow) { return; } + EnableWindow(hList, TRUE); + EnableWindow(hAddress, TRUE); + EnableWindow(hScrlBar, TRUE); + EnableWindow(hGoButton, TRUE); + EnableWindow(hStepButton, TRUE); + EnableWindow(hSkipButton, FALSE); + EnableWindow(hR4300iRegisters, TRUE); + EnableWindow(hRSPRegisters, TRUE); + EnableWindow(hR4300iDebugger, TRUE); + EnableWindow(hMemory, TRUE); + SendMessage(hBPButton, BM_SETSTYLE, BS_PUSHBUTTON,TRUE); + SendMessage(hStepButton, BM_SETSTYLE, BS_DEFPUSHBUTTON,TRUE); + SendMessage(RSPCommandshWnd, DM_SETDEFID,IDC_STEP_BUTTON,0); + + if (Stepping_Commands) { + si.cbSize = sizeof(si); + si.fMask = SIF_RANGE | SIF_POS | SIF_PAGE; + si.nMin = 0; + si.nMax = (0x1000 >> 2) -1; + si.nPos = (*PrgCount >> 2); + si.nPage = 30; + SetScrollInfo(hScrlBar,SB_CTL,&si,TRUE); + + SetRSPCommandViewto( *PrgCount ); + SetForegroundWindow(RSPCommandshWnd); + } +} + +void Enter_RSP_Commands_Window ( void ) { + Create_RSP_Commands_Window ( FALSE ); +} + +void Paint_RSP_Commands (HWND hDlg) { + PAINTSTRUCT ps; + RECT rcBox; + HFONT hOldFont; + int OldBkMode; + + BeginPaint( hDlg, &ps ); + + rcBox.left = 5; rcBox.top = 5; + rcBox.right = 343; rcBox.bottom = 463; + DrawEdge( ps.hdc, &rcBox, EDGE_RAISED, BF_RECT ); + + rcBox.left = 8; rcBox.top = 8; + rcBox.right = 340; rcBox.bottom = 460; + DrawEdge( ps.hdc, &rcBox, EDGE_ETCHED, BF_RECT ); + + rcBox.left = 347; rcBox.top = 7; + rcBox.right = 446; rcBox.bottom = 42; + DrawEdge( ps.hdc, &rcBox, EDGE_ETCHED, BF_RECT ); + + rcBox.left = 352; rcBox.top = 2; + rcBox.right = 400; rcBox.bottom = 15; + FillRect( ps.hdc, &rcBox,(HBRUSH)COLOR_WINDOW); + + rcBox.left = 14; rcBox.top = 14; + rcBox.right = 88; rcBox.bottom = 32; + DrawEdge( ps.hdc, &rcBox, EDGE_ETCHED , BF_RECT ); + + rcBox.left = 86; rcBox.top = 14; + rcBox.right = 173; rcBox.bottom = 32; + DrawEdge( ps.hdc, &rcBox, EDGE_ETCHED , BF_RECT ); + + rcBox.left = 171; rcBox.top = 14; + rcBox.right = 320; rcBox.bottom = 32; + DrawEdge( ps.hdc, &rcBox, EDGE_ETCHED , BF_RECT ); + + hOldFont = (HFONT)SelectObject( ps.hdc,GetStockObject(DEFAULT_GUI_FONT ) ); + OldBkMode = SetBkMode( ps.hdc, TRANSPARENT ); + + TextOut( ps.hdc, 23,16,"Offset",6); + TextOut( ps.hdc, 97,16,"Instruction",11); + TextOut( ps.hdc, 180,16,"Arguments",9); + TextOut( ps.hdc, 354,2," Address ",9); + TextOut( ps.hdc, 358,19,"0x",2); + + SelectObject( ps.hdc,hOldFont ); + SetBkMode( ps.hdc, OldBkMode ); + + EndPaint( hDlg, &ps ); +} + +void RefreshRSPCommands ( void ) { + DWORD location, LinesUsed; + char AsciiAddress[20]; + int count; + + if (InRSPCommandsWindow == FALSE) { return; } + + GetWindowText(hAddress,AsciiAddress,sizeof(AsciiAddress)); + location = AsciiToHex(AsciiAddress) & ~3; + + if (location > 0xF88) { location = 0xF88; } + for (count = 0 ; count < RSP_MaxCommandLines; count += LinesUsed ){ + LinesUsed = DisplayRSPCommand ( location, count ); + location += 4; + } +} + +LRESULT CALLBACK RSP_Commands_Proc (HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { + switch (uMsg) { + case WM_INITDIALOG: + RSPCommandshWnd = hDlg; + RSP_Commands_Setup( hDlg ); + break; + case WM_MOVE: + //StoreCurrentWinPos("RSP Commands",hDlg); + break; + case WM_DRAWITEM: + if (wParam == IDC_LIST) { + DrawRSPCommand (lParam); + } + break; + case WM_PAINT: + Paint_RSP_Commands( hDlg ); + RedrawWindow(hScrlBar,NULL,NULL, RDW_INVALIDATE |RDW_ERASE); + return TRUE; + case WM_COMMAND: + switch (LOWORD(wParam)) { + case IDC_LIST: + if (HIWORD(wParam) == LBN_DBLCLK ) { + DWORD Location, Selected; + Selected = SendMessage(hList,LB_GETCURSEL,(WPARAM)0, (LPARAM)0); + Location = RSPCommandLine[Selected].Location; + if (Location != (DWORD)-1) { + if (CheckForRSPBPoint(Location)) { + RemoveRSPBreakPoint(Location); + } else { + AddRSP_BPoint(Location, FALSE); + } + RefreshRSPCommands(); + } + } + break; + case IDC_ADDRESS: + if (HIWORD(wParam) == EN_CHANGE ) { + RefreshRSPCommands(); + } + break; + case IDC_GO_BUTTON: + SetRSPCommandToRunning(); + break; + case IDC_BREAK_BUTTON: + SetRSPCommandToStepping(); + break; + case IDC_STEP_BUTTON: + WaitingForStep = FALSE; + break; + /*case IDC_SKIP_BUTTON: + SkipNextRSPOpCode = TRUE; + WaitingFor_RSPStep = FALSE; + break;*/ + case IDC_BP_BUTTON: + if (DebugInfo.Enter_BPoint_Window != NULL) { + DebugInfo.Enter_BPoint_Window(); + } + break; + case IDC_RSP_REGISTERS_BUTTON: + Enter_RSP_Register_Window(); + break; + case IDC_R4300I_DEBUGGER_BUTTON: + if (DebugInfo.Enter_R4300i_Commands_Window != NULL) { + DebugInfo.Enter_R4300i_Commands_Window(); + } + break; + case IDC_R4300I_REGISTERS_BUTTON: + if (DebugInfo.Enter_R4300i_Register_Window != NULL) { + DebugInfo.Enter_R4300i_Register_Window(); + } + break; + case IDC_MEMORY_BUTTON: + if (DebugInfo.Enter_Memory_Window != NULL) { + DebugInfo.Enter_Memory_Window(); + } + break; + case IDCANCEL: + EndDialog( hDlg, IDCANCEL ); + break; + } + break; + case WM_VSCROLL: + if ((HWND)lParam == hScrlBar) { + DWORD location; + char Value[20]; + SCROLLINFO si; + + GetWindowText(hAddress,Value,sizeof(Value)); + location = AsciiToHex(Value) & ~3; + + switch (LOWORD(wParam)) { + case SB_THUMBTRACK: + sprintf(Value,"%03X",((short int)HIWORD(wParam) << 2 )); + SetWindowText(hAddress,Value); + si.cbSize = sizeof(si); + si.fMask = SIF_POS; + si.nPos = (short int)HIWORD(wParam); + SetScrollInfo(hScrlBar,SB_CTL,&si,TRUE); + break; + case SB_LINEDOWN: + if (location < 0xF88) { + sprintf(Value,"%03X",location + 0x4); + SetWindowText(hAddress,Value); + si.cbSize = sizeof(si); + si.fMask = SIF_POS; + si.nPos = ((location + 0x4) >> 2); + SetScrollInfo(hScrlBar,SB_CTL,&si,TRUE); + } else { + sprintf(Value,"%03X",0xF88); + SetWindowText(hAddress,Value); + si.cbSize = sizeof(si); + si.fMask = SIF_POS; + si.nPos = (0xFFC >> 2); + SetScrollInfo(hScrlBar,SB_CTL,&si,TRUE); + } + break; + case SB_LINEUP: + if (location > 0x4 ) { + sprintf(Value,"%03X",location - 0x4); + SetWindowText(hAddress,Value); + si.cbSize = sizeof(si); + si.fMask = SIF_POS; + si.nPos = ((location - 0x4) >> 2); + SetScrollInfo(hScrlBar,SB_CTL,&si,TRUE); + } else { + sprintf(Value,"%03X",0); + SetWindowText(hAddress,Value); + si.cbSize = sizeof(si); + si.fMask = SIF_POS; + si.nPos = 0; + SetScrollInfo(hScrlBar,SB_CTL,&si,TRUE); + } + break; + case SB_PAGEDOWN: + if ((location + 0x74)< 0xF88) { + sprintf(Value,"%03X",location + 0x74); + SetWindowText(hAddress,Value); + si.cbSize = sizeof(si); + si.fMask = SIF_POS; + si.nPos = ((location + 0x74) >> 2); + SetScrollInfo(hScrlBar,SB_CTL,&si,TRUE); + } else { + sprintf(Value,"%03X",0xF88); + SetWindowText(hAddress,Value); + si.cbSize = sizeof(si); + si.fMask = SIF_POS; + si.nPos = (0xF8F >> 2); + SetScrollInfo(hScrlBar,SB_CTL,&si,TRUE); + } + break; + case SB_PAGEUP: + if ((location - 0x74) > 0x74 ) { + sprintf(Value,"%03X",location - 0x74); + SetWindowText(hAddress,Value); + si.cbSize = sizeof(si); + si.fMask = SIF_POS; + si.nPos = ((location - 0x74) >> 2); + SetScrollInfo(hScrlBar,SB_CTL,&si,TRUE); + } else { + sprintf(Value,"%03X",0); + SetWindowText(hAddress,Value); + si.cbSize = sizeof(si); + si.fMask = SIF_POS; + si.nPos = 0; + SetScrollInfo(hScrlBar,SB_CTL,&si,TRUE); + } + break; + } + } + break; + default: + return FALSE; + } + return TRUE; +} + +void RSP_Commands_Setup ( HWND hDlg ) { +#define WindowWidth 457 +#define WindowHeight 494 + char Location[10]; + DWORD X, Y, WndPos; + + hList = CreateWindowEx(WS_EX_STATICEDGE, "LISTBOX","", WS_CHILD | WS_VISIBLE | + LBS_OWNERDRAWFIXED | LBS_NOTIFY,14,30,303,445, hDlg, + (HMENU)IDC_LIST, hinstDLL,NULL ); + if ( hList) { + SendMessage(hList,WM_SETFONT, (WPARAM)GetStockObject(DEFAULT_GUI_FONT),0); + SendMessage(hList,LB_SETITEMHEIGHT, (WPARAM)0,(LPARAM)MAKELPARAM(14, 0)); + } + + sprintf(Location,"%03X",*PrgCount); + hAddress = CreateWindowEx(0,"EDIT",Location, WS_CHILD | ES_UPPERCASE | WS_VISIBLE | + WS_BORDER | WS_TABSTOP,375,17,36,18, hDlg,(HMENU)IDC_ADDRESS,hinstDLL, NULL ); + if (hAddress) { + SendMessage(hAddress,WM_SETFONT, (WPARAM)GetStockObject(DEFAULT_GUI_FONT),0); + SendMessage(hAddress,EM_SETLIMITTEXT, (WPARAM)3,(LPARAM)0); + } + + hFunctionlist = CreateWindowEx(0,"COMBOBOX","", WS_CHILD | WS_VSCROLL | + CBS_DROPDOWNLIST | CBS_SORT | WS_TABSTOP,352,56,89,150,hDlg, + (HMENU)IDC_FUNCTION_COMBO,hinstDLL,NULL); + if (hFunctionlist) { + SendMessage(hFunctionlist,WM_SETFONT, (WPARAM)GetStockObject(DEFAULT_GUI_FONT),0); + } + + hGoButton = CreateWindowEx(WS_EX_STATICEDGE, "BUTTON","&Go", WS_CHILD | + BS_DEFPUSHBUTTON | WS_VISIBLE | WS_TABSTOP, 347,56,100,24, hDlg,(HMENU)IDC_GO_BUTTON, + hinstDLL,NULL ); + if (hGoButton) { + SendMessage(hGoButton,WM_SETFONT, (WPARAM)GetStockObject(DEFAULT_GUI_FONT),0); + } + + hBreakButton = CreateWindowEx(WS_EX_STATICEDGE, "BUTTON","&Break", WS_DISABLED | + WS_CHILD | BS_PUSHBUTTON | WS_VISIBLE | WS_TABSTOP | BS_TEXT, 347,85,100,24,hDlg, + (HMENU)IDC_BREAK_BUTTON,hinstDLL,NULL ); + if (hBreakButton) { + SendMessage(hBreakButton,WM_SETFONT,(WPARAM)GetStockObject(DEFAULT_GUI_FONT),0); + } + + hStepButton = CreateWindowEx(WS_EX_STATICEDGE, "BUTTON","&Step", WS_CHILD | + BS_PUSHBUTTON | WS_VISIBLE | WS_TABSTOP | BS_TEXT, 347,114,100,24,hDlg, + (HMENU)IDC_STEP_BUTTON,hinstDLL,NULL ); + if (hStepButton) { + SendMessage(hStepButton,WM_SETFONT,(WPARAM)GetStockObject(DEFAULT_GUI_FONT),0); + } + + hSkipButton = CreateWindowEx(WS_EX_STATICEDGE, "BUTTON","&Skip", WS_CHILD | + BS_PUSHBUTTON | WS_VISIBLE | WS_TABSTOP | BS_TEXT, 347,143,100,24,hDlg, + (HMENU)IDC_SKIP_BUTTON,hinstDLL,NULL ); + if (hSkipButton) { + SendMessage(hSkipButton,WM_SETFONT,(WPARAM)GetStockObject(DEFAULT_GUI_FONT),0); + } + + WndPos = 324; + if (DebugInfo.Enter_BPoint_Window == NULL) { WndPos += 29;} + if (DebugInfo.Enter_R4300i_Commands_Window == NULL) { WndPos += 29;} + if (DebugInfo.Enter_R4300i_Register_Window == NULL) { WndPos += 29;} + if (DebugInfo.Enter_Memory_Window == NULL) { WndPos += 29;} + + if (DebugInfo.Enter_BPoint_Window != NULL) { + hBPButton = CreateWindowEx(WS_EX_STATICEDGE, "BUTTON","&Break Points", WS_CHILD | + BS_PUSHBUTTON | WS_VISIBLE | WS_TABSTOP | BS_TEXT, 347,WndPos,100,24,hDlg, + (HMENU)IDC_BP_BUTTON,hinstDLL,NULL ); + if (hBPButton) { + SendMessage(hBPButton,WM_SETFONT,(WPARAM)GetStockObject(DEFAULT_GUI_FONT),0); + } + } + + WndPos += 29; + hRSPRegisters = CreateWindowEx(WS_EX_STATICEDGE,"BUTTON", "RSP &Registers...", + WS_CHILD | BS_PUSHBUTTON | WS_VISIBLE | WS_TABSTOP | BS_TEXT, 347,WndPos,100,24,hDlg, + (HMENU)IDC_RSP_REGISTERS_BUTTON,hinstDLL,NULL ); + if (hRSPRegisters) { + SendMessage(hRSPRegisters,WM_SETFONT,(WPARAM)GetStockObject(DEFAULT_GUI_FONT),0); + } + + WndPos += 29; + if (DebugInfo.Enter_R4300i_Commands_Window != NULL) { + hR4300iDebugger = CreateWindowEx(WS_EX_STATICEDGE,"BUTTON", "R4300i &Debugger...", + WS_CHILD | BS_PUSHBUTTON | WS_VISIBLE | WS_TABSTOP | BS_TEXT, 347,WndPos,100,24,hDlg, + (HMENU)IDC_R4300I_DEBUGGER_BUTTON,hinstDLL,NULL ); + if (hR4300iDebugger) { + SendMessage(hR4300iDebugger,WM_SETFONT,(WPARAM)GetStockObject(DEFAULT_GUI_FONT),0); + } + } + + WndPos += 29; + if (DebugInfo.Enter_R4300i_Register_Window != NULL) { + hR4300iRegisters = CreateWindowEx(WS_EX_STATICEDGE,"BUTTON","R4300i R&egisters...", + WS_CHILD | BS_PUSHBUTTON | WS_VISIBLE | WS_TABSTOP | BS_TEXT, 347,WndPos,100,24,hDlg, + (HMENU)IDC_R4300I_REGISTERS_BUTTON,hinstDLL,NULL ); + if (hR4300iRegisters) { + SendMessage(hR4300iRegisters,WM_SETFONT, (WPARAM)GetStockObject(DEFAULT_GUI_FONT),0); + } + } + + WndPos += 29; + if (DebugInfo.Enter_Memory_Window != NULL) { + hMemory = CreateWindowEx(WS_EX_STATICEDGE,"BUTTON", "&Memory...", WS_CHILD | + BS_PUSHBUTTON | WS_VISIBLE | WS_TABSTOP | BS_TEXT, 347,WndPos,100,24,hDlg, + (HMENU)IDC_MEMORY_BUTTON,hinstDLL,NULL ); + if (hMemory) { + SendMessage(hMemory,WM_SETFONT,(WPARAM)GetStockObject(DEFAULT_GUI_FONT),0); + } + } + + hScrlBar = CreateWindowEx(WS_EX_STATICEDGE, "SCROLLBAR","", WS_CHILD | WS_VISIBLE | + WS_TABSTOP | SBS_VERT, 318,14,18,439, hDlg, (HMENU)IDC_SCRL_BAR, hinstDLL, NULL ); + + if ( RSP_Running ) { + Enable_RSP_Commands_Window(); + } else { + Disable_RSP_Commands_Window(); + } + + //if ( !GetStoredWinPos("RSP Commands", &X, &Y ) ) { + X = (GetSystemMetrics( SM_CXSCREEN ) - WindowWidth) / 2; + Y = (GetSystemMetrics( SM_CYSCREEN ) - WindowHeight) / 2; + //} + SetWindowText(hDlg,"RSP Commands"); + + SetWindowPos(hDlg,NULL,X,Y,WindowWidth,WindowHeight, SWP_NOZORDER | + SWP_SHOWWINDOW); + +} + +char * RSPSpecialName ( DWORD OpCode, DWORD PC ) { + OPCODE command; + command.Hex = OpCode; + + switch (command.funct) { + case RSP_SPECIAL_SLL: + if (command.rd != 0) { + sprintf(CommandName,"SLL\t%s, %s, 0x%X",GPR_Name(command.rd), + GPR_Name(command.rt), command.sa); + } else { + sprintf(CommandName,"NOP"); + } + break; + case RSP_SPECIAL_SRL: + sprintf(CommandName,"SRL\t%s, %s, 0x%X",GPR_Name(command.rd), + GPR_Name(command.rt), command.sa); + break; + case RSP_SPECIAL_SRA: + sprintf(CommandName,"SRA\t%s, %s, 0x%X",GPR_Name(command.rd), + GPR_Name(command.rt), command.sa); + break; + case RSP_SPECIAL_SLLV: + sprintf(CommandName,"SLLV\t%s, %s, %s",GPR_Name(command.rd), + GPR_Name(command.rt), GPR_Name(command.rs)); + break; + case RSP_SPECIAL_SRLV: + sprintf(CommandName,"SRLV\t%s, %s, %s",GPR_Name(command.rd), + GPR_Name(command.rt), GPR_Name(command.rs)); + break; + case RSP_SPECIAL_SRAV: + sprintf(CommandName,"SRAV\t%s, %s, %s",GPR_Name(command.rd), + GPR_Name(command.rt), GPR_Name(command.rs)); + break; + case RSP_SPECIAL_JR: + sprintf(CommandName,"JR\t%s",GPR_Name(command.rs)); + break; + case RSP_SPECIAL_JALR: + sprintf(CommandName,"JALR\t%s, %s",GPR_Name(command.rd),GPR_Name(command.rs)); + break; + case RSP_SPECIAL_BREAK: + sprintf(CommandName,"BREAK"); + break; + case RSP_SPECIAL_ADD: + sprintf(CommandName,"ADD\t%s, %s, %s",GPR_Name(command.rd),GPR_Name(command.rs), + GPR_Name(command.rt)); + break; + case RSP_SPECIAL_ADDU: + sprintf(CommandName,"ADDU\t%s, %s, %s",GPR_Name(command.rd),GPR_Name(command.rs), + GPR_Name(command.rt)); + break; + case RSP_SPECIAL_SUB: + sprintf(CommandName,"SUB\t%s, %s, %s",GPR_Name(command.rd),GPR_Name(command.rs), + GPR_Name(command.rt)); + break; + case RSP_SPECIAL_SUBU: + sprintf(CommandName,"SUBU\t%s, %s, %s",GPR_Name(command.rd),GPR_Name(command.rs), + GPR_Name(command.rt)); + break; + case RSP_SPECIAL_AND: + sprintf(CommandName,"AND\t%s, %s, %s",GPR_Name(command.rd),GPR_Name(command.rs), + GPR_Name(command.rt)); + break; + case RSP_SPECIAL_OR: + sprintf(CommandName,"OR\t%s, %s, %s",GPR_Name(command.rd),GPR_Name(command.rs), + GPR_Name(command.rt)); + break; + case RSP_SPECIAL_XOR: + sprintf(CommandName,"XOR\t%s, %s, %s",GPR_Name(command.rd),GPR_Name(command.rs), + GPR_Name(command.rt)); + break; + case RSP_SPECIAL_NOR: + sprintf(CommandName,"NOR\t%s, %s, %s",GPR_Name(command.rd),GPR_Name(command.rs), + GPR_Name(command.rt)); + break; + case RSP_SPECIAL_SLT: + sprintf(CommandName,"SLT\t%s, %s, %s",GPR_Name(command.rd),GPR_Name(command.rs), + GPR_Name(command.rt)); + break; + case RSP_SPECIAL_SLTU: + sprintf(CommandName,"SLTU\t%s, %s, %s",GPR_Name(command.rd),GPR_Name(command.rs), + GPR_Name(command.rt)); + break; + default: + sprintf(CommandName,"RSP: Unknown\t%02X %02X %02X %02X", + command.Ascii[3],command.Ascii[2],command.Ascii[1],command.Ascii[0]); + } + return CommandName; +} + +char * RSPRegimmName ( DWORD OpCode, DWORD PC ) { + OPCODE command; + command.Hex = OpCode; + + switch (command.rt) { + case RSP_REGIMM_BLTZ: + sprintf(CommandName,"BLTZ\t%s, 0x%03X",GPR_Name(command.rs), + (PC + ((short)command.offset << 2) + 4) & 0xFFC); + break; + case RSP_REGIMM_BGEZ: + sprintf(CommandName,"BGEZ\t%s, 0x%03X",GPR_Name(command.rs), + (PC + ((short)command.offset << 2) + 4) & 0xFFC); + break; + case RSP_REGIMM_BLTZAL: + sprintf(CommandName,"BLTZAL\t%s, 0x%03X",GPR_Name(command.rs), + (PC + ((short)command.offset << 2) + 4) & 0xFFC); + break; + case RSP_REGIMM_BGEZAL: + if (command.rs == 0) { + sprintf(CommandName,"BAL\t0x%03X",(PC + ((short)command.offset << 2) + 4) & 0xFFC); + } else { + sprintf(CommandName,"BGEZAL\t%s, 0x%03X",GPR_Name(command.rs), + (PC + ((short)command.offset << 2) + 4) & 0xFFC); + } + break; + default: + sprintf(CommandName,"RSP: Unknown\t%02X %02X %02X %02X", + command.Ascii[3],command.Ascii[2],command.Ascii[1],command.Ascii[0]); + } + return CommandName; +} + +char * RSPCop0Name ( DWORD OpCode, DWORD PC ) { + OPCODE command; + command.Hex = OpCode; + switch (command.rs) { + case RSP_COP0_MF: + sprintf(CommandName,"MFC0\t%s, %s",GPR_Name(command.rt),COP0_Name(command.rd)); + break; + case RSP_COP0_MT: + sprintf(CommandName,"MTC0\t%s, %s",GPR_Name(command.rt),COP0_Name(command.rd)); + break; + default: + sprintf(CommandName,"RSP: Unknown\t%02X %02X %02X %02X", + command.Ascii[3],command.Ascii[2],command.Ascii[1],command.Ascii[0]); + } + return CommandName; +} + +char * RSPCop2Name ( DWORD OpCode, DWORD PC ) { + OPCODE command; + command.Hex = OpCode; + + if ( ( command.rs & 0x10 ) == 0 ) { + switch (command.rs) { + case RSP_COP2_MF: + sprintf(CommandName,"MFC2\t%s, $v%d [%d]",GPR_Name(command.rt), + command.rd, command.sa >> 1); + break; + case RSP_COP2_CF: + sprintf(CommandName,"CFC2\t%s, %d",GPR_Name(command.rt), + command.rd % 4); + break; + case RSP_COP2_MT: + sprintf(CommandName,"MTC2\t%s, $v%d [%d]",GPR_Name(command.rt), + command.rd, command.sa >> 1); + break; + case RSP_COP2_CT: + sprintf(CommandName,"CTC2\t%s, %d",GPR_Name(command.rt), + command.rd % 4); + break; + default: + sprintf(CommandName,"RSP: Unknown\t%02X %02X %02X %02X", + command.Ascii[3],command.Ascii[2],command.Ascii[1],command.Ascii[0]); + } + } else { + switch (command.funct) { + case RSP_VECTOR_VMULF: + sprintf(CommandName,"VMULF\t$v%d, $v%d, $v%d%s",command.sa, command.rd, + command.rt, ElementSpecifier(command.rs & 0xF)); + break; + case RSP_VECTOR_VMULU: + sprintf(CommandName,"VMULU\t$v%d, $v%d, $v%d%s",command.sa, command.rd, + command.rt, ElementSpecifier(command.rs & 0xF)); + break; + case RSP_VECTOR_VRNDP: + sprintf(CommandName,"VRNDP\t$v%d, $v%d, $v%d%s",command.sa, command.rd, + command.rt, ElementSpecifier(command.rs & 0xF)); + break; + case RSP_VECTOR_VMULQ: + sprintf(CommandName,"VMULQ\t$v%d, $v%d, $v%d%s",command.sa, command.rd, + command.rt, ElementSpecifier(command.rs & 0xF)); + break; + case RSP_VECTOR_VMUDL: + sprintf(CommandName,"VMUDL\t$v%d, $v%d, $v%d%s",command.sa, command.rd, + command.rt, ElementSpecifier(command.rs & 0xF)); + break; + case RSP_VECTOR_VMUDM: + sprintf(CommandName,"VMUDM\t$v%d, $v%d, $v%d%s",command.sa, command.rd, + command.rt, ElementSpecifier(command.rs & 0xF)); + break; + case RSP_VECTOR_VMUDN: + sprintf(CommandName,"VMUDN\t$v%d, $v%d, $v%d%s",command.sa, command.rd, + command.rt, ElementSpecifier(command.rs & 0xF)); + break; + case RSP_VECTOR_VMUDH: + sprintf(CommandName,"VMUDH\t$v%d, $v%d, $v%d%s",command.sa, command.rd, + command.rt, ElementSpecifier(command.rs & 0xF)); + break; + case RSP_VECTOR_VMACF: + sprintf(CommandName,"VMACF\t$v%d, $v%d, $v%d%s",command.sa, command.rd, + command.rt, ElementSpecifier(command.rs & 0xF)); + break; + case RSP_VECTOR_VMACU: + sprintf(CommandName,"VMACU\t$v%d, $v%d, $v%d%s",command.sa, command.rd, + command.rt, ElementSpecifier(command.rs & 0xF)); + break; + case RSP_VECTOR_VRNDN: + sprintf(CommandName,"VRNDN\t$v%d, $v%d, $v%d%s",command.sa, command.rd, + command.rt, ElementSpecifier(command.rs & 0xF)); + break; + case RSP_VECTOR_VMACQ: + sprintf(CommandName,"VMACQ\t$v%d, $v%d, $v%d%s",command.sa, command.rd, + command.rt, ElementSpecifier(command.rs & 0xF)); + break; + case RSP_VECTOR_VMADL: + sprintf(CommandName,"VMADL\t$v%d, $v%d, $v%d%s",command.sa, command.rd, + command.rt, ElementSpecifier(command.rs & 0xF)); + break; + case RSP_VECTOR_VMADM: + sprintf(CommandName,"VMADM\t$v%d, $v%d, $v%d%s",command.sa, command.rd, + command.rt, ElementSpecifier(command.rs & 0xF)); + break; + case RSP_VECTOR_VMADN: + sprintf(CommandName,"VMADN\t$v%d, $v%d, $v%d%s",command.sa, command.rd, + command.rt, ElementSpecifier(command.rs & 0xF)); + break; + case RSP_VECTOR_VMADH: + sprintf(CommandName,"VMADH\t$v%d, $v%d, $v%d%s",command.sa, command.rd, + command.rt, ElementSpecifier(command.rs & 0xF)); + break; + case RSP_VECTOR_VADD: + sprintf(CommandName,"VADD\t$v%d, $v%d, $v%d%s",command.sa, command.rd, + command.rt, ElementSpecifier(command.rs & 0xF)); + break; + case RSP_VECTOR_VSUB: + sprintf(CommandName,"VSUB\t$v%d, $v%d, $v%d%s",command.sa, command.rd, + command.rt, ElementSpecifier(command.rs & 0xF)); + break; + case RSP_VECTOR_VABS: + sprintf(CommandName,"VABS\t$v%d, $v%d, $v%d%s",command.sa, command.rd, + command.rt, ElementSpecifier(command.rs & 0xF)); + break; + case RSP_VECTOR_VADDC: + sprintf(CommandName,"VADDC\t$v%d, $v%d, $v%d%s",command.sa, command.rd, + command.rt, ElementSpecifier(command.rs & 0xF)); + break; + case RSP_VECTOR_VSUBC: + sprintf(CommandName,"VSUBC\t$v%d, $v%d, $v%d%s",command.sa, command.rd, + command.rt, ElementSpecifier(command.rs & 0xF)); + break; + case RSP_VECTOR_VSAW: + sprintf(CommandName,"VSAW\t$v%d [%d], $v%d, $v%d ",command.sa, (command.rs & 0xF), + command.rd, command.rt); + break; + case RSP_VECTOR_VLT: + sprintf(CommandName,"VLT\t$v%d, $v%d, $v%d%s",command.sa, command.rd, + command.rt, ElementSpecifier(command.rs & 0xF)); + break; + case RSP_VECTOR_VEQ: + sprintf(CommandName,"VEQ\t$v%d, $v%d, $v%d%s",command.sa, command.rd, + command.rt, ElementSpecifier(command.rs & 0xF)); + break; + case RSP_VECTOR_VNE: + sprintf(CommandName,"VNE\t$v%d, $v%d, $v%d%s",command.sa, command.rd, + command.rt, ElementSpecifier(command.rs & 0xF)); + break; + case RSP_VECTOR_VGE: + sprintf(CommandName,"VGE\t$v%d, $v%d, $v%d%s",command.sa, command.rd, + command.rt, ElementSpecifier(command.rs & 0xF)); + break; + case RSP_VECTOR_VCL: + sprintf(CommandName,"VCL\t$v%d, $v%d, $v%d%s",command.sa, command.rd, + command.rt, ElementSpecifier(command.rs & 0xF)); + break; + case RSP_VECTOR_VCH: + sprintf(CommandName,"VCH\t$v%d, $v%d, $v%d%s",command.sa, command.rd, + command.rt, ElementSpecifier(command.rs & 0xF)); + break; + case RSP_VECTOR_VCR: + sprintf(CommandName,"VCR\t$v%d, $v%d, $v%d%s",command.sa, command.rd, + command.rt, ElementSpecifier(command.rs & 0xF)); + break; + case RSP_VECTOR_VMRG: + sprintf(CommandName,"VMRG\t$v%d, $v%d, $v%d%s",command.sa, command.rd, + command.rt, ElementSpecifier(command.rs & 0xF)); + break; + case RSP_VECTOR_VAND: + sprintf(CommandName,"VAND\t$v%d, $v%d, $v%d%s",command.sa, command.rd, + command.rt, ElementSpecifier(command.rs & 0xF)); + break; + case RSP_VECTOR_VNAND: + sprintf(CommandName,"VNAND\t$v%d, $v%d, $v%d%s",command.sa, command.rd, + command.rt, ElementSpecifier(command.rs & 0xF)); + break; + case RSP_VECTOR_VOR: + sprintf(CommandName,"VOR\t$v%d, $v%d, $v%d%s",command.sa, command.rd, + command.rt, ElementSpecifier(command.rs & 0xF)); + break; + case RSP_VECTOR_VNOR: + sprintf(CommandName,"VNOR\t$v%d, $v%d, $v%d%s",command.sa, command.rd, + command.rt, ElementSpecifier(command.rs & 0xF)); + break; + case RSP_VECTOR_VXOR: + sprintf(CommandName,"VXOR\t$v%d, $v%d, $v%d%s",command.sa, command.rd, + command.rt, ElementSpecifier(command.rs & 0xF)); + break; + case RSP_VECTOR_VNXOR: + sprintf(CommandName,"VNXOR\t$v%d, $v%d, $v%d%s",command.sa, command.rd, + command.rt, ElementSpecifier(command.rs & 0xF)); + break; + case RSP_VECTOR_VRCP: + sprintf(CommandName,"VRCP\t$v%d [%d], $v%d%s",command.sa, (command.rd & 0x7), + command.rt, ElementSpecifier(command.rs & 0xF)); + break; + case RSP_VECTOR_VRCPL: + sprintf(CommandName,"VRCPL\t$v%d [%d], $v%d%s",command.sa, (command.rd & 0x7), + command.rt, ElementSpecifier(command.rs & 0xF)); + break; + case RSP_VECTOR_VRCPH: + sprintf(CommandName,"VRCPH\t$v%d [%d], $v%d%s",command.sa, (command.rd & 0x7), + command.rt, ElementSpecifier(command.rs & 0xF)); + break; + case RSP_VECTOR_VMOV: + sprintf(CommandName,"VMOV\t$v%d [%d], $v%d%s",command.sa, (command.rd & 0x7), + command.rt, ElementSpecifier(command.rs & 0xF)); + break; + case RSP_VECTOR_VRSQ: + sprintf(CommandName,"VRSQ\t$v%d [%d], $v%d%s",command.sa, (command.rd & 0x7), + command.rt, ElementSpecifier(command.rs & 0xF)); + break; + case RSP_VECTOR_VRSQL: + sprintf(CommandName,"VRSQL\t$v%d [%d], $v%d%s",command.sa, (command.rd & 0x7), + command.rt, ElementSpecifier(command.rs & 0xF)); + break; + case RSP_VECTOR_VRSQH: + sprintf(CommandName,"VRSQH\t$v%d [%d], $v%d%s",command.sa, (command.rd & 0x7), + command.rt, ElementSpecifier(command.rs & 0xF)); + break; + case RSP_VECTOR_VNOOP: + sprintf(CommandName,"VNOOP"); + break; + default: + sprintf(CommandName,"RSP: Unknown\t%02X %02X %02X %02X", + command.Ascii[3],command.Ascii[2],command.Ascii[1],command.Ascii[0]); + } + } + return CommandName; +} + +char * RSPLc2Name ( DWORD OpCode, DWORD PC ) { + OPCODE command; + command.Hex = OpCode; + + switch (command.rd) { + case RSP_LSC2_BV: + sprintf(CommandName,"LBV\t$v%d [%d], 0x%04X (%s)",command.rt, command.del, + command.voffset, GPR_Name(command.base)); + break; + case RSP_LSC2_SV: + sprintf(CommandName,"LSV\t$v%d [%d], 0x%04X (%s)",command.rt, command.del, + (command.voffset << 1), GPR_Name(command.base)); + break; + case RSP_LSC2_LV: + sprintf(CommandName,"LLV\t$v%d [%d], 0x%04X (%s)",command.rt, command.del, + (command.voffset << 2), GPR_Name(command.base)); + break; + case RSP_LSC2_DV: + sprintf(CommandName,"LDV\t$v%d [%d], 0x%04X (%s)",command.rt, command.del, + (command.voffset << 3), GPR_Name(command.base)); + break; + case RSP_LSC2_QV: + sprintf(CommandName,"LQV\t$v%d [%d], 0x%04X (%s)",command.rt, command.del, + (command.voffset << 4), GPR_Name(command.base)); + break; + case RSP_LSC2_RV: + sprintf(CommandName,"LRV\t$v%d [%d], 0x%04X (%s)",command.rt, command.del, + (command.voffset << 4), GPR_Name(command.base)); + break; + case RSP_LSC2_PV: + sprintf(CommandName,"LPV\t$v%d [%d], 0x%04X (%s)",command.rt, command.del, + (command.voffset << 3), GPR_Name(command.base)); + break; + case RSP_LSC2_UV: + sprintf(CommandName,"LUV\t$v%d [%d], 0x%04X (%s)",command.rt, command.del, + (command.voffset << 3), GPR_Name(command.base)); + break; + case RSP_LSC2_HV: + sprintf(CommandName,"LHV\t$v%d [%d], 0x%04X (%s)",command.rt, command.del, + (command.voffset << 4), GPR_Name(command.base)); + break; + case RSP_LSC2_FV: + sprintf(CommandName,"LFV\t$v%d [%d], 0x%04X (%s)",command.rt, command.del, + (command.voffset << 4), GPR_Name(command.base)); + break; + case RSP_LSC2_WV: + sprintf(CommandName,"LWV\t$v%d [%d], 0x%04X (%s)",command.rt, command.del, + (command.voffset << 4), GPR_Name(command.base)); + break; + case RSP_LSC2_TV: + sprintf(CommandName,"LTV\t$v%d [%d], 0x%04X (%s)",command.rt, command.del, + (command.voffset << 4), GPR_Name(command.base)); + break; + default: + sprintf(CommandName,"RSP: Unknown\t%02X %02X %02X %02X", + command.Ascii[3],command.Ascii[2],command.Ascii[1],command.Ascii[0]); + } + return CommandName; +} + +char * RSPSc2Name ( DWORD OpCode, DWORD PC ) { + OPCODE command; + command.Hex = OpCode; + + switch (command.rd) { + case RSP_LSC2_BV: + sprintf(CommandName,"SBV\t$v%d [%d], 0x%04X (%s)",command.rt, command.del, + command.voffset, GPR_Name(command.base)); + break; + case RSP_LSC2_SV: + sprintf(CommandName,"SSV\t$v%d [%d], 0x%04X (%s)",command.rt, command.del, + (command.voffset << 1), GPR_Name(command.base)); + break; + case RSP_LSC2_LV: + sprintf(CommandName,"SLV\t$v%d [%d], 0x%04X (%s)",command.rt, command.del, + (command.voffset << 2), GPR_Name(command.base)); + break; + case RSP_LSC2_DV: + sprintf(CommandName,"SDV\t$v%d [%d], 0x%04X (%s)",command.rt, command.del, + (command.voffset << 3), GPR_Name(command.base)); + break; + case RSP_LSC2_QV: + sprintf(CommandName,"SQV\t$v%d [%d], 0x%04X (%s)",command.rt, command.del, + (command.voffset << 4), GPR_Name(command.base)); + break; + case RSP_LSC2_RV: + sprintf(CommandName,"SRV\t$v%d [%d], 0x%04X (%s)",command.rt, command.del, + (command.voffset << 4), GPR_Name(command.base)); + break; + case RSP_LSC2_PV: + sprintf(CommandName,"SPV\t$v%d [%d], 0x%04X (%s)",command.rt, command.del, + (command.voffset << 3), GPR_Name(command.base)); + break; + case RSP_LSC2_UV: + sprintf(CommandName,"SUV\t$v%d [%d], 0x%04X (%s)",command.rt, command.del, + (command.voffset << 3), GPR_Name(command.base)); + break; + case RSP_LSC2_HV: + sprintf(CommandName,"SHV\t$v%d [%d], 0x%04X (%s)",command.rt, command.del, + (command.voffset << 4), GPR_Name(command.base)); + break; + case RSP_LSC2_FV: + sprintf(CommandName,"SFV\t$v%d [%d], 0x%04X (%s)",command.rt, command.del, + (command.voffset << 4), GPR_Name(command.base)); + break; + case RSP_LSC2_WV: + sprintf(CommandName,"SWV\t$v%d [%d], 0x%04X (%s)",command.rt, command.del, + (command.voffset << 4), GPR_Name(command.base)); + break; + case RSP_LSC2_TV: + sprintf(CommandName,"STV\t$v%d [%d], 0x%04X (%s)",command.rt, command.del, + (command.voffset << 4), GPR_Name(command.base)); + break; + default: + sprintf(CommandName,"RSP: Unknown\t%02X %02X %02X %02X", + command.Ascii[3],command.Ascii[2],command.Ascii[1],command.Ascii[0]); + } + return CommandName; +} + +char * RSPOpcodeName ( DWORD OpCode, DWORD PC ) { + OPCODE command; + command.Hex = OpCode; + + switch (command.op) { + case RSP_SPECIAL: + return RSPSpecialName(OpCode,PC); + break; + case RSP_REGIMM: + return RSPRegimmName(OpCode,PC); + break; + case RSP_J: + sprintf(CommandName,"J\t0x%03X",(command.target << 2) & 0xFFC); + break; + case RSP_JAL: + sprintf(CommandName,"JAL\t0x%03X",(command.target << 2) & 0xFFC); + break; + case RSP_BEQ: + if (command.rs == 0 && command.rt == 0) { + sprintf(CommandName,"B\t0x%03X",(PC + ((short)command.offset << 2) + 4) & 0xFFC); + } else if (command.rs == 0 || command.rt == 0){ + sprintf(CommandName,"BEQZ\t%s, 0x%03X",GPR_Name(command.rs == 0 ? command.rt : command.rs), + (PC + ((short)command.offset << 2) + 4) & 0xFFC); + } else { + sprintf(CommandName,"BEQ\t%s, %s, 0x%03X",GPR_Name(command.rs),GPR_Name(command.rt), + (PC + ((short)command.offset << 2) + 4) & 0xFFC); + } + break; + case RSP_BNE: + sprintf(CommandName,"BNE\t%s, %s, 0x%03X",GPR_Name(command.rs),GPR_Name(command.rt), + (PC + ((short)command.offset << 2) + 4) & 0xFFC); + break; + case RSP_BLEZ: + sprintf(CommandName,"BLEZ\t%s, 0x%03X",GPR_Name(command.rs),(PC + ((short)command.offset << 2) + 4) & 0xFFC); + break; + case RSP_BGTZ: + sprintf(CommandName,"BGTZ\t%s, 0x%03X",GPR_Name(command.rs),(PC + ((short)command.offset << 2) + 4) & 0xFFC); + break; + case RSP_ADDI: + sprintf(CommandName,"ADDI\t%s, %s, 0x%04X",GPR_Name(command.rt), GPR_Name(command.rs), + command.immediate); + break; + case RSP_ADDIU: + sprintf(CommandName,"ADDIU\t%s, %s, 0x%04X",GPR_Name(command.rt), GPR_Name(command.rs), + command.immediate); + break; + case RSP_SLTI: + sprintf(CommandName,"SLTI\t%s, %s, 0x%04X",GPR_Name(command.rt), GPR_Name(command.rs), + command.immediate); + break; + case RSP_SLTIU: + sprintf(CommandName,"SLTIU\t%s, %s, 0x%04X",GPR_Name(command.rt), GPR_Name(command.rs), + command.immediate); + break; + case RSP_ANDI: + sprintf(CommandName,"ANDI\t%s, %s, 0x%04X",GPR_Name(command.rt), GPR_Name(command.rs), + command.immediate); + break; + case RSP_ORI: + sprintf(CommandName,"ORI\t%s, %s, 0x%04X",GPR_Name(command.rt), GPR_Name(command.rs), + command.immediate); + break; + case RSP_XORI: + sprintf(CommandName,"XORI\t%s, %s, 0x%04X",GPR_Name(command.rt), GPR_Name(command.rs), + command.immediate); + break; + case RSP_LUI: + sprintf(CommandName,"LUI\t%s, 0x%04X",GPR_Name(command.rt), command.immediate); + break; + case RSP_CP0: + return RSPCop0Name(OpCode,PC); + break; + case RSP_CP2: + return RSPCop2Name(OpCode,PC); + break; + case RSP_LB: + sprintf(CommandName,"LB\t%s, 0x%04X(%s)",GPR_Name(command.rt), command.offset, + GPR_Name(command.base)); + break; + case RSP_LH: + sprintf(CommandName,"LH\t%s, 0x%04X(%s)",GPR_Name(command.rt), command.offset, + GPR_Name(command.base)); + break; + case RSP_LW: + sprintf(CommandName,"LW\t%s, 0x%04X(%s)",GPR_Name(command.rt), command.offset, + GPR_Name(command.base)); + break; + case RSP_LBU: + sprintf(CommandName,"LBU\t%s, 0x%04X(%s)",GPR_Name(command.rt), command.offset, + GPR_Name(command.base)); + break; + case RSP_LHU: + sprintf(CommandName,"LHU\t%s, 0x%04X(%s)",GPR_Name(command.rt), command.offset, + GPR_Name(command.base)); + break; + case RSP_SB: + sprintf(CommandName,"SB\t%s, 0x%04X(%s)",GPR_Name(command.rt), command.offset, + GPR_Name(command.base)); + break; + case RSP_SH: + sprintf(CommandName,"SH\t%s, 0x%04X(%s)",GPR_Name(command.rt), command.offset, + GPR_Name(command.base)); + break; + case RSP_SW: + sprintf(CommandName,"SW\t%s, 0x%04X(%s)",GPR_Name(command.rt), command.offset, + GPR_Name(command.base)); + break; + case RSP_LC2: + return RSPLc2Name(OpCode,PC); + break; + case RSP_SC2: + return RSPSc2Name(OpCode,PC); + break; + default: + sprintf(CommandName,"RSP: Unknown\t%02X %02X %02X %02X", + command.Ascii[3],command.Ascii[2],command.Ascii[1],command.Ascii[0]); + } + return CommandName; +} + +void SetRSPCommandToRunning ( void ) { + Stepping_Commands = FALSE; + if (InRSPCommandsWindow == FALSE) { return; } + EnableWindow(hGoButton, FALSE); + EnableWindow(hBreakButton, TRUE); + EnableWindow(hStepButton, FALSE); + EnableWindow(hSkipButton, FALSE); + SendMessage(RSPCommandshWnd, DM_SETDEFID,IDC_BREAK_BUTTON,0); + SendMessage(hGoButton, BM_SETSTYLE,BS_PUSHBUTTON,TRUE); + SendMessage(hBreakButton, BM_SETSTYLE,BS_DEFPUSHBUTTON,TRUE); + SetFocus(hBreakButton); +} + +void SetRSPCommandToStepping ( void ) { + if (InRSPCommandsWindow == FALSE) { return; } + EnableWindow(hGoButton, TRUE); + EnableWindow(hBreakButton, FALSE); + EnableWindow(hStepButton, TRUE); + EnableWindow(hSkipButton, TRUE); + SendMessage(hBreakButton, BM_SETSTYLE, BS_PUSHBUTTON,TRUE); + SendMessage(hStepButton, BM_SETSTYLE, BS_DEFPUSHBUTTON,TRUE); + SendMessage(RSPCommandshWnd, DM_SETDEFID,IDC_STEP_BUTTON,0); + SetFocus(hStepButton); + Stepping_Commands = TRUE; +} + +void SetRSPCommandViewto ( UINT NewLocation ) { + unsigned int location; + char Value[20]; + + if (InRSPCommandsWindow == FALSE) { return; } + + GetWindowText(hAddress,Value,sizeof(Value)); + location = AsciiToHex(Value) & ~3; + + if ( NewLocation < location || NewLocation >= location + 120 ) { + sprintf(Value,"%03X",NewLocation); + SetWindowText(hAddress,Value); + } else { + RefreshRSPCommands(); + } +} diff --git a/Source/RSP/RSP Command.h b/Source/RSP/RSP Command.h new file mode 100644 index 000000000..7c256dc4b --- /dev/null +++ b/Source/RSP/RSP Command.h @@ -0,0 +1,40 @@ +/* + * RSP Compiler plug in for Project 64 (A Nintendo 64 emulator). + * + * (c) Copyright 2001 jabo (jabo@emulation64.com) and + * zilmar (zilmar@emulation64.com) + * + * pj64 homepage: www.pj64.net + * + * Permission to use, copy, modify and distribute Project64 in both binary and + * source form, for non-commercial purposes, is hereby granted without fee, + * providing that this license information and copyright notice appear with + * all copies and any derived work. + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event shall the authors be held liable for any damages + * arising from the use of this software. + * + * Project64 is freeware for PERSONAL USE only. Commercial users should + * seek permission of the copyright holders first. Commercial use includes + * charging money for Project64 or software derived from Project64. + * + * The copyright holders request that bug fixes and improvements to the code + * should be forwarded to them so if they want them. + * + */ + +char * RSPOpcodeName ( DWORD OpCode, DWORD PC ); + +void DumpRSPCode (void); +void DumpRSPData (void); +void Disable_RSP_Commands_Window ( void ); +void Enable_RSP_Commands_Window ( void ); +void Enter_RSP_Commands_Window ( void ); +void RefreshRSPCommands ( void ); +void SetRSPCommandToRunning ( void ); +void SetRSPCommandToStepping ( void ); +void SetRSPCommandViewto ( UINT NewLocation ); + +extern DWORD Stepping_Commands, WaitingForStep; +extern BOOL InRSPCommandsWindow; diff --git a/Source/RSP/RSP Register.c b/Source/RSP/RSP Register.c new file mode 100644 index 000000000..d93cdf756 --- /dev/null +++ b/Source/RSP/RSP Register.c @@ -0,0 +1,667 @@ +/* + * RSP Compiler plug in for Project 64 (A Nintendo 64 emulator). + * + * (c) Copyright 2001 jabo (jabo@emulation64.com) and + * zilmar (zilmar@emulation64.com) + * + * pj64 homepage: www.pj64.net + * + * Permission to use, copy, modify and distribute Project64 in both binary and + * source form, for non-commercial purposes, is hereby granted without fee, + * providing that this license information and copyright notice appear with + * all copies and any derived work. + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event shall the authors be held liable for any damages + * arising from the use of this software. + * + * Project64 is freeware for PERSONAL USE only. Commercial users should + * seek permission of the copyright holders first. Commercial use includes + * charging money for Project64 or software derived from Project64. + * + * The copyright holders request that bug fixes and improvements to the code + * should be forwarded to them so if they want them. + * + */ + +#include +#include +#include +#include "rsp.h" +#include "types.h" + +#define GeneralPurpose 1 +#define ControlProcessor0 2 +#define HiddenRegisters 3 +#define Vector1 4 +#define Vector2 5 + +#define IDC_TAB_CONTROL 1000 + +void Create_RSP_Register_Window ( int ); +void HideRSP_RegisterPanel ( int ); +void PaintRSP_HiddenPanel ( HWND ); +void PaintRSP_CP0Panel ( HWND ); +void PaintRSP_GPRPanel ( HWND ); +void PaintRSP_Vector1_Panel ( HWND ); +void PaintRSP_Vector2_Panel ( HWND ); +void ShowRSP_RegisterPanel ( int ); +void SetupRSP_HiddenPanel ( HWND ); +void SetupRSP_CP0Panel ( HWND ); +void SetupRSP_GPRPanel ( HWND ); +void SetupRSP_RegistersMain ( HWND ); +void SetupRSP_Vect1Panel ( HWND ); +void SetupRSP_Vect2Panel ( HWND ); +void UpdateRSPRegistersScreen ( void ); + +LRESULT CALLBACK RefreshRSP_RegProc ( HWND, UINT, WPARAM, LPARAM ); +LRESULT CALLBACK RSP_Registers_Proc ( HWND, UINT, WPARAM, LPARAM ); + +HWND RSP_Registers_hDlg, hTab, hStatic, hGPR[32], hCP0[16], hHIDDEN[12], + hVECT1[16], hVECT2[16]; +int InRSPRegisterWindow = FALSE; +FARPROC RefreshProc; + +/*** RSP Registers ***/ +UWORD32 RSP_GPR[32], RSP_Flags[4]; +UDWORD RSP_ACCUM[8]; +VECTOR RSP_Vect[32]; + +char * GPR_Strings[32] = { + "R0", "AT", "V0", "V1", "A0", "A1", "A2", "A3", + "T0", "T1", "T2", "T3", "T4", "T5", "T6", "T7", + "S0", "S1", "S2", "S3", "S4", "S5", "S6", "S7", + "T8", "T9", "K0", "K1", "GP", "SP", "S8", "RA" +}; + +void Create_RSP_Register_Window ( int Child ) { + DWORD ThreadID; + if ( Child ) { + InRSPRegisterWindow = TRUE; + DialogBox( hinstDLL, "RSPREGISTERS", NULL,(DLGPROC) RSP_Registers_Proc ); + InRSPRegisterWindow = FALSE; + } else { + if (!InRSPRegisterWindow) { + CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)Create_RSP_Register_Window, + (LPVOID)TRUE,0, &ThreadID); + } else { + SetForegroundWindow(RSP_Registers_hDlg); + } + } +} + +void Enter_RSP_Register_Window ( void ) { + Create_RSP_Register_Window ( FALSE ); +} + +void HideRSP_RegisterPanel ( int Panel) { + int count; + + switch( Panel ) { + case GeneralPurpose: + for (count = 0; count < 32;count ++) { ShowWindow(hGPR[count], FALSE ); } + break; + case ControlProcessor0: + for (count = 0; count < 16;count ++) { ShowWindow(hCP0[count], FALSE ); } + break; + case HiddenRegisters: + for (count = 0; count < 12;count ++) { ShowWindow(hHIDDEN[count], FALSE ); } + break; + case Vector1: + for (count = 0; count < 16;count ++) { ShowWindow(hVECT1[count], FALSE ); } + break; + case Vector2: + for (count = 0; count < 16;count ++) { ShowWindow(hVECT2[count], FALSE ); } + break; + } +} + +void InitilizeRSPRegisters (void) { + memset(RSP_GPR,0,sizeof(RSP_GPR)); + memset(RSP_Vect,0,sizeof(RSP_Vect)); +} + +void PaintRSP_HiddenPanel (HWND hWnd) { + PAINTSTRUCT ps; + RECT rcBox; + HFONT hOldFont; + int OldBkMode; + BeginPaint( hWnd, &ps ); + + rcBox.left = 66; rcBox.top = 39; + rcBox.right = 320; rcBox.bottom = 265; + DrawEdge( ps.hdc, &rcBox, EDGE_ETCHED, BF_RECT ); + + rcBox.left = 350; rcBox.top = 39; + rcBox.right = 510; rcBox.bottom = 265; + DrawEdge( ps.hdc, &rcBox, EDGE_ETCHED, BF_RECT ); + + rcBox.left = 75; rcBox.top = 35; + rcBox.right = 150; rcBox.bottom = 50; + FillRect( ps.hdc, &rcBox,(HBRUSH)COLOR_WINDOW); + + rcBox.left = 365; rcBox.top = 35; + rcBox.right = 425; rcBox.bottom = 50; + FillRect( ps.hdc, &rcBox,(HBRUSH)COLOR_WINDOW); + + hOldFont = SelectObject( ps.hdc, + GetStockObject(DEFAULT_GUI_FONT) ); + OldBkMode = SetBkMode( ps.hdc, TRANSPARENT ); + + TextOut( ps.hdc, 80,34,"Accumulators",12); + TextOut( ps.hdc, 80,56,"Accumulator 0:",14); + TextOut( ps.hdc, 80,81,"Accumulator 1:",14); + TextOut( ps.hdc, 80,106,"Accumulator 2:",14); + TextOut( ps.hdc, 80,131,"Accumulator 3:",14); + TextOut( ps.hdc, 80,156,"Accumulator 4:",14); + TextOut( ps.hdc, 80,181,"Accumulator 5:",14); + TextOut( ps.hdc, 80,206,"Accumulator 6:",14); + TextOut( ps.hdc, 80,231,"Accumulator 7:",14); + + TextOut( ps.hdc, 371,34,"RSP Flags",9); + TextOut( ps.hdc, 375,86,"Flag 0:",7); + TextOut( ps.hdc, 375,116,"Flag 2:",7); + TextOut( ps.hdc, 375,146,"Flag 3:",7); + TextOut( ps.hdc, 375,176,"Flag 4:",7); + + SelectObject( ps.hdc,hOldFont ); + SetBkMode( ps.hdc, OldBkMode ); + EndPaint( hWnd, &ps ); +} + +void PaintRSP_CP0Panel (HWND hWnd) { + PAINTSTRUCT ps; + RECT rcBox; + HFONT hOldFont; + int OldBkMode; + BeginPaint( hWnd, &ps ); + + rcBox.left = 41; + rcBox.top = 29; + rcBox.right = 573; + rcBox.bottom = 275; + DrawEdge( ps.hdc, &rcBox, EDGE_ETCHED, BF_RECT ); + + hOldFont = SelectObject( ps.hdc, + GetStockObject(DEFAULT_GUI_FONT) ); + OldBkMode = SetBkMode( ps.hdc, TRANSPARENT ); + + TextOut( ps.hdc, 53,48,"Reg 0 - SP memory address:",26); + TextOut( ps.hdc, 53,76,"Reg 1 - SP DRAM DMA address:",28); + TextOut( ps.hdc, 53,104,"Reg 2 - SP read DMA length:",27); + TextOut( ps.hdc, 53,132,"Reg 3 - SP write DMA length:",28); + TextOut( ps.hdc, 53,160,"Reg 4 - SP status:",18); + TextOut( ps.hdc, 53,188,"Reg 5 - SP DMA full:",20); + TextOut( ps.hdc, 53,216,"Reg 6 - SP DMA busy:",20); + TextOut( ps.hdc, 53,244,"Reg 7 - SP semaphore:",21); + TextOut( ps.hdc, 313,48,"Reg 8 - DP CMD DMA start:",25); + TextOut( ps.hdc, 313,76,"Reg 9 - DP CMD DMA end:",23); + TextOut( ps.hdc, 313,104,"Reg 10 - DP CMD DMA current:",28); + TextOut( ps.hdc, 313,132,"Reg 11 - DP CMD status:",23); + TextOut( ps.hdc, 313,160,"Reg 12 - DP clock counter:",26); + TextOut( ps.hdc, 313,188,"Reg 13 - DP buffer busy counter:",32); + TextOut( ps.hdc, 313,216,"Reg 14 - DP pipe busy counter:",30); + TextOut( ps.hdc, 313,244,"Reg 15 - DP TMEM load counter:",30); + + SelectObject( ps.hdc,hOldFont ); + SetBkMode( ps.hdc, OldBkMode ); + EndPaint( hWnd, &ps ); +} + +void PaintRSP_GPRPanel (HWND hWnd) { + PAINTSTRUCT ps; + RECT rcBox; + HFONT hOldFont; + int OldBkMode; + BeginPaint( hWnd, &ps ); + + rcBox.left = 41; + rcBox.top = 29; + rcBox.right = 573; + rcBox.bottom = 275; + DrawEdge( ps.hdc, &rcBox, EDGE_ETCHED, BF_RECT ); + + hOldFont = SelectObject( ps.hdc, + GetStockObject(DEFAULT_GUI_FONT) ); + OldBkMode = SetBkMode( ps.hdc, TRANSPARENT ); + + TextOut( ps.hdc, 53,46,"R0 - Reg 0:",11); + TextOut( ps.hdc, 53,66,"AT - Reg 1:",11); + TextOut( ps.hdc, 53,86,"V0 - Reg 2:",11); + TextOut( ps.hdc, 53,106,"V1 - Reg 3:",11); + TextOut( ps.hdc, 53,126,"A0 - Reg 4:",11); + TextOut( ps.hdc, 53,146,"A1 - Reg 5:",11); + TextOut( ps.hdc, 53,166,"A2 - Reg 6:",11); + TextOut( ps.hdc, 53,186,"A3 - Reg 7:",11); + TextOut( ps.hdc, 53,206,"T0 - Reg 8:",11); + TextOut( ps.hdc, 53,226,"T1 - Reg 9:",11); + TextOut( ps.hdc, 53,246,"T2 - Reg 10:",12); + TextOut( ps.hdc, 228,46,"T3 - Reg 11:",12); + TextOut( ps.hdc, 228,66,"T4 - Reg 12:",12); + TextOut( ps.hdc, 228,86,"T5 - Reg 13:",12); + TextOut( ps.hdc, 228,106,"T6 - Reg 14:",12); + TextOut( ps.hdc, 228,126,"T7 - Reg 15:",12); + TextOut( ps.hdc, 228,146,"S0 - Reg 16:",12); + TextOut( ps.hdc, 228,166,"S1 - Reg 17:",12); + TextOut( ps.hdc, 228,186,"S2 - Reg 18:",12); + TextOut( ps.hdc, 228,206,"S3 - Reg 19:",12); + TextOut( ps.hdc, 228,226,"S4 - Reg 20:",12); + TextOut( ps.hdc, 228,246,"S5 - Reg 21:",12); + TextOut( ps.hdc, 408,46,"S6 - Reg 22:",12); + TextOut( ps.hdc, 408,66,"S7 - Reg 23:",12); + TextOut( ps.hdc, 408,86,"T8 - Reg 24:",12); + TextOut( ps.hdc, 408,106,"T9 - Reg 25:",12); + TextOut( ps.hdc, 408,126,"K0 - Reg 26:",12); + TextOut( ps.hdc, 408,146,"K1 - Reg 27:",12); + TextOut( ps.hdc, 408,166,"GP - Reg 28:",12); + TextOut( ps.hdc, 408,186,"SP - Reg 29:",12); + TextOut( ps.hdc, 408,206,"S8 - Reg 30:",12); + TextOut( ps.hdc, 408,226,"RA - Reg 31:",12); + + SelectObject( ps.hdc,hOldFont ); + SetBkMode( ps.hdc, OldBkMode ); + EndPaint( hWnd, &ps ); +} + +void PaintRSP_Vector1_Panel (HWND hWnd) { + PAINTSTRUCT ps; + RECT rcBox; + HFONT hOldFont; + int OldBkMode; + BeginPaint( hWnd, &ps ); + + rcBox.left = 10; + rcBox.top = 29; + rcBox.right = 606; + rcBox.bottom = 275; + DrawEdge( ps.hdc, &rcBox, EDGE_ETCHED, BF_RECT ); + + hOldFont = SelectObject( ps.hdc, + GetStockObject(DEFAULT_GUI_FONT) ); + OldBkMode = SetBkMode( ps.hdc, TRANSPARENT ); + + TextOut( ps.hdc, 20,48,"$v0:",4); + TextOut( ps.hdc, 20,76,"$v1:",4); + TextOut( ps.hdc, 20,104,"$v2:",4); + TextOut( ps.hdc, 20,132,"$v3:",4); + TextOut( ps.hdc, 20,160,"$v4:",4); + TextOut( ps.hdc, 20,188,"$v5:",4); + TextOut( ps.hdc, 20,216,"$v6:",4); + TextOut( ps.hdc, 20,244,"$v7:",4); + TextOut( ps.hdc, 310,48,"$v8:",4); + TextOut( ps.hdc, 310,76,"$v9:",4); + TextOut( ps.hdc, 310,104,"$v10:",5); + TextOut( ps.hdc, 310,132,"$v11:",5); + TextOut( ps.hdc, 310,160,"$v12:",5); + TextOut( ps.hdc, 310,188,"$v13:",5); + TextOut( ps.hdc, 310,216,"$v14:",5); + TextOut( ps.hdc, 310,244,"$v15:",5); + + SelectObject( ps.hdc,hOldFont ); + SetBkMode( ps.hdc, OldBkMode ); + EndPaint( hWnd, &ps ); +} + +void PaintRSP_Vector2_Panel (HWND hWnd) { + PAINTSTRUCT ps; + RECT rcBox; + HFONT hOldFont; + int OldBkMode; + BeginPaint( hWnd, &ps ); + + rcBox.left = 10; + rcBox.top = 29; + rcBox.right = 606; + rcBox.bottom = 275; + DrawEdge( ps.hdc, &rcBox, EDGE_ETCHED, BF_RECT ); + + hOldFont = SelectObject( ps.hdc, + GetStockObject(DEFAULT_GUI_FONT) ); + OldBkMode = SetBkMode( ps.hdc, TRANSPARENT ); + + TextOut( ps.hdc, 20,48,"$v16:",5); + TextOut( ps.hdc, 20,76,"$v17:",5); + TextOut( ps.hdc, 20,104,"$v18:",5); + TextOut( ps.hdc, 20,132,"$v19:",5); + TextOut( ps.hdc, 20,160,"$v20:",5); + TextOut( ps.hdc, 20,188,"$v21:",5); + TextOut( ps.hdc, 20,216,"$v22:",5); + TextOut( ps.hdc, 20,244,"$v23:",5); + TextOut( ps.hdc, 310,48,"$v24:",5); + TextOut( ps.hdc, 310,76,"$v25:",5); + TextOut( ps.hdc, 310,104,"$v26:",5); + TextOut( ps.hdc, 310,132,"$v27:",5); + TextOut( ps.hdc, 310,160,"$v28:",5); + TextOut( ps.hdc, 310,188,"$v29:",5); + TextOut( ps.hdc, 310,216,"$v30:",5); + TextOut( ps.hdc, 310,244,"$v31:",5); + + SelectObject( ps.hdc,hOldFont ); + SetBkMode( ps.hdc, OldBkMode ); + EndPaint( hWnd, &ps ); +} + +LRESULT CALLBACK RefreshRSP_RegProc ( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam ) { + int nSel; + TC_ITEM item; + + switch( uMsg ) { + case WM_PAINT: + nSel = TabCtrl_GetCurSel( hTab ); + if ( nSel > -1 ) { + item.mask = TCIF_PARAM; + TabCtrl_GetItem( hTab, nSel, &item ); + switch( item.lParam ) { + case GeneralPurpose: + PaintRSP_GPRPanel (hWnd); + break; + case ControlProcessor0: + PaintRSP_CP0Panel (hWnd); + break; + case HiddenRegisters: + PaintRSP_HiddenPanel (hWnd); + break; + case Vector1: + PaintRSP_Vector1_Panel (hWnd); + break; + case Vector2: + PaintRSP_Vector2_Panel (hWnd); + break; + } + + } + break; + default: + return( (*RefreshProc)(hWnd, uMsg, wParam, lParam) ); + } + return( FALSE ); +} + +LRESULT CALLBACK RSP_Registers_Proc (HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { + static RECT rcDisp; + static int CurrentPanel = GeneralPurpose; + TC_ITEM item; + + switch (uMsg) { + case WM_INITDIALOG: + RSP_Registers_hDlg = hDlg; + SetupRSP_RegistersMain( hDlg ); + break; + case WM_MOVE: + //StoreCurrentWinPos("RSP Registers",hDlg); + break; + case WM_SIZE: + GetClientRect( hDlg, &rcDisp); + TabCtrl_AdjustRect( hTab, FALSE, &rcDisp ); + break; + case WM_NOTIFY: + switch (((NMHDR *)lParam)->code) { + case TCN_SELCHANGE: + InvalidateRect( hTab, &rcDisp, TRUE ); + HideRSP_RegisterPanel (CurrentPanel); + item.mask = TCIF_PARAM; + TabCtrl_GetItem( hTab, TabCtrl_GetCurSel( hTab ), &item ); + CurrentPanel = item.lParam; + InvalidateRect( hStatic, NULL, FALSE ); + UpdateRSPRegistersScreen(); + ShowRSP_RegisterPanel ( CurrentPanel ); + break; + } + break; + case WM_COMMAND: + switch (LOWORD(wParam)) { + case IDCANCEL: + CurrentPanel = GeneralPurpose; + EndDialog( hDlg, IDCANCEL ); + break; + } + default: + return FALSE; + } + return TRUE; +} + +void SetupRSP_HiddenPanel (HWND hDlg) { + int count; + + for (count = 0; count < 8;count ++) { + hHIDDEN[count] = CreateWindowEx(WS_EX_CLIENTEDGE,"EDIT","", WS_CHILD | + ES_READONLY | WS_BORDER | WS_TABSTOP,170,(count*25) + 60,140,19, + hDlg,0,hinstDLL, NULL ); + SendMessage(hHIDDEN[count],WM_SETFONT, (WPARAM)GetStockObject(DEFAULT_GUI_FONT),0); + } + for (count = 0; count < 4;count ++) { + hHIDDEN[count + 8] = CreateWindowEx(WS_EX_CLIENTEDGE,"EDIT","", WS_CHILD | + ES_READONLY | WS_BORDER | WS_TABSTOP,425,(count*30) + 90,55,19, + hDlg,0,hinstDLL, NULL ); + SendMessage(hHIDDEN[count + 8],WM_SETFONT, (WPARAM)GetStockObject(DEFAULT_GUI_FONT),0); + } +} + +void SetupRSP_CP0Panel (HWND hDlg) { + int count; + + for (count = 0; count < 8;count ++) { + hCP0[count] = CreateWindowEx(WS_EX_CLIENTEDGE,"EDIT","", WS_CHILD | + ES_READONLY | WS_BORDER | WS_TABSTOP,225,(count*28) + 53,75,19, + hDlg,0,hinstDLL, NULL ); + SendMessage(hCP0[count],WM_SETFONT, (WPARAM)GetStockObject(DEFAULT_GUI_FONT),0); + } + for (count = 0; count < 8;count ++) { + hCP0[count + 8] = CreateWindowEx(WS_EX_CLIENTEDGE,"EDIT","", WS_CHILD | + ES_READONLY | WS_BORDER | WS_TABSTOP,485,(count*28) + 53,75,19, + hDlg,0,hinstDLL, NULL ); + SendMessage(hCP0[ count + 8 ],WM_SETFONT, (WPARAM)GetStockObject(DEFAULT_GUI_FONT),0); + } +} + +void SetupRSP_GPRPanel (HWND hDlg) { + int count; + + for (count = 0; count < 11;count ++) { + hGPR[count] = CreateWindowEx(WS_EX_CLIENTEDGE,"EDIT","", WS_CHILD | + ES_READONLY | WS_BORDER | WS_TABSTOP,135,(count*20) + 50,75,19, + hDlg,0,hinstDLL, NULL ); + SendMessage(hGPR[count],WM_SETFONT, (WPARAM)GetStockObject(DEFAULT_GUI_FONT),0); + } + for (count = 0; count < 11;count ++) { + hGPR[count + 11] = CreateWindowEx(WS_EX_CLIENTEDGE,"EDIT","", WS_CHILD | + ES_READONLY | WS_BORDER | WS_TABSTOP,315,(count*20) + 50,75,19, + hDlg,0,hinstDLL, NULL ); + SendMessage(hGPR[ count + 11 ],WM_SETFONT, (WPARAM)GetStockObject(DEFAULT_GUI_FONT),0); + } + for (count = 0; count < 10;count ++) { + hGPR[count + 22] = CreateWindowEx(WS_EX_CLIENTEDGE,"EDIT","", WS_CHILD | + ES_READONLY | WS_BORDER | WS_TABSTOP,485,(count*20) + 50,75,19, + hDlg,0,hinstDLL, NULL ); + SendMessage(hGPR[ count + 22 ],WM_SETFONT, (WPARAM)GetStockObject(DEFAULT_GUI_FONT),0); + } +} + +void SetupRSP_RegistersMain (HWND hDlg) { +#define WindowWidth 630 +#define WindowHeight 325 + DWORD X, Y; + + hTab = CreateWindowEx(0,WC_TABCONTROL,"", WS_TABSTOP | WS_CHILD | WS_VISIBLE,5,6,616,290, + hDlg,(HMENU)IDC_TAB_CONTROL,hinstDLL,NULL ); + if ( hTab ) { + TC_ITEM item; + SendMessage(hTab, WM_SETFONT, (WPARAM)GetStockObject( DEFAULT_GUI_FONT ), 0); + item.mask = TCIF_TEXT | TCIF_PARAM; + item.pszText = " General Purpose "; + item.lParam = GeneralPurpose; + TabCtrl_InsertItem( hTab,0, &item); + item.lParam = ControlProcessor0; + item.pszText = " Control Processor 0 "; + TabCtrl_InsertItem( hTab,1, &item); + item.lParam = HiddenRegisters; + item.pszText = " Hidden Registers "; + TabCtrl_InsertItem( hTab,2, &item); + item.lParam = Vector1; + item.pszText = " RSP Vectors $v0 - $v15 "; + TabCtrl_InsertItem( hTab,3, &item); + item.lParam = Vector2; + item.pszText = " RSP Vectors $v16 - $v31 "; + TabCtrl_InsertItem( hTab,4, &item); + } + + SetupRSP_HiddenPanel ( hDlg ); + SetupRSP_CP0Panel ( hDlg ); + SetupRSP_GPRPanel ( hDlg ); + SetupRSP_Vect1Panel ( hDlg ); + SetupRSP_Vect2Panel ( hDlg ); + + hStatic = CreateWindowEx(0,"STATIC","", WS_CHILD|WS_VISIBLE, 5,6,616,290,hDlg,0,hinstDLL,NULL ); + RefreshProc = (FARPROC)SetWindowLong( hStatic,GWL_WNDPROC,(long)RefreshRSP_RegProc); + + UpdateRSPRegistersScreen (); + ShowRSP_RegisterPanel ( GeneralPurpose ); + SetWindowText(hDlg," RSP Registers"); + + //if ( !GetStoredWinPos( "RSP Registers", &X, &Y ) ) { + X = (GetSystemMetrics( SM_CXSCREEN ) - WindowWidth) / 2; + Y = (GetSystemMetrics( SM_CYSCREEN ) - WindowHeight) / 2; + //} + SetWindowPos(hDlg,NULL,X,Y,WindowWidth,WindowHeight, SWP_NOZORDER | SWP_SHOWWINDOW); +} + +void SetupRSP_Vect1Panel (HWND hDlg) { + int count; + + for (count = 0; count < 8;count ++) { + hVECT1[count] = CreateWindowEx(WS_EX_CLIENTEDGE,"EDIT","", WS_CHILD | + ES_READONLY | WS_BORDER | WS_TABSTOP,55,(count*28) + 52,254,19, + hDlg,0,hinstDLL, NULL ); + SendMessage(hVECT1[count],WM_SETFONT, (WPARAM)GetStockObject(DEFAULT_GUI_FONT),0); + } + for (count = 0; count < 8;count ++) { + hVECT1[count + 8] = CreateWindowEx(WS_EX_CLIENTEDGE,"EDIT","", WS_CHILD | + ES_READONLY | WS_BORDER | WS_TABSTOP,345,(count*28) + 52,254,19, + hDlg,0,hinstDLL, NULL ); + SendMessage(hVECT1[count + 8],WM_SETFONT, (WPARAM)GetStockObject(DEFAULT_GUI_FONT),0); + } +} + +void SetupRSP_Vect2Panel (HWND hDlg) { + int count; + + for (count = 0; count < 8;count ++) { + hVECT2[count] = CreateWindowEx(WS_EX_CLIENTEDGE,"EDIT","", WS_CHILD | + ES_READONLY | WS_BORDER | WS_TABSTOP,55,(count*28) + 52,254,19, + hDlg,0,hinstDLL, NULL ); + SendMessage(hVECT2[count],WM_SETFONT, (WPARAM)GetStockObject(DEFAULT_GUI_FONT),0); + } + for (count = 0; count < 8;count ++) { + hVECT2[count + 8] = CreateWindowEx(WS_EX_CLIENTEDGE,"EDIT","", WS_CHILD | + ES_READONLY | WS_BORDER | WS_TABSTOP,345,(count*28) + 52,254,19, + hDlg,0,hinstDLL, NULL ); + SendMessage(hVECT2[count + 8],WM_SETFONT, (WPARAM)GetStockObject(DEFAULT_GUI_FONT),0); + } +} + +void ShowRSP_RegisterPanel ( int Panel) { + int count; + + switch( Panel ) { + case GeneralPurpose: + for (count = 0; count < 32;count ++) { ShowWindow(hGPR[count], TRUE ); } + break; + case ControlProcessor0: + for (count = 0; count < 16;count ++) { ShowWindow(hCP0[count], TRUE ); } + break; + case HiddenRegisters: + for (count = 0; count < 12;count ++) { ShowWindow(hHIDDEN[count], TRUE ); } + break; + case Vector1: + for (count = 0; count < 16;count ++) { ShowWindow(hVECT1[count], TRUE ); } + break; + case Vector2: + for (count = 0; count < 16;count ++) { ShowWindow(hVECT2[count], TRUE ); } + break; + } +} + +void UpdateRSPRegistersScreen ( void ) { + char RegisterValue[100]; + int count, nSel; + TC_ITEM item; + + if (!InRSPRegisterWindow) { return; } + nSel = TabCtrl_GetCurSel( hTab ); + if ( nSel > -1 ) { + item.mask = TCIF_PARAM; + TabCtrl_GetItem( hTab, nSel, &item ); + switch( item.lParam ) { + case GeneralPurpose: + for (count = 0; count < 32;count ++) { + sprintf(RegisterValue," 0x%08X",RSP_GPR[count].UW); + SetWindowText(hGPR[count],RegisterValue); + } + break; + case ControlProcessor0: + if (RSPInfo.SP_MEM_ADDR_REG) + { + sprintf(RegisterValue," 0x%08X",*RSPInfo.SP_MEM_ADDR_REG); + SetWindowText(hCP0[0],RegisterValue); + sprintf(RegisterValue," 0x%08X",*RSPInfo.SP_DRAM_ADDR_REG); + SetWindowText(hCP0[1],RegisterValue); + sprintf(RegisterValue," 0x%08X",*RSPInfo.SP_RD_LEN_REG); + SetWindowText(hCP0[2],RegisterValue); + sprintf(RegisterValue," 0x%08X",*RSPInfo.SP_WR_LEN_REG); + SetWindowText(hCP0[3],RegisterValue); + sprintf(RegisterValue," 0x%08X",*RSPInfo.SP_STATUS_REG); + SetWindowText(hCP0[4],RegisterValue); + sprintf(RegisterValue," 0x%08X",*RSPInfo.SP_DMA_FULL_REG); + SetWindowText(hCP0[5],RegisterValue); + sprintf(RegisterValue," 0x%08X",*RSPInfo.SP_DMA_BUSY_REG); + SetWindowText(hCP0[6],RegisterValue); + sprintf(RegisterValue," 0x%08X",*RSPInfo.SP_SEMAPHORE_REG); + SetWindowText(hCP0[7],RegisterValue); + sprintf(RegisterValue," 0x%08X",*RSPInfo.DPC_START_REG); + SetWindowText(hCP0[8],RegisterValue); + sprintf(RegisterValue," 0x%08X",*RSPInfo.DPC_END_REG); + SetWindowText(hCP0[9],RegisterValue); + sprintf(RegisterValue," 0x%08X",*RSPInfo.DPC_CURRENT_REG); + SetWindowText(hCP0[10],RegisterValue); + sprintf(RegisterValue," 0x%08X",*RSPInfo.DPC_STATUS_REG); + SetWindowText(hCP0[11],RegisterValue); + sprintf(RegisterValue," 0x%08X",*RSPInfo.DPC_CLOCK_REG); + SetWindowText(hCP0[12],RegisterValue); + sprintf(RegisterValue," 0x%08X",*RSPInfo.DPC_BUFBUSY_REG); + SetWindowText(hCP0[13],RegisterValue); + sprintf(RegisterValue," 0x%08X",*RSPInfo.DPC_PIPEBUSY_REG); + SetWindowText(hCP0[14],RegisterValue); + sprintf(RegisterValue," 0x%08X",*RSPInfo.DPC_TMEM_REG); + SetWindowText(hCP0[15],RegisterValue); + } + break; + case HiddenRegisters: + for (count = 0; count < 8;count ++) { + sprintf(RegisterValue," 0x%08X - %08X",RSP_ACCUM[count].W[1], RSP_ACCUM[count].W[0]); + SetWindowText(hHIDDEN[count],RegisterValue); + } + for (count = 0; count < 3;count ++) { + sprintf(RegisterValue," 0x%04X",RSP_Flags[count].UHW[0]); + SetWindowText(hHIDDEN[count + 8],RegisterValue); + } + sprintf(RegisterValue," 0x%04X",RSP_Flags[2].UHW[0]); + SetWindowText(hHIDDEN[11],RegisterValue); + break; + case Vector1: + for (count = 0; count < 16;count ++) { + sprintf(RegisterValue," 0x%08X - %08X - %08X - %08X", RSP_Vect[count].W[3], + RSP_Vect[count].W[2], RSP_Vect[count].W[1], RSP_Vect[count].W[0]); + SetWindowText(hVECT1[count],RegisterValue); + } + break; + case Vector2: + for (count = 0; count < 16;count ++) { + sprintf(RegisterValue," 0x%08X - %08X - %08X - %08X", RSP_Vect[count + 16].W[3], + RSP_Vect[count + 16].W[2], RSP_Vect[count + 16].W[1], RSP_Vect[count + 16].W[0]); + SetWindowText(hVECT2[count],RegisterValue); + } + break; + } + } +} diff --git a/Source/RSP/RSP Registers.h b/Source/RSP/RSP Registers.h new file mode 100644 index 000000000..cc2ad6181 --- /dev/null +++ b/Source/RSP/RSP Registers.h @@ -0,0 +1,151 @@ +/* + * RSP Compiler plug in for Project 64 (A Nintendo 64 emulator). + * + * (c) Copyright 2001 jabo (jabo@emulation64.com) and + * zilmar (zilmar@emulation64.com) + * + * pj64 homepage: www.pj64.net + * + * Permission to use, copy, modify and distribute Project64 in both binary and + * source form, for non-commercial purposes, is hereby granted without fee, + * providing that this license information and copyright notice appear with + * all copies and any derived work. + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event shall the authors be held liable for any damages + * arising from the use of this software. + * + * Project64 is freeware for PERSONAL USE only. Commercial users should + * seek permission of the copyright holders first. Commercial use includes + * charging money for Project64 or software derived from Project64. + * + * The copyright holders request that bug fixes and improvements to the code + * should be forwarded to them so if they want them. + * + */ + +#include "types.h" + +#define SP_STATUS_HALT 0x001 /* Bit 0: halt */ +#define SP_STATUS_BROKE 0x002 /* Bit 1: broke */ +#define SP_STATUS_DMA_BUSY 0x004 /* Bit 2: dma busy */ +#define SP_STATUS_DMA_FULL 0x008 /* Bit 3: dma full */ +#define SP_STATUS_IO_FULL 0x010 /* Bit 4: io full */ +#define SP_STATUS_SSTEP 0x020 /* Bit 5: single step */ +#define SP_STATUS_INTR_BREAK 0x040 /* Bit 6: interrupt on break */ +#define SP_STATUS_SIG0 0x080 /* Bit 7: signal 0 set */ +#define SP_STATUS_SIG1 0x100 /* Bit 8: signal 1 set */ +#define SP_STATUS_SIG2 0x200 /* Bit 9: signal 2 set */ +#define SP_STATUS_SIG3 0x400 /* Bit 10: signal 3 set */ +#define SP_STATUS_SIG4 0x800 /* Bit 11: signal 4 set */ +#define SP_STATUS_SIG5 0x1000 /* Bit 12: signal 5 set */ +#define SP_STATUS_SIG6 0x2000 /* Bit 13: signal 6 set */ +#define SP_STATUS_SIG7 0x4000 /* Bit 14: signal 7 set */ + +#define SP_CLR_HALT 0x00001 /* Bit 0: clear halt */ +#define SP_SET_HALT 0x00002 /* Bit 1: set halt */ +#define SP_CLR_BROKE 0x00004 /* Bit 2: clear broke */ +#define SP_CLR_INTR 0x00008 /* Bit 3: clear intr */ +#define SP_SET_INTR 0x00010 /* Bit 4: set intr */ +#define SP_CLR_SSTEP 0x00020 /* Bit 5: clear sstep */ +#define SP_SET_SSTEP 0x00040 /* Bit 6: set sstep */ +#define SP_CLR_INTR_BREAK 0x00080 /* Bit 7: clear intr on break */ +#define SP_SET_INTR_BREAK 0x00100 /* Bit 8: set intr on break */ +#define SP_CLR_SIG0 0x00200 /* Bit 9: clear signal 0 */ +#define SP_SET_SIG0 0x00400 /* Bit 10: set signal 0 */ +#define SP_CLR_SIG1 0x00800 /* Bit 11: clear signal 1 */ +#define SP_SET_SIG1 0x01000 /* Bit 12: set signal 1 */ +#define SP_CLR_SIG2 0x02000 /* Bit 13: clear signal 2 */ +#define SP_SET_SIG2 0x04000 /* Bit 14: set signal 2 */ +#define SP_CLR_SIG3 0x08000 /* Bit 15: clear signal 3 */ +#define SP_SET_SIG3 0x10000 /* Bit 16: set signal 3 */ +#define SP_CLR_SIG4 0x20000 /* Bit 17: clear signal 4 */ +#define SP_SET_SIG4 0x40000 /* Bit 18: set signal 4 */ +#define SP_CLR_SIG5 0x80000 /* Bit 19: clear signal 5 */ +#define SP_SET_SIG5 0x100000 /* Bit 20: set signal 5 */ +#define SP_CLR_SIG6 0x200000 /* Bit 21: clear signal 6 */ +#define SP_SET_SIG6 0x400000 /* Bit 22: set signal 6 */ +#define SP_CLR_SIG7 0x800000 /* Bit 23: clear signal 7 */ +#define SP_SET_SIG7 0x1000000 /* Bit 24: set signal 7 */ + +#define DPC_CLR_XBUS_DMEM_DMA 0x0001 /* Bit 0: clear xbus_dmem_dma */ +#define DPC_SET_XBUS_DMEM_DMA 0x0002 /* Bit 1: set xbus_dmem_dma */ +#define DPC_CLR_FREEZE 0x0004 /* Bit 2: clear freeze */ +#define DPC_SET_FREEZE 0x0008 /* Bit 3: set freeze */ +#define DPC_CLR_FLUSH 0x0010 /* Bit 4: clear flush */ +#define DPC_SET_FLUSH 0x0020 /* Bit 5: set flush */ +#define DPC_CLR_TMEM_CTR 0x0040 /* Bit 6: clear tmem ctr */ +#define DPC_CLR_PIPE_CTR 0x0080 /* Bit 7: clear pipe ctr */ +#define DPC_CLR_CMD_CTR 0x0100 /* Bit 8: clear cmd ctr */ +#define DPC_CLR_CLOCK_CTR 0x0200 /* Bit 9: clear clock ctr */ + +#define DPC_STATUS_XBUS_DMEM_DMA 0x001 /* Bit 0: xbus_dmem_dma */ +#define DPC_STATUS_FREEZE 0x002 /* Bit 1: freeze */ +#define DPC_STATUS_FLUSH 0x004 /* Bit 2: flush */ +#define DPC_STATUS_START_GCLK 0x008 /* Bit 3: start gclk */ +#define DPC_STATUS_TMEM_BUSY 0x010 /* Bit 4: tmem busy */ +#define DPC_STATUS_PIPE_BUSY 0x020 /* Bit 5: pipe busy */ +#define DPC_STATUS_CMD_BUSY 0x040 /* Bit 6: cmd busy */ +#define DPC_STATUS_CBUF_READY 0x080 /* Bit 7: cbuf ready */ +#define DPC_STATUS_DMA_BUSY 0x100 /* Bit 8: dma busy */ +#define DPC_STATUS_END_VALID 0x200 /* Bit 9: end valid */ +#define DPC_STATUS_START_VALID 0x400 /* Bit 10: start valid */ + +#define R4300i_SP_Intr 0x1 + +extern char * x86_Strings[8]; +extern char * GPR_Strings[32]; + +#define x86_Name(Reg) (x86_Strings[(Reg)]) +#define GPR_Name(Reg) (GPR_Strings[(Reg)]) + +/* +#define GPR_Name(Reg)\ + (Reg) == 0 ? "R0" : (Reg) == 1 ? "AT" : (Reg) == 2 ? "V0" : (Reg) == 3 ? "V1" :\ + (Reg) == 4 ? "A0" : (Reg) == 5 ? "A1" : (Reg) == 6 ? "A2" : (Reg) == 7 ? "A3" :\ + (Reg) == 8 ? "T0" : (Reg) == 9 ? "T1" : (Reg) == 10 ? "T2" : (Reg) == 11 ? "T3" :\ + (Reg) == 12 ? "T4" : (Reg) == 13 ? "T5" : (Reg) == 14 ? "T6" : (Reg) == 15 ? "T7" :\ + (Reg) == 16 ? "S0" : (Reg) == 17 ? "S1" : (Reg) == 18 ? "S2" : (Reg) == 19 ? "S3" :\ + (Reg) == 20 ? "S4" : (Reg) == 21 ? "S5" : (Reg) == 22 ? "S6" : (Reg) == 23 ? "S7" :\ + (Reg) == 24 ? "T8" : (Reg) == 25 ? "T9" : (Reg) == 26 ? "K0" : (Reg) == 27 ? "K1" :\ + (Reg) == 28 ? "GP" : (Reg) == 29 ? "SP" : (Reg) == 30 ? "S8" :\ + (Reg) == 31 ? "RA" : "Unknown Register" +*/ + +#define COP0_Name(Reg)\ + (Reg) == 0 ? "SP memory address" :\ + (Reg) == 1 ? "SP DRAM DMA address" :\ + (Reg) == 2 ? "SP read DMA length" :\ + (Reg) == 3 ? "SP write DMA length" :\ + (Reg) == 4 ? "SP status" :\ + (Reg) == 5 ? "SP DMA full" :\ + (Reg) == 6 ? "SP DMA busy" :\ + (Reg) == 7 ? "SP semaphore" :\ + (Reg) == 8 ? "DP CMD DMA start" :\ + (Reg) == 9 ? "DP CMD DMA end" :\ + (Reg) == 10 ? "DP CMD DMA current" :\ + (Reg) == 11 ? "DP CMD status" :\ + (Reg) == 12 ? "DP clock counter" :\ + (Reg) == 13 ? "DP buffer busy counter" :\ + (Reg) == 14 ? "DP pipe busy counter" :\ + (Reg) == 15 ? "DP TMEM load counter" :\ + "Unknown Register" + +#define ElementSpecifier(Elem)\ + (Elem) == 0 ? "" : (Elem) == 1 ? "" : (Elem) == 2 ? " [0q]" :\ + (Elem) == 3 ? " [1q]" : (Elem) == 4 ? " [0h]" : (Elem) == 5 ? " [1h]" :\ + (Elem) == 6 ? " [2h]" : (Elem) == 7 ? " [3h]" : (Elem) == 8 ? " [0]" :\ + (Elem) == 9 ? " [1]" : (Elem) == 10 ? " [2]" : (Elem) == 11 ? " [3]" :\ + (Elem) == 12 ? " [4]" : (Elem) == 13 ? " [5]" : (Elem) == 14 ? " [6]" :\ + (Elem) == 15 ? " [7]" : "Unknown Element" + +void Enter_RSP_Register_Window ( void ); +void InitilizeRSPRegisters (void); +void UpdateRSPRegistersScreen ( void ); + +/*** RSP Registers ***/ +extern UWORD32 RSP_GPR[32], RSP_Flags[4]; +extern UDWORD RSP_ACCUM[8]; +extern VECTOR RSP_Vect[32]; + + diff --git a/Source/RSP/RSP.dsp b/Source/RSP/RSP.dsp new file mode 100644 index 000000000..8b7962866 --- /dev/null +++ b/Source/RSP/RSP.dsp @@ -0,0 +1,291 @@ +# Microsoft Developer Studio Project File - Name="RSP" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 + +CFG=RSP - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "RSP.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "RSP.mak" CFG="RSP - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "RSP - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "RSP - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "RSP - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "../../Build/RSP/Release" +# PROP Intermediate_Dir "../../Build/RSP/Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "RSP_EXPORTS" /YX /FD /c +# ADD CPP /nologo /MD /W3 /GX /O2 /I "../" /I "./" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "RSP_EXPORTS" /YX /FD /c +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0xc09 /d "NDEBUG" +# ADD RSC /l 0xc09 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 /out:"../../Bin/Release/RSP 1.7.dll" + +!ELSEIF "$(CFG)" == "RSP - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "../../Build/RSP/Debug" +# PROP Intermediate_Dir "../../Build/RSP/Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "RSP_EXPORTS" /YX /FD /GZ /c +# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "../" /I "./" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "RSP_EXPORTS" /YX /FD /GZ /c +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0xc09 /d "_DEBUG" +# ADD RSC /l 0xc09 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /out:"../../Bin/Debug/RSP 1.7.dll" /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "RSP - Win32 Release" +# Name "RSP - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Group "RSP Source Files" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\breakpoint.c +# End Source File +# Begin Source File + +SOURCE=.\Cpu.c +# End Source File +# Begin Source File + +SOURCE=.\dma.c +# End Source File +# Begin Source File + +SOURCE=".\Interpreter CPU.c" +# End Source File +# Begin Source File + +SOURCE=".\Interpreter Ops.c" +# End Source File +# Begin Source File + +SOURCE=.\log.cpp +# End Source File +# Begin Source File + +SOURCE=.\memory.c +# End Source File +# Begin Source File + +SOURCE=.\Mmx.c +# End Source File +# Begin Source File + +SOURCE=.\Profiling.cpp +# End Source File +# Begin Source File + +SOURCE=".\Recompiler Analysis.c" +# End Source File +# Begin Source File + +SOURCE=".\Recompiler CPU.c" +# End Source File +# Begin Source File + +SOURCE=".\Recompiler Ops.c" +# End Source File +# Begin Source File + +SOURCE=".\Recompiler Sections.c" +# End Source File +# Begin Source File + +SOURCE=".\RSP Command.c" +# End Source File +# Begin Source File + +SOURCE=".\RSP Register.c" +# End Source File +# Begin Source File + +SOURCE=.\RSP.rc +# End Source File +# Begin Source File + +SOURCE=.\Sse.c +# End Source File +# Begin Source File + +SOURCE=.\X86.c +# End Source File +# End Group +# Begin Source File + +SOURCE=.\Main.cpp +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Group "RSP Header Files" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\breakpoint.h +# End Source File +# Begin Source File + +SOURCE=.\Cpu.h +# End Source File +# Begin Source File + +SOURCE=.\dma.h +# End Source File +# Begin Source File + +SOURCE=".\Interpreter CPU.h" +# End Source File +# Begin Source File + +SOURCE=".\Interpreter Ops.h" +# End Source File +# Begin Source File + +SOURCE=.\log.h +# End Source File +# Begin Source File + +SOURCE=.\memory.h +# End Source File +# Begin Source File + +SOURCE=.\OpCode.h +# End Source File +# Begin Source File + +SOURCE=.\Profiling.h +# End Source File +# Begin Source File + +SOURCE=".\Recompiler CPU.h" +# End Source File +# Begin Source File + +SOURCE=".\Recompiler Ops.h" +# End Source File +# Begin Source File + +SOURCE=.\resource.h +# End Source File +# Begin Source File + +SOURCE=".\RSP Command.h" +# End Source File +# Begin Source File + +SOURCE=".\RSP Registers.h" +# End Source File +# Begin Source File + +SOURCE=.\Rsp.h +# End Source File +# Begin Source File + +SOURCE=.\Types.h +# End Source File +# Begin Source File + +SOURCE=.\X86.h +# End Source File +# End Group +# Begin Group "Support Headers" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\Support\CriticalSection.h +# End Source File +# Begin Source File + +SOURCE=".\Support\Ini File Class.h" +# End Source File +# Begin Source File + +SOURCE=".\Support\Log Class.h" +# End Source File +# Begin Source File + +SOURCE=.\Support\md5.h +# End Source File +# Begin Source File + +SOURCE=".\Support\std string.h" +# End Source File +# Begin Source File + +SOURCE=.\Support\Support.h +# End Source File +# Begin Source File + +SOURCE=.\Support\Version.h +# End Source File +# Begin Source File + +SOURCE=.\Support\XString.h +# End Source File +# End Group +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/Source/RSP/RSP.rc b/Source/RSP/RSP.rc new file mode 100644 index 000000000..863afe7da --- /dev/null +++ b/Source/RSP/RSP.rc @@ -0,0 +1,269 @@ +//Microsoft Developer Studio generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "afxres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (Australia) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENA) +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_AUS +#pragma code_page(1252) +#endif //_WIN32 + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +RSPCOMMAND DIALOG DISCARDABLE 0, 0, 187, 94 +STYLE DS_MODALFRAME | WS_MAXIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU +FONT 8, "MS Sans Serif" +BEGIN +END + +RSPREGISTERS DIALOG DISCARDABLE 0, 0, 186, 95 +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Dialog" +FONT 8, "MS Sans Serif" +BEGIN +END + +RSPCOMPILER DIALOGEX 0, 0, 226, 135 +STYLE DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "RSP Compiler" +FONT 8, "MS Sans Serif" +BEGIN + PUSHBUTTON "OK",IDOK,109,113,50,14 + PUSHBUTTON "Cancel",IDCANCEL,161,113,50,14 + CONTROL "SSE",IDC_CHECK_SSE,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,127,74,30,10 + CONTROL "MMX",IDC_CHECK_MMX,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,127,46,33,10 + CONTROL "MMX ²",IDC_CHECK_MMX2,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,127,60,37,10 + CONTROL "Vector Dest Analysis",IDC_COMPILER_DEST,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,22,18,81,10 + CONTROL "Accumulator Analysis",IDC_COMPILER_ACCUM,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,22,32,83,10 + CONTROL "Flag Analysis",IDC_COMPILER_FLAGS,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,22,46,57,10 + CONTROL "Instruction Re-ordering",IDC_COMPILER_REORDER,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,22,74,87,10 + CONTROL "Microcode sections",IDC_COMPILER_SECTIONS,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,127,88,77,10 + CONTROL "GPR Mem Aligned",IDC_COMPILER_ALIGNGPR,"Button", + BS_AUTOCHECKBOX | WS_DISABLED | WS_TABSTOP,127,18,74,10 + CONTROL "VEC Mem Aligned",IDC_COMPILER_ALIGNVEC,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,127,32,73,10 + GROUPBOX "",IDC_STATIC,7,3,209,104 + CONTROL "GPR Constant Analysis",IDC_COMPILER_GPRCONSTANTS,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,22,60,89,10 + CTEXT "x86: 0.00 KB / 0.00 KB",IDC_COMPILER_BUFFERS,21,89,91, + 11,SS_CENTERIMAGE,WS_EX_CLIENTEDGE +END + +RSPCONFIG DIALOG DISCARDABLE 0, 0, 179, 138 +STYLE DS_MODALFRAME | DS_SETFOREGROUND | DS_CENTER | WS_POPUP | WS_CAPTION | + WS_SYSMENU +CAPTION "Configure RSP" +FONT 8, "MS Sans Serif" +BEGIN + PUSHBUTTON "OK",IDOK,38,116,50,14 + PUSHBUTTON "Cancel",IDCANCEL,90,116,50,14 + CONTROL "send Audio Lists to Audio Plugin",IDC_AUDIOHLE,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,22,42,117,10 + CTEXT "disables RSP emulation for the following lists, allows plugins to process them instead", + IDC_STATIC,13,15,155,20 + GROUPBOX "",IDC_STATIC,7,3,165,69 + CONTROL "send Display Lists to Graphics Plugin",IDC_GRAPHICSHLE, + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,22,55,131,10 + GROUPBOX "",IDC_STATIC,7,73,166,34 + LTEXT "CPU core style:",IDC_STATIC,18,88,50,8 + COMBOBOX IDC_COMPILER_SELECT,83,86,78,39,CBS_DROPDOWNLIST | + WS_TABSTOP +END + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO MOVEABLE PURE +BEGIN + "RSPCOMMAND", DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 180 + TOPMARGIN, 7 + BOTTOMMARGIN, 87 + END + + "RSPREGISTERS", DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 179 + TOPMARGIN, 7 + BOTTOMMARGIN, 88 + END + + "RSPCOMPILER", DIALOG + BEGIN + LEFTMARGIN, 6 + RIGHTMARGIN, 217 + TOPMARGIN, 7 + BOTTOMMARGIN, 127 + END + + "RSPCONFIG", DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 172 + TOPMARGIN, 7 + BOTTOMMARGIN, 131 + END +END +#endif // APSTUDIO_INVOKED + + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE MOVEABLE PURE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE MOVEABLE PURE +BEGIN + "#include ""afxres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE MOVEABLE PURE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Menu +// + +RspMenu MENU DISCARDABLE +BEGIN + MENUITEM "RSP &Commands...", ID_RSPCOMMANDS + MENUITEM "RSP &Registers...", ID_RSPREGISTERS + MENUITEM "RSP Com&piler...", ID_COMPILER + MENUITEM SEPARATOR + POPUP "CPU Method" + BEGIN + MENUITEM "Recompiler", ID_CPUMETHOD_RECOMPILER + MENUITEM "Interpreter", ID_CPUMETHOD_INTERPT + END + MENUITEM SEPARATOR + POPUP "Pro&filing" + BEGIN + MENUITEM "&On", ID_PROFILING_ON + MENUITEM "O&ff", ID_PROFILING_OFF + MENUITEM SEPARATOR + MENUITEM "Reset Stats", ID_PROFILING_RESETSTATS + MENUITEM "Generate Log", ID_PROFILING_GENERATELOG + MENUITEM SEPARATOR + MENUITEM "Log Individual Blocks", ID_PROFILING_LOGINDIVIDUALBLOCKS + + END + POPUP "Dump" + BEGIN + MENUITEM "&RSP code", ID_DUMP_RSPCODE + MENUITEM "DMEM", ID_DUMP_DMEM + END + POPUP "Settings" + BEGIN + MENUITEM "Show Compiler Errors", ID_SHOWCOMPILERERRORS + MENUITEM "Break on start of task", ID_BREAKONSTARTOFTASK + MENUITEM "Log RDP Commands", ID_LOGRDPCOMMANDS + MENUITEM "Log X86 code", ID_SETTINGS_LOGX86CODE + END +END + + +#ifndef _MAC +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 1,7,0,2 + PRODUCTVERSION 1,7,0,2 + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x40004L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "0c0904b0" + BEGIN + VALUE "Comments", "\0" + VALUE "CompanyName", "Project64\0" + VALUE "FileDescription", "RSP emulation Plugin\0" + VALUE "FileVersion", "1, 7, 0, 2\0" + VALUE "InternalName", "RSP Plugin\0" + VALUE "LegalCopyright", "Copyright © 2006\0" + VALUE "LegalTrademarks", "\0" + VALUE "OriginalFilename", "RSP.dll\0" + VALUE "PrivateBuild", "\0" + VALUE "ProductName", " RSP\0" + VALUE "ProductVersion", "1, 7, 0, 2\0" + VALUE "SpecialBuild", "\0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0xc09, 1200 + END +END + +#endif // !_MAC + +#endif // English (Australia) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/Source/RSP/Recompiler Analysis.c b/Source/RSP/Recompiler Analysis.c new file mode 100644 index 000000000..3ba9a32ca --- /dev/null +++ b/Source/RSP/Recompiler Analysis.c @@ -0,0 +1,1796 @@ +/* + * RSP Compiler plug in for Project 64 (A Nintendo 64 emulator). + * + * (c) Copyright 2001 jabo (jabo@emulation64.com) and + * zilmar (zilmar@emulation64.com) + * + * pj64 homepage: www.pj64.net + * + * Permission to use, copy, modify and distribute Project64 in both binary and + * source form, for non-commercial purposes, is hereby granted without fee, + * providing that this license information and copyright notice appear with + * all copies and any derived work. + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event shall the authors be held liable for any damages + * arising from the use of this software. + * + * Project64 is freeware for PERSONAL USE only. Commercial users should + * seek permission of the copyright holders first. Commercial use includes + * charging money for Project64 or software derived from Project64. + * + * The copyright holders request that bug fixes and improvements to the code + * should be forwarded to them so if they want them. + * + */ + +#include +#include "rsp.h" +#include "CPU.h" +#include "Recompiler CPU.h" +#include "RSP Command.h" +#include "memory.h" +#include "opcode.h" +#include "log.h" + +/************************************************************ +** IsOpcodeNop +** +** Output: BOOLean whether opcode at PC is a NOP +** Input: PC +*************************************************************/ + +BOOL IsOpcodeNop(DWORD PC) { + OPCODE RspOp; + RSP_LW_IMEM(PC, &RspOp.Hex); + + if (RspOp.op == RSP_SPECIAL && RspOp.funct == RSP_SPECIAL_SLL) { + return (RspOp.rd == 0) ? TRUE : FALSE; + } + + return FALSE; +} + +/************************************************************ +** IsNextInstructionMmx +** +** Output: determines EMMS status +** Input: PC +*************************************************************/ + +BOOL IsNextInstructionMmx(DWORD PC) { + OPCODE RspOp; + + if (IsMmxEnabled == FALSE) + return FALSE; + + PC += 4; + if (PC >= 0x1000) return FALSE; + RSP_LW_IMEM(PC, &RspOp.Hex); + + if (RspOp.op != RSP_CP2) + return FALSE; + + if ((RspOp.rs & 0x10) != 0) { + switch (RspOp.funct) { + case RSP_VECTOR_VMULF: + case RSP_VECTOR_VMUDL: /* Warning: Not all handled? */ + case RSP_VECTOR_VMUDM: + case RSP_VECTOR_VMUDN: + case RSP_VECTOR_VMUDH: + if (TRUE == WriteToAccum(7, PC)) { + return FALSE; + } else if ((RspOp.rs & 0x0f) >= 2 && (RspOp.rs & 0x0f) <= 7 && IsMmx2Enabled == FALSE) { + return FALSE; + } else + return TRUE; + + case RSP_VECTOR_VAND: + case RSP_VECTOR_VOR: + case RSP_VECTOR_VXOR: + if (TRUE == WriteToAccum(Low16BitAccum, PC)) { + return FALSE; + } else if ((RspOp.rs & 0x0f) >= 2 && (RspOp.rs & 0x0f) <= 7 && IsMmx2Enabled == FALSE) { + return FALSE; + } else + return TRUE; + + case RSP_VECTOR_VADD: + /* Requires no accumulator write! & No flags! */ + if (WriteToAccum(Low16BitAccum, CompilePC) == TRUE) { + return FALSE; + } else if (UseRspFlags(CompilePC) == TRUE) { + return FALSE; + } else if ((RspOp.rs & 0x0f) >= 2 && (RspOp.rs & 0x0f) <= 7 && IsMmx2Enabled == FALSE) { + return FALSE; + } else + return TRUE; + + default: + return FALSE; + } + } else + return FALSE; +} + +/************************************************************ +** WriteToAccum2 +** +** Output: +** TRUE: Accumulation series +** FALSE: Accumulator is reset after this op +** +** Input: PC, Location in accumulator +*************************************************************/ + +#define HIT_BRANCH 0x2 + +DWORD WriteToAccum2 (int Location, int PC, BOOL RecursiveCall) { + OPCODE RspOp; + DWORD BranchTarget = 0; + signed int BranchImmed = 0; + DWORD JumpTarget = 0; + int Instruction_State = NextInstruction; + + if (Compiler.bAccum == FALSE) return TRUE; + + if (Instruction_State == DELAY_SLOT) { + return TRUE; + } + + do { + PC += 4; + if (PC >= 0x1000) { return TRUE; } + RSP_LW_IMEM(PC, &RspOp.Hex); + + switch (RspOp.op) { + case RSP_REGIMM: + switch (RspOp.rt) { + case RSP_REGIMM_BLTZ: + case RSP_REGIMM_BGEZ: + case RSP_REGIMM_BLTZAL: + case RSP_REGIMM_BGEZAL: + Instruction_State = DO_DELAY_SLOT; + break; + default: + CompilerWarning("Unkown opcode in WriteToAccum\n%s",RSPOpcodeName(RspOp.Hex,PC)); + return TRUE; + } + break; + case RSP_SPECIAL: + switch (RspOp.funct) { + case RSP_SPECIAL_SLL: + case RSP_SPECIAL_SRL: + case RSP_SPECIAL_SRA: + case RSP_SPECIAL_SLLV: + case RSP_SPECIAL_SRLV: + case RSP_SPECIAL_SRAV: + case RSP_SPECIAL_ADD: + case RSP_SPECIAL_ADDU: + case RSP_SPECIAL_SUB: + case RSP_SPECIAL_SUBU: + case RSP_SPECIAL_AND: + case RSP_SPECIAL_OR: + case RSP_SPECIAL_XOR: + case RSP_SPECIAL_NOR: + case RSP_SPECIAL_SLT: + case RSP_SPECIAL_SLTU: + case RSP_SPECIAL_BREAK: + break; + + case RSP_SPECIAL_JR: + Instruction_State = DO_DELAY_SLOT; + break; + + default: + CompilerWarning("Unkown opcode in WriteToAccum\n%s",RSPOpcodeName(RspOp.Hex,PC)); + return TRUE; + } + break; + case RSP_J: + /* there is no way a loopback is going to use accumulator */ + if (Compiler.bAudioUcode && (RspOp.target << 2) < PC) { + return FALSE; + } + /* rarely occurs let them have their way */ + return TRUE; + + case RSP_JAL: + /* there is no way calling a subroutine is going to use accum */ + /* or come back and continue an existing calculation */ + return (Compiler.bAudioUcode) ? FALSE : TRUE; + + case RSP_BEQ: + case RSP_BNE: + case RSP_BLEZ: + case RSP_BGTZ: + BranchImmed = (short)RspOp.offset; + if (Compiler.bAudioUcode) { + OPCODE NextOp; + + /* ignore backward branches and pretend its a nop */ + if (BranchImmed <= 0) { + break; + } + /* if the opcode 8 bytes before the dest is a J backward than ignore this */ + BranchImmed = (PC + ((short)RspOp.offset << 2) + 4) & 0xFFC; + RSP_LW_IMEM(BranchImmed - 8, &NextOp.Hex); + if (RspOp.op == RSP_J && (RspOp.target << 2) < PC) { + break; + } + } + BranchTarget = (PC + ((short)RspOp.offset << 2) + 4) & 0xFFC; + Instruction_State = DO_DELAY_SLOT; + break; + case RSP_ADDI: + case RSP_ADDIU: + case RSP_SLTI: + case RSP_SLTIU: + case RSP_ANDI: + case RSP_ORI: + case RSP_XORI: + case RSP_LUI: + case RSP_CP0: + break; + + case RSP_CP2: + if ((RspOp.rs & 0x10) != 0) { + switch (RspOp.funct) { + case RSP_VECTOR_VMULF: + case RSP_VECTOR_VMUDL: + case RSP_VECTOR_VMUDM: + case RSP_VECTOR_VMUDN: + case RSP_VECTOR_VMUDH: + return FALSE; + case RSP_VECTOR_VMACF: + case RSP_VECTOR_VMADL: + case RSP_VECTOR_VMADM: + case RSP_VECTOR_VMADN: + case RSP_VECTOR_VMADH: + return TRUE; + case RSP_VECTOR_VABS: + case RSP_VECTOR_VADD: + case RSP_VECTOR_VADDC: + case RSP_VECTOR_VSUB: + case RSP_VECTOR_VSUBC: + case RSP_VECTOR_VAND: + case RSP_VECTOR_VOR: + case RSP_VECTOR_VXOR: + case RSP_VECTOR_VNXOR: + /* since these modify the accumulator lower-16 bits we can */ + /* safely assume these 'reset' the accumulator no matter what */ + return FALSE; + case RSP_VECTOR_VCR: + case RSP_VECTOR_VCH: + case RSP_VECTOR_VCL: + case RSP_VECTOR_VRCP: + case RSP_VECTOR_VRCPL: + case RSP_VECTOR_VRCPH: + case RSP_VECTOR_VRSQL: + case RSP_VECTOR_VRSQH: + case RSP_VECTOR_VLT: + case RSP_VECTOR_VEQ: + case RSP_VECTOR_VGE: + if (Location == Low16BitAccum) { return FALSE; } + break; + + case RSP_VECTOR_VMOV: + case RSP_VECTOR_VMRG: + break; + case RSP_VECTOR_VSAW: + return TRUE; + default: + CompilerWarning("Unkown opcode in WriteToVectorDest\n%s",RSPOpcodeName(RspOp.Hex,PC)); + return TRUE; + } + } else { + switch (RspOp.rs) { + case RSP_COP2_CF: + case RSP_COP2_CT: + case RSP_COP2_MT: + case RSP_COP2_MF: + break; + default: + CompilerWarning("Unkown opcode in WriteToVectorDest\n%s",RSPOpcodeName(RspOp.Hex,PC)); + return TRUE; + } + } + break; + case RSP_LB: + case RSP_LH: + case RSP_LW: + case RSP_LBU: + case RSP_LHU: + case RSP_SB: + case RSP_SH: + case RSP_SW: + break; + case RSP_LC2: + switch (RspOp.rd) { + case RSP_LSC2_BV: + case RSP_LSC2_SV: + case RSP_LSC2_DV: + case RSP_LSC2_RV: + case RSP_LSC2_QV: + case RSP_LSC2_LV: + case RSP_LSC2_UV: + case RSP_LSC2_PV: + case RSP_LSC2_TV: + case RSP_LSC2_HV: + break; + default: + CompilerWarning("Unkown opcode in WriteToAccum\n%s",RSPOpcodeName(RspOp.Hex,PC)); + return TRUE; + } + break; + case RSP_SC2: + switch (RspOp.rd) { + case RSP_LSC2_BV: + case RSP_LSC2_SV: + case RSP_LSC2_LV: + case RSP_LSC2_DV: + case RSP_LSC2_QV: + case RSP_LSC2_RV: + case RSP_LSC2_PV: + case RSP_LSC2_UV: + case RSP_LSC2_HV: + case RSP_LSC2_FV: + case RSP_LSC2_WV: + case RSP_LSC2_TV: + break; + default: + CompilerWarning("Unkown opcode in WriteToAccum\n%s",RSPOpcodeName(RspOp.Hex,PC)); + return TRUE; + } + break; + default: + CompilerWarning("Unkown opcode in WriteToAccum\n%s",RSPOpcodeName(RspOp.Hex,PC)); + return TRUE; + } + switch (Instruction_State) { + case NORMAL: break; + case DO_DELAY_SLOT: + Instruction_State = DELAY_SLOT; + break; + case DELAY_SLOT: + Instruction_State = FINISH_BLOCK; + break; + } + } while (Instruction_State != FINISH_BLOCK); + + /* + * This is a tricky situation because most of the + * microcode does loops, so looping back and checking + * can prove effective, but it's still a branch.. + */ + + if (BranchTarget != 0 && RecursiveCall == FALSE) { + DWORD BranchTaken, BranchFall; + + /* analysis of branch taken */ + BranchTaken = WriteToAccum2(Location, BranchTarget - 4, TRUE); + /* analysis of branch as nop */ + BranchFall = WriteToAccum2(Location, PC, TRUE); + + if (BranchImmed < 0) { + if (BranchTaken != FALSE) { + /* + * took this back branch and found a place + * that needs this vector as a source + */ + return TRUE; + } else if (BranchFall == HIT_BRANCH) { + return TRUE; + } + /* otherwise this is completely valid */ + return BranchFall; + } else { + if (BranchFall != FALSE) { + /* + * took this forward branch and found a place + * that needs this vector as a source + */ + return TRUE; + } else if (BranchTaken == HIT_BRANCH) { + return TRUE; + } + /* otherwise this is completely valid */ + return BranchTaken; + } + } + return TRUE; +} + +BOOL WriteToAccum (int Location, int PC) { + DWORD value = WriteToAccum2(Location, PC, FALSE); + + if (value == HIT_BRANCH) { + return TRUE; /* ??? */ + } else + return value; +} + +/************************************************************ +** WriteToVectorDest +** +** Output: +** TRUE: Destination is used as a source later +** FALSE: Destination is over-written later +** +** Input: PC, Register +*************************************************************/ + +BOOL WriteToVectorDest2 (DWORD DestReg, int PC, BOOL RecursiveCall) { + OPCODE RspOp; + DWORD BranchTarget = 0; + signed int BranchImmed = 0; + DWORD JumpTarget = 0; + + int Instruction_State = NextInstruction; + + if (Compiler.bDest == FALSE) return TRUE; + + if (Instruction_State == DELAY_SLOT) { + return TRUE; + } + + do { + PC += 4; + if (PC >= 0x1000) { return TRUE; } + RSP_LW_IMEM(PC, &RspOp.Hex); + + switch (RspOp.op) { + + case RSP_REGIMM: + switch (RspOp.rt) { + case RSP_REGIMM_BLTZ: + case RSP_REGIMM_BGEZ: + case RSP_REGIMM_BLTZAL: + case RSP_REGIMM_BGEZAL: + Instruction_State = DO_DELAY_SLOT; + break; + default: + CompilerWarning("Unkown opcode in WriteToVectorDest\n%s",RSPOpcodeName(RspOp.Hex,PC)); + return TRUE; + } + break; + case RSP_SPECIAL: + switch (RspOp.funct) { + case RSP_SPECIAL_SLL: + case RSP_SPECIAL_SRL: + case RSP_SPECIAL_SRA: + case RSP_SPECIAL_SLLV: + case RSP_SPECIAL_SRLV: + case RSP_SPECIAL_SRAV: + case RSP_SPECIAL_ADD: + case RSP_SPECIAL_ADDU: + case RSP_SPECIAL_SUB: + case RSP_SPECIAL_SUBU: + case RSP_SPECIAL_AND: + case RSP_SPECIAL_OR: + case RSP_SPECIAL_XOR: + case RSP_SPECIAL_NOR: + case RSP_SPECIAL_SLT: + case RSP_SPECIAL_SLTU: + case RSP_SPECIAL_BREAK: + break; + + case RSP_SPECIAL_JR: + Instruction_State = DO_DELAY_SLOT; + break; + + default: + CompilerWarning("Unkown opcode in WriteToVectorDest\n%s",RSPOpcodeName(RspOp.Hex,PC)); + return TRUE; + } + break; + case RSP_J: + /* there is no way a loopback is going to use accumulator */ + if (Compiler.bAudioUcode && (RspOp.target << 2) < PC) { + return FALSE; + } + /* rarely occurs let them have their way */ + return TRUE; + + case RSP_JAL: + /* Assume reg is being passed to function or used after the function call */ + return TRUE; + + case RSP_BEQ: + case RSP_BNE: + case RSP_BLEZ: + case RSP_BGTZ: + BranchImmed = (short)RspOp.offset; + if (Compiler.bAudioUcode) { + OPCODE NextOp; + + /* ignore backward branches and pretend its a nop */ + if (BranchImmed <= 0) { + break; + } + /* if the opcode 8 bytes before the dest is a J backward than ignore this */ + BranchImmed = (PC + ((short)RspOp.offset << 2) + 4) & 0xFFC; + RSP_LW_IMEM(BranchImmed - 8, &NextOp.Hex); + if (RspOp.op == RSP_J && (RspOp.target << 2) < PC) { + break; + } + } + BranchTarget = (PC + ((short)RspOp.offset << 2) + 4) & 0xFFC; + Instruction_State = DO_DELAY_SLOT; + break; + case RSP_ADDI: + case RSP_ADDIU: + case RSP_SLTI: + case RSP_SLTIU: + case RSP_ANDI: + case RSP_ORI: + case RSP_XORI: + case RSP_LUI: + case RSP_CP0: + break; + + case RSP_CP2: + if ((RspOp.rs & 0x10) != 0) { + switch (RspOp.funct) { + case RSP_VECTOR_VMULF: + case RSP_VECTOR_VMUDL: + case RSP_VECTOR_VMUDM: + case RSP_VECTOR_VMUDN: + case RSP_VECTOR_VMUDH: + case RSP_VECTOR_VMACF: + case RSP_VECTOR_VMADL: + case RSP_VECTOR_VMADM: + case RSP_VECTOR_VMADN: + case RSP_VECTOR_VMADH: + case RSP_VECTOR_VADD: + case RSP_VECTOR_VADDC: + case RSP_VECTOR_VSUB: + case RSP_VECTOR_VSUBC: + case RSP_VECTOR_VAND: + case RSP_VECTOR_VOR: + case RSP_VECTOR_VXOR: + case RSP_VECTOR_VNXOR: + case RSP_VECTOR_VABS: + if (DestReg == RspOp.rd) { return TRUE; } + if (DestReg == RspOp.rt) { return TRUE; } + if (DestReg == RspOp.sa) { return FALSE; } + break; + + case RSP_VECTOR_VMOV: + if (DestReg == RspOp.rt) { return TRUE; } + break; + + case RSP_VECTOR_VCR: + case RSP_VECTOR_VRCP: + case RSP_VECTOR_VRCPH: + case RSP_VECTOR_VRSQH: + case RSP_VECTOR_VCH: + case RSP_VECTOR_VCL: + return TRUE; + + case RSP_VECTOR_VMRG: + case RSP_VECTOR_VLT: + case RSP_VECTOR_VEQ: + case RSP_VECTOR_VGE: + if (DestReg == RspOp.rd) { return TRUE; } + if (DestReg == RspOp.rt) { return TRUE; } + if (DestReg == RspOp.sa) { return FALSE; } + break; + case RSP_VECTOR_VSAW: + if (DestReg == RspOp.sa) { return FALSE; } + break; + default: + CompilerWarning("Unkown opcode in WriteToVectorDest\n%s",RSPOpcodeName(RspOp.Hex,PC)); + return TRUE; + } + } else { + switch (RspOp.rs) { + case RSP_COP2_CF: + case RSP_COP2_CT: + break; + case RSP_COP2_MT: + /* if (DestReg == RspOp.rd) { return FALSE; } */ + break; + case RSP_COP2_MF: + if (DestReg == RspOp.rd) { return TRUE; } + break; + default: + CompilerWarning("Unkown opcode in WriteToVectorDest\n%s",RSPOpcodeName(RspOp.Hex,PC)); + return TRUE; + } + } + break; + case RSP_LB: + case RSP_LH: + case RSP_LW: + case RSP_LBU: + case RSP_LHU: + case RSP_SB: + case RSP_SH: + case RSP_SW: + break; + case RSP_LC2: + switch (RspOp.rd) { + case RSP_LSC2_SV: + case RSP_LSC2_DV: + case RSP_LSC2_RV: + break; + + case RSP_LSC2_HV: + case RSP_LSC2_QV: + case RSP_LSC2_BV: + case RSP_LSC2_LV: + case RSP_LSC2_UV: + case RSP_LSC2_PV: + case RSP_LSC2_TV: + break; + + default: + CompilerWarning("Unkown opcode in WriteToVectorDest\n%s",RSPOpcodeName(RspOp.Hex,PC)); + return TRUE; + } + break; + case RSP_SC2: + switch (RspOp.rd) { + case RSP_LSC2_BV: + case RSP_LSC2_SV: + case RSP_LSC2_LV: + case RSP_LSC2_DV: + case RSP_LSC2_QV: + case RSP_LSC2_RV: + case RSP_LSC2_PV: + case RSP_LSC2_UV: + case RSP_LSC2_HV: + case RSP_LSC2_FV: + case RSP_LSC2_WV: + case RSP_LSC2_TV: + if (DestReg == RspOp.rt) { return TRUE; } + break; + default: + CompilerWarning("Unkown opcode in WriteToVectorDest\n%s",RSPOpcodeName(RspOp.Hex,PC)); + return TRUE; + } + break; + default: + CompilerWarning("Unkown opcode in WriteToVectorDest\n%s",RSPOpcodeName(RspOp.Hex,PC)); + return TRUE; + } + switch (Instruction_State) { + case NORMAL: break; + case DO_DELAY_SLOT: + Instruction_State = DELAY_SLOT; + break; + case DELAY_SLOT: + Instruction_State = FINISH_BLOCK; + break; + } + } while (Instruction_State != FINISH_BLOCK); + + /* + * This is a tricky situation because most of the + * microcode does loops, so looping back and checking + * can prove effective, but it's still a branch.. + */ + + if (BranchTarget != 0 && RecursiveCall == FALSE) { + DWORD BranchTaken, BranchFall; + + /* analysis of branch taken */ + BranchTaken = WriteToVectorDest2(DestReg, BranchTarget - 4, TRUE); + /* analysis of branch as nop */ + BranchFall = WriteToVectorDest2(DestReg, PC, TRUE); + + if (BranchImmed < 0) { + if (BranchTaken != FALSE) { + /* + * took this back branch and found a place + * that needs this vector as a source + */ + return TRUE; + } else if (BranchFall == HIT_BRANCH) { + return TRUE; + } + /* otherwise this is completely valid */ + return BranchFall; + } else { + if (BranchFall != FALSE) { + /* + * took this forward branch and found a place + * that needs this vector as a source + */ + return TRUE; + } else if (BranchTaken == HIT_BRANCH) { + return TRUE; + } + /* otherwise this is completely valid */ + return BranchTaken; + } + } + + return TRUE; +} + +BOOL WriteToVectorDest (DWORD DestReg, int PC) { + DWORD value; + value = WriteToVectorDest2(DestReg, PC, FALSE); + + if (value == HIT_BRANCH) { + return TRUE; /* ??? */ + } else + return value; +} + +/************************************************************ +** UseRspFlags +** +** Output: +** TRUE: Flags are determined not in use +** FALSE: Either unable to determine or are in use +** +** Input: PC +*************************************************************/ + +/* TODO: consider delay slots and such in a branch? */ +BOOL UseRspFlags (int PC) { + OPCODE RspOp; + int Instruction_State = NextInstruction; + + if (Compiler.bFlags == FALSE) return TRUE; + + if (Instruction_State == DELAY_SLOT) { + return TRUE; + } + + do { + PC -= 4; + if (PC < 0) { return TRUE; } + RSP_LW_IMEM(PC, &RspOp.Hex); + + switch (RspOp.op) { + + case RSP_REGIMM: + switch (RspOp.rt) { + case RSP_REGIMM_BLTZ: + case RSP_REGIMM_BGEZ: + case RSP_REGIMM_BLTZAL: + case RSP_REGIMM_BGEZAL: + Instruction_State = DO_DELAY_SLOT; + break; + default: + CompilerWarning("Unkown opcode in UseRspFlags\n%s",RSPOpcodeName(RspOp.Hex,PC)); + return TRUE; + } + break; + case RSP_SPECIAL: + switch (RspOp.funct) { + case RSP_SPECIAL_SLL: + case RSP_SPECIAL_SRL: + case RSP_SPECIAL_SRA: + case RSP_SPECIAL_SLLV: + case RSP_SPECIAL_SRLV: + case RSP_SPECIAL_SRAV: + case RSP_SPECIAL_ADD: + case RSP_SPECIAL_ADDU: + case RSP_SPECIAL_SUB: + case RSP_SPECIAL_SUBU: + case RSP_SPECIAL_AND: + case RSP_SPECIAL_OR: + case RSP_SPECIAL_XOR: + case RSP_SPECIAL_NOR: + case RSP_SPECIAL_SLT: + case RSP_SPECIAL_SLTU: + case RSP_SPECIAL_BREAK: + break; + + case RSP_SPECIAL_JR: + Instruction_State = DO_DELAY_SLOT; + break; + + default: + CompilerWarning("Unkown opcode in WriteToVectorDest\n%s",RSPOpcodeName(RspOp.Hex,PC)); + return TRUE; + } + break; + case RSP_J: + case RSP_JAL: + case RSP_BEQ: + case RSP_BNE: + case RSP_BLEZ: + case RSP_BGTZ: + Instruction_State = DO_DELAY_SLOT; + break; + case RSP_ADDI: + case RSP_ADDIU: + case RSP_SLTI: + case RSP_SLTIU: + case RSP_ANDI: + case RSP_ORI: + case RSP_XORI: + case RSP_LUI: + case RSP_CP0: + break; + + case RSP_CP2: + if ((RspOp.rs & 0x10) != 0) { + switch (RspOp.funct) { + case RSP_VECTOR_VMULF: + case RSP_VECTOR_VMUDL: + case RSP_VECTOR_VMUDM: + case RSP_VECTOR_VMUDN: + case RSP_VECTOR_VMUDH: + break; + case RSP_VECTOR_VMACF: + case RSP_VECTOR_VMADL: + case RSP_VECTOR_VMADM: + case RSP_VECTOR_VMADN: + case RSP_VECTOR_VMADH: + break; + + case RSP_VECTOR_VSUB: + case RSP_VECTOR_VADD: + return FALSE; + case RSP_VECTOR_VSUBC: + case RSP_VECTOR_VADDC: + return TRUE; + + case RSP_VECTOR_VABS: + case RSP_VECTOR_VAND: + case RSP_VECTOR_VOR: + case RSP_VECTOR_VXOR: + case RSP_VECTOR_VRCPH: + case RSP_VECTOR_VRSQL: + case RSP_VECTOR_VRSQH: + case RSP_VECTOR_VRCPL: + case RSP_VECTOR_VRCP: + break; + + case RSP_VECTOR_VCR: + case RSP_VECTOR_VCH: + case RSP_VECTOR_VCL: + case RSP_VECTOR_VLT: + case RSP_VECTOR_VEQ: + case RSP_VECTOR_VGE: + case RSP_VECTOR_VMRG: + return TRUE; + + case RSP_VECTOR_VSAW: + case RSP_VECTOR_VMOV: + break; + + default: + CompilerWarning("Unkown opcode in UseRspFlags\n%s",RSPOpcodeName(RspOp.Hex,PC)); + return TRUE; + } + } else { + switch (RspOp.rs) { + case RSP_COP2_CT: + return TRUE; + + case RSP_COP2_CF: + case RSP_COP2_MT: + case RSP_COP2_MF: + break; + default: + CompilerWarning("Unkown opcode in UseRspFlags\n%s",RSPOpcodeName(RspOp.Hex,PC)); + return TRUE; + } + } + break; + case RSP_LB: + case RSP_LH: + case RSP_LW: + case RSP_LBU: + case RSP_LHU: + case RSP_SB: + case RSP_SH: + case RSP_SW: + break; + case RSP_LC2: + switch (RspOp.rd) { + case RSP_LSC2_BV: + case RSP_LSC2_SV: + case RSP_LSC2_DV: + case RSP_LSC2_RV: + case RSP_LSC2_QV: + case RSP_LSC2_LV: + case RSP_LSC2_UV: + case RSP_LSC2_PV: + case RSP_LSC2_TV: + case RSP_LSC2_HV: + break; + default: + CompilerWarning("Unkown opcode in UseRspFlags\n%s",RSPOpcodeName(RspOp.Hex,PC)); + return TRUE; + } + break; + case RSP_SC2: + switch (RspOp.rd) { + case RSP_LSC2_BV: + case RSP_LSC2_SV: + case RSP_LSC2_LV: + case RSP_LSC2_DV: + case RSP_LSC2_QV: + case RSP_LSC2_RV: + case RSP_LSC2_PV: + case RSP_LSC2_UV: + case RSP_LSC2_HV: + case RSP_LSC2_FV: + case RSP_LSC2_WV: + case RSP_LSC2_TV: + break; + default: + CompilerWarning("Unkown opcode in UseRspFlags\n%s",RSPOpcodeName(RspOp.Hex,PC)); + return TRUE; + } + break; + default: + CompilerWarning("Unkown opcode in UseRspFlags\n%s",RSPOpcodeName(RspOp.Hex,PC)); + return TRUE; + } + switch (Instruction_State) { + case NORMAL: break; + case DO_DELAY_SLOT: + Instruction_State = DELAY_SLOT; + break; + case DELAY_SLOT: + Instruction_State = FINISH_BLOCK; + break; + } + } while ( Instruction_State != FINISH_BLOCK); + return TRUE; +} + +/************************************************************ +** IsRegisterConstant +** +** Output: +** TRUE: Register is constant throughout +** FALSE: Register is not constant at all +** +** Input: PC, Pointer to constant to fill +*************************************************************/ + +BOOL IsRegisterConstant (DWORD Reg, DWORD * Constant) { + DWORD PC = 0; + DWORD References = 0; + DWORD Const = 0; + OPCODE RspOp; + + if (Compiler.bGPRConstants == FALSE) + return FALSE; + + while (PC < 0x1000) { + + RSP_LW_IMEM(PC, &RspOp.Hex); + + /* resample command in microcode likes S7 */ + /* if (PC == 0xFBC) { + PC += 4; + continue; + }*/ + + PC += 4; + + switch (RspOp.op) { + case RSP_REGIMM: + break; + + case RSP_SPECIAL: + switch (RspOp.funct) { + case RSP_SPECIAL_SLL: + case RSP_SPECIAL_SRL: + case RSP_SPECIAL_SRA: + case RSP_SPECIAL_SLLV: + case RSP_SPECIAL_SRLV: + case RSP_SPECIAL_SRAV: + case RSP_SPECIAL_ADD: + case RSP_SPECIAL_ADDU: + case RSP_SPECIAL_SUB: + case RSP_SPECIAL_SUBU: + case RSP_SPECIAL_AND: + case RSP_SPECIAL_OR: + case RSP_SPECIAL_XOR: + case RSP_SPECIAL_NOR: + case RSP_SPECIAL_SLT: + case RSP_SPECIAL_SLTU: + if (RspOp.rd == Reg) { return FALSE; } + break; + + case RSP_SPECIAL_BREAK: + case RSP_SPECIAL_JR: + break; + + default: + // CompilerWarning("Unkown opcode in IsRegisterConstant\n%s",RSPOpcodeName(RspOp.Hex,PC)); + // return FALSE; + break; + } + break; + + case RSP_J: + case RSP_JAL: + case RSP_BEQ: + case RSP_BNE: + case RSP_BLEZ: + case RSP_BGTZ: + break; + + case RSP_ADDI: + case RSP_ADDIU: + if (RspOp.rt == Reg) { + if (RspOp.rs == 0) { + if (References > 0) { + return FALSE; + } + Const = (short)RspOp.immediate; + References++; + } else { + return FALSE; + } + } + break; + case RSP_ORI: + if (RspOp.rt == Reg) { + if (!RspOp.rs) { + if (References > 0) { return FALSE; } + Const = (WORD)RspOp.immediate; + References++; + } else + return FALSE; + } + break; + + case RSP_LUI: + if (RspOp.rt == Reg) { + if (References > 0) { return FALSE; } + Const = (short)RspOp.offset << 16; + References++; + } + break; + + case RSP_ANDI: + case RSP_XORI: + case RSP_SLTI: + case RSP_SLTIU: + if (RspOp.rt == Reg) { return FALSE; } + break; + + case RSP_CP0: + switch (RspOp.rs) { + case RSP_COP0_MF: + if (RspOp.rt == Reg) { return FALSE; } + case RSP_COP0_MT: + break; + } + break; + + case RSP_CP2: + if ((RspOp.rs & 0x10) == 0) { + switch (RspOp.rs) { + case RSP_COP2_CT: + case RSP_COP2_MT: + break; + + case RSP_COP2_CF: + case RSP_COP2_MF: + if (RspOp.rt == Reg) { return FALSE; } + break; + + default: + // CompilerWarning("Unkown opcode in IsRegisterConstant\n%s",RSPOpcodeName(RspOp.Hex,PC)); + // return FALSE; + break; + } + } + break; + + case RSP_LB: + case RSP_LH: + case RSP_LW: + case RSP_LBU: + case RSP_LHU: + if (RspOp.rt == Reg) { return FALSE; } + break; + + case RSP_SB: + case RSP_SH: + case RSP_SW: + break; + case RSP_LC2: + break; + case RSP_SC2: + break; + default: + // CompilerWarning("Unkown opcode in IsRegisterConstant\n%s",RSPOpcodeName(RspOp.Hex,PC)); + // return FALSE; + break; + } + } + + if (References > 0) { + *Constant = Const; + return TRUE; + } else { + *Constant = 0; + return FALSE; + } +} + +/************************************************************ +** IsOpcodeBranch +** +** Output: +** TRUE: opcode is a branch +** FALSE: opcode is not a branch +** +** Input: PC +*************************************************************/ + +BOOL IsOpcodeBranch(DWORD PC, OPCODE RspOp) { + switch (RspOp.op) { + case RSP_REGIMM: + switch (RspOp.rt) { + case RSP_REGIMM_BLTZ: + case RSP_REGIMM_BGEZ: + case RSP_REGIMM_BLTZAL: + case RSP_REGIMM_BGEZAL: + return TRUE; + default: + //CompilerWarning("Unknown opcode in IsOpcodeBranch\n%s",RSPOpcodeName(RspOp.Hex,PC)); + break; + } + break; + case RSP_SPECIAL: + switch (RspOp.funct) { + case RSP_SPECIAL_SLL: + case RSP_SPECIAL_SRL: + case RSP_SPECIAL_SRA: + case RSP_SPECIAL_SLLV: + case RSP_SPECIAL_SRLV: + case RSP_SPECIAL_SRAV: + case RSP_SPECIAL_ADD: + case RSP_SPECIAL_ADDU: + case RSP_SPECIAL_SUB: + case RSP_SPECIAL_SUBU: + case RSP_SPECIAL_AND: + case RSP_SPECIAL_OR: + case RSP_SPECIAL_XOR: + case RSP_SPECIAL_NOR: + case RSP_SPECIAL_SLT: + case RSP_SPECIAL_SLTU: + case RSP_SPECIAL_BREAK: + break; + + case RSP_SPECIAL_JALR: + case RSP_SPECIAL_JR: + return TRUE; + + default: + //CompilerWarning("Unknown opcode in IsOpcodeBranch\n%s",RSPOpcodeName(RspOp.Hex,PC)); + break; + } + break; + case RSP_J: + case RSP_JAL: + case RSP_BEQ: + case RSP_BNE: + case RSP_BLEZ: + case RSP_BGTZ: + return TRUE; + + case RSP_ADDI: + case RSP_ADDIU: + case RSP_SLTI: + case RSP_SLTIU: + case RSP_ANDI: + case RSP_ORI: + case RSP_XORI: + case RSP_LUI: + + case RSP_CP0: + case RSP_CP2: + break; + + case RSP_LB: + case RSP_LH: + case RSP_LW: + case RSP_LBU: + case RSP_LHU: + case RSP_SB: + case RSP_SH: + case RSP_SW: + break; + + case RSP_LC2: + case RSP_SC2: + break; + + default: + //CompilerWarning("Unknown opcode in IsOpcodeBranch\n%s",RSPOpcodeName(RspOp.Hex,PC)); + break; + } + + return FALSE; +} + +/************************************************************ +** GetInstructionInfo +** +** Output: None in regard to return value +** +** Input: +** pointer to info structure, fills this +** with valid opcode data +*************************************************************/ + +/* 3 possible values, GPR, VEC, VEC & GPR, NOOP is zero */ +#define GPR_Instruction 0x0001 /* GPR Instruction flag */ +#define VEC_Instruction 0x0002 /* Vec Instruction flag */ +#define Instruction_Mask (GPR_Instruction | VEC_Instruction) + +/* 3 possible values, one flag must be set only */ +#define Load_Operation 0x0004 /* Load Instruction flag */ +#define Store_Operation 0x0008 /* Store Instruction flag */ +#define Accum_Operation 0x0010 /* Vector op uses accum - loads & stores dont */ +#define MemOperation_Mask (Load_Operation | Store_Operation) +#define Operation_Mask (MemOperation_Mask | Accum_Operation) + +/* Per situation basis flags */ +#define VEC_ResetAccum 0x0000 /* Vector op resets acc */ +#define VEC_Accumulate 0x0020 /* Vector op accumulates */ + +#define InvalidOpcode 0x0040 + +typedef struct { + union { + DWORD DestReg; + DWORD StoredReg; + }; + union { + DWORD SourceReg0; + DWORD IndexReg; + }; + DWORD SourceReg1; + DWORD flags; +} OPCODE_INFO; + +void GetInstructionInfo(DWORD PC, OPCODE * RspOp, OPCODE_INFO * info) { + switch (RspOp->op) { + case RSP_REGIMM: + switch (RspOp->rt) { + case RSP_REGIMM_BLTZ: + case RSP_REGIMM_BLTZAL: + case RSP_REGIMM_BGEZ: + case RSP_REGIMM_BGEZAL: + info->flags = InvalidOpcode; + info->SourceReg0 = RspOp->rs; + info->SourceReg1 = -1; + break; + + default: + CompilerWarning("Unkown opcode in GetInstructionInfo\n%s",RSPOpcodeName(RspOp->Hex,PC)); + info->flags = InvalidOpcode; + break; + } + break; + case RSP_SPECIAL: + switch (RspOp->funct) { + case RSP_SPECIAL_BREAK: + info->DestReg = -1; + info->SourceReg0 = -1; + info->SourceReg1 = -1; + info->flags = GPR_Instruction; + break; + + case RSP_SPECIAL_SLL: + case RSP_SPECIAL_SRL: + case RSP_SPECIAL_SRA: + info->DestReg = RspOp->rd; + info->SourceReg0 = RspOp->rt; + info->SourceReg1 = -1; + info->flags = GPR_Instruction; + break; + case RSP_SPECIAL_SLLV: + case RSP_SPECIAL_SRLV: + case RSP_SPECIAL_SRAV: + case RSP_SPECIAL_ADD: + case RSP_SPECIAL_ADDU: + case RSP_SPECIAL_SUB: + case RSP_SPECIAL_SUBU: + case RSP_SPECIAL_AND: + case RSP_SPECIAL_OR: + case RSP_SPECIAL_XOR: + case RSP_SPECIAL_NOR: + case RSP_SPECIAL_SLT: + case RSP_SPECIAL_SLTU: + info->DestReg = RspOp->rd; + info->SourceReg0 = RspOp->rs; + info->SourceReg1 = RspOp->rt; + info->flags = GPR_Instruction; + break; + + case RSP_SPECIAL_JR: + info->flags = InvalidOpcode; + info->SourceReg0 = -1; + info->SourceReg1 = -1; + break; + + default: + CompilerWarning("Unkown opcode in GetInstructionInfo\n%s",RSPOpcodeName(RspOp->Hex,PC)); + info->flags = InvalidOpcode; + break; + } + break; + case RSP_J: + case RSP_JAL: + info->flags = InvalidOpcode; + info->SourceReg0 = -1; + info->SourceReg1 = -1; + break; + case RSP_BEQ: + case RSP_BNE: + info->flags = InvalidOpcode; + info->SourceReg0 = RspOp->rt; + info->SourceReg1 = RspOp->rs; + break; + case RSP_BLEZ: + case RSP_BGTZ: + info->flags = InvalidOpcode; + info->SourceReg0 = RspOp->rs; + info->SourceReg1 = -1; + break; + + case RSP_ADDI: + case RSP_ADDIU: + case RSP_SLTI: + case RSP_SLTIU: + case RSP_ANDI: + case RSP_ORI: + case RSP_XORI: + info->DestReg = RspOp->rt; + info->SourceReg0 = RspOp->rs; + info->SourceReg1 = -1; + info->flags = GPR_Instruction; + break; + + case RSP_LUI: + info->DestReg = RspOp->rt; + info->SourceReg0 = -1; + info->SourceReg1 = -1; + info->flags = GPR_Instruction; + break; + + case RSP_CP0: + switch (RspOp->rs) { + case RSP_COP0_MF: + info->DestReg = RspOp->rt; + info->SourceReg0 = -1; + info->SourceReg1 = -1; + info->flags = GPR_Instruction | Load_Operation; + break; + + case RSP_COP0_MT: + info->StoredReg = RspOp->rt; + info->SourceReg0 = -1; + info->SourceReg1 = -1; + info->flags = GPR_Instruction | Store_Operation; + break; + } + break; + + case RSP_CP2: + if ((RspOp->rs & 0x10) != 0) { + switch (RspOp->funct) { + case RSP_VECTOR_VNOOP: + info->DestReg = -1; + info->SourceReg0 = -1; + info->SourceReg1 = -1; + info->flags = VEC_Instruction; + break; + + case RSP_VECTOR_VMULF: + case RSP_VECTOR_VMUDL: + case RSP_VECTOR_VMUDM: + case RSP_VECTOR_VMUDN: + case RSP_VECTOR_VMUDH: + info->DestReg = RspOp->sa; + info->SourceReg0 = RspOp->rd; + info->SourceReg1 = RspOp->rt; + info->flags = VEC_Instruction | VEC_ResetAccum | Accum_Operation; + break; + case RSP_VECTOR_VMACF: + case RSP_VECTOR_VMADL: + case RSP_VECTOR_VMADM: + case RSP_VECTOR_VMADN: + case RSP_VECTOR_VMADH: + info->DestReg = RspOp->sa; + info->SourceReg0 = RspOp->rd; + info->SourceReg1 = RspOp->rt; + info->flags = VEC_Instruction | VEC_Accumulate | Accum_Operation; + break; + case RSP_VECTOR_VABS: + case RSP_VECTOR_VADD: + case RSP_VECTOR_VADDC: + case RSP_VECTOR_VSUB: + case RSP_VECTOR_VSUBC: + case RSP_VECTOR_VAND: + case RSP_VECTOR_VOR: + case RSP_VECTOR_VXOR: + case RSP_VECTOR_VNXOR: + case RSP_VECTOR_VCR: + case RSP_VECTOR_VCH: + case RSP_VECTOR_VCL: + case RSP_VECTOR_VRCP: + case RSP_VECTOR_VRCPL: + case RSP_VECTOR_VRCPH: + case RSP_VECTOR_VRSQL: + case RSP_VECTOR_VRSQH: + case RSP_VECTOR_VLT: + case RSP_VECTOR_VEQ: + case RSP_VECTOR_VGE: + case RSP_VECTOR_VNE: + info->DestReg = RspOp->sa; + info->SourceReg0 = RspOp->rd; + info->SourceReg1 = RspOp->rt; + info->flags = VEC_Instruction | VEC_ResetAccum | Accum_Operation; + break; + + case RSP_VECTOR_VMOV: + info->flags = InvalidOpcode; + /* info->DestReg = RspOp->sa; + info->SourceReg0 = RspOp->rt; + info->SourceReg1 = -1; + info->flags = VEC_Instruction; /* Assume reset? */ + break; + + case RSP_VECTOR_VMRG: + info->flags = InvalidOpcode; + /* info->DestReg = RspOp->sa; + info->SourceReg0 = RspOp->rt; + info->SourceReg1 = RspOp->rd; + info->flags = VEC_Instruction; /* Assum reset? */ + break; + + case RSP_VECTOR_VSAW: + // info->flags = InvalidOpcode; + info->DestReg = RspOp->sa; + info->SourceReg0 = -1; + info->SourceReg1 = -1; + info->flags = VEC_Instruction | Accum_Operation | VEC_Accumulate; + break; + + default: + CompilerWarning("Unkown opcode in GetInstructionInfo\n%s",RSPOpcodeName(RspOp->Hex,PC)); + info->flags = InvalidOpcode; + break; + } + } else { + switch (RspOp->rs) { + case RSP_COP2_CT: + info->StoredReg = RspOp->rt; + info->SourceReg0 = -1; + info->SourceReg1 = -1; + info->flags = GPR_Instruction | Store_Operation; + break; + case RSP_COP2_CF: + info->DestReg = RspOp->rt; + info->SourceReg0 = -1; + info->SourceReg1 = -1; + info->flags = GPR_Instruction | Load_Operation; + break; + + /* RD is always the vector register, RT is always GPR */ + case RSP_COP2_MT: + info->DestReg = RspOp->rd; + info->SourceReg0 = RspOp->rt; + info->SourceReg1 = -1; + info->flags = VEC_Instruction | GPR_Instruction | Load_Operation; + break; + case RSP_COP2_MF: + info->DestReg = RspOp->rt; + info->SourceReg0 = RspOp->rd; + info->SourceReg1 = -1; + info->flags = VEC_Instruction | GPR_Instruction | Store_Operation; + break; + default: + CompilerWarning("Unkown opcode in GetInstructionInfo\n%s",RSPOpcodeName(RspOp->Hex,PC)); + info->flags = InvalidOpcode; + break; + } + } + break; + case RSP_LB: + case RSP_LH: + case RSP_LW: + case RSP_LBU: + case RSP_LHU: + info->DestReg = RspOp->rt; + info->IndexReg = RspOp->base; + info->SourceReg1 = -1; + info->flags = Load_Operation | GPR_Instruction; + break; + case RSP_SB: + case RSP_SH: + case RSP_SW: + info->StoredReg = RspOp->rt; + info->IndexReg = RspOp->base; + info->SourceReg1 = -1; + info->flags = Store_Operation | GPR_Instruction; + break; + case RSP_LC2: + switch (RspOp->rd) { + case RSP_LSC2_SV: + case RSP_LSC2_DV: + case RSP_LSC2_RV: + case RSP_LSC2_QV: + case RSP_LSC2_LV: + case RSP_LSC2_UV: + case RSP_LSC2_PV: + info->DestReg = RspOp->rt; + info->IndexReg = RspOp->base; + info->SourceReg1 = -1; + info->flags = Load_Operation | VEC_Instruction; + break; + + case RSP_LSC2_TV: + info->flags = InvalidOpcode; + break; + default: + CompilerWarning("Unkown opcode in GetInstructionInfo\n%s",RSPOpcodeName(RspOp->Hex,PC)); + info->flags = InvalidOpcode; + break; + } + break; + case RSP_SC2: + switch (RspOp->rd) { + case RSP_LSC2_BV: + case RSP_LSC2_SV: + case RSP_LSC2_LV: + case RSP_LSC2_DV: + case RSP_LSC2_QV: + case RSP_LSC2_RV: + case RSP_LSC2_PV: + case RSP_LSC2_UV: + case RSP_LSC2_HV: + case RSP_LSC2_FV: + case RSP_LSC2_WV: + info->DestReg = RspOp->rt; + info->IndexReg = RspOp->base; + info->SourceReg1 = -1; + info->flags = Store_Operation | VEC_Instruction; + break; + case RSP_LSC2_TV: + info->flags = InvalidOpcode; + break; + default: + CompilerWarning("Unkown opcode in GetInstructionInfo\n%s",RSPOpcodeName(RspOp->Hex,PC)); + info->flags = InvalidOpcode; + break; + } + break; + default: + /* CompilerWarning("Unkown opcode in GetInstructionInfo\n%s",RSPOpcodeName(RspOp->Hex,PC)); + */ info->flags = InvalidOpcode; + break; + } +} + +/************************************************************ +** DelaySlotAffectBranch +** +** Output: +** TRUE: Delay slot does affect the branch +** FALSE: Registers do not affect each other +** +** Input: PC +*************************************************************/ + +BOOL DelaySlotAffectBranch(DWORD PC) { + OPCODE Branch, Delay; + OPCODE_INFO infoBranch, infoDelay; + + if (IsOpcodeNop(PC + 4) == TRUE) { + return FALSE; + } + + RSP_LW_IMEM(PC, &Branch.Hex); + RSP_LW_IMEM(PC+4, &Delay.Hex); + + memset(&infoDelay,0,sizeof(infoDelay)); + memset(&infoBranch,0,sizeof(infoBranch)); + + GetInstructionInfo(PC, &Branch, &infoBranch); + GetInstructionInfo(PC+4, &Delay, &infoDelay); + + if ((infoDelay.flags & Instruction_Mask) == VEC_Instruction) { + return FALSE; + } + + if (infoBranch.SourceReg0 == infoDelay.DestReg) { return TRUE; } + if (infoBranch.SourceReg1 == infoDelay.DestReg) { return TRUE; } + + return FALSE; +} + +/************************************************************ +** CompareInstructions +** +** Output: +** TRUE: The opcodes are fine, no dependency +** FALSE: Watch it, these ops cant be touched +** +** Input: +** Top, not the current operation, the one above +** Bottom: the current opcode for re-ordering bubble style +*************************************************************/ + +BOOL CompareInstructions(DWORD PC, OPCODE * Top, OPCODE * Bottom) { + + OPCODE_INFO info0, info1; + DWORD InstructionType; + + GetInstructionInfo(PC - 4, Top, &info0); + GetInstructionInfo(PC, Bottom, &info1); + + /* usually branches and such */ + if ((info0.flags & InvalidOpcode) != 0) return FALSE; + if ((info1.flags & InvalidOpcode) != 0) return FALSE; + + InstructionType = (info0.flags & Instruction_Mask) << 2; + InstructionType |= info1.flags & Instruction_Mask; + InstructionType &= 0x0F; /* Paranoia */ + + /* 4 bit range, 16 possible combinations */ + switch (InstructionType) { + /* + ** Detect noop instruction, 7 cases, (see flags) */ + case 0x01: case 0x02: case 0x03: /* First is a noop */ + return TRUE; + case 0x00: /* Both ??? */ + case 0x10: case 0x20: case 0x30: /* Second is a noop */ + return FALSE; + + case 0x06: /* GPR than Vector - 01,10 */ + if ((info0.flags & MemOperation_Mask) != 0 && (info1.flags & MemOperation_Mask) != 0) { + /* TODO: We have a vector & GPR memory operation */ + return FALSE; + } else if ((info1.flags & MemOperation_Mask) != 0) { + /* We have a vector memory operation */ + return (info1.IndexReg == info0.DestReg) ? FALSE : TRUE; + } else { + /* We could have memory or normal gpr instruction here + ** paired with some kind of vector operation + */ + return TRUE; + } + return FALSE; + + case 0x0A: /* Vector than Vector - 10,10 */ + + /* + ** Check for Vector Store than Vector multiply (VMULF) + ** + ** This basically gives preferences to putting stores + ** as close to the finish of an operation as possible + */ + if ((info0.flags & Store_Operation) != 0 && (info1.flags & Accum_Operation) != 0 + && !(info1.flags & VEC_Accumulate)) { return FALSE; } + + /* + ** Look for loads and than some kind of vector operation + ** that does no accumulating, there is no reason to reorder + */ + if ((info0.flags & Load_Operation) != 0 && (info1.flags & Accum_Operation) != 0 + && !(info1.flags & VEC_Accumulate)) { return FALSE; } + + if ((info0.flags & MemOperation_Mask) != 0 && (info1.flags & MemOperation_Mask) != 0) { + /* + ** TODO: This is a bitch, its best to leave it alone + **/ + return FALSE; + } else if ((info1.flags & MemOperation_Mask) != 0) { + /* Remember stored reg & loaded reg are the same */ + if (info0.DestReg == info1.DestReg) { return FALSE; } + + if (info1.flags & Load_Operation) { + if (info0.SourceReg0 == info1.DestReg) { return FALSE; } + if (info0.SourceReg1 == info1.DestReg) { return FALSE; } + } else if (info1.flags & Store_Operation) { + /* It can store source regs */ + return TRUE; + } + + return TRUE; + } else if ((info0.flags & MemOperation_Mask) != 0) { + /* Remember stored reg & loaded reg are the same */ + if (info0.DestReg == info1.DestReg) { return FALSE; } + + if (info0.flags & Load_Operation) { + if (info1.SourceReg0 == info0.DestReg) { return FALSE; } + if (info1.SourceReg1 == info0.DestReg) { return FALSE; } + } else if (info0.flags & Store_Operation) { + /* It can store source regs */ + return TRUE; + } + + return TRUE; + } else if ((info0.flags & VEC_Accumulate) != 0) { + /* + ** Example: + ** VMACF + ** VMUDH or VMADH or VADD + */ + + return FALSE; + } else if ((info1.flags & VEC_Accumulate) != 0) { + /* + ** Example: + ** VMULF + ** VMADH + */ + + return FALSE; + } else { + /* + ** Example: + ** VMULF or VADDC + ** VADD or VMUDH + */ + + return FALSE; + } + break; + + case 0x09: /* Vector than GPR - 10,01 */ + /********** + ** this is where the bias comes into play, otherwise + ** we can sit here all day swapping these 2 types + ***********/ + return FALSE; + + case 0x05: /* GPR than GPR - 01,01 */ + case 0x07: /* GPR than Cop2 - 01, 11 */ + case 0x0D: /* Cop2 than GPR - 11, 01 */ + case 0x0F: /* Cop2 than Cop2 - 11, 11 */ + return FALSE; + + case 0x0B: /* Vector than Cop2 - 10, 11 */ + if (info1.flags & Load_Operation) { + /* Move To Cop2 (dest) from GPR (source) */ + if (info1.DestReg == info0.DestReg) { return FALSE; } + if (info1.DestReg == info0.SourceReg0) { return FALSE; } + if (info1.DestReg == info0.SourceReg1) { return FALSE; } + } else if (info1.flags & Store_Operation) { + /* Move From Cop2 (source) to GPR (dest) */ + if (info1.SourceReg0 == info0.DestReg) { return FALSE; } + if (info1.SourceReg0 == info0.SourceReg0) { return FALSE; } + if (info1.SourceReg0 == info0.SourceReg1) { return FALSE; } + } else { + CompilerWarning("ReOrder: Unhandled Vector than Cop2"); + } + // we want vectors on top + return FALSE; + + case 0x0E: /* Cop2 than Vector - 11, 10 */ + if (info0.flags & Load_Operation) { + /* Move To Cop2 (dest) from GPR (source) */ + if (info0.DestReg == info1.DestReg) { return FALSE; } + if (info0.DestReg == info1.SourceReg0) { return FALSE; } + if (info0.DestReg == info1.SourceReg1) { return FALSE; } + } else if (info0.flags & Store_Operation) { + /* Move From Cop2 (source) to GPR (dest) */ + if (info0.SourceReg0 == info1.DestReg) { return FALSE; } + if (info0.SourceReg0 == info1.SourceReg0) { return FALSE; } + if (info0.SourceReg0 == info1.SourceReg1) { return FALSE; } + } else { + CompilerWarning("ReOrder: Unhandled Cop2 than Vector"); + } + // we want this at the top + return TRUE; + + default: + CompilerWarning("ReOrder: Unhandled instruction type: %i", InstructionType); + } + + return FALSE; +} diff --git a/Source/RSP/Recompiler CPU.c b/Source/RSP/Recompiler CPU.c new file mode 100644 index 000000000..c96427882 --- /dev/null +++ b/Source/RSP/Recompiler CPU.c @@ -0,0 +1,941 @@ +/* + * RSP Compiler plug in for Project 64 (A Nintendo 64 emulator). + * + * (c) Copyright 2001 jabo (jabo@emulation64.com) and + * zilmar (zilmar@emulation64.com) + * + * pj64 homepage: www.pj64.net + * + * Permission to use, copy, modify and distribute Project64 in both binary and + * source form, for non-commercial purposes, is hereby granted without fee, + * providing that this license information and copyright notice appear with + * all copies and any derived work. + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event shall the authors be held liable for any damages + * arising from the use of this software. + * + * Project64 is freeware for PERSONAL USE only. Commercial users should + * seek permission of the copyright holders first. Commercial use includes + * charging money for Project64 or software derived from Project64. + * + * The copyright holders request that bug fixes and improvements to the code + * should be forwarded to them so if they want them. + * + */ + +#include +#include +#include +#include "RSP.h" +#include "Cpu.h" +#include "Recompiler CPU.h" +#include "Recompiler Ops.h" +#include "RSP registers.h" +#include "RSP Command.h" +#include "memory.h" +#include "opcode.h" +#include "log.h" +#include "Profiling.h" +#include "x86.h" + +/* #define REORDER_BLOCK_VERBOSE */ +#define LINK_BRANCHES_VERBOSE /* no choice really */ +#define X86_RECOMP_VERBOSE +#define BUILD_BRANCHLABELS_VERBOSE + +DWORD CompilePC, BlockID = 0; +DWORD dwBuffer = MainBuffer; +BOOL ChangedPC; + +RSP_BLOCK CurrentBlock; +RSP_CODE RspCode; + +BYTE * pLastSecondary = NULL, * pLastPrimary = NULL; + +void BuildRecompilerCPU ( void ) { + RSP_Opcode[ 0] = Compile_SPECIAL; + RSP_Opcode[ 1] = Compile_REGIMM; + RSP_Opcode[ 2] = Compile_J; + RSP_Opcode[ 3] = Compile_JAL; + RSP_Opcode[ 4] = Compile_BEQ; + RSP_Opcode[ 5] = Compile_BNE; + RSP_Opcode[ 6] = Compile_BLEZ; + RSP_Opcode[ 7] = Compile_BGTZ; + RSP_Opcode[ 8] = Compile_ADDI; + RSP_Opcode[ 9] = Compile_ADDIU; + RSP_Opcode[10] = Compile_SLTI; + RSP_Opcode[11] = Compile_SLTIU; + RSP_Opcode[12] = Compile_ANDI; + RSP_Opcode[13] = Compile_ORI; + RSP_Opcode[14] = Compile_XORI; + RSP_Opcode[15] = Compile_LUI; + RSP_Opcode[16] = Compile_COP0; + RSP_Opcode[17] = Compile_UnknownOpcode; + RSP_Opcode[18] = Compile_COP2; + RSP_Opcode[19] = Compile_UnknownOpcode; + RSP_Opcode[20] = Compile_UnknownOpcode; + RSP_Opcode[21] = Compile_UnknownOpcode; + RSP_Opcode[22] = Compile_UnknownOpcode; + RSP_Opcode[23] = Compile_UnknownOpcode; + RSP_Opcode[24] = Compile_UnknownOpcode; + RSP_Opcode[25] = Compile_UnknownOpcode; + RSP_Opcode[26] = Compile_UnknownOpcode; + RSP_Opcode[27] = Compile_UnknownOpcode; + RSP_Opcode[28] = Compile_UnknownOpcode; + RSP_Opcode[29] = Compile_UnknownOpcode; + RSP_Opcode[30] = Compile_UnknownOpcode; + RSP_Opcode[31] = Compile_UnknownOpcode; + RSP_Opcode[32] = Compile_LB; + RSP_Opcode[33] = Compile_LH; + RSP_Opcode[34] = Compile_UnknownOpcode; + RSP_Opcode[35] = Compile_LW; + RSP_Opcode[36] = Compile_LBU; + RSP_Opcode[37] = Compile_LHU; + RSP_Opcode[38] = Compile_UnknownOpcode; + RSP_Opcode[39] = Compile_UnknownOpcode; + RSP_Opcode[40] = Compile_SB; + RSP_Opcode[41] = Compile_SH; + RSP_Opcode[42] = Compile_UnknownOpcode; + RSP_Opcode[43] = Compile_SW; + RSP_Opcode[44] = Compile_UnknownOpcode; + RSP_Opcode[45] = Compile_UnknownOpcode; + RSP_Opcode[46] = Compile_UnknownOpcode; + RSP_Opcode[47] = Compile_UnknownOpcode; + RSP_Opcode[48] = Compile_UnknownOpcode; + RSP_Opcode[49] = Compile_UnknownOpcode; + RSP_Opcode[50] = Compile_LC2; + RSP_Opcode[51] = Compile_UnknownOpcode; + RSP_Opcode[52] = Compile_UnknownOpcode; + RSP_Opcode[53] = Compile_UnknownOpcode; + RSP_Opcode[54] = Compile_UnknownOpcode; + RSP_Opcode[55] = Compile_UnknownOpcode; + RSP_Opcode[56] = Compile_UnknownOpcode; + RSP_Opcode[57] = Compile_UnknownOpcode; + RSP_Opcode[58] = Compile_SC2; + RSP_Opcode[59] = Compile_UnknownOpcode; + RSP_Opcode[60] = Compile_UnknownOpcode; + RSP_Opcode[61] = Compile_UnknownOpcode; + RSP_Opcode[62] = Compile_UnknownOpcode; + RSP_Opcode[63] = Compile_UnknownOpcode; + + RSP_Special[ 0] = Compile_Special_SLL; + RSP_Special[ 1] = Compile_UnknownOpcode; + RSP_Special[ 2] = Compile_Special_SRL; + RSP_Special[ 3] = Compile_Special_SRA; + RSP_Special[ 4] = Compile_Special_SLLV; + RSP_Special[ 5] = Compile_UnknownOpcode; + RSP_Special[ 6] = Compile_Special_SRLV; + RSP_Special[ 7] = Compile_Special_SRAV; + RSP_Special[ 8] = Compile_Special_JR; + RSP_Special[ 9] = Compile_Special_JALR; + RSP_Special[10] = Compile_UnknownOpcode; + RSP_Special[11] = Compile_UnknownOpcode; + RSP_Special[12] = Compile_UnknownOpcode; + RSP_Special[13] = Compile_Special_BREAK; + RSP_Special[14] = Compile_UnknownOpcode; + RSP_Special[15] = Compile_UnknownOpcode; + RSP_Special[16] = Compile_UnknownOpcode; + RSP_Special[17] = Compile_UnknownOpcode; + RSP_Special[18] = Compile_UnknownOpcode; + RSP_Special[19] = Compile_UnknownOpcode; + RSP_Special[20] = Compile_UnknownOpcode; + RSP_Special[21] = Compile_UnknownOpcode; + RSP_Special[22] = Compile_UnknownOpcode; + RSP_Special[23] = Compile_UnknownOpcode; + RSP_Special[24] = Compile_UnknownOpcode; + RSP_Special[25] = Compile_UnknownOpcode; + RSP_Special[26] = Compile_UnknownOpcode; + RSP_Special[27] = Compile_UnknownOpcode; + RSP_Special[28] = Compile_UnknownOpcode; + RSP_Special[29] = Compile_UnknownOpcode; + RSP_Special[30] = Compile_UnknownOpcode; + RSP_Special[31] = Compile_UnknownOpcode; + RSP_Special[32] = Compile_Special_ADD; + RSP_Special[33] = Compile_Special_ADDU; + RSP_Special[34] = Compile_Special_SUB; + RSP_Special[35] = Compile_Special_SUBU; + RSP_Special[36] = Compile_Special_AND; + RSP_Special[37] = Compile_Special_OR; + RSP_Special[38] = Compile_Special_XOR; + RSP_Special[39] = Compile_Special_NOR; + RSP_Special[40] = Compile_UnknownOpcode; + RSP_Special[41] = Compile_UnknownOpcode; + RSP_Special[42] = Compile_Special_SLT; + RSP_Special[43] = Compile_Special_SLTU; + RSP_Special[44] = Compile_UnknownOpcode; + RSP_Special[45] = Compile_UnknownOpcode; + RSP_Special[46] = Compile_UnknownOpcode; + RSP_Special[47] = Compile_UnknownOpcode; + RSP_Special[48] = Compile_UnknownOpcode; + RSP_Special[49] = Compile_UnknownOpcode; + RSP_Special[50] = Compile_UnknownOpcode; + RSP_Special[51] = Compile_UnknownOpcode; + RSP_Special[52] = Compile_UnknownOpcode; + RSP_Special[53] = Compile_UnknownOpcode; + RSP_Special[54] = Compile_UnknownOpcode; + RSP_Special[55] = Compile_UnknownOpcode; + RSP_Special[56] = Compile_UnknownOpcode; + RSP_Special[57] = Compile_UnknownOpcode; + RSP_Special[58] = Compile_UnknownOpcode; + RSP_Special[59] = Compile_UnknownOpcode; + RSP_Special[60] = Compile_UnknownOpcode; + RSP_Special[61] = Compile_UnknownOpcode; + RSP_Special[62] = Compile_UnknownOpcode; + RSP_Special[63] = Compile_UnknownOpcode; + + RSP_RegImm[ 0] = Compile_RegImm_BLTZ; + RSP_RegImm[ 1] = Compile_RegImm_BGEZ; + RSP_RegImm[ 2] = Compile_UnknownOpcode; + RSP_RegImm[ 3] = Compile_UnknownOpcode; + RSP_RegImm[ 4] = Compile_UnknownOpcode; + RSP_RegImm[ 5] = Compile_UnknownOpcode; + RSP_RegImm[ 6] = Compile_UnknownOpcode; + RSP_RegImm[ 7] = Compile_UnknownOpcode; + RSP_RegImm[ 8] = Compile_UnknownOpcode; + RSP_RegImm[ 9] = Compile_UnknownOpcode; + RSP_RegImm[10] = Compile_UnknownOpcode; + RSP_RegImm[11] = Compile_UnknownOpcode; + RSP_RegImm[12] = Compile_UnknownOpcode; + RSP_RegImm[13] = Compile_UnknownOpcode; + RSP_RegImm[14] = Compile_UnknownOpcode; + RSP_RegImm[15] = Compile_UnknownOpcode; + RSP_RegImm[16] = Compile_RegImm_BLTZAL; + RSP_RegImm[17] = Compile_RegImm_BGEZAL; + RSP_RegImm[18] = Compile_UnknownOpcode; + RSP_RegImm[19] = Compile_UnknownOpcode; + RSP_RegImm[20] = Compile_UnknownOpcode; + RSP_RegImm[21] = Compile_UnknownOpcode; + RSP_RegImm[22] = Compile_UnknownOpcode; + RSP_RegImm[23] = Compile_UnknownOpcode; + RSP_RegImm[24] = Compile_UnknownOpcode; + RSP_RegImm[25] = Compile_UnknownOpcode; + RSP_RegImm[26] = Compile_UnknownOpcode; + RSP_RegImm[27] = Compile_UnknownOpcode; + RSP_RegImm[28] = Compile_UnknownOpcode; + RSP_RegImm[29] = Compile_UnknownOpcode; + RSP_RegImm[30] = Compile_UnknownOpcode; + RSP_RegImm[31] = Compile_UnknownOpcode; + + RSP_Cop0[ 0] = Compile_Cop0_MF; + RSP_Cop0[ 1] = Compile_UnknownOpcode; + RSP_Cop0[ 2] = Compile_UnknownOpcode; + RSP_Cop0[ 3] = Compile_UnknownOpcode; + RSP_Cop0[ 4] = Compile_Cop0_MT; + RSP_Cop0[ 5] = Compile_UnknownOpcode; + RSP_Cop0[ 6] = Compile_UnknownOpcode; + RSP_Cop0[ 7] = Compile_UnknownOpcode; + RSP_Cop0[ 8] = Compile_UnknownOpcode; + RSP_Cop0[ 9] = Compile_UnknownOpcode; + RSP_Cop0[10] = Compile_UnknownOpcode; + RSP_Cop0[11] = Compile_UnknownOpcode; + RSP_Cop0[12] = Compile_UnknownOpcode; + RSP_Cop0[13] = Compile_UnknownOpcode; + RSP_Cop0[14] = Compile_UnknownOpcode; + RSP_Cop0[15] = Compile_UnknownOpcode; + RSP_Cop0[16] = Compile_UnknownOpcode; + RSP_Cop0[17] = Compile_UnknownOpcode; + RSP_Cop0[18] = Compile_UnknownOpcode; + RSP_Cop0[19] = Compile_UnknownOpcode; + RSP_Cop0[20] = Compile_UnknownOpcode; + RSP_Cop0[21] = Compile_UnknownOpcode; + RSP_Cop0[22] = Compile_UnknownOpcode; + RSP_Cop0[23] = Compile_UnknownOpcode; + RSP_Cop0[24] = Compile_UnknownOpcode; + RSP_Cop0[25] = Compile_UnknownOpcode; + RSP_Cop0[26] = Compile_UnknownOpcode; + RSP_Cop0[27] = Compile_UnknownOpcode; + RSP_Cop0[28] = Compile_UnknownOpcode; + RSP_Cop0[29] = Compile_UnknownOpcode; + RSP_Cop0[30] = Compile_UnknownOpcode; + RSP_Cop0[31] = Compile_UnknownOpcode; + + RSP_Cop2[ 0] = Compile_Cop2_MF; + RSP_Cop2[ 1] = Compile_UnknownOpcode; + RSP_Cop2[ 2] = Compile_Cop2_CF; + RSP_Cop2[ 3] = Compile_UnknownOpcode; + RSP_Cop2[ 4] = Compile_Cop2_MT; + RSP_Cop2[ 5] = Compile_UnknownOpcode; + RSP_Cop2[ 6] = Compile_Cop2_CT; + RSP_Cop2[ 7] = Compile_UnknownOpcode; + RSP_Cop2[ 8] = Compile_UnknownOpcode; + RSP_Cop2[ 9] = Compile_UnknownOpcode; + RSP_Cop2[10] = Compile_UnknownOpcode; + RSP_Cop2[11] = Compile_UnknownOpcode; + RSP_Cop2[12] = Compile_UnknownOpcode; + RSP_Cop2[13] = Compile_UnknownOpcode; + RSP_Cop2[14] = Compile_UnknownOpcode; + RSP_Cop2[15] = Compile_UnknownOpcode; + RSP_Cop2[16] = Compile_COP2_VECTOR; + RSP_Cop2[17] = Compile_COP2_VECTOR; + RSP_Cop2[18] = Compile_COP2_VECTOR; + RSP_Cop2[19] = Compile_COP2_VECTOR; + RSP_Cop2[20] = Compile_COP2_VECTOR; + RSP_Cop2[21] = Compile_COP2_VECTOR; + RSP_Cop2[22] = Compile_COP2_VECTOR; + RSP_Cop2[23] = Compile_COP2_VECTOR; + RSP_Cop2[24] = Compile_COP2_VECTOR; + RSP_Cop2[25] = Compile_COP2_VECTOR; + RSP_Cop2[26] = Compile_COP2_VECTOR; + RSP_Cop2[27] = Compile_COP2_VECTOR; + RSP_Cop2[28] = Compile_COP2_VECTOR; + RSP_Cop2[29] = Compile_COP2_VECTOR; + RSP_Cop2[30] = Compile_COP2_VECTOR; + RSP_Cop2[31] = Compile_COP2_VECTOR; + + RSP_Vector[ 0] = Compile_Vector_VMULF; + RSP_Vector[ 1] = Compile_Vector_VMULU; + RSP_Vector[ 2] = Compile_UnknownOpcode; + RSP_Vector[ 3] = Compile_UnknownOpcode; + RSP_Vector[ 4] = Compile_Vector_VMUDL; + RSP_Vector[ 5] = Compile_Vector_VMUDM; + RSP_Vector[ 6] = Compile_Vector_VMUDN; + RSP_Vector[ 7] = Compile_Vector_VMUDH; + RSP_Vector[ 8] = Compile_Vector_VMACF; + RSP_Vector[ 9] = Compile_Vector_VMACU; + RSP_Vector[10] = Compile_UnknownOpcode; + RSP_Vector[11] = Compile_Vector_VMACQ; + RSP_Vector[12] = Compile_Vector_VMADL; + RSP_Vector[13] = Compile_Vector_VMADM; + RSP_Vector[14] = Compile_Vector_VMADN; + RSP_Vector[15] = Compile_Vector_VMADH; + RSP_Vector[16] = Compile_Vector_VADD; + RSP_Vector[17] = Compile_Vector_VSUB; + RSP_Vector[18] = Compile_UnknownOpcode; + RSP_Vector[19] = Compile_Vector_VABS; + RSP_Vector[20] = Compile_Vector_VADDC; + RSP_Vector[21] = Compile_Vector_VSUBC; + RSP_Vector[22] = Compile_UnknownOpcode; + RSP_Vector[23] = Compile_UnknownOpcode; + RSP_Vector[24] = Compile_UnknownOpcode; + RSP_Vector[25] = Compile_UnknownOpcode; + RSP_Vector[26] = Compile_UnknownOpcode; + RSP_Vector[27] = Compile_UnknownOpcode; + RSP_Vector[28] = Compile_UnknownOpcode; + RSP_Vector[29] = Compile_Vector_VSAW; + RSP_Vector[30] = Compile_UnknownOpcode; + RSP_Vector[31] = Compile_UnknownOpcode; + RSP_Vector[32] = Compile_Vector_VLT; + RSP_Vector[33] = Compile_Vector_VEQ; + RSP_Vector[34] = Compile_Vector_VNE; + RSP_Vector[35] = Compile_Vector_VGE; + RSP_Vector[36] = Compile_Vector_VCL; + RSP_Vector[37] = Compile_Vector_VCH; + RSP_Vector[38] = Compile_Vector_VCR; + RSP_Vector[39] = Compile_Vector_VMRG; + RSP_Vector[40] = Compile_Vector_VAND; + RSP_Vector[41] = Compile_Vector_VNAND; + RSP_Vector[42] = Compile_Vector_VOR; + RSP_Vector[43] = Compile_Vector_VNOR; + RSP_Vector[44] = Compile_Vector_VXOR; + RSP_Vector[45] = Compile_Vector_VNXOR; + RSP_Vector[46] = Compile_UnknownOpcode; + RSP_Vector[47] = Compile_UnknownOpcode; + RSP_Vector[48] = Compile_Vector_VRCP; + RSP_Vector[49] = Compile_Vector_VRCPL; + RSP_Vector[50] = Compile_Vector_VRCPH; + RSP_Vector[51] = Compile_Vector_VMOV; + RSP_Vector[52] = Compile_Vector_VRSQ; + RSP_Vector[53] = Compile_Vector_VRSQL; + RSP_Vector[54] = Compile_Vector_VRSQH; + RSP_Vector[55] = Compile_Vector_VNOOP; + RSP_Vector[56] = Compile_UnknownOpcode; + RSP_Vector[57] = Compile_UnknownOpcode; + RSP_Vector[58] = Compile_UnknownOpcode; + RSP_Vector[59] = Compile_UnknownOpcode; + RSP_Vector[60] = Compile_UnknownOpcode; + RSP_Vector[61] = Compile_UnknownOpcode; + RSP_Vector[62] = Compile_UnknownOpcode; + RSP_Vector[63] = Compile_UnknownOpcode; + + RSP_Lc2[ 0] = Compile_Opcode_LBV; + RSP_Lc2[ 1] = Compile_Opcode_LSV; + RSP_Lc2[ 2] = Compile_Opcode_LLV; + RSP_Lc2[ 3] = Compile_Opcode_LDV; + RSP_Lc2[ 4] = Compile_Opcode_LQV; + RSP_Lc2[ 5] = Compile_Opcode_LRV; + RSP_Lc2[ 6] = Compile_Opcode_LPV; + RSP_Lc2[ 7] = Compile_Opcode_LUV; + RSP_Lc2[ 8] = Compile_Opcode_LHV; + RSP_Lc2[ 9] = Compile_Opcode_LFV; + RSP_Lc2[10] = Compile_UnknownOpcode; + RSP_Lc2[11] = Compile_Opcode_LTV; + RSP_Lc2[12] = Compile_UnknownOpcode; + RSP_Lc2[13] = Compile_UnknownOpcode; + RSP_Lc2[14] = Compile_UnknownOpcode; + RSP_Lc2[15] = Compile_UnknownOpcode; + RSP_Lc2[16] = Compile_UnknownOpcode; + RSP_Lc2[17] = Compile_UnknownOpcode; + RSP_Lc2[18] = Compile_UnknownOpcode; + RSP_Lc2[19] = Compile_UnknownOpcode; + RSP_Lc2[20] = Compile_UnknownOpcode; + RSP_Lc2[21] = Compile_UnknownOpcode; + RSP_Lc2[22] = Compile_UnknownOpcode; + RSP_Lc2[23] = Compile_UnknownOpcode; + RSP_Lc2[24] = Compile_UnknownOpcode; + RSP_Lc2[25] = Compile_UnknownOpcode; + RSP_Lc2[26] = Compile_UnknownOpcode; + RSP_Lc2[27] = Compile_UnknownOpcode; + RSP_Lc2[28] = Compile_UnknownOpcode; + RSP_Lc2[29] = Compile_UnknownOpcode; + RSP_Lc2[30] = Compile_UnknownOpcode; + RSP_Lc2[31] = Compile_UnknownOpcode; + + RSP_Sc2[ 0] = Compile_Opcode_SBV; + RSP_Sc2[ 1] = Compile_Opcode_SSV; + RSP_Sc2[ 2] = Compile_Opcode_SLV; + RSP_Sc2[ 3] = Compile_Opcode_SDV; + RSP_Sc2[ 4] = Compile_Opcode_SQV; + RSP_Sc2[ 5] = Compile_Opcode_SRV; + RSP_Sc2[ 6] = Compile_Opcode_SPV; + RSP_Sc2[ 7] = Compile_Opcode_SUV; + RSP_Sc2[ 8] = Compile_Opcode_SHV; + RSP_Sc2[ 9] = Compile_Opcode_SFV; + RSP_Sc2[10] = Compile_Opcode_SWV; + RSP_Sc2[11] = Compile_Opcode_STV; + RSP_Sc2[12] = Compile_UnknownOpcode; + RSP_Sc2[13] = Compile_UnknownOpcode; + RSP_Sc2[14] = Compile_UnknownOpcode; + RSP_Sc2[15] = Compile_UnknownOpcode; + RSP_Sc2[16] = Compile_UnknownOpcode; + RSP_Sc2[17] = Compile_UnknownOpcode; + RSP_Sc2[18] = Compile_UnknownOpcode; + RSP_Sc2[19] = Compile_UnknownOpcode; + RSP_Sc2[20] = Compile_UnknownOpcode; + RSP_Sc2[21] = Compile_UnknownOpcode; + RSP_Sc2[22] = Compile_UnknownOpcode; + RSP_Sc2[23] = Compile_UnknownOpcode; + RSP_Sc2[24] = Compile_UnknownOpcode; + RSP_Sc2[25] = Compile_UnknownOpcode; + RSP_Sc2[26] = Compile_UnknownOpcode; + RSP_Sc2[27] = Compile_UnknownOpcode; + RSP_Sc2[28] = Compile_UnknownOpcode; + RSP_Sc2[29] = Compile_UnknownOpcode; + RSP_Sc2[30] = Compile_UnknownOpcode; + RSP_Sc2[31] = Compile_UnknownOpcode; + + BlockID = 0; + ChangedPC = FALSE; + #ifdef Log_x86Code + Start_x86_Log(); + #endif +} + +/****************************************************** +** ReOrderSubBlock +** +** Desc: +** this can be done, but will be interesting to put +** between branches labels, and actual branches, whichever +** occurs first in code +** +********************************************************/ + +void ReOrderInstructions(DWORD StartPC, DWORD EndPC) { + DWORD InstructionCount = EndPC - StartPC; + DWORD Count, ReorderedOps, CurrentPC; + OPCODE PreviousOp, CurrentOp, RspOp; + + PreviousOp.Hex = *(DWORD*)(RSPInfo.IMEM + StartPC); + + if (TRUE == IsOpcodeBranch(StartPC, PreviousOp)) { + /* the sub block ends here anyway */ + return; + } + + if (IsOpcodeNop(StartPC) && IsOpcodeNop(StartPC + 4) && IsOpcodeNop(StartPC + 8)) { + /* Dont even bother */ + return; + } + + CPU_Message("***** Doing reorder (%X to %X) *****", StartPC, EndPC); + + if (InstructionCount < 0x0010) { return; } + if (InstructionCount > 0x0A00) { return; } + + CPU_Message(" Before:"); + for (Count = StartPC; Count < EndPC; Count += 4) { + RSP_LW_IMEM(Count, &RspOp.Hex); + CPU_Message(" %X %s",Count,RSPOpcodeName(RspOp.Hex,Count)); + } + + for (Count = 0; Count < InstructionCount; Count += 4) { + CurrentPC = StartPC; + PreviousOp.Hex = *(DWORD*)(RSPInfo.IMEM + CurrentPC); + ReorderedOps = 0; + + for (;;) { + CurrentPC += 4; + if (CurrentPC >= EndPC) { break; } + CurrentOp.Hex = *(DWORD*)(RSPInfo.IMEM + CurrentPC); + + if (TRUE == CompareInstructions(CurrentPC, &PreviousOp, &CurrentOp)) { + /* Move current opcode up */ + *(DWORD*)(RSPInfo.IMEM + CurrentPC - 4) = CurrentOp.Hex; + *(DWORD*)(RSPInfo.IMEM + CurrentPC) = PreviousOp.Hex; + + ReorderedOps++; + +#ifdef REORDER_BLOCK_VERBOSE + CPU_Message("Swapped %X and %X", CurrentPC - 4, CurrentPC); +#endif + } + PreviousOp.Hex = *(DWORD*)(RSPInfo.IMEM + CurrentPC); + + if (IsOpcodeNop(CurrentPC) && IsOpcodeNop(CurrentPC + 4) && IsOpcodeNop(CurrentPC + 8)) { + CurrentPC = EndPC; + } + } + + if (ReorderedOps == 0) { + Count = InstructionCount; + } + } + + CPU_Message(" After:"); + for (Count = StartPC; Count < EndPC; Count += 4) { + RSP_LW_IMEM(Count, &RspOp.Hex); + CPU_Message(" %X %s",Count,RSPOpcodeName(RspOp.Hex,Count)); + } + CPU_Message(""); +} + +void ReOrderSubBlock(RSP_BLOCK * Block) { + DWORD end = 0x0ffc; + DWORD count; + + if (!Compiler.bReOrdering) { + return; + } + if (Block->CurrPC > 0xFF0) { + return; + } + + /* find the label or jump closest to us */ + if (RspCode.LabelCount) { + for (count = 0; count < RspCode.LabelCount; count++) { + if (RspCode.BranchLabels[count] < end && RspCode.BranchLabels[count] > Block->CurrPC) { + end = RspCode.BranchLabels[count]; + } + } + } + if (RspCode.BranchCount) { + for (count = 0; count < RspCode.BranchCount; count++) { + if (RspCode.BranchLocations[count] < end && RspCode.BranchLocations[count] > Block->CurrPC) { + end = RspCode.BranchLocations[count]; + } + } + } + /* it wont actually re-order the op at the end */ + ReOrderInstructions(Block->CurrPC, end); +} + +/****************************************************** +** DetectGPRConstants +** +** Desc: +** this needs to be called on a sub-block basis, like +** after every time we hit a branch and delay slot +** +********************************************************/ + +void DetectGPRConstants(RSP_CODE * code) { + DWORD Count, Constant = 0; + + memset(&code->bIsRegConst, 0, sizeof(BOOL) * 0x20); + memset(&code->MipsRegConst, 0, sizeof(DWORD) * 0x20); + + if (!Compiler.bGPRConstants) { + return; + } + CPU_Message("***** Detecting constants *****"); + + /* R0 is constant zero, R31 or RA is not constant */ + code->bIsRegConst[0] = TRUE; + code->MipsRegConst[0] = 0; + + /* Do your global search for them */ + for (Count = 1; Count < 31; Count++) { + if (IsRegisterConstant(Count, &Constant) == TRUE) { + CPU_Message("Global: %s is a constant of: %08X", GPR_Name(Count), Constant); + code->bIsRegConst[Count] = TRUE; + code->MipsRegConst[Count] = Constant; + } + } + CPU_Message(""); +} + +/****************************************************** +** CompilerToggleBuffer and ClearX86Code +** +** Desc: +** 1> toggles the compiler buffer, useful for poorly +** taken branches like alignment +** +** 2> clears all the x86 code, jump tables etc +** +********************************************************/ + +void CompilerToggleBuffer(void) { + if (dwBuffer == MainBuffer) { + dwBuffer = SecondaryBuffer; + pLastPrimary = RecompPos; + + if (pLastSecondary == NULL) { + pLastSecondary = RecompCodeSecondary; + } + + RecompPos = pLastSecondary; + CPU_Message(" (Secondary Buffer Active 0x%08X)", pLastSecondary); + } else { + dwBuffer = MainBuffer; + pLastSecondary = RecompPos; + + if (pLastPrimary == NULL) { + pLastPrimary = RecompCode; + } + + RecompPos = pLastPrimary; + CPU_Message(" (Primary Buffer Active 0x%08X)", pLastPrimary); + } +} + +void ClearAllx86Code (void) { + extern DWORD NoOfMaps, MapsCRC[32]; + extern BYTE *JumpTables; + + memset(&MapsCRC, 0, sizeof(DWORD) * 0x20); + NoOfMaps = 0; + memset(JumpTables,0,0x1000*32); + + RecompPos = RecompCode; + + pLastPrimary = NULL; + pLastSecondary = NULL; +} + +/****************************************************** +** Link Branches +** +** Desc: +** resolves all the collected branches, x86 style +** +********************************************************/ + +void LinkBranches(RSP_BLOCK * Block) { + DWORD OrigPrgCount = *PrgCount; + DWORD Count, Target; + DWORD * JumpWord; + BYTE * X86Code; + RSP_BLOCK Save; + + if (!CurrentBlock.ResolveCount) { + return; + } + CPU_Message("***** Linking branches (%i) *****", CurrentBlock.ResolveCount); + + for (Count = 0; Count < CurrentBlock.ResolveCount; Count++) { + Target = CurrentBlock.BranchesToResolve[Count].TargetPC; + X86Code = *(JumpTable + (Target >> 2)); + + if (!X86Code) { + *PrgCount = Target; + CPU_Message(""); + CPU_Message("===== (Generate Code: %04X) =====", Target); + Save = *Block; + + /* compile this block and link */ + CompilerRSPBlock(); + LinkBranches(Block); + + *Block = Save; + CPU_Message("===== (End Generate Code: %04X) =====", Target); + CPU_Message(""); + X86Code = *(JumpTable + (Target >> 2)); + } + + JumpWord = CurrentBlock.BranchesToResolve[Count].X86JumpLoc; + x86_SetBranch32b(JumpWord, (DWORD*)X86Code); + + CPU_Message("Linked RSP branch from x86: %08X, to RSP: %X / x86: %08X", + JumpWord, Target, X86Code); + } + *PrgCount = OrigPrgCount; + CPU_Message("***** Done Linking Branches *****"); + CPU_Message(""); +} + +/****************************************************** +** BuildBranchLabels +** +** Desc: +** Branch labels are used to start and stop re-ordering +** sections as well as set the jump table to points +** within a block that are safe +** +********************************************************/ + +void BuildBranchLabels(void) { + OPCODE RspOp; + DWORD i, Dest; + +#ifdef BUILD_BRANCHLABELS_VERBOSE + CPU_Message("***** Building branch labels *****"); +#endif + + for (i = 0; i < 0x1000; i += 4) { + RspOp.Hex = *(DWORD*)(RSPInfo.IMEM + i); + + if (TRUE == IsOpcodeBranch(i, RspOp)) { + if (RspCode.LabelCount >= (sizeof(RspCode.BranchLabels) / sizeof(RspCode.BranchLabels[0])) - 1) { + CompilerWarning("Out of space for Branch Labels"); + return; + } + + if (RspCode.BranchCount >= (sizeof(RspCode.BranchLocations) / sizeof(RspCode.BranchLocations[0])) - 1) { + CompilerWarning("Out of space for Branch Locations"); + return; + } + RspCode.BranchLocations[RspCode.BranchCount++] = i; + if (RspOp.op == RSP_SPECIAL) { + /* register jump not predictable */ + } else if (RspOp.op == RSP_J || RspOp.op == RSP_JAL) { + /* for JAL its a sub-block for returns */ + Dest = (RspOp.target << 2) & 0xFFC; + RspCode.BranchLabels[RspCode.LabelCount] = Dest; + RspCode.LabelCount += 1; +#ifdef BUILD_BRANCHLABELS_VERBOSE + CPU_Message("[%02i] Added branch at %X to %X", RspCode.LabelCount, i, Dest); +#endif + } else { + Dest = (i + ((short)RspOp.offset << 2) + 4) & 0xFFC; + RspCode.BranchLabels[RspCode.LabelCount] = Dest; + RspCode.LabelCount += 1; +#ifdef BUILD_BRANCHLABELS_VERBOSE + CPU_Message("[%02i] Added branch at %X to %X", RspCode.LabelCount, i, Dest); +#endif + } + } + } + +#ifdef BUILD_BRANCHLABELS_VERBOSE + CPU_Message("***** End branch labels *****"); + CPU_Message(""); +#endif +} + +BOOL IsJumpLabel(DWORD PC) { + DWORD Count; + + if (!RspCode.LabelCount) { + return FALSE; + } + + for (Count = 0; Count < RspCode.LabelCount; Count++) { + if (PC == RspCode.BranchLabels[Count]) { + return TRUE; + } + } + return FALSE; +} + +void CompilerLinkBlocks(void) { + BYTE * KnownCode = *(JumpTable + (CompilePC >> 2)); + + CPU_Message("***** Linking block to X86: %08X *****", KnownCode); + NextInstruction = FINISH_BLOCK; + + /* block linking scenario */ + JmpLabel32("Linked block", 0); + x86_SetBranch32b(RecompPos - 4, KnownCode); +} + +void CompilerRSPBlock ( void ) { + DWORD Count, Padding, X86BaseAddress = (DWORD)RecompPos; + BYTE * IMEM_SAVE = malloc(0x1000); + + NextInstruction = NORMAL; + CompilePC = *PrgCount; + + memset(&CurrentBlock, 0, sizeof(CurrentBlock)); + CurrentBlock.StartPC = CompilePC; + CurrentBlock.CurrPC = CompilePC; + + /* Align the block to a boundary */ + if (X86BaseAddress & 7) { + Padding = (8 - (X86BaseAddress & 7)) & 7; + for (Count = 0; Count < Padding; Count++) { + CPU_Message("%08X: nop", RecompPos); + *(RecompPos++) = 0x90; + } + } + + CPU_Message("====== block %d ======", BlockID++); + CPU_Message("x86 code at: %X",RecompPos); + CPU_Message("Jumpt Table: %X",Table ); + CPU_Message("Start of Block: %X",CurrentBlock.StartPC ); + CPU_Message("====== recompiled code ======"); + + if (Compiler.bReOrdering == TRUE) { + memcpy(IMEM_SAVE, RSPInfo.IMEM, 0x1000); + ReOrderSubBlock(&CurrentBlock); + } + + /* this is for the block about to be compiled */ + *(JumpTable + (CompilePC >> 2)) = RecompPos; + + do { + /* + * Re-Ordering is setup to allow us to have loop labels + * so here we see if this is one and put it in the jump table + */ + if (NextInstruction == NORMAL && IsJumpLabel(CompilePC)) { + /* jumps come around twice */ + if (NULL == *(JumpTable + (CompilePC >> 2))) { + CPU_Message("***** Adding Jump Table Entry for PC: %04X at X86: %08X *****", CompilePC, RecompPos); + CPU_Message(""); + *(JumpTable + (CompilePC >> 2)) = RecompPos; + + /* reorder from here to next label or branch */ + CurrentBlock.CurrPC = CompilePC; + ReOrderSubBlock(&CurrentBlock); + } else if (NextInstruction != DELAY_SLOT_DONE) { + /* + * we could link the blocks here, but performance + * wise it might be better to just let it run + */ + } + } + + if (Compiler.bSections == TRUE) { + if (TRUE == RSP_DoSections()) { + continue; + } + } + +#ifdef X86_RECOMP_VERBOSE + if (FALSE == IsOpcodeNop(CompilePC)) { + CPU_Message("X86 Address: %08X", RecompPos); + } +#endif + + RSP_LW_IMEM(CompilePC, &RSPOpC.Hex); + + if (LogRDP && NextInstruction != DELAY_SLOT_DONE){ + char str[40]; + sprintf(str,"%X",CompilePC); + PushImm32(str,CompilePC); + Call_Direct(RDP_LogLoc,"RDP_LogLoc"); + AddConstToX86Reg(x86_ESP, 4); + } + + if (RSPOpC.Hex == 0xFFFFFFFF) { + /* i think this pops up an unknown op dialog */ + /* NextInstruction = FINISH_BLOCK; */ + } else { + ((void (*)()) RSP_Opcode[ RSPOpC.op ])(); + } + + switch (NextInstruction) { + case NORMAL: + CompilePC += 4; + break; + case DO_DELAY_SLOT: + NextInstruction = DELAY_SLOT; + CompilePC += 4; + break; + case DELAY_SLOT: + NextInstruction = DELAY_SLOT_DONE; + CompilePC -= 4; + break; + case FINISH_SUB_BLOCK: + NextInstruction = NORMAL; + CompilePC += 8; + if (CompilePC >= 0x1000) { + NextInstruction = FINISH_BLOCK; + } else if (NULL == *(JumpTable + (CompilePC >> 2))) { + /* this is for the new block being compiled now */ + CPU_Message("**** Continuing static SubBlock (jump table entry added for PC: %04X at X86: %08X) *****", CompilePC, RecompPos); + *(JumpTable + (CompilePC >> 2)) = RecompPos; + + CurrentBlock.CurrPC = CompilePC; + /* reorder from after delay to next label or branch */ + ReOrderSubBlock(&CurrentBlock); + } else { + CompilerLinkBlocks(); + } + break; + + case FINISH_BLOCK: break; + default: + DisplayError("Rsp Main loop\n\nWTF NextInstruction = %d",NextInstruction); + CompilePC += 4; + break; + } + } while ( NextInstruction != FINISH_BLOCK && CompilePC < 0x1000); + CPU_Message("==== end of recompiled code ===="); + + if (Compiler.bReOrdering == TRUE) { + memcpy(RSPInfo.IMEM, IMEM_SAVE, 0x1000); + } + free(IMEM_SAVE); +} + +DWORD RunRecompilerCPU ( DWORD Cycles ) { + BYTE * Block; + + RSP_Running = TRUE; + SetJumpTable(0x800); + + while (RSP_Running) { + Block = *(JumpTable + (*PrgCount >> 2)); + + if (Block == NULL) { + if (Profiling && !IndvidualBlock) { + StartTimer(Timer_Compiling); + } + + __try { + memset(&RspCode, 0, sizeof(RspCode)); + BuildBranchLabels(); + DetectGPRConstants(&RspCode); + CompilerRSPBlock(); + } __except(EXCEPTION_EXECUTE_HANDLER) { + DisplayError("Error CompilePC = %08X", CompilePC); + ClearAllx86Code(); + continue; + } + + Block = *(JumpTable + (*PrgCount >> 2)); + + /* + ** we are done compiling, but we may have references + ** to fill in still either from this block, or jumps + ** that go out of it, let's rock + **/ + + LinkBranches(&CurrentBlock); + if (Profiling && !IndvidualBlock) { + StopTimer(); + } + } + + if (Profiling && IndvidualBlock) { + StartTimer(*PrgCount); + } + + _asm { + pushad + call Block + popad + } + if (Profiling && IndvidualBlock) { + StopTimer(); + } + } + + if (IsMmxEnabled == TRUE) { + _asm emms + } + return Cycles; +} \ No newline at end of file diff --git a/Source/RSP/Recompiler CPU.h b/Source/RSP/Recompiler CPU.h new file mode 100644 index 000000000..a062452b3 --- /dev/null +++ b/Source/RSP/Recompiler CPU.h @@ -0,0 +1,114 @@ +/* + * RSP Compiler plug in for Project 64 (A Nintendo 64 emulator). + * + * (c) Copyright 2001 jabo (jabo@emulation64.com) and + * zilmar (zilmar@emulation64.com) + * + * pj64 homepage: www.pj64.net + * + * Permission to use, copy, modify and distribute Project64 in both binary and + * source form, for non-commercial purposes, is hereby granted without fee, + * providing that this license information and copyright notice appear with + * all copies and any derived work. + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event shall the authors be held liable for any damages + * arising from the use of this software. + * + * Project64 is freeware for PERSONAL USE only. Commercial users should + * seek permission of the copyright holders first. Commercial use includes + * charging money for Project64 or software derived from Project64. + * + * The copyright holders request that bug fixes and improvements to the code + * should be forwarded to them so if they want them. + * + */ + +#include "opcode.h" + +#define NORMAL 0 +#define DO_DELAY_SLOT 1 +#define DELAY_SLOT 2 +#define DELAY_SLOT_DONE 3 +#define FINISH_BLOCK 4 +#define FINISH_SUB_BLOCK 5 + +extern DWORD CompilePC, NextInstruction; +extern BOOL ChangedPC; + +#define CompilerWarning if (ShowErrors) DisplayError + +#define High16BitAccum 1 +#define Middle16BitAccum 2 +#define Low16BitAccum 4 +#define EntireAccum (Low16BitAccum|Middle16BitAccum|High16BitAccum) + +BOOL WriteToAccum (int Location, int PC); +BOOL WriteToVectorDest (DWORD DestReg, int PC); +BOOL UseRspFlags (int PC); + +BOOL DelaySlotAffectBranch(DWORD PC); +BOOL CompareInstructions(DWORD PC, OPCODE * Top, OPCODE * Bottom); +BOOL IsOpcodeBranch(DWORD PC, OPCODE RspOp); +BOOL IsOpcodeNop(DWORD PC); + +BOOL IsNextInstructionMmx(DWORD PC); +BOOL IsRegisterConstant (DWORD Reg, DWORD * Constant); + +void RSP_Element2Mmx(int MmxReg); +void RSP_MultiElement2Mmx(int MmxReg1, int MmxReg2); + +#define MainBuffer 0 +#define SecondaryBuffer 1 + +DWORD RunRecompilerCPU ( DWORD Cycles ); +void BuildRecompilerCPU ( void ); + +void CompilerRSPBlock ( void ); +void CompilerToggleBuffer (void); +BOOL RSP_DoSections(void); + +typedef struct { + DWORD StartPC, CurrPC; /* block start */ + + struct { + DWORD TargetPC; /* Target for this unknown branch */ + DWORD * X86JumpLoc; /* Our x86 dword to fill */ + } BranchesToResolve[200]; /* Branches inside or outside block */ + + DWORD ResolveCount; /* Branches with NULL jump table */ +} RSP_BLOCK; + +extern RSP_BLOCK CurrentBlock; + +typedef struct { + BOOL bIsRegConst[32]; /* BOOLean toggle for constant */ + DWORD MipsRegConst[32]; /* Value of register 32-bit */ + DWORD BranchLabels[250]; + DWORD LabelCount; + DWORD BranchLocations[250]; + DWORD BranchCount; +} RSP_CODE; + +extern RSP_CODE RspCode; + +#define IsRegConst(i) (RspCode.bIsRegConst[i]) +#define MipsRegConst(i) (RspCode.MipsRegConst[i]) + +typedef struct { + BOOL mmx, mmx2, sse; /* CPU specs and compiling */ + BOOL bFlags; /* RSP Flag Analysis */ + BOOL bReOrdering; /* Instruction reordering */ + BOOL bSections; /* Microcode sections */ + BOOL bDest; /* Vector destionation toggle */ + BOOL bAccum; /* Accumulator toggle */ + BOOL bGPRConstants; /* Analyze GPR constants */ + BOOL bAlignVector; /* Align known vector loads */ + BOOL bAudioUcode; /* Audio ucode analysis */ +} RSP_COMPILER; + +extern RSP_COMPILER Compiler; + +#define IsMmxEnabled (Compiler.mmx) +#define IsMmx2Enabled (Compiler.mmx2) +#define IsSseEnabled (Compiler.sse) \ No newline at end of file diff --git a/Source/RSP/Recompiler Ops.c b/Source/RSP/Recompiler Ops.c new file mode 100644 index 000000000..bb7006721 --- /dev/null +++ b/Source/RSP/Recompiler Ops.c @@ -0,0 +1,4702 @@ +/* + * RSP Compiler plug in for Project 64 (A Nintendo 64 emulator). + * + * (c) Copyright 2001 jabo (jabo@emulation64.com) and + * zilmar (zilmar@emulation64.com) + * + * pj64 homepage: www.pj64.net + * + * Permission to use, copy, modify and distribute Project64 in both binary and + * source form, for non-commercial purposes, is hereby granted without fee, + * providing that this license information and copyright notice appear with + * all copies and any derived work. + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event shall the authors be held liable for any damages + * arising from the use of this software. + * + * Project64 is freeware for PERSONAL USE only. Commercial users should + * seek permission of the copyright holders first. Commercial use includes + * charging money for Project64 or software derived from Project64. + * + * The copyright holders request that bug fixes and improvements to the code + * should be forwarded to them so if they want them. + * + */ + +#include +#include +#include "RSP.h" +#include "CPU.h" +#include "Recompiler CPU.h" +#include "Interpreter Ops.h" +#include "RSP Command.h" +#include "RSP Registers.h" +#include "memory.h" +#include "dma.h" +#include "log.h" +#include "x86.h" +#include "Profiling.h" + +UWORD32 Recp, RecpResult, SQroot, SQrootResult; +DWORD ESP_RegSave = 0, EBP_RegSave = 0; +DWORD BranchCompare = 0; + +/* align option affects: sw, lh, sh */ +/* align option affects: lrv, ssv, lsv */ + +#define Compile_Immediates /* ADDI, ADDIU, ANDI, ORI, XORI, LUI */ +#define Compile_GPRLoads /* LB, LH, LW, LBU, LHU */ +#define Compile_GPRStores /* SB, SH, SW */ +#define Compile_Special /* SLL, SRL, SRA, SRLV */ + /* XOR, OR, AND, SUB, SUBU, ADDU, ADD, SLT */ +#define Compile_Cop0 +#define Compile_Cop2 + +#define RSP_VectorMuls +#define RSP_VectorLoads +#define RSP_VectorMisc + +#ifdef RSP_VectorMuls +# define CompileVmulf /* Verified 12/17/2000 - Jabo */ +# define CompileVmacf /* Rewritten & Verified 12/15/2000 - Jabo */ +# define CompileVmudm /* Verified 12/17/2000 - Jabo */ +# define CompileVmudh /* Verified 12/17/2000 - Jabo */ +# define CompileVmudn /* Verified 12/17/2000 - Jabo */ +# define CompileVmudl /* Verified 12/17/2000 - Jabo */ +# define CompileVmadl +# define CompileVmadm /* Verified 12/17/2000 - Jabo */ +# define CompileVmadh /* Verified 12/15/2000 - Jabo */ +# define CompileVmadn /* Verified 12/17/2000 - Jabo */ +#endif +#ifdef RSP_VectorMisc +# define CompileVrsqh +# define CompileVrcph +# define CompileVsaw /* Verified 12/17/2000 - Jabo */ +# define CompileVabs /* Verified 12/15/2000 - Jabo */ +# define CompileVmov /* Verified 12/17/2000 - Jabo */ +# define CompileVxor /* Verified 12/17/2000 - Jabo */ +# define CompileVor /* Verified 12/17/2000 - Jabo */ +# define CompileVand /* Verified 12/17/2000 - Jabo */ +# define CompileVsub /* Verified 12/17/2000 - Jabo (watch flags) */ +# define CompileVadd /* Verified 12/17/2000 - Jabo (watch flags) */ +# define CompileVaddc +# define CompileVsubc +# define CompileVmrg +#endif +#ifdef RSP_VectorLoads +# define CompileSqv /* Verified 12/17/2000 - Jabo */ +# define CompileSdv /* Verified 12/17/2000 - Jabo */ +# define CompileSsv /* Verified 12/17/2000 - Jabo */ +# define CompileLrv /* Rewritten & Verified 12/17/2000 - Jabo */ +# define CompileLqv /* Verified 12/17/2000 - Jabo */ +# define CompileLdv /* Verified 12/17/2000 - Jabo */ +# define CompileLsv /* Verified 12/17/2000 - Jabo */ +# define CompileLlv /* Verified 12/17/2000 - Jabo */ +# define CompileSlv +#endif + +void Branch_AddRef(DWORD Target, DWORD * X86Loc) { + if (CurrentBlock.ResolveCount >= 150) { + CompilerWarning("Out of branch reference space"); + } else { + BYTE * KnownCode = *(JumpTable + (Target >> 2)); + + if (KnownCode == NULL) { + DWORD i = CurrentBlock.ResolveCount; + CurrentBlock.BranchesToResolve[i].TargetPC = Target; + CurrentBlock.BranchesToResolve[i].X86JumpLoc = X86Loc; + CurrentBlock.ResolveCount += 1; + } else { + CPU_Message(" (static jump to %X)", KnownCode); + x86_SetBranch32b((DWORD*)X86Loc, (DWORD*)KnownCode); + } + } +} + +void Cheat_r4300iOpcode ( void * FunctAddress, char * FunctName) { + CPU_Message(" %X %s",CompilePC,RSPOpcodeName(RSPOpC.Hex,CompilePC)); + MoveConstToVariable(RSPOpC.Hex, &RSPOpC.Hex, "RSPOpC.Hex" ); + Call_Direct(FunctAddress, FunctName); +} + +void Cheat_r4300iOpcodeNoMessage( void * FunctAddress, char * FunctName) { + MoveConstToVariable(RSPOpC.Hex, &RSPOpC.Hex, "RSPOpC.Hex" ); + Call_Direct(FunctAddress, FunctName); +} + +void x86_SetBranch8b(void * JumpByte, void * Destination) { + /* calculate 32-bit relative offset */ + signed int n = (BYTE*)Destination - ((BYTE*)JumpByte + 1); + + /* check limits, no pun intended */ + if (n > 0x80 || n < -0x7F) { + CompilerWarning("FATAL: Jump out of 8b range %i (PC = %04X)", n, CompilePC); + } else + *(BYTE*)(JumpByte) = (BYTE)n; +} + +void x86_SetBranch32b(void * JumpByte, void * Destination) { + *(DWORD*)(JumpByte) = (DWORD)((BYTE*)Destination - (BYTE*)((DWORD*)JumpByte + 1)); +} + +void BreakPoint() { + CPU_Message(" int 3"); + *(RecompPos++) = 0xCC; +} + +/************************* OpCode functions *************************/ +void Compile_SPECIAL ( void ) { + ((void (*)()) RSP_Special[ RSPOpC.funct ])(); +} + +void Compile_REGIMM ( void ) { + ((void (*)()) RSP_RegImm[ RSPOpC.rt ])(); +} + +void Compile_J ( void ) { + if ( NextInstruction == NORMAL ) { + CPU_Message(" %X %s",CompilePC,RSPOpcodeName(RSPOpC.Hex,CompilePC)); + NextInstruction = DO_DELAY_SLOT; + } else if ( NextInstruction == DELAY_SLOT_DONE ) { + JmpLabel32 ( "BranchToJump", 0 ); + Branch_AddRef((RSPOpC.target << 2) & 0xFFC, (DWORD*)(RecompPos - 4)); + NextInstruction = FINISH_SUB_BLOCK; + } else { + CompilerWarning("J error\nWeird Delay Slot.\n\nNextInstruction = %X\nEmulation will now stop", NextInstruction); + BreakPoint(); + } +} + +void Compile_JAL ( void ) { + if ( NextInstruction == NORMAL ) { + CPU_Message(" %X %s",CompilePC,RSPOpcodeName(RSPOpC.Hex,CompilePC)); + MoveConstToVariable(CompilePC + 8, &RSP_GPR[31].UW, "RA.W"); + NextInstruction = DO_DELAY_SLOT; + } else if ( NextInstruction == DELAY_SLOT_DONE ) { + // before we branch quickly update our stats + if (Profiling && IndvidualBlock) + { + char Str[40]; + sprintf(Str,"%03X",(RSPOpC.target << 2) & 0xFFC); + Push(x86_EAX); + PushImm32(Str,*PrgCount); + Call_Direct(StartTimer, "StartTimer"); + AddConstToX86Reg(x86_ESP, 4); + Pop(x86_EAX); + } + JmpLabel32 ( "BranchToJump", 0 ); + Branch_AddRef((RSPOpC.target << 2) & 0xFFC, (DWORD*)(RecompPos - 4)); + NextInstruction = FINISH_SUB_BLOCK; + } else { + CompilerWarning("J error\nWeird Delay Slot.\n\nNextInstruction = %X\nEmulation will now stop", NextInstruction); + BreakPoint(); + } +} + +void Compile_BEQ ( void ) { + static BOOL bDelayAffect; + + if ( NextInstruction == NORMAL ) { + CPU_Message(" %X %s",CompilePC,RSPOpcodeName(RSPOpC.Hex,CompilePC)); + if (RSPOpC.rs == 0 && RSPOpC.rt == 0) { + NextInstruction = DO_DELAY_SLOT; + return; + } + bDelayAffect = DelaySlotAffectBranch(CompilePC); + if (FALSE == bDelayAffect) { + NextInstruction = DO_DELAY_SLOT; + return; + } + if (RSPOpC.rt == 0) { + CompConstToVariable(0,&RSP_GPR[RSPOpC.rs].W,GPR_Name(RSPOpC.rs)); + } else if (RSPOpC.rs == 0) { + CompConstToVariable(0,&RSP_GPR[RSPOpC.rt].W,GPR_Name(RSPOpC.rt)); + } else { + MoveVariableToX86reg(&RSP_GPR[RSPOpC.rt].W,GPR_Name(RSPOpC.rt),x86_EAX); + CompX86regToVariable(x86_EAX,&RSP_GPR[RSPOpC.rs].W,GPR_Name(RSPOpC.rs)); + } + SetzVariable(&BranchCompare, "BranchCompare"); + NextInstruction = DO_DELAY_SLOT; + } else if ( NextInstruction == DELAY_SLOT_DONE ) { + DWORD Target = (CompilePC + ((short)RSPOpC.offset << 2) + 4) & 0xFFC; + + if (RSPOpC.rs == 0 && RSPOpC.rt == 0) { + JmpLabel32 ( "BranchToJump", 0 ); + Branch_AddRef(Target, (DWORD*)(RecompPos - 4)); + NextInstruction = FINISH_SUB_BLOCK; + return; + } + if (FALSE == bDelayAffect) { + if (RSPOpC.rt == 0) { + CompConstToVariable(0,&RSP_GPR[RSPOpC.rs].W,GPR_Name(RSPOpC.rs)); + } else if (RSPOpC.rs == 0) { + CompConstToVariable(0,&RSP_GPR[RSPOpC.rt].W,GPR_Name(RSPOpC.rt)); + } else { + MoveVariableToX86reg(&RSP_GPR[RSPOpC.rt].W,GPR_Name(RSPOpC.rt),x86_EAX); + CompX86regToVariable(x86_EAX,&RSP_GPR[RSPOpC.rs].W,GPR_Name(RSPOpC.rs)); + } + JeLabel32("BranchEqual", 0); + } else { + /* take a look at the branch compare variable */ + CompConstToVariable(TRUE, &BranchCompare, "BranchCompare"); + JeLabel32("BranchEqual", 0); + } + Branch_AddRef(Target, (DWORD*)(RecompPos - 4)); + NextInstruction = FINISH_SUB_BLOCK; + } else { + CompilerWarning("BEQ error\nWeird Delay Slot.\n\nNextInstruction = %X\nEmulation will now stop", NextInstruction); + BreakPoint(); + } +} + +void Compile_BNE ( void ) { + static BOOL bDelayAffect; + + if ( NextInstruction == NORMAL ) { + CPU_Message(" %X %s",CompilePC,RSPOpcodeName(RSPOpC.Hex,CompilePC)); + if (RSPOpC.rs == 0 && RSPOpC.rt == 0) { + NextInstruction = DO_DELAY_SLOT; + return; + } + + bDelayAffect = DelaySlotAffectBranch(CompilePC); + if (FALSE == bDelayAffect) { + NextInstruction = DO_DELAY_SLOT; + return; + } + if (RSPOpC.rt == 0) { + CompConstToVariable(0,&RSP_GPR[RSPOpC.rs].W,GPR_Name(RSPOpC.rs)); + } else if (RSPOpC.rs == 0) { + CompConstToVariable(0,&RSP_GPR[RSPOpC.rt].W,GPR_Name(RSPOpC.rt)); + } else { + MoveVariableToX86reg(&RSP_GPR[RSPOpC.rt].W,GPR_Name(RSPOpC.rt),x86_EAX); + CompX86regToVariable(x86_EAX,&RSP_GPR[RSPOpC.rs].W,GPR_Name(RSPOpC.rs)); + } + SetnzVariable(&BranchCompare, "BranchCompare"); + NextInstruction = DO_DELAY_SLOT; + } else if ( NextInstruction == DELAY_SLOT_DONE ) { + DWORD Target = (CompilePC + ((short)RSPOpC.offset << 2) + 4) & 0xFFC; + + if (RSPOpC.rs == 0 && RSPOpC.rt == 0) { + NextInstruction = FINISH_SUB_BLOCK; + return; + } + + if (FALSE == bDelayAffect) { + if (RSPOpC.rt == 0) { + CompConstToVariable(0,&RSP_GPR[RSPOpC.rs].W,GPR_Name(RSPOpC.rs)); + } else if (RSPOpC.rs == 0) { + CompConstToVariable(0,&RSP_GPR[RSPOpC.rt].W,GPR_Name(RSPOpC.rt)); + } else { + MoveVariableToX86reg(&RSP_GPR[RSPOpC.rt].W,GPR_Name(RSPOpC.rt),x86_EAX); + CompX86regToVariable(x86_EAX,&RSP_GPR[RSPOpC.rs].W,GPR_Name(RSPOpC.rs)); + } + JneLabel32("BranchNotEqual", 0); + } else { + /* take a look at the branch compare variable */ + CompConstToVariable(TRUE, &BranchCompare, "BranchCompare"); + JeLabel32("BranchNotEqual", 0); + } + Branch_AddRef(Target, (DWORD*)(RecompPos - 4)); + NextInstruction = FINISH_SUB_BLOCK; + } else { + CompilerWarning("BNE error\nWeird Delay Slot.\n\nNextInstruction = %X\nEmulation will now stop", NextInstruction); + BreakPoint(); + } +} + +void Compile_BLEZ ( void ) { + static BOOL bDelayAffect; + + if ( NextInstruction == NORMAL ) { + CPU_Message(" %X %s",CompilePC,RSPOpcodeName(RSPOpC.Hex,CompilePC)); + if (RSPOpC.rs == 0) { + NextInstruction = DO_DELAY_SLOT; + return; + } + bDelayAffect = DelaySlotAffectBranch(CompilePC); + if (FALSE == bDelayAffect) { + NextInstruction = DO_DELAY_SLOT; + return; + } + CompConstToVariable(0,&RSP_GPR[RSPOpC.rs].W,GPR_Name(RSPOpC.rs)); + SetleVariable(&BranchCompare, "BranchCompare"); + NextInstruction = DO_DELAY_SLOT; + } else if ( NextInstruction == DELAY_SLOT_DONE ) { + DWORD Target = (CompilePC + ((short)RSPOpC.offset << 2) + 4) & 0xFFC; + + if (RSPOpC.rs == 0) { + JmpLabel32 ( "BranchToJump", 0 ); + Branch_AddRef(Target, (DWORD*)(RecompPos - 4)); + NextInstruction = FINISH_SUB_BLOCK; + return; + } + if (FALSE == bDelayAffect) { + CompConstToVariable(0,&RSP_GPR[RSPOpC.rs].W,GPR_Name(RSPOpC.rs)); + JleLabel32("BranchLessEqual", 0); + } else { + /* take a look at the branch compare variable */ + CompConstToVariable(TRUE, &BranchCompare, "BranchCompare"); + JeLabel32("BranchLessEqual", 0); + } + + Branch_AddRef(Target, (DWORD*)(RecompPos - 4)); + NextInstruction = FINISH_SUB_BLOCK; + } else { + CompilerWarning("BLEZ error\nWeird Delay Slot.\n\nNextInstruction = %X\nEmulation will now stop", NextInstruction); + BreakPoint(); + } +} + +void Compile_BGTZ ( void ) { + static BOOL bDelayAffect; + + if ( NextInstruction == NORMAL ) { + CPU_Message(" %X %s",CompilePC,RSPOpcodeName(RSPOpC.Hex,CompilePC)); + if (RSPOpC.rs == 0) { + NextInstruction = DO_DELAY_SLOT; + return; + } + bDelayAffect = DelaySlotAffectBranch(CompilePC); + if (FALSE == bDelayAffect) { + NextInstruction = DO_DELAY_SLOT; + return; + } + CompConstToVariable(0,&RSP_GPR[RSPOpC.rs].W,GPR_Name(RSPOpC.rs)); + SetgVariable(&BranchCompare, "BranchCompare"); + NextInstruction = DO_DELAY_SLOT; + } else if ( NextInstruction == DELAY_SLOT_DONE ) { + DWORD Target = (CompilePC + ((short)RSPOpC.offset << 2) + 4) & 0xFFC; + + if (RSPOpC.rs == 0) { + NextInstruction = FINISH_SUB_BLOCK; + return; + } + if (FALSE == bDelayAffect) { + CompConstToVariable(0,&RSP_GPR[RSPOpC.rs].W,GPR_Name(RSPOpC.rs)); + JgLabel32("BranchGreater", 0); + } else { + /* take a look at the branch compare variable */ + CompConstToVariable(TRUE, &BranchCompare, "BranchCompare"); + JeLabel32("BranchGreater", 0); + } + Branch_AddRef(Target, (DWORD*)(RecompPos - 4)); + NextInstruction = FINISH_SUB_BLOCK; + } else { + CompilerWarning("BGTZ error\nWeird Delay Slot.\n\nNextInstruction = %X\nEmulation will now stop", NextInstruction); + BreakPoint(); + } +} + +void Compile_ADDI ( void ) { + int Immediate = (short)RSPOpC.immediate; + + #ifndef Compile_Immediates + Cheat_r4300iOpcode(RSP_Opcode_ADDI,"RSP_Opcode_ADDI"); return; + #endif + + CPU_Message(" %X %s",CompilePC,RSPOpcodeName(RSPOpC.Hex,CompilePC)); + + if (RSPOpC.rt == 0) return; + + if (RSPOpC.rt == RSPOpC.rs) { + 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) { + MoveConstToVariable(MipsRegConst(RSPOpC.rs) + Immediate, &RSP_GPR[RSPOpC.rt].UW, GPR_Name(RSPOpC.rt)); + } else { + MoveVariableToX86reg(&RSP_GPR[RSPOpC.rs].UW, GPR_Name(RSPOpC.rs), x86_EAX); + if (Immediate != 0) { + AddConstToX86Reg(x86_EAX, Immediate); + } + MoveX86regToVariable(x86_EAX, &RSP_GPR[RSPOpC.rt].UW, GPR_Name(RSPOpC.rt)); + } +} + +void Compile_ADDIU ( void ) { + int Immediate = (short)RSPOpC.immediate; + + #ifndef Compile_Immediates + Cheat_r4300iOpcode(RSP_Opcode_ADDIU,"RSP_Opcode_ADDIU"); return; + #endif + + CPU_Message(" %X %s",CompilePC,RSPOpcodeName(RSPOpC.Hex,CompilePC)); + + if (RSPOpC.rt == 0) return; + + if (RSPOpC.rt == RSPOpC.rs) { + 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); + MoveX86regToVariable(x86_EAX, &RSP_GPR[RSPOpC.rt].UW, GPR_Name(RSPOpC.rt)); + } +} + +void Compile_SLTI ( void ) { + Cheat_r4300iOpcode(RSP_Opcode_SLTI,"RSP_Opcode_SLTI"); + +} + +void Compile_SLTIU ( void ) { + Cheat_r4300iOpcode(RSP_Opcode_SLTIU,"RSP_Opcode_SLTIU"); + +} + +void Compile_ANDI ( void ) { + int Immediate = (unsigned short)RSPOpC.immediate; + + #ifndef Compile_Immediates + Cheat_r4300iOpcode(RSP_Opcode_ANDI,"RSP_Opcode_ANDI"); return; + #endif + + CPU_Message(" %X %s",CompilePC,RSPOpcodeName(RSPOpC.Hex,CompilePC)); + + if (RSPOpC.rt == 0) return; + + if (RSPOpC.rt == RSPOpC.rs) { + 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 { + MoveVariableToX86reg(&RSP_GPR[RSPOpC.rs].UW, GPR_Name(RSPOpC.rs), x86_EAX); + AndConstToX86Reg(x86_EAX, Immediate); + MoveX86regToVariable(x86_EAX, &RSP_GPR[RSPOpC.rt].UW, GPR_Name(RSPOpC.rt)); + } +} + +void Compile_ORI ( void ) { + int Immediate = (unsigned short)RSPOpC.immediate; + + #ifndef Compile_Immediates + Cheat_r4300iOpcode(RSP_Opcode_ORI,"RSP_Opcode_ORI"); return; + #endif + + CPU_Message(" %X %s",CompilePC,RSPOpcodeName(RSPOpC.Hex,CompilePC)); + + if (RSPOpC.rt == 0) return; + + if (RSPOpC.rt == RSPOpC.rs) { + OrConstToVariable(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); + if (Immediate != 0) { + OrConstToX86Reg(Immediate, x86_EAX); + } + MoveX86regToVariable(x86_EAX, &RSP_GPR[RSPOpC.rt].UW, GPR_Name(RSPOpC.rt)); + } +} + +void Compile_XORI ( void ) { + int Immediate = (unsigned short)RSPOpC.immediate; + + #ifndef Compile_Immediates + Cheat_r4300iOpcode(RSP_Opcode_XORI,"RSP_Opcode_XORI"); return; + #endif + + CPU_Message(" %X %s",CompilePC,RSPOpcodeName(RSPOpC.Hex,CompilePC)); + + if (RSPOpC.rt == 0) return; + + if (RSPOpC.rt == RSPOpC.rs) { + XorConstToVariable(&RSP_GPR[RSPOpC.rt].UW, GPR_Name(RSPOpC.rt), Immediate); + } 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); + if (Immediate != 0) { + XorConstToX86Reg(x86_EAX, Immediate); + } + MoveX86regToVariable(x86_EAX, &RSP_GPR[RSPOpC.rt].UW, GPR_Name(RSPOpC.rt)); + } +} + +void Compile_LUI ( void ) { + int constant = (short)RSPOpC.offset << 16; + + #ifndef Compile_Immediates + Cheat_r4300iOpcode(RSP_Opcode_LUI,"RSP_Opcode_LUI"); return; + #endif + + CPU_Message(" %X %s",CompilePC,RSPOpcodeName(RSPOpC.Hex,CompilePC)); + + if (RSPOpC.rt == 0) return; + MoveConstToVariable(constant, &RSP_GPR[RSPOpC.rt].W, GPR_Name(RSPOpC.rt)); +} + +void Compile_COP0 (void) { + ((void (*)()) RSP_Cop0[ RSPOpC.rs ])(); +} + +void Compile_COP2 (void) { + ((void (*)()) RSP_Cop2[ RSPOpC.rs ])(); +} + +void Compile_LB ( void ) { + int Offset = (short)RSPOpC.offset; + + #ifndef Compile_GPRLoads + Cheat_r4300iOpcode(RSP_Opcode_LB,"RSP_Opcode_LB"); return; + #endif + + CPU_Message(" %X %s",CompilePC,RSPOpcodeName(RSPOpC.Hex,CompilePC)); + + 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); + + MoveSxN64MemToX86regByte(x86_EAX, x86_EBX); + MoveX86regToVariable(x86_EAX, &RSP_GPR[RSPOpC.rt].UW, GPR_Name(RSPOpC.rt)); +} + +void Compile_LH ( void ) { + int Offset = (short)RSPOpC.offset; + BYTE * Jump[2]; + + #ifndef Compile_GPRLoads + Cheat_r4300iOpcode(RSP_Opcode_LH,"RSP_Opcode_LH"); return; + #endif + + CPU_Message(" %X %s",CompilePC,RSPOpcodeName(RSPOpC.Hex,CompilePC)); + + if (IsRegConst(RSPOpC.base) == TRUE) { + DWORD Addr = (MipsRegConst(RSPOpC.base) + Offset) ^ 2; + Addr &= 0xfff; + + if ((Addr & 1) != 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, 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); + + TestConstToX86Reg(1, x86_EBX); + JneLabel32("Unaligned", 0); + Jump[0] = RecompPos - 4; + + CompilerToggleBuffer(); + + CPU_Message(" Unaligned:"); + x86_SetBranch32b(Jump[0], RecompPos); + + X86BreakPoint(__FILE__,__LINE__); + JmpLabel32("Done", 0); + Jump[1] = RecompPos - 4; + + CompilerToggleBuffer(); + + XorConstToX86Reg(x86_EBX, 2); + AndConstToX86Reg(x86_EBX, 0x0fff); + + MoveSxN64MemToX86regHalf(x86_EAX, x86_EBX); + MoveX86regToVariable(x86_EAX, &RSP_GPR[RSPOpC.rt].UW, GPR_Name(RSPOpC.rt)); + + CPU_Message(" Done:"); + x86_SetBranch32b(Jump[1], RecompPos); +} + +void Compile_LW ( void ) { + int Offset = (short)RSPOpC.offset; + BYTE * Jump[2]; + + #ifndef Compile_GPRLoads + Cheat_r4300iOpcode(RSP_Opcode_LW,"RSP_Opcode_LW"); return; + #endif + + CPU_Message(" %X %s",CompilePC,RSPOpcodeName(RSPOpC.Hex,CompilePC)); + + if (IsRegConst(RSPOpC.base) == TRUE) { + DWORD Addr = (MipsRegConst(RSPOpC.base) + Offset) & 0xfff; + + if ((Addr & 3) != 0) { + CompilerWarning("Unaligned LW at constant address PC = %04X", CompilePC); + Cheat_r4300iOpcodeNoMessage(RSP_Opcode_LW,"RSP_Opcode_LW"); + } else { + char Address[32]; + sprintf(Address, "Dmem + %Xh", Addr); + MoveVariableToX86reg(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); + + TestConstToX86Reg(3, x86_EBX); + JneLabel32("UnAligned", 0); + Jump[0] = RecompPos - 4; + + CompilerToggleBuffer(); + + x86_SetBranch32b(Jump[0], RecompPos); + CPU_Message(" Unaligned:"); + + LeaSourceAndOffset(x86_ECX , x86_EBX, 2); + LeaSourceAndOffset(x86_EDX , x86_EBX, 3); + MoveX86RegToX86Reg(x86_EBX, x86_EAX); + AddConstToX86Reg(x86_EBX, 1); + + XorConstToX86Reg(x86_EAX, 3); + XorConstToX86Reg(x86_EBX, 3); + XorConstToX86Reg(x86_ECX, 3); + XorConstToX86Reg(x86_EDX, 3); + MoveN64MemToX86regByte(x86_EAX, x86_EAX); + MoveN64MemToX86regByte(x86_EBX, x86_EBX); + MoveN64MemToX86regByte(x86_ECX, x86_ECX); + MoveN64MemToX86regByte(x86_EDX, x86_EDX); + MoveX86regByteToVariable(x86_EAX, &RSP_GPR[RSPOpC.rt].UB[3], GPR_Name(RSPOpC.rt)); + MoveX86regByteToVariable(x86_EBX, &RSP_GPR[RSPOpC.rt].UB[2], GPR_Name(RSPOpC.rt)); + MoveX86regByteToVariable(x86_ECX, &RSP_GPR[RSPOpC.rt].UB[1], GPR_Name(RSPOpC.rt)); + MoveX86regByteToVariable(x86_EDX, &RSP_GPR[RSPOpC.rt].UB[0], GPR_Name(RSPOpC.rt)); + + JmpLabel32("Done", 0); + Jump[1] = RecompPos - 4; + CompilerToggleBuffer(); + + AndConstToX86Reg(x86_EBX, 0x0fff); + MoveN64MemToX86reg(x86_EAX, x86_EBX); + MoveX86regToVariable(x86_EAX, &RSP_GPR[RSPOpC.rt].UW, GPR_Name(RSPOpC.rt)); + + CPU_Message(" Done:"); + x86_SetBranch32b(Jump[1], RecompPos); +} + +void Compile_LBU ( void ) { + int Offset = (short)RSPOpC.offset; + + #ifndef Compile_GPRLoads + Cheat_r4300iOpcode(RSP_Opcode_LBU,"RSP_Opcode_LBU"); return; + #endif + + CPU_Message(" %X %s",CompilePC,RSPOpcodeName(RSPOpC.Hex,CompilePC)); + + MoveVariableToX86reg(&RSP_GPR[RSPOpC.base].UW, GPR_Name(RSPOpC.base), x86_EBX); + XorX86RegToX86Reg(x86_EAX, x86_EAX); + + if (Offset != 0) AddConstToX86Reg(x86_EBX, Offset); + XorConstToX86Reg(x86_EBX, 3); + AndConstToX86Reg(x86_EBX, 0x0fff); + + MoveN64MemToX86regByte(x86_EAX, x86_EBX); + MoveX86regToVariable(x86_EAX, &RSP_GPR[RSPOpC.rt].UW, GPR_Name(RSPOpC.rt)); +} + +void Compile_LHU ( void ) { + int Offset = (short)RSPOpC.offset; + BYTE * Jump[2]; + + #ifndef Compile_GPRLoads + Cheat_r4300iOpcode(RSP_Opcode_LHU,"RSP_Opcode_LHU"); return; + #endif + + CPU_Message(" %X %s",CompilePC,RSPOpcodeName(RSPOpC.Hex,CompilePC)); + + if (IsRegConst(RSPOpC.base) == TRUE) { + DWORD Addr = (MipsRegConst(RSPOpC.base) + Offset) ^ 2; + Addr &= 0xfff; + + if ((Addr & 1) != 0) { + CompilerWarning("Unaligned LHU at constant address PC = %04X", CompilePC); + Cheat_r4300iOpcodeNoMessage(RSP_Opcode_LHU,"RSP_Opcode_LHU"); + return; + } else { + char Address[32]; + sprintf(Address, "Dmem + %Xh", Addr); + MoveZxVariableToX86regHalf(RSPInfo.DMEM + Addr, Address, x86_ECX); + MoveX86regToVariable(x86_ECX, &RSP_GPR[RSPOpC.rt].UW, GPR_Name(RSPOpC.rt)); + return; + } + } + + /* + * should really just do it by bytes but whatever for now + */ + MoveVariableToX86reg(&RSP_GPR[RSPOpC.base].UW, GPR_Name(RSPOpC.base), x86_EBX); + if (Offset != 0) { + AddConstToX86Reg(x86_EBX, Offset); + } + TestConstToX86Reg(1, x86_EBX); + JneLabel32("Unaligned", 0); + Jump[0] = RecompPos - 4; + + CompilerToggleBuffer(); + CPU_Message(" Unaligned:"); + x86_SetBranch32b(Jump[0], RecompPos); + Cheat_r4300iOpcodeNoMessage(RSP_Opcode_LHU,"RSP_Opcode_LHU"); + JmpLabel32("Done", 0); + Jump[1] = RecompPos - 4; + CompilerToggleBuffer(); + + XorConstToX86Reg(x86_EBX, 2); + AndConstToX86Reg(x86_EBX, 0x0fff); + MoveZxN64MemToX86regHalf(x86_EAX, x86_EBX); + MoveX86regToVariable(x86_EAX, &RSP_GPR[RSPOpC.rt].UW, GPR_Name(RSPOpC.rt)); + + CPU_Message(" Done:"); + x86_SetBranch32b(Jump[1], RecompPos); +} + +void Compile_SB ( void ) { + int Offset = (short)RSPOpC.offset; + + #ifndef Compile_GPRStores + Cheat_r4300iOpcode(RSP_Opcode_SB,"RSP_Opcode_SB"); return; + #endif + + 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 (Offset != 0) AddConstToX86Reg(x86_EBX, Offset); + XorConstToX86Reg(x86_EBX, 3); + AndConstToX86Reg(x86_EBX, 0x0fff); + + MoveX86regByteToN64Mem(x86_EAX, x86_EBX); +} + +void Compile_SH ( void ) { + int Offset = (short)RSPOpC.offset; + BYTE * Jump[2]; + + #ifndef Compile_GPRStores + Cheat_r4300iOpcode(RSP_Opcode_SH,"RSP_Opcode_SH"); return; + #endif + + CPU_Message(" %X %s",CompilePC,RSPOpcodeName(RSPOpC.Hex,CompilePC)); + + if (IsRegConst(RSPOpC.base) == TRUE) { + DWORD Addr = (MipsRegConst(RSPOpC.base) + Offset) ^ 2; + Addr &= 0xfff; + + if ((Offset & 1) != 0) { + CompilerWarning("Unaligned SH at constant address PC = %04X", CompilePC); + Cheat_r4300iOpcodeNoMessage(RSP_Opcode_SH,"RSP_Opcode_SH"); + return; + } 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); + return; + } + } + + MoveVariableToX86reg(&RSP_GPR[RSPOpC.base].UW, GPR_Name(RSPOpC.base), x86_EBX); + if (Offset != 0) AddConstToX86Reg(x86_EBX, Offset); + + TestConstToX86Reg(1, x86_EBX); + JneLabel32("Unaligned", 0); + Jump[0] = RecompPos - 4; + + CompilerToggleBuffer(); + + CPU_Message(" Unaligned:"); + x86_SetBranch32b(Jump[0], RecompPos); + + X86BreakPoint(__FILE__,__LINE__); + JmpLabel32("Done", 0); + Jump[1] = RecompPos - 4; + + CompilerToggleBuffer(); + + 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); + + CPU_Message(" Done:"); + x86_SetBranch32b(Jump[1], RecompPos); +} + +void Compile_SW ( void ) { + int Offset = (short)RSPOpC.offset; + BYTE * Jump[2]; + + #ifndef Compile_GPRStores + Cheat_r4300iOpcode(RSP_Opcode_SW,"RSP_Opcode_SW"); return; + #endif + + CPU_Message(" %X %s",CompilePC,RSPOpcodeName(RSPOpC.Hex,CompilePC)); + + if (IsRegConst(RSPOpC.base) == TRUE) { + 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"); + 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); + return; + } + } + + MoveVariableToX86reg(&RSP_GPR[RSPOpC.base].UW, GPR_Name(RSPOpC.base), x86_EBX); + if (Offset != 0) AddConstToX86Reg(x86_EBX, Offset); + + TestConstToX86Reg(3, x86_EBX); + JneLabel32("Unaligned", 0); + Jump[0] = RecompPos - 4; + + CompilerToggleBuffer(); + + CPU_Message(" Unaligned:"); + x86_SetBranch32b(Jump[0], RecompPos); + +// X86BreakPoint(__FILE__,__LINE__); + + Push(x86_EBX); + LeaSourceAndOffset(x86_ECX , x86_EBX, 2); + LeaSourceAndOffset(x86_EDX , x86_EBX, 3); + XorConstToX86Reg(x86_ECX, 3); + XorConstToX86Reg(x86_EDX, 3); + MoveVariableToX86regByte(&RSP_GPR[RSPOpC.rt].UB[1], GPR_Name(RSPOpC.rt),x86_EAX); //cx + MoveVariableToX86regByte(&RSP_GPR[RSPOpC.rt].UB[0], GPR_Name(RSPOpC.rt),x86_EBX); //dx + MoveX86regByteToN64Mem(x86_EAX, x86_ECX); + MoveX86regByteToN64Mem(x86_EBX, x86_EDX); + Pop(x86_EBX); + + MoveX86RegToX86Reg(x86_EBX, x86_EAX); + AddConstToX86Reg(x86_EBX, 1); + XorConstToX86Reg(x86_EAX, 3); + XorConstToX86Reg(x86_EBX, 3); + + MoveVariableToX86regByte(&RSP_GPR[RSPOpC.rt].UB[3], GPR_Name(RSPOpC.rt),x86_ECX); //ax + MoveVariableToX86regByte(&RSP_GPR[RSPOpC.rt].UB[2], GPR_Name(RSPOpC.rt),x86_EDX); //bx + + MoveX86regByteToN64Mem(x86_ECX, x86_EAX); + MoveX86regByteToN64Mem(x86_EDX, x86_EBX); + + JmpLabel32("Done", 0); + Jump[1] = RecompPos - 4; + + CompilerToggleBuffer(); + + AndConstToX86Reg(x86_EBX, 0x0fff); + if (RSPOpC.rt == 0) { + XorX86RegToX86Reg(x86_EAX,x86_EAX); + } else { + MoveVariableToX86reg(&RSP_GPR[RSPOpC.rt].UW, GPR_Name(RSPOpC.rt), x86_EAX); + } + MoveX86regToN64Mem(x86_EAX, x86_EBX); + + CPU_Message(" Done:"); + x86_SetBranch32b(Jump[1], RecompPos); +} + +void Compile_LC2 (void) { + ((void (*)()) RSP_Lc2 [ RSPOpC.rd ])(); +} + +void Compile_SC2 (void) { + ((void (*)()) RSP_Sc2 [ RSPOpC.rd ])(); +} +/********************** R4300i OpCodes: Special **********************/ + +void Compile_Special_SLL ( void ) { + #ifndef Compile_Special + Cheat_r4300iOpcode(RSP_Special_SLL,"RSP_Special_SLL"); return; + #endif + + CPU_Message(" %X %s",CompilePC,RSPOpcodeName(RSPOpC.Hex,CompilePC)); + if (RSPOpC.rd == 0) return; + + if (RSPOpC.rd == RSPOpC.rt) { + ShiftLeftSignVariableImmed(&RSP_GPR[RSPOpC.rd].W, GPR_Name(RSPOpC.rd), (BYTE)RSPOpC.sa); + } else { + MoveVariableToX86reg(&RSP_GPR[RSPOpC.rt].W, GPR_Name(RSPOpC.rt), x86_EAX); + ShiftLeftSignImmed(x86_EAX, (BYTE)RSPOpC.sa); + MoveX86regToVariable(x86_EAX, &RSP_GPR[RSPOpC.rd].W, GPR_Name(RSPOpC.rd)); + } +} + +void Compile_Special_SRL ( void ) { + #ifndef Compile_Special + Cheat_r4300iOpcode(RSP_Special_SRL,"RSP_Special_SRL"); return; + #endif + + CPU_Message(" %X %s",CompilePC,RSPOpcodeName(RSPOpC.Hex,CompilePC)); + if (RSPOpC.rd == 0) return; + + if (RSPOpC.rd == RSPOpC.rt) { + ShiftRightUnsignVariableImmed(&RSP_GPR[RSPOpC.rd].W, GPR_Name(RSPOpC.rd), (BYTE)RSPOpC.sa); + } else { + MoveVariableToX86reg(&RSP_GPR[RSPOpC.rt].W, GPR_Name(RSPOpC.rt), x86_EAX); + ShiftRightUnsignImmed(x86_EAX, (BYTE)RSPOpC.sa); + MoveX86regToVariable(x86_EAX, &RSP_GPR[RSPOpC.rd].W, GPR_Name(RSPOpC.rd)); + } +} + +void Compile_Special_SRA ( void ) { + #ifndef Compile_Special + Cheat_r4300iOpcode(RSP_Special_SRA,"RSP_Special_SRA"); return; + #endif + + CPU_Message(" %X %s",CompilePC,RSPOpcodeName(RSPOpC.Hex,CompilePC)); + if (RSPOpC.rd == 0) return; + + if (RSPOpC.rd == RSPOpC.rt) { + ShiftRightSignVariableImmed(&RSP_GPR[RSPOpC.rd].W, GPR_Name(RSPOpC.rd), (BYTE)RSPOpC.sa); + } else { + MoveVariableToX86reg(&RSP_GPR[RSPOpC.rt].W, GPR_Name(RSPOpC.rt), x86_EAX); + ShiftRightSignImmed(x86_EAX, (BYTE)RSPOpC.sa); + MoveX86regToVariable(x86_EAX, &RSP_GPR[RSPOpC.rd].W, GPR_Name(RSPOpC.rd)); + } +} + +void Compile_Special_SLLV ( void ) { + Cheat_r4300iOpcode(RSP_Special_SLLV,"RSP_Special_SLLV"); +} + +void Compile_Special_SRLV ( void ) { + #ifndef Compile_Special + Cheat_r4300iOpcode(RSP_Special_SRLV,"RSP_Special_SRLV"); return; + #endif + + CPU_Message(" %X %s",CompilePC,RSPOpcodeName(RSPOpC.Hex,CompilePC)); + if (RSPOpC.rd == 0) return; + + MoveVariableToX86reg(&RSP_GPR[RSPOpC.rt].W, GPR_Name(RSPOpC.rt), x86_EAX); + MoveVariableToX86reg(&RSP_GPR[RSPOpC.rs].W, GPR_Name(RSPOpC.rs), x86_ECX); + AndConstToX86Reg(x86_ECX, 0x1F); + ShiftRightUnsign(x86_EAX); + MoveX86regToVariable(x86_EAX, &RSP_GPR[RSPOpC.rd].W, GPR_Name(RSPOpC.rd)); +} + +void Compile_Special_SRAV ( void ) { + Cheat_r4300iOpcode(RSP_Special_SRAV,"RSP_Special_SRAV"); +} + +void UpdateAudioTimer() { +/* char Label[100]; + sprintf(Label,"COMMAND: %02X (PC = %08X)",RSP_GPR[1].UW >> 1, *PrgCount); + StartTimer(Label);*/ +} + +void Compile_Special_JR (void) { + BYTE * Jump; + + if ( NextInstruction == NORMAL ) { + CPU_Message(" %X %s",CompilePC,RSPOpcodeName(RSPOpC.Hex,CompilePC)); + /* transfer destination to location pointed to by PrgCount */ + MoveVariableToX86reg(&RSP_GPR[RSPOpC.rs].W,GPR_Name(RSPOpC.rs),x86_EAX); + AndConstToX86Reg(x86_EAX,0xFFC); + MoveX86regToVariable(x86_EAX,PrgCount,"RSP PC"); + ChangedPC = TRUE; + NextInstruction = DO_DELAY_SLOT; + } else if ( NextInstruction == DELAY_SLOT_DONE ) { + MoveVariableToX86reg(PrgCount,"RSP PC", x86_EAX); + if (Profiling && IndvidualBlock) + { + Push(x86_EAX); + Push(x86_EAX); + Call_Direct(StartTimer, "StartTimer"); + AddConstToX86Reg(x86_ESP, 4); + Pop(x86_EAX); + } + AddVariableToX86reg(x86_EAX, &JumpTable, "JumpTable"); + MoveX86regPointerToX86reg(x86_EAX, x86_EAX); + + TestX86RegToX86Reg(x86_EAX, x86_EAX); + JeLabel8("Null", 0); + Jump = RecompPos - 1; + + // before we branch quickly update our stats + /*if (CompilePC == 0x080) { + Pushad(); + Call_Direct(UpdateAudioTimer, "UpdateAudioTimer"); + Popad(); + }*/ + JumpX86Reg(x86_EAX); + + x86_SetBranch8b(Jump, RecompPos); + CPU_Message(" Null:"); + Ret(); + ChangedPC = FALSE; + NextInstruction = FINISH_SUB_BLOCK; + } else { + CompilerWarning("WTF\n\nJR\nNextInstruction = %X", NextInstruction); + BreakPoint(); + } +} + +void Compile_Special_JALR ( void ) { + BYTE * Jump; + DWORD Const = (CompilePC + 8) & 0xFFC; + + if (NextInstruction == NORMAL) { + CPU_Message(" %X %s",CompilePC,RSPOpcodeName(RSPOpC.Hex,CompilePC)); + MoveConstToVariable(Const, &RSP_GPR[RSPOpC.rd].W,GPR_Name(RSPOpC.rd)); + MoveVariableToX86reg(&RSP_GPR[RSPOpC.rs].W,GPR_Name(RSPOpC.rs),x86_EAX); + AndConstToX86Reg(x86_EAX,0xFFC); + MoveX86regToVariable(x86_EAX,PrgCount,"RSP PC"); + NextInstruction = DO_DELAY_SLOT; + } else if (NextInstruction == DELAY_SLOT_DONE) { + MoveVariableToX86reg(PrgCount,"RSP PC", x86_EAX); + AddVariableToX86reg(x86_EAX, &JumpTable, "JumpTable"); + MoveX86regPointerToX86reg(x86_EAX, x86_EAX); + + TestX86RegToX86Reg(x86_EAX, x86_EAX); + JeLabel8("Null", 0); + Jump = RecompPos - 1; + JumpX86Reg(x86_EAX); + + x86_SetBranch8b(Jump, RecompPos); + CPU_Message(" Null:"); + Ret(); + NextInstruction = FINISH_SUB_BLOCK; + } else { + CompilerWarning("WTF\n\nJALR\nNextInstruction = %X", NextInstruction); + BreakPoint(); + } +} + +void Compile_Special_BREAK ( void ) { + Cheat_r4300iOpcode(RSP_Special_BREAK,"RSP_Special_BREAK"); + if (NextInstruction != NORMAL) { + DisplayError("Compile_Special_BREAK: problem"); + } + MoveConstToVariable(CompilePC + 4,PrgCount,"RSP PC"); + Ret(); + NextInstruction = FINISH_BLOCK; +} + +void Compile_Special_ADD ( void ) { + #ifndef Compile_Special + Cheat_r4300iOpcode(RSP_Special_ADD,"RSP_Special_ADD"); return; + #endif + + CPU_Message(" %X %s",CompilePC,RSPOpcodeName(RSPOpC.Hex,CompilePC)); + + if (RSPOpC.rd == 0) return; + + if (RSPOpC.rd == RSPOpC.rs) { + MoveVariableToX86reg(&RSP_GPR[RSPOpC.rt].W, GPR_Name(RSPOpC.rt), x86_EAX); + AddX86regToVariable(x86_EAX, &RSP_GPR[RSPOpC.rd].W, GPR_Name(RSPOpC.rd)); + } else if (RSPOpC.rd == RSPOpC.rt) { + MoveVariableToX86reg(&RSP_GPR[RSPOpC.rs].W, GPR_Name(RSPOpC.rs), x86_EAX); + AddX86regToVariable(x86_EAX, &RSP_GPR[RSPOpC.rd].W, GPR_Name(RSPOpC.rd)); + } else if (RSPOpC.rs == RSPOpC.rt) { + MoveVariableToX86reg(&RSP_GPR[RSPOpC.rs].W, GPR_Name(RSPOpC.rs), x86_EAX); + AddX86RegToX86Reg(x86_EAX, x86_EAX); + MoveX86regToVariable(x86_EAX, &RSP_GPR[RSPOpC.rd].W, GPR_Name(RSPOpC.rd)); + } else if (RSPOpC.rs == 0) { + MoveVariableToX86reg(&RSP_GPR[RSPOpC.rt].W, GPR_Name(RSPOpC.rt), x86_EAX); + MoveX86regToVariable(x86_EAX, &RSP_GPR[RSPOpC.rd].W, GPR_Name(RSPOpC.rd)); + } else if (RSPOpC.rt == 0) { + MoveVariableToX86reg(&RSP_GPR[RSPOpC.rs].W, GPR_Name(RSPOpC.rs), x86_EAX); + MoveX86regToVariable(x86_EAX, &RSP_GPR[RSPOpC.rd].W, GPR_Name(RSPOpC.rd)); + } else { + MoveVariableToX86reg(&RSP_GPR[RSPOpC.rs].W, GPR_Name(RSPOpC.rs), x86_EAX); + AddVariableToX86reg(x86_EAX, &RSP_GPR[RSPOpC.rt].W, GPR_Name(RSPOpC.rt)); + MoveX86regToVariable(x86_EAX, &RSP_GPR[RSPOpC.rd].W, GPR_Name(RSPOpC.rd)); + } +} + +void Compile_Special_ADDU ( void ) { + #ifndef Compile_Special + Cheat_r4300iOpcode(RSP_Special_ADDU,"RSP_Special_ADDU"); return; + #endif + + CPU_Message(" %X %s",CompilePC,RSPOpcodeName(RSPOpC.Hex,CompilePC)); + + if (RSPOpC.rd == 0) return; + + if (RSPOpC.rd == RSPOpC.rs) { + MoveVariableToX86reg(&RSP_GPR[RSPOpC.rt].W, GPR_Name(RSPOpC.rt), x86_EAX); + AddX86regToVariable(x86_EAX, &RSP_GPR[RSPOpC.rd].W, GPR_Name(RSPOpC.rd)); + } else if (RSPOpC.rd == RSPOpC.rt) { + MoveVariableToX86reg(&RSP_GPR[RSPOpC.rs].W, GPR_Name(RSPOpC.rs), x86_EAX); + AddX86regToVariable(x86_EAX, &RSP_GPR[RSPOpC.rd].W, GPR_Name(RSPOpC.rd)); + } else if (RSPOpC.rs == RSPOpC.rt) { + MoveVariableToX86reg(&RSP_GPR[RSPOpC.rs].W, GPR_Name(RSPOpC.rs), x86_EAX); + AddX86RegToX86Reg(x86_EAX, x86_EAX); + MoveX86regToVariable(x86_EAX, &RSP_GPR[RSPOpC.rd].W, GPR_Name(RSPOpC.rd)); + } else if (RSPOpC.rs == 0) { + MoveVariableToX86reg(&RSP_GPR[RSPOpC.rt].W, GPR_Name(RSPOpC.rt), x86_EAX); + MoveX86regToVariable(x86_EAX, &RSP_GPR[RSPOpC.rd].W, GPR_Name(RSPOpC.rd)); + } else if (RSPOpC.rt == 0) { + MoveVariableToX86reg(&RSP_GPR[RSPOpC.rs].W, GPR_Name(RSPOpC.rs), x86_EAX); + MoveX86regToVariable(x86_EAX, &RSP_GPR[RSPOpC.rd].W, GPR_Name(RSPOpC.rd)); + } else { + MoveVariableToX86reg(&RSP_GPR[RSPOpC.rs].W, GPR_Name(RSPOpC.rs), x86_EAX); + AddVariableToX86reg(x86_EAX, &RSP_GPR[RSPOpC.rt].W, GPR_Name(RSPOpC.rt)); + MoveX86regToVariable(x86_EAX, &RSP_GPR[RSPOpC.rd].W, GPR_Name(RSPOpC.rd)); + } +} + +void Compile_Special_SUB ( void ) { + #ifndef Compile_Special + Cheat_r4300iOpcode(RSP_Special_SUB,"RSP_Special_SUB"); return; + #endif + + CPU_Message(" %X %s",CompilePC,RSPOpcodeName(RSPOpC.Hex,CompilePC)); + + if (RSPOpC.rd == 0) return; + + if (RSPOpC.rd == RSPOpC.rs) { + MoveVariableToX86reg(&RSP_GPR[RSPOpC.rt].W, GPR_Name(RSPOpC.rt), x86_EAX); + SubX86regFromVariable(x86_EAX, &RSP_GPR[RSPOpC.rd].W, "RSP_GPR[RSPOpC.rd].W"); + } else if (RSPOpC.rs == RSPOpC.rt) { + MoveConstToVariable(0, &RSP_GPR[RSPOpC.rd].W, GPR_Name(RSPOpC.rd)); + } else { + MoveVariableToX86reg(&RSP_GPR[RSPOpC.rs].W, GPR_Name(RSPOpC.rs), x86_EAX); + SubVariableFromX86reg(x86_EAX, &RSP_GPR[RSPOpC.rt].W, GPR_Name(RSPOpC.rt)); + MoveX86regToVariable(x86_EAX, &RSP_GPR[RSPOpC.rd].W, GPR_Name(RSPOpC.rd)); + } +} + +void Compile_Special_SUBU ( void ) { + #ifndef Compile_Special + Cheat_r4300iOpcode(RSP_Special_SUBU,"RSP_Special_SUBU"); return; + #endif + + CPU_Message(" %X %s",CompilePC,RSPOpcodeName(RSPOpC.Hex,CompilePC)); + + if (RSPOpC.rd == 0) return; + + if (RSPOpC.rd == RSPOpC.rs) { + MoveVariableToX86reg(&RSP_GPR[RSPOpC.rt].W, GPR_Name(RSPOpC.rt), x86_EAX); + SubX86regFromVariable(x86_EAX, &RSP_GPR[RSPOpC.rd].W, GPR_Name(RSPOpC.rd)); + } else if (RSPOpC.rs == RSPOpC.rt) { + MoveConstToVariable(0, &RSP_GPR[RSPOpC.rd].W, GPR_Name(RSPOpC.rd)); + } else { + MoveVariableToX86reg(&RSP_GPR[RSPOpC.rs].W, GPR_Name(RSPOpC.rs), x86_EAX); + SubVariableFromX86reg(x86_EAX, &RSP_GPR[RSPOpC.rt].W, GPR_Name(RSPOpC.rt)); + MoveX86regToVariable(x86_EAX, &RSP_GPR[RSPOpC.rd].W, GPR_Name(RSPOpC.rd)); + } +} + +void Compile_Special_AND ( void ) { + #ifndef Compile_Special + Cheat_r4300iOpcode(RSP_Special_AND,"RSP_Special_AND"); return; + #endif + + CPU_Message(" %X %s",CompilePC,RSPOpcodeName(RSPOpC.Hex,CompilePC)); + + if (RSPOpC.rd == 0) return; + + if (RSPOpC.rd == RSPOpC.rs) { + MoveVariableToX86reg(&RSP_GPR[RSPOpC.rt].W, GPR_Name(RSPOpC.rt), x86_EAX); + AndX86RegToVariable(&RSP_GPR[RSPOpC.rd].W, GPR_Name(RSPOpC.rd), x86_EAX); + } else if (RSPOpC.rd == RSPOpC.rt) { + MoveVariableToX86reg(&RSP_GPR[RSPOpC.rs].W, GPR_Name(RSPOpC.rs), x86_EAX); + AndX86RegToVariable(&RSP_GPR[RSPOpC.rd].W, GPR_Name(RSPOpC.rd), x86_EAX); + } else if (RSPOpC.rs == RSPOpC.rt) { + MoveVariableToX86reg(&RSP_GPR[RSPOpC.rs].W, GPR_Name(RSPOpC.rs), x86_EAX); + MoveX86regToVariable(x86_EAX, &RSP_GPR[RSPOpC.rd].W, GPR_Name(RSPOpC.rd)); + } else { + MoveVariableToX86reg(&RSP_GPR[RSPOpC.rs].W, GPR_Name(RSPOpC.rs), x86_EAX); + AndVariableToX86Reg(&RSP_GPR[RSPOpC.rt].W, GPR_Name(RSPOpC.rt), x86_EAX); + MoveX86regToVariable(x86_EAX, &RSP_GPR[RSPOpC.rd].W, GPR_Name(RSPOpC.rd)); + } +} + +void Compile_Special_OR ( void ) { + #ifndef Compile_Special + Cheat_r4300iOpcode(RSP_Special_OR,"RSP_Special_OR"); return; + #endif + + CPU_Message(" %X %s",CompilePC,RSPOpcodeName(RSPOpC.Hex,CompilePC)); + + if (RSPOpC.rd == 0) return; + + if (RSPOpC.rd == RSPOpC.rs) { + MoveVariableToX86reg(&RSP_GPR[RSPOpC.rt].W, GPR_Name(RSPOpC.rt), x86_EAX); + OrX86RegToVariable(&RSP_GPR[RSPOpC.rd].W, GPR_Name(RSPOpC.rd), x86_EAX); + } else if (RSPOpC.rd == RSPOpC.rt) { + MoveVariableToX86reg(&RSP_GPR[RSPOpC.rs].W, GPR_Name(RSPOpC.rs), x86_EAX); + OrX86RegToVariable(&RSP_GPR[RSPOpC.rd].W, GPR_Name(RSPOpC.rd), x86_EAX); + } else if (RSPOpC.rs == 0) { + MoveVariableToX86reg(&RSP_GPR[RSPOpC.rt].W, GPR_Name(RSPOpC.rt), x86_EAX); + MoveX86regToVariable(x86_EAX, &RSP_GPR[RSPOpC.rd].W, GPR_Name(RSPOpC.rd)); + } else if (RSPOpC.rt == 0) { + MoveVariableToX86reg(&RSP_GPR[RSPOpC.rs].W, GPR_Name(RSPOpC.rs), x86_EAX); + MoveX86regToVariable(x86_EAX, &RSP_GPR[RSPOpC.rd].W, GPR_Name(RSPOpC.rd)); + } else { + MoveVariableToX86reg(&RSP_GPR[RSPOpC.rs].W, GPR_Name(RSPOpC.rs), x86_EAX); + OrVariableToX86Reg(&RSP_GPR[RSPOpC.rt].W, GPR_Name(RSPOpC.rt), x86_EAX); + MoveX86regToVariable(x86_EAX, &RSP_GPR[RSPOpC.rd].W, GPR_Name(RSPOpC.rd)); + } +} + +void Compile_Special_XOR ( void ) { + #ifndef Compile_Special + Cheat_r4300iOpcode(RSP_Special_XOR,"RSP_Special_XOR"); return; + #endif + + CPU_Message(" %X %s",CompilePC,RSPOpcodeName(RSPOpC.Hex,CompilePC)); + + if (RSPOpC.rd == 0) return; + + if (RSPOpC.rd == RSPOpC.rs) { + MoveVariableToX86reg(&RSP_GPR[RSPOpC.rt].W, GPR_Name(RSPOpC.rt), x86_EAX); + XorX86RegToVariable(&RSP_GPR[RSPOpC.rd].W, GPR_Name(RSPOpC.rd), x86_EAX); + } else if (RSPOpC.rd == RSPOpC.rt) { + MoveVariableToX86reg(&RSP_GPR[RSPOpC.rs].W, GPR_Name(RSPOpC.rs), x86_EAX); + XorX86RegToVariable(&RSP_GPR[RSPOpC.rd].W, GPR_Name(RSPOpC.rd), x86_EAX); + } else if (RSPOpC.rs == RSPOpC.rt) { + MoveConstToVariable(0, &RSP_GPR[RSPOpC.rd].W, GPR_Name(RSPOpC.rd)); + } else { + MoveVariableToX86reg(&RSP_GPR[RSPOpC.rs].W, GPR_Name(RSPOpC.rs), x86_EAX); + XorVariableToX86reg(&RSP_GPR[RSPOpC.rt].W, GPR_Name(RSPOpC.rt), x86_EAX); + MoveX86regToVariable(x86_EAX, &RSP_GPR[RSPOpC.rd].W, GPR_Name(RSPOpC.rd)); + } +} + +void Compile_Special_NOR ( void ) { + Cheat_r4300iOpcode(RSP_Special_NOR,"RSP_Special_NOR"); +} + +void Compile_Special_SLT ( void ) { + #ifndef Compile_Special + Cheat_r4300iOpcode(RSP_Special_SLT,"RSP_Special_SLT"); return; + #endif + + CPU_Message(" %X %s",CompilePC,RSPOpcodeName(RSPOpC.Hex,CompilePC)); + if (RSPOpC.rt == 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); + CompConstToX86reg(x86_EAX, 0); + Setg(x86_EBX); + } else if (RSPOpC.rt == 0) { + MoveVariableToX86reg(&RSP_GPR[RSPOpC.rs].UW, GPR_Name(RSPOpC.rs), x86_EAX); + CompConstToX86reg(x86_EAX, 0); + Setl(x86_EBX); + } else { + MoveVariableToX86reg(&RSP_GPR[RSPOpC.rs].UW, GPR_Name(RSPOpC.rs), x86_EAX); + CompX86regToVariable(x86_EAX, &RSP_GPR[RSPOpC.rt].UW, GPR_Name(RSPOpC.rt)); + Setl(x86_EBX); + } + MoveX86regToVariable(x86_EBX, &RSP_GPR[RSPOpC.rd].UW, GPR_Name(RSPOpC.rd)); + } +} + +void Compile_Special_SLTU ( void ) { + Cheat_r4300iOpcode(RSP_Special_SLTU,"RSP_Special_SLTU"); +} + +/********************** R4300i OpCodes: RegImm **********************/ +void Compile_RegImm_BLTZ ( void ) { + static BOOL bDelayAffect; + + if ( NextInstruction == NORMAL ) { + CPU_Message(" %X %s",CompilePC,RSPOpcodeName(RSPOpC.Hex,CompilePC)); + if (RSPOpC.rs == 0) { + NextInstruction = DO_DELAY_SLOT; + return; + } + bDelayAffect = DelaySlotAffectBranch(CompilePC); + if (FALSE == bDelayAffect) { + NextInstruction = DO_DELAY_SLOT; + return; + } + CompConstToVariable(0,&RSP_GPR[RSPOpC.rs].W,GPR_Name(RSPOpC.rs)); + SetlVariable(&BranchCompare, "BranchCompare"); + NextInstruction = DO_DELAY_SLOT; + } else if ( NextInstruction == DELAY_SLOT_DONE ) { + DWORD Target = (CompilePC + ((short)RSPOpC.offset << 2) + 4) & 0xFFC; + + if (RSPOpC.rs == 0) { + NextInstruction = FINISH_SUB_BLOCK; + return; + } + if (FALSE == bDelayAffect) { + CompConstToVariable(0,&RSP_GPR[RSPOpC.rs].W,GPR_Name(RSPOpC.rs)); + JlLabel32("BranchLess", 0); + } else { + /* take a look at the branch compare variable */ + CompConstToVariable(TRUE, &BranchCompare, "BranchCompare"); + JeLabel32("BranchLess", 0); + } + Branch_AddRef(Target, (DWORD*)(RecompPos - 4)); + NextInstruction = FINISH_SUB_BLOCK; + } else { + CompilerWarning("BLTZ error\nWeird Delay Slot.\n\nNextInstruction = %X\nPC = %X\nEmulation will now stop", NextInstruction, CompilePC); + BreakPoint(); + } +} + +void Compile_RegImm_BGEZ ( void ) { + static BOOL bDelayAffect; + + if ( NextInstruction == NORMAL ) { + CPU_Message(" %X %s",CompilePC,RSPOpcodeName(RSPOpC.Hex,CompilePC)); + if (RSPOpC.rs == 0) { + NextInstruction = DO_DELAY_SLOT; + return; + } + bDelayAffect = DelaySlotAffectBranch(CompilePC); + if (FALSE == bDelayAffect) { + NextInstruction = DO_DELAY_SLOT; + return; + } + CompConstToVariable(0,&RSP_GPR[RSPOpC.rs].W,GPR_Name(RSPOpC.rs)); + SetgeVariable(&BranchCompare, "BranchCompare"); + NextInstruction = DO_DELAY_SLOT; + } else if ( NextInstruction == DELAY_SLOT_DONE ) { + DWORD Target = (CompilePC + ((short)RSPOpC.offset << 2) + 4) & 0xFFC; + + if (RSPOpC.rs == 0) { + JmpLabel32 ( "BranchToJump", 0 ); + Branch_AddRef(Target, (DWORD*)(RecompPos - 4)); + NextInstruction = FINISH_SUB_BLOCK; + return; + } + if (FALSE == bDelayAffect) { + CompConstToVariable(0,&RSP_GPR[RSPOpC.rs].W,GPR_Name(RSPOpC.rs)); + JgeLabel32("BranchGreaterEqual", 0); + } else { + /* take a look at the branch compare variable */ + CompConstToVariable(TRUE, &BranchCompare, "BranchCompare"); + JeLabel32("BranchGreaterEqual", 0); + } + Branch_AddRef(Target, (DWORD*)(RecompPos - 4)); + NextInstruction = FINISH_SUB_BLOCK; + } else { + CompilerWarning("BGEZ error\nWeird Delay Slot.\n\nNextInstruction = %X\nEmulation will now stop", NextInstruction); + BreakPoint(); + } +} + +void Compile_RegImm_BLTZAL ( void ) { + if ( NextInstruction == NORMAL ) { + CPU_Message(" %X %s",CompilePC,RSPOpcodeName(RSPOpC.Hex,CompilePC)); + MoveConstToVariable(CompilePC + 8, &RSP_GPR[31].UW, "RA.W"); + if (RSPOpC.rs == 0) { + NextInstruction = DO_DELAY_SLOT; + return; + } + CompConstToVariable(0,&RSP_GPR[RSPOpC.rs].W,GPR_Name(RSPOpC.rs)); + SetlVariable(&BranchCompare, "BranchCompare"); + NextInstruction = DO_DELAY_SLOT; + } else if ( NextInstruction == DELAY_SLOT_DONE ) { + DWORD Target = (CompilePC + ((short)RSPOpC.offset << 2) + 4) & 0xFFC; + + if (RSPOpC.rs == 0) { + NextInstruction = FINISH_SUB_BLOCK; + return; + } + + /* take a look at the branch compare variable */ + CompConstToVariable(TRUE, &BranchCompare, "BranchCompare"); + JeLabel32("BranchLessEqual", 0); + Branch_AddRef(Target, (DWORD*)(RecompPos - 4)); + NextInstruction = FINISH_SUB_BLOCK; + } else { + CompilerWarning("BLTZAL error\nWeird Delay Slot.\n\nNextInstruction = %X\nEmulation will now stop", NextInstruction); + BreakPoint(); + } +} + +void Compile_RegImm_BGEZAL ( void ) { + static BOOL bDelayAffect; + + if ( NextInstruction == NORMAL ) { + CPU_Message(" %X %s",CompilePC,RSPOpcodeName(RSPOpC.Hex,CompilePC)); + MoveConstToVariable(CompilePC + 8, &RSP_GPR[31].UW, "RA.W"); + if (RSPOpC.rs == 0) { + NextInstruction = DO_DELAY_SLOT; + return; + } + bDelayAffect = DelaySlotAffectBranch(CompilePC); + if (FALSE == bDelayAffect) { + NextInstruction = DO_DELAY_SLOT; + return; + } + CompConstToVariable(0,&RSP_GPR[RSPOpC.rs].W,GPR_Name(RSPOpC.rs)); + SetgeVariable(&BranchCompare, "BranchCompare"); + NextInstruction = DO_DELAY_SLOT; + } else if ( NextInstruction == DELAY_SLOT_DONE ) { + DWORD Target = (CompilePC + ((short)RSPOpC.offset << 2) + 4) & 0xFFC; + + if (RSPOpC.rs == 0) { + JmpLabel32 ( "BranchToJump", 0 ); + Branch_AddRef(Target, (DWORD*)(RecompPos - 4)); + NextInstruction = FINISH_SUB_BLOCK; + return; + } + if (FALSE == bDelayAffect) { + CompConstToVariable(0,&RSP_GPR[RSPOpC.rs].W,GPR_Name(RSPOpC.rs)); + JgeLabel32("BranchGreaterEqual", 0); + } else { + /* take a look at the branch compare variable */ + CompConstToVariable(TRUE, &BranchCompare, "BranchCompare"); + JeLabel32("BranchGreaterEqual", 0); + } + Branch_AddRef(Target, (DWORD*)(RecompPos - 4)); + NextInstruction = FINISH_SUB_BLOCK; + } else { + CompilerWarning("BGEZAL error\nWeird Delay Slot.\n\nNextInstruction = %X\nEmulation will now stop", NextInstruction); + BreakPoint(); + } +} + +/************************** Cop0 functions *************************/ + +void Compile_Cop0_MF ( void ) { + #ifndef Compile_Cop0 + Cheat_r4300iOpcode(RSP_Cop0_MF,"RSP_Cop0_MF"); return; + #endif + + CPU_Message(" %X %s",CompilePC,RSPOpcodeName(RSPOpC.Hex,CompilePC)); + if (LogRDP) + { + char str[40]; + + sprintf(str,"%d",RSPOpC.rd); + PushImm32(str,RSPOpC.rd); + sprintf(str,"%X",CompilePC); + PushImm32(str,CompilePC); + Call_Direct(RDP_LogMF0,"RDP_LogMF0"); + AddConstToX86Reg(x86_ESP, 8); + } + + switch (RSPOpC.rd) { + case 4: + MoveVariableToX86reg(RSPInfo.SP_STATUS_REG, "SP_STATUS_REG", x86_EAX); + MoveX86regToVariable(x86_EAX, &RSP_GPR[RSPOpC.rt].UW, GPR_Name(RSPOpC.rt)); + break; + case 5: + MoveVariableToX86reg(RSPInfo.SP_DMA_FULL_REG, "SP_DMA_FULL_REG", x86_EAX); + MoveX86regToVariable(x86_EAX, &RSP_GPR[RSPOpC.rt].UW, GPR_Name(RSPOpC.rt)); + break; + case 6: + MoveVariableToX86reg(RSPInfo.SP_DMA_BUSY_REG, "SP_DMA_BUSY_REG", x86_EAX); + MoveX86regToVariable(x86_EAX, &RSP_GPR[RSPOpC.rt].UW, GPR_Name(RSPOpC.rt)); + break; + case 7: + MoveConstToVariable(0, &RSP_GPR[RSPOpC.rt].UW, GPR_Name(RSPOpC.rt)); + //Cheat_r4300iOpcode(RSP_Cop0_MF,"RSP_Cop0_MF"); + break; + case 8: + MoveVariableToX86reg(RSPInfo.DPC_START_REG, "DPC_START_REG", x86_EAX); + MoveX86regToVariable(x86_EAX, &RSP_GPR[RSPOpC.rt].UW, GPR_Name(RSPOpC.rt)); + break; + case 9: + MoveVariableToX86reg(RSPInfo.DPC_END_REG, "DPC_END_REG", x86_EAX); + MoveX86regToVariable(x86_EAX, &RSP_GPR[RSPOpC.rt].UW, GPR_Name(RSPOpC.rt)); + break; + case 10: + MoveVariableToX86reg(RSPInfo.DPC_CURRENT_REG, "DPC_CURRENT_REG", x86_EAX); + MoveX86regToVariable(x86_EAX, &RSP_GPR[RSPOpC.rt].UW, GPR_Name(RSPOpC.rt)); + break; + case 11: + MoveVariableToX86reg(RSPInfo.DPC_STATUS_REG, "DPC_STATUS_REG", x86_EAX); + MoveX86regToVariable(x86_EAX, &RSP_GPR[RSPOpC.rt].UW, GPR_Name(RSPOpC.rt)); + break; + case 12: + MoveVariableToX86reg(RSPInfo.DPC_CLOCK_REG, "DPC_CLOCK_REG", x86_EAX); + MoveX86regToVariable(x86_EAX, &RSP_GPR[RSPOpC.rt].UW, GPR_Name(RSPOpC.rt)); + break; + + default: + CompilerWarning("have not implemented RSP MF CP0 reg %s (%d)",COP0_Name(RSPOpC.rd),RSPOpC.rd); + } +} + +void Compile_Cop0_MT ( void ) { +#ifndef Compile_Cop0 + Cheat_r4300iOpcode(RSP_Cop0_MT,"RSP_Cop0_MT"); +#else + CPU_Message(" %X %s",CompilePC,RSPOpcodeName(RSPOpC.Hex,CompilePC)); + if (LogRDP) + { + char str[40]; + + MoveVariableToX86reg(&RSP_GPR[RSPOpC.rt].UW, GPR_Name(RSPOpC.rt), x86_EAX); + Push(x86_EAX); + sprintf(str,"%d",RSPOpC.rd); + PushImm32(str,RSPOpC.rd); + sprintf(str,"%X",CompilePC); + PushImm32(str,CompilePC); + Call_Direct(RDP_LogMT0,"RDP_LogMT0"); + AddConstToX86Reg(x86_ESP, 12); + } + + switch (RSPOpC.rd) { + case 0: + MoveVariableToX86reg(&RSP_GPR[RSPOpC.rt].UW, GPR_Name(RSPOpC.rt), x86_EAX); + MoveX86regToVariable(x86_EAX, RSPInfo.SP_MEM_ADDR_REG,"SP_MEM_ADDR_REG"); + break; + case 1: + MoveVariableToX86reg(&RSP_GPR[RSPOpC.rt].UW, GPR_Name(RSPOpC.rt), x86_EAX); + MoveX86regToVariable(x86_EAX, RSPInfo.SP_DRAM_ADDR_REG,"SP_DRAM_ADDR_REG"); + break; + case 2: + MoveVariableToX86reg(&RSP_GPR[RSPOpC.rt].UW, GPR_Name(RSPOpC.rt), x86_EAX); + MoveX86regToVariable(x86_EAX, RSPInfo.SP_RD_LEN_REG,"SP_RD_LEN_REG"); + Call_Direct(SP_DMA_READ, "SP_DMA_READ"); + break; + case 3: + MoveVariableToX86reg(&RSP_GPR[RSPOpC.rt].UW, GPR_Name(RSPOpC.rt), x86_EAX); + MoveX86regToVariable(x86_EAX, RSPInfo.SP_WR_LEN_REG,"SP_WR_LEN_REG"); + Call_Direct(SP_DMA_WRITE, "SP_DMA_WRITE"); + break; + case 7: + MoveConstToVariable(0, RSPInfo.SP_SEMAPHORE_REG, "SP_SEMAPHORE_REG"); + break; + case 8: + MoveVariableToX86reg(&RSP_GPR[RSPOpC.rt].UW, GPR_Name(RSPOpC.rt), x86_EAX); + MoveX86regToVariable(x86_EAX, RSPInfo.DPC_START_REG,"DPC_START_REG"); + MoveX86regToVariable(x86_EAX, RSPInfo.DPC_CURRENT_REG,"DPC_CURRENT_REG"); + break; + case 9: + MoveVariableToX86reg(&RSP_GPR[RSPOpC.rt].UW, GPR_Name(RSPOpC.rt), x86_EAX); + MoveX86regToVariable(x86_EAX, RSPInfo.DPC_END_REG,"DPC_END_REG"); + + if (LogRDP) + { + Call_Direct(RDP_LogDlist, "RDP_LogDlist"); + } + + if (RSPInfo.ProcessRdpList != NULL) + { + if (Profiling) + { + PushImm32("Timer_RDP_Running",Timer_RDP_Running); + Call_Direct(StartTimer,"StartTimer"); + AddConstToX86Reg(x86_ESP, 4); + Push(x86_EAX); + } + Call_Direct(RSPInfo.ProcessRdpList, "ProcessRdpList"); + if (Profiling) + { + Call_Direct(StartTimer,"StartTimer"); + AddConstToX86Reg(x86_ESP, 4); + } + } + + + break; + case 10: + MoveVariableToX86reg(&RSP_GPR[RSPOpC.rt].UW, GPR_Name(RSPOpC.rt), x86_EAX); + MoveX86regToVariable(x86_EAX, RSPInfo.DPC_CURRENT_REG,"DPC_CURRENT_REG"); + break; + + default: + Cheat_r4300iOpcode(RSP_Cop0_MT,"RSP_Cop0_MT"); + break; + } +#endif + if (RSPOpC.rd == 2 && !ChangedPC) { + BYTE * Jump; + + TestConstToVariable(0x1000, RSPInfo.SP_MEM_ADDR_REG, "RSPInfo.SP_MEM_ADDR_REG"); + JeLabel8("DontExit", 0); + Jump = RecompPos - 1; + + MoveConstToVariable(CompilePC + 4,PrgCount,"RSP PC"); + Ret(); + + CPU_Message("DontExit:"); + x86_SetBranch8b(Jump, RecompPos); + } +} +/************************** Cop2 functions *************************/ + +void Compile_Cop2_MF ( void ) { + char Reg[256]; + int element = (RSPOpC.sa >> 1); + + int element1 = 15 - element; + int element2 = 15 - ((element + 1) % 16); + + #ifndef Compile_Cop2 + Cheat_r4300iOpcode(RSP_Cop2_MF,"RSP_Cop2_MF"); return; + #endif + + CPU_Message(" %X %s",CompilePC,RSPOpcodeName(RSPOpC.Hex,CompilePC)); + + if (element2 != (element1 - 1)) { + XorX86RegToX86Reg(x86_EAX, x86_EAX); + XorX86RegToX86Reg(x86_EBX, x86_EBX); + + sprintf(Reg, "RSP_Vect[%i].B[%i]", RSPOpC.rd, element1); + MoveVariableToX86regByte(&RSP_Vect[RSPOpC.rd].B[element1], Reg, x86_EAX); + + sprintf(Reg, "RSP_Vect[%i].B[%i]", RSPOpC.rd, element2); + MoveVariableToX86regByte(&RSP_Vect[RSPOpC.rd].B[element2], Reg, x86_EBX); + + ShiftLeftSignImmed(x86_EAX, 8); + OrX86RegToX86Reg(x86_EAX, x86_EBX); + Cwde(); + + MoveX86regToVariable(x86_EAX, &RSP_GPR[RSPOpC.rt].W, GPR_Name(RSPOpC.rt)); + } else { + sprintf(Reg, "RSP_Vect[%i].B[%i]", RSPOpC.rd, element2); + MoveSxVariableToX86regHalf(&RSP_Vect[RSPOpC.rd].B[element2], Reg, x86_EAX); + + MoveX86regToVariable(x86_EAX, &RSP_GPR[RSPOpC.rt].W, GPR_Name(RSPOpC.rt)); + } +} + +void Compile_Cop2_CF ( void ) { + Cheat_r4300iOpcode(RSP_Cop2_CF,"RSP_Cop2_CF"); +} + +void Compile_Cop2_MT ( void ) { + char Reg[256]; + int element = 15 - (RSPOpC.sa >> 1); + + #ifndef Compile_Cop2 + Cheat_r4300iOpcode(RSP_Cop2_MT,"RSP_Cop2_MT"); return; + #endif + + CPU_Message(" %X %s",CompilePC,RSPOpcodeName(RSPOpC.Hex,CompilePC)); + + if (element == 0) { + sprintf(Reg, "RSP_GPR[%i].B[1]", RSPOpC.rt); + MoveVariableToX86regByte(&RSP_GPR[RSPOpC.rt].B[1], Reg, x86_EAX); + + sprintf(Reg, "RSP_Vect[%i].B[%i]", RSPOpC.rd, element); + MoveX86regByteToVariable(x86_EAX, &RSP_Vect[RSPOpC.rd].B[element], Reg); + } else { + sprintf(Reg, "RSP_GPR[%i].B[0]", RSPOpC.rt); + MoveVariableToX86regHalf(&RSP_GPR[RSPOpC.rt].B[0], Reg, x86_EAX); + + sprintf(Reg, "RSP_Vect[%i].B[%i]", RSPOpC.rd, element - 1); + MoveX86regHalfToVariable(x86_EAX, &RSP_Vect[RSPOpC.rd].B[element - 1], Reg); + } +} + +void Compile_Cop2_CT ( void ) { + Cheat_r4300iOpcode(RSP_Cop2_CT,"RSP_Cop2_CT"); +} + +void Compile_COP2_VECTOR (void) { + ((void (*)()) RSP_Vector[ RSPOpC.funct ])(); +} + +/************************** Vect functions **************************/ + +UDWORD MMX_Scratch; + +void RSP_Element2Mmx(int MmxReg) { + char Reg[256]; + + DWORD Rs = RSPOpC.rs & 0x0f; + DWORD el; + + switch (Rs) { + case 0: case 1: + case 2: case 3: + case 4: case 5: + case 6: case 7: + CompilerWarning("Unimplemented RSP_Element2Mmx"); + break; + + default: + /* + * Noticed the exclusive-or of seven to take into account + * the pseudo-swapping we have in the vector registers + */ + + el = (RSPOpC.rs & 0x07) ^ 7; + + if (IsMmx2Enabled == FALSE) { + sprintf(Reg, "RSP_Vect[%i].HW[%i]", RSPOpC.rt, el); + MoveVariableToX86regHalf(&RSP_Vect[RSPOpC.rt].HW[el], Reg, x86_ECX); + MoveX86regHalfToVariable(x86_ECX, &MMX_Scratch.HW[0], "MMX_Scratch.HW[0]"); + MoveX86regHalfToVariable(x86_ECX, &MMX_Scratch.HW[1], "MMX_Scratch.HW[1]"); + MoveX86regHalfToVariable(x86_ECX, &MMX_Scratch.HW[2], "MMX_Scratch.HW[2]"); + MoveX86regHalfToVariable(x86_ECX, &MMX_Scratch.HW[3], "MMX_Scratch.HW[3]"); + MmxMoveQwordVariableToReg(MmxReg, &MMX_Scratch.HW[0], "MMX_Scratch.HW[0]"); + } else { + unsigned long Qword; + + Qword = (el >> 2) & 0x1; + el &= 0x3; + + sprintf(Reg, "RSP_Vect[%i].DW[%i]", RSPOpC.rt, Qword); + MmxShuffleMemoryToReg(MmxReg, + &RSP_Vect[RSPOpC.rt].DW[Qword], Reg, _MMX_SHUFFLE(el, el, el, el)); + } + break; + } +} + +void RSP_MultiElement2Mmx(int MmxReg1, int MmxReg2) { + char Reg[256]; + DWORD Rs = RSPOpC.rs & 0x0f; + + /* + * Ok, this is tricky, hopefully this clears it up: + * + * $vd[0] = $vd[0] + $vt[2] + * because of swapped registers becomes: + * $vd[7] = $vd[7] + $vt[5] + * + * we must perform this swap correctly, this involves the 3-bit + * xclusive or, 2-bits of which are done within a dword boundary, + * the last bit, is ignored because we are loading the source linearly, + * so the xclusive or has transparently happened on that side + * + */ + + switch (Rs) { + case 0: + case 1: + sprintf(Reg, "RSP_Vect[%i].UHW[0]", RSPOpC.rt); + MmxMoveQwordVariableToReg(MmxReg1, &RSP_Vect[RSPOpC.rt].UHW[0], Reg); + sprintf(Reg, "RSP_Vect[%i].UHW[4]", RSPOpC.rt); + MmxMoveQwordVariableToReg(MmxReg2, &RSP_Vect[RSPOpC.rt].UHW[4], Reg); + break; + case 2: + /* [0q] | 0 | 0 | 2 | 2 | 4 | 4 | 6 | 6 | */ + sprintf(Reg, "RSP_Vect[%i].DW[0]", RSPOpC.rt); + MmxShuffleMemoryToReg(MmxReg1, &RSP_Vect[RSPOpC.rt].DW[0], Reg, 0xF5); + sprintf(Reg, "RSP_Vect[%i].DW[1]", RSPOpC.rt); + MmxShuffleMemoryToReg(MmxReg2, &RSP_Vect[RSPOpC.rt].DW[1], Reg, 0xF5); + break; + case 3: + /* [1q] | 1 | 1 | 3 | 3 | 5 | 5 | 7 | 7 | */ + sprintf(Reg, "RSP_Vect[%i].DW[0]", RSPOpC.rt); + MmxShuffleMemoryToReg(MmxReg1, &RSP_Vect[RSPOpC.rt].DW[0], Reg, 0xA0); + //MmxShuffleMemoryToReg(MmxReg1, &RSP_Vect[RSPOpC.rt].DW[0], Reg, 0x0A); + sprintf(Reg, "RSP_Vect[%i].DW[1]", RSPOpC.rt); + MmxShuffleMemoryToReg(MmxReg2, &RSP_Vect[RSPOpC.rt].DW[1], Reg, 0xA0); + //MmxShuffleMemoryToReg(MmxReg2, &RSP_Vect[RSPOpC.rt].DW[1], Reg, 0x0A); + break; + case 4: + /* [0h] | 0 | 0 | 0 | 0 | 4 | 4 | 4 | 4 | */ + sprintf(Reg, "RSP_Vect[%i].DW[0]", RSPOpC.rt); + MmxShuffleMemoryToReg(MmxReg1, &RSP_Vect[RSPOpC.rt].DW[0], Reg, 0xFF); + sprintf(Reg, "RSP_Vect[%i].DW[1]", RSPOpC.rt); + MmxShuffleMemoryToReg(MmxReg2, &RSP_Vect[RSPOpC.rt].DW[1], Reg, 0xFF); + break; + case 5: + /* [1h] | 1 | 1 | 1 | 1 | 5 | 5 | 5 | 5 | */ + sprintf(Reg, "RSP_Vect[%i].DW[0]", RSPOpC.rt); + MmxShuffleMemoryToReg(MmxReg1, &RSP_Vect[RSPOpC.rt].DW[0], Reg, 0xAA); + sprintf(Reg, "RSP_Vect[%i].DW[1]", RSPOpC.rt); + MmxShuffleMemoryToReg(MmxReg2, &RSP_Vect[RSPOpC.rt].DW[1], Reg, 0xAA); + break; + case 6: + /* [2h] | 2 | 2 | 2 | 2 | 6 | 6 | 6 | 6 | */ + sprintf(Reg, "RSP_Vect[%i].DW[0]", RSPOpC.rt); + MmxShuffleMemoryToReg(MmxReg1, &RSP_Vect[RSPOpC.rt].DW[0], Reg, 0x55); + sprintf(Reg, "RSP_Vect[%i].DW[1]", RSPOpC.rt); + MmxShuffleMemoryToReg(MmxReg2, &RSP_Vect[RSPOpC.rt].DW[1], Reg, 0x55); + break; + case 7: + /* [3h] | 3 | 3 | 3 | 3 | 7 | 7 | 7 | 7 | */ + sprintf(Reg, "RSP_Vect[%i].DW[0]", RSPOpC.rt); + MmxShuffleMemoryToReg(MmxReg1, &RSP_Vect[RSPOpC.rt].DW[0], Reg, 0x00); + sprintf(Reg, "RSP_Vect[%i].DW[1]", RSPOpC.rt); + MmxShuffleMemoryToReg(MmxReg2, &RSP_Vect[RSPOpC.rt].DW[1], Reg, 0x00); + break; + + default: + CompilerWarning("Unimplemented RSP_MultiElement2Mmx [?]"); + break; + } +} + +BOOL Compile_Vector_VMULF_MMX ( void ) { + char Reg[256]; + + /* Do our MMX checks here */ + if (IsMmxEnabled == FALSE) + return FALSE; + if ((RSPOpC.rs & 0x0f) >= 2 && (RSPOpC.rs & 0x0f) <= 7 && IsMmx2Enabled == FALSE) + return FALSE; + + /* NOTE: Problem here is the lack of +/- 0x8000 rounding */ + sprintf(Reg, "RSP_Vect[%i].UHW[0]", RSPOpC.rd); + MmxMoveQwordVariableToReg(x86_MM0, &RSP_Vect[RSPOpC.rd].UHW[0], Reg); + sprintf(Reg, "RSP_Vect[%i].UHW[4]", RSPOpC.rd); + MmxMoveQwordVariableToReg(x86_MM1, &RSP_Vect[RSPOpC.rd].UHW[4], Reg); + + if ((RSPOpC.rs & 0xF) < 2) { + sprintf(Reg, "RSP_Vect[%i].UHW[0]", RSPOpC.rt); + MmxPmulhwRegToVariable(x86_MM0, &RSP_Vect[RSPOpC.rt].UHW[0], Reg); + sprintf(Reg, "RSP_Vect[%i].UHW[4]", RSPOpC.rt); + MmxPmulhwRegToVariable(x86_MM1, &RSP_Vect[RSPOpC.rt].UHW[4], Reg); + } else if ((RSPOpC.rs & 0xF) >= 8) { + RSP_Element2Mmx(x86_MM2); + MmxPmulhwRegToReg(x86_MM0, x86_MM2); + MmxPmulhwRegToReg(x86_MM1, x86_MM2); + } else { + RSP_MultiElement2Mmx(x86_MM2, x86_MM3); + MmxPmulhwRegToReg(x86_MM0, x86_MM2); + MmxPmulhwRegToReg(x86_MM1, x86_MM3); + } + MmxPsllwImmed(x86_MM0, 1); + MmxPsllwImmed(x86_MM1, 1); + + sprintf(Reg, "RSP_Vect[%i].UHW[0]", RSPOpC.sa); + MmxMoveQwordRegToVariable(x86_MM0, &RSP_Vect[RSPOpC.sa].UHW[0], Reg); + sprintf(Reg, "RSP_Vect[%i].UHW[4]", RSPOpC.sa); + MmxMoveQwordRegToVariable(x86_MM1, &RSP_Vect[RSPOpC.sa].UHW[4], Reg); + + if (IsNextInstructionMmx(CompilePC) == FALSE) + MmxEmptyMultimediaState(); + + return TRUE; +} + +void Compile_Vector_VMULF ( void ) { + char Reg[256]; + int count, el, del; + + BOOL bOptimize = ((RSPOpC.rs & 0x0f) >= 8) ? TRUE : FALSE; + BOOL bWriteToAccum = WriteToAccum(EntireAccum, CompilePC); + BOOL bWriteToDest = WriteToVectorDest(RSPOpC.sa, CompilePC); + + #ifndef CompileVmulf + Cheat_r4300iOpcode(RSP_Vector_VMULF,"RSP_Vector_VMULF"); return; + #endif + + CPU_Message(" %X %s",CompilePC,RSPOpcodeName(RSPOpC.Hex,CompilePC)); + + if (bWriteToAccum == FALSE) { + if (TRUE == Compile_Vector_VMULF_MMX()) + return; + } + + if (bOptimize == TRUE) { + del = (RSPOpC.rs & 0x07) ^ 7; + sprintf(Reg, "RSP_Vect[%i].HW[%i]", RSPOpC.rt, del); + MoveSxVariableToX86regHalf(&RSP_Vect[RSPOpC.rt].HW[del], Reg, x86_EBX); + } + + if (bWriteToDest == TRUE) { + MoveConstToX86reg(0x7fff0000, x86_ESI); + } + if (bWriteToAccum == TRUE) { + XorX86RegToX86Reg(x86_EDI, x86_EDI); + } + + for (count = 0; count < 8; count++) { + CPU_Message(" Iteration: %i", count); + + el = Indx[RSPOpC.rs].B[count]; + del = EleSpec[RSPOpC.rs].B[el]; + + sprintf(Reg, "RSP_Vect[%i].HW[%i]", RSPOpC.rd, el); + MoveSxVariableToX86regHalf(&RSP_Vect[RSPOpC.rd].HW[el], Reg, x86_EAX); + + if (RSPOpC.rt == RSPOpC.rd && !bOptimize) { + imulX86reg(x86_EAX); + } else { + if (bOptimize == FALSE) { + sprintf(Reg, "RSP_Vect[%i].HW[%i]", RSPOpC.rt, del); + MoveSxVariableToX86regHalf(&RSP_Vect[RSPOpC.rt].HW[del], Reg, x86_EBX); + } + imulX86reg(x86_EBX); + } + + ShiftLeftSignImmed(x86_EAX, 1); + AddConstToX86Reg(x86_EAX, 0x8000); + + if (bWriteToAccum == TRUE) { + MoveX86regToVariable(x86_EAX, &RSP_ACCUM[el].HW[1], "RSP_ACCUM[el].HW[1]"); + /* calculate sign extension into edx */ + MoveX86RegToX86Reg(x86_EAX, x86_EDX); + ShiftRightSignImmed(x86_EDX, 31); + } + + CompConstToX86reg(x86_EAX, 0x80008000); + + if (bWriteToAccum == TRUE) { + CondMoveEqual(x86_EDX, x86_EDI); + MoveX86regHalfToVariable(x86_EDX, &RSP_ACCUM[el].HW[3], "RSP_ACCUM[el].HW[3]"); + } + if (bWriteToDest == TRUE) { + CondMoveEqual(x86_EAX, x86_ESI); + ShiftRightUnsignImmed(x86_EAX, 16); + MoveX86regHalfToVariable(x86_EAX, &RSP_Vect[RSPOpC.sa].HW[el], "RSP_Vect[RSPOpC.sa].HW[el]"); + } + } +} + +void Compile_Vector_VMULU ( void ) { + Cheat_r4300iOpcode(RSP_Vector_VMULU,"RSP_Vector_VMULU"); +} + +BOOL Compile_Vector_VMUDL_MMX ( void ) { + char Reg[256]; + + /* Do our MMX checks here */ + if (IsMmxEnabled == FALSE) + return FALSE; + if (IsMmx2Enabled == FALSE) + return FALSE; + + sprintf(Reg, "RSP_Vect[%i].UHW[0]", RSPOpC.rd); + MmxMoveQwordVariableToReg(x86_MM0, &RSP_Vect[RSPOpC.rd].UHW[0], Reg); + sprintf(Reg, "RSP_Vect[%i].UHW[4]", RSPOpC.rd); + MmxMoveQwordVariableToReg(x86_MM1, &RSP_Vect[RSPOpC.rd].UHW[4], Reg); + + if ((RSPOpC.rs & 0xF) < 2) { + sprintf(Reg, "RSP_Vect[%i].UHW[0]", RSPOpC.rt); + MmxMoveQwordVariableToReg(x86_MM2, &RSP_Vect[RSPOpC.rt].UHW[0], Reg); + sprintf(Reg, "RSP_Vect[%i].UHW[4]", RSPOpC.rt); + MmxMoveQwordVariableToReg(x86_MM3, &RSP_Vect[RSPOpC.rt].UHW[4], Reg); + + MmxPmulhuwRegToReg(x86_MM0, x86_MM2); + MmxPmulhuwRegToReg(x86_MM1, x86_MM3); + } else if ((RSPOpC.rs & 0xF) >= 8) { + RSP_Element2Mmx(x86_MM2); + MmxPmulhuwRegToReg(x86_MM0, x86_MM2); + MmxPmulhuwRegToReg(x86_MM1, x86_MM2); + } else { + RSP_MultiElement2Mmx(x86_MM2, x86_MM3); + MmxPmulhuwRegToReg(x86_MM0, x86_MM2); + MmxPmulhuwRegToReg(x86_MM1, x86_MM3); + } + + sprintf(Reg, "RSP_Vect[%i].UHW[0]", RSPOpC.sa); + MmxMoveQwordRegToVariable(x86_MM0, &RSP_Vect[RSPOpC.sa].UHW[0], Reg); + sprintf(Reg, "RSP_Vect[%i].UHW[4]", RSPOpC.sa); + MmxMoveQwordRegToVariable(x86_MM1, &RSP_Vect[RSPOpC.sa].UHW[4], Reg); + + if (IsNextInstructionMmx(CompilePC) == FALSE) + MmxEmptyMultimediaState(); + + return TRUE; +} + +void Compile_Vector_VMUDL ( void ) { + char Reg[256]; + int count, el, del; + + BOOL bOptimize = ((RSPOpC.rs & 0x0f) >= 8) ? TRUE : FALSE; + BOOL bWriteToDest = WriteToVectorDest(RSPOpC.sa, CompilePC); + BOOL bWriteToAccum = WriteToAccum(EntireAccum, CompilePC); + + #ifndef CompileVmudl + Cheat_r4300iOpcode(RSP_Vector_VMUDL,"RSP_Vector_VMUDL"); return; + #endif + + CPU_Message(" %X %s",CompilePC,RSPOpcodeName(RSPOpC.Hex,CompilePC)); + + if (bWriteToAccum == FALSE) { + if (TRUE == Compile_Vector_VMUDL_MMX()) + return; + } + + if (bOptimize == TRUE) { + del = (RSPOpC.rs & 0x07) ^ 7; + sprintf(Reg, "RSP_Vect[%i].HW[%i]", RSPOpC.rt, del); + MoveZxVariableToX86regHalf(&RSP_Vect[RSPOpC.rt].HW[del], Reg, x86_EBX); + } + + if (bWriteToAccum == TRUE) + XorX86RegToX86Reg(x86_EDI, x86_EDI); + + for (count = 0; count < 8; count++) { + CPU_Message(" Iteration: %i", count); + el = Indx[RSPOpC.rs].B[count]; + del = EleSpec[RSPOpC.rs].B[el]; + + sprintf(Reg, "RSP_Vect[%i].UHW[%i]", RSPOpC.rd, el); + MoveZxVariableToX86regHalf(&RSP_Vect[RSPOpC.rd].UHW[el], Reg, x86_EAX); + + if (bOptimize == FALSE) { + sprintf(Reg, "RSP_Vect[%i].HW[%i]", RSPOpC.rt, del); + MoveZxVariableToX86regHalf(&RSP_Vect[RSPOpC.rt].HW[del], Reg, x86_EBX); + } + + imulX86reg(x86_EBX); + + if (bWriteToAccum == TRUE) { + sprintf(Reg, "RSP_ACCUM[%i].UW[0]", el); + MoveX86regToVariable(x86_EAX, &RSP_ACCUM[el].UW[0], Reg); + sprintf(Reg, "RSP_ACCUM[%i].UW[1]", el); + MoveX86regToVariable(x86_EDI, &RSP_ACCUM[el].UW[1], Reg); + } + + if (bWriteToDest == TRUE) { + ShiftRightUnsignImmed(x86_EAX, 16); + sprintf(Reg, "RSP_Vect[%i].HW[%i]", RSPOpC.sa, el); + MoveX86regHalfToVariable(x86_EAX, &RSP_Vect[RSPOpC.sa].HW[el], Reg); + } + } +} + +BOOL Compile_Vector_VMUDM_MMX ( void ) { + char Reg[256]; + + /* Do our MMX checks here */ + if (IsMmxEnabled == FALSE) + return FALSE; + if (IsMmx2Enabled == FALSE) + return FALSE; + + sprintf(Reg, "RSP_Vect[%i].UHW[0]", RSPOpC.rd); + MmxMoveQwordVariableToReg(x86_MM0, &RSP_Vect[RSPOpC.rd].UHW[0], Reg); + sprintf(Reg, "RSP_Vect[%i].UHW[4]", RSPOpC.rd); + MmxMoveQwordVariableToReg(x86_MM1, &RSP_Vect[RSPOpC.rd].UHW[4], Reg); + + if ((RSPOpC.rs & 0xF) < 2) { + sprintf(Reg, "RSP_Vect[%i].UHW[0]", RSPOpC.rt); + MmxMoveQwordVariableToReg(x86_MM4, &RSP_Vect[RSPOpC.rt].UHW[0], Reg); + sprintf(Reg, "RSP_Vect[%i].UHW[4]", RSPOpC.rt); + MmxMoveQwordVariableToReg(x86_MM5, &RSP_Vect[RSPOpC.rt].UHW[4], Reg); + + /* Copy the signed portion */ + MmxMoveRegToReg(x86_MM2, x86_MM0); + MmxMoveRegToReg(x86_MM3, x86_MM1); + + /* high((u16)a * b) */ + MmxPmulhuwRegToReg(x86_MM0, x86_MM4); + MmxPmulhuwRegToReg(x86_MM1, x86_MM5); + + /* low((a >> 15) * b) */ + MmxPsrawImmed(x86_MM2, 15); + MmxPsrawImmed(x86_MM3, 15); + MmxPmullwRegToReg(x86_MM2, x86_MM4); + MmxPmullwRegToReg(x86_MM3, x86_MM5); + } else if ((RSPOpC.rs & 0xF) >= 8) { + RSP_Element2Mmx(x86_MM4); + + /* Copy the signed portion */ + MmxMoveRegToReg(x86_MM2, x86_MM0); + MmxMoveRegToReg(x86_MM3, x86_MM1); + + /* high((u16)a * b) */ + MmxPmulhuwRegToReg(x86_MM0, x86_MM4); + MmxPmulhuwRegToReg(x86_MM1, x86_MM4); + + /* low((a >> 15) * b) */ + MmxPsrawImmed(x86_MM2, 15); + MmxPsrawImmed(x86_MM3, 15); + MmxPmullwRegToReg(x86_MM2, x86_MM4); + MmxPmullwRegToReg(x86_MM3, x86_MM4); + } else { + RSP_MultiElement2Mmx(x86_MM4, x86_MM5); + + /* Copy the signed portion */ + MmxMoveRegToReg(x86_MM2, x86_MM0); + MmxMoveRegToReg(x86_MM3, x86_MM1); + + /* high((u16)a * b) */ + MmxPmulhuwRegToReg(x86_MM0, x86_MM4); + MmxPmulhuwRegToReg(x86_MM1, x86_MM5); + + /* low((a >> 15) * b) */ + MmxPsrawImmed(x86_MM2, 15); + MmxPsrawImmed(x86_MM3, 15); + MmxPmullwRegToReg(x86_MM2, x86_MM4); + MmxPmullwRegToReg(x86_MM3, x86_MM5); + } + + /* Add them up */ + MmxPaddwRegToReg(x86_MM0, x86_MM2); + MmxPaddwRegToReg(x86_MM1, x86_MM3); + + sprintf(Reg, "RSP_Vect[%i].UHW[0]", RSPOpC.sa); + MmxMoveQwordRegToVariable(x86_MM0, &RSP_Vect[RSPOpC.sa].UHW[0], Reg); + sprintf(Reg, "RSP_Vect[%i].UHW[4]", RSPOpC.sa); + MmxMoveQwordRegToVariable(x86_MM1, &RSP_Vect[RSPOpC.sa].UHW[4], Reg); + + if (IsNextInstructionMmx(CompilePC) == FALSE) + MmxEmptyMultimediaState(); + + return TRUE; +} + +void Compile_Vector_VMUDM ( void ) { + char Reg[256]; + int count, el, del; + + BOOL bOptimize = ((RSPOpC.rs & 0x0f) >= 8) ? TRUE : FALSE; + BOOL bWriteToDest = WriteToVectorDest(RSPOpC.sa, CompilePC); + BOOL bWriteToAccum = WriteToAccum(EntireAccum, CompilePC); + + #ifndef CompileVmudm + Cheat_r4300iOpcode(RSP_Vector_VMUDM,"RSP_Vector_VMUDM"); return; + #endif + + CPU_Message(" %X %s",CompilePC,RSPOpcodeName(RSPOpC.Hex,CompilePC)); + + if (bWriteToAccum == FALSE) { + if (TRUE == Compile_Vector_VMUDM_MMX()) + return; + } + + if (bOptimize == TRUE) { + del = (RSPOpC.rs & 0x07) ^ 7; + sprintf(Reg, "RSP_Vect[%i].HW[%i]", RSPOpC.rt, del); + MoveZxVariableToX86regHalf(&RSP_Vect[RSPOpC.rt].HW[del], Reg, x86_EBX); + } + + Push(x86_EBP); + sprintf(Reg, "RSP_Vect[%i].HW[0]", RSPOpC.rd); + MoveOffsetToX86reg((DWORD)&RSP_Vect[RSPOpC.rd].HW[0], Reg, x86_EBP); + + if (bWriteToDest) { + sprintf(Reg, "RSP_Vect[%i].HW[0]", RSPOpC.sa); + MoveOffsetToX86reg((DWORD)&RSP_Vect[RSPOpC.sa].HW[0], Reg, x86_ECX); + } else if (!bOptimize) { + sprintf(Reg, "RSP_Vect[%i].HW[0]", RSPOpC.rt); + MoveOffsetToX86reg((DWORD)&RSP_Vect[RSPOpC.rt].HW[0], Reg, x86_ECX); + } + + for (count = 0; count < 8; count++) { + CPU_Message(" Iteration: %i", count); + el = Indx[RSPOpC.rs].B[count]; + del = EleSpec[RSPOpC.rs].B[el]; + + /*sprintf(Reg, "RSP_Vect[%i].HW[%i]", RSPOpC.rd, el); + MoveSxVariableToX86regHalf(&RSP_Vect[RSPOpC.rd].HW[el], Reg, x86_EAX);*/ + MoveSxX86RegPtrDispToX86RegHalf(x86_EBP, el * 2, x86_EAX); + + if (bOptimize == FALSE) { + if (bWriteToDest == TRUE) { + sprintf(Reg, "RSP_Vect[%i].HW[%i]", RSPOpC.rt, del); + MoveZxVariableToX86regHalf(&RSP_Vect[RSPOpC.rt].HW[del], Reg, x86_EBX); + } else { + MoveZxX86RegPtrDispToX86RegHalf(x86_ECX, del * 2, x86_EBX); + } + } + + imulX86reg(x86_EBX); + + if (bWriteToAccum == FALSE && bWriteToDest == TRUE) { + ShiftRightUnsignImmed(x86_EAX, 16); + /*sprintf(Reg, "RSP_Vect[%i].HW[%i]", RSPOpC.sa, el); + MoveX86regHalfToVariable(x86_EAX, &RSP_Vect[RSPOpC.sa].HW[el], Reg);*/ + MoveX86regHalfToX86regPointerDisp(x86_EAX, x86_ECX, el * 2); + } else { + MoveX86RegToX86Reg(x86_EAX, x86_EDX); + ShiftRightSignImmed(x86_EDX, 16); + ShiftLeftSignImmed(x86_EAX, 16); + + if (bWriteToAccum == TRUE) { + sprintf(Reg, "RSP_ACCUM[%i].UW[0]", el); + MoveX86regToVariable(x86_EAX, &RSP_ACCUM[el].UW[0], Reg); + sprintf(Reg, "RSP_ACCUM[%i].UW[1]", el); + MoveX86regToVariable(x86_EDX ,&RSP_ACCUM[el].UW[1], Reg); + } + if (bWriteToDest == TRUE) { + /*sprintf(Reg, "RSP_Vect[%i].HW[%i]", RSPOpC.sa, el); + MoveX86regHalfToVariable(x86_EDX, &RSP_Vect[RSPOpC.sa].HW[el], Reg);*/ + MoveX86regHalfToX86regPointerDisp(x86_EDX, x86_ECX, el * 2); + } + } + } + + Pop(x86_EBP); +} + +BOOL Compile_Vector_VMUDN_MMX ( void ) { + char Reg[256]; + + /* Do our MMX checks here */ + if (IsMmxEnabled == FALSE) + return FALSE; + if ((RSPOpC.rs & 0x0f) >= 2 && (RSPOpC.rs & 0x0f) <= 7 && IsMmx2Enabled == FALSE) + return FALSE; + + sprintf(Reg, "RSP_Vect[%i].UHW[0]", RSPOpC.rd); + MmxMoveQwordVariableToReg(x86_MM0, &RSP_Vect[RSPOpC.rd].UHW[0], Reg); + sprintf(Reg, "RSP_Vect[%i].UHW[4]", RSPOpC.rd); + MmxMoveQwordVariableToReg(x86_MM1, &RSP_Vect[RSPOpC.rd].UHW[4], Reg); + + if ((RSPOpC.rs & 0xF) < 2) { + sprintf(Reg, "RSP_Vect[%i].UHW[0]", RSPOpC.rt); + MmxPmullwVariableToReg(x86_MM0, &RSP_Vect[RSPOpC.rt].UHW[0], Reg); + sprintf(Reg, "RSP_Vect[%i].UHW[4]", RSPOpC.rt); + MmxPmullwVariableToReg(x86_MM1, &RSP_Vect[RSPOpC.rt].UHW[4], Reg); + } else if ((RSPOpC.rs & 0xF) >= 8) { + RSP_Element2Mmx(x86_MM2); + MmxPmullwRegToReg(x86_MM0, x86_MM2); + MmxPmullwRegToReg(x86_MM1, x86_MM2); + } else { + RSP_MultiElement2Mmx(x86_MM2, x86_MM3); + MmxPmullwRegToReg(x86_MM0, x86_MM2); + MmxPmullwRegToReg(x86_MM1, x86_MM3); + } + + sprintf(Reg, "RSP_Vect[%i].UHW[0]", RSPOpC.sa); + MmxMoveQwordRegToVariable(x86_MM0, &RSP_Vect[RSPOpC.sa].UHW[0], Reg); + sprintf(Reg, "RSP_Vect[%i].UHW[4]", RSPOpC.sa); + MmxMoveQwordRegToVariable(x86_MM1, &RSP_Vect[RSPOpC.sa].UHW[4], Reg); + + if (IsNextInstructionMmx(CompilePC) == FALSE) + MmxEmptyMultimediaState(); + + return TRUE; +} + +void Compile_Vector_VMUDN ( void ) { + char Reg[256]; + int count, el, del; + + BOOL bOptimize = ((RSPOpC.rs & 0x0f) >= 8) ? TRUE : FALSE; + BOOL bWriteToDest = WriteToVectorDest(RSPOpC.sa, CompilePC); + BOOL bWriteToAccum = WriteToAccum(EntireAccum, CompilePC); + + #ifndef CompileVmudn + Cheat_r4300iOpcode(RSP_Vector_VMUDN,"RSP_Vector_VMUDN"); return; + #endif + + CPU_Message(" %X %s",CompilePC,RSPOpcodeName(RSPOpC.Hex,CompilePC)); + + if (bWriteToAccum == FALSE) { + if (TRUE == Compile_Vector_VMUDN_MMX()) + return; + } + + if (bOptimize == TRUE) { + del = (RSPOpC.rs & 0x07) ^ 7; + sprintf(Reg, "RSP_Vect[%i].HW[%i]", RSPOpC.rt, del); + MoveSxVariableToX86regHalf(&RSP_Vect[RSPOpC.rt].HW[del], Reg, x86_EBX); + } + + Push(x86_EBP); + sprintf(Reg, "RSP_Vect[%i].HW[0]", RSPOpC.rd); + MoveOffsetToX86reg((DWORD)&RSP_Vect[RSPOpC.rd].HW[0], Reg, x86_EBP); + + for (count = 0; count < 8; count++) { + CPU_Message(" Iteration: %i", count); + el = Indx[RSPOpC.rs].B[count]; + del = EleSpec[RSPOpC.rs].B[el]; + + /*sprintf(Reg, "RSP_Vect[%i].UHW[%i]", RSPOpC.rd, el); + MoveZxVariableToX86regHalf(&RSP_Vect[RSPOpC.rd].UHW[el], Reg, x86_EAX);*/ + MoveZxX86RegPtrDispToX86RegHalf(x86_EBP, el * 2, x86_EAX); + + if (bOptimize == FALSE) { + sprintf(Reg, "RSP_Vect[%i].HW[%i]", RSPOpC.rt, del); + MoveSxVariableToX86regHalf(&RSP_Vect[RSPOpC.rt].HW[del], Reg, x86_EBX); + } + + imulX86reg(x86_EBX); + + if (bWriteToDest == TRUE) { + sprintf(Reg, "RSP_Vect[%i].HW[%i]", RSPOpC.sa, el); + MoveX86regHalfToVariable(x86_EAX, &RSP_Vect[RSPOpC.sa].HW[el], Reg); + } + + if (bWriteToAccum == TRUE) { + MoveX86RegToX86Reg(x86_EAX, x86_EDX); + ShiftRightSignImmed(x86_EDX, 16); + ShiftLeftSignImmed(x86_EAX, 16); + sprintf(Reg, "RSP_ACCUM[%i].UW[0]", el); + MoveX86regToVariable(x86_EAX, &RSP_ACCUM[el].UW[0], Reg); + sprintf(Reg, "RSP_ACCUM[%i].UW[1]", el); + MoveX86regToVariable(x86_EDX, &RSP_ACCUM[el].UW[1], Reg); + } + } + Pop(x86_EBP); +} + +BOOL Compile_Vector_VMUDH_MMX ( void ) { + char Reg[256]; + + /* Do our MMX checks here */ + if (IsMmxEnabled == FALSE) + return FALSE; + if ((RSPOpC.rs & 0x0f) >= 2 && (RSPOpC.rs & 0x0f) <= 7 && IsMmx2Enabled == FALSE) + return FALSE; + + sprintf(Reg, "RSP_Vect[%i].HW[0]", RSPOpC.rd); + MmxMoveQwordVariableToReg(x86_MM0, &RSP_Vect[RSPOpC.rd].HW[0], Reg); + sprintf(Reg, "RSP_Vect[%i].HW[4]", RSPOpC.rd); + MmxMoveQwordVariableToReg(x86_MM1, &RSP_Vect[RSPOpC.rd].HW[4], Reg); + + /* Registers 4 & 5 are high */ + MmxMoveRegToReg(x86_MM4, x86_MM0); + MmxMoveRegToReg(x86_MM5, x86_MM1); + + if ((RSPOpC.rs & 0x0f) < 2) { + sprintf(Reg, "RSP_Vect[%i].HW[0]", RSPOpC.rt); + MmxMoveQwordVariableToReg(x86_MM2, &RSP_Vect[RSPOpC.rt].HW[0], Reg); + sprintf(Reg, "RSP_Vect[%i].HW[4]", RSPOpC.rt); + MmxMoveQwordVariableToReg(x86_MM3, &RSP_Vect[RSPOpC.rt].HW[4], Reg); + + MmxPmullwRegToReg(x86_MM0, x86_MM2); + MmxPmulhwRegToReg(x86_MM4, x86_MM2); + MmxPmullwRegToReg(x86_MM1, x86_MM3); + MmxPmulhwRegToReg(x86_MM5, x86_MM3); + } else if ((RSPOpC.rs & 0x0f) >= 8) { + RSP_Element2Mmx(x86_MM2); + + MmxPmullwRegToReg(x86_MM0, x86_MM2); + MmxPmulhwRegToReg(x86_MM4, x86_MM2); + MmxPmullwRegToReg(x86_MM1, x86_MM2); + MmxPmulhwRegToReg(x86_MM5, x86_MM2); + } else { + RSP_MultiElement2Mmx(x86_MM2, x86_MM3); + + MmxPmullwRegToReg(x86_MM0, x86_MM2); + MmxPmulhwRegToReg(x86_MM4, x86_MM2); + MmxPmullwRegToReg(x86_MM1, x86_MM3); + MmxPmulhwRegToReg(x86_MM5, x86_MM3); + } + + /* 0 & 1 are low, 4 & 5 are high */ + MmxMoveRegToReg(x86_MM6, x86_MM0); + MmxMoveRegToReg(x86_MM7, x86_MM1); + + MmxUnpackLowWord(x86_MM0, x86_MM4); + MmxUnpackHighWord(x86_MM6, x86_MM4); + MmxUnpackLowWord(x86_MM1, x86_MM5); + MmxUnpackHighWord(x86_MM7, x86_MM5); + + /* Integrate copies */ + MmxPackSignedDwords(x86_MM0, x86_MM6); + MmxPackSignedDwords(x86_MM1, x86_MM7); + + sprintf(Reg, "RSP_Vect[%i].HW[0]", RSPOpC.sa); + MmxMoveQwordRegToVariable(x86_MM0, &RSP_Vect[RSPOpC.sa].HW[0], Reg); + sprintf(Reg, "RSP_Vect[%i].HW[4]", RSPOpC.sa); + MmxMoveQwordRegToVariable(x86_MM1, &RSP_Vect[RSPOpC.sa].HW[4], Reg); + + if (IsNextInstructionMmx(CompilePC) == FALSE) + MmxEmptyMultimediaState(); + + return TRUE; +} + +void Compile_Vector_VMUDH ( void ) { + char Reg[256]; + int count, el, del; + + BOOL bOptimize = ((RSPOpC.rs & 0x0f) >= 8) ? TRUE : FALSE; + BOOL bWriteToDest = WriteToVectorDest(RSPOpC.sa, CompilePC); + BOOL bWriteToAccum = WriteToAccum(EntireAccum, CompilePC); + + #ifndef CompileVmudh + Cheat_r4300iOpcode(RSP_Vector_VMUDH,"RSP_Vector_VMUDH"); return; + #endif + + CPU_Message(" %X %s",CompilePC,RSPOpcodeName(RSPOpC.Hex,CompilePC)); + + if (bWriteToAccum == FALSE) { + if (TRUE == Compile_Vector_VMUDH_MMX()) + return; + } + + if (bWriteToDest == FALSE && bOptimize == TRUE) { + Push(x86_EBP); + sprintf(Reg, "RSP_Vect[%i].HW[0]", RSPOpC.rd); + + /* Load source */ + del = (RSPOpC.rs & 0x07) ^ 7; + sprintf(Reg, "RSP_Vect[%i].HW[%i]", RSPOpC.rt, del); + MoveSxVariableToX86regHalf(&RSP_Vect[RSPOpC.rt].HW[del], Reg, x86_EBX); + + /* + * Pipe lined segment 0 + */ + + sprintf(Reg, "RSP_Vect[%i].HW[0]", RSPOpC.rd); + MoveOffsetToX86reg((DWORD)&RSP_Vect[RSPOpC.rd].HW[0], Reg, x86_EBP); + + MoveSxX86RegPtrDispToX86RegHalf(x86_EBP, 0, x86_EAX); + MoveSxX86RegPtrDispToX86RegHalf(x86_EBP, 2, x86_ECX); + MoveSxX86RegPtrDispToX86RegHalf(x86_EBP, 4, x86_EDI); + MoveSxX86RegPtrDispToX86RegHalf(x86_EBP, 6, x86_ESI); + + ImulX86RegToX86Reg(x86_EAX, x86_EBX); + ImulX86RegToX86Reg(x86_ECX, x86_EBX); + ImulX86RegToX86Reg(x86_EDI, x86_EBX); + ImulX86RegToX86Reg(x86_ESI, x86_EBX); + XorX86RegToX86Reg(x86_EDX, x86_EDX); + + MoveOffsetToX86reg((DWORD)&RSP_ACCUM[0].W[0], "RSP_ACCUM[0].W[0]", x86_EBP); + + MoveX86RegToX86regPointerDisp(x86_EDX, x86_EBP, 0); + MoveX86RegToX86regPointerDisp(x86_EAX, x86_EBP, 4); + MoveX86RegToX86regPointerDisp(x86_EDX, x86_EBP, 8); + MoveX86RegToX86regPointerDisp(x86_ECX, x86_EBP, 12); + MoveX86RegToX86regPointerDisp(x86_EDX, x86_EBP, 16); + MoveX86RegToX86regPointerDisp(x86_EDI, x86_EBP, 20); + MoveX86RegToX86regPointerDisp(x86_EDX, x86_EBP, 24); + MoveX86RegToX86regPointerDisp(x86_ESI, x86_EBP, 28); + + /* + * Pipe lined segment 1 + */ + + sprintf(Reg, "RSP_Vect[%i].HW[0]", RSPOpC.rd); + MoveOffsetToX86reg((DWORD)&RSP_Vect[RSPOpC.rd].HW[0], Reg, x86_EBP); + + MoveSxX86RegPtrDispToX86RegHalf(x86_EBP, 8, x86_EAX); + MoveSxX86RegPtrDispToX86RegHalf(x86_EBP, 10, x86_ECX); + MoveSxX86RegPtrDispToX86RegHalf(x86_EBP, 12, x86_EDI); + MoveSxX86RegPtrDispToX86RegHalf(x86_EBP, 14, x86_ESI); + + ImulX86RegToX86Reg(x86_EAX, x86_EBX); + ImulX86RegToX86Reg(x86_ECX, x86_EBX); + ImulX86RegToX86Reg(x86_EDI, x86_EBX); + ImulX86RegToX86Reg(x86_ESI, x86_EBX); + XorX86RegToX86Reg(x86_EDX, x86_EDX); + + MoveOffsetToX86reg((DWORD)&RSP_ACCUM[0].W[0], "RSP_ACCUM[0].W[0]", x86_EBP); + + MoveX86RegToX86regPointerDisp(x86_EDX, x86_EBP, 32); + MoveX86RegToX86regPointerDisp(x86_EAX, x86_EBP, 36); + MoveX86RegToX86regPointerDisp(x86_EDX, x86_EBP, 40); + MoveX86RegToX86regPointerDisp(x86_ECX, x86_EBP, 44); + MoveX86RegToX86regPointerDisp(x86_EDX, x86_EBP, 48); + MoveX86RegToX86regPointerDisp(x86_EDI, x86_EBP, 52); + MoveX86RegToX86regPointerDisp(x86_EDX, x86_EBP, 56); + MoveX86RegToX86regPointerDisp(x86_ESI, x86_EBP, 60); + + Pop(x86_EBP); + } else { + if (bOptimize == TRUE) { + del = (RSPOpC.rs & 0x07) ^ 7; + sprintf(Reg, "RSP_Vect[%i].HW[%i]", RSPOpC.rt, del); + MoveSxVariableToX86regHalf(&RSP_Vect[RSPOpC.rt].HW[del], Reg, x86_EBX); + } + if (bWriteToDest == TRUE) { + /* + * Prepare for conditional moves + */ + MoveConstToX86reg(0x00007fff, x86_ESI); + MoveConstToX86reg(0xFFFF8000, x86_EDI); + } + + for (count = 0; count < 8; count++) { + CPU_Message(" Iteration: %i", count); + el = Indx[RSPOpC.rs].B[count]; + del = EleSpec[RSPOpC.rs].B[el]; + + sprintf(Reg, "RSP_Vect[%i].HW[%i]", RSPOpC.rd, el); + MoveSxVariableToX86regHalf(&RSP_Vect[RSPOpC.rd].HW[el], Reg, x86_EAX); + + if (bOptimize == FALSE) { + sprintf(Reg, "RSP_Vect[%i].HW[%i]", RSPOpC.rt, del); + MoveSxVariableToX86regHalf(&RSP_Vect[RSPOpC.rt].HW[del], Reg, x86_EBX); + } + imulX86reg(x86_EBX); + + if (bWriteToAccum == TRUE) { + MoveX86regToVariable(x86_EAX, &RSP_ACCUM[el].W[1], "RSP_ACCUM[el].W[1]"); + MoveConstToVariable(0, &RSP_ACCUM[el].W[0], "RSP_ACCUM[el].W[0]"); + } + + if (bWriteToDest == TRUE) { + CompX86RegToX86Reg(x86_EAX, x86_ESI); + CondMoveGreater(x86_EAX, x86_ESI); + CompX86RegToX86Reg(x86_EAX, x86_EDI); + CondMoveLess(x86_EAX, x86_EDI); + + sprintf(Reg, "RSP_Vect[%i].HW[%i]", RSPOpC.sa, el); + MoveX86regHalfToVariable(x86_EAX, &RSP_Vect[RSPOpC.sa].HW[el], Reg); + } + } + } +} + +void Compile_Vector_VMACF ( void ) { + char Reg[256]; + int count, el, del; + + BOOL bOptimize = ((RSPOpC.rs & 0x0f) >= 8) ? TRUE : FALSE; + BOOL bWriteToDest = WriteToVectorDest(RSPOpC.sa, CompilePC); + BOOL bWriteToAccum = WriteToAccum(EntireAccum, CompilePC); + + #ifndef CompileVmacf + Cheat_r4300iOpcode(RSP_Vector_VMACF,"RSP_Vector_VMACF"); return; + #endif + + CPU_Message(" %X %s",CompilePC,RSPOpcodeName(RSPOpC.Hex,CompilePC)); + + if (bWriteToDest == TRUE) { + /* + * Prepare for conditional moves + */ + MoveConstToX86reg(0x00007fff, x86_ESI); + MoveConstToX86reg(0xFFFF8000, x86_EDI); + } + if (bOptimize == TRUE) { + del = (RSPOpC.rs & 0x07) ^ 7; + sprintf(Reg, "RSP_Vect[%i].HW[%i]", RSPOpC.rt, del); + MoveSxVariableToX86regHalf(&RSP_Vect[RSPOpC.rt].HW[del], Reg, x86_EBX); + } + + for (count = 0; count < 8; count++) { + el = Indx[RSPOpC.rs].B[count]; + del = EleSpec[RSPOpC.rs].B[el]; + + CPU_Message(" Iteration: %i", count); + + sprintf(Reg, "RSP_Vect[%i].HW[%i]", RSPOpC.rd, el); + MoveSxVariableToX86regHalf(&RSP_Vect[RSPOpC.rd].HW[el], Reg, x86_EAX); + + if (bOptimize == FALSE) { + sprintf(Reg, "RSP_Vect[%i].HW[%i]", RSPOpC.rt, del); + MoveSxVariableToX86regHalf(&RSP_Vect[RSPOpC.rt].HW[del], Reg, x86_EBX); + } + + imulX86reg(x86_EBX); + + MoveX86RegToX86Reg(x86_EAX, x86_EDX); + ShiftRightSignImmed(x86_EDX, 15); + ShiftLeftSignImmed(x86_EAX, 17); + + AddX86regToVariable(x86_EAX, &RSP_ACCUM[el].W[0], "RSP_ACCUM[el].W[0]"); + AdcX86regToVariable(x86_EDX, &RSP_ACCUM[el].W[1], "RSP_ACCUM[el].W[1]"); + + if (bWriteToDest == TRUE) { + MoveVariableToX86reg(&RSP_ACCUM[el].W[1], "RSP_ACCUM[el].W[1]", x86_EAX); + + CompX86RegToX86Reg(x86_EAX, x86_ESI); + CondMoveGreater(x86_EAX, x86_ESI); + CompX86RegToX86Reg(x86_EAX, x86_EDI); + CondMoveLess(x86_EAX, x86_EDI); + + sprintf(Reg, "RSP_Vect[%i].HW[%i]", RSPOpC.sa, el); + MoveX86regHalfToVariable(x86_EAX, &RSP_Vect[RSPOpC.sa].HW[el], Reg); + } + } +} + +void Compile_Vector_VMACU ( void ) { + Cheat_r4300iOpcode(RSP_Vector_VMACU,"RSP_Vector_VMACU"); +} + +void Compile_Vector_VMACQ ( void ) { + Cheat_r4300iOpcode(RSP_Vector_VMACQ,"RSP_Vector_VMACQ"); +} + +void Compile_Vector_VMADL ( void ) { + char Reg[256]; + int count, el, del; + + BOOL bOptimize = ((RSPOpC.rs & 0x0f) >= 8) ? TRUE : FALSE; + BOOL bWriteToDest = WriteToVectorDest(RSPOpC.sa, CompilePC); + + #ifndef CompileVmadl + Cheat_r4300iOpcode(RSP_Vector_VMADL,"RSP_Vector_VMADL"); return; + #endif + + CPU_Message(" %X %s",CompilePC,RSPOpcodeName(RSPOpC.Hex,CompilePC)); + + if (bOptimize == TRUE) { + del = (RSPOpC.rs & 0x07) ^ 7; + sprintf(Reg, "RSP_Vect[%i].HW[%i]", RSPOpC.rt, del); + MoveZxVariableToX86regHalf(&RSP_Vect[RSPOpC.rt].HW[del], Reg, x86_EBX); + } + + if (bWriteToDest == TRUE) { + /* + * Prepare for conditional moves + */ + MoveConstToX86reg(0x00007FFF, x86_ESI); + MoveConstToX86reg(0xFFFF8000, x86_EDI); + + Push(x86_EBP); + MoveConstToX86reg(0x0000FFFF, x86_EBP); + } + + for (count = 0; count < 8; count++) { + CPU_Message(" Iteration: %i", count); + el = Indx[RSPOpC.rs].B[count]; + del = EleSpec[RSPOpC.rs].B[el]; + + sprintf(Reg, "RSP_Vect[%i].HW[%i]", RSPOpC.rd, el); + MoveZxVariableToX86regHalf(&RSP_Vect[RSPOpC.rd].HW[el], Reg, x86_EAX); + + if (bOptimize == FALSE) { + sprintf(Reg, "RSP_Vect[%i].HW[%i]", RSPOpC.rt, del); + MoveZxVariableToX86regHalf(&RSP_Vect[RSPOpC.rt].HW[del], Reg, x86_EBX); + } + + imulX86reg(x86_EBX); + sprintf(Reg, "RSP_ACCUM[%i].W[0]", el); + AddX86regToVariable(x86_EAX, &RSP_ACCUM[el].W[0], Reg); + sprintf(Reg, "RSP_ACCUM[%i].W[1]", el); + AdcConstToVariable(&RSP_ACCUM[el].W[1], Reg, 0); + + if (bWriteToDest != FALSE) { + XorX86RegToX86Reg(x86_EDX, x86_EDX); + MoveVariableToX86reg(&RSP_ACCUM[el].W[1], "RSP_ACCUM[el].W[1]", x86_EAX); + MoveZxVariableToX86regHalf(&RSP_ACCUM[el].HW[1], "RSP_ACCUM[el].hW[1]", x86_ECX); + + CompX86RegToX86Reg(x86_EAX, x86_ESI); + CondMoveGreater(x86_ECX, x86_EBP); + CompX86RegToX86Reg(x86_EAX, x86_EDI); + CondMoveLess(x86_ECX, x86_EDX); + + sprintf(Reg, "RSP_Vect[%i].HW[%i]", RSPOpC.sa, el); + MoveX86regHalfToVariable(x86_ECX, &RSP_Vect[RSPOpC.sa].HW[el], Reg); + } + } + + if (bWriteToDest == TRUE) { + Pop(x86_EBP); + } +} + +void Compile_Vector_VMADM ( void ) { + char Reg[256]; + int count, el, del; + + BOOL bOptimize = ((RSPOpC.rs & 0x0f) >= 8) ? TRUE : FALSE; + BOOL bWriteToDest = WriteToVectorDest(RSPOpC.sa, CompilePC); + BOOL bWriteToAccum = WriteToAccum(EntireAccum, CompilePC); + + #ifndef CompileVmadm + Cheat_r4300iOpcode(RSP_Vector_VMADM,"RSP_Vector_VMADM"); return; + #endif + + CPU_Message(" %X %s",CompilePC,RSPOpcodeName(RSPOpC.Hex,CompilePC)); + + if (bOptimize == TRUE) { + del = (RSPOpC.rs & 0x07) ^ 7; + sprintf(Reg, "RSP_Vect[%i].HW[%i]", RSPOpC.rt, del); + MoveZxVariableToX86regHalf(&RSP_Vect[RSPOpC.rt].HW[del], Reg, x86_EBX); + } + if (bWriteToDest == TRUE) { + /* + * Prepare for conditional moves + */ + MoveConstToX86reg(0x00007fff, x86_ESI); + MoveConstToX86reg(0xFFFF8000, x86_EDI); + } + + Push(x86_EBP); + sprintf(Reg, "RSP_Vect[%i].HW[0]", RSPOpC.rd); + MoveOffsetToX86reg((DWORD)&RSP_Vect[RSPOpC.rd].HW[0], Reg, x86_EBP); + + if (bWriteToDest) { + sprintf(Reg, "RSP_Vect[%i].HW[0]", RSPOpC.sa); + MoveOffsetToX86reg((DWORD)&RSP_Vect[RSPOpC.sa].HW[0], Reg, x86_ECX); + } else if (!bOptimize) { + sprintf(Reg, "RSP_Vect[%i].HW[0]", RSPOpC.rt); + MoveOffsetToX86reg((DWORD)&RSP_Vect[RSPOpC.rt].HW[0], Reg, x86_ECX); + } + + for (count = 0; count < 8; count++) { + CPU_Message(" Iteration: %i", count); + el = Indx[RSPOpC.rs].B[count]; + del = EleSpec[RSPOpC.rs].B[el]; + + /*sprintf(Reg, "RSP_Vect[%i].HW[%i]", RSPOpC.rd, el); + MoveSxVariableToX86regHalf(&RSP_Vect[RSPOpC.rd].HW[el], Reg, x86_EAX);*/ + MoveSxX86RegPtrDispToX86RegHalf(x86_EBP, el * 2, x86_EAX); + + if (bOptimize == FALSE) { + if (bWriteToDest == TRUE) { + sprintf(Reg, "RSP_Vect[%i].HW[%i]", RSPOpC.rt, del); + MoveZxVariableToX86regHalf(&RSP_Vect[RSPOpC.rt].HW[del], "RSP_Vect[RSPOpC.rt].HW[del]", x86_EBX); + } else { + MoveZxX86RegPtrDispToX86RegHalf(x86_ECX, del * 2, x86_EBX); + } + } + + imulX86reg(x86_EBX); + + MoveX86RegToX86Reg(x86_EAX, x86_EDX); + ShiftRightSignImmed(x86_EDX, 16); + ShiftLeftSignImmed(x86_EAX, 16); + AddX86regToVariable(x86_EAX, &RSP_ACCUM[el].W[0], "RSP_ACCUM[el].W[0]"); + AdcX86regToVariable(x86_EDX, &RSP_ACCUM[el].W[1], "RSP_ACCUM[el].W[1]"); + + if (bWriteToDest == TRUE) { + /* For compare */ + sprintf(Reg, "RSP_ACCUM[%i].W[1]", el); + MoveVariableToX86reg(&RSP_ACCUM[el].W[1], "RSP_ACCUM[el].W[1]", x86_EAX); + + CompX86RegToX86Reg(x86_EAX, x86_ESI); + CondMoveGreater(x86_EAX, x86_ESI); + CompX86RegToX86Reg(x86_EAX, x86_EDI); + CondMoveLess(x86_EAX, x86_EDI); + + /*sprintf(Reg, "RSP_Vect[%i].HW[%i]", RSPOpC.sa, el); + MoveX86regHalfToVariable(x86_EAX, &RSP_Vect[RSPOpC.sa].HW[el], Reg);*/ + MoveX86regHalfToX86regPointerDisp(x86_EAX, x86_ECX, el * 2); + } + } + + Pop(x86_EBP); +} + +void Compile_Vector_VMADN ( void ) { + char Reg[256]; + int count, el, del; + + BOOL bOptimize = ((RSPOpC.rs & 0x0f) >= 8) ? TRUE : FALSE; + BOOL bWriteToDest = WriteToVectorDest(RSPOpC.sa, CompilePC); + BOOL bWriteToAccum = WriteToAccum(EntireAccum, CompilePC); + + #ifndef CompileVmadn + Cheat_r4300iOpcode(RSP_Vector_VMADN,"RSP_Vector_VMADN"); return; + #endif + + CPU_Message(" %X %s",CompilePC,RSPOpcodeName(RSPOpC.Hex,CompilePC)); + + if (bOptimize == TRUE) { + del = (RSPOpC.rs & 0x07) ^ 7; + sprintf(Reg, "RSP_Vect[%i].HW[%i]", RSPOpC.rt, del); + MoveSxVariableToX86regHalf(&RSP_Vect[RSPOpC.rt].HW[del], Reg, x86_EBX); + } + if (bWriteToDest == TRUE) { + /* + * Prepare for conditional moves + */ + MoveConstToX86reg(0x0000ffff, x86_ESI); + MoveConstToX86reg(0x00000000, x86_EDI); + } + + Push(x86_EBP); + sprintf(Reg, "RSP_Vect[%i].HW[0]", RSPOpC.rd); + MoveOffsetToX86reg((DWORD)&RSP_Vect[RSPOpC.rd].HW[0], Reg, x86_EBP); + + for (count = 0; count < 8; count++) { + CPU_Message(" Iteration: %i", count); + el = Indx[RSPOpC.rs].B[count]; + del = EleSpec[RSPOpC.rs].B[el]; + + /*sprintf(Reg, "RSP_Vect[%i].UHW[%i]", RSPOpC.rd, el); + MoveZxVariableToX86regHalf(&RSP_Vect[RSPOpC.rd].UHW[el], Reg, x86_EAX);*/ + MoveZxX86RegPtrDispToX86RegHalf(x86_EBP, el * 2, x86_EAX); + + if (bOptimize == FALSE) { + sprintf(Reg, "RSP_Vect[%i].HW[%i]", RSPOpC.rt, del); + MoveSxVariableToX86regHalf(&RSP_Vect[RSPOpC.rt].HW[del], Reg, x86_EBX); + } + + imulX86reg(x86_EBX); + + MoveX86RegToX86Reg(x86_EAX, x86_EDX); + ShiftRightSignImmed(x86_EDX, 16); + ShiftLeftSignImmed(x86_EAX, 16); + AddX86regToVariable(x86_EAX, &RSP_ACCUM[el].W[0], "RSP_ACCUM[el].W[0]"); + AdcX86regToVariable(x86_EDX, &RSP_ACCUM[el].W[1], "RSP_ACCUM[el].W[1]"); + + if (bWriteToDest == TRUE) { + /* For compare */ + sprintf(Reg, "RSP_ACCUM[%i].W[1]", el); + MoveVariableToX86reg(&RSP_ACCUM[el].W[1], Reg, x86_EAX); + + /* For vector */ + sprintf(Reg, "RSP_ACCUM[%i].HW[1]", el); + MoveVariableToX86regHalf(&RSP_ACCUM[el].HW[1], Reg, x86_ECX); + + /* Weird eh */ + CompConstToX86reg(x86_EAX, 0x7fff); + CondMoveGreater(x86_ECX, x86_ESI); + CompConstToX86reg(x86_EAX, -0x8000); + CondMoveLess(x86_ECX, x86_EDI); + + sprintf(Reg, "RSP_Vect[%i].HW[%i]", RSPOpC.sa, el); + MoveX86regHalfToVariable(x86_ECX, &RSP_Vect[RSPOpC.sa].HW[el], Reg); + } + } + Pop(x86_EBP); +} + +void Compile_Vector_VMADH ( void ) { + char Reg[256]; + int count, el, del; + + BOOL bOptimize = ((RSPOpC.rs & 0x0f) >= 8) ? TRUE : FALSE; + BOOL bWriteToDest = WriteToVectorDest(RSPOpC.sa, CompilePC); + + #ifndef CompileVmadh + Cheat_r4300iOpcode(RSP_Vector_VMADH,"RSP_Vector_VMADH"); return; + #endif + + CPU_Message(" %X %s",CompilePC,RSPOpcodeName(RSPOpC.Hex,CompilePC)); + + if (bOptimize == TRUE) { + del = (RSPOpC.rs & 0x07) ^ 7; + sprintf(Reg, "RSP_Vect[%i].HW[%i]", RSPOpC.rt, del); + MoveSxVariableToX86regHalf(&RSP_Vect[RSPOpC.rt].HW[del], Reg, x86_EBX); + } + + if (bWriteToDest == TRUE) { + /* + * Prepare for conditional moves + */ + MoveConstToX86reg(0x00007fff, x86_ESI); + MoveConstToX86reg(0xFFFF8000, x86_EDI); + } + + if (bWriteToDest == FALSE && bOptimize == TRUE) { + Push(x86_EBP); + sprintf(Reg, "RSP_Vect[%i].HW[0]", RSPOpC.rd); + MoveOffsetToX86reg((DWORD)&RSP_Vect[RSPOpC.rd].HW[0], Reg, x86_EBP); + + /* + * Pipe lined segment 0 + */ + MoveSxX86RegPtrDispToX86RegHalf(x86_EBP, 0, x86_EAX); + MoveSxX86RegPtrDispToX86RegHalf(x86_EBP, 2, x86_ECX); + MoveSxX86RegPtrDispToX86RegHalf(x86_EBP, 4, x86_EDI); + MoveSxX86RegPtrDispToX86RegHalf(x86_EBP, 6, x86_ESI); + + ImulX86RegToX86Reg(x86_EAX, x86_EBX); + ImulX86RegToX86Reg(x86_ECX, x86_EBX); + ImulX86RegToX86Reg(x86_EDI, x86_EBX); + ImulX86RegToX86Reg(x86_ESI, x86_EBX); + + sprintf(Reg, "RSP_ACCUM[%i].W[1]", 0); + AddX86regToVariable(x86_EAX, &RSP_ACCUM[0].W[1], Reg); + sprintf(Reg, "RSP_ACCUM[%i].W[1]", 1); + AddX86regToVariable(x86_ECX, &RSP_ACCUM[1].W[1], Reg); + sprintf(Reg, "RSP_ACCUM[%i].W[1]", 2); + AddX86regToVariable(x86_EDI, &RSP_ACCUM[2].W[1], Reg); + sprintf(Reg, "RSP_ACCUM[%i].W[1]", 3); + AddX86regToVariable(x86_ESI, &RSP_ACCUM[3].W[1], Reg); + + /* + * Pipe lined segment 1 + */ + MoveSxX86RegPtrDispToX86RegHalf(x86_EBP, 8, x86_EAX); + MoveSxX86RegPtrDispToX86RegHalf(x86_EBP, 10, x86_ECX); + MoveSxX86RegPtrDispToX86RegHalf(x86_EBP, 12, x86_EDI); + MoveSxX86RegPtrDispToX86RegHalf(x86_EBP, 14, x86_ESI); + + ImulX86RegToX86Reg(x86_EAX, x86_EBX); + ImulX86RegToX86Reg(x86_ECX, x86_EBX); + ImulX86RegToX86Reg(x86_EDI, x86_EBX); + ImulX86RegToX86Reg(x86_ESI, x86_EBX); + + sprintf(Reg, "RSP_ACCUM[%i].W[1]", 4); + AddX86regToVariable(x86_EAX, &RSP_ACCUM[4].W[1], Reg); + sprintf(Reg, "RSP_ACCUM[%i].W[1]", 5); + AddX86regToVariable(x86_ECX, &RSP_ACCUM[5].W[1], Reg); + sprintf(Reg, "RSP_ACCUM[%i].W[1]", 6); + AddX86regToVariable(x86_EDI, &RSP_ACCUM[6].W[1], Reg); + sprintf(Reg, "RSP_ACCUM[%i].W[1]", 7); + AddX86regToVariable(x86_ESI, &RSP_ACCUM[7].W[1], Reg); + + Pop(x86_EBP); + } else { + Push(x86_EBP); + sprintf(Reg, "RSP_Vect[%i].HW[0]", RSPOpC.rd); + MoveOffsetToX86reg((DWORD)&RSP_Vect[RSPOpC.rd].HW[0], Reg, x86_EBP); + + if (bWriteToDest) { + sprintf(Reg, "RSP_Vect[%i].HW[0]", RSPOpC.sa); + MoveOffsetToX86reg((DWORD)&RSP_Vect[RSPOpC.sa].HW[0], Reg, x86_ECX); + } else if (!bOptimize) { + sprintf(Reg, "RSP_Vect[%i].HW[0]", RSPOpC.rt); + MoveOffsetToX86reg((DWORD)&RSP_Vect[RSPOpC.rt].HW[0], Reg, x86_ECX); + } + + for (count = 0; count < 8; count++) { + CPU_Message(" Iteration: %i", count); + el = Indx[RSPOpC.rs].B[count]; + del = EleSpec[RSPOpC.rs].B[el]; + + /*sprintf(Reg, "RSP_Vect[%i].HW[%i]", RSPOpC.rd, el); + MoveSxVariableToX86regHalf(&RSP_Vect[RSPOpC.rd].HW[el], Reg, x86_EAX);*/ + MoveSxX86RegPtrDispToX86RegHalf(x86_EBP, el * 2, x86_EAX); + + if (bOptimize == FALSE) { + if (bWriteToDest == TRUE) { + sprintf(Reg, "RSP_Vect[%i].HW[%i]", RSPOpC.rt, del); + MoveSxVariableToX86regHalf(&RSP_Vect[RSPOpC.rt].HW[del], Reg, x86_EBX); + } else { + MoveSxX86RegPtrDispToX86RegHalf(x86_ECX, del * 2, x86_EBX); + } + } + + imulX86reg(x86_EBX); + sprintf(Reg, "RSP_ACCUM[%i].W[1]", el); + AddX86regToVariable(x86_EAX, &RSP_ACCUM[el].W[1], Reg); + + if (bWriteToDest == TRUE) { + MoveVariableToX86reg(&RSP_ACCUM[el].W[1], "RSP_ACCUM[el].W[1]", x86_EAX); + + CompX86RegToX86Reg(x86_EAX, x86_ESI); + CondMoveGreater(x86_EAX, x86_ESI); + CompX86RegToX86Reg(x86_EAX, x86_EDI); + CondMoveLess(x86_EAX, x86_EDI); + + /*sprintf(Reg, "RSP_Vect[%i].HW[%i]", RSPOpC.sa, el); + MoveX86regHalfToVariable(x86_EAX, &RSP_Vect[RSPOpC.sa].HW[el], Reg);*/ + MoveX86regHalfToX86regPointerDisp(x86_EAX, x86_ECX, el * 2); + } + } + Pop(x86_EBP); + } +} + +BOOL Compile_Vector_VADD_MMX ( void ) { + char Reg[256]; + + /* Do our MMX checks here */ + if (IsMmxEnabled == FALSE) + return FALSE; + if ((RSPOpC.rs & 0x0f) >= 2 && (RSPOpC.rs & 0x0f) <= 7 && IsMmx2Enabled == FALSE) + return FALSE; + + sprintf(Reg, "RSP_Vect[%i].UHW[0]", RSPOpC.rd); + MmxMoveQwordVariableToReg(x86_MM0, &RSP_Vect[RSPOpC.rd].UHW[0], Reg); + sprintf(Reg, "RSP_Vect[%i].UHW[4]", RSPOpC.rd); + MmxMoveQwordVariableToReg(x86_MM1, &RSP_Vect[RSPOpC.rd].UHW[4], Reg); + + if ((RSPOpC.rs & 15) >= 8) { + RSP_Element2Mmx(x86_MM2); + MmxPaddswRegToReg(x86_MM0, x86_MM2); + MmxPaddswRegToReg(x86_MM1, x86_MM2); + } else if ((RSPOpC.rs & 15) < 2) { + sprintf(Reg, "RSP_Vect[%i].HW[0]", RSPOpC.rt); + MmxPaddswVariableToReg(x86_MM0, &RSP_Vect[RSPOpC.rt].HW[0], Reg); + sprintf(Reg, "RSP_Vect[%i].HW[4]", RSPOpC.rt); + MmxPaddswVariableToReg(x86_MM1, &RSP_Vect[RSPOpC.rt].HW[4], Reg); + } else { + RSP_MultiElement2Mmx(x86_MM2, x86_MM3); + MmxPaddswRegToReg(x86_MM0, x86_MM2); + MmxPaddswRegToReg(x86_MM1, x86_MM3); + } + + sprintf(Reg, "RSP_Vect[%i].UHW[0]", RSPOpC.sa); + MmxMoveQwordRegToVariable(x86_MM0, &RSP_Vect[RSPOpC.sa].UHW[0], Reg); + sprintf(Reg, "RSP_Vect[%i].UHW[4]", RSPOpC.sa); + MmxMoveQwordRegToVariable(x86_MM1, &RSP_Vect[RSPOpC.sa].UHW[4], Reg); + + if (IsNextInstructionMmx(CompilePC) != TRUE) { + MmxEmptyMultimediaState(); + } + + return TRUE; +} + +void Compile_Vector_VADD ( void ) { + char Reg[256]; + int count, el, del; + + + BOOL bWriteToDest = WriteToVectorDest(RSPOpC.sa, CompilePC); + BOOL bElement = ((RSPOpC.rs & 0x0f) >= 8) ? TRUE : FALSE; + BOOL bWriteToAccum = WriteToAccum(Low16BitAccum, CompilePC); + BOOL bFlagUseage = UseRspFlags(CompilePC); + + #ifndef CompileVadd + Cheat_r4300iOpcode(RSP_Vector_VADD,"RSP_Vector_VADD"); return; + #endif + + CPU_Message(" %X %s",CompilePC,RSPOpcodeName(RSPOpC.Hex,CompilePC)); + + if (bWriteToAccum == FALSE && bFlagUseage == FALSE) { + if (TRUE == Compile_Vector_VADD_MMX()) + return; + } + + if (bElement == TRUE) { + del = (RSPOpC.rs & 0x07) ^ 7; + sprintf(Reg, "RSP_Vect[%i].HW[%i]", RSPOpC.rt, del); + MoveSxVariableToX86regHalf(&RSP_Vect[RSPOpC.rt].HW[del], Reg, x86_EBX); + } + if (bWriteToDest == TRUE) { + /* + * Prepare for conditional moves + */ + MoveConstToX86reg(0x00007fff, x86_ESI); + MoveConstToX86reg(0xffff8000, x86_EDI); + } + + /* Used for involking x86 carry flag */ + XorX86RegToX86Reg(x86_ECX, x86_ECX); + Push(x86_EBP); + MoveVariableToX86reg(&RSP_Flags[0].UW, "RSP_Flags[0].UW", x86_EBP); + + for (count = 0; count < 8; count++) { + CPU_Message(" Iteration: %i", count); + el = Indx[RSPOpC.rs].B[count]; + del = EleSpec[RSPOpC.rs].B[el]; + + sprintf(Reg, "RSP_Vect[%i].HW[%i]", RSPOpC.rd, el); + MoveSxVariableToX86regHalf(&RSP_Vect[RSPOpC.rd].HW[el], Reg, x86_EAX); + + if (bElement == FALSE) { + sprintf(Reg, "RSP_Vect[%i].HW[%i]", RSPOpC.rt, del); + MoveSxVariableToX86regHalf(&RSP_Vect[RSPOpC.rt].HW[del], Reg, x86_EBX); + } + + MoveX86RegToX86Reg(x86_EBP, x86_EDX); + AndConstToX86Reg(x86_EDX, 1 << (7 - el)); + CompX86RegToX86Reg(x86_ECX, x86_EDX); + + AdcX86RegToX86Reg(x86_EAX, x86_EBX); + + if (bWriteToAccum == TRUE) { + MoveX86regHalfToVariable(x86_EAX, &RSP_ACCUM[el].HW[1], "RSP_ACCUM[el].HW[1]"); + } + if (bWriteToDest == TRUE) { + CompX86RegToX86Reg(x86_EAX, x86_ESI); + CondMoveGreater(x86_EAX, x86_ESI); + CompX86RegToX86Reg(x86_EAX, x86_EDI); + CondMoveLess(x86_EAX, x86_EDI); + + sprintf(Reg, "RSP_Vect[%i].HW[%i]", RSPOpC.sa, el); + MoveX86regHalfToVariable(x86_EAX, &RSP_Vect[RSPOpC.sa].HW[el], Reg); + } + } + MoveConstToVariable(0, &RSP_Flags[0].UW, "RSP_Flags[0].UW"); + Pop(x86_EBP); +} + +BOOL Compile_Vector_VSUB_MMX ( void ) { + char Reg[256]; + + /* Do our MMX checks here */ + if (IsMmxEnabled == FALSE) + return FALSE; + if ((RSPOpC.rs & 0x0f) >= 2 && (RSPOpC.rs & 0x0f) <= 7 && IsMmx2Enabled == FALSE) + return FALSE; + + sprintf(Reg, "RSP_Vect[%i].UHW[0]", RSPOpC.rd); + MmxMoveQwordVariableToReg(x86_MM0, &RSP_Vect[RSPOpC.rd].UHW[0], Reg); + sprintf(Reg, "RSP_Vect[%i].UHW[4]", RSPOpC.rd); + MmxMoveQwordVariableToReg(x86_MM1, &RSP_Vect[RSPOpC.rd].UHW[4], Reg); + + if ((RSPOpC.rs & 15) >= 8) { + RSP_Element2Mmx(x86_MM2); + MmxPsubswRegToReg(x86_MM0, x86_MM2); + MmxPsubswRegToReg(x86_MM1, x86_MM2); + } else if ((RSPOpC.rs & 15) < 2) { + sprintf(Reg, "RSP_Vect[%i].HW[0]", RSPOpC.rt); + MmxPsubswVariableToReg(x86_MM0, &RSP_Vect[RSPOpC.rt].HW[0], Reg); + sprintf(Reg, "RSP_Vect[%i].HW[4]", RSPOpC.rt); + MmxPsubswVariableToReg(x86_MM1, &RSP_Vect[RSPOpC.rt].HW[4], Reg); + } else { + RSP_MultiElement2Mmx(x86_MM2, x86_MM3); + MmxPsubswRegToReg(x86_MM0, x86_MM2); + MmxPsubswRegToReg(x86_MM1, x86_MM3); + } + + sprintf(Reg, "RSP_Vect[%i].UHW[0]", RSPOpC.sa); + MmxMoveQwordRegToVariable(x86_MM0, &RSP_Vect[RSPOpC.sa].UHW[0], Reg); + sprintf(Reg, "RSP_Vect[%i].UHW[4]", RSPOpC.sa); + MmxMoveQwordRegToVariable(x86_MM1, &RSP_Vect[RSPOpC.sa].UHW[4], Reg); + if (IsNextInstructionMmx(CompilePC) != TRUE) { + MmxEmptyMultimediaState(); + } + + return TRUE; +} + +void Compile_Vector_VSUB ( void ) { + char Reg[256]; + int count, el, del; + + BOOL bWriteToDest = WriteToVectorDest(RSPOpC.sa, CompilePC); + BOOL bOptimize = ((RSPOpC.rs & 0x0f) >= 8) ? TRUE : FALSE; + BOOL bWriteToAccum = WriteToAccum(Low16BitAccum, CompilePC); + BOOL bFlagUseage = UseRspFlags(CompilePC); + + #ifndef CompileVsub + Cheat_r4300iOpcode(RSP_Vector_VSUB,"RSP_Vector_VSUB"); return; + #endif + + CPU_Message(" %X %s",CompilePC,RSPOpcodeName(RSPOpC.Hex,CompilePC)); + + if (bWriteToAccum == FALSE && bFlagUseage == FALSE) { + if (TRUE == Compile_Vector_VSUB_MMX()) + return; + } + + Push(x86_EBP); + + /* Used for involking the x86 carry flag */ + XorX86RegToX86Reg(x86_ECX, x86_ECX); + MoveVariableToX86reg(&RSP_Flags[0].UW, "RSP_Flags[0].UW", x86_EBP); + + if (bOptimize == TRUE) { + del = (RSPOpC.rs & 0x07) ^ 7; + sprintf(Reg, "RSP_Vect[%i].HW[%i]", RSPOpC.rt, del); + MoveSxVariableToX86regHalf(&RSP_Vect[RSPOpC.rt].HW[del], Reg, x86_EBX); + } + + if (bWriteToDest == TRUE) { + /* + * Prepare for conditional moves + */ + MoveConstToX86reg(0x00007fff, x86_ESI); + MoveConstToX86reg(0xffff8000, x86_EDI); + } + + for (count = 0; count < 8; count++) { + CPU_Message(" Iteration: %i", count); + el = Indx[RSPOpC.rs].B[count]; + del = EleSpec[RSPOpC.rs].B[el]; + + MoveSxVariableToX86regHalf(&RSP_Vect[RSPOpC.rd].HW[el], "RSP_Vect[RSPOpC.rd].HW[el]", x86_EAX); + if (bOptimize == FALSE) { + sprintf(Reg, "RSP_Vect[%i].HW[%i]", RSPOpC.rt, del); + MoveSxVariableToX86regHalf(&RSP_Vect[RSPOpC.rt].HW[del], Reg, x86_EBX); + } + + MoveX86RegToX86Reg(x86_EBP, x86_EDX); + AndConstToX86Reg(x86_EDX, 1 << (7 - el)); + CompX86RegToX86Reg(x86_ECX, x86_EDX); + + SbbX86RegToX86Reg(x86_EAX, x86_EBX); + + if (bWriteToAccum == TRUE) { + MoveX86regHalfToVariable(x86_EAX, &RSP_ACCUM[el].HW[1], "RSP_ACCUM[el].HW[1]"); + } + if (bWriteToDest == TRUE) { + CompX86RegToX86Reg(x86_EAX, x86_ESI); + CondMoveGreater(x86_EAX, x86_ESI); + CompX86RegToX86Reg(x86_EAX, x86_EDI); + CondMoveLess(x86_EAX, x86_EDI); + + sprintf(Reg, "RSP_Vect[%i].HW[%i]", RSPOpC.sa, el); + MoveX86regHalfToVariable(x86_EAX, &RSP_Vect[RSPOpC.sa].HW[el], Reg); + } + } + + MoveConstToVariable(0, &RSP_Flags[0].UW, "RSP_Flags[0].UW"); + Pop(x86_EBP); +} + +void Compile_Vector_VABS ( void ) { + int count, el, del; + char Reg[256]; + + BOOL bWriteToDest = WriteToVectorDest(RSPOpC.sa, CompilePC); + BOOL bWriteToAccum = WriteToAccum(Low16BitAccum, CompilePC); + + #ifndef CompileVabs + Cheat_r4300iOpcode(RSP_Vector_VABS,"RSP_Vector_VABS"); return; + #endif + + CPU_Message(" %X %s",CompilePC,RSPOpcodeName(RSPOpC.Hex,CompilePC)); + + for (count = 0; count < 8; count++) { + CPU_Message(" Iteration: %i", count); + el = Indx[RSPOpC.rs].B[count]; + del = EleSpec[RSPOpC.rs].B[el]; + + if (RSPOpC.rd == RSPOpC.rt && (RSPOpC.rs & 0xF) < 2) { + /** + ** Optimize: EDI/ESI unused, and ECX is const etc + ***/ + + sprintf(Reg, "RSP_Vect[%i].HW[%i]", RSPOpC.rd, el); + MoveSxVariableToX86regHalf(&RSP_Vect[RSPOpC.rd].HW[el], Reg, x86_EAX); + + /*** Obtain the negative of the source ****/ + MoveX86RegToX86Reg(x86_EAX, x86_EBX); + NegateX86reg(x86_EBX); + + /** + ** determine negative value, + ** note: negate(FFFF8000h) == 00008000h + ***/ + + MoveConstToX86reg(0x7fff, x86_ECX); + CompConstToX86reg(x86_EBX, 0x00008000); + CondMoveEqual(x86_EBX, x86_ECX); + + /* sign clamp, dest = (eax >= 0) ? eax : ebx */ + CompConstToX86reg(x86_EAX, 0); + CondMoveLess(x86_EAX, x86_EBX); + + if (bWriteToDest == TRUE) { + sprintf(Reg, "RSP_Vect[%i].HW[%i]", RSPOpC.sa, el); + MoveX86regHalfToVariable(x86_EAX, &RSP_Vect[RSPOpC.sa].HW[el], Reg); + } + if (bWriteToAccum == TRUE) { + sprintf(Reg, "RSP_ACCUM[%i].HW[1]", el); + MoveX86regHalfToVariable(x86_EAX, &RSP_ACCUM[el].HW[1], Reg); + } + } else { + /** + ** Optimize: ESI unused, and EDX is const etc + ***/ + + sprintf(Reg, "RSP_Vect[%i].HW[%i]", RSPOpC.rd, el); + MoveSxVariableToX86regHalf(&RSP_Vect[RSPOpC.rd].HW[el], Reg, x86_EAX); + sprintf(Reg, "RSP_Vect[%i].HW[%i]", RSPOpC.rt, del); + MoveSxVariableToX86regHalf(&RSP_Vect[RSPOpC.rt].HW[del], Reg, x86_EBX); + + /*** Obtain the negative of the source ****/ + MoveX86RegToX86Reg(x86_EBX, x86_ECX); + NegateX86reg(x86_EBX); + + /** + ** determine negative value, + ** note: negate(FFFF8000h) == 00008000h + ***/ + + MoveConstToX86reg(0x7fff, x86_EDX); + CompConstToX86reg(x86_EBX, 0x00008000); + CondMoveEqual(x86_EBX, x86_EDX); + + /* sign clamp, dest = (eax >= 0) ? ecx : ebx */ + CompConstToX86reg(x86_EAX, 0); + CondMoveGreaterEqual(x86_EDI, x86_ECX); + CondMoveLess(x86_EDI, x86_EBX); + + if (bWriteToDest == TRUE) { + sprintf(Reg, "RSP_Vect[%i].HW[%i]", RSPOpC.sa, el); + MoveX86regHalfToVariable(x86_EDI, &RSP_Vect[RSPOpC.sa].HW[el], Reg); + } + if (bWriteToAccum == TRUE) { + sprintf(Reg, "RSP_ACCUM[%i].HW[1]", el); + MoveX86regHalfToVariable(x86_EDI, &RSP_ACCUM[el].HW[1], Reg); + } + } + } +} + +void Compile_Vector_VADDC ( void ) { + char Reg[256]; + int count, el, del; + + BOOL bWriteToDest = WriteToVectorDest(RSPOpC.sa, CompilePC); + BOOL bWriteToAccum = WriteToAccum(Low16BitAccum, CompilePC); + BOOL bElement = ((RSPOpC.rs & 0x0f) >= 8) ? TRUE : FALSE; + + #ifndef CompileVaddc + Cheat_r4300iOpcode(RSP_Vector_VADDC,"RSP_Vector_VADDC"); return; + #endif + + CPU_Message(" %X %s",CompilePC,RSPOpcodeName(RSPOpC.Hex,CompilePC)); + + if (bElement == TRUE) { + del = (RSPOpC.rs & 0x07) ^ 7; + sprintf(Reg, "RSP_Vect[%i].HW[%i]", RSPOpC.rt, del); + MoveZxVariableToX86regHalf(&RSP_Vect[RSPOpC.rt].HW[del], Reg, x86_EBX); + } + + /* Initialize flag register */ + XorX86RegToX86Reg(x86_ECX, x86_ECX); + + Push(x86_EBP); + sprintf(Reg, "RSP_Vect[%i].HW[0]", RSPOpC.rd); + MoveOffsetToX86reg((DWORD)&RSP_Vect[RSPOpC.rd].HW[0], Reg, x86_EBP); + + for (count = 0; count < 8; count++) { + CPU_Message(" Iteration: %i", count); + el = Indx[RSPOpC.rs].B[count]; + del = EleSpec[RSPOpC.rs].B[el]; + + /*sprintf(Reg, "RSP_Vect[%i].HW[%i]", RSPOpC.rd, el); + MoveZxVariableToX86regHalf(&RSP_Vect[RSPOpC.rd].HW[el], Reg, x86_EAX);*/ + MoveZxX86RegPtrDispToX86RegHalf(x86_EBP, el * 2, x86_EAX); + + if (bElement == FALSE) { + sprintf(Reg, "RSP_Vect[%i].HW[%i]", RSPOpC.rt, del); + MoveZxVariableToX86regHalf(&RSP_Vect[RSPOpC.rt].HW[del], Reg, x86_EBX); + } + + AddX86RegToX86Reg(x86_EAX, x86_EBX); + + XorX86RegToX86Reg(x86_EDX, x86_EDX); + TestConstToX86Reg(0xFFFF0000, x86_EAX); + Setnz(x86_EDX); + if ((7 - el) != 0) { + ShiftLeftSignImmed(x86_EDX, 7 - el); + } + OrX86RegToX86Reg(x86_ECX, x86_EDX); + + if (bWriteToAccum == TRUE) { + MoveX86regHalfToVariable(x86_EAX, &RSP_ACCUM[el].HW[1], "RSP_ACCUM[el].HW[1]"); + } + if (bWriteToDest == TRUE) { + sprintf(Reg, "RSP_Vect[%i].HW[%i]", RSPOpC.sa, el); + MoveX86regHalfToVariable(x86_EAX, &RSP_Vect[RSPOpC.sa].HW[el], Reg); + } + } + MoveX86regToVariable(x86_ECX, &RSP_Flags[0].UW, "RSP_Flags[0].UW"); + Pop(x86_EBP); +} + +void Compile_Vector_VSUBC ( void ) { + char Reg[256]; + int count, el, del; + + BOOL bWriteToDest = WriteToVectorDest(RSPOpC.sa, CompilePC); + BOOL bWriteToAccum = WriteToAccum(Low16BitAccum, CompilePC); + BOOL bElement = ((RSPOpC.rs & 0x0f) >= 8) ? TRUE : FALSE; + + #ifndef CompileVsubc + Cheat_r4300iOpcode(RSP_Vector_VSUBC,"RSP_Vector_VSUBC"); return; + #endif + + CPU_Message(" %X %s",CompilePC,RSPOpcodeName(RSPOpC.Hex,CompilePC)); + + if (bElement == TRUE) { + del = (RSPOpC.rs & 0x07) ^ 7; + sprintf(Reg, "RSP_Vect[%i].HW[%i]", RSPOpC.rt, del); + MoveZxVariableToX86regHalf(&RSP_Vect[RSPOpC.rt].HW[del], Reg, x86_EBX); + } + + /* Initialize flag register */ + XorX86RegToX86Reg(x86_ECX, x86_ECX); + + for (count = 0; count < 8; count++) { + CPU_Message(" Iteration: %i", count); + el = Indx[RSPOpC.rs].B[count]; + del = EleSpec[RSPOpC.rs].B[el]; + + sprintf(Reg, "RSP_Vect[%i].HW[%i]", RSPOpC.rd, el); + MoveZxVariableToX86regHalf(&RSP_Vect[RSPOpC.rd].HW[el], Reg, x86_EAX); + + if (bElement == FALSE) { + sprintf(Reg, "RSP_Vect[%i].HW[%i]", RSPOpC.rt, del); + MoveZxVariableToX86regHalf(&RSP_Vect[RSPOpC.rt].HW[del], Reg, x86_EBX); + } + + SubX86RegToX86Reg(x86_EAX, x86_EBX); + + XorX86RegToX86Reg(x86_EDX, x86_EDX); + TestConstToX86Reg(0x0000FFFF, x86_EAX); + Setnz(x86_EDX); + ShiftLeftSignImmed(x86_EDX, 15 - el); + OrX86RegToX86Reg(x86_ECX, x86_EDX); + + XorX86RegToX86Reg(x86_EDX, x86_EDX); + TestConstToX86Reg(0xFFFF0000, x86_EAX); + Setnz(x86_EDX); + ShiftLeftSignImmed(x86_EDX, 7 - el); + OrX86RegToX86Reg(x86_ECX, x86_EDX); + + if (bWriteToAccum == TRUE) { + MoveX86regHalfToVariable(x86_EAX, &RSP_ACCUM[el].HW[1], "RSP_ACCUM[el].HW[1]"); + } + if (bWriteToDest == TRUE) { + sprintf(Reg, "RSP_Vect[%i].HW[%i]", RSPOpC.sa, el); + MoveX86regHalfToVariable(x86_EAX, &RSP_Vect[RSPOpC.sa].HW[el], Reg); + } + } + MoveX86regToVariable(x86_ECX, &RSP_Flags[0].UW, "RSP_Flags[0].UW"); +} + +void Compile_Vector_VSAW ( void ) { + char Reg[256]; + DWORD Word; + + #ifndef CompileVsaw + Cheat_r4300iOpcode(RSP_Vector_VSAW,"RSP_Vector_VSAW"); return; + #endif + + CPU_Message(" %X %s",CompilePC,RSPOpcodeName(RSPOpC.Hex,CompilePC)); + + switch ((RSPOpC.rs & 0xF)) { + case 8: Word = 3; break; + case 9: Word = 2; break; + case 10: Word = 1; break; + default: + MoveConstToVariable(0, &RSP_Vect[RSPOpC.sa].DW[1], "RSP_Vect[RSPOpC.sa].DW[1]"); + MoveConstToVariable(0, &RSP_Vect[RSPOpC.sa].DW[0], "RSP_Vect[RSPOpC.sa].DW[0]"); + return; + } + + sprintf(Reg, "RSP_ACCUM[1].HW[%i]", Word); + MoveVariableToX86regHalf(&RSP_ACCUM[1].HW[Word], Reg, x86_EAX); + sprintf(Reg, "RSP_ACCUM[3].HW[%i]", Word); + MoveVariableToX86regHalf(&RSP_ACCUM[3].HW[Word], Reg, x86_EBX); + sprintf(Reg, "RSP_ACCUM[5].HW[%i]", Word); + MoveVariableToX86regHalf(&RSP_ACCUM[5].HW[Word], Reg, x86_ECX); + sprintf(Reg, "RSP_ACCUM[7].HW[%i]", Word); + MoveVariableToX86regHalf(&RSP_ACCUM[7].HW[Word], Reg, x86_EDX); + + ShiftLeftSignImmed(x86_EAX, 16); + ShiftLeftSignImmed(x86_EBX, 16); + ShiftLeftSignImmed(x86_ECX, 16); + ShiftLeftSignImmed(x86_EDX, 16); + + sprintf(Reg, "RSP_ACCUM[0].HW[%i]", Word); + MoveVariableToX86regHalf(&RSP_ACCUM[0].HW[Word], Reg, x86_EAX); + sprintf(Reg, "RSP_ACCUM[2].HW[%i]", Word); + MoveVariableToX86regHalf(&RSP_ACCUM[2].HW[Word], Reg, x86_EBX); + sprintf(Reg, "RSP_ACCUM[4].HW[%i]", Word); + MoveVariableToX86regHalf(&RSP_ACCUM[4].HW[Word], Reg, x86_ECX); + sprintf(Reg, "RSP_ACCUM[6].HW[%i]", Word); + MoveVariableToX86regHalf(&RSP_ACCUM[6].HW[Word], Reg, x86_EDX); + + sprintf(Reg, "RSP_Vect[%i].HW[0]", RSPOpC.sa); + MoveX86regToVariable(x86_EAX, &RSP_Vect[RSPOpC.sa].HW[0], Reg); + sprintf(Reg, "RSP_Vect[%i].HW[2]", RSPOpC.sa); + MoveX86regToVariable(x86_EBX, &RSP_Vect[RSPOpC.sa].HW[2], Reg); + sprintf(Reg, "RSP_Vect[%i].HW[4]", RSPOpC.sa); + MoveX86regToVariable(x86_ECX, &RSP_Vect[RSPOpC.sa].HW[4], Reg); + sprintf(Reg, "RSP_Vect[%i].HW[6]", RSPOpC.sa); + MoveX86regToVariable(x86_EDX, &RSP_Vect[RSPOpC.sa].HW[6], Reg); +} + +void Compile_Vector_VLT ( void ) { + Cheat_r4300iOpcode(RSP_Vector_VLT,"RSP_Vector_VLT"); +} + +void Compile_Vector_VEQ ( void ) { + Cheat_r4300iOpcode(RSP_Vector_VEQ,"RSP_Vector_VEQ"); +} + +void Compile_Vector_VNE ( void ) { + Cheat_r4300iOpcode(RSP_Vector_VNE,"RSP_Vector_VNE"); +} + +BOOL Compile_Vector_VGE_MMX(void) { + char Reg[256]; + + if ((RSPOpC.rs & 0xF) >= 2 && (RSPOpC.rs & 0xF) <= 7 && IsMmx2Enabled == FALSE) + return FALSE; + + CPU_Message(" %X %s",CompilePC,RSPOpcodeName(RSPOpC.Hex,CompilePC)); + MoveConstToVariable(0, &RSP_Flags[1].UW, "RSP_Flags[1].UW"); + + sprintf(Reg, "RSP_Vect[%i].HW[0]", RSPOpC.rd); + MmxMoveQwordVariableToReg(x86_MM0, &RSP_Vect[RSPOpC.rd].HW[0], Reg); + sprintf(Reg, "RSP_Vect[%i].HW[4]", RSPOpC.rd); + MmxMoveQwordVariableToReg(x86_MM1, &RSP_Vect[RSPOpC.rd].HW[4], Reg); + MmxMoveRegToReg(x86_MM2, x86_MM0); + MmxMoveRegToReg(x86_MM3, x86_MM1); + + if ((RSPOpC.rs & 0x0f) < 2) { + sprintf(Reg, "RSP_Vect[%i].HW[0]", RSPOpC.rt); + MmxMoveQwordVariableToReg(x86_MM4, &RSP_Vect[RSPOpC.rt].HW[0], Reg); + sprintf(Reg, "RSP_Vect[%i].HW[4]", RSPOpC.rt); + MmxMoveQwordVariableToReg(x86_MM5, &RSP_Vect[RSPOpC.rt].HW[4], Reg); + } else if ((RSPOpC.rs & 0x0f) >= 8) { + RSP_Element2Mmx(x86_MM4); + } else { + RSP_MultiElement2Mmx(x86_MM4, x86_MM5); + } + + MmxCompareGreaterWordRegToReg(x86_MM2, x86_MM4); + MmxCompareGreaterWordRegToReg(x86_MM3, ((RSPOpC.rs & 0x0f) >= 8) ? x86_MM4 : x86_MM5); + + MmxPandRegToReg(x86_MM0, x86_MM2); + MmxPandRegToReg(x86_MM1, x86_MM3); + MmxPandnRegToReg(x86_MM2, x86_MM4); + MmxPandnRegToReg(x86_MM3, ((RSPOpC.rs & 0x0f) >= 8) ? x86_MM4 : x86_MM5); + + MmxPorRegToReg(x86_MM0, x86_MM2); + MmxPorRegToReg(x86_MM1, x86_MM3); + MoveConstToVariable(0, &RSP_Flags[0].UW, "RSP_Flags[0].UW"); + return TRUE; +} + +void Compile_Vector_VGE ( void ) { +/* BOOL bWriteToAccum = WriteToAccum(Low16BitAccum, CompilePC); + + /* FIXME: works ok, but needs careful flag analysis */ +/* #if defined (DLIST) + if (bWriteToAccum == FALSE && TRUE == Compile_Vector_VGE_MMX()) { + return; + } + #endif +*/ + Cheat_r4300iOpcode(RSP_Vector_VGE,"RSP_Vector_VGE"); +} + +void Compile_Vector_VCL ( void ) { + Cheat_r4300iOpcode(RSP_Vector_VCL,"RSP_Vector_VCL"); +} + +void Compile_Vector_VCH ( void ) { + Cheat_r4300iOpcode(RSP_Vector_VCH,"RSP_Vector_VCH"); +} + +void Compile_Vector_VCR ( void ) { + Cheat_r4300iOpcode(RSP_Vector_VCR,"RSP_Vector_VCR"); +} + +void Compile_Vector_VMRG ( void ) { + char Reg[256]; + int count, el, del; + + #ifndef CompileVmrg + Cheat_r4300iOpcode(RSP_Vector_VMRG,"RSP_Vector_VMRG"); return; + #endif + + CPU_Message(" %X %s",CompilePC,RSPOpcodeName(RSPOpC.Hex,CompilePC)); + MoveVariableToX86reg(&RSP_Flags[1].UW, "RSP_Flags[1].UW", x86_EDX); + + for (count = 0;count < 8; count++) { + el = Indx[RSPOpC.rs].UB[count]; + del = EleSpec[RSPOpC.rs].UB[el]; + CPU_Message(" Iteration: %i", count); + + sprintf(Reg, "RSP_Vect[%i].HW[%i]", RSPOpC.rd, el); + MoveZxVariableToX86regHalf(&RSP_Vect[RSPOpC.rd].HW[el], Reg, x86_EAX); + sprintf(Reg, "RSP_Vect[%i].HW[%i]", RSPOpC.rt, del); + MoveZxVariableToX86regHalf(&RSP_Vect[RSPOpC.rt].HW[del], Reg, x86_EBX); + + TestConstToX86Reg(1 << (7 - el), x86_EDX); + CondMoveNotEqual(x86_ECX, x86_EAX); + CondMoveEqual(x86_ECX, x86_EBX); + + sprintf(Reg, "RSP_Vect[%i].HW[%i]", RSPOpC.sa, el); + MoveX86regHalfToVariable(x86_ECX, &RSP_Vect[RSPOpC.sa].HW[el], Reg); + } +} + +BOOL Compile_Vector_VAND_MMX ( void ) { + char Reg[256]; + + /* Do our MMX checks here */ + if (IsMmxEnabled == FALSE) + return FALSE; + if ((RSPOpC.rs & 0x0f) >= 2 && (RSPOpC.rs & 0x0f) <= 7 && IsMmx2Enabled == FALSE) + return FALSE; + + sprintf(Reg, "RSP_Vect[%i].UHW[0]", RSPOpC.rd); + MmxMoveQwordVariableToReg(x86_MM0, &RSP_Vect[RSPOpC.rd].UHW[0], Reg); + sprintf(Reg, "RSP_Vect[%i].UHW[4]", RSPOpC.rd); + MmxMoveQwordVariableToReg(x86_MM1, &RSP_Vect[RSPOpC.rd].UHW[4], Reg); + + if ((RSPOpC.rs & 0xF) >= 8) { + RSP_Element2Mmx(x86_MM2); + MmxPandRegToReg(x86_MM0, x86_MM2); + MmxPandRegToReg(x86_MM1, x86_MM2); + } else if ((RSPOpC.rs & 0xF) < 2) { + sprintf(Reg, "RSP_Vect[%i].HW[0]", RSPOpC.rt); + MmxPandVariableToReg(&RSP_Vect[RSPOpC.rt].HW[0], Reg, x86_MM0); + sprintf(Reg, "RSP_Vect[%i].HW[4]", RSPOpC.rt); + MmxPandVariableToReg(&RSP_Vect[RSPOpC.rt].HW[4], Reg, x86_MM1); + } else { + RSP_MultiElement2Mmx(x86_MM2, x86_MM3); + MmxPandRegToReg(x86_MM0, x86_MM2); + MmxPandRegToReg(x86_MM1, x86_MM3); + } + + sprintf(Reg, "RSP_Vect[%i].UHW[0]", RSPOpC.sa); + MmxMoveQwordRegToVariable(x86_MM0, &RSP_Vect[RSPOpC.sa].UHW[0], Reg); + sprintf(Reg, "RSP_Vect[%i].UHW[4]", RSPOpC.sa); + MmxMoveQwordRegToVariable(x86_MM1, &RSP_Vect[RSPOpC.sa].UHW[4], Reg); + + if (IsNextInstructionMmx(CompilePC) == FALSE) + MmxEmptyMultimediaState(); + + return TRUE; +} + +void Compile_Vector_VAND ( void ) { + char Reg[256]; + int el, del, count; + BOOL bElement = ((RSPOpC.rs & 0x0f) >= 8) ? TRUE : FALSE; + BOOL bWriteToAccum = WriteToAccum(Low16BitAccum, CompilePC); + + #ifndef CompileVand + Cheat_r4300iOpcode(RSP_Vector_VAND,"RSP_Vector_VAND"); return; + #endif + + CPU_Message(" %X %s",CompilePC,RSPOpcodeName(RSPOpC.Hex,CompilePC)); + + if (bWriteToAccum == FALSE) { + if (TRUE == Compile_Vector_VAND_MMX()) + return; + } + + if (bElement == TRUE) { + del = (RSPOpC.rs & 0x07) ^ 7; + sprintf(Reg, "RSP_Vect[%i].HW[%i]", RSPOpC.rt, del); + MoveVariableToX86regHalf(&RSP_Vect[RSPOpC.rt].HW[del], Reg, x86_EBX); + } + + for (count = 0; count < 8; count++) { + el = Indx[RSPOpC.rs].B[count]; + del = EleSpec[RSPOpC.rs].B[el]; + + CPU_Message(" Iteration: %i", count); + + sprintf(Reg, "RSP_Vect[%i].HW[%i]", RSPOpC.rd, el); + MoveVariableToX86regHalf(&RSP_Vect[RSPOpC.rd].HW[el], Reg, x86_EAX); + + if (bElement == FALSE) { + sprintf(Reg, "RSP_Vect[%i].HW[%i]", RSPOpC.rt, del); + AndVariableToX86regHalf(&RSP_Vect[RSPOpC.rt].HW[del], Reg, x86_EAX); + } else { + AndX86RegHalfToX86RegHalf(x86_EAX, x86_EBX); + } + + sprintf(Reg, "RSP_Vect[%i].HW[%i]", RSPOpC.sa, el); + MoveX86regHalfToVariable(x86_EAX, &RSP_Vect[RSPOpC.sa].HW[el], Reg); + + if (bWriteToAccum != FALSE) { + sprintf(Reg, "RSP_ACCUM[el].HW[1]", el); + MoveX86regHalfToVariable(x86_EAX, &RSP_ACCUM[el].HW[1], Reg); + } + } +} + +void Compile_Vector_VNAND ( void ) { + Cheat_r4300iOpcode(RSP_Vector_VNAND,"RSP_Vector_VNAND"); +} + +BOOL Compile_Vector_VOR_MMX ( void ) { + char Reg[256]; + + /* Do our MMX checks here */ + if (IsMmxEnabled == FALSE) + return FALSE; + if ((RSPOpC.rs & 0x0f) >= 2 && (RSPOpC.rs & 0x0f) <= 7 && IsMmx2Enabled == FALSE) + return FALSE; + + sprintf(Reg, "RSP_Vect[%i].UHW[0]", RSPOpC.rd); + MmxMoveQwordVariableToReg(x86_MM0, &RSP_Vect[RSPOpC.rd].UHW[0], Reg); + sprintf(Reg, "RSP_Vect[%i].UHW[4]", RSPOpC.rd); + MmxMoveQwordVariableToReg(x86_MM1, &RSP_Vect[RSPOpC.rd].UHW[4], Reg); + + if ((RSPOpC.rs & 0xF) >= 8) { + RSP_Element2Mmx(x86_MM2); + MmxPorRegToReg(x86_MM0, x86_MM2); + MmxPorRegToReg(x86_MM1, x86_MM2); + } else if ((RSPOpC.rs & 0xF) < 2) { + sprintf(Reg, "RSP_Vect[%i].HW[0]", RSPOpC.rt); + MmxPorVariableToReg(&RSP_Vect[RSPOpC.rt].HW[0], Reg, x86_MM0); + sprintf(Reg, "RSP_Vect[%i].HW[4]", RSPOpC.rt); + MmxPorVariableToReg(&RSP_Vect[RSPOpC.rt].HW[4], Reg, x86_MM1); + } else { + RSP_MultiElement2Mmx(x86_MM2, x86_MM3); + MmxPorRegToReg(x86_MM0, x86_MM2); + MmxPorRegToReg(x86_MM1, x86_MM3); + } + + sprintf(Reg, "RSP_Vect[%i].UHW[0]", RSPOpC.sa); + MmxMoveQwordRegToVariable(x86_MM0, &RSP_Vect[RSPOpC.sa].UHW[0], Reg); + sprintf(Reg, "RSP_Vect[%i].UHW[4]", RSPOpC.sa); + MmxMoveQwordRegToVariable(x86_MM1, &RSP_Vect[RSPOpC.sa].UHW[4], Reg); + + if (IsNextInstructionMmx(CompilePC) == FALSE) + MmxEmptyMultimediaState(); + + return TRUE; +} + +void Compile_Vector_VOR ( void ) { + char Reg[256]; + int el, del, count; + BOOL bElement = ((RSPOpC.rs & 0x0f) >= 8) ? TRUE : FALSE; + BOOL bWriteToAccum = WriteToAccum(Low16BitAccum, CompilePC); + + #ifndef CompileVor + Cheat_r4300iOpcode(RSP_Vector_VOR,"RSP_Vector_VOR"); return; + #endif + + CPU_Message(" %X %s",CompilePC,RSPOpcodeName(RSPOpC.Hex,CompilePC)); + + if (bWriteToAccum == FALSE) { + if (TRUE == Compile_Vector_VOR_MMX()) + return; + } + + if (bElement == TRUE) { + del = (RSPOpC.rs & 0x07) ^ 7; + sprintf(Reg, "RSP_Vect[%i].HW[%i]", RSPOpC.rt, del); + MoveVariableToX86regHalf(&RSP_Vect[RSPOpC.rt].HW[del], Reg, x86_EBX); + } + + for (count = 0; count < 8; count++) { + el = Indx[RSPOpC.rs].B[count]; + del = EleSpec[RSPOpC.rs].B[el]; + + CPU_Message(" Iteration: %i", count); + + sprintf(Reg, "RSP_Vect[%i].HW[%i]", RSPOpC.rd, el); + MoveVariableToX86regHalf(&RSP_Vect[RSPOpC.rd].HW[el], Reg, x86_EAX); + + if (bElement == FALSE) { + sprintf(Reg, "RSP_Vect[%i].HW[%i]", RSPOpC.rt, del); + OrVariableToX86regHalf(&RSP_Vect[RSPOpC.rt].HW[del], Reg, x86_EAX); + } else { + OrX86RegToX86Reg(x86_EAX, x86_EBX); + } + + if (bWriteToAccum == TRUE) { + sprintf(Reg, "RSP_ACCUM[el].HW[1]", el); + MoveX86regHalfToVariable(x86_EAX, &RSP_ACCUM[el].HW[1], Reg); + } + sprintf(Reg, "RSP_Vect[%i].HW[%i]", RSPOpC.sa, el); + MoveX86regHalfToVariable(x86_EAX, &RSP_Vect[RSPOpC.sa].HW[el], Reg); + } +} + +void Compile_Vector_VNOR ( void ) { + Cheat_r4300iOpcode(RSP_Vector_VNOR,"RSP_Vector_VNOR"); +} + +BOOL Compile_Vector_VXOR_MMX ( void ) { + char Reg[256]; + + /* Do our MMX checks here */ + if (IsMmxEnabled == FALSE) + return FALSE; + if ((RSPOpC.rs & 0x0f) >= 2 && (RSPOpC.rs & 0x0f) <= 7 && IsMmx2Enabled == FALSE) + return FALSE; + + if ((RSPOpC.rs & 0xF) < 2 && (RSPOpC.rd == RSPOpC.rt)) { + static DWORD VXOR_DynaRegCount = 0; + MmxXorRegToReg(VXOR_DynaRegCount, VXOR_DynaRegCount); + + sprintf(Reg, "RSP_Vect[%i].UHW[0]", RSPOpC.sa); + MmxMoveQwordRegToVariable(VXOR_DynaRegCount, &RSP_Vect[RSPOpC.sa].UHW[0], Reg); + sprintf(Reg, "RSP_Vect[%i].UHW[4]", RSPOpC.sa); + MmxMoveQwordRegToVariable(VXOR_DynaRegCount, &RSP_Vect[RSPOpC.sa].UHW[4], Reg); + VXOR_DynaRegCount = (VXOR_DynaRegCount + 1) & 7; + } else { + sprintf(Reg, "RSP_Vect[%i].UHW[0]", RSPOpC.rd); + MmxMoveQwordVariableToReg(x86_MM0, &RSP_Vect[RSPOpC.rd].UHW[0], Reg); + sprintf(Reg, "RSP_Vect[%i].UHW[4]", RSPOpC.rd); + MmxMoveQwordVariableToReg(x86_MM1, &RSP_Vect[RSPOpC.rd].UHW[4], Reg); + + if ((RSPOpC.rs & 0xF) >= 8) { + RSP_Element2Mmx(x86_MM2); + MmxXorRegToReg(x86_MM0, x86_MM2); + MmxXorRegToReg(x86_MM1, x86_MM2); + } else if ((RSPOpC.rs & 0xF) < 2) { + sprintf(Reg, "RSP_Vect[%i].HW[0]", RSPOpC.rt); + MmxMoveQwordVariableToReg(x86_MM2, &RSP_Vect[RSPOpC.rt].HW[0], Reg); + sprintf(Reg, "RSP_Vect[%i].HW[4]", RSPOpC.rt); + MmxMoveQwordVariableToReg(x86_MM3, &RSP_Vect[RSPOpC.rt].HW[4], Reg); + + MmxXorRegToReg(x86_MM0, x86_MM2); + MmxXorRegToReg(x86_MM1, x86_MM3); + } else { + RSP_MultiElement2Mmx(x86_MM2, x86_MM3); + MmxXorRegToReg(x86_MM0, x86_MM2); + MmxXorRegToReg(x86_MM1, x86_MM3); + } + + sprintf(Reg, "RSP_Vect[%i].UHW[0]", RSPOpC.sa); + MmxMoveQwordRegToVariable(x86_MM0, &RSP_Vect[RSPOpC.sa].UHW[0], Reg); + sprintf(Reg, "RSP_Vect[%i].UHW[4]", RSPOpC.sa); + MmxMoveQwordRegToVariable(x86_MM1, &RSP_Vect[RSPOpC.sa].UHW[4], Reg); + } + + if (IsNextInstructionMmx(CompilePC) == FALSE) + MmxEmptyMultimediaState(); + + return TRUE; +} + +void Compile_Vector_VXOR ( void ) { + #ifdef CompileVxor + char Reg[256]; + DWORD count; + BOOL bWriteToAccum = WriteToAccum(Low16BitAccum, CompilePC); + + CPU_Message(" %X %s",CompilePC,RSPOpcodeName(RSPOpC.Hex,CompilePC)); + + if (!bWriteToAccum || ((RSPOpC.rs & 0xF) < 2 && RSPOpC.rd == RSPOpC.rt)) { + if (TRUE == Compile_Vector_VXOR_MMX()) { + if (bWriteToAccum == TRUE) { + XorX86RegToX86Reg(x86_EAX, x86_EAX); + for (count = 0; count < 8; count++) { + sprintf(Reg, "RSP_ACCUM[%i].HW[1]", count); + MoveX86regHalfToVariable(x86_EAX, &RSP_ACCUM[count].HW[1], Reg); + } + } + return; + } + } + #endif + + Cheat_r4300iOpcodeNoMessage(RSP_Vector_VXOR,"RSP_Vector_VXOR"); +} + +void Compile_Vector_VNXOR ( void ) { + Cheat_r4300iOpcode(RSP_Vector_VNXOR,"RSP_Vector_VNXOR"); +} + +void Compile_Vector_VRCP ( void ) { + Cheat_r4300iOpcode(RSP_Vector_VRCP,"RSP_Vector_VRCP"); +} + +void Compile_Vector_VRCPL ( void ) { + Cheat_r4300iOpcode(RSP_Vector_VRCPL,"RSP_Vector_VRCPL"); +} + +void Compile_Vector_VRCPH ( void ) { + char Reg[256]; + int count, el, last = -1; + BOOL bWriteToAccum = WriteToAccum(Low16BitAccum, CompilePC); + + #ifndef CompileVrcph + Cheat_r4300iOpcode(RSP_Vector_VRCPH,"RSP_Vector_VRCPH"); 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); + 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); + 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 ) { + char Reg[256]; + int el; + + #ifndef CompileVmov + Cheat_r4300iOpcode(RSP_Vector_VMOV,"RSP_Vector_VMOV"); 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); + + MoveVariableToX86regHalf(&RSP_Vect[RSPOpC.rt].UHW[el], Reg, x86_ECX); + + 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); +} + +void Compile_Vector_VRSQ ( void ) { + CPU_Message(" %X %s",CompilePC,RSPOpcodeName(RSPOpC.Hex,CompilePC)); + Cheat_r4300iOpcodeNoMessage(RSP_Vector_VRSQ,"RSP_Vector_VRSQ"); +} + +void Compile_Vector_VRSQL ( void ) { + CPU_Message(" %X %s",CompilePC,RSPOpcodeName(RSPOpC.Hex,CompilePC)); + Cheat_r4300iOpcodeNoMessage(RSP_Vector_VRSQL,"RSP_Vector_VRSQL"); +} + +void Compile_Vector_VRSQH ( void ) { + char Reg[256]; + int count, el; + + #ifndef CompileVrsqh + Cheat_r4300iOpcode(RSP_Vector_VRSQH,"RSP_Vector_VRSQH"); 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); + MoveVariableToX86regHalf(&RSP_Vect[RSPOpC.rt].UHW[el], Reg, x86_EDX); + MoveX86regHalfToVariable(x86_EDX, &SQroot.UHW[1], "SQroot.UHW[1]"); + + MoveVariableToX86regHalf(&SQrootResult.UHW[1], "SQrootResult.UHW[1]", x86_ECX); + 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 ) { + +} + +/************************** lc2 functions **************************/ + +void Compile_Opcode_LBV ( void ) { + Cheat_r4300iOpcode(RSP_Opcode_LBV,"RSP_Opcode_LBV"); +} + +void Compile_Opcode_LSV ( void ) { + char Reg[256]; + int offset = (RSPOpC.voffset << 1); + + if (RSPOpC.del > 14) { + rsp_UnknownOpcode(); + return; + } + + #ifndef CompileLsv + Cheat_r4300iOpcode(RSP_Opcode_LSV,"RSP_Opcode_LSV"); return; + #endif + + CPU_Message(" %X %s",CompilePC,RSPOpcodeName(RSPOpC.Hex,CompilePC)); + + if (IsRegConst(RSPOpC.base) == TRUE) { + DWORD Addr = (MipsRegConst(RSPOpC.base) + offset) & 0xfff; + + if ((Addr & 1) != 0) { + sprintf(Reg, "Dmem + %Xh", (Addr + 0) ^ 3); + MoveVariableToX86regByte(RSPInfo.DMEM + ((Addr + 0) ^ 3), Reg, x86_ECX); + sprintf(Reg, "Dmem + %Xh", (Addr + 1) ^ 3); + MoveVariableToX86regByte(RSPInfo.DMEM + ((Addr + 1) ^ 3), Reg, x86_EDX); + + sprintf(Reg, "RSP_Vect[%i].B[%i]", RSPOpC.rt, 15 - (RSPOpC.del + 0)); + MoveX86regByteToVariable(x86_ECX, &RSP_Vect[RSPOpC.rt].B[15 - (RSPOpC.del + 0)], Reg); + sprintf(Reg, "RSP_Vect[%i].B[%i]", RSPOpC.rt, 15 - (RSPOpC.del + 1)); + MoveX86regByteToVariable(x86_EDX, &RSP_Vect[RSPOpC.rt].B[15 - (RSPOpC.del + 1)], Reg); + } else { + sprintf(Reg, "Dmem + %Xh", Addr ^ 2); + MoveVariableToX86regHalf(RSPInfo.DMEM + (Addr ^ 2), Reg, x86_EDX); + sprintf(Reg, "RSP_Vect[%i].B[%i]", RSPOpC.rt, 15 - (RSPOpC.del + 1)); + MoveX86regHalfToVariable(x86_EDX, &RSP_Vect[RSPOpC.rt].B[15 - (RSPOpC.del + 1)], Reg); + } + return; + } + + MoveVariableToX86reg(&RSP_GPR[RSPOpC.base].UW, GPR_Name(RSPOpC.base), x86_EBX); + if (offset != 0) AddConstToX86Reg(x86_EBX, offset); + AndConstToX86Reg(x86_EBX, 0x0FFF); + + if (Compiler.bAlignVector == TRUE) { + XorConstToX86Reg(x86_EBX, 2); + MoveN64MemToX86regHalf(x86_ECX, x86_EBX); + sprintf(Reg, "RSP_Vect[%i].B[%i]", RSPOpC.rt, 15 - (RSPOpC.del + 1)); + MoveX86regHalfToVariable(x86_ECX, &RSP_Vect[RSPOpC.rt].B[15 - (RSPOpC.del + 1)], Reg); + } else { + LeaSourceAndOffset(x86_EAX, x86_EBX, 1); + XorConstToX86Reg(x86_EBX, 3); + XorConstToX86Reg(x86_EAX, 3); + + MoveN64MemToX86regByte(x86_ECX, x86_EBX); + MoveN64MemToX86regByte(x86_EDX, x86_EAX); + + sprintf(Reg, "RSP_Vect[%i].B[%i]", RSPOpC.rt, 15 - (RSPOpC.del + 0)); + MoveX86regByteToVariable(x86_ECX, &RSP_Vect[RSPOpC.rt].B[15 - (RSPOpC.del + 0)], Reg); + + sprintf(Reg, "RSP_Vect[%i].B[%i]", RSPOpC.rt, 15 - (RSPOpC.del + 1)); + MoveX86regByteToVariable(x86_EDX, &RSP_Vect[RSPOpC.rt].B[15 - (RSPOpC.del + 1)], Reg); + } +} + +void Compile_Opcode_LLV ( void ) { + char Reg[256]; + int offset = (RSPOpC.voffset << 2); + BYTE * Jump[2]; + + #ifndef CompileLlv + Cheat_r4300iOpcode(RSP_Opcode_LLV,"RSP_Opcode_LLV"); return; + #endif + + CPU_Message(" %X %s",CompilePC,RSPOpcodeName(RSPOpC.Hex,CompilePC)); + + if ((RSPOpC.del & 0x3) != 0) { + rsp_UnknownOpcode(); + return; + } + + if (IsRegConst(RSPOpC.base) == TRUE) { + DWORD Addr = (MipsRegConst(RSPOpC.base) + offset) & 0xfff; + + if ((Addr & 3) != 0) { + CompilerWarning("Unaligned LLV at constant address"); + Cheat_r4300iOpcodeNoMessage(RSP_Opcode_LLV,"RSP_Opcode_LLV"); + return; + } + + sprintf(Reg, "Dmem + %Xh", Addr); + MoveVariableToX86reg(RSPInfo.DMEM + Addr, Reg, x86_EAX); + sprintf(Reg, "RSP_Vect[%i].B[%i]", RSPOpC.rt, 16 - RSPOpC.del - 4); + MoveX86regToVariable(x86_EAX, &RSP_Vect[RSPOpC.rt].B[16 - RSPOpC.del - 4], Reg); + return; + } + + MoveVariableToX86reg(&RSP_GPR[RSPOpC.base].UW, GPR_Name(RSPOpC.base), x86_EBX); + if (offset != 0) AddConstToX86Reg(x86_EBX, offset); + + TestConstToX86Reg(3, x86_EBX); + JneLabel32("Unaligned", 0); + Jump[0] = RecompPos - 4; + + /* + * Unaligned + */ + CompilerToggleBuffer(); + + CPU_Message(" Unaligned:"); + *((DWORD *)(Jump[0]))=(DWORD)(RecompPos - Jump[0] - 4); + Cheat_r4300iOpcodeNoMessage(RSP_Opcode_LLV,"RSP_Opcode_LLV"); + JmpLabel32("Done", 0); + Jump[1] = RecompPos - 4; + + CompilerToggleBuffer(); + + /* + * Aligned + */ + AndConstToX86Reg(x86_EBX, 0x0fff); + MoveN64MemToX86reg(x86_EAX, x86_EBX); + /* Because of byte swapping this swizzle works nicely */ + sprintf(Reg, "RSP_Vect[%i].B[%i]", RSPOpC.rt, 16 - RSPOpC.del - 4); + MoveX86regToVariable(x86_EAX, &RSP_Vect[RSPOpC.rt].B[16 - RSPOpC.del - 4], Reg); + + CPU_Message(" Done:"); + *((DWORD *)(Jump[1]))=(DWORD)(RecompPos - Jump[1] - 4); +} + +void Compile_Opcode_LDV ( void ) { + char Reg[256]; + int offset = (RSPOpC.voffset << 3); + BYTE * Jump[2], * LoopEntry; + + #ifndef CompileLdv + Cheat_r4300iOpcode(RSP_Opcode_LDV,"RSP_Opcode_LDV"); return; + #endif + + CPU_Message(" %X %s",CompilePC,RSPOpcodeName(RSPOpC.Hex,CompilePC)); + + /* FIXME: Conker's hits this */ + //if ((RSPOpC.del & 0x7) != 0) { + // rsp_UnknownOpcode(); + // return; + //} + + if (IsRegConst(RSPOpC.base) == TRUE) { + DWORD Addr = (MipsRegConst(RSPOpC.base) + offset) & 0xfff; + + if ((Addr & 3) != 0) { + CompilerWarning("Unaligned LDV at constant address PC = %04X", CompilePC); + Cheat_r4300iOpcodeNoMessage(RSP_Opcode_LDV,"RSP_Opcode_LDV"); + return; + } + + sprintf(Reg, "Dmem + %Xh", Addr); + MoveVariableToX86reg(RSPInfo.DMEM + Addr + 0, Reg, x86_EAX); + sprintf(Reg, "Dmem + %Xh", Addr + 4); + MoveVariableToX86reg(RSPInfo.DMEM + Addr + 4, Reg, x86_ECX); + + sprintf(Reg, "RSP_Vect[%i].B[%i]", RSPOpC.rt, 16 - RSPOpC.del - 4); + MoveX86regToVariable(x86_EAX, &RSP_Vect[RSPOpC.rt].B[16 - RSPOpC.del - 4], Reg); + sprintf(Reg, "RSP_Vect[%i].B[%i]", RSPOpC.rt, 16 - RSPOpC.del - 8); + MoveX86regToVariable(x86_ECX, &RSP_Vect[RSPOpC.rt].B[16 - RSPOpC.del - 8], Reg); + return; + } + + MoveVariableToX86reg(&RSP_GPR[RSPOpC.base].UW, GPR_Name(RSPOpC.base), x86_EBX); + if (offset != 0) { + AddConstToX86Reg(x86_EBX, offset); + } + AndConstToX86Reg(x86_EBX, 0x0fff); + TestConstToX86Reg(3, x86_EBX); + JneLabel32("Unaligned", 0); + Jump[0] = RecompPos - 4; + + CompilerToggleBuffer(); + CPU_Message(" Unaligned:"); + x86_SetBranch32b(Jump[0], RecompPos); + sprintf(Reg, "RSP_Vect[%i].UB[%i]", RSPOpC.rt, 15 - RSPOpC.del); + MoveOffsetToX86reg((DWORD)&RSP_Vect[RSPOpC.rt].UB[15 - RSPOpC.del], Reg, x86_EDI); + MoveConstToX86reg(8, x86_ECX); + +/* mov eax, ebx + dec edi + xor eax, 3h + inc ebx + mov dl, byte ptr [eax+Dmem] + dec ecx + mov byte ptr [edi+1], dl + jne $Loop */ + + LoopEntry = RecompPos; + CPU_Message(" Loop:"); + MoveX86RegToX86Reg(x86_EBX, x86_EAX); + XorConstToX86Reg(x86_EAX, 3); + MoveN64MemToX86regByte(x86_EDX, x86_EAX); + MoveX86regByteToX86regPointer(x86_EDX, x86_EDI); + IncX86reg(x86_EBX); /* address constant */ + DecX86reg(x86_EDI); /* vector pointer */ + DecX86reg(x86_ECX); /* counter */ + JneLabel8("Loop", 0); + x86_SetBranch8b(RecompPos - 1, LoopEntry); + + JmpLabel32("Done", 0); + Jump[1] = RecompPos - 4; + CompilerToggleBuffer(); + + MoveN64MemToX86reg(x86_EAX, x86_EBX); + MoveN64MemDispToX86reg(x86_ECX, x86_EBX, 4); + + /* Because of byte swapping this swizzle works nicely */ + sprintf(Reg, "RSP_Vect[%i].B[%i]", RSPOpC.rt, 16 - RSPOpC.del - 4); + MoveX86regToVariable(x86_EAX, &RSP_Vect[RSPOpC.rt].B[16 - RSPOpC.del - 4], Reg); + sprintf(Reg, "RSP_Vect[%i].B[%i]", RSPOpC.rt, 16 - RSPOpC.del - 8); + MoveX86regToVariable(x86_ECX, &RSP_Vect[RSPOpC.rt].B[16 - RSPOpC.del - 8], Reg); + + CPU_Message(" Done:"); + x86_SetBranch32b(Jump[1], RecompPos); +} + +void Compile_Opcode_LQV ( void ) { + char Reg[256]; + int offset = (RSPOpC.voffset << 4); + BYTE * Jump[2]; + + #ifndef CompileLqv + Cheat_r4300iOpcode(RSP_Opcode_LQV,"RSP_Opcode_LQV"); return; + #endif + + CPU_Message(" %X %s",CompilePC,RSPOpcodeName(RSPOpC.Hex,CompilePC)); + + if (RSPOpC.del != 0) { + rsp_UnknownOpcode(); + return; + } + + if (IsRegConst(RSPOpC.base) == TRUE) { + DWORD Addr = (MipsRegConst(RSPOpC.base) + offset) & 0xfff; + + if (Addr & 15) { + CompilerWarning("Unaligned LQV at constant address PC = %04X", CompilePC); + Cheat_r4300iOpcodeNoMessage(RSP_Opcode_LQV,"RSP_Opcode_LQV"); + return; + } + + /* + * Aligned store + */ + + if (IsSseEnabled == FALSE) { + sprintf(Reg, "Dmem+%Xh+0", Addr); + MoveVariableToX86reg(RSPInfo.DMEM + Addr + 0, Reg, x86_EAX); + sprintf(Reg, "Dmem+%Xh+4", Addr); + MoveVariableToX86reg(RSPInfo.DMEM + Addr + 4, Reg, x86_EBX); + sprintf(Reg, "Dmem+%Xh+8", Addr); + MoveVariableToX86reg(RSPInfo.DMEM + Addr + 8, Reg, x86_ECX); + sprintf(Reg, "Dmem+%Xh+C", Addr); + MoveVariableToX86reg(RSPInfo.DMEM + Addr + 12, Reg, x86_EDX); + + sprintf(Reg, "RSP_Vect[%i].B[12]", RSPOpC.rt); + MoveX86regToVariable(x86_EAX, &RSP_Vect[RSPOpC.rt].B[12], Reg); + sprintf(Reg, "RSP_Vect[%i].B[8]", RSPOpC.rt); + MoveX86regToVariable(x86_EBX, &RSP_Vect[RSPOpC.rt].B[8], Reg); + sprintf(Reg, "RSP_Vect[%i].B[4]", RSPOpC.rt); + MoveX86regToVariable(x86_ECX, &RSP_Vect[RSPOpC.rt].B[4], Reg); + sprintf(Reg, "RSP_Vect[%i].B[0]", RSPOpC.rt); + MoveX86regToVariable(x86_EDX, &RSP_Vect[RSPOpC.rt].B[0], Reg); + } else { + sprintf(Reg, "Dmem+%Xh", Addr); + SseMoveUnalignedVariableToReg(RSPInfo.DMEM + Addr, Reg, x86_XMM0); + SseShuffleReg(x86_XMM0, x86_MM0, 0x1b); + sprintf(Reg, "RSP_Vect[%i].B[0]", RSPOpC.rt); + SseMoveAlignedRegToVariable(x86_XMM0, &RSP_Vect[RSPOpC.rt].B[0], Reg); + } + return; + } + + MoveVariableToX86reg(&RSP_GPR[RSPOpC.base].UW, GPR_Name(RSPOpC.base), x86_EBX); + if (offset != 0) { + AddConstToX86Reg(x86_EBX, offset); + } + TestConstToX86Reg(15, x86_EBX); + JneLabel32("Unaligned", 0); + Jump[0] = RecompPos - 4; + + CompilerToggleBuffer(); + CPU_Message(" Unaligned:"); + x86_SetBranch32b(Jump[0], RecompPos); + + Cheat_r4300iOpcodeNoMessage(RSP_Opcode_LQV,"RSP_Opcode_LQV"); + JmpLabel32("Done", 0); + Jump[1] = RecompPos - 4; + CompilerToggleBuffer(); + + AndConstToX86Reg(x86_EBX, 0x0fff); + if (IsSseEnabled == FALSE) { + MoveN64MemDispToX86reg(x86_EAX, x86_EBX, 0); + MoveN64MemDispToX86reg(x86_ECX, x86_EBX, 4); + MoveN64MemDispToX86reg(x86_EDX, x86_EBX, 8); + MoveN64MemDispToX86reg(x86_EDI, x86_EBX, 12); + + sprintf(Reg, "RSP_Vect[%i].B[12]", RSPOpC.rt); + MoveX86regToVariable(x86_EAX, &RSP_Vect[RSPOpC.rt].B[12], Reg); + sprintf(Reg, "RSP_Vect[%i].B[8]", RSPOpC.rt); + MoveX86regToVariable(x86_ECX, &RSP_Vect[RSPOpC.rt].B[8], Reg); + sprintf(Reg, "RSP_Vect[%i].B[4]", RSPOpC.rt); + MoveX86regToVariable(x86_EDX, &RSP_Vect[RSPOpC.rt].B[4], Reg); + sprintf(Reg, "RSP_Vect[%i].B[0]", RSPOpC.rt); + MoveX86regToVariable(x86_EDI, &RSP_Vect[RSPOpC.rt].B[0], Reg); + } else { + SseMoveUnalignedN64MemToReg(x86_XMM0, x86_EBX); + SseShuffleReg(x86_XMM0, x86_MM0, 0x1b); + sprintf(Reg, "RSP_Vect[%i].B[0]", RSPOpC.rt); + SseMoveAlignedRegToVariable(x86_XMM0, &RSP_Vect[RSPOpC.rt].B[0], Reg); + } + CPU_Message(" Done:"); + x86_SetBranch32b((DWORD*)Jump[1], (DWORD*)RecompPos); +} + +void Compile_Opcode_LRV ( void ) { + int offset = (RSPOpC.voffset << 4); + BYTE * Loop, * Jump[2]; + + #ifndef CompileLrv + Cheat_r4300iOpcode(RSP_Opcode_LRV,"RSP_Opcode_LRV"); return; + #endif + + CPU_Message(" %X %s",CompilePC,RSPOpcodeName(RSPOpC.Hex,CompilePC)); + + if (RSPOpC.del != 0) { + rsp_UnknownOpcode(); + return; + } + + MoveVariableToX86reg(&RSP_GPR[RSPOpC.base].UW, GPR_Name(RSPOpC.base), x86_EBX); + if (offset != 0) AddConstToX86Reg(x86_EBX, offset); + + if (Compiler.bAlignVector == FALSE) { + TestConstToX86Reg(1, x86_EBX); + JneLabel32("Unaligned", 0); + Jump[0] = RecompPos - 4; + + /* Unaligned */ + CompilerToggleBuffer(); + + CPU_Message(" Unaligned:"); + x86_SetBranch32b(Jump[0], RecompPos); + + Cheat_r4300iOpcodeNoMessage(RSP_Opcode_LRV,"RSP_Opcode_LRV"); + JmpLabel32("Done", 0); + Jump[1] = RecompPos - 4; + + CompilerToggleBuffer(); + } + + /* Aligned */ + MoveX86RegToX86Reg(x86_EBX, x86_EAX); + AndConstToX86Reg(x86_EAX, 0x0F); + AndConstToX86Reg(x86_EBX, 0x0ff0); + + MoveX86RegToX86Reg(x86_EAX, x86_ECX); + ShiftRightUnsignImmed(x86_ECX, 1); + + JeLabel8("Done", 0); + Jump[0] = RecompPos - 1; +/* + DecX86reg(x86_EAX); + LeaSourceAndOffset(x86_EAX, x86_EAX, (DWORD) &RSP_Vect[RSPOpC.rt].B[0]); + DecX86reg(x86_EAX); +*/ + AddConstToX86Reg(x86_EAX, ((DWORD)&RSP_Vect[RSPOpC.rt].UB[0]) - 2); + + CPU_Message(" Loop:"); + Loop = RecompPos; + + MoveX86RegToX86Reg(x86_EBX, x86_ESI); + XorConstToX86Reg(x86_ESI, 2); + MoveN64MemToX86regHalf(x86_EDX, x86_ESI); + MoveX86regHalfToX86regPointer(x86_EDX, x86_EAX); + + AddConstToX86Reg(x86_EBX, 2); /* Dmem pointer */ + SubConstFromX86Reg(x86_EAX, 2); /* Vector pointer */ + DecX86reg(x86_ECX); /* Loop counter */ + JneLabel8("Loop", 0); + x86_SetBranch8b(RecompPos - 1, Loop); + + if (Compiler.bAlignVector == FALSE) { + CPU_Message(" Done:"); + x86_SetBranch32b((DWORD*)Jump[1], (DWORD*)RecompPos); + } + + x86_SetBranch8b(Jump[0], RecompPos); +} + +void Compile_Opcode_LPV ( void ) { + Cheat_r4300iOpcode(RSP_Opcode_LPV,"RSP_Opcode_LPV"); +} + +void Compile_Opcode_LUV ( void ) { + Cheat_r4300iOpcode(RSP_Opcode_LUV,"RSP_Opcode_LUV"); +} + + +void Compile_Opcode_LHV ( void ) { + Cheat_r4300iOpcode(RSP_Opcode_LHV,"RSP_Opcode_LHV"); +} + + +void Compile_Opcode_LFV ( void ) { + Cheat_r4300iOpcode(RSP_Opcode_LFV,"RSP_Opcode_LFV"); +} + +void Compile_Opcode_LTV ( void ) { + Cheat_r4300iOpcode(RSP_Opcode_LTV,"RSP_Opcode_LTV"); +} + +/************************** sc2 functions **************************/ + +void Compile_Opcode_SBV ( void ) { + Cheat_r4300iOpcode(RSP_Opcode_SBV,"RSP_Opcode_SBV"); +} + +void Compile_Opcode_SSV ( void ) { + char Reg[256]; + int offset = (RSPOpC.voffset << 1); + + if (RSPOpC.del > 14) { + rsp_UnknownOpcode(); + return; + } + + #ifndef CompileSsv + Cheat_r4300iOpcode(RSP_Opcode_SSV,"RSP_Opcode_SSV"); return; + #endif + + CPU_Message(" %X %s",CompilePC,RSPOpcodeName(RSPOpC.Hex,CompilePC)); + + if (IsRegConst(RSPOpC.base) == TRUE) { + DWORD Addr = (MipsRegConst(RSPOpC.base) + offset) & 0xfff; + + if ((Addr & 1) != 0) { + sprintf(Reg, "RSP_Vect[%i].B[%i]", RSPOpC.rt, 15 - (RSPOpC.del + 0)); + MoveVariableToX86regByte(&RSP_Vect[RSPOpC.rt].B[15 - (RSPOpC.del + 0)], Reg, x86_ECX); + sprintf(Reg, "RSP_Vect[%i].B[%i]", RSPOpC.rt, 15 - (RSPOpC.del + 1)); + MoveVariableToX86regByte(&RSP_Vect[RSPOpC.rt].B[15 - (RSPOpC.del + 1)], Reg, x86_EDX); + + sprintf(Reg, "Dmem + %Xh", (Addr + 0) ^ 3); + MoveX86regByteToVariable(x86_ECX, RSPInfo.DMEM + ((Addr + 0) ^ 3), Reg); + sprintf(Reg, "Dmem + %Xh", (Addr + 1) ^ 3); + MoveX86regByteToVariable(x86_EDX, RSPInfo.DMEM + ((Addr + 1) ^ 3), Reg); + } else { + sprintf(Reg, "RSP_Vect[%i].B[%i]", RSPOpC.rt, 15 - (RSPOpC.del + 1)); + MoveVariableToX86regHalf(&RSP_Vect[RSPOpC.rt].B[15 - (RSPOpC.del + 1)], Reg, x86_ECX); + sprintf(Reg, "Dmem + %Xh", Addr ^ 2); + MoveX86regHalfToVariable(x86_ECX, RSPInfo.DMEM + (Addr ^ 2), Reg); + } + return; + } + + MoveVariableToX86reg(&RSP_GPR[RSPOpC.base].UW, GPR_Name(RSPOpC.base), x86_EBX); + if (offset != 0) AddConstToX86Reg(x86_EBX, offset); + AndConstToX86Reg(x86_EBX, 0x0FFF); + + if (Compiler.bAlignVector == TRUE) { + sprintf(Reg, "RSP_Vect[%i].B[%i]", RSPOpC.rt, 15 - (RSPOpC.del + 1)); + MoveVariableToX86regHalf(&RSP_Vect[RSPOpC.rt].B[15 - (RSPOpC.del + 1)], Reg, x86_ECX); + XorConstToX86Reg(x86_EBX, 2); + MoveX86regHalfToN64Mem(x86_ECX, x86_EBX); + } else { + LeaSourceAndOffset(x86_EAX, x86_EBX, 1); + XorConstToX86Reg(x86_EBX, 3); + XorConstToX86Reg(x86_EAX, 3); + + sprintf(Reg, "RSP_Vect[%i].B[%i]", RSPOpC.rt, 15 - (RSPOpC.del + 0)); + MoveVariableToX86regByte(&RSP_Vect[RSPOpC.rt].B[15 - (RSPOpC.del + 0)], Reg, x86_ECX); + sprintf(Reg, "RSP_Vect[%i].B[%i]", RSPOpC.rt, 15 - (RSPOpC.del + 1)); + MoveVariableToX86regByte(&RSP_Vect[RSPOpC.rt].B[15 - (RSPOpC.del + 1)], Reg, x86_EDX); + + MoveX86regByteToN64Mem(x86_ECX, x86_EBX); + MoveX86regByteToN64Mem(x86_EDX, x86_EAX); + } +} + +void Compile_Opcode_SLV ( void ) { + char Reg[256]; + int offset = (RSPOpC.voffset << 2); + BYTE * Jump[2]; + + #ifndef CompileSlv + Cheat_r4300iOpcode(RSP_Opcode_SLV,"RSP_Opcode_SLV"); return; + #endif + + CPU_Message(" %X %s",CompilePC,RSPOpcodeName(RSPOpC.Hex,CompilePC)); + +// if ((RSPOpC.del & 0x3) != 0) { +// rsp_UnknownOpcode(); +// return; +// } + + if (IsRegConst(RSPOpC.base) == TRUE) { + DWORD Addr = (MipsRegConst(RSPOpC.base) + offset) & 0xfff; + + if ((Addr & 3) != 0) { + CompilerWarning("Unaligned SLV at constant address"); + Cheat_r4300iOpcodeNoMessage(RSP_Opcode_SLV,"RSP_Opcode_SLV"); + return; + } + + sprintf(Reg, "RSP_Vect[%i].B[%i]", RSPOpC.rt, 16 - RSPOpC.del - 4); + MoveVariableToX86reg(&RSP_Vect[RSPOpC.rt].B[16 - RSPOpC.del - 4], Reg, x86_EAX); + sprintf(Reg, "Dmem + %Xh", Addr); + MoveX86regToVariable(x86_EAX, RSPInfo.DMEM + Addr, Reg); + return; + } + + MoveVariableToX86reg(&RSP_GPR[RSPOpC.base].UW, GPR_Name(RSPOpC.base), x86_EBX); + if (offset != 0) AddConstToX86Reg(x86_EBX, offset); + + TestConstToX86Reg(3, x86_EBX); + JneLabel32("Unaligned", 0); + Jump[0] = RecompPos - 4; + + /* + * Unaligned + */ + CompilerToggleBuffer(); + + CPU_Message(" Unaligned:"); + *((DWORD *)(Jump[0]))=(DWORD)(RecompPos - Jump[0] - 4); + Cheat_r4300iOpcodeNoMessage(RSP_Opcode_SLV,"RSP_Opcode_SLV"); + JmpLabel32("Done", 0); + Jump[1] = RecompPos - 4; + + CompilerToggleBuffer(); + + /* + * Aligned + */ + + /* Because of byte swapping this swizzle works nicely */ + sprintf(Reg, "RSP_Vect[%i].B[%i]", RSPOpC.rt, 16 - RSPOpC.del - 4); + MoveVariableToX86reg(&RSP_Vect[RSPOpC.rt].B[16 - RSPOpC.del - 4], Reg, x86_EAX); + + AndConstToX86Reg(x86_EBX, 0x0fff); + MoveX86regToN64Mem(x86_EAX, x86_EBX); + + CPU_Message(" Done:"); + *((DWORD *)(Jump[1]))=(DWORD)(RecompPos - Jump[1] - 4); +} + +void Compile_Opcode_SDV ( void ) { + char Reg[256]; + int offset = (RSPOpC.voffset << 3); + BYTE * Jump[2], * LoopEntry; + + //if ((RSPOpC.del & 0x7) != 0) { + // rsp_UnknownOpcode(); + // return; + //} + + #ifndef CompileSdv + Cheat_r4300iOpcode(RSP_Opcode_SDV,"RSP_Opcode_SDV"); return; + #endif + + CPU_Message(" %X %s",CompilePC,RSPOpcodeName(RSPOpC.Hex,CompilePC)); + + if (IsRegConst(RSPOpC.base) == TRUE) { + DWORD Addr = (MipsRegConst(RSPOpC.base) + offset) & 0xfff; + + if ((Addr & 3) != 0) { + CompilerWarning("Unaligned SDV at constant address PC = %04X", CompilePC); + Cheat_r4300iOpcodeNoMessage(RSP_Opcode_SDV,"RSP_Opcode_SDV"); + return; + } + + sprintf(Reg, "RSP_Vect[%i].B[%i]", RSPOpC.rt, 16 - RSPOpC.del - 4); + MoveVariableToX86reg(&RSP_Vect[RSPOpC.rt].B[16 - RSPOpC.del - 4], Reg, x86_EAX); + sprintf(Reg, "RSP_Vect[%i].B[%i]", RSPOpC.rt, 16 - RSPOpC.del - 8); + MoveVariableToX86reg(&RSP_Vect[RSPOpC.rt].B[16 - RSPOpC.del - 8], Reg, x86_EBX); + + sprintf(Reg, "Dmem + %Xh", Addr); + MoveX86regToVariable(x86_EAX, RSPInfo.DMEM + Addr, Reg); + sprintf(Reg, "Dmem + %Xh", Addr + 4); + MoveX86regToVariable(x86_EBX, RSPInfo.DMEM + Addr + 4, Reg); + return; + } + + MoveVariableToX86reg(&RSP_GPR[RSPOpC.base].UW, GPR_Name(RSPOpC.base), x86_EBX); + if (offset != 0) { + AddConstToX86Reg(x86_EBX, offset); + } + AndConstToX86Reg(x86_EBX, 0x0fff); + TestConstToX86Reg(3, x86_EBX); + JneLabel32("Unaligned", 0); + Jump[0] = RecompPos - 4; + + CompilerToggleBuffer(); + CPU_Message(" Unaligned:"); + x86_SetBranch32b((DWORD*)Jump[0], (DWORD*)RecompPos); + + sprintf(Reg, "RSP_Vect[%i].UB[%i]", RSPOpC.rt, 15 - RSPOpC.del); + MoveOffsetToX86reg((DWORD)&RSP_Vect[RSPOpC.rt].UB[15 - RSPOpC.del], Reg, x86_EDI); + MoveConstToX86reg(8, x86_ECX); + + CPU_Message(" Loop:"); + LoopEntry = RecompPos; + MoveX86RegToX86Reg(x86_EBX, x86_EAX); + XorConstToX86Reg(x86_EAX, 3); + MoveX86regPointerToX86regByte(x86_EDX, x86_EDI); + MoveX86regByteToN64Mem(x86_EDX, x86_EAX); + IncX86reg(x86_EBX); /* address constant */ + DecX86reg(x86_EDI); /* vector pointer */ + DecX86reg(x86_ECX); /* counter */ + JneLabel8("Loop", 0); + x86_SetBranch8b(RecompPos - 1, LoopEntry); + + JmpLabel32("Done", 0); + Jump[1] = RecompPos - 4; + CompilerToggleBuffer(); + + sprintf(Reg, "RSP_Vect[%i].B[%i]", RSPOpC.rt, 16 - RSPOpC.del - 4); + MoveVariableToX86reg(&RSP_Vect[RSPOpC.rt].B[16 - RSPOpC.del - 4], Reg, x86_EAX); + sprintf(Reg, "RSP_Vect[%i].B[%i]", RSPOpC.rt, 16 - RSPOpC.del - 8); + MoveVariableToX86reg(&RSP_Vect[RSPOpC.rt].B[16 - RSPOpC.del - 8], Reg, x86_ECX); + MoveX86regToN64Mem(x86_EAX, x86_EBX); + MoveX86regToN64MemDisp(x86_ECX, x86_EBX, 4); + + CPU_Message(" Done:"); + x86_SetBranch32b((DWORD*)Jump[1], (DWORD*)RecompPos); +} + +void Compile_Opcode_SQV ( void ) { + char Reg[256]; + int offset = (RSPOpC.voffset << 4); + BYTE * Jump[2]; + + #ifndef CompileSqv + Cheat_r4300iOpcode(RSP_Opcode_SQV,"RSP_Opcode_SQV"); return; + #endif + + CPU_Message(" %X %s",CompilePC,RSPOpcodeName(RSPOpC.Hex,CompilePC)); + + if (RSPOpC.del != 0) { + rsp_UnknownOpcode(); + return; + } + + if (IsRegConst(RSPOpC.base) == TRUE) { + DWORD Addr = (MipsRegConst(RSPOpC.base) + offset) & 0xfff; + + if (Addr & 15) { + CompilerWarning("Unaligned SQV at constant address %04X", CompilePC); + Cheat_r4300iOpcodeNoMessage(RSP_Opcode_SQV,"RSP_Opcode_SQV"); + return; + } + + /* + * Aligned store + */ + + if (IsSseEnabled == FALSE) { + sprintf(Reg, "RSP_Vect[%i].B[12]", RSPOpC.rt); + MoveVariableToX86reg(&RSP_Vect[RSPOpC.rt].B[12], Reg, x86_EAX); + sprintf(Reg, "RSP_Vect[%i].B[8]", RSPOpC.rt); + MoveVariableToX86reg(&RSP_Vect[RSPOpC.rt].B[8], Reg, x86_EBX); + sprintf(Reg, "RSP_Vect[%i].B[4]", RSPOpC.rt); + MoveVariableToX86reg(&RSP_Vect[RSPOpC.rt].B[4], Reg, x86_ECX); + sprintf(Reg, "RSP_Vect[%i].B[0]", RSPOpC.rt); + MoveVariableToX86reg(&RSP_Vect[RSPOpC.rt].B[0], Reg, x86_EDX); + + sprintf(Reg, "Dmem+%Xh+0", Addr); + MoveX86regToVariable(x86_EAX, RSPInfo.DMEM + Addr + 0, Reg); + sprintf(Reg, "Dmem+%Xh+4", Addr); + MoveX86regToVariable(x86_EBX, RSPInfo.DMEM + Addr + 4, Reg); + sprintf(Reg, "Dmem+%Xh+8", Addr); + MoveX86regToVariable(x86_ECX, RSPInfo.DMEM + Addr + 8, Reg); + sprintf(Reg, "Dmem+%Xh+C", Addr); + MoveX86regToVariable(x86_EDX, RSPInfo.DMEM + Addr + 12, Reg); + } else { + sprintf(Reg, "RSP_Vect[%i].B[0]", RSPOpC.rt); + SseMoveAlignedVariableToReg(&RSP_Vect[RSPOpC.rt].B[0], Reg, x86_XMM0); + SseShuffleReg(x86_XMM0, x86_MM0, 0x1b); + sprintf(Reg, "Dmem+%Xh", Addr); + SseMoveUnalignedRegToVariable(x86_XMM0, RSPInfo.DMEM + Addr, Reg); + } + return; + } + + MoveVariableToX86reg(&RSP_GPR[RSPOpC.base].UW, GPR_Name(RSPOpC.base), x86_EBX); + if (offset != 0) { + AddConstToX86Reg(x86_EBX, offset); + } + TestConstToX86Reg(15, x86_EBX); + JneLabel32("Unaligned", 0); + Jump[0] = RecompPos - 4; + + CompilerToggleBuffer(); + CPU_Message(" Unaligned:"); + x86_SetBranch32b((DWORD*)Jump[0], (DWORD*)RecompPos); + Cheat_r4300iOpcodeNoMessage(RSP_Opcode_SQV,"RSP_Opcode_SQV"); + JmpLabel32("Done", 0); + Jump[1] = RecompPos - 4; + CompilerToggleBuffer(); + + AndConstToX86Reg(x86_EBX, 0x0fff); + if (IsSseEnabled == FALSE) { + sprintf(Reg, "RSP_Vect[%i].B[12]", RSPOpC.rt); + MoveVariableToX86reg(&RSP_Vect[RSPOpC.rt].B[12], Reg, x86_EAX); + sprintf(Reg, "RSP_Vect[%i].B[8]", RSPOpC.rt); + MoveVariableToX86reg(&RSP_Vect[RSPOpC.rt].B[8], Reg, x86_ECX); + sprintf(Reg, "RSP_Vect[%i].B[4]", RSPOpC.rt); + MoveVariableToX86reg(&RSP_Vect[RSPOpC.rt].B[4], Reg, x86_EDX); + sprintf(Reg, "RSP_Vect[%i].B[0]", RSPOpC.rt); + MoveVariableToX86reg(&RSP_Vect[RSPOpC.rt].B[0], Reg, x86_EDI); + + MoveX86regToN64MemDisp(x86_EAX, x86_EBX, 0); + MoveX86regToN64MemDisp(x86_ECX, x86_EBX, 4); + MoveX86regToN64MemDisp(x86_EDX, x86_EBX, 8); + MoveX86regToN64MemDisp(x86_EDI, x86_EBX, 12); + } else { + sprintf(Reg, "RSP_Vect[%i].B[0]", RSPOpC.rt); + SseMoveAlignedVariableToReg(&RSP_Vect[RSPOpC.rt].B[0], Reg, x86_XMM0); + SseShuffleReg(x86_XMM0, x86_MM0, 0x1b); + SseMoveUnalignedRegToN64Mem(x86_XMM0, x86_EBX); + } + CPU_Message(" Done:"); + x86_SetBranch32b((DWORD*)Jump[1], (DWORD*)RecompPos); +} + +void Compile_Opcode_SRV ( void ) { + Cheat_r4300iOpcode(RSP_Opcode_SRV,"RSP_Opcode_SRV"); +} + +void Compile_Opcode_SPV ( void ) { + Cheat_r4300iOpcode(RSP_Opcode_SPV,"RSP_Opcode_SPV"); +} + +void Compile_Opcode_SUV ( void ) { + Cheat_r4300iOpcode(RSP_Opcode_SUV,"RSP_Opcode_SUV"); +} + +void Compile_Opcode_SHV ( void ) { + Cheat_r4300iOpcode(RSP_Opcode_SHV,"RSP_Opcode_SHV"); +} + +void Compile_Opcode_SFV ( void ) { + Cheat_r4300iOpcode(RSP_Opcode_SFV,"RSP_Opcode_SFV"); +} + +void Compile_Opcode_STV ( void ) { + Cheat_r4300iOpcode(RSP_Opcode_STV,"RSP_Opcode_STV"); +} + +void Compile_Opcode_SWV ( void ) { + Cheat_r4300iOpcode(RSP_Opcode_SWV,"RSP_Opcode_SWV"); +} + +/************************** Other functions **************************/ + +void Compile_UnknownOpcode (void) { + CPU_Message(" %X Unhandled Opcode: %s",CompilePC, RSPOpcodeName(RSPOpC.Hex,CompilePC) ); + NextInstruction = FINISH_BLOCK; + MoveConstToVariable(CompilePC,PrgCount,"RSP PC"); + MoveConstToVariable(RSPOpC.Hex,&RSPOpC.Hex, "RSPOpC.Hex"); + Call_Direct(rsp_UnknownOpcode, "rsp_UnknownOpcode" ); + Ret(); +} diff --git a/Source/RSP/Recompiler Ops.h b/Source/RSP/Recompiler Ops.h new file mode 100644 index 000000000..750353259 --- /dev/null +++ b/Source/RSP/Recompiler Ops.h @@ -0,0 +1,158 @@ +/* + * RSP Compiler plug in for Project 64 (A Nintendo 64 emulator). + * + * (c) Copyright 2001 jabo (jabo@emulation64.com) and + * zilmar (zilmar@emulation64.com) + * + * pj64 homepage: www.pj64.net + * + * Permission to use, copy, modify and distribute Project64 in both binary and + * source form, for non-commercial purposes, is hereby granted without fee, + * providing that this license information and copyright notice appear with + * all copies and any derived work. + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event shall the authors be held liable for any damages + * arising from the use of this software. + * + * Project64 is freeware for PERSONAL USE only. Commercial users should + * seek permission of the copyright holders first. Commercial use includes + * charging money for Project64 or software derived from Project64. + * + * The copyright holders request that bug fixes and improvements to the code + * should be forwarded to them so if they want them. + * + */ + +/************************* OpCode functions *************************/ +void Compile_SPECIAL ( void ); +void Compile_REGIMM ( void ); +void Compile_J ( void ); +void Compile_JAL ( void ); +void Compile_BEQ ( void ); +void Compile_BNE ( void ); +void Compile_BLEZ ( void ); +void Compile_BGTZ ( void ); +void Compile_ADDI ( void ); +void Compile_ADDIU ( void ); +void Compile_SLTI ( void ); +void Compile_SLTIU ( void ); +void Compile_ANDI ( void ); +void Compile_ORI ( void ); +void Compile_XORI ( void ); +void Compile_LUI ( void ); +void Compile_COP0 ( void ); +void Compile_COP2 ( void ); +void Compile_LB ( void ); +void Compile_LH ( void ); +void Compile_LW ( void ); +void Compile_LBU ( void ); +void Compile_LHU ( void ); +void Compile_SB ( void ); +void Compile_SH ( void ); +void Compile_SW ( void ); +void Compile_LC2 ( void ); +void Compile_SC2 ( void ); +/********************** R4300i OpCodes: Special **********************/ +void Compile_Special_SLL ( void ); +void Compile_Special_SRL ( void ); +void Compile_Special_SRA ( void ); +void Compile_Special_SLLV ( void ); +void Compile_Special_SRLV ( void ); +void Compile_Special_SRAV ( void ); +void Compile_Special_JR ( void ); +void Compile_Special_JALR ( void ); +void Compile_Special_BREAK ( void ); +void Compile_Special_ADD ( void ); +void Compile_Special_ADDU ( void ); +void Compile_Special_SUB ( void ); +void Compile_Special_SUBU ( void ); +void Compile_Special_AND ( void ); +void Compile_Special_OR ( void ); +void Compile_Special_XOR ( void ); +void Compile_Special_NOR ( void ); +void Compile_Special_SLT ( void ); +void Compile_Special_SLTU ( void ); +/********************** R4300i OpCodes: RegImm **********************/ +void Compile_RegImm_BLTZ ( void ); +void Compile_RegImm_BGEZ ( void ); +void Compile_RegImm_BLTZAL ( void ); +void Compile_RegImm_BGEZAL ( void ); +/************************** Cop0 functions *************************/ +void Compile_Cop0_MF ( void ); +void Compile_Cop0_MT ( void ); +/************************** Cop2 functions *************************/ +void Compile_Cop2_MF ( void ); +void Compile_Cop2_CF ( void ); +void Compile_Cop2_MT ( void ); +void Compile_Cop2_CT ( void ); +void Compile_COP2_VECTOR ( void ); +/************************** Vect functions **************************/ +void Compile_Vector_VMULF ( void ); +void Compile_Vector_VMULU ( void ); +void Compile_Vector_VMUDL ( void ); +void Compile_Vector_VMUDM ( void ); +void Compile_Vector_VMUDN ( void ); +void Compile_Vector_VMUDH ( void ); +void Compile_Vector_VMACF ( void ); +void Compile_Vector_VMACU ( void ); +void Compile_Vector_VMACQ ( void ); +void Compile_Vector_VMADL ( void ); +void Compile_Vector_VMADM ( void ); +void Compile_Vector_VMADN ( void ); +void Compile_Vector_VMADH ( void ); +void Compile_Vector_VADD ( void ); +void Compile_Vector_VSUB ( void ); +void Compile_Vector_VABS ( void ); +void Compile_Vector_VADDC ( void ); +void Compile_Vector_VSUBC ( void ); +void Compile_Vector_VSAW ( void ); +void Compile_Vector_VLT ( void ); +void Compile_Vector_VEQ ( void ); +void Compile_Vector_VNE ( void ); +void Compile_Vector_VGE ( void ); +void Compile_Vector_VCL ( void ); +void Compile_Vector_VCH ( void ); +void Compile_Vector_VCR ( void ); +void Compile_Vector_VMRG ( void ); +void Compile_Vector_VAND ( void ); +void Compile_Vector_VNAND ( void ); +void Compile_Vector_VOR ( void ); +void Compile_Vector_VNOR ( void ); +void Compile_Vector_VXOR ( void ); +void Compile_Vector_VNXOR ( void ); +void Compile_Vector_VRCP ( void ); +void Compile_Vector_VRCPL ( void ); +void Compile_Vector_VRCPH ( void ); +void Compile_Vector_VMOV ( void ); +void Compile_Vector_VRSQ ( void ); +void Compile_Vector_VRSQL ( void ); +void Compile_Vector_VRSQH ( void ); +void Compile_Vector_VNOOP ( void ); +/************************** lc2 functions **************************/ +void Compile_Opcode_LBV ( void ); +void Compile_Opcode_LSV ( void ); +void Compile_Opcode_LLV ( void ); +void Compile_Opcode_LDV ( void ); +void Compile_Opcode_LQV ( void ); +void Compile_Opcode_LRV ( void ); +void Compile_Opcode_LPV ( void ); +void Compile_Opcode_LUV ( void ); +void Compile_Opcode_LHV ( void ); +void Compile_Opcode_LFV ( void ); +void Compile_Opcode_LTV ( void ); +/************************** sc2 functions **************************/ +void Compile_Opcode_SBV ( void ); +void Compile_Opcode_SSV ( void ); +void Compile_Opcode_SLV ( void ); +void Compile_Opcode_SDV ( void ); +void Compile_Opcode_SQV ( void ); +void Compile_Opcode_SRV ( void ); +void Compile_Opcode_SPV ( void ); +void Compile_Opcode_SUV ( void ); +void Compile_Opcode_SHV ( void ); +void Compile_Opcode_SFV ( void ); +void Compile_Opcode_SWV ( void ); +void Compile_Opcode_STV ( void ); +/************************** Other functions **************************/ +void Compile_UnknownOpcode (void); diff --git a/Source/RSP/Recompiler Sections.c b/Source/RSP/Recompiler Sections.c new file mode 100644 index 000000000..c0eb99a18 --- /dev/null +++ b/Source/RSP/Recompiler Sections.c @@ -0,0 +1,1136 @@ +/* + * RSP Compiler plug in for Project 64 (A Nintendo 64 emulator). + * + * (c) Copyright 2001 jabo (jabo@emulation64.com) and + * zilmar (zilmar@emulation64.com) + * + * pj64 homepage: www.pj64.net + * + * Permission to use, copy, modify and distribute Project64 in both binary and + * source form, for non-commercial purposes, is hereby granted without fee, + * providing that this license information and copyright notice appear with + * all copies and any derived work. + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event shall the authors be held liable for any damages + * arising from the use of this software. + * + * Project64 is freeware for PERSONAL USE only. Commercial users should + * seek permission of the copyright holders first. Commercial use includes + * charging money for Project64 or software derived from Project64. + * + * The copyright holders request that bug fixes and improvements to the code + * should be forwarded to them so if they want them. + * + */ + +#include +#include +#include "RSP.h" +#include "CPU.h" +#include "Recompiler CPU.h" +#include "RSP Command.h" +#include "RSP Registers.h" +#include "memory.h" +#include "dma.h" +#include "log.h" +#include "x86.h" + +void RSP_Sections_VMUDH ( OPCODE RspOp, DWORD AccumStyle ) { + char Reg[256]; + + /***************************************** + ** VMUDH + ** - affects the upper 32-bits + ******************************************/ + + if (AccumStyle == Low16BitAccum) { + MmxXorRegToReg(x86_MM0, x86_MM0); + MmxXorRegToReg(x86_MM1, x86_MM1); + return; + } + + RSPOpC = RspOp; + + /**** Load source registers ****/ + sprintf(Reg, "RSP_Vect[%i].HW[0]", RspOp.rd); + MmxMoveQwordVariableToReg(x86_MM0, &RSP_Vect[RspOp.rd].HW[0], Reg); + sprintf(Reg, "RSP_Vect[%i].HW[4]", RspOp.rd); + MmxMoveQwordVariableToReg(x86_MM1, &RSP_Vect[RspOp.rd].HW[4], Reg); + + /******* VMUDH *******/ + if ((RspOp.rs & 0x0f) < 2) { + sprintf(Reg, "RSP_Vect[%i].HW[0]", RspOp.rt); + MmxMoveQwordVariableToReg(x86_MM2, &RSP_Vect[RspOp.rt].HW[0], Reg); + sprintf(Reg, "RSP_Vect[%i].HW[4]", RspOp.rt); + MmxMoveQwordVariableToReg(x86_MM3, &RSP_Vect[RspOp.rt].HW[4], Reg); + + if (AccumStyle == Middle16BitAccum) { + MmxPmullwRegToReg(x86_MM0, x86_MM2); + MmxPmullwRegToReg(x86_MM1, x86_MM3); + } else { + MmxPmulhwRegToReg(x86_MM0, x86_MM2); + MmxPmulhwRegToReg(x86_MM1, x86_MM3); + } + } else if ((RspOp.rs & 0x0f) >= 8) { + RSP_Element2Mmx(x86_MM2); + if (AccumStyle == Middle16BitAccum) { + MmxPmullwRegToReg(x86_MM0, x86_MM2); + MmxPmullwRegToReg(x86_MM1, x86_MM2); + } else { + MmxPmulhwRegToReg(x86_MM0, x86_MM2); + MmxPmulhwRegToReg(x86_MM1, x86_MM2); + } + } else { + RSP_MultiElement2Mmx(x86_MM2, x86_MM3); + if (AccumStyle == Middle16BitAccum) { + MmxPmullwRegToReg(x86_MM0, x86_MM2); + MmxPmullwRegToReg(x86_MM1, x86_MM3); + } else { + MmxPmulhwRegToReg(x86_MM0, x86_MM2); + MmxPmulhwRegToReg(x86_MM1, x86_MM3); + } + } +} + +void RSP_Sections_VMADH ( OPCODE RspOp, DWORD AccumStyle ) { + char Reg[256]; + + /***************************************** + ** VMADH + ** - affects the upper 32-bits + ******************************************/ + + if (AccumStyle == Low16BitAccum) { + return; + } + + RSPOpC = RspOp; + + /**** Load source registers ****/ + sprintf(Reg, "RSP_Vect[%i].HW[0]", RspOp.rd); + MmxMoveQwordVariableToReg(x86_MM0 + 2, &RSP_Vect[RspOp.rd].HW[0], Reg); + sprintf(Reg, "RSP_Vect[%i].HW[4]", RspOp.rd); + MmxMoveQwordVariableToReg(x86_MM1 + 2, &RSP_Vect[RspOp.rd].HW[4], Reg); + + /******* VMUDH *******/ + if ((RspOp.rs & 0x0f) < 2) { + sprintf(Reg, "RSP_Vect[%i].HW[0]", RspOp.rt); + MmxMoveQwordVariableToReg(x86_MM2 + 2, &RSP_Vect[RspOp.rt].HW[0], Reg); + sprintf(Reg, "RSP_Vect[%i].HW[4]", RspOp.rt); + MmxMoveQwordVariableToReg(x86_MM3 + 2, &RSP_Vect[RspOp.rt].HW[4], Reg); + + if (AccumStyle == Middle16BitAccum) { + MmxPmullwRegToReg(x86_MM0 + 2, x86_MM2 + 2); + MmxPmullwRegToReg(x86_MM1 + 2, x86_MM3 + 2); + } else { + MmxPmulhwRegToReg(x86_MM0 + 2, x86_MM2 + 2); + MmxPmulhwRegToReg(x86_MM1 + 2, x86_MM3 + 2); + } + } else if ((RspOp.rs & 0x0f) >= 8) { + RSP_Element2Mmx(x86_MM2 + 2); + if (AccumStyle == Middle16BitAccum) { + MmxPmullwRegToReg(x86_MM0 + 2, x86_MM2 + 2); + MmxPmullwRegToReg(x86_MM1 + 2, x86_MM2 + 2); + } else { + MmxPmulhwRegToReg(x86_MM0 + 2, x86_MM2 + 2); + MmxPmulhwRegToReg(x86_MM1 + 2, x86_MM2 + 2); + } + } else { + RSP_MultiElement2Mmx(x86_MM2 + 2, x86_MM3 + 2); + if (AccumStyle == Middle16BitAccum) { + MmxPmullwRegToReg(x86_MM0 + 2, x86_MM2 + 2); + MmxPmullwRegToReg(x86_MM1 + 2, x86_MM3 + 2); + } else { + MmxPmulhwRegToReg(x86_MM0 + 2, x86_MM2 + 2); + MmxPmulhwRegToReg(x86_MM1 + 2, x86_MM3 + 2); + } + } + + MmxPaddswRegToReg(x86_MM0, x86_MM0 + 2); + MmxPaddswRegToReg(x86_MM1, x86_MM1 + 2); +} + +void RSP_Sections_VMUDL ( OPCODE RspOp, DWORD AccumStyle ) { + char Reg[256]; + + /***************************************** + ** VMUDL + ** - affects the lower 16-bits + ******************************************/ + + if (AccumStyle != Low16BitAccum) { + MmxXorRegToReg(x86_MM0, x86_MM0); + MmxXorRegToReg(x86_MM1, x86_MM1); + return; + } + + RSPOpC = RspOp; + + /**** Load source registers ****/ + sprintf(Reg, "RSP_Vect[%i].HW[0]", RspOp.rd); + MmxMoveQwordVariableToReg(x86_MM0, &RSP_Vect[RspOp.rd].HW[0], Reg); + sprintf(Reg, "RSP_Vect[%i].HW[4]", RspOp.rd); + MmxMoveQwordVariableToReg(x86_MM1, &RSP_Vect[RspOp.rd].HW[4], Reg); + + /******* VMUDL *******/ + if ((RspOp.rs & 0x0f) < 2) { + sprintf(Reg, "RSP_Vect[%i].HW[0]", RspOp.rt); + MmxMoveQwordVariableToReg(x86_MM2, &RSP_Vect[RspOp.rt].HW[0], Reg); + sprintf(Reg, "RSP_Vect[%i].HW[4]", RspOp.rt); + MmxMoveQwordVariableToReg(x86_MM3, &RSP_Vect[RspOp.rt].HW[4], Reg); + + MmxPmullwRegToReg(x86_MM0, x86_MM2); + MmxPmullwRegToReg(x86_MM1, x86_MM3); + } else if ((RspOp.rs & 0x0f) >= 8) { + RSP_Element2Mmx(x86_MM2); + MmxPmullwRegToReg(x86_MM0, x86_MM2); + MmxPmullwRegToReg(x86_MM1, x86_MM2); + } else { + RSP_MultiElement2Mmx(x86_MM2, x86_MM3); + MmxPmullwRegToReg(x86_MM0, x86_MM2); + MmxPmullwRegToReg(x86_MM1, x86_MM3); + } +} + +void RSP_Sections_VMADL ( OPCODE RspOp, DWORD AccumStyle ) { + char Reg[256]; + + /***************************************** + ** VMADL + ** - affects the lower 16-bits + ******************************************/ + + if (AccumStyle != Low16BitAccum) { + return; + } + + RSPOpC = RspOp; + + /**** Load source registers ****/ + sprintf(Reg, "RSP_Vect[%i].HW[0]", RspOp.rd); + MmxMoveQwordVariableToReg(x86_MM0 + 2, &RSP_Vect[RspOp.rd].HW[0], Reg); + sprintf(Reg, "RSP_Vect[%i].HW[4]", RspOp.rd); + MmxMoveQwordVariableToReg(x86_MM1 + 2, &RSP_Vect[RspOp.rd].HW[4], Reg); + + /******* VMADL *******/ + if ((RspOp.rs & 0x0f) < 2) { + sprintf(Reg, "RSP_Vect[%i].HW[0]", RspOp.rt); + MmxMoveQwordVariableToReg(x86_MM2 + 2, &RSP_Vect[RspOp.rt].HW[0], Reg); + sprintf(Reg, "RSP_Vect[%i].HW[4]", RspOp.rt); + MmxMoveQwordVariableToReg(x86_MM3 + 2, &RSP_Vect[RspOp.rt].HW[4], Reg); + + MmxPmullwRegToReg(x86_MM0 + 2, x86_MM2 + 2); + MmxPmullwRegToReg(x86_MM1 + 2, x86_MM3 + 2); + } else if ((RspOp.rs & 0x0f) >= 8) { + RSP_Element2Mmx(x86_MM2); + MmxPmullwRegToReg(x86_MM0 + 2, x86_MM2 + 2); + MmxPmullwRegToReg(x86_MM1 + 2, x86_MM2 + 2); + } else { + RSP_MultiElement2Mmx(x86_MM2 + 2, x86_MM3 + 2); + MmxPmullwRegToReg(x86_MM0 + 2, x86_MM2 + 2); + MmxPmullwRegToReg(x86_MM1 + 2, x86_MM3 + 2); + } + + MmxPaddswRegToReg(x86_MM0, x86_MM0 + 2); + MmxPaddswRegToReg(x86_MM1, x86_MM1 + 2); +} + +void RSP_Sections_VMUDM ( OPCODE RspOp, DWORD AccumStyle ) { + char Reg[256]; + + /***************************************** + ** VMUDM + ** - affects the middle 32-bits, s16*u16 + ******************************************/ + + if (AccumStyle == High16BitAccum) { + MmxXorRegToReg(x86_MM0, x86_MM0); + MmxXorRegToReg(x86_MM1, x86_MM1); + return; + } + + RSPOpC = RspOp; + + /**** Load source registers ****/ + sprintf(Reg, "RSP_Vect[%i].HW[0]", RspOp.rd); + MmxMoveQwordVariableToReg(x86_MM0, &RSP_Vect[RspOp.rd].HW[0], Reg); + sprintf(Reg, "RSP_Vect[%i].HW[4]", RspOp.rd); + MmxMoveQwordVariableToReg(x86_MM1, &RSP_Vect[RspOp.rd].HW[4], Reg); + + /******* VMUDM *******/ + if (AccumStyle != Middle16BitAccum) { + if ((RspOp.rs & 0x0f) < 2) { + sprintf(Reg, "RSP_Vect[%i].HW[0]", RspOp.rt); + MmxMoveQwordVariableToReg(x86_MM2, &RSP_Vect[RspOp.rt].HW[0], Reg); + sprintf(Reg, "RSP_Vect[%i].HW[4]", RspOp.rt); + MmxMoveQwordVariableToReg(x86_MM3, &RSP_Vect[RspOp.rt].HW[4], Reg); + + MmxPmullwRegToReg(x86_MM0, x86_MM2); + MmxPmullwRegToReg(x86_MM1, x86_MM3); + } else if ((RspOp.rs & 0x0f) >= 8) { + RSP_Element2Mmx(x86_MM2); + MmxPmullwRegToReg(x86_MM0, x86_MM2); + MmxPmullwRegToReg(x86_MM1, x86_MM2); + } else { + RSP_MultiElement2Mmx(x86_MM2, x86_MM3); + MmxPmullwRegToReg(x86_MM0, x86_MM2); + MmxPmullwRegToReg(x86_MM1, x86_MM3); + } + } else { + if ((RSPOpC.rs & 0xF) < 2) { + sprintf(Reg, "RSP_Vect[%i].UHW[0]", RSPOpC.rt); + MmxMoveQwordVariableToReg(x86_MM4, &RSP_Vect[RSPOpC.rt].UHW[0], Reg); + sprintf(Reg, "RSP_Vect[%i].UHW[4]", RSPOpC.rt); + MmxMoveQwordVariableToReg(x86_MM5, &RSP_Vect[RSPOpC.rt].UHW[4], Reg); + + /* Copy the signed portion */ + MmxMoveRegToReg(x86_MM2, x86_MM0); + MmxMoveRegToReg(x86_MM3, x86_MM1); + + /* high((u16)a * b) */ + MmxPmulhuwRegToReg(x86_MM0, x86_MM4); + MmxPmulhuwRegToReg(x86_MM1, x86_MM5); + + /* low((a >> 15) * b) */ + MmxPsrawImmed(x86_MM2, 15); + MmxPsrawImmed(x86_MM3, 15); + MmxPmullwRegToReg(x86_MM2, x86_MM4); + MmxPmullwRegToReg(x86_MM3, x86_MM5); + } else if ((RSPOpC.rs & 0xF) >= 8) { + RSP_Element2Mmx(x86_MM4); + + /* Copy the signed portion */ + MmxMoveRegToReg(x86_MM2, x86_MM0); + MmxMoveRegToReg(x86_MM3, x86_MM1); + + /* high((u16)a * b) */ + MmxPmulhuwRegToReg(x86_MM0, x86_MM4); + MmxPmulhuwRegToReg(x86_MM1, x86_MM4); + + /* low((a >> 15) * b) */ + MmxPsrawImmed(x86_MM2, 15); + MmxPsrawImmed(x86_MM3, 15); + MmxPmullwRegToReg(x86_MM2, x86_MM4); + MmxPmullwRegToReg(x86_MM3, x86_MM4); + } else { + RSP_MultiElement2Mmx(x86_MM4, x86_MM5); + + /* Copy the signed portion */ + MmxMoveRegToReg(x86_MM2, x86_MM0); + MmxMoveRegToReg(x86_MM3, x86_MM1); + + /* high((u16)a * b) */ + MmxPmulhuwRegToReg(x86_MM0, x86_MM4); + MmxPmulhuwRegToReg(x86_MM1, x86_MM5); + + /* low((a >> 15) * b) */ + MmxPsrawImmed(x86_MM2, 15); + MmxPsrawImmed(x86_MM3, 15); + MmxPmullwRegToReg(x86_MM2, x86_MM4); + MmxPmullwRegToReg(x86_MM3, x86_MM5); + } + + /* Add them up */ + MmxPaddwRegToReg(x86_MM0, x86_MM2); + MmxPaddwRegToReg(x86_MM1, x86_MM3); + } +} + +void RSP_Sections_VMADM ( OPCODE RspOp, DWORD AccumStyle ) { + char Reg[256]; + + /***************************************** + ** VMADM + ** - affects the middle 32-bits, s16*u16 + ******************************************/ + + if (AccumStyle == High16BitAccum) { + MmxXorRegToReg(x86_MM0, x86_MM0); + MmxXorRegToReg(x86_MM1, x86_MM1); + return; + } + + RSPOpC = RspOp; + + /**** Load source registers ****/ + sprintf(Reg, "RSP_Vect[%i].HW[0]", RspOp.rd); + MmxMoveQwordVariableToReg(x86_MM0 + 2, &RSP_Vect[RspOp.rd].HW[0], Reg); + sprintf(Reg, "RSP_Vect[%i].HW[4]", RspOp.rd); + MmxMoveQwordVariableToReg(x86_MM1 + 2, &RSP_Vect[RspOp.rd].HW[4], Reg); + + /******* VMADM *******/ + if (AccumStyle != Middle16BitAccum) { + if ((RspOp.rs & 0x0f) < 2) { + sprintf(Reg, "RSP_Vect[%i].HW[0]", RspOp.rt); + MmxMoveQwordVariableToReg(x86_MM2 + 2, &RSP_Vect[RspOp.rt].HW[0], Reg); + sprintf(Reg, "RSP_Vect[%i].HW[4]", RspOp.rt); + MmxMoveQwordVariableToReg(x86_MM3 + 2, &RSP_Vect[RspOp.rt].HW[4], Reg); + + MmxPmullwRegToReg(x86_MM0 + 2, x86_MM2 + 2); + MmxPmullwRegToReg(x86_MM1 + 2, x86_MM3 + 2); + } else if ((RspOp.rs & 0x0f) >= 8) { + RSP_Element2Mmx(x86_MM2 + 2); + MmxPmullwRegToReg(x86_MM0 + 2, x86_MM2 + 2); + MmxPmullwRegToReg(x86_MM1 + 2, x86_MM2 + 2); + } else { + RSP_MultiElement2Mmx(x86_MM2 + 2, x86_MM3 + 2); + MmxPmullwRegToReg(x86_MM0 + 2, x86_MM2 + 2); + MmxPmullwRegToReg(x86_MM1 + 2, x86_MM3 + 2); + } + } else { + if ((RSPOpC.rs & 0xF) < 2) { + sprintf(Reg, "RSP_Vect[%i].UHW[0]", RSPOpC.rt); + MmxMoveQwordVariableToReg(x86_MM4 + 2, &RSP_Vect[RSPOpC.rt].UHW[0], Reg); + sprintf(Reg, "RSP_Vect[%i].UHW[4]", RSPOpC.rt); + MmxMoveQwordVariableToReg(x86_MM5 + 2, &RSP_Vect[RSPOpC.rt].UHW[4], Reg); + + /* Copy the signed portion */ + MmxMoveRegToReg(x86_MM2 + 2, x86_MM0 + 2); + MmxMoveRegToReg(x86_MM3 + 2, x86_MM1 + 2); + + /* high((u16)a * b) */ + MmxPmulhuwRegToReg(x86_MM0 + 2, x86_MM4 + 2); + MmxPmulhuwRegToReg(x86_MM1 + 2, x86_MM5 + 2); + + /* low((a >> 15) * b) */ + MmxPsrawImmed(x86_MM2 + 2, 15); + MmxPsrawImmed(x86_MM3 + 2, 15); + MmxPmullwRegToReg(x86_MM2 + 2, x86_MM4 + 2); + MmxPmullwRegToReg(x86_MM3 + 2, x86_MM5 + 2); + } else if ((RSPOpC.rs & 0xF) >= 8) { + RSP_Element2Mmx(x86_MM4 + 2); + + /* Copy the signed portion */ + MmxMoveRegToReg(x86_MM2 + 2, x86_MM0 + 2); + MmxMoveRegToReg(x86_MM3 + 2, x86_MM1 + 2); + + /* high((u16)a * b) */ + MmxPmulhuwRegToReg(x86_MM0 + 2, x86_MM4 + 2); + MmxPmulhuwRegToReg(x86_MM1 + 2, x86_MM4 + 2); + + /* low((a >> 15) * b) */ + MmxPsrawImmed(x86_MM2 + 2, 15); + MmxPsrawImmed(x86_MM3 + 2, 15); + MmxPmullwRegToReg(x86_MM2 + 2, x86_MM4 + 2); + MmxPmullwRegToReg(x86_MM3 + 2, x86_MM4 + 2); + } else { + RSP_MultiElement2Mmx(x86_MM4 + 2, x86_MM5 + 2); + + /* Copy the signed portion */ + MmxMoveRegToReg(x86_MM2 + 2, x86_MM0 + 2); + MmxMoveRegToReg(x86_MM3 + 2, x86_MM1 + 2); + + /* high((u16)a * b) */ + MmxPmulhuwRegToReg(x86_MM0 + 2, x86_MM4 + 2); + MmxPmulhuwRegToReg(x86_MM1 + 2, x86_MM5 + 2); + + /* low((a >> 15) * b) */ + MmxPsrawImmed(x86_MM2 + 2, 15); + MmxPsrawImmed(x86_MM3 + 2, 15); + MmxPmullwRegToReg(x86_MM2 + 2, x86_MM4 + 2); + MmxPmullwRegToReg(x86_MM3 + 2, x86_MM5 + 2); + } + + /* Add them up */ + MmxPaddwRegToReg(x86_MM0 + 2, x86_MM2 + 2); + MmxPaddwRegToReg(x86_MM1 + 2, x86_MM3 + 2); + } + + MmxPaddswRegToReg(x86_MM0, x86_MM0 + 2); + MmxPaddswRegToReg(x86_MM1, x86_MM1 + 2); +} + +void RSP_Sections_VMUDN ( OPCODE RspOp, DWORD AccumStyle ) { + char Reg[256]; + + /***************************************** + ** VMUDN + ** - affects the middle 32-bits, u16*s16 + ******************************************/ + + if (AccumStyle == High16BitAccum) { + MmxXorRegToReg(x86_MM0, x86_MM0); + MmxXorRegToReg(x86_MM1, x86_MM1); + return; + } + + RSPOpC = RspOp; + + /******* VMUDN *******/ + if (AccumStyle != Middle16BitAccum) { + + /**** Load source registers ****/ + sprintf(Reg, "RSP_Vect[%i].HW[0]", RspOp.rd); + MmxMoveQwordVariableToReg(x86_MM0, &RSP_Vect[RspOp.rd].HW[0], Reg); + sprintf(Reg, "RSP_Vect[%i].HW[4]", RspOp.rd); + MmxMoveQwordVariableToReg(x86_MM1, &RSP_Vect[RspOp.rd].HW[4], Reg); + + if ((RspOp.rs & 0x0f) < 2) { + sprintf(Reg, "RSP_Vect[%i].HW[0]", RspOp.rt); + MmxMoveQwordVariableToReg(x86_MM2, &RSP_Vect[RspOp.rt].HW[0], Reg); + sprintf(Reg, "RSP_Vect[%i].HW[4]", RspOp.rt); + MmxMoveQwordVariableToReg(x86_MM3, &RSP_Vect[RspOp.rt].HW[4], Reg); + + MmxPmullwRegToReg(x86_MM0, x86_MM2); + MmxPmullwRegToReg(x86_MM1, x86_MM3); + } else if ((RspOp.rs & 0x0f) >= 8) { + RSP_Element2Mmx(x86_MM2); + + MmxPmullwRegToReg(x86_MM0, x86_MM2); + MmxPmullwRegToReg(x86_MM1, x86_MM2); + } else { + RSP_MultiElement2Mmx(x86_MM2, x86_MM3); + + MmxPmullwRegToReg(x86_MM0, x86_MM2); + MmxPmullwRegToReg(x86_MM1, x86_MM3); + } + } else { + + /*** + ** NOTE: for code clarity, this is the same as VMUDM, + ** just the mmx registers are swapped, this is easier + ****/ + + /**** Load source registers ****/ + sprintf(Reg, "RSP_Vect[%i].HW[0]", RspOp.rd); + MmxMoveQwordVariableToReg(x86_MM4, &RSP_Vect[RspOp.rd].HW[0], Reg); + sprintf(Reg, "RSP_Vect[%i].HW[4]", RspOp.rd); + MmxMoveQwordVariableToReg(x86_MM5, &RSP_Vect[RspOp.rd].HW[4], Reg); + + if ((RSPOpC.rs & 0xF) < 2) { + sprintf(Reg, "RSP_Vect[%i].UHW[0]", RSPOpC.rt); + MmxMoveQwordVariableToReg(x86_MM0, &RSP_Vect[RSPOpC.rt].UHW[0], Reg); + sprintf(Reg, "RSP_Vect[%i].UHW[4]", RSPOpC.rt); + MmxMoveQwordVariableToReg(x86_MM1, &RSP_Vect[RSPOpC.rt].UHW[4], Reg); + } else if ((RSPOpC.rs & 0xF) >= 8) { + RSP_Element2Mmx(x86_MM0); + MmxMoveRegToReg(x86_MM1, x86_MM0); + } else { + RSP_MultiElement2Mmx(x86_MM0, x86_MM1); + } + + /* Copy the signed portion */ + MmxMoveRegToReg(x86_MM2, x86_MM0); + MmxMoveRegToReg(x86_MM3, x86_MM1); + + /* high((u16)a * b) */ + MmxPmulhuwRegToReg(x86_MM0, x86_MM4); + MmxPmulhuwRegToReg(x86_MM1, x86_MM5); + + /* low((a >> 15) * b) */ + MmxPsrawImmed(x86_MM2, 15); + MmxPsrawImmed(x86_MM3, 15); + MmxPmullwRegToReg(x86_MM2, x86_MM4); + MmxPmullwRegToReg(x86_MM3, x86_MM5); + + /* Add them up */ + MmxPaddwRegToReg(x86_MM0, x86_MM2); + MmxPaddwRegToReg(x86_MM1, x86_MM3); + } +} + +void RSP_Sections_VMADN ( OPCODE RspOp, DWORD AccumStyle ) { + char Reg[256]; + + /***************************************** + ** VMADN + ** - affects the middle 32-bits, u16*s16 + ******************************************/ + + if (AccumStyle == High16BitAccum) { + return; + } + + RSPOpC = RspOp; + + /******* VMADN *******/ + if (AccumStyle != Middle16BitAccum) { + /**** Load source registers ****/ + sprintf(Reg, "RSP_Vect[%i].HW[0]", RspOp.rd); + MmxMoveQwordVariableToReg(x86_MM0 + 2, &RSP_Vect[RspOp.rd].HW[0], Reg); + sprintf(Reg, "RSP_Vect[%i].HW[4]", RspOp.rd); + MmxMoveQwordVariableToReg(x86_MM1 + 2, &RSP_Vect[RspOp.rd].HW[4], Reg); + + if ((RspOp.rs & 0x0f) < 2) { + sprintf(Reg, "RSP_Vect[%i].HW[0]", RspOp.rt); + MmxMoveQwordVariableToReg(x86_MM2 + 2, &RSP_Vect[RspOp.rt].HW[0], Reg); + sprintf(Reg, "RSP_Vect[%i].HW[4]", RspOp.rt); + MmxMoveQwordVariableToReg(x86_MM3 + 2, &RSP_Vect[RspOp.rt].HW[4], Reg); + + MmxPmullwRegToReg(x86_MM0 + 2, x86_MM2 + 2); + MmxPmullwRegToReg(x86_MM1 + 2, x86_MM3 + 2); + } else if ((RspOp.rs & 0x0f) >= 8) { + RSP_Element2Mmx(x86_MM2 + 2); + + MmxPmullwRegToReg(x86_MM0 + 2, x86_MM2 + 2); + MmxPmullwRegToReg(x86_MM1 + 2, x86_MM2 + 2); + } else { + RSP_MultiElement2Mmx(x86_MM2 + 2, x86_MM3 + 2); + + MmxPmullwRegToReg(x86_MM0 + 2, x86_MM2 + 2); + MmxPmullwRegToReg(x86_MM1 + 2, x86_MM3 + 2); + } + } else { + + /* + ** NOTE: for code clarity, this is the same as VMADM, + ** just the mmx registers are swapped, this is easier + */ + + /**** Load source registers ****/ + sprintf(Reg, "RSP_Vect[%i].HW[0]", RspOp.rd); + MmxMoveQwordVariableToReg(x86_MM4 + 2, &RSP_Vect[RspOp.rd].HW[0], Reg); + sprintf(Reg, "RSP_Vect[%i].HW[4]", RspOp.rd); + MmxMoveQwordVariableToReg(x86_MM5 + 2, &RSP_Vect[RspOp.rd].HW[4], Reg); + + if ((RSPOpC.rs & 0xF) < 2) { + sprintf(Reg, "RSP_Vect[%i].UHW[0]", RSPOpC.rt); + MmxMoveQwordVariableToReg(x86_MM0 + 2, &RSP_Vect[RSPOpC.rt].UHW[0], Reg); + sprintf(Reg, "RSP_Vect[%i].UHW[4]", RSPOpC.rt); + MmxMoveQwordVariableToReg(x86_MM1 + 2, &RSP_Vect[RSPOpC.rt].UHW[4], Reg); + } else if ((RSPOpC.rs & 0xF) >= 8) { + RSP_Element2Mmx(x86_MM0 + 2); + MmxMoveRegToReg(x86_MM1 + 2, x86_MM0 + 2); + } else { + RSP_MultiElement2Mmx(x86_MM0 + 2, x86_MM1 + 2); + } + + /* Copy the signed portion */ + MmxMoveRegToReg(x86_MM2 + 2, x86_MM0 + 2); + MmxMoveRegToReg(x86_MM3 + 2, x86_MM1 + 2); + + /* high((u16)a * b) */ + MmxPmulhuwRegToReg(x86_MM0 + 2, x86_MM4 + 2); + MmxPmulhuwRegToReg(x86_MM1 + 2, x86_MM5 + 2); + + /* low((a >> 15) * b) */ + MmxPsrawImmed(x86_MM2 + 2, 15); + MmxPsrawImmed(x86_MM3 + 2, 15); + MmxPmullwRegToReg(x86_MM2 + 2, x86_MM4 + 2); + MmxPmullwRegToReg(x86_MM3 + 2, x86_MM5 + 2); + + /* Add them up */ + MmxPaddwRegToReg(x86_MM0 + 2, x86_MM2 + 2); + MmxPaddwRegToReg(x86_MM1 + 2, x86_MM3 + 2); + } + + /* + ** only thing is when we are responsible for clamping + ** so we adopt unsigned here? + */ + MmxPaddswRegToReg(x86_MM0, x86_MM0 + 2); + MmxPaddswRegToReg(x86_MM1, x86_MM1 + 2); + +} + +void RSP_Sections_VMULF ( OPCODE RspOp, DWORD AccumStyle ) { + char Reg[256]; + + /***************************************** + ** VMULF + ** - affects the middle 32-bits, s16*s16*2 + ******************************************/ + + if (AccumStyle == High16BitAccum) { + MmxXorRegToReg(x86_MM0, x86_MM0); + MmxXorRegToReg(x86_MM1, x86_MM1); + return; + } + + RSPOpC = RspOp; + + /**** Load source registers ****/ + sprintf(Reg, "RSP_Vect[%i].HW[0]", RspOp.rd); + MmxMoveQwordVariableToReg(x86_MM0, &RSP_Vect[RspOp.rd].HW[0], Reg); + sprintf(Reg, "RSP_Vect[%i].HW[4]", RspOp.rd); + MmxMoveQwordVariableToReg(x86_MM1, &RSP_Vect[RspOp.rd].HW[4], Reg); + + /******* VMULF *******/ + if ((RspOp.rs & 0x0f) < 2) { + sprintf(Reg, "RSP_Vect[%i].HW[0]", RspOp.rt); + MmxMoveQwordVariableToReg(x86_MM2, &RSP_Vect[RspOp.rt].HW[0], Reg); + sprintf(Reg, "RSP_Vect[%i].HW[4]", RspOp.rt); + MmxMoveQwordVariableToReg(x86_MM3, &RSP_Vect[RspOp.rt].HW[4], Reg); + + if (AccumStyle != Middle16BitAccum) { + MmxPmullwRegToReg(x86_MM0, x86_MM2); + MmxPmullwRegToReg(x86_MM1, x86_MM3); + } else { + MmxPmulhwRegToReg(x86_MM0, x86_MM2); + MmxPmulhwRegToReg(x86_MM1, x86_MM3); + } + } else if ((RspOp.rs & 0x0f) >= 8) { + RSP_Element2Mmx(x86_MM2); + if (AccumStyle != Middle16BitAccum) { + MmxPmullwRegToReg(x86_MM0, x86_MM2); + MmxPmullwRegToReg(x86_MM1, x86_MM2); + } else { + MmxPmulhwRegToReg(x86_MM0, x86_MM2); + MmxPmulhwRegToReg(x86_MM1, x86_MM2); + } + } else { + RSP_MultiElement2Mmx(x86_MM2, x86_MM3); + if (AccumStyle != Middle16BitAccum) { + MmxPmullwRegToReg(x86_MM0, x86_MM2); + MmxPmullwRegToReg(x86_MM1, x86_MM3); + } else { + MmxPmulhwRegToReg(x86_MM0, x86_MM2); + MmxPmulhwRegToReg(x86_MM1, x86_MM3); + } + } + + MmxPsllwImmed(x86_MM0, 1); + MmxPsllwImmed(x86_MM1, 1); +} + +void RSP_Sections_VMACF ( OPCODE RspOp, DWORD AccumStyle ) { + char Reg[256]; + + /***************************************** + ** VMACF + ** - affects the upper 32-bits, s16*s16*2 + ******************************************/ + + if (AccumStyle == High16BitAccum) { + return; + } + + RSPOpC = RspOp; + + /**** Load source registers ****/ + sprintf(Reg, "RSP_Vect[%i].HW[0]", RspOp.rd); + MmxMoveQwordVariableToReg(x86_MM0 + 2, &RSP_Vect[RspOp.rd].HW[0], Reg); + sprintf(Reg, "RSP_Vect[%i].HW[4]", RspOp.rd); + MmxMoveQwordVariableToReg(x86_MM1 + 2, &RSP_Vect[RspOp.rd].HW[4], Reg); + + /******* VMACF *******/ + if ((RspOp.rs & 0x0f) < 2) { + sprintf(Reg, "RSP_Vect[%i].HW[0]", RspOp.rt); + MmxMoveQwordVariableToReg(x86_MM2 + 2, &RSP_Vect[RspOp.rt].HW[0], Reg); + sprintf(Reg, "RSP_Vect[%i].HW[4]", RspOp.rt); + MmxMoveQwordVariableToReg(x86_MM3 + 2, &RSP_Vect[RspOp.rt].HW[4], Reg); + + if (AccumStyle != Middle16BitAccum) { + MmxPmullwRegToReg(x86_MM0 + 2, x86_MM2 + 2); + MmxPmullwRegToReg(x86_MM1 + 2, x86_MM3 + 2); + } else { + MmxPmulhwRegToReg(x86_MM0 + 2, x86_MM2 + 2); + MmxPmulhwRegToReg(x86_MM1 + 2, x86_MM3 + 2); + } + } else if ((RspOp.rs & 0x0f) >= 8) { + RSP_Element2Mmx(x86_MM2 + 2); + if (AccumStyle != Middle16BitAccum) { + MmxPmullwRegToReg(x86_MM0 + 2, x86_MM2 + 2); + MmxPmullwRegToReg(x86_MM1 + 2, x86_MM2 + 2); + } else { + MmxPmulhwRegToReg(x86_MM0 + 2, x86_MM2 + 2); + MmxPmulhwRegToReg(x86_MM1 + 2, x86_MM2 + 2); + } + } else { + RSP_MultiElement2Mmx(x86_MM2 + 2, x86_MM3 + 2); + if (AccumStyle != Middle16BitAccum) { + MmxPmullwRegToReg(x86_MM0 + 2, x86_MM2 + 2); + MmxPmullwRegToReg(x86_MM1 + 2, x86_MM3 + 2); + } else { + MmxPmulhwRegToReg(x86_MM0 + 2, x86_MM2 + 2); + MmxPmulhwRegToReg(x86_MM1 + 2, x86_MM3 + 2); + } + } + + MmxPsllwImmed(x86_MM0 + 2, 1); + MmxPsllwImmed(x86_MM1 + 2, 1); + MmxPaddswRegToReg(x86_MM0, x86_MM0 + 2); + MmxPaddswRegToReg(x86_MM1, x86_MM1 + 2); +} + +/******************** Microcode Sections *********************/ + +static DWORD Section_000_VMADN; /* Yah i know, but leave it */ + +BOOL Check_Section_000(void) { + DWORD i; + OPCODE op0, op1; + + RSP_LW_IMEM(CompilePC + 0x00, &op0.Hex); + + /************************************ + ** Example: (mario audio microcode) + ** + ** 0x574 VMUDN $v30, $v3, $v23 + ** 0x578 VMADN $v30, $v4, $v23 + ** + *************************************/ + + if (!(op0.op == RSP_CP2 && (op0.rs & 0x10) != 0 && op0.funct == RSP_VECTOR_VMUDN)) { + return FALSE; + } + Section_000_VMADN = 0; + + for (i = 0; i < 0x20; i++) { + RSP_LW_IMEM(CompilePC + 0x04 + (i * 4), &op1.Hex); + + if (!(op1.op == RSP_CP2 && (op1.rs & 0x10) != 0 && op1.funct == RSP_VECTOR_VMADN)) { + break; + } else { + Section_000_VMADN++; + } + + if ((op1.rs & 0xF) >= 2 && (op1.rs & 0xF) <= 7 && IsMmx2Enabled == FALSE) { + return FALSE; + } + } + + /* We need at least 1 VMADN */ + if (Section_000_VMADN == 0) { + return FALSE; + } + + /* FIXME: check dest & flushes */ + if (TRUE == WriteToAccum(7, CompilePC + 0x4 + (Section_000_VMADN * 4) - 0x4)) { + return FALSE; + } + if (IsMmxEnabled == FALSE) { + return FALSE; + } + return TRUE; +} + +void Compile_Section_000(void) { + char Reg[256]; + OPCODE vmudn, vmadn; + DWORD i; + + RSP_LW_IMEM(CompilePC + 0x00, &vmudn.Hex); + + CPU_Message("Compiling: %X to ..., RSP Optimization $000", CompilePC); + CPU_Message(" %X %s",CompilePC+0x00,RSPOpcodeName(vmudn.Hex,CompilePC + 0x00)); + if (LogRDP){ + char str[40]; + sprintf(str,"%X",CompilePC); + PushImm32(str,CompilePC); + Call_Direct(RDP_LogLoc,"RDP_LogLoc"); + AddConstToX86Reg(x86_ESP, 4); + } + + for (i = 0; i < Section_000_VMADN; i++) { + RSP_LW_IMEM(CompilePC + 0x04 + (i * 4), &vmadn.Hex); + CPU_Message(" %X %s",CompilePC+0x04+(i*4),RSPOpcodeName(vmadn.Hex,CompilePC+0x04+(i*4))); + + if (LogRDP){ + char str[40]; + sprintf(str,"%X",CompilePC+0x04+(i*4)); + PushImm32(str,CompilePC+0x04+(i*4)); + Call_Direct(RDP_LogLoc,"RDP_LogLoc"); + AddConstToX86Reg(x86_ESP, 4); + } + + } + + RSP_Sections_VMUDN(vmudn, Low16BitAccum); + CompilePC += 4; + + for (i = 0; i < Section_000_VMADN; i++) { + RSP_LW_IMEM(CompilePC, &vmadn.Hex); + CompilePC += 4; + RSP_Sections_VMADN(vmadn, Low16BitAccum); + if (WriteToVectorDest(vmadn.sa, CompilePC - 4) == TRUE) { + sprintf(Reg, "RSP_Vect[%i].HW[0]", vmadn.sa); + MmxMoveQwordRegToVariable(x86_MM0, &RSP_Vect[vmadn.sa].HW[0], Reg); + sprintf(Reg, "RSP_Vect[%i].HW[4]", vmadn.sa); + MmxMoveQwordRegToVariable(x86_MM1, &RSP_Vect[vmadn.sa].HW[4], Reg); + } + } + + sprintf(Reg, "RSP_Vect[%i].HW[0]", vmadn.sa); + MmxMoveQwordRegToVariable(x86_MM0, &RSP_Vect[vmadn.sa].HW[0], Reg); + sprintf(Reg, "RSP_Vect[%i].HW[4]", vmadn.sa); + MmxMoveQwordRegToVariable(x86_MM1, &RSP_Vect[vmadn.sa].HW[4], Reg); + + MmxEmptyMultimediaState(); +} + +static DWORD Section_001_VMACF; + +BOOL Check_Section_001(void) { + DWORD i; + OPCODE op0, op1; + + RSP_LW_IMEM(CompilePC + 0x00, &op0.Hex); + + /************************************ + ** Example: (mario audio microcode) + ** + ** 0xCC0 VMULF $v28, $v28, $v10 [6] + ** 0xCC4 VMACF $v28, $v17, $v16 + *************************************/ + + if (!(op0.op == RSP_CP2 && (op0.rs & 0x10) != 0 && op0.funct == RSP_VECTOR_VMULF)) { + return FALSE; + } + Section_001_VMACF = 0; + + for (i = 0; i < 0x20; i++) { + RSP_LW_IMEM(CompilePC + 0x04 + (i * 4), &op1.Hex); + + if (!(op1.op == RSP_CP2 && (op1.rs & 0x10) != 0 && op1.funct == RSP_VECTOR_VMACF)) { + break; + } else { + Section_001_VMACF++; + } + + if ((op1.rs & 0xF) >= 2 && (op1.rs & 0xF) <= 7 && IsMmx2Enabled == FALSE) { + return FALSE; + } + } + + /* We need at least 1 VMACF */ + if (Section_001_VMACF == 0) { + return FALSE; + } + + if (IsMmxEnabled == FALSE) { + return FALSE; + } + + /* dests are checked elsewhere, this is fine */ + if (TRUE == WriteToAccum(7, CompilePC + 0x4 + (Section_001_VMACF * 4) - 0x4)) { + return FALSE; + } + + return TRUE; +} + +void Compile_Section_001(void) { + DWORD i; + char Reg[256]; + OPCODE vmulf, vmacf; + + RSP_LW_IMEM(CompilePC + 0x00, &vmulf.Hex); + + CPU_Message("Compiling: %X to ..., RSP Optimization $001", CompilePC); + CPU_Message(" %X %s",CompilePC+0x00,RSPOpcodeName(vmulf.Hex,CompilePC + 0x00)); + + for (i = 0; i < Section_001_VMACF; i++) { + RSP_LW_IMEM(CompilePC + 0x04 + (i * 4), &vmacf.Hex); + CPU_Message(" %X %s",CompilePC+0x04+(i*4),RSPOpcodeName(vmacf.Hex,CompilePC+0x04+(i*4))); + } + + RSP_Sections_VMULF(vmulf, Middle16BitAccum); + + if (WriteToVectorDest(vmulf.sa, CompilePC) == TRUE) { + sprintf(Reg, "RSP_Vect[%i].HW[0]", vmulf.sa); + MmxMoveQwordRegToVariable(x86_MM0, &RSP_Vect[vmulf.sa].HW[0], Reg); + sprintf(Reg, "RSP_Vect[%i].HW[4]", vmulf.sa); + MmxMoveQwordRegToVariable(x86_MM1, &RSP_Vect[vmulf.sa].HW[4], Reg); + } + CompilePC += 4; + + for (i = 0; i < Section_001_VMACF; i++) { + RSP_LW_IMEM(CompilePC, &vmacf.Hex); + CompilePC += 4; + + RSP_Sections_VMACF(vmacf, Middle16BitAccum); + if (WriteToVectorDest(vmacf.sa, CompilePC - 4) == TRUE) { + sprintf(Reg, "RSP_Vect[%i].HW[0]", vmacf.sa); + MmxMoveQwordRegToVariable(x86_MM0, &RSP_Vect[vmacf.sa].HW[0], Reg); + sprintf(Reg, "RSP_Vect[%i].HW[4]", vmacf.sa); + MmxMoveQwordRegToVariable(x86_MM1, &RSP_Vect[vmacf.sa].HW[4], Reg); + } + } + + MmxEmptyMultimediaState(); +} + +BOOL Check_Section_002 ( void ) { + DWORD Count; + OPCODE op[0x0C]; + + for (Count = 0; Count < 0x0C; Count++) { + RSP_LW_IMEM(CompilePC + (Count * 0x04), &op[Count].Hex); + } + + /************************************ + ** Example: (mario audio microcode) + ** + ** 5F4 VMUDH $v2, $v21, $v27 [6] + ** 5F8 VMADH $v2, $v20, $v27 [7] + ** 5FC VMADH $v2, $v19, $v30 [0] + ** 600 VMADH $v2, $v18, $v30 [1] + ** 604 VMADH $v2, $v17, $v30 [2] + ** 608 VMADH $v2, $v16, $v30 [3] + ** 60C VMADH $v28, $v15, $v30 [4] + ** 610 VMADH $v2, $v14, $v30 [5] + ** 614 VMADH $v2, $v13, $v30 [6] + ** 618 VMADH $v2, $v30, $v31 [5] + ** 61C VSAW $v26 [9], $v7, $v28 + ** 620 VSAW $v28 [8], $v7, $v28 + ************************************/ + + if (IsMmxEnabled == FALSE) { + return FALSE; + } + + if (!(op[0].op == RSP_CP2 && (op[0].rs & 0x10) != 0 && op[0].funct == RSP_VECTOR_VMUDH)) { + return FALSE; + } + if ((op[0].rs & 0xF) < 8) { + return FALSE; + } + + for (Count = 1; Count < 10; Count++) { + if (!(op[Count].op == RSP_CP2 && (op[Count].rs & 0x10) != 0 && op[Count].funct == RSP_VECTOR_VMADH)) { + return FALSE; + } + if ((op[Count].rs & 0xF) < 8) { + return FALSE; + } + } + + if (!(op[10].op == RSP_CP2 && (op[10].rs & 0x10) != 0 && op[10].funct == RSP_VECTOR_VSAW)) return FALSE; + if (!(op[11].op == RSP_CP2 && (op[11].rs & 0x10) != 0 && op[11].funct == RSP_VECTOR_VSAW)) return FALSE; + + if ((op[10].rs & 0xF) != 9) { return FALSE; } + if ((op[11].rs & 0xF) != 8) { return FALSE; } + + if (TRUE == WriteToAccum(7, CompilePC + 0x2C)) + return FALSE; + + return TRUE; +} + +void Compile_Section_002 ( void ) { + char Reg[256]; + + DWORD Count; + OPCODE op[0x0C]; + + OPCODE vmudh, vsaw; + + CPU_Message("Compiling: %X to ..., RSP Optimization $002", CompilePC); + for (Count = 0; Count < 0xC; Count++) { + RSP_LW_IMEM(CompilePC + (Count * 0x04), &op[Count].Hex); + CPU_Message(" %X %s",CompilePC+(Count*0x04),RSPOpcodeName(op[Count].Hex,CompilePC + (Count*0x04))); + if (LogRDP){ + char str[40]; + sprintf(str,"%X",CompilePC+(Count*0x04)); + PushImm32(str,CompilePC+(Count*0x04)); + Call_Direct(RDP_LogLoc,"RDP_LogLoc"); + AddConstToX86Reg(x86_ESP, 4); + } + } + + vmudh = op[0]; + RSP_Sections_VMUDH(vmudh, High16BitAccum); + + /******* VMADHs *******/ + for (Count = 1; Count < 10; Count++) { + RSP_Sections_VMADH(op[Count], High16BitAccum); + } + + /***** VSAWs *****/ + vsaw = op[10]; + MmxXorRegToReg(x86_MM4, x86_MM4); + sprintf(Reg, "RSP_Vect[%i].HW[0]", RSPOpC.sa); + MmxMoveQwordRegToVariable(x86_MM4, &RSP_Vect[vsaw.sa].HW[0], Reg); + sprintf(Reg, "RSP_Vect[%i].HW[4]", RSPOpC.sa); + MmxMoveQwordRegToVariable(x86_MM4, &RSP_Vect[vsaw.sa].HW[4], Reg); + + vsaw = op[11]; + sprintf(Reg, "RSP_Vect[%i].HW[0]", RSPOpC.sa); + MmxMoveQwordRegToVariable(x86_MM0, &RSP_Vect[vsaw.sa].HW[0], Reg); + sprintf(Reg, "RSP_Vect[%i].HW[4]", RSPOpC.sa); + MmxMoveQwordRegToVariable(x86_MM1, &RSP_Vect[vsaw.sa].HW[4], Reg); + + MmxEmptyMultimediaState(); + + CompilePC += 12 * sizeof(OPCODE); +} + +BOOL Check_Section_003 ( void ) { + DWORD Count; + OPCODE op[4]; + + for (Count = 0; Count < 4; Count++) { + RSP_LW_IMEM(CompilePC + (Count * 0x04), &op[Count].Hex); + } + + /************************************ + ** Example: (zelda audio microcode) + ** + ** VMUDM $v23, $v31, $v23 [7] + ** VMADH $v23, $v31, $v22 [7] + ** VMADM $v22, $v25, $v18 [4] + ** VMADN $v23, $v31, $v30 [0] + ************************************/ + + if (op[0].Hex == 0x4BF7FDC5 && op[1].Hex == 0x4BF6FDCF && op[2].Hex == 0x4B92CD8D && op[3].Hex == 0x4B1EFDCE) { + if (TRUE == WriteToAccum(7, CompilePC + 0xc)) + return FALSE; + + return TRUE; + } + return FALSE; +} + +static void resampler_hle() { + UDWORD accum, initial; + DWORD const2 = (DWORD)RSP_Vect[18].UHW[4 ^ 7]; + __int64 const3 = (__int64)((int)RSP_Vect[30].HW[0 ^ 7]) << 16; + int i; + + // VMUDM $v23, $v31, $v23 [7] + initial.DW = (__int64)((DWORD)RSP_Vect[23].UHW[7 ^ 7]) << 16; + // VMADH $v23, $v31, $v22 [7] + initial.W[1] += (int)RSP_Vect[22].HW[7 ^ 7]; + + for (i = 0; i < 8; i++) { + accum.DW = initial.DW; + + // VMADM $v22, $v25, $v18 [4] + accum.DW += (__int64)((int)RSP_Vect[25].HW[i] * const2) << 16; + if (accum.W[1] > 0x7FFF) { + RSP_Vect[22].HW[i] = 0x7FFF; + } else if (accum.W[1] < -0x8000) { + RSP_Vect[22].HW[i] = -0x8000; + } else { + RSP_Vect[22].HW[i] = accum.HW[2]; + } + + // VMADN $v23, $v31, $v30 [0] + accum.DW += const3; + if (accum.W[1] > 0x7FFF) { + RSP_Vect[23].HW[i] = 0xFFFF; + } else if (accum.W[1] < -0x8000) { + RSP_Vect[23].HW[i] = 0; + } else { + RSP_Vect[23].HW[i] = accum.HW[1]; + } + } +} + +void Compile_Section_003 ( void ) { + CPU_Message("Compiling: %X to ..., RSP Optimization $003", CompilePC); + Call_Direct(resampler_hle, "Resampler_HLE"); + CompilePC += 4 * sizeof(OPCODE); +} + +BOOL RSP_DoSections(void) { + if (TRUE == Check_Section_000()) { + Compile_Section_000(); + return TRUE; + } + if (TRUE == Check_Section_001()) { + Compile_Section_001(); + return TRUE; + } + if (TRUE == Check_Section_002()) { + Compile_Section_002(); + return TRUE; + } + if (TRUE == Check_Section_003()) { + Compile_Section_003(); + return TRUE; + } + return FALSE; +} \ No newline at end of file diff --git a/Source/RSP/Rsp.h b/Source/RSP/Rsp.h new file mode 100644 index 000000000..444fbf0b7 --- /dev/null +++ b/Source/RSP/Rsp.h @@ -0,0 +1,152 @@ +/* + * RSP Compiler plug in for Project 64 (A Nintendo 64 emulator). + * + * (c) Copyright 2001 jabo (jabo@emulation64.com) and + * zilmar (zilmar@emulation64.com) + * + * pj64 homepage: www.pj64.net + * + * Permission to use, copy, modify and distribute Project64 in both binary and + * source form, for non-commercial purposes, is hereby granted without fee, + * providing that this license information and copyright notice appear with + * all copies and any derived work. + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event shall the authors be held liable for any damages + * arising from the use of this software. + * + * Project64 is freeware for PERSONAL USE only. Commercial users should + * seek permission of the copyright holders first. Commercial use includes + * charging money for Project64 or software derived from Project64. + * + * The copyright holders request that bug fixes and improvements to the code + * should be forwarded to them so if they want them. + * + */ + +#if defined(__cplusplus) +extern "C" { +#endif + +/************ Profiling **************/ +#define Default_ProfilingOn FALSE +#define Default_IndvidualBlock FALSE +#define Default_ShowErrors FALSE +#define Default_AudioHle FALSE + +/* Note: BOOL, BYTE, WORD, DWORD, TRUE, FALSE are defined in windows.h */ + +#define PLUGIN_TYPE_RSP 1 +#define PLUGIN_TYPE_GFX 2 +#define PLUGIN_TYPE_AUDIO 3 +#define PLUGIN_TYPE_CONTROLLER 4 + +typedef struct { + WORD Version; /* Should be set to 0x0101 */ + WORD Type; /* Set to PLUGIN_TYPE_RSP */ + char Name[100]; /* Name of the DLL */ + + /* If DLL supports memory these memory options then set them to TRUE or FALSE + if it does not support it */ + BOOL NormalMemory; /* a normal BYTE array */ + BOOL MemoryBswaped; /* a normal BYTE array where the memory has been pre + bswap on a dword (32 bits) boundry */ +} PLUGIN_INFO; + +typedef struct { + HINSTANCE hInst; + BOOL MemoryBswaped; /* If this is set to TRUE, then the memory has been pre + bswap on a dword (32 bits) boundry */ + BYTE * RDRAM; + BYTE * DMEM; + BYTE * IMEM; + + DWORD * MI_INTR_REG; + + DWORD * SP_MEM_ADDR_REG; + DWORD * SP_DRAM_ADDR_REG; + DWORD * SP_RD_LEN_REG; + DWORD * SP_WR_LEN_REG; + DWORD * SP_STATUS_REG; + DWORD * SP_DMA_FULL_REG; + DWORD * SP_DMA_BUSY_REG; + DWORD * SP_PC_REG; + DWORD * SP_SEMAPHORE_REG; + + DWORD * DPC_START_REG; + DWORD * DPC_END_REG; + DWORD * DPC_CURRENT_REG; + DWORD * DPC_STATUS_REG; + DWORD * DPC_CLOCK_REG; + DWORD * DPC_BUFBUSY_REG; + DWORD * DPC_PIPEBUSY_REG; + DWORD * DPC_TMEM_REG; + + void (*CheckInterrupts)( void ); + void (*ProcessDList)( void ); + void (*ProcessAList)( void ); + void (*ProcessRdpList)( void ); + void (*ShowCFB)( void ); +} RSP_INFO; + +typedef struct { + /* Menu */ + /* Items should have an ID between 5001 and 5100 */ + HMENU hRSPMenu; + void (*ProcessMenuItem) ( int ID ); + + /* Break Points */ + BOOL UseBPoints; + char BPPanelName[20]; + void (*Add_BPoint) ( void ); + void (*CreateBPPanel) ( HWND hDlg, RECT rcBox ); + void (*HideBPPanel) ( void ); + void (*PaintBPPanel) ( PAINTSTRUCT ps ); + void (*ShowBPPanel) ( void ); + void (*RefreshBpoints) ( HWND hList ); + void (*RemoveBpoint) ( HWND hList, int index ); + void (*RemoveAllBpoint) ( void ); + + /* RSP command Window */ + void (*Enter_RSP_Commands_Window) ( void ); +} RSPDEBUG_INFO; + +typedef struct { + void (*UpdateBreakPoints)( void ); + void (*UpdateMemory)( void ); + void (*UpdateR4300iRegisters)( void ); + void (*Enter_BPoint_Window)( void ); + void (*Enter_R4300i_Commands_Window)( void ); + void (*Enter_R4300i_Register_Window)( void ); + void (*Enter_RSP_Commands_Window) ( void ); + void (*Enter_Memory_Window)( void ); +} DEBUG_INFO; + +__declspec(dllexport) void CloseDLL (void); +__declspec(dllexport) void DllAbout ( HWND hParent ); +__declspec(dllexport) DWORD DoRspCycles ( DWORD Cycles ); +__declspec(dllexport) void GetDllInfo ( PLUGIN_INFO * PluginInfo ); +__declspec(dllexport) void GetRspDebugInfo ( RSPDEBUG_INFO * DebugInfo ); +__declspec(dllexport) void InitiateRSP ( RSP_INFO Rsp_Info, DWORD * CycleCount); +__declspec(dllexport) void InitiateRSPDebugger ( DEBUG_INFO Debug_Info); +__declspec(dllexport) void RomClosed (void); +__declspec(dllexport) void DllConfig (HWND hWnd); +__declspec(dllexport) void EnableDebugging (BOOL Enabled); +__declspec(dllexport) void PluginLoaded (void); + +DWORD AsciiToHex (char * HexValue); +void DisplayError (char * Message, ...); +int GetStoredWinPos( char * WinName, DWORD * X, DWORD * Y ); + +#define InterpreterCPU 0 +#define RecompilerCPU 1 + +extern BOOL DebuggingEnabled, Profiling, IndvidualBlock, ShowErrors, BreakOnStart, LogRDP, LogX86Code; +extern DWORD CPUCore; +extern DEBUG_INFO DebugInfo; +extern RSP_INFO RSPInfo; +extern HINSTANCE hinstDLL; + +#if defined(__cplusplus) +} +#endif diff --git a/Source/RSP/Sse.c b/Source/RSP/Sse.c new file mode 100644 index 000000000..e7caff69b --- /dev/null +++ b/Source/RSP/Sse.c @@ -0,0 +1,341 @@ +/* + * RSP Compiler plug in for Project 64 (A Nintendo 64 emulator). + * + * (c) Copyright 2001 jabo (jabo@emulation64.com) and + * zilmar (zilmar@emulation64.com) + * + * pj64 homepage: www.pj64.net + * + * Permission to use, copy, modify and distribute Project64 in both binary and + * source form, for non-commercial purposes, is hereby granted without fee, + * providing that this license information and copyright notice appear with + * all copies and any derived work. + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event shall the authors be held liable for any damages + * arising from the use of this software. + * + * Project64 is freeware for PERSONAL USE only. Commercial users should + * seek permission of the copyright holders first. Commercial use includes + * charging money for Project64 or software derived from Project64. + * + * The copyright holders request that bug fixes and improvements to the code + * should be forwarded to them so if they want them. + * + */ + +#include +#include +#include "rsp.h" +#include "x86.h" +#include "memory.h" +#include "RSP registers.h" +#include "log.h" + +#define PUTDST8(dest,value) (*((BYTE *)(dest))=(BYTE)(value)); dest += 1; +#define PUTDST16(dest,value) (*((WORD *)(dest))=(WORD)(value)); dest += 2; +#define PUTDST32(dest,value) (*((DWORD *)(dest))=(DWORD)(value)); dest += 4; + +char * sse_Strings[8] = { + "xmm0", "xmm1", "xmm2", "xmm3", + "xmm4", "xmm5", "xmm6", "xmm7" +}; + +#define sse_Name(Reg) (sse_Strings[(Reg)]) + +void SseMoveAlignedVariableToReg(void *Variable, char *VariableName, int sseReg) { + BYTE x86Command; + + CPU_Message(" movaps %s, xmmword ptr [%s]",sse_Name(sseReg), VariableName); + + switch (sseReg) { + case x86_XMM0: x86Command = 0x05; break; + case x86_XMM1: x86Command = 0x0D; break; + case x86_XMM2: x86Command = 0x15; break; + case x86_XMM3: x86Command = 0x1D; break; + case x86_XMM4: x86Command = 0x25; break; + case x86_XMM5: x86Command = 0x2D; break; + case x86_XMM6: x86Command = 0x35; break; + case x86_XMM7: x86Command = 0x3D; break; + } + + PUTDST16(RecompPos,0x280f); + PUTDST8(RecompPos, x86Command); + PUTDST32(RecompPos,Variable); +} + +void SseMoveAlignedN64MemToReg(int sseReg, int AddrReg) { + BYTE x86Command; + + CPU_Message(" movaps %s, xmmword ptr [Dmem+%s]",sse_Name(sseReg), x86_Name(AddrReg)); + + switch (sseReg) { + case x86_XMM0: x86Command = 0x80; break; + case x86_XMM1: x86Command = 0x88; break; + case x86_XMM2: x86Command = 0x90; break; + case x86_XMM3: x86Command = 0x98; break; + case x86_XMM4: x86Command = 0xA0; break; + case x86_XMM5: x86Command = 0xA8; break; + case x86_XMM6: x86Command = 0xB0; break; + case x86_XMM7: x86Command = 0xB8; break; + } + switch (AddrReg) { + 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; + } + + PUTDST16(RecompPos,0x280f); + PUTDST8(RecompPos, x86Command); + PUTDST32(RecompPos,RSPInfo.DMEM); +} + +void SseMoveAlignedRegToVariable(int sseReg, void *Variable, char *VariableName) { + BYTE x86Command; + + CPU_Message(" movaps xmmword ptr [%s], %s",VariableName, sse_Name(sseReg)); + + switch (sseReg) { + case x86_XMM0: x86Command = 0x05; break; + case x86_XMM1: x86Command = 0x0D; break; + case x86_XMM2: x86Command = 0x15; break; + case x86_XMM3: x86Command = 0x1D; break; + case x86_XMM4: x86Command = 0x25; break; + case x86_XMM5: x86Command = 0x2D; break; + case x86_XMM6: x86Command = 0x35; break; + case x86_XMM7: x86Command = 0x3D; break; + } + + PUTDST16(RecompPos,0x290f); + PUTDST8(RecompPos, x86Command); + PUTDST32(RecompPos,Variable); +} + +void SseMoveAlignedRegToN64Mem(int sseReg, int AddrReg) { + BYTE x86Command; + + CPU_Message(" movaps xmmword ptr [Dmem+%s], %s",x86_Name(AddrReg),sse_Name(sseReg)); + + switch (sseReg) { + case x86_XMM0: x86Command = 0x80; break; + case x86_XMM1: x86Command = 0x88; break; + case x86_XMM2: x86Command = 0x90; break; + case x86_XMM3: x86Command = 0x98; break; + case x86_XMM4: x86Command = 0xA0; break; + case x86_XMM5: x86Command = 0xA8; break; + case x86_XMM6: x86Command = 0xB0; break; + case x86_XMM7: x86Command = 0xB8; break; + } + switch (AddrReg) { + 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; + } + + PUTDST16(RecompPos,0x290f); + PUTDST8(RecompPos, x86Command); + PUTDST32(RecompPos,RSPInfo.DMEM); +} + +void SseMoveUnalignedVariableToReg(void *Variable, char *VariableName, int sseReg) { + BYTE x86Command; + + CPU_Message(" movups %s, xmmword ptr [%s]",sse_Name(sseReg), VariableName); + + switch (sseReg) { + case x86_XMM0: x86Command = 0x05; break; + case x86_XMM1: x86Command = 0x0D; break; + case x86_XMM2: x86Command = 0x15; break; + case x86_XMM3: x86Command = 0x1D; break; + case x86_XMM4: x86Command = 0x25; break; + case x86_XMM5: x86Command = 0x2D; break; + case x86_XMM6: x86Command = 0x35; break; + case x86_XMM7: x86Command = 0x3D; break; + } + + PUTDST16(RecompPos,0x100f); + PUTDST8(RecompPos, x86Command); + PUTDST32(RecompPos,Variable); +} + +void SseMoveUnalignedN64MemToReg(int sseReg, int AddrReg) { + BYTE x86Command; + + CPU_Message(" movups %s, xmmword ptr [Dmem+%s]",sse_Name(sseReg), x86_Name(AddrReg)); + + switch (sseReg) { + case x86_XMM0: x86Command = 0x80; break; + case x86_XMM1: x86Command = 0x88; break; + case x86_XMM2: x86Command = 0x90; break; + case x86_XMM3: x86Command = 0x98; break; + case x86_XMM4: x86Command = 0xA0; break; + case x86_XMM5: x86Command = 0xA8; break; + case x86_XMM6: x86Command = 0xB0; break; + case x86_XMM7: x86Command = 0xB8; break; + } + switch (AddrReg) { + 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; + } + + PUTDST16(RecompPos,0x100f); + PUTDST8(RecompPos, x86Command); + PUTDST32(RecompPos,RSPInfo.DMEM); +} + +void SseMoveUnalignedRegToVariable(int sseReg, void *Variable, char *VariableName) { + BYTE x86Command; + + CPU_Message(" movups xmmword ptr [%s], %s",VariableName, sse_Name(sseReg)); + + switch (sseReg) { + case x86_XMM0: x86Command = 0x05; break; + case x86_XMM1: x86Command = 0x0D; break; + case x86_XMM2: x86Command = 0x15; break; + case x86_XMM3: x86Command = 0x1D; break; + case x86_XMM4: x86Command = 0x25; break; + case x86_XMM5: x86Command = 0x2D; break; + case x86_XMM6: x86Command = 0x35; break; + case x86_XMM7: x86Command = 0x3D; break; + } + + PUTDST16(RecompPos,0x110f); + PUTDST8(RecompPos, x86Command); + PUTDST32(RecompPos,Variable); +} + +void SseMoveUnalignedRegToN64Mem(int sseReg, int AddrReg) { + BYTE x86Command; + + CPU_Message(" movups xmmword ptr [Dmem+%s], %s",x86_Name(AddrReg),sse_Name(sseReg)); + + switch (sseReg) { + case x86_XMM0: x86Command = 0x80; break; + case x86_XMM1: x86Command = 0x88; break; + case x86_XMM2: x86Command = 0x90; break; + case x86_XMM3: x86Command = 0x98; break; + case x86_XMM4: x86Command = 0xA0; break; + case x86_XMM5: x86Command = 0xA8; break; + case x86_XMM6: x86Command = 0xB0; break; + case x86_XMM7: x86Command = 0xB8; break; + } + switch (AddrReg) { + 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; + } + + PUTDST16(RecompPos,0x110f); + PUTDST8(RecompPos, x86Command); + PUTDST32(RecompPos,RSPInfo.DMEM); +} + +void SseMoveRegToReg(int Dest, int Source) { + BYTE x86Command; + + CPU_Message(" movaps %s, %s", sse_Name(Dest), sse_Name(Source)); + + switch (Dest) { + case x86_XMM0: x86Command = 0x00; break; + case x86_XMM1: x86Command = 0x08; break; + case x86_XMM2: x86Command = 0x10; break; + case x86_XMM3: x86Command = 0x18; break; + case x86_XMM4: x86Command = 0x20; break; + case x86_XMM5: x86Command = 0x28; break; + case x86_XMM6: x86Command = 0x30; break; + case x86_XMM7: x86Command = 0x38; break; + } + switch (Source) { + case x86_XMM0: x86Command += 0x00; break; + case x86_XMM1: x86Command += 0x01; break; + case x86_XMM2: x86Command += 0x02; break; + case x86_XMM3: x86Command += 0x03; break; + case x86_XMM4: x86Command += 0x04; break; + case x86_XMM5: x86Command += 0x05; break; + case x86_XMM6: x86Command += 0x06; break; + case x86_XMM7: x86Command += 0x07; break; + } + + PUTDST16(RecompPos,0x280f); + PUTDST8(RecompPos, 0xC0 | x86Command); +} + +void SseXorRegToReg(int Dest, int Source) { + BYTE x86Command; + + CPU_Message(" xorps %s, %s", sse_Name(Dest), sse_Name(Source)); + + switch (Dest) { + case x86_XMM0: x86Command = 0x00; break; + case x86_XMM1: x86Command = 0x08; break; + case x86_XMM2: x86Command = 0x10; break; + case x86_XMM3: x86Command = 0x18; break; + case x86_XMM4: x86Command = 0x20; break; + case x86_XMM5: x86Command = 0x28; break; + case x86_XMM6: x86Command = 0x30; break; + case x86_XMM7: x86Command = 0x28; break; + } + switch (Source) { + case x86_XMM0: x86Command += 0x00; break; + case x86_XMM1: x86Command += 0x01; break; + case x86_XMM2: x86Command += 0x02; break; + case x86_XMM3: x86Command += 0x03; break; + case x86_XMM4: x86Command += 0x04; break; + case x86_XMM5: x86Command += 0x05; break; + case x86_XMM6: x86Command += 0x06; break; + case x86_XMM7: x86Command += 0x07; break; + } + PUTDST16(RecompPos,0x570f); + PUTDST8(RecompPos, 0xC0 | x86Command); +} + +void SseShuffleReg(int Dest, int Source, BYTE Immed) { + BYTE x86Command; + + CPU_Message(" shufps %s, %s, %02X", sse_Name(Dest), sse_Name(Source), Immed); + + switch (Dest) { + case x86_XMM0: x86Command = 0x00; break; + case x86_XMM1: x86Command = 0x08; break; + case x86_XMM2: x86Command = 0x10; break; + case x86_XMM3: x86Command = 0x18; break; + case x86_XMM4: x86Command = 0x20; break; + case x86_XMM5: x86Command = 0x28; break; + case x86_XMM6: x86Command = 0x30; break; + case x86_XMM7: x86Command = 0x38; break; + } + switch (Source) { + case x86_XMM0: x86Command += 0x00; break; + case x86_XMM1: x86Command += 0x01; break; + case x86_XMM2: x86Command += 0x02; break; + case x86_XMM3: x86Command += 0x03; break; + case x86_XMM4: x86Command += 0x04; break; + case x86_XMM5: x86Command += 0x05; break; + case x86_XMM6: x86Command += 0x06; break; + case x86_XMM7: x86Command += 0x07; break; + } + PUTDST16(RecompPos,0xC60f); + PUTDST8(RecompPos, 0xC0 | x86Command); + PUTDST8(RecompPos, Immed); +} diff --git a/Source/RSP/Types.h b/Source/RSP/Types.h new file mode 100644 index 000000000..a5db19dec --- /dev/null +++ b/Source/RSP/Types.h @@ -0,0 +1,66 @@ +/* + * RSP Compiler plug in for Project 64 (A Nintendo 64 emulator). + * + * (c) Copyright 2001 jabo (jabo@emulation64.com) and + * zilmar (zilmar@emulation64.com) + * + * pj64 homepage: www.pj64.net + * + * Permission to use, copy, modify and distribute Project64 in both binary and + * source form, for non-commercial purposes, is hereby granted without fee, + * providing that this license information and copyright notice appear with + * all copies and any derived work. + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event shall the authors be held liable for any damages + * arising from the use of this software. + * + * Project64 is freeware for PERSONAL USE only. Commercial users should + * seek permission of the copyright holders first. Commercial use includes + * charging money for Project64 or software derived from Project64. + * + * The copyright holders request that bug fixes and improvements to the code + * should be forwarded to them so if they want them. + * + */ + +#ifndef __Types_h +#define __Types_h + +typedef union tagUWORD { + long W; + float F; + unsigned long UW; + short HW[2]; + unsigned short UHW[2]; + char B[4]; + unsigned char UB[4]; +} UWORD32; + +typedef union tagUDWORD { + double D; + _int64 DW; + unsigned _int64 UDW; + long W[2]; + float F[2]; + unsigned long UW[2]; + short HW[4]; + unsigned short UHW[4]; + char B[8]; + unsigned char UB[8]; +} UDWORD; + +typedef union tagVect { + double FD[2]; + _int64 DW[2]; + unsigned _int64 UDW[2]; + long W[4]; + float FS[4]; + unsigned long UW[4]; + short HW[8]; + unsigned short UHW[8]; + char B[16]; + unsigned char UB[16]; +} VECTOR; + +#endif \ No newline at end of file diff --git a/Source/RSP/X86.c b/Source/RSP/X86.c new file mode 100644 index 000000000..a0fab3724 --- /dev/null +++ b/Source/RSP/X86.c @@ -0,0 +1,2812 @@ +/* + * RSP Compiler plug in for Project 64 (A Nintendo 64 emulator). + * + * (c) Copyright 2001 jabo (jabo@emulation64.com) and + * zilmar (zilmar@emulation64.com) + * + * pj64 homepage: www.pj64.net + * + * Permission to use, copy, modify and distribute Project64 in both binary and + * source form, for non-commercial purposes, is hereby granted without fee, + * providing that this license information and copyright notice appear with + * all copies and any derived work. + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event shall the authors be held liable for any damages + * arising from the use of this software. + * + * Project64 is freeware for PERSONAL USE only. Commercial users should + * seek permission of the copyright holders first. Commercial use includes + * charging money for Project64 or software derived from Project64. + * + * The copyright holders request that bug fixes and improvements to the code + * should be forwarded to them so if they want them. + * + */ + +#include +#include +#include "rsp.h" +#include "x86.h" +#include "memory.h" +#include "RSP registers.h" +#include "log.h" + +#define PUTDST8(dest,value) (*((BYTE *)(dest))=(BYTE)(value)); dest += 1; +#define PUTDST16(dest,value) (*((WORD *)(dest))=(WORD)(value)); dest += 2; +#define PUTDST32(dest,value) (*((DWORD *)(dest))=(DWORD)(value)); dest += 4; + +char * x86_Strings[8] = { + "eax", "ebx", "ecx", "edx", + "esi", "edi", "ebp", "esp" +}; + +char * x86_ByteStrings[8] = { + "al", "bl", "cl", "dl", + "?4", "?5", "?6", "?7" +}; + +char * x86_HalfStrings[8] = { + "ax", "bx", "cx", "dx", + "si", "di", "bp", "sp" +}; + +extern BOOL ConditionalMove; + +#define x86Byte_Name(Reg) (x86_ByteStrings[(Reg)]) +#define x86Half_Name(Reg) (x86_HalfStrings[(Reg)]) + +void AdcX86RegToX86Reg(int Destination, int Source) { + WORD x86Command; + + CPU_Message(" adc %s, %s",x86_Name(Destination),x86_Name(Source)); + switch (Source) { + case x86_EAX: x86Command = 0x0013; break; + case x86_EBX: x86Command = 0x0313; break; + case x86_ECX: x86Command = 0x0113; break; + case x86_EDX: x86Command = 0x0213; break; + case x86_ESI: x86Command = 0x0613; break; + case x86_EDI: x86Command = 0x0713; break; + case x86_ESP: x86Command = 0x0413; break; + case x86_EBP: x86Command = 0x0513; break; + } + switch (Destination) { + case x86_EAX: x86Command += 0xC000; break; + case x86_EBX: x86Command += 0xD800; break; + case x86_ECX: x86Command += 0xC800; break; + case x86_EDX: x86Command += 0xD000; break; + case x86_ESI: x86Command += 0xF000; break; + case x86_EDI: x86Command += 0xF800; break; + case x86_ESP: x86Command += 0xE000; break; + case x86_EBP: x86Command += 0xE800; break; + } + PUTDST16(RecompPos,x86Command); +} + +void AdcX86regToVariable(int x86reg, void * Variable, char * VariableName) { + CPU_Message(" adc dword ptr [%s], %s",VariableName, x86_Name(x86reg)); + switch (x86reg) { + case x86_EAX: PUTDST16(RecompPos,0x0511); break; + case x86_EBX: PUTDST16(RecompPos,0x1D11); break; + case x86_ECX: PUTDST16(RecompPos,0x0D11); break; + case x86_EDX: PUTDST16(RecompPos,0x1511); break; + case x86_ESI: PUTDST16(RecompPos,0x3511); break; + case x86_EDI: PUTDST16(RecompPos,0x3D11); break; + case x86_ESP: PUTDST16(RecompPos,0x2511); break; + case x86_EBP: PUTDST16(RecompPos,0x2D11); break; + default: + DisplayError("AddVariableToX86reg\nUnknown x86 Register"); + } + PUTDST32(RecompPos,Variable); +} + +void AdcX86regHalfToVariable(int x86reg, void * Variable, char * VariableName) { + CPU_Message(" adc word ptr [%s], %s",VariableName, x86Half_Name(x86reg)); + + PUTDST8(RecompPos, 0x66); + switch (x86reg) { + case x86_EAX: PUTDST16(RecompPos,0x0511); break; + case x86_EBX: PUTDST16(RecompPos,0x1D11); break; + case x86_ECX: PUTDST16(RecompPos,0x0D11); break; + case x86_EDX: PUTDST16(RecompPos,0x1511); break; + case x86_ESI: PUTDST16(RecompPos,0x3511); break; + case x86_EDI: PUTDST16(RecompPos,0x3D11); break; + case x86_ESP: PUTDST16(RecompPos,0x2511); break; + case x86_EBP: PUTDST16(RecompPos,0x2D11); break; + default: + DisplayError("AdcX86regHalfToVariable\nUnknown x86 Register"); + } + PUTDST32(RecompPos,Variable); +} + +void AdcConstToVariable(void *Variable, char *VariableName, BYTE Constant) { + CPU_Message(" adc dword ptr [%s], %Xh", VariableName, Constant); + PUTDST16(RecompPos,0x1583); + PUTDST32(RecompPos,Variable); + PUTDST8(RecompPos,Constant); +} + +void AdcConstToX86reg( BYTE Constant, int x86reg ) { + CPU_Message(" adc %s, %Xh",x86_Name(x86reg), Constant); + switch (x86reg) { + case x86_EAX: PUTDST16(RecompPos,0xD083); break; + case x86_EBX: PUTDST16(RecompPos,0xD383); break; + case x86_ECX: PUTDST16(RecompPos,0xD183); break; + case x86_EDX: PUTDST16(RecompPos,0xD283); break; + case x86_ESI: PUTDST16(RecompPos,0xD683); break; + case x86_EDI: PUTDST16(RecompPos,0xD783); break; + case x86_ESP: PUTDST16(RecompPos,0xD483); break; + case x86_EBP: PUTDST16(RecompPos,0xD583); break; + default: + DisplayError("AdcConstantToX86reg\nUnknown x86 Register"); + } + PUTDST8(RecompPos,Constant); +} + +void AddConstToVariable (DWORD Const, void *Variable, char *VariableName) { + CPU_Message(" add dword ptr [%s], 0x%X",VariableName, Const); + PUTDST16(RecompPos,0x0581); + PUTDST32(RecompPos,Variable); + PUTDST32(RecompPos,Const); +} + +void AddConstToX86Reg (int x86Reg, DWORD Const) { + CPU_Message(" add %s, %Xh",x86_Name(x86Reg),Const); + if ((Const & 0xFFFFFF80) != 0 && (Const & 0xFFFFFF80) != 0xFFFFFF80) { + switch (x86Reg) { + case x86_EAX: PUTDST16(RecompPos,0xC081); break; + case x86_EBX: PUTDST16(RecompPos,0xC381); break; + case x86_ECX: PUTDST16(RecompPos,0xC181); break; + case x86_EDX: PUTDST16(RecompPos,0xC281); break; + case x86_ESI: PUTDST16(RecompPos,0xC681); break; + case x86_EDI: PUTDST16(RecompPos,0xC781); break; + case x86_ESP: PUTDST16(RecompPos,0xC481); break; + case x86_EBP: PUTDST16(RecompPos,0xC581); break; + } + PUTDST32(RecompPos, Const); + } else { + switch (x86Reg) { + case x86_EAX: PUTDST16(RecompPos,0xC083); break; + case x86_EBX: PUTDST16(RecompPos,0xC383); break; + case x86_ECX: PUTDST16(RecompPos,0xC183); break; + case x86_EDX: PUTDST16(RecompPos,0xC283); break; + case x86_ESI: PUTDST16(RecompPos,0xC683); break; + case x86_EDI: PUTDST16(RecompPos,0xC783); break; + case x86_ESP: PUTDST16(RecompPos,0xC483); break; + case x86_EBP: PUTDST16(RecompPos,0xC583); break; + } + PUTDST8(RecompPos, Const); + } +} + +void AdcConstHalfToVariable(void *Variable, char *VariableName, BYTE Constant) { + CPU_Message(" adc word ptr [%s], %Xh", VariableName, Constant); + + PUTDST8(RecompPos,0x66); + PUTDST8(RecompPos,0x83); + PUTDST8(RecompPos,0x15); + + PUTDST32(RecompPos,Variable); + + PUTDST8(RecompPos,Constant); +} + +void AddVariableToX86reg(int x86reg, void * Variable, char * VariableName) { + CPU_Message(" add %s, dword ptr [%s]",x86_Name(x86reg),VariableName); + switch (x86reg) { + case x86_EAX: PUTDST16(RecompPos,0x0503); break; + case x86_EBX: PUTDST16(RecompPos,0x1D03); break; + case x86_ECX: PUTDST16(RecompPos,0x0D03); break; + case x86_EDX: PUTDST16(RecompPos,0x1503); break; + case x86_ESI: PUTDST16(RecompPos,0x3503); break; + case x86_EDI: PUTDST16(RecompPos,0x3D03); break; + case x86_ESP: PUTDST16(RecompPos,0x2503); break; + case x86_EBP: PUTDST16(RecompPos,0x2D03); break; + default: + DisplayError("AddVariableToX86reg\nUnknown x86 Register"); + } + PUTDST32(RecompPos,Variable); +} + +void AddX86regToVariable(int x86reg, void * Variable, char * VariableName) { + CPU_Message(" add dword ptr [%s], %s",VariableName, x86_Name(x86reg)); + switch (x86reg) { + case x86_EAX: PUTDST16(RecompPos,0x0501); break; + case x86_EBX: PUTDST16(RecompPos,0x1D01); break; + case x86_ECX: PUTDST16(RecompPos,0x0D01); break; + case x86_EDX: PUTDST16(RecompPos,0x1501); break; + case x86_ESI: PUTDST16(RecompPos,0x3501); break; + case x86_EDI: PUTDST16(RecompPos,0x3D01); break; + case x86_ESP: PUTDST16(RecompPos,0x2501); break; + case x86_EBP: PUTDST16(RecompPos,0x2D01); break; + default: + DisplayError("AddVariableToX86reg\nUnknown x86 Register"); + } + PUTDST32(RecompPos,Variable); +} + +void AddX86regHalfToVariable(int x86reg, void * Variable, char * VariableName) { + CPU_Message(" add word ptr [%s], %s",VariableName, x86Half_Name(x86reg)); + + PUTDST8(RecompPos,0x66); + + switch (x86reg) { + case x86_EAX: PUTDST16(RecompPos,0x0501); break; + case x86_EBX: PUTDST16(RecompPos,0x1D01); break; + case x86_ECX: PUTDST16(RecompPos,0x0D01); break; + case x86_EDX: PUTDST16(RecompPos,0x1501); break; + case x86_ESI: PUTDST16(RecompPos,0x3501); break; + case x86_EDI: PUTDST16(RecompPos,0x3D01); break; + case x86_ESP: PUTDST16(RecompPos,0x2501); break; + case x86_EBP: PUTDST16(RecompPos,0x2D01); break; + default: + DisplayError("AddVariableToX86reg\nUnknown x86 Register"); + } + PUTDST32(RecompPos,Variable); +} + +void AddX86RegToX86Reg(int Destination, int Source) { + WORD x86Command; + + CPU_Message(" add %s, %s",x86_Name(Destination),x86_Name(Source)); + switch (Source) { + case x86_EAX: x86Command = 0x0003; break; + case x86_EBX: x86Command = 0x0303; break; + case x86_ECX: x86Command = 0x0103; break; + case x86_EDX: x86Command = 0x0203; break; + case x86_ESI: x86Command = 0x0603; break; + case x86_EDI: x86Command = 0x0703; break; + case x86_ESP: x86Command = 0x0403; break; + case x86_EBP: x86Command = 0x0503; break; + } + switch (Destination) { + case x86_EAX: x86Command += 0xC000; break; + case x86_EBX: x86Command += 0xD800; break; + case x86_ECX: x86Command += 0xC800; break; + case x86_EDX: x86Command += 0xD000; break; + case x86_ESI: x86Command += 0xF000; break; + case x86_EDI: x86Command += 0xF800; break; + case x86_ESP: x86Command += 0xE000; break; + case x86_EBP: x86Command += 0xE800; break; + } + PUTDST16(RecompPos,x86Command); +} + +void AndConstToVariable (DWORD Const, void *Variable, char *VariableName) { + CPU_Message(" and dword ptr [%s], 0x%X",VariableName, Const); + PUTDST16(RecompPos,0x2581); + PUTDST32(RecompPos,Variable); + PUTDST32(RecompPos,Const); +} + +void AndConstToX86Reg(int x86Reg, DWORD Const) { + CPU_Message(" and %s, %Xh",x86_Name(x86Reg),Const); + if ((Const & 0xFFFFFF80) != 0 && (Const & 0xFFFFFF80) != 0xFFFFFF80) { + switch (x86Reg) { + case x86_EAX: PUTDST16(RecompPos,0xE081); break; + case x86_EBX: PUTDST16(RecompPos,0xE381); break; + case x86_ECX: PUTDST16(RecompPos,0xE181); break; + case x86_EDX: PUTDST16(RecompPos,0xE281); break; + case x86_ESI: PUTDST16(RecompPos,0xE681); break; + case x86_EDI: PUTDST16(RecompPos,0xE781); break; + case x86_ESP: PUTDST16(RecompPos,0xE481); break; + case x86_EBP: PUTDST16(RecompPos,0xE581); break; + } + PUTDST32(RecompPos, Const); + } else { + switch (x86Reg) { + case x86_EAX: PUTDST16(RecompPos,0xE083); break; + case x86_EBX: PUTDST16(RecompPos,0xE383); break; + case x86_ECX: PUTDST16(RecompPos,0xE183); break; + case x86_EDX: PUTDST16(RecompPos,0xE283); break; + case x86_ESI: PUTDST16(RecompPos,0xE683); break; + case x86_EDI: PUTDST16(RecompPos,0xE783); break; + case x86_ESP: PUTDST16(RecompPos,0xE483); break; + case x86_EBP: PUTDST16(RecompPos,0xE583); break; + } + PUTDST8(RecompPos, Const); + } +} + +void AndVariableToX86Reg(void * Variable, char * VariableName, int x86Reg) { + CPU_Message(" and %s, dword ptr [%s]",x86_Name(x86Reg),VariableName); + switch (x86Reg) { + case x86_EAX: PUTDST16(RecompPos,0x0523); break; + case x86_EBX: PUTDST16(RecompPos,0x1D23); break; + case x86_ECX: PUTDST16(RecompPos,0x0D23); break; + case x86_EDX: PUTDST16(RecompPos,0x1523); break; + case x86_ESI: PUTDST16(RecompPos,0x3523); break; + case x86_EDI: PUTDST16(RecompPos,0x3D23); break; + case x86_ESP: PUTDST16(RecompPos,0x2523); break; + case x86_EBP: PUTDST16(RecompPos,0x2D23); break; + } + PUTDST32(RecompPos,Variable); +} + +void AndVariableToX86regHalf(void * Variable, char * VariableName, int x86Reg) { + CPU_Message(" and %s, word ptr [%s]",x86Half_Name(x86Reg),VariableName); + PUTDST8(RecompPos, 0x66); + switch (x86Reg) { + case x86_EAX: PUTDST16(RecompPos,0x0523); break; + case x86_EBX: PUTDST16(RecompPos,0x1D23); break; + case x86_ECX: PUTDST16(RecompPos,0x0D23); break; + case x86_EDX: PUTDST16(RecompPos,0x1523); break; + case x86_ESI: PUTDST16(RecompPos,0x3523); break; + case x86_EDI: PUTDST16(RecompPos,0x3D23); break; + case x86_ESP: PUTDST16(RecompPos,0x2523); break; + case x86_EBP: PUTDST16(RecompPos,0x2D23); break; + } + PUTDST32(RecompPos,Variable); +} + +void AndX86RegToVariable(void * Variable, char * VariableName, int x86Reg) { + CPU_Message(" and dword ptr [%s], %s", VariableName, x86_Name(x86Reg)); + switch (x86Reg) { + case x86_EAX: PUTDST16(RecompPos,0x0521); break; + case x86_EBX: PUTDST16(RecompPos,0x1D21); break; + case x86_ECX: PUTDST16(RecompPos,0x0D21); break; + case x86_EDX: PUTDST16(RecompPos,0x1521); break; + case x86_ESI: PUTDST16(RecompPos,0x3521); break; + case x86_EDI: PUTDST16(RecompPos,0x3D21); break; + case x86_ESP: PUTDST16(RecompPos,0x2521); break; + case x86_EBP: PUTDST16(RecompPos,0x2D21); break; + } + PUTDST32(RecompPos,Variable); +} + +void AndX86RegToX86Reg(int Destination, int Source) { + WORD x86Command; + + CPU_Message(" and %s, %s",x86_Name(Destination),x86_Name(Source)); + switch (Destination) { + case x86_EAX: x86Command = 0x0021; break; + case x86_EBX: x86Command = 0x0321; break; + case x86_ECX: x86Command = 0x0121; break; + case x86_EDX: x86Command = 0x0221; break; + case x86_ESI: x86Command = 0x0621; break; + case x86_EDI: x86Command = 0x0721; break; + case x86_ESP: x86Command = 0x0421; break; + case x86_EBP: x86Command = 0x0521; break; + } + switch (Source) { + case x86_EAX: x86Command += 0xC000; break; + case x86_EBX: x86Command += 0xD800; break; + case x86_ECX: x86Command += 0xC800; break; + case x86_EDX: x86Command += 0xD000; break; + case x86_ESI: x86Command += 0xF000; break; + case x86_EDI: x86Command += 0xF800; break; + case x86_ESP: x86Command += 0xE000; break; + case x86_EBP: x86Command += 0xE800; break; + } + PUTDST16(RecompPos,x86Command); +} + +void AndX86RegHalfToX86RegHalf(int Destination, int Source) { + WORD x86Command; + + CPU_Message(" and %s, %s",x86Half_Name(Destination),x86Half_Name(Source)); + PUTDST8(RecompPos, 0x66); + + switch (Destination) { + case x86_EAX: x86Command = 0x0021; break; + case x86_EBX: x86Command = 0x0321; break; + case x86_ECX: x86Command = 0x0121; break; + case x86_EDX: x86Command = 0x0221; break; + case x86_ESI: x86Command = 0x0621; break; + case x86_EDI: x86Command = 0x0721; break; + case x86_ESP: x86Command = 0x0421; break; + case x86_EBP: x86Command = 0x0521; break; + } + switch (Source) { + case x86_EAX: x86Command += 0xC000; break; + case x86_EBX: x86Command += 0xD800; break; + case x86_ECX: x86Command += 0xC800; break; + case x86_EDX: x86Command += 0xD000; break; + case x86_ESI: x86Command += 0xF000; break; + case x86_EDI: x86Command += 0xF800; break; + case x86_ESP: x86Command += 0xE000; break; + case x86_EBP: x86Command += 0xE800; break; + } + PUTDST16(RecompPos,x86Command); +} + +void BreakPointNotification (const char * const FileName, const int LineNumber) { + DisplayError("Break Point found\nFile: %s\nLine: %d",FileName,LineNumber); +} + +void X86BreakPoint (LPCSTR FileName, int LineNumber) { + Pushad(); + PushImm32("LineNumber",LineNumber); + PushImm32("FileName",(DWORD)FileName); + Call_Direct(BreakPointNotification,"BreakPointNotification"); + AddConstToX86Reg(x86_ESP, 8); + Popad(); + CPU_Message(" int 3"); + PUTDST8(RecompPos,0xCC); +} + +void Call_Direct(void * FunctAddress, char * FunctName) { + CPU_Message(" call offset %s",FunctName); + PUTDST8(RecompPos,0xE8); + PUTDST32(RecompPos,(DWORD)FunctAddress-(DWORD)RecompPos - 4); +} + +void Call_Indirect(void * FunctAddress, char * FunctName) { + CPU_Message(" call [%s]",FunctName); + PUTDST16(RecompPos,0x15FF); + PUTDST32(RecompPos,FunctAddress); +} + +void CondMoveEqual(int Destination, int Source) { + if (ConditionalMove == FALSE) { + BYTE * Jump; + CPU_Message(" [*]cmove %s, %s",x86_Name(Destination),x86_Name(Source)); + + JneLabel8("label", 0); + Jump = RecompPos - 1; + MoveX86RegToX86Reg(Source, Destination); + CPU_Message(" label:"); + x86_SetBranch8b(Jump, RecompPos); + } else { + BYTE x86Command; + CPU_Message(" cmove %s, %s",x86_Name(Destination),x86_Name(Source)); + + PUTDST16(RecompPos,0x440F); + + 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 CondMoveNotEqual(int Destination, int Source) { + if (ConditionalMove == FALSE) { + BYTE * Jump; + CPU_Message(" [*]cmovne %s, %s",x86_Name(Destination),x86_Name(Source)); + + JeLabel8("label", 0); + Jump = RecompPos - 1; + MoveX86RegToX86Reg(Source, Destination); + CPU_Message(" label:"); + x86_SetBranch8b(Jump, RecompPos); + } else { + BYTE x86Command; + CPU_Message(" cmovne %s, %s",x86_Name(Destination),x86_Name(Source)); + + PUTDST16(RecompPos,0x450F); + + 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 CondMoveGreater(int Destination, int Source) { + if (ConditionalMove == FALSE) { + BYTE * Jump; + CPU_Message(" [*]cmovg %s, %s",x86_Name(Destination),x86_Name(Source)); + + JleLabel8("label", 0); + Jump = RecompPos - 1; + MoveX86RegToX86Reg(Source, Destination); + CPU_Message(" label:"); + x86_SetBranch8b(Jump, RecompPos); + } else { + BYTE x86Command; + CPU_Message(" cmovg %s, %s",x86_Name(Destination),x86_Name(Source)); + + PUTDST16(RecompPos,0x4F0F); + + 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 CondMoveGreaterEqual(int Destination, int Source) { + if (ConditionalMove == FALSE) { + BYTE * Jump; + CPU_Message(" [*]cmovge %s, %s",x86_Name(Destination),x86_Name(Source)); + + JlLabel8("label", 0); + Jump = RecompPos - 1; + MoveX86RegToX86Reg(Source, Destination); + CPU_Message(" label:"); + x86_SetBranch8b(Jump, RecompPos); + } else { + BYTE x86Command; + CPU_Message(" cmovge %s, %s",x86_Name(Destination),x86_Name(Source)); + + PUTDST16(RecompPos,0x4D0F); + + 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 CondMoveLess(int Destination, int Source) { + if (ConditionalMove == FALSE) { + BYTE * Jump; + CPU_Message(" [*]cmovl %s, %s",x86_Name(Destination),x86_Name(Source)); + + JgeLabel8("label", 0); + Jump = RecompPos - 1; + MoveX86RegToX86Reg(Source, Destination); + CPU_Message(" label:"); + x86_SetBranch8b(Jump, RecompPos); + } else { + BYTE x86Command; + CPU_Message(" cmovl %s, %s",x86_Name(Destination),x86_Name(Source)); + + PUTDST16(RecompPos,0x4C0F); + + 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 CondMoveLessEqual(int Destination, int Source) { + if (ConditionalMove == FALSE) { + BYTE * Jump; + CPU_Message(" [*]cmovle %s, %s",x86_Name(Destination),x86_Name(Source)); + + JgLabel8("label", 0); + Jump = RecompPos - 1; + MoveX86RegToX86Reg(Source, Destination); + CPU_Message(" label:"); + x86_SetBranch8b(Jump, RecompPos); + } else { + BYTE x86Command; + CPU_Message(" cmovle %s, %s",x86_Name(Destination),x86_Name(Source)); + + PUTDST16(RecompPos,0x4E0F); + + 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 CompConstToVariable(DWORD Const, void * Variable, char * VariableName) { + CPU_Message(" cmp dword ptr [%s], 0x%X",VariableName, Const); + PUTDST16(RecompPos,0x3D81); + PUTDST32(RecompPos,Variable); + PUTDST32(RecompPos,Const); +} + +void CompConstHalfToVariable(WORD Const, void * Variable, char * VariableName) { + CPU_Message(" cmp word ptr [%s], 0x%X",VariableName, Const); + PUTDST8(RecompPos,0x66); + PUTDST8(RecompPos,0x81); + PUTDST8(RecompPos,0x3D); + + PUTDST32(RecompPos,Variable); + PUTDST16(RecompPos,Const); +} + +void CompConstToX86reg(int x86Reg, DWORD Const) { + CPU_Message(" cmp %s, %Xh",x86_Name(x86Reg),Const); + if ((Const & 0xFFFFFF80) != 0 && (Const & 0xFFFFFF80) != 0xFFFFFF80) { + switch (x86Reg) { + case x86_EAX: PUTDST16(RecompPos,0xF881); break; + case x86_EBX: PUTDST16(RecompPos,0xFB81); break; + case x86_ECX: PUTDST16(RecompPos,0xF981); break; + case x86_EDX: PUTDST16(RecompPos,0xFA81); break; + case x86_ESI: PUTDST16(RecompPos,0xFE81); break; + case x86_EDI: PUTDST16(RecompPos,0xFF81); break; + case x86_ESP: PUTDST16(RecompPos,0xFC81); break; + case x86_EBP: PUTDST16(RecompPos,0xFD81); break; + default: + DisplayError("CompConstToX86reg\nUnknown x86 Register"); + } + PUTDST32(RecompPos,Const); + } else { + switch (x86Reg) { + case x86_EAX: PUTDST16(RecompPos,0xF883); break; + case x86_EBX: PUTDST16(RecompPos,0xFB83); break; + case x86_ECX: PUTDST16(RecompPos,0xF983); break; + case x86_EDX: PUTDST16(RecompPos,0xFA83); break; + case x86_ESI: PUTDST16(RecompPos,0xFE83); break; + case x86_EDI: PUTDST16(RecompPos,0xFF83); break; + case x86_ESP: PUTDST16(RecompPos,0xFC83); break; + case x86_EBP: PUTDST16(RecompPos,0xFD83); break; + } + PUTDST8(RecompPos, Const); + } +} + +void CompX86regToVariable(int x86Reg, void * Variable, char * VariableName) { + CPU_Message(" cmp %s, dword ptr [%s]",x86_Name(x86Reg),VariableName); + switch (x86Reg) { + case x86_EAX: PUTDST16(RecompPos,0x053B); break; + case x86_EBX: PUTDST16(RecompPos,0x1D3B); break; + case x86_ECX: PUTDST16(RecompPos,0x0D3B); break; + case x86_EDX: PUTDST16(RecompPos,0x153B); break; + case x86_ESI: PUTDST16(RecompPos,0x353B); break; + case x86_EDI: PUTDST16(RecompPos,0x3D3B); break; + case x86_ESP: PUTDST16(RecompPos,0x253B); break; + case x86_EBP: PUTDST16(RecompPos,0x2D3B); break; + default: + DisplayError("Unknown x86 Register"); + } + PUTDST32(RecompPos,Variable); +} + +void CompVariableToX86reg(int x86Reg, void * Variable, char * VariableName) { + CPU_Message(" cmp dword ptr [%s], %s",VariableName, x86_Name(x86Reg)); + switch (x86Reg) { + case x86_EAX: PUTDST16(RecompPos,0x0539); break; + case x86_EBX: PUTDST16(RecompPos,0x1D39); break; + case x86_ECX: PUTDST16(RecompPos,0x0D39); break; + case x86_EDX: PUTDST16(RecompPos,0x1539); break; + case x86_ESI: PUTDST16(RecompPos,0x3539); break; + case x86_EDI: PUTDST16(RecompPos,0x3D39); break; + case x86_ESP: PUTDST16(RecompPos,0x2539); break; + case x86_EBP: PUTDST16(RecompPos,0x2D39); break; + default: + DisplayError("Unknown x86 Register"); + } + PUTDST32(RecompPos,Variable); +} + +void CompX86RegToX86Reg(int Destination, int Source) { + WORD x86Command; + + CPU_Message(" cmp %s, %s",x86_Name(Destination),x86_Name(Source)); + + switch (Source) { + case x86_EAX: x86Command = 0x003B; break; + case x86_EBX: x86Command = 0x033B; break; + case x86_ECX: x86Command = 0x013B; break; + case x86_EDX: x86Command = 0x023B; break; + case x86_ESI: x86Command = 0x063B; break; + case x86_EDI: x86Command = 0x073B; break; + case x86_ESP: x86Command = 0x043B; break; + case x86_EBP: x86Command = 0x053B; break; + } + switch (Destination) { + case x86_EAX: x86Command += 0xC000; break; + case x86_EBX: x86Command += 0xD800; break; + case x86_ECX: x86Command += 0xC800; break; + case x86_EDX: x86Command += 0xD000; break; + case x86_ESI: x86Command += 0xF000; break; + case x86_EDI: x86Command += 0xF800; break; + case x86_ESP: x86Command += 0xE000; break; + case x86_EBP: x86Command += 0xE800; break; + } + PUTDST16(RecompPos,x86Command); +} + +void Cwd(void) { + CPU_Message(" cwd"); + PUTDST16(RecompPos, 0x9966); +} + +void Cwde(void) { + CPU_Message(" cwde"); + PUTDST8(RecompPos, 0x98); +} + +void DecX86reg(x86Reg) { + CPU_Message(" dec %s",x86_Name(x86Reg)); + switch (x86Reg) { + case x86_EAX: PUTDST16(RecompPos,0xC8FF); break; + case x86_EBX: PUTDST16(RecompPos,0xCBFF); break; + case x86_ECX: PUTDST16(RecompPos,0xC9FF); break; + case x86_EDX: PUTDST16(RecompPos,0xCAFF); break; + case x86_ESI: PUTDST16(RecompPos,0xCEFF); break; + case x86_EDI: PUTDST16(RecompPos,0xCFFF); break; + case x86_ESP: PUTDST8 (RecompPos,0x4C); break; + case x86_EBP: PUTDST8 (RecompPos,0x4D); break; + default: + DisplayError("DecX86reg\nUnknown x86 Register"); + } +} + +void DivX86reg(int x86reg) { + CPU_Message(" div %s",x86_Name(x86reg)); + switch (x86reg) { + case x86_EBX: PUTDST16(RecompPos,0xf3F7); break; + case x86_ECX: PUTDST16(RecompPos,0xf1F7); break; + case x86_EDX: PUTDST16(RecompPos,0xf2F7); break; + case x86_ESI: PUTDST16(RecompPos,0xf6F7); break; + case x86_EDI: PUTDST16(RecompPos,0xf7F7); break; + case x86_ESP: PUTDST16(RecompPos,0xf4F7); break; + case x86_EBP: PUTDST16(RecompPos,0xf5F7); break; + default: + DisplayError("divX86reg\nUnknown x86 Register"); + } +} + +void idivX86reg(int x86reg) { + CPU_Message(" idiv %s",x86_Name(x86reg)); + switch (x86reg) { + case x86_EBX: PUTDST16(RecompPos,0xfbF7); break; + case x86_ECX: PUTDST16(RecompPos,0xf9F7); break; + case x86_EDX: PUTDST16(RecompPos,0xfaF7); break; + case x86_ESI: PUTDST16(RecompPos,0xfeF7); break; + case x86_EDI: PUTDST16(RecompPos,0xffF7); break; + case x86_ESP: PUTDST16(RecompPos,0xfcF7); break; + case x86_EBP: PUTDST16(RecompPos,0xfdF7); break; + default: + DisplayError("idivX86reg\nUnknown x86 Register"); + } +} + +void imulX86reg(int x86reg) { + CPU_Message(" imul %s",x86_Name(x86reg)); + switch (x86reg) { + case x86_EAX: PUTDST16(RecompPos,0xE8F7); break; + case x86_EBX: PUTDST16(RecompPos,0xEBF7); break; + case x86_ECX: PUTDST16(RecompPos,0xE9F7); break; + case x86_EDX: PUTDST16(RecompPos,0xEAF7); break; + case x86_ESI: PUTDST16(RecompPos,0xEEF7); break; + case x86_EDI: PUTDST16(RecompPos,0xEFF7); break; + case x86_ESP: PUTDST16(RecompPos,0xECF7); break; + case x86_EBP: PUTDST16(RecompPos,0xEDF7); break; + default: + DisplayError("imulX86reg\nUnknown x86 Register"); + } +} + +void ImulX86RegToX86Reg(int Destination, int Source) { + BYTE x86Command; + + CPU_Message(" imul %s, %s",x86_Name(Destination), x86_Name(Source)); + + 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; + } + + PUTDST16(RecompPos, 0xAF0F); + PUTDST8(RecompPos, x86Command); +} + +void IncX86reg(int x86Reg) { + CPU_Message(" inc %s",x86_Name(x86Reg)); + switch (x86Reg) { + case x86_EAX: PUTDST16(RecompPos,0xC0FF); break; + case x86_EBX: PUTDST16(RecompPos,0xC3FF); break; + case x86_ECX: PUTDST16(RecompPos,0xC1FF); break; + case x86_EDX: PUTDST16(RecompPos,0xC2FF); break; + case x86_ESI: PUTDST16(RecompPos,0xC6FF); break; + case x86_EDI: PUTDST16(RecompPos,0xC7FF); break; + case x86_ESP: PUTDST8 (RecompPos,0x44); break; + case x86_EBP: PUTDST8 (RecompPos,0x45); break; + default: + DisplayError("IncX86reg\nUnknown x86 Register"); + } +} + +void JaeLabel32(char * Label,DWORD Value) { + CPU_Message(" jae $%s",Label); + PUTDST16(RecompPos,0x830F); + PUTDST32(RecompPos,Value); +} + +void JaLabel8(char * Label, BYTE Value) { + CPU_Message(" ja $%s",Label); + PUTDST8(RecompPos,0x77); + PUTDST8(RecompPos,Value); +} + +void JaLabel32(char * Label,DWORD Value) { + CPU_Message(" ja $%s",Label); + PUTDST16(RecompPos,0x870F); + PUTDST32(RecompPos,Value); +} + +void JbLabel8(char * Label, BYTE Value) { + CPU_Message(" jb $%s",Label); + PUTDST8(RecompPos,0x72); + PUTDST8(RecompPos,Value); +} + +void JbLabel32(char * Label,DWORD Value) { + CPU_Message(" jb $%s",Label); + PUTDST16(RecompPos,0x820F); + PUTDST32(RecompPos,Value); +} + +void JeLabel8(char * Label, BYTE Value) { + CPU_Message(" je $%s",Label); + PUTDST8(RecompPos,0x74); + PUTDST8(RecompPos,Value); +} + +void JeLabel32(char * Label,DWORD Value) { + CPU_Message(" je $%s",Label); + PUTDST16(RecompPos,0x840F); + PUTDST32(RecompPos,Value); +} + +void JgeLabel8(char * Label, BYTE Value) { + CPU_Message(" jge $%s",Label); + PUTDST8(RecompPos,0x7D); + PUTDST8(RecompPos,Value); +} + +void JgeLabel32(char * Label,DWORD Value) { + CPU_Message(" jge $%s",Label); + PUTDST16(RecompPos,0x8D0F); + PUTDST32(RecompPos,Value); +} + +void JgLabel8(char * Label, BYTE Value) { + CPU_Message(" jg $%s",Label); + PUTDST8(RecompPos,0x7F); + PUTDST8(RecompPos,Value); +} + +void JgLabel32(char * Label,DWORD Value) { + CPU_Message(" jg $%s",Label); + PUTDST16(RecompPos,0x8F0F); + PUTDST32(RecompPos,Value); +} + +void JleLabel8(char * Label, BYTE Value) { + CPU_Message(" jle $%s",Label); + PUTDST8(RecompPos,0x7E); + PUTDST8(RecompPos,Value); +} + +void JleLabel32(char * Label,DWORD Value) { + CPU_Message(" jle $%s",Label); + PUTDST16(RecompPos,0x8E0F); + PUTDST32(RecompPos,Value); +} + +void JlLabel8(char * Label, BYTE Value) { + CPU_Message(" jl $%s",Label); + PUTDST8(RecompPos,0x7C); + PUTDST8(RecompPos,Value); +} + +void JlLabel32(char * Label,DWORD Value) { + CPU_Message(" jl $%s",Label); + PUTDST16(RecompPos,0x8C0F); + PUTDST32(RecompPos,Value); +} + +void JumpX86Reg( int x86reg ) { + CPU_Message(" jmp %s",x86_Name(x86reg)); + + switch (x86reg) { + case x86_EAX: PUTDST16(RecompPos,0xe0ff); break; + case x86_EBX: PUTDST16(RecompPos,0xe3ff); break; + case x86_ECX: PUTDST16(RecompPos,0xe1ff); break; + case x86_EDX: PUTDST16(RecompPos,0xe2ff); break; + case x86_ESI: PUTDST16(RecompPos,0xe6ff); break; + case x86_EDI: PUTDST16(RecompPos,0xe7ff); break; + default: DisplayError("JumpX86Reg: Unknown reg"); + } +} + +void JmpLabel8(char * Label, BYTE Value) { + CPU_Message(" jmp $%s",Label); + PUTDST8(RecompPos,0xEB); + PUTDST8(RecompPos,Value); +} + +void JmpLabel32(char * Label, DWORD Value) { + CPU_Message(" jmp $%s",Label); + PUTDST8(RecompPos,0xE9); + PUTDST32(RecompPos,Value); +} + +void JneLabel8(char * Label, BYTE Value) { + CPU_Message(" jne $%s",Label); + PUTDST8(RecompPos,0x75); + PUTDST8(RecompPos,Value); +} + +void JneLabel32(char *Label, DWORD Value) { + CPU_Message(" jne $%s",Label); + PUTDST16(RecompPos,0x850F); + PUTDST32(RecompPos,Value); +} + +void JnsLabel8(char * Label, BYTE Value) { + CPU_Message(" jns $%s",Label); + PUTDST8(RecompPos,0x79); + PUTDST8(RecompPos,Value); +} + +void JnsLabel32(char *Label, DWORD Value) { + CPU_Message(" jns $%s",Label); + PUTDST16(RecompPos,0x890F); + PUTDST32(RecompPos,Value); +} + +void JsLabel32(char *Label, DWORD Value) { + CPU_Message(" js $%s",Label); + PUTDST16(RecompPos,0x880F); + PUTDST32(RecompPos,Value); +} + +/* +** NOTE: this op can get really complex with muls +** if we need this rewrite it into 1 function +**/ + +void LeaSourceAndOffset(int x86DestReg, int x86SourceReg, int offset) { + WORD x86Command; + + CPU_Message(" lea %s, [%s + %0Xh]",x86_Name(x86DestReg),x86_Name(x86SourceReg),offset); + switch (x86DestReg) { + case x86_EAX: x86Command = 0x808D; break; + case x86_EBX: x86Command = 0x988D; break; + case x86_ECX: x86Command = 0x888D; break; + case x86_EDX: x86Command = 0x908D; break; + case x86_ESI: x86Command = 0xB08D; break; + case x86_EDI: x86Command = 0xB88D; break; + case x86_ESP: x86Command = 0xA08D; break; + case x86_EBP: x86Command = 0xA88D; break; + default: + DisplayError("LeaSourceAndOffset\nUnknown x86 Register"); + } + switch (x86SourceReg) { + case x86_EAX: x86Command += 0x0000; break; + case x86_EBX: x86Command += 0x0300; break; + case x86_ECX: x86Command += 0x0100; break; + case x86_EDX: x86Command += 0x0200; break; + case x86_ESI: x86Command += 0x0600; break; + case x86_EDI: x86Command += 0x0700; break; + case x86_ESP: x86Command += 0x0400; break; + case x86_EBP: x86Command += 0x0500; break; + default: + DisplayError("LeaSourceAndOffset\nUnknown x86 Register"); + } + + if ((offset & 0xFFFFFF80) != 0 && (offset & 0xFFFFFF80) != 0xFFFFFF80) { + PUTDST16(RecompPos,x86Command); + PUTDST32(RecompPos,offset); + } else { + PUTDST16(RecompPos,(x86Command & 0x7FFF) | 0x4000); + PUTDST8(RecompPos,offset); + } +} + +void MoveConstByteToVariable (BYTE Const,void *Variable, char *VariableName) { + CPU_Message(" mov byte ptr [%s], %Xh",VariableName,Const); + PUTDST16(RecompPos,0x05C6); + PUTDST32(RecompPos,Variable); + PUTDST8(RecompPos,Const); +} + +void MoveConstHalfToVariable (WORD Const,void *Variable, char *VariableName) { + CPU_Message(" mov word ptr [%s], %Xh",VariableName,Const); + PUTDST8(RecompPos,0x66); + PUTDST16(RecompPos,0x05C7); + PUTDST32(RecompPos,Variable); + PUTDST16(RecompPos,Const); +} + +void MoveConstToVariable (DWORD Const,void *Variable, char *VariableName) { + CPU_Message(" mov dword ptr [%s], %Xh",VariableName,Const); + PUTDST16(RecompPos,0x05C7); + PUTDST32(RecompPos,Variable); + PUTDST32(RecompPos,Const); +} + +void MoveConstToX86reg(DWORD Const, int x86reg) { + CPU_Message(" mov %s, %Xh",x86_Name(x86reg),Const); + switch (x86reg) { + case x86_EAX: PUTDST16(RecompPos,0xC0C7); break; + case x86_EBX: PUTDST16(RecompPos,0xC3C7); break; + case x86_ECX: PUTDST16(RecompPos,0xC1C7); break; + case x86_EDX: PUTDST16(RecompPos,0xC2C7); break; + case x86_ESI: PUTDST16(RecompPos,0xC6C7); break; + case x86_EDI: PUTDST16(RecompPos,0xC7C7); break; + case x86_ESP: PUTDST16(RecompPos,0xC4C7); break; + case x86_EBP: PUTDST16(RecompPos,0xC5C7); break; + default: + DisplayError("MoveConstToX86reg\nUnknown x86 Register"); + } + PUTDST32(RecompPos,Const); +} + +void MoveOffsetToX86reg(DWORD Const, char * VariableName, int x86reg) { + CPU_Message(" mov %s, offset %s",x86_Name(x86reg),VariableName); + switch (x86reg) { + case x86_EAX: PUTDST16(RecompPos,0xC0C7); break; + case x86_EBX: PUTDST16(RecompPos,0xC3C7); break; + case x86_ECX: PUTDST16(RecompPos,0xC1C7); break; + case x86_EDX: PUTDST16(RecompPos,0xC2C7); break; + case x86_ESI: PUTDST16(RecompPos,0xC6C7); break; + case x86_EDI: PUTDST16(RecompPos,0xC7C7); break; + case x86_ESP: PUTDST16(RecompPos,0xC4C7); break; + case x86_EBP: PUTDST16(RecompPos,0xC5C7); break; + default: + DisplayError("MoveOffsetToX86reg\nUnknown x86 Register"); + } + PUTDST32(RecompPos,Const); +} + +void MoveX86regPointerToX86regByte(int Destination, int AddrReg) { + BYTE x86Command = 0; + + CPU_Message(" mov %s, byte ptr [%s]",x86Byte_Name(Destination), x86_Name(AddrReg)); + + switch (AddrReg) { + 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; + default: DisplayError("MoveX86regPointerToX86regByte\nUnknown x86 Register"); + } + + switch (Destination) { + case x86_EAX: x86Command += 0x00; break; + case x86_EBX: x86Command += 0x18; break; + case x86_ECX: x86Command += 0x08; break; + case x86_EDX: x86Command += 0x10; break; + default: DisplayError("MoveX86regPointerToX86regByte\nUnknown x86 Register"); + } + + PUTDST8(RecompPos, 0x8A); + PUTDST8(RecompPos, x86Command); +} + +void MoveX86regPointerToX86regHalf(int Destination, int AddrReg) { + unsigned char x86Amb = 0; + + CPU_Message(" mov %s, word ptr [%s]",x86Half_Name(Destination), x86_Name(AddrReg)); + + switch (AddrReg) { + case x86_EAX: x86Amb = 0x00; break; + case x86_EBX: x86Amb = 0x03; break; + case x86_ECX: x86Amb = 0x01; break; + case x86_EDX: x86Amb = 0x02; break; + case x86_ESI: x86Amb = 0x06; break; + case x86_EDI: x86Amb = 0x07; break; + default: DisplayError("MoveX86regPointerToX86regHalf\nUnknown x86 Register"); + } + + switch (Destination) { + case x86_EAX: x86Amb += 0x00; break; + case x86_ECX: x86Amb += 0x08; break; + case x86_EDX: x86Amb += 0x10; break; + case x86_EBX: x86Amb += 0x18; break; + case x86_ESI: x86Amb += 0x30; break; + case x86_EDI: x86Amb += 0x38; break; + case x86_ESP: x86Amb += 0x20; break; + case x86_EBP: x86Amb += 0x28; break; + default: DisplayError("MoveX86regPointerToX86regHalf\nUnknown x86 Register"); + } + + PUTDST16(RecompPos, 0x8B66); + PUTDST8(RecompPos, x86Amb); +} + +void MoveX86regPointerToX86reg(int Destination, int AddrReg) { + BYTE x86Amb; + CPU_Message(" mov %s, dword ptr [%s]",x86_Name(Destination), x86_Name(AddrReg)); + + switch (AddrReg) { + case x86_EAX: x86Amb = 0x00; break; + case x86_EBX: x86Amb = 0x03; break; + case x86_ECX: x86Amb = 0x01; break; + case x86_EDX: x86Amb = 0x02; break; + case x86_ESI: x86Amb = 0x06; break; + case x86_EDI: x86Amb = 0x07; break; + case x86_ESP: x86Amb = 0x04; break; + case x86_EBP: x86Amb = 0x05; break; + default: DisplayError("MoveX86regPointerToX86reg\nUnknown x86 Register"); + } + + switch (Destination) { + case x86_EAX: x86Amb += 0x00; break; + case x86_ECX: x86Amb += 0x08; break; + case x86_EDX: x86Amb += 0x10; break; + case x86_EBX: x86Amb += 0x18; break; + case x86_ESI: x86Amb += 0x30; break; + case x86_EDI: x86Amb += 0x38; break; + case x86_ESP: x86Amb += 0x20; break; + case x86_EBP: x86Amb += 0x28; break; + default: DisplayError("MoveX86regPointerToX86reg\nUnknown x86 Register"); + } + + PUTDST8(RecompPos, 0x8B); + PUTDST8(RecompPos, x86Amb); +} + +void MoveX86regByteToX86regPointer(int Source, int AddrReg) { + BYTE x86Amb; + CPU_Message(" mov byte ptr [%s], %s",x86_Name(AddrReg), x86Byte_Name(Source)); + + switch (AddrReg) { + case x86_EAX: x86Amb = 0x00; break; + case x86_EBX: x86Amb = 0x03; break; + case x86_ECX: x86Amb = 0x01; break; + case x86_EDX: x86Amb = 0x02; break; + case x86_ESI: x86Amb = 0x06; break; + case x86_EDI: x86Amb = 0x07; break; + case x86_ESP: x86Amb = 0x04; break; + case x86_EBP: x86Amb = 0x05; break; + default: DisplayError("MoveX86regBytePointer\nUnknown x86 Register"); + } + + switch (Source) { + case x86_EAX: x86Amb += 0x00; break; + case x86_ECX: x86Amb += 0x08; break; + case x86_EDX: x86Amb += 0x10; break; + case x86_EBX: x86Amb += 0x18; break; + case x86_ESI: x86Amb += 0x30; break; + case x86_EDI: x86Amb += 0x38; break; + case x86_ESP: x86Amb += 0x20; break; + case x86_EBP: x86Amb += 0x28; break; + default: DisplayError("MoveX86regBytePointer\nUnknown x86 Register"); + } + + PUTDST8(RecompPos, 0x88); + PUTDST8(RecompPos, x86Amb); +} + +void MoveX86regHalfToX86regPointer(int Source, int AddrReg) { + BYTE x86Amb; + + CPU_Message(" mov word ptr [%s], %s",x86_Name(AddrReg), x86Half_Name(Source)); + + switch (AddrReg) { + case x86_EAX: x86Amb = 0x00; break; + case x86_EBX: x86Amb = 0x03; break; + case x86_ECX: x86Amb = 0x01; break; + case x86_EDX: x86Amb = 0x02; break; + case x86_ESI: x86Amb = 0x06; break; + case x86_EDI: x86Amb = 0x07; break; + case x86_ESP: x86Amb = 0x04; break; + case x86_EBP: x86Amb = 0x05; break; + default: DisplayError("MoveX86regBytePointer\nUnknown x86 Register"); + } + + switch (Source) { + case x86_EAX: x86Amb += 0x00; break; + case x86_ECX: x86Amb += 0x08; break; + case x86_EDX: x86Amb += 0x10; break; + case x86_EBX: x86Amb += 0x18; break; + case x86_ESI: x86Amb += 0x30; break; + case x86_EDI: x86Amb += 0x38; break; + case x86_ESP: x86Amb += 0x20; break; + case x86_EBP: x86Amb += 0x28; break; + default: DisplayError("MoveX86regBytePointer\nUnknown x86 Register"); + } + + PUTDST16(RecompPos, 0x8966); + PUTDST8(RecompPos, x86Amb); +} + +void MoveX86regHalfToX86regPointerDisp(int Source, int AddrReg, BYTE Disp) { + BYTE x86Amb; + + CPU_Message(" mov word ptr [%s+%X], %s",x86_Name(AddrReg), Disp, x86Half_Name(Source)); + + switch (AddrReg) { + case x86_EAX: x86Amb = 0x00; break; + case x86_EBX: x86Amb = 0x03; break; + case x86_ECX: x86Amb = 0x01; break; + case x86_EDX: x86Amb = 0x02; break; + case x86_ESI: x86Amb = 0x06; break; + case x86_EDI: x86Amb = 0x07; break; + case x86_ESP: x86Amb = 0x04; break; + case x86_EBP: x86Amb = 0x05; break; + default: DisplayError("MoveX86regBytePointer\nUnknown x86 Register"); + } + + switch (Source) { + case x86_EAX: x86Amb += 0x00; break; + case x86_ECX: x86Amb += 0x08; break; + case x86_EDX: x86Amb += 0x10; break; + case x86_EBX: x86Amb += 0x18; break; + case x86_ESI: x86Amb += 0x30; break; + case x86_EDI: x86Amb += 0x38; break; + case x86_ESP: x86Amb += 0x20; break; + case x86_EBP: x86Amb += 0x28; break; + default: DisplayError("MoveX86regBytePointer\nUnknown x86 Register"); + } + + PUTDST16(RecompPos, 0x8966); + PUTDST8(RecompPos, x86Amb | 0x40); + PUTDST8(RecompPos, Disp); +} + +void MoveX86regToX86regPointer(int Source, int AddrReg) { + BYTE x86Amb; + CPU_Message(" mov dword ptr [%s], %s",x86_Name(AddrReg), x86_Name(Source)); + + switch (AddrReg) { + case x86_EAX: x86Amb = 0x00; break; + case x86_EBX: x86Amb = 0x03; break; + case x86_ECX: x86Amb = 0x01; break; + case x86_EDX: x86Amb = 0x02; break; + case x86_ESI: x86Amb = 0x06; break; + case x86_EDI: x86Amb = 0x07; break; + case x86_ESP: x86Amb = 0x04; break; + case x86_EBP: x86Amb = 0x05; break; + default: DisplayError("MoveX86regToX86regPointer\nUnknown x86 Register"); + } + + switch (Source) { + case x86_EAX: x86Amb += 0x00; break; + case x86_ECX: x86Amb += 0x08; break; + case x86_EDX: x86Amb += 0x10; break; + case x86_EBX: x86Amb += 0x18; break; + case x86_ESI: x86Amb += 0x30; break; + case x86_EDI: x86Amb += 0x38; break; + case x86_ESP: x86Amb += 0x20; break; + case x86_EBP: x86Amb += 0x28; break; + default: DisplayError("MoveX86regToX86regPointer\nUnknown x86 Register"); + } + + PUTDST8(RecompPos, 0x89); + PUTDST8(RecompPos, x86Amb); +} + +void MoveX86RegToX86regPointerDisp ( int Source, int AddrReg, BYTE Disp ) { + BYTE x86Amb; + CPU_Message(" mov dword ptr [%s+%X], %s",x86_Name(AddrReg), Disp, x86_Name(Source)); + + switch (AddrReg) { + case x86_EAX: x86Amb = 0x00; break; + case x86_EBX: x86Amb = 0x03; break; + case x86_ECX: x86Amb = 0x01; break; + case x86_EDX: x86Amb = 0x02; break; + case x86_ESI: x86Amb = 0x06; break; + case x86_EDI: x86Amb = 0x07; break; + case x86_ESP: DisplayError("MoveX86RegToX86regPointerDisp: ESP is invalid"); break; + case x86_EBP: x86Amb = 0x05; break; + default: DisplayError("MoveX86regToX86regPointer\nUnknown x86 Register"); + } + + switch (Source) { + case x86_EAX: x86Amb += 0x00; break; + case x86_ECX: x86Amb += 0x08; break; + case x86_EDX: x86Amb += 0x10; break; + case x86_EBX: x86Amb += 0x18; break; + case x86_ESI: x86Amb += 0x30; break; + case x86_EDI: x86Amb += 0x38; break; + case x86_ESP: x86Amb += 0x20; break; + case x86_EBP: x86Amb += 0x28; break; + default: DisplayError("MoveX86regToX86regPointer\nUnknown x86 Register"); + } + + PUTDST8(RecompPos, 0x89); + PUTDST8(RecompPos, x86Amb | 0x40); + PUTDST8(RecompPos, Disp); +} + +void MoveN64MemDispToX86reg(int x86reg, int AddrReg, BYTE Disp) { + WORD x86Command; + + CPU_Message(" mov %s, dword ptr [%s+Dmem+%Xh]",x86_Name(x86reg),x86_Name(AddrReg),Disp); + switch (AddrReg) { + case x86_EAX: x86Command = 0x008B; break; + case x86_EBX: x86Command = 0x038B; break; + case x86_ECX: x86Command = 0x018B; break; + case x86_EDX: x86Command = 0x028B; break; + case x86_ESI: x86Command = 0x068B; break; + case x86_EDI: x86Command = 0x078B; break; + case x86_ESP: x86Command = 0x048B; break; + case x86_EBP: x86Command = 0x058B; break; + } + switch (x86reg) { + case x86_EAX: x86Command += 0x8000; break; + case x86_EBX: x86Command += 0x9800; break; + case x86_ECX: x86Command += 0x8800; break; + case x86_EDX: x86Command += 0x9000; break; + case x86_ESI: x86Command += 0xB000; break; + case x86_EDI: x86Command += 0xB800; break; + case x86_ESP: x86Command += 0xA000; break; + case x86_EBP: x86Command += 0xA800; break; + } + PUTDST16(RecompPos,x86Command); + PUTDST32(RecompPos,RSPInfo.DMEM + Disp); +} + +void MoveN64MemToX86reg(int x86reg, int AddrReg) { + WORD x86Command; + + CPU_Message(" mov %s, dword ptr [%s+Dmem]",x86_Name(x86reg),x86_Name(AddrReg)); + + switch (AddrReg) { + case x86_EAX: x86Command = 0x008B; break; + case x86_EBX: x86Command = 0x038B; break; + case x86_ECX: x86Command = 0x018B; break; + case x86_EDX: x86Command = 0x028B; break; + case x86_ESI: x86Command = 0x068B; break; + case x86_EDI: x86Command = 0x078B; break; + case x86_ESP: x86Command = 0x048B; break; + case x86_EBP: x86Command = 0x058B; break; + } + switch (x86reg) { + case x86_EAX: x86Command += 0x8000; break; + case x86_EBX: x86Command += 0x9800; break; + case x86_ECX: x86Command += 0x8800; break; + case x86_EDX: x86Command += 0x9000; break; + case x86_ESI: x86Command += 0xB000; break; + case x86_EDI: x86Command += 0xB800; break; + case x86_ESP: x86Command += 0xA000; break; + case x86_EBP: x86Command += 0xA800; break; + } + PUTDST16(RecompPos,x86Command); + PUTDST32(RecompPos,RSPInfo.DMEM); +} + +void MoveN64MemToX86regByte(int x86reg, int AddrReg) { + WORD x86Command; + + CPU_Message(" mov %s, byte ptr [%s+Dmem]",x86Byte_Name(x86reg),x86_Name(AddrReg)); + switch (AddrReg) { + case x86_EAX: x86Command = 0x008A; break; + case x86_EBX: x86Command = 0x038A; break; + case x86_ECX: x86Command = 0x018A; break; + case x86_EDX: x86Command = 0x028A; break; + case x86_ESI: x86Command = 0x068A; break; + case x86_EDI: x86Command = 0x078A; break; + case x86_ESP: x86Command = 0x048A; break; + case x86_EBP: x86Command = 0x058A; break; + } + switch (x86reg) { + case x86_EAX: x86Command += 0x8000; break; + case x86_EBX: x86Command += 0x9800; break; + case x86_ECX: x86Command += 0x8800; break; + case x86_EDX: x86Command += 0x9000; break; + default: + DisplayError("MoveN64MemToX86regByte\nInvalid x86 Register"); + break; + } + PUTDST16(RecompPos,x86Command); + PUTDST32(RecompPos,RSPInfo.DMEM); +} + +void MoveN64MemToX86regHalf(int x86reg, int AddrReg) { + WORD x86Command; + + CPU_Message(" mov %s, word ptr [%s+Dmem]",x86Half_Name(x86reg),x86_Name(AddrReg)); + + PUTDST8(RecompPos,0x66); + switch (AddrReg) { + case x86_EAX: x86Command = 0x008B; break; + case x86_EBX: x86Command = 0x038B; break; + case x86_ECX: x86Command = 0x018B; break; + case x86_EDX: x86Command = 0x028B; break; + case x86_ESI: x86Command = 0x068B; break; + case x86_EDI: x86Command = 0x078B; break; + case x86_ESP: x86Command = 0x048B; break; + case x86_EBP: x86Command = 0x058B; break; + } + switch (x86reg) { + case x86_EAX: x86Command += 0x8000; break; + case x86_EBX: x86Command += 0x9800; break; + case x86_ECX: x86Command += 0x8800; break; + case x86_EDX: x86Command += 0x9000; break; + case x86_ESI: x86Command += 0xB000; break; + case x86_EDI: x86Command += 0xB800; break; + case x86_ESP: x86Command += 0xA000; break; + case x86_EBP: x86Command += 0xA800; break; + } + PUTDST16(RecompPos,x86Command); + PUTDST32(RecompPos,RSPInfo.DMEM); +} + +void MoveX86regByteToN64Mem(int x86reg, int AddrReg) { + WORD x86Command; + + CPU_Message(" mov byte ptr [%s+Dmem], %s",x86_Name(AddrReg),x86Byte_Name(x86reg)); + + switch (AddrReg) { + case x86_EAX: x86Command = 0x0088; break; + case x86_EBX: x86Command = 0x0388; break; + case x86_ECX: x86Command = 0x0188; break; + case x86_EDX: x86Command = 0x0288; break; + case x86_ESI: x86Command = 0x0688; break; + case x86_EDI: x86Command = 0x0788; break; + } + switch (x86reg) { + case x86_EAX: x86Command += 0x8000; break; + case x86_EBX: x86Command += 0x9800; break; + case x86_ECX: x86Command += 0x8800; break; + case x86_EDX: x86Command += 0x9000; break; + } + PUTDST16(RecompPos,x86Command); + PUTDST32(RecompPos,RSPInfo.DMEM); +} + +void MoveX86regHalfToN64Mem(int x86reg, int AddrReg) { + WORD x86Command; + + CPU_Message(" mov word ptr [%s+Dmem], %s",x86_Name(AddrReg),x86Half_Name(x86reg)); + PUTDST8(RecompPos,0x66); + switch (AddrReg) { + case x86_EAX: x86Command = 0x0089; break; + case x86_EBX: x86Command = 0x0389; break; + case x86_ECX: x86Command = 0x0189; break; + case x86_EDX: x86Command = 0x0289; break; + case x86_ESI: x86Command = 0x0689; break; + case x86_EDI: x86Command = 0x0789; break; + case x86_ESP: x86Command = 0x0489; break; + case x86_EBP: x86Command = 0x0589; break; + } + switch (x86reg) { + case x86_EAX: x86Command += 0x8000; break; + case x86_EBX: x86Command += 0x9800; break; + case x86_ECX: x86Command += 0x8800; break; + case x86_EDX: x86Command += 0x9000; break; + case x86_ESI: x86Command += 0xB000; break; + case x86_EDI: x86Command += 0xB800; break; + case x86_ESP: x86Command += 0xA000; break; + case x86_EBP: x86Command += 0xA800; break; + } + PUTDST16(RecompPos,x86Command); + PUTDST32(RecompPos,RSPInfo.DMEM); +} + +void MoveX86regToN64Mem(int x86reg, int AddrReg) { + WORD x86Command; + + CPU_Message(" mov dword ptr [%s+N64mem], %s",x86_Name(AddrReg),x86_Name(x86reg)); + switch (AddrReg) { + case x86_EAX: x86Command = 0x0089; break; + case x86_EBX: x86Command = 0x0389; break; + case x86_ECX: x86Command = 0x0189; break; + case x86_EDX: x86Command = 0x0289; break; + case x86_ESI: x86Command = 0x0689; break; + case x86_EDI: x86Command = 0x0789; break; + case x86_ESP: x86Command = 0x0489; break; + case x86_EBP: x86Command = 0x0589; break; + } + switch (x86reg) { + case x86_EAX: x86Command += 0x8000; break; + case x86_EBX: x86Command += 0x9800; break; + case x86_ECX: x86Command += 0x8800; break; + case x86_EDX: x86Command += 0x9000; break; + case x86_ESI: x86Command += 0xB000; break; + case x86_EDI: x86Command += 0xB800; break; + case x86_ESP: x86Command += 0xA000; break; + case x86_EBP: x86Command += 0xA800; break; + } + PUTDST16(RecompPos,x86Command); + PUTDST32(RecompPos,RSPInfo.DMEM); +} + +void MoveX86regToN64MemDisp(int x86reg, int AddrReg, BYTE Disp) { + WORD x86Command; + + CPU_Message(" mov dword ptr [%s+N64mem+%d], %s",x86_Name(AddrReg),Disp,x86_Name(x86reg)); + switch (AddrReg) { + case x86_EAX: x86Command = 0x0089; break; + case x86_EBX: x86Command = 0x0389; break; + case x86_ECX: x86Command = 0x0189; break; + case x86_EDX: x86Command = 0x0289; break; + case x86_ESI: x86Command = 0x0689; break; + case x86_EDI: x86Command = 0x0789; break; + case x86_ESP: x86Command = 0x0489; break; + case x86_EBP: x86Command = 0x0589; break; + } + switch (x86reg) { + case x86_EAX: x86Command += 0x8000; break; + case x86_EBX: x86Command += 0x9800; break; + case x86_ECX: x86Command += 0x8800; break; + case x86_EDX: x86Command += 0x9000; break; + case x86_ESI: x86Command += 0xB000; break; + case x86_EDI: x86Command += 0xB800; break; + case x86_ESP: x86Command += 0xA000; break; + case x86_EBP: x86Command += 0xA800; break; + } + PUTDST16(RecompPos,x86Command); + PUTDST32(RecompPos,RSPInfo.DMEM+Disp); +} + +void MoveVariableToX86reg(void *Variable, char *VariableName, int x86reg) { + CPU_Message(" mov %s, dword ptr [%s]",x86_Name(x86reg),VariableName); + switch (x86reg) { + case x86_EAX: PUTDST16(RecompPos,0x058B); break; + case x86_EBX: PUTDST16(RecompPos,0x1D8B); break; + case x86_ECX: PUTDST16(RecompPos,0x0D8B); break; + case x86_EDX: PUTDST16(RecompPos,0x158B); break; + case x86_ESI: PUTDST16(RecompPos,0x358B); break; + case x86_EDI: PUTDST16(RecompPos,0x3D8B); break; + case x86_ESP: PUTDST16(RecompPos,0x258B); break; + case x86_EBP: PUTDST16(RecompPos,0x2D8B); break; + default: DisplayError("MoveVariableToX86reg\nUnknown x86 Register"); + } + PUTDST32(RecompPos,Variable); +} + +void MoveVariableToX86regByte(void *Variable, char *VariableName, int x86reg) { + CPU_Message(" mov %s, byte ptr [%s]",x86Byte_Name(x86reg),VariableName); + switch (x86reg) { + case x86_EAX: PUTDST16(RecompPos,0x058A); break; + case x86_EBX: PUTDST16(RecompPos,0x1D8A); break; + case x86_ECX: PUTDST16(RecompPos,0x0D8A); break; + case x86_EDX: PUTDST16(RecompPos,0x158A); break; + default: DisplayError("MoveVariableToX86regByte\nUnknown x86 Register"); + } + PUTDST32(RecompPos,Variable); +} + +void MoveVariableToX86regHalf(void *Variable, char *VariableName, int x86reg) { + CPU_Message(" mov %s, word ptr [%s]",x86Half_Name(x86reg),VariableName); + PUTDST8(RecompPos,0x66); + switch (x86reg) { + case x86_EAX: PUTDST16(RecompPos,0x058B); break; + case x86_EBX: PUTDST16(RecompPos,0x1D8B); break; + case x86_ECX: PUTDST16(RecompPos,0x0D8B); break; + case x86_EDX: PUTDST16(RecompPos,0x158B); break; + case x86_ESI: PUTDST16(RecompPos,0x358B); break; + case x86_EDI: PUTDST16(RecompPos,0x3D8B); break; + case x86_ESP: PUTDST16(RecompPos,0x258B); break; + case x86_EBP: PUTDST16(RecompPos,0x2D8B); break; + default: DisplayError("MoveVariableToX86reg\nUnknown x86 Register"); + } + PUTDST32(RecompPos,Variable); +} + +void MoveX86regByteToVariable(int x86reg, void * Variable, char * VariableName) { + CPU_Message(" mov byte ptr [%s], %s",VariableName,x86Byte_Name(x86reg)); + switch (x86reg) { + case x86_EAX: PUTDST16(RecompPos,0x0588); break; + case x86_EBX: PUTDST16(RecompPos,0x1D88); break; + case x86_ECX: PUTDST16(RecompPos,0x0D88); break; + case x86_EDX: PUTDST16(RecompPos,0x1588); break; + default: + DisplayError("MoveX86regByteToVariable\nUnknown x86 Register"); + } + PUTDST32(RecompPos,Variable); +} + +void MoveX86regHalfToVariable(int x86reg, void * Variable, char * VariableName) { + CPU_Message(" mov word ptr [%s], %s",VariableName,x86Half_Name(x86reg)); + PUTDST8(RecompPos,0x66); + switch (x86reg) { + case x86_EAX: PUTDST16(RecompPos,0x0589); break; + case x86_EBX: PUTDST16(RecompPos,0x1D89); break; + case x86_ECX: PUTDST16(RecompPos,0x0D89); break; + case x86_EDX: PUTDST16(RecompPos,0x1589); break; + case x86_ESI: PUTDST16(RecompPos,0x3589); break; + case x86_EDI: PUTDST16(RecompPos,0x3D89); break; + case x86_ESP: PUTDST16(RecompPos,0x2589); break; + case x86_EBP: PUTDST16(RecompPos,0x2D89); break; + default: + DisplayError("MoveX86regHalfToVariable\nUnknown x86 Register"); + } + PUTDST32(RecompPos,Variable); +} + +void MoveX86regToVariable(int x86reg, void * Variable, char * VariableName) { + CPU_Message(" mov dword ptr [%s], %s",VariableName,x86_Name(x86reg)); + switch (x86reg) { + case x86_EAX: PUTDST16(RecompPos,0x0589); break; + case x86_EBX: PUTDST16(RecompPos,0x1D89); break; + case x86_ECX: PUTDST16(RecompPos,0x0D89); break; + case x86_EDX: PUTDST16(RecompPos,0x1589); break; + case x86_ESI: PUTDST16(RecompPos,0x3589); break; + case x86_EDI: PUTDST16(RecompPos,0x3D89); break; + case x86_ESP: PUTDST16(RecompPos,0x2589); break; + case x86_EBP: PUTDST16(RecompPos,0x2D89); break; + default: + DisplayError("MoveX86regToVariable\nUnknown x86 Register"); + } + PUTDST32(RecompPos,Variable); +} + +void MoveX86RegToX86Reg(int Source, int Destination) { + WORD x86Command; + + CPU_Message(" mov %s, %s",x86_Name(Destination),x86_Name(Source)); + + switch (Destination) { + case x86_EAX: x86Command = 0x0089; break; + case x86_EBX: x86Command = 0x0389; break; + case x86_ECX: x86Command = 0x0189; break; + case x86_EDX: x86Command = 0x0289; break; + case x86_ESI: x86Command = 0x0689; break; + case x86_EDI: x86Command = 0x0789; break; + case x86_ESP: x86Command = 0x0489; break; + case x86_EBP: x86Command = 0x0589; break; + } + + switch (Source) { + case x86_EAX: x86Command += 0xC000; break; + case x86_EBX: x86Command += 0xD800; break; + case x86_ECX: x86Command += 0xC800; break; + case x86_EDX: x86Command += 0xD000; break; + case x86_ESI: x86Command += 0xF000; break; + case x86_EDI: x86Command += 0xF800; break; + case x86_ESP: x86Command += 0xE000; break; + case x86_EBP: x86Command += 0xE800; break; + } + PUTDST16(RecompPos,x86Command); +} + +void MoveSxX86RegHalfToX86Reg(int Source, int Destination) { + WORD x86Command; + + CPU_Message(" movsx %s, %s",x86_Name(Destination),x86Half_Name(Source)); + + switch (Source) { + case x86_EAX: x86Command = 0x00BF; break; + case x86_EBX: x86Command = 0x03BF; break; + case x86_ECX: x86Command = 0x01BF; break; + case x86_EDX: x86Command = 0x02BF; break; + case x86_ESI: x86Command = 0x06BF; break; + case x86_EDI: x86Command = 0x07BF; break; + case x86_ESP: x86Command = 0x04BF; break; + case x86_EBP: x86Command = 0x05BF; break; + } + + switch (Destination) { + case x86_EAX: x86Command += 0xC000; break; + case x86_EBX: x86Command += 0xD800; break; + case x86_ECX: x86Command += 0xC800; break; + case x86_EDX: x86Command += 0xD000; break; + case x86_ESI: x86Command += 0xF000; break; + case x86_EDI: x86Command += 0xF800; break; + case x86_ESP: x86Command += 0xE000; break; + case x86_EBP: x86Command += 0xE800; break; + } + PUTDST8(RecompPos, 0x0f); + PUTDST16(RecompPos,x86Command); +} + +void MoveSxX86RegPtrDispToX86RegHalf(int AddrReg, BYTE Disp, int Destination) { + BYTE x86Command; + + CPU_Message(" movsx %s, [%s+%X]",x86_Name(Destination), x86_Name(AddrReg),Disp); + + switch (AddrReg) { + 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 += 0x40; break; + case x86_EBX: x86Command += 0x58; break; + case x86_ECX: x86Command += 0x48; break; + case x86_EDX: x86Command += 0x50; break; + case x86_ESI: x86Command += 0x70; break; + case x86_EDI: x86Command += 0x78; break; + case x86_ESP: x86Command += 0x60; break; + case x86_EBP: x86Command += 0x68; break; + } + PUTDST16(RecompPos, 0xBF0F); + PUTDST8(RecompPos, x86Command); + PUTDST8(RecompPos, Disp); +} + +void MoveSxVariableToX86regHalf(void *Variable, char *VariableName, int x86reg) { + CPU_Message(" movsx %s, word ptr [%s]",x86_Name(x86reg),VariableName); + + PUTDST16(RecompPos, 0xbf0f); + + 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("MoveSxVariableToX86regHalf\nUnknown x86 Register"); + } + PUTDST32(RecompPos,Variable); +} + +void MoveSxN64MemToX86regByte(int x86reg, int AddrReg) { + WORD x86Command; + + CPU_Message(" movsx %s, byte ptr [%s+Dmem]",x86_Name(x86reg),x86_Name(AddrReg)); + switch (AddrReg) { + case x86_EAX: x86Command = 0x00BE; break; + case x86_EBX: x86Command = 0x03BE; break; + case x86_ECX: x86Command = 0x01BE; break; + case x86_EDX: x86Command = 0x02BE; break; + case x86_ESI: x86Command = 0x06BE; break; + case x86_EDI: x86Command = 0x07BE; break; + case x86_ESP: x86Command = 0x04BE; break; + case x86_EBP: x86Command = 0x05BE; break; + } + switch (x86reg) { + case x86_EAX: x86Command += 0x8000; break; + case x86_EBX: x86Command += 0x9800; break; + case x86_ECX: x86Command += 0x8800; break; + case x86_EDX: x86Command += 0x9000; break; + default: + DisplayError("MoveSxN64MemToX86regByte\nInvalid x86 Register"); + break; + } + PUTDST8(RecompPos,0x0f); + PUTDST16(RecompPos,x86Command); + PUTDST32(RecompPos,RSPInfo.DMEM); +} + +void MoveSxN64MemToX86regHalf(int x86reg, int AddrReg) { + WORD x86Command; + + CPU_Message(" movsx %s, word ptr [%s+Dmem]",x86_Name(x86reg),x86_Name(AddrReg)); + + switch (AddrReg) { + case x86_EAX: x86Command = 0x00BF; break; + case x86_EBX: x86Command = 0x03BF; break; + case x86_ECX: x86Command = 0x01BF; break; + case x86_EDX: x86Command = 0x02BF; break; + case x86_ESI: x86Command = 0x06BF; break; + case x86_EDI: x86Command = 0x07BF; break; + case x86_ESP: x86Command = 0x04BF; break; + case x86_EBP: x86Command = 0x05BF; break; + } + switch (x86reg) { + case x86_EAX: x86Command += 0x8000; break; + case x86_EBX: x86Command += 0x9800; break; + case x86_ECX: x86Command += 0x8800; break; + case x86_EDX: x86Command += 0x9000; break; + case x86_ESI: x86Command += 0xB000; break; + case x86_EDI: x86Command += 0xB800; break; + case x86_ESP: x86Command += 0xA000; break; + case x86_EBP: x86Command += 0xA800; break; + } + + PUTDST8(RecompPos, 0x0f); + PUTDST16(RecompPos,x86Command); + PUTDST32(RecompPos,RSPInfo.DMEM); +} + +void MoveZxX86RegHalfToX86Reg(int Source, int Destination) { + WORD x86Command; + + CPU_Message(" movzx %s, %s",x86_Name(Destination),x86Half_Name(Source)); + + switch (Source) { + case x86_EAX: x86Command = 0x00B7; break; + case x86_EBX: x86Command = 0x03B7; break; + case x86_ECX: x86Command = 0x01B7; break; + case x86_EDX: x86Command = 0x02B7; break; + case x86_ESI: x86Command = 0x06B7; break; + case x86_EDI: x86Command = 0x07B7; break; + case x86_ESP: x86Command = 0x04B7; break; + case x86_EBP: x86Command = 0x05B7; break; + } + + switch (Destination) { + case x86_EAX: x86Command += 0xC000; break; + case x86_EBX: x86Command += 0xD800; break; + case x86_ECX: x86Command += 0xC800; break; + case x86_EDX: x86Command += 0xD000; break; + case x86_ESI: x86Command += 0xF000; break; + case x86_EDI: x86Command += 0xF800; break; + case x86_ESP: x86Command += 0xE000; break; + case x86_EBP: x86Command += 0xE800; break; + } + PUTDST8(RecompPos, 0x0f); + PUTDST16(RecompPos,x86Command); +} + +void MoveZxX86RegPtrDispToX86RegHalf(int AddrReg, BYTE Disp, int Destination) { + BYTE x86Command; + + CPU_Message(" movzx %s, [%s+%X]",x86_Name(Destination), x86_Name(AddrReg), Disp); + + switch (AddrReg) { + 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 += 0x40; break; + case x86_EBX: x86Command += 0x58; break; + case x86_ECX: x86Command += 0x48; break; + case x86_EDX: x86Command += 0x50; break; + case x86_ESI: x86Command += 0x70; break; + case x86_EDI: x86Command += 0x78; break; + case x86_ESP: x86Command += 0x60; break; + case x86_EBP: x86Command += 0x68; break; + } + PUTDST16(RecompPos, 0xB70F); + PUTDST8(RecompPos, x86Command); + PUTDST8(RecompPos, Disp); +} + +void MoveZxVariableToX86regHalf(void *Variable, char *VariableName, int x86reg) { + CPU_Message(" movzx %s, word ptr [%s]",x86_Name(x86reg),VariableName); + + PUTDST16(RecompPos, 0xb70f); + + 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("MoveZxVariableToX86regHalf\nUnknown x86 Register"); + } + PUTDST32(RecompPos,Variable); +} + +void MoveZxN64MemToX86regByte(int x86reg, int AddrReg) { + WORD x86Command; + + CPU_Message(" movzx %s, byte ptr [%s+Dmem]",x86_Name(x86reg),x86_Name(AddrReg)); + switch (AddrReg) { + case x86_EAX: x86Command = 0x00B6; break; + case x86_EBX: x86Command = 0x03B6; break; + case x86_ECX: x86Command = 0x01B6; break; + case x86_EDX: x86Command = 0x02B6; break; + case x86_ESI: x86Command = 0x06B6; break; + case x86_EDI: x86Command = 0x07B6; break; + case x86_ESP: x86Command = 0x04B6; break; + case x86_EBP: x86Command = 0x05B6; break; + } + switch (x86reg) { + case x86_EAX: x86Command += 0x8000; break; + case x86_EBX: x86Command += 0x9800; break; + case x86_ECX: x86Command += 0x8800; break; + case x86_EDX: x86Command += 0x9000; break; + default: + DisplayError("MoveZxN64MemToX86regByte\nInvalid x86 Register"); + break; + } + PUTDST8(RecompPos,0x0f); + PUTDST16(RecompPos,x86Command); + PUTDST32(RecompPos,RSPInfo.DMEM); +} + +void MoveZxN64MemToX86regHalf(int x86reg, int AddrReg) { + WORD x86Command; + + CPU_Message(" movzx %s, word ptr [%s+Dmem]",x86_Name(x86reg),x86_Name(AddrReg)); + + switch (AddrReg) { + case x86_EAX: x86Command = 0x00B7; break; + case x86_EBX: x86Command = 0x03B7; break; + case x86_ECX: x86Command = 0x01B7; break; + case x86_EDX: x86Command = 0x02B7; break; + case x86_ESI: x86Command = 0x06B7; break; + case x86_EDI: x86Command = 0x07B7; break; + case x86_ESP: x86Command = 0x04B7; break; + case x86_EBP: x86Command = 0x05B7; break; + } + switch (x86reg) { + case x86_EAX: x86Command += 0x8000; break; + case x86_EBX: x86Command += 0x9800; break; + case x86_ECX: x86Command += 0x8800; break; + case x86_EDX: x86Command += 0x9000; break; + case x86_ESI: x86Command += 0xB000; break; + case x86_EDI: x86Command += 0xB800; break; + case x86_ESP: x86Command += 0xA000; break; + case x86_EBP: x86Command += 0xA800; break; + } + + PUTDST8(RecompPos, 0x0f); + PUTDST16(RecompPos,x86Command); + PUTDST32(RecompPos,RSPInfo.DMEM); +} + +void MulX86reg(int x86reg) { + CPU_Message(" mul %s",x86_Name(x86reg)); + switch (x86reg) { + case x86_EAX: PUTDST16(RecompPos,0xE0F7); break; + case x86_EBX: PUTDST16(RecompPos,0xE3F7); break; + case x86_ECX: PUTDST16(RecompPos,0xE1F7); break; + case x86_EDX: PUTDST16(RecompPos,0xE2F7); break; + case x86_ESI: PUTDST16(RecompPos,0xE6F7); break; + case x86_EDI: PUTDST16(RecompPos,0xE7F7); break; + case x86_ESP: PUTDST16(RecompPos,0xE4F7); break; + case x86_EBP: PUTDST16(RecompPos,0xE5F7); break; + default: + DisplayError("MulX86reg\nUnknown x86 Register"); + } +} + +void NegateX86reg(int x86reg) { + CPU_Message(" neg %s", x86_Name(x86reg)); + switch (x86reg) { + case x86_EAX: PUTDST16(RecompPos,0xd8f7); break; + case x86_EBX: PUTDST16(RecompPos,0xdbf7); break; + case x86_ECX: PUTDST16(RecompPos,0xd9f7); break; + case x86_EDX: PUTDST16(RecompPos,0xdaf7); break; + case x86_ESI: PUTDST16(RecompPos,0xdef7); break; + case x86_EDI: PUTDST16(RecompPos,0xdff7); break; + case x86_ESP: PUTDST16(RecompPos,0xdcf7); break; + case x86_EBP: PUTDST16(RecompPos,0xddf7); break; + default: + DisplayError("NegateX86reg\nUnknown x86 Register"); + } +} + +void OrConstToVariable(DWORD Const, void * Variable, char * VariableName) { + CPU_Message(" or dword ptr [%s], 0x%X",VariableName, Const); + PUTDST16(RecompPos,0x0D81); + PUTDST32(RecompPos,Variable); + PUTDST32(RecompPos,Const); +} + +void OrConstToX86Reg(DWORD Const, int x86Reg) { + CPU_Message(" or %s, %Xh",x86_Name(x86Reg),Const); + if ((Const & 0xFFFFFF80) != 0 && (Const & 0xFFFFFF80) != 0xFFFFFF80) { + switch (x86Reg) { + case x86_EAX: PUTDST16(RecompPos,0xC881); break; + case x86_EBX: PUTDST16(RecompPos,0xCB81); break; + case x86_ECX: PUTDST16(RecompPos,0xC981); break; + case x86_EDX: PUTDST16(RecompPos,0xCA81); break; + case x86_ESI: PUTDST16(RecompPos,0xCE81); break; + case x86_EDI: PUTDST16(RecompPos,0xCF81); break; + case x86_ESP: PUTDST16(RecompPos,0xCC81); break; + case x86_EBP: PUTDST16(RecompPos,0xCD81); break; + } + PUTDST32(RecompPos, Const); + } else { + switch (x86Reg) { + case x86_EAX: PUTDST16(RecompPos,0xC883); break; + case x86_EBX: PUTDST16(RecompPos,0xCB83); break; + case x86_ECX: PUTDST16(RecompPos,0xC983); break; + case x86_EDX: PUTDST16(RecompPos,0xCA83); break; + case x86_ESI: PUTDST16(RecompPos,0xCE83); break; + case x86_EDI: PUTDST16(RecompPos,0xCF83); break; + case x86_ESP: PUTDST16(RecompPos,0xCC83); break; + case x86_EBP: PUTDST16(RecompPos,0xCD83); break; + } + PUTDST8(RecompPos, Const); + } +} + +void OrVariableToX86Reg(void * Variable, char * VariableName, int x86Reg) { + CPU_Message(" or %s, dword ptr [%s]",x86_Name(x86Reg),VariableName); + switch (x86Reg) { + case x86_EAX: PUTDST16(RecompPos,0x050B); break; + case x86_EBX: PUTDST16(RecompPos,0x1D0B); break; + case x86_ECX: PUTDST16(RecompPos,0x0D0B); break; + case x86_EDX: PUTDST16(RecompPos,0x150B); break; + case x86_ESI: PUTDST16(RecompPos,0x350B); break; + case x86_EDI: PUTDST16(RecompPos,0x3D0B); break; + case x86_ESP: PUTDST16(RecompPos,0x250B); break; + case x86_EBP: PUTDST16(RecompPos,0x2D0B); break; + } + PUTDST32(RecompPos,Variable); +} + +void OrVariableToX86regHalf(void * Variable, char * VariableName, int x86Reg) { + CPU_Message(" or %s, word ptr [%s]",x86Half_Name(x86Reg),VariableName); + PUTDST8(RecompPos,0x66); + switch (x86Reg) { + case x86_EAX: PUTDST16(RecompPos,0x050B); break; + case x86_EBX: PUTDST16(RecompPos,0x1D0B); break; + case x86_ECX: PUTDST16(RecompPos,0x0D0B); break; + case x86_EDX: PUTDST16(RecompPos,0x150B); break; + case x86_ESI: PUTDST16(RecompPos,0x350B); break; + case x86_EDI: PUTDST16(RecompPos,0x3D0B); break; + case x86_ESP: PUTDST16(RecompPos,0x250B); break; + case x86_EBP: PUTDST16(RecompPos,0x2D0B); break; + } + PUTDST32(RecompPos,Variable); +} + +void OrX86RegToVariable(void * Variable, char * VariableName, int x86Reg) { + CPU_Message(" or dword ptr [%s], %s",VariableName, x86_Name(x86Reg)); + switch (x86Reg) { + case x86_EAX: PUTDST16(RecompPos,0x0509); break; + case x86_EBX: PUTDST16(RecompPos,0x1D09); break; + case x86_ECX: PUTDST16(RecompPos,0x0D09); break; + case x86_EDX: PUTDST16(RecompPos,0x1509); break; + case x86_ESI: PUTDST16(RecompPos,0x3509); break; + case x86_EDI: PUTDST16(RecompPos,0x3D09); break; + case x86_ESP: PUTDST16(RecompPos,0x2509); break; + case x86_EBP: PUTDST16(RecompPos,0x2D09); break; + } + PUTDST32(RecompPos,Variable); +} + +void OrX86RegToX86Reg(int Destination, int Source) { + WORD x86Command; + + CPU_Message(" or %s, %s",x86_Name(Destination),x86_Name(Source)); + switch (Source) { + case x86_EAX: x86Command = 0x000B; break; + case x86_EBX: x86Command = 0x030B; break; + case x86_ECX: x86Command = 0x010B; break; + case x86_EDX: x86Command = 0x020B; break; + case x86_ESI: x86Command = 0x060B; break; + case x86_EDI: x86Command = 0x070B; break; + case x86_ESP: x86Command = 0x040B; break; + case x86_EBP: x86Command = 0x050B; break; + } + switch (Destination) { + case x86_EAX: x86Command += 0xC000; break; + case x86_EBX: x86Command += 0xD800; break; + case x86_ECX: x86Command += 0xC800; break; + case x86_EDX: x86Command += 0xD000; break; + case x86_ESI: x86Command += 0xF000; break; + case x86_EDI: x86Command += 0xF800; break; + case x86_ESP: x86Command += 0xE000; break; + case x86_EBP: x86Command += 0xE800; break; + } + PUTDST16(RecompPos,x86Command); +} + +void Popad(void) { + CPU_Message(" popad"); + PUTDST8(RecompPos,0x61); +} + +void Pushad(void) { + CPU_Message(" pushad"); + PUTDST8(RecompPos,0x60); +} + +void Push(int x86reg) { + CPU_Message(" push %s", x86_Name(x86reg)); + + switch(x86reg) { + case x86_EAX: PUTDST8(RecompPos, 0x50); break; + case x86_EBX: PUTDST8(RecompPos, 0x53); break; + case x86_ECX: PUTDST8(RecompPos, 0x51); break; + case x86_EDX: PUTDST8(RecompPos, 0x52); break; + case x86_ESI: PUTDST8(RecompPos, 0x56); break; + case x86_EDI: PUTDST8(RecompPos, 0x57); break; + case x86_ESP: PUTDST8(RecompPos, 0x54); break; + case x86_EBP: PUTDST8(RecompPos, 0x55); break; + } +} + +void Pop(int x86reg) { + CPU_Message(" pop %s", x86_Name(x86reg)); + + switch(x86reg) { + case x86_EAX: PUTDST8(RecompPos, 0x58); break; + case x86_EBX: PUTDST8(RecompPos, 0x5B); break; + case x86_ECX: PUTDST8(RecompPos, 0x59); break; + case x86_EDX: PUTDST8(RecompPos, 0x5A); break; + case x86_ESI: PUTDST8(RecompPos, 0x5E); break; + case x86_EDI: PUTDST8(RecompPos, 0x5F); break; + case x86_ESP: PUTDST8(RecompPos, 0x5C); break; + case x86_EBP: PUTDST8(RecompPos, 0x5D); break; + } +} + +void PushImm32(char * String, DWORD Value) { + CPU_Message(" push %s",String); + PUTDST8(RecompPos,0x68); + PUTDST32(RecompPos,Value); +} + +void Ret(void) { + CPU_Message(" ret"); + PUTDST8(RecompPos,0xC3); +} + +void Setl(int x86reg) { + CPU_Message(" setl %s",x86Byte_Name(x86reg)); + PUTDST16(RecompPos,0x9C0F); + switch (x86reg) { + case x86_EAX: PUTDST8(RecompPos,0xC0); break; + case x86_EBX: PUTDST8(RecompPos,0xC3); break; + case x86_ECX: PUTDST8(RecompPos,0xC1); break; + case x86_EDX: PUTDST8(RecompPos,0xC2); break; + default: + DisplayError("Setl\nUnknown x86 Register"); + } +} + +void SetlVariable(void * Variable, char * VariableName) { + CPU_Message(" setl byte ptr [%s]",VariableName); + PUTDST16(RecompPos,0x9C0F); + PUTDST8(RecompPos,0x05); + PUTDST32(RecompPos,Variable); +} + +void SetleVariable(void * Variable, char * VariableName) { + CPU_Message(" setle byte ptr [%s]",VariableName); + PUTDST16(RecompPos,0x9E0F); + PUTDST8(RecompPos,0x05); + PUTDST32(RecompPos,Variable); +} + +void Setb(int x86reg) { + CPU_Message(" setb %s",x86Byte_Name(x86reg)); + PUTDST16(RecompPos,0x920F); + switch (x86reg) { + case x86_EAX: PUTDST8(RecompPos,0xC0); break; + case x86_EBX: PUTDST8(RecompPos,0xC3); break; + case x86_ECX: PUTDST8(RecompPos,0xC1); break; + case x86_EDX: PUTDST8(RecompPos,0xC2); break; + default: + DisplayError("Setb\nUnknown x86 Register"); + } +} + +void SetbVariable(void * Variable, char * VariableName) { + CPU_Message(" setb byte ptr [%s]",VariableName); + PUTDST16(RecompPos,0x920F); + PUTDST8(RecompPos,0x05); + PUTDST32(RecompPos,Variable); +} + +void Setg(int x86reg) { + CPU_Message(" setg %s",x86Byte_Name(x86reg)); + PUTDST16(RecompPos,0x9F0F); + switch (x86reg) { + case x86_EAX: PUTDST8(RecompPos,0xC0); break; + case x86_EBX: PUTDST8(RecompPos,0xC3); break; + case x86_ECX: PUTDST8(RecompPos,0xC1); break; + case x86_EDX: PUTDST8(RecompPos,0xC2); break; + default: + DisplayError("Setg\nUnknown x86 Register"); + } +} + +void SetgVariable(void * Variable, char * VariableName) { + CPU_Message(" setg byte ptr [%s]",VariableName); + PUTDST16(RecompPos,0x9F0F); + PUTDST8(RecompPos,0x05); + PUTDST32(RecompPos,Variable); +} + +void SetgeVariable(void * Variable, char * VariableName) { + CPU_Message(" setge byte ptr [%s]",VariableName); + PUTDST16(RecompPos,0x9D0F); + PUTDST8(RecompPos,0x05); + PUTDST32(RecompPos,Variable); +} + +void Seta(int x86reg) { + CPU_Message(" seta %s",x86Byte_Name(x86reg)); + PUTDST16(RecompPos,0x970F); + switch (x86reg) { + case x86_EAX: PUTDST8(RecompPos,0xC0); break; + case x86_EBX: PUTDST8(RecompPos,0xC3); break; + case x86_ECX: PUTDST8(RecompPos,0xC1); break; + case x86_EDX: PUTDST8(RecompPos,0xC2); break; + default: + DisplayError("Seta\nUnknown x86 Register"); + } +} + +void SetaVariable(void * Variable, char * VariableName) { + CPU_Message(" seta byte ptr [%s]",VariableName); + PUTDST16(RecompPos,0x970F); + PUTDST8(RecompPos,0x05); + PUTDST32(RecompPos,Variable); +} + +void Setae(int x86reg) { + CPU_Message(" setae %s",x86Byte_Name(x86reg)); + PUTDST16(RecompPos,0x930F); + switch (x86reg) { + case x86_EAX: PUTDST8(RecompPos,0xC0); break; + case x86_EBX: PUTDST8(RecompPos,0xC3); break; + case x86_ECX: PUTDST8(RecompPos,0xC1); break; + case x86_EDX: PUTDST8(RecompPos,0xC2); break; + default: + DisplayError("Seta\nUnknown x86 Register"); + } +} + +void Setz(int x86reg) { + CPU_Message(" setz %s",x86Byte_Name(x86reg)); + PUTDST16(RecompPos,0x940F); + switch (x86reg) { + case x86_EAX: PUTDST8(RecompPos,0xC0); break; + case x86_EBX: PUTDST8(RecompPos,0xC3); break; + case x86_ECX: PUTDST8(RecompPos,0xC1); break; + case x86_EDX: PUTDST8(RecompPos,0xC2); break; + default: + DisplayError("Setz\nUnknown x86 Register"); + } +} + +void SetzVariable(void * Variable, char * VariableName) { + CPU_Message(" setz byte ptr [%s]",VariableName); + PUTDST16(RecompPos,0x940F); + PUTDST8(RecompPos,0x05); + PUTDST32(RecompPos,Variable); +} + +void Setnz(int x86reg) { + CPU_Message(" setnz %s",x86Byte_Name(x86reg)); + PUTDST16(RecompPos,0x950F); + switch (x86reg) { + case x86_EAX: PUTDST8(RecompPos,0xC0); break; + case x86_EBX: PUTDST8(RecompPos,0xC3); break; + case x86_ECX: PUTDST8(RecompPos,0xC1); break; + case x86_EDX: PUTDST8(RecompPos,0xC2); break; + default: + DisplayError("Setnz\nUnknown x86 Register"); + } +} + +void SetnzVariable(void * Variable, char * VariableName) { + CPU_Message(" setnz byte ptr [%s]",VariableName); + PUTDST16(RecompPos,0x950F); + PUTDST8(RecompPos,0x05); + PUTDST32(RecompPos,Variable); +} + +void ShiftLeftDoubleImmed(int Destination, int Source, BYTE Immediate) { + BYTE x86Amb = 0xC0; + + CPU_Message(" shld %s, %s, %Xh", x86_Name(Destination),x86_Name(Source), Immediate); + PUTDST16(RecompPos,0xA40F); + + switch (Destination) { + case x86_EAX: x86Amb += 0x00; break; + case x86_EBX: x86Amb += 0x03; break; + case x86_ECX: x86Amb += 0x01; break; + case x86_EDX: x86Amb += 0x02; break; + case x86_ESI: x86Amb += 0x06; break; + case x86_EDI: x86Amb += 0x07; break; + case x86_ESP: x86Amb += 0x04; break; + case x86_EBP: x86Amb += 0x05; break; + } + + switch (Source) { + case x86_EAX: x86Amb += 0x00; break; + case x86_EBX: x86Amb += 0x18; break; + case x86_ECX: x86Amb += 0x08; break; + case x86_EDX: x86Amb += 0x10; break; + case x86_ESI: x86Amb += 0x30; break; + case x86_EDI: x86Amb += 0x38; break; + case x86_ESP: x86Amb += 0x20; break; + case x86_EBP: x86Amb += 0x28; break; + } + + PUTDST8(RecompPos,x86Amb); + PUTDST8(RecompPos,Immediate); +} + +void ShiftRightDoubleImmed(int Destination, int Source, BYTE Immediate) { + BYTE x86Amb = 0xC0; + + CPU_Message(" shrd %s, %s, %Xh", x86_Name(Destination),x86_Name(Source), Immediate); + PUTDST16(RecompPos,0xAC0F); + + switch (Destination) { + case x86_EAX: x86Amb += 0x00; break; + case x86_EBX: x86Amb += 0x03; break; + case x86_ECX: x86Amb += 0x01; break; + case x86_EDX: x86Amb += 0x02; break; + case x86_ESI: x86Amb += 0x06; break; + case x86_EDI: x86Amb += 0x07; break; + case x86_ESP: x86Amb += 0x04; break; + case x86_EBP: x86Amb += 0x05; break; + } + + switch (Source) { + case x86_EAX: x86Amb += 0x00; break; + case x86_EBX: x86Amb += 0x18; break; + case x86_ECX: x86Amb += 0x08; break; + case x86_EDX: x86Amb += 0x10; break; + case x86_ESI: x86Amb += 0x30; break; + case x86_EDI: x86Amb += 0x38; break; + case x86_ESP: x86Amb += 0x20; break; + case x86_EBP: x86Amb += 0x28; break; + } + + PUTDST8(RecompPos,x86Amb); + PUTDST8(RecompPos,Immediate); +} + +void ShiftLeftSign(int x86reg) { + CPU_Message(" shl %s, cl",x86_Name(x86reg)); + switch (x86reg) { + case x86_EAX: PUTDST16(RecompPos,0xE0D3); break; + case x86_EBX: PUTDST16(RecompPos,0xE3D3); break; + case x86_ECX: PUTDST16(RecompPos,0xE1D3); break; + case x86_EDX: PUTDST16(RecompPos,0xE2D3); break; + case x86_ESI: PUTDST16(RecompPos,0xE6D3); break; + case x86_EDI: PUTDST16(RecompPos,0xE7D3); break; + case x86_ESP: PUTDST16(RecompPos,0xE4D3); break; + case x86_EBP: PUTDST16(RecompPos,0xE5D3); break; + } +} + +void ShiftLeftSignImmed(int x86reg, BYTE Immediate) { + CPU_Message(" shl %s, %Xh",x86_Name(x86reg),Immediate); + switch (x86reg) { + case x86_EAX: PUTDST16(RecompPos,0xE0C1); break; + case x86_EBX: PUTDST16(RecompPos,0xE3C1); break; + case x86_ECX: PUTDST16(RecompPos,0xE1C1); break; + case x86_EDX: PUTDST16(RecompPos,0xE2C1); break; + case x86_ESI: PUTDST16(RecompPos,0xE6C1); break; + case x86_EDI: PUTDST16(RecompPos,0xE7C1); break; + case x86_ESP: PUTDST16(RecompPos,0xE4C1); break; + case x86_EBP: PUTDST16(RecompPos,0xE5C1); break; + } + PUTDST8(RecompPos,Immediate); +} + +void ShiftLeftSignVariableImmed(void *Variable, char *VariableName, BYTE Immediate) { + CPU_Message(" shl dword ptr [%s], %Xh",VariableName, Immediate); + + PUTDST16(RecompPos,0x25C1) + PUTDST32(RecompPos, Variable); + PUTDST8(RecompPos,Immediate); +} + +void ShiftRightSignImmed(int x86reg, BYTE Immediate) { + CPU_Message(" sar %s, %Xh",x86_Name(x86reg),Immediate); + switch (x86reg) { + case x86_EAX: PUTDST16(RecompPos,0xF8C1); break; + case x86_EBX: PUTDST16(RecompPos,0xFBC1); break; + case x86_ECX: PUTDST16(RecompPos,0xF9C1); break; + case x86_EDX: PUTDST16(RecompPos,0xFAC1); break; + case x86_ESI: PUTDST16(RecompPos,0xFEC1); break; + case x86_EDI: PUTDST16(RecompPos,0xFFC1); break; + case x86_ESP: PUTDST16(RecompPos,0xFCC1); break; + case x86_EBP: PUTDST16(RecompPos,0xFDC1); break; + default: + DisplayError("ShiftRightSignImmed\nUnknown x86 Register"); + } + PUTDST8(RecompPos,Immediate); +} + +void ShiftRightSignVariableImmed(void *Variable, char *VariableName, BYTE Immediate) { + CPU_Message(" sar dword ptr [%s], %Xh",VariableName, Immediate); + + PUTDST16(RecompPos,0x3DC1) + PUTDST32(RecompPos, Variable); + PUTDST8(RecompPos,Immediate); +} + +void ShiftRightUnsign(int x86reg) { + CPU_Message(" shr %s, cl",x86_Name(x86reg)); + switch (x86reg) { + case x86_EAX: PUTDST16(RecompPos,0xE8D3); break; + case x86_EBX: PUTDST16(RecompPos,0xEBD3); break; + case x86_ECX: PUTDST16(RecompPos,0xE9D3); break; + case x86_EDX: PUTDST16(RecompPos,0xEAD3); break; + case x86_ESI: PUTDST16(RecompPos,0xEED3); break; + case x86_EDI: PUTDST16(RecompPos,0xEFD3); break; + case x86_ESP: PUTDST16(RecompPos,0xECD3); break; + case x86_EBP: PUTDST16(RecompPos,0xEDD3); break; + } +} + +void ShiftRightUnsignImmed(int x86reg, BYTE Immediate) { + CPU_Message(" shr %s, %Xh",x86_Name(x86reg),Immediate); + switch (x86reg) { + case x86_EAX: PUTDST16(RecompPos,0xE8C1); break; + case x86_EBX: PUTDST16(RecompPos,0xEBC1); break; + case x86_ECX: PUTDST16(RecompPos,0xE9C1); break; + case x86_EDX: PUTDST16(RecompPos,0xEAC1); break; + case x86_ESI: PUTDST16(RecompPos,0xEEC1); break; + case x86_EDI: PUTDST16(RecompPos,0xEFC1); break; + case x86_ESP: PUTDST16(RecompPos,0xECC1); break; + case x86_EBP: PUTDST16(RecompPos,0xEDC1); break; + } + PUTDST8(RecompPos,Immediate); +} + +void ShiftRightUnsignVariableImmed(void *Variable, char *VariableName, BYTE Immediate) { + CPU_Message(" shr dword ptr [%s], %Xh",VariableName, Immediate); + + PUTDST16(RecompPos,0x2DC1) + PUTDST32(RecompPos, Variable); + PUTDST8(RecompPos,Immediate); +} + +void SubConstFromVariable (DWORD Const, void *Variable, char *VariableName) { + CPU_Message(" sub dword ptr [%s], 0x%X",VariableName, Const);\ + PUTDST16(RecompPos,0x2D81); + PUTDST32(RecompPos,Variable); + PUTDST32(RecompPos,Const); +} + +void SubConstFromX86Reg (int x86Reg, DWORD Const) { + CPU_Message(" sub %s, %Xh",x86_Name(x86Reg),Const); + if ((Const & 0xFFFFFF80) != 0 && (Const & 0xFFFFFF80) != 0xFFFFFF80) { + switch (x86Reg) { + case x86_EAX: PUTDST16(RecompPos,0xE881); break; + case x86_EBX: PUTDST16(RecompPos,0xEB81); break; + case x86_ECX: PUTDST16(RecompPos,0xE981); break; + case x86_EDX: PUTDST16(RecompPos,0xEA81); break; + case x86_ESI: PUTDST16(RecompPos,0xEE81); break; + case x86_EDI: PUTDST16(RecompPos,0xEF81); break; + case x86_ESP: PUTDST16(RecompPos,0xEC81); break; + case x86_EBP: PUTDST16(RecompPos,0xED81); break; + } + PUTDST32(RecompPos, Const); + } else { + switch (x86Reg) { + case x86_EAX: PUTDST16(RecompPos,0xE883); break; + case x86_EBX: PUTDST16(RecompPos,0xEB83); break; + case x86_ECX: PUTDST16(RecompPos,0xE983); break; + case x86_EDX: PUTDST16(RecompPos,0xEA83); break; + case x86_ESI: PUTDST16(RecompPos,0xEE83); break; + case x86_EDI: PUTDST16(RecompPos,0xEF83); break; + case x86_ESP: PUTDST16(RecompPos,0xEC83); break; + case x86_EBP: PUTDST16(RecompPos,0xED83); break; + } + PUTDST8(RecompPos, Const); + } +} + +void SubVariableFromX86reg(int x86reg, void * Variable, char * VariableName) { + CPU_Message(" sub %s, dword ptr [%s]",x86_Name(x86reg),VariableName); + switch (x86reg) { + case x86_EAX: PUTDST16(RecompPos,0x052B); break; + case x86_EBX: PUTDST16(RecompPos,0x1D2B); break; + case x86_ECX: PUTDST16(RecompPos,0x0D2B); break; + case x86_EDX: PUTDST16(RecompPos,0x152B); break; + case x86_ESI: PUTDST16(RecompPos,0x352B); break; + case x86_EDI: PUTDST16(RecompPos,0x3D2B); break; + case x86_ESP: PUTDST16(RecompPos,0x252B); break; + case x86_EBP: PUTDST16(RecompPos,0x2D2B); break; + default: + DisplayError("SubVariableFromX86reg\nUnknown x86 Register"); + } + PUTDST32(RecompPos,Variable); +} + +void SubX86regFromVariable(int x86reg, void * Variable, char * VariableName) { + CPU_Message(" sub dword ptr [%s], %s",VariableName, x86_Name(x86reg)); + switch (x86reg) { + case x86_EAX: PUTDST16(RecompPos,0x0529); break; + case x86_EBX: PUTDST16(RecompPos,0x1D29); break; + case x86_ECX: PUTDST16(RecompPos,0x0D29); break; + case x86_EDX: PUTDST16(RecompPos,0x1529); break; + case x86_ESI: PUTDST16(RecompPos,0x3529); break; + case x86_EDI: PUTDST16(RecompPos,0x3D29); break; + case x86_ESP: PUTDST16(RecompPos,0x2529); break; + case x86_EBP: PUTDST16(RecompPos,0x2D29); break; + default: + DisplayError("SubX86regFromVariable\nUnknown x86 Register"); + } + PUTDST32(RecompPos,Variable); +} + +void SubX86RegToX86Reg(int Destination, int Source) { + WORD x86Command; + CPU_Message(" sub %s, %s",x86_Name(Destination),x86_Name(Source)); + switch (Source) { + case x86_EAX: x86Command = 0x002B; break; + case x86_EBX: x86Command = 0x032B; break; + case x86_ECX: x86Command = 0x012B; break; + case x86_EDX: x86Command = 0x022B; break; + case x86_ESI: x86Command = 0x062B; break; + case x86_EDI: x86Command = 0x072B; break; + case x86_ESP: x86Command = 0x042B; break; + case x86_EBP: x86Command = 0x052B; break; + } + switch (Destination) { + case x86_EAX: x86Command += 0xC000; break; + case x86_EBX: x86Command += 0xD800; break; + case x86_ECX: x86Command += 0xC800; break; + case x86_EDX: x86Command += 0xD000; break; + case x86_ESI: x86Command += 0xF000; break; + case x86_EDI: x86Command += 0xF800; break; + case x86_ESP: x86Command += 0xE000; break; + case x86_EBP: x86Command += 0xE800; break; + } + PUTDST16(RecompPos,x86Command); +} + +void SbbX86RegToX86Reg(int Destination, int Source) { + WORD x86Command; + CPU_Message(" sbb %s, %s",x86_Name(Destination),x86_Name(Source)); + switch (Source) { + case x86_EAX: x86Command = 0x001B; break; + case x86_EBX: x86Command = 0x031B; break; + case x86_ECX: x86Command = 0x011B; break; + case x86_EDX: x86Command = 0x021B; break; + case x86_ESI: x86Command = 0x061B; break; + case x86_EDI: x86Command = 0x071B; break; + case x86_ESP: x86Command = 0x041B; break; + case x86_EBP: x86Command = 0x051B; break; + } + switch (Destination) { + case x86_EAX: x86Command += 0xC000; break; + case x86_EBX: x86Command += 0xD800; break; + case x86_ECX: x86Command += 0xC800; break; + case x86_EDX: x86Command += 0xD000; break; + case x86_ESI: x86Command += 0xF000; break; + case x86_EDI: x86Command += 0xF800; break; + case x86_ESP: x86Command += 0xE000; break; + case x86_EBP: x86Command += 0xE800; break; + } + PUTDST16(RecompPos,x86Command); +} + +void TestConstToVariable(DWORD Const, void * Variable, char * VariableName) { + CPU_Message(" test dword ptr [%s], 0x%X",VariableName, Const); + PUTDST16(RecompPos,0x05F7); + PUTDST32(RecompPos,Variable); + PUTDST32(RecompPos,Const); +} + +void TestConstToX86Reg(DWORD Const, int x86reg) { + CPU_Message(" test %s, 0x%X",x86_Name(x86reg), Const); + + switch (x86reg) { + case x86_EAX: PUTDST8 (RecompPos,0xA9); break; + case x86_EBX: PUTDST16(RecompPos,0xC3F7); break; + case x86_ECX: PUTDST16(RecompPos,0xC1F7); break; + case x86_EDX: PUTDST16(RecompPos,0xC2F7); break; + case x86_ESI: PUTDST16(RecompPos,0xC6F7); break; + case x86_EDI: PUTDST16(RecompPos,0xC7F7); break; + case x86_ESP: PUTDST16(RecompPos,0xC4F7); break; + case x86_EBP: PUTDST16(RecompPos,0xC5F7); break; + } + PUTDST32(RecompPos,Const); +} + +void TestX86RegToX86Reg(int Destination, int Source) { + WORD x86Command; + + CPU_Message(" test %s, %s",x86_Name(Destination),x86_Name(Source)); + switch (Source) { + case x86_EAX: x86Command = 0x0085; break; + case x86_EBX: x86Command = 0x0385; break; + case x86_ECX: x86Command = 0x0185; break; + case x86_EDX: x86Command = 0x0285; break; + case x86_ESI: x86Command = 0x0685; break; + case x86_EDI: x86Command = 0x0785; break; + case x86_ESP: x86Command = 0x0485; break; + case x86_EBP: x86Command = 0x0585; break; + } + switch (Destination) { + case x86_EAX: x86Command += 0xC000; break; + case x86_EBX: x86Command += 0xD800; break; + case x86_ECX: x86Command += 0xC800; break; + case x86_EDX: x86Command += 0xD000; break; + case x86_ESI: x86Command += 0xF000; break; + case x86_EDI: x86Command += 0xF800; break; + case x86_ESP: x86Command += 0xE000; break; + case x86_EBP: x86Command += 0xE800; break; + } + PUTDST16(RecompPos,x86Command); +} + +void XorConstToX86Reg(int x86Reg, DWORD Const) { + CPU_Message(" xor %s, %Xh",x86_Name(x86Reg),Const); + if ((Const & 0xFFFFFF80) != 0 && (Const & 0xFFFFFF80) != 0xFFFFFF80) { + switch (x86Reg) { + case x86_EAX: PUTDST16(RecompPos,0xF081); break; + case x86_EBX: PUTDST16(RecompPos,0xF381); break; + case x86_ECX: PUTDST16(RecompPos,0xF181); break; + case x86_EDX: PUTDST16(RecompPos,0xF281); break; + case x86_ESI: PUTDST16(RecompPos,0xF681); break; + case x86_EDI: PUTDST16(RecompPos,0xF781); break; + case x86_ESP: PUTDST16(RecompPos,0xF481); break; + case x86_EBP: PUTDST16(RecompPos,0xF581); break; + } + PUTDST32(RecompPos, Const); + } else { + switch (x86Reg) { + case x86_EAX: PUTDST16(RecompPos,0xF083); break; + case x86_EBX: PUTDST16(RecompPos,0xF383); break; + case x86_ECX: PUTDST16(RecompPos,0xF183); break; + case x86_EDX: PUTDST16(RecompPos,0xF283); break; + case x86_ESI: PUTDST16(RecompPos,0xF683); break; + case x86_EDI: PUTDST16(RecompPos,0xF783); break; + case x86_ESP: PUTDST16(RecompPos,0xF483); break; + case x86_EBP: PUTDST16(RecompPos,0xF583); break; + } + PUTDST8(RecompPos, Const); + } +} + +void XorConstToVariable(void *Variable, char *VariableName, DWORD Const) { + + CPU_Message(" xor dword ptr [%s], 0x%X",VariableName, Const); + + PUTDST16(RecompPos, 0x3581); + PUTDST32(RecompPos,Variable); + PUTDST32(RecompPos, Const); +} + +void XorX86RegToX86Reg(int Source, int Destination) { + WORD x86Command; + + CPU_Message(" xor %s, %s",x86_Name(Source),x86_Name(Destination)); + + switch (Source) { + case x86_EAX: x86Command = 0x0031; break; + case x86_EBX: x86Command = 0x0331; break; + case x86_ECX: x86Command = 0x0131; break; + case x86_EDX: x86Command = 0x0231; break; + case x86_ESI: x86Command = 0x0631; break; + case x86_EDI: x86Command = 0x0731; break; + case x86_ESP: x86Command = 0x0431; break; + case x86_EBP: x86Command = 0x0531; break; + } + switch (Destination) { + case x86_EAX: x86Command += 0xC000; break; + case x86_EBX: x86Command += 0xD800; break; + case x86_ECX: x86Command += 0xC800; break; + case x86_EDX: x86Command += 0xD000; break; + case x86_ESI: x86Command += 0xF000; break; + case x86_EDI: x86Command += 0xF800; break; + case x86_ESP: x86Command += 0xE000; break; + case x86_EBP: x86Command += 0xE800; break; + } + PUTDST16(RecompPos,x86Command); +} + +void XorVariableToX86reg(void *Variable, char *VariableName, int x86reg) { + CPU_Message(" xor %s, dword ptr [%s]",x86_Name(x86reg),VariableName); + switch (x86reg) { + case x86_EAX: PUTDST16(RecompPos,0x0533); break; + case x86_EBX: PUTDST16(RecompPos,0x1D33); break; + case x86_ECX: PUTDST16(RecompPos,0x0D33); break; + case x86_EDX: PUTDST16(RecompPos,0x1533); break; + case x86_ESI: PUTDST16(RecompPos,0x3533); break; + case x86_EDI: PUTDST16(RecompPos,0x3D33); break; + case x86_ESP: PUTDST16(RecompPos,0x2533); break; + case x86_EBP: PUTDST16(RecompPos,0x2D33); break; + default: DisplayError("XorVariableToX86reg\nUnknown x86 Register"); + } + PUTDST32(RecompPos,Variable); +} + +void XorX86RegToVariable(void *Variable, char *VariableName, int x86reg) { + CPU_Message(" xor dword ptr [%s], %s",VariableName, x86_Name(x86reg)); + switch (x86reg) { + case x86_EAX: PUTDST16(RecompPos,0x0531); break; + case x86_EBX: PUTDST16(RecompPos,0x1D31); break; + case x86_ECX: PUTDST16(RecompPos,0x0D31); break; + case x86_EDX: PUTDST16(RecompPos,0x1531); break; + case x86_ESI: PUTDST16(RecompPos,0x3531); break; + case x86_EDI: PUTDST16(RecompPos,0x3D31); break; + case x86_ESP: PUTDST16(RecompPos,0x2531); break; + case x86_EBP: PUTDST16(RecompPos,0x2D31); break; + default: DisplayError("XorX86RegToVariable\nUnknown x86 Register"); + } + PUTDST32(RecompPos,Variable); +} diff --git a/Source/RSP/X86.h b/Source/RSP/X86.h new file mode 100644 index 000000000..e054a65f0 --- /dev/null +++ b/Source/RSP/X86.h @@ -0,0 +1,262 @@ +/* + * RSP Compiler plug in for Project 64 (A Nintendo 64 emulator). + * + * (c) Copyright 2001 jabo (jabo@emulation64.com) and + * zilmar (zilmar@emulation64.com) + * + * pj64 homepage: www.pj64.net + * + * Permission to use, copy, modify and distribute Project64 in both binary and + * source form, for non-commercial purposes, is hereby granted without fee, + * providing that this license information and copyright notice appear with + * all copies and any derived work. + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event shall the authors be held liable for any damages + * arising from the use of this software. + * + * Project64 is freeware for PERSONAL USE only. Commercial users should + * seek permission of the copyright holders first. Commercial use includes + * charging money for Project64 or software derived from Project64. + * + * The copyright holders request that bug fixes and improvements to the code + * should be forwarded to them so if they want them. + * + */ + +enum x86RegValues { + x86_EAX = 0, x86_EBX = 1, x86_ECX = 2, x86_EDX = 3, + x86_ESI = 4, x86_EDI = 5, x86_EBP = 6, x86_ESP = 7 +}; + +enum mmxRegValues { + x86_MM0 = 0, x86_MM1 = 1, x86_MM2 = 2, x86_MM3 = 3, + x86_MM4 = 4, x86_MM5 = 5, x86_MM6 = 6, x86_MM7 = 7 +}; + +enum sseRegValues { + x86_XMM0 = 0, x86_XMM1 = 1, x86_XMM2 = 2, x86_XMM3 = 3, + x86_XMM4 = 4, x86_XMM5 = 5, x86_XMM6 = 6, x86_XMM7 = 7 +}; + +void AdcX86RegToX86Reg ( int Destination, int Source ); +void AdcX86regToVariable ( int x86reg, void * Variable, char * VariableName ); +void AdcX86regHalfToVariable ( int x86reg, void * Variable, char * VariableName ); +void AdcConstToX86reg ( BYTE Constant, int x86reg ); +void AdcConstToVariable ( void *Variable, char *VariableName, BYTE Constant ); +void AdcConstHalfToVariable ( void *Variable, char *VariableName, BYTE Constant ); +void AddConstToVariable ( DWORD Const, void *Variable, char *VariableName ); +void AddConstToX86Reg ( int x86Reg, DWORD Const ); +void AddVariableToX86reg ( int x86reg, void * Variable, char * VariableName ); +void AddX86regToVariable ( int x86reg, void * Variable, char * VariableName ); +void AddX86regHalfToVariable ( int x86reg, void * Variable, char * VariableName ); +void AddX86RegToX86Reg ( int Destination, int Source ); +void AndConstToVariable ( DWORD Const, void *Variable, char *VariableName ); +void AndConstToX86Reg ( int x86Reg, DWORD Const ); +void AndVariableToX86Reg ( void * Variable, char * VariableName, int x86Reg ); +void AndVariableToX86regHalf ( void * Variable, char * VariableName, int x86Reg ); +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 Call_Direct ( void * FunctAddress, char * FunctName ); +void Call_Indirect ( void * FunctAddress, char * FunctName ); +void CondMoveEqual ( int Destination, int Source ); +void CondMoveNotEqual ( int Destination, int Source ); +void CondMoveGreater ( int Destination, int Source ); +void CondMoveGreaterEqual ( int Destination, int Source ); +void CondMoveLess ( int Destination, int Source ); +void CondMoveLessEqual ( int Destination, int Source ); +void CompConstToVariable ( DWORD Const, void * Variable, char * VariableName ); +void CompConstHalfToVariable ( WORD Const, void * Variable, char * VariableName ); +void CompConstToX86reg ( int x86Reg, DWORD Const ); +void CompX86regToVariable ( int x86Reg, void * Variable, char * VariableName ); +void CompVariableToX86reg ( int x86Reg, void * Variable, char * VariableName ); +void CompX86RegToX86Reg ( int Destination, int Source ); +void Cwd ( void ); +void Cwde ( void ); +void DecX86reg ( int x86Reg ); +void DivX86reg ( int x86reg ); +void idivX86reg ( int x86reg ); +void imulX86reg ( int x86reg ); +void ImulX86RegToX86Reg ( int Destination, int Source ); +void IncX86reg ( int x86Reg ); +void JaeLabel32 ( char * Label, DWORD Value ); +void JaLabel8 ( char * Label, BYTE Value ); +void JaLabel32 ( char * Label, DWORD Value ); +void JbLabel8 ( char * Label, BYTE Value ); +void JbLabel32 ( char * Label, DWORD Value ); +void JeLabel8 ( char * Label, BYTE Value ); +void JeLabel32 ( char * Label, DWORD Value ); +void JgeLabel8 ( char * Label, BYTE Value ); +void JgeLabel32 ( char * Label, DWORD Value ); +void JgLabel8 ( char * Label, BYTE Value ); +void JgLabel32 ( char * Label, DWORD Value ); +void JleLabel8 ( char * Label, BYTE Value ); +void JleLabel32 ( char * Label, DWORD Value ); +void JlLabel8 ( char * Label, BYTE Value ); +void JlLabel32 ( char * Label, DWORD Value ); +void JumpX86Reg ( int x86reg ); +void JmpLabel8 ( char * Label, BYTE Value ); +void JmpLabel32 ( char * Label, DWORD Value ); +void JneLabel8 ( char * Label, BYTE Value ); +void JneLabel32 ( char * Label, DWORD Value ); +void JnsLabel8 ( char * Label, BYTE Value ); +void JnsLabel32 ( char * Label, DWORD Value ); +void JsLabel32 ( char * Label, DWORD Value ); +void LeaSourceAndOffset ( int x86DestReg, int x86SourceReg, int offset ); +void MoveConstByteToN64Mem ( BYTE Const, int AddrReg ); +void MoveConstHalfToN64Mem ( WORD Const, int AddrReg ); +void MoveConstByteToVariable ( BYTE Const,void *Variable, char *VariableName ); +void MoveConstHalfToVariable ( WORD Const, void *Variable, char *VariableName ); +void MoveConstToN64Mem ( DWORD Const, int AddrReg ); +void MoveConstToN64MemDisp ( DWORD Const, int AddrReg, BYTE Disp ); +void MoveConstToVariable ( DWORD Const, void *Variable, char *VariableName ); +void MoveConstToX86reg ( DWORD Const, int x86reg ); +void MoveOffsetToX86reg ( DWORD Const, char * VariableName, int x86reg ); +void MoveX86regByteToX86regPointer ( int Source, int AddrReg ); +void MoveX86regHalfToX86regPointer ( int Source, int AddrReg ); +void MoveX86regHalfToX86regPointerDisp ( int Source, int AddrReg, BYTE Disp); +void MoveX86regToX86regPointer ( int Source, int AddrReg ); +void MoveX86RegToX86regPointerDisp ( int Source, int AddrReg, BYTE Disp ); +void MoveX86regPointerToX86regByte ( int Destination, int AddrReg ); +void MoveX86regPointerToX86regHalf ( int Destination, int AddrReg ); +void MoveX86regPointerToX86reg ( int Destination, int AddrReg ); +void MoveN64MemDispToX86reg ( int x86reg, int AddrReg, BYTE Disp ); +void MoveN64MemToX86reg ( int x86reg, int AddrReg ); +void MoveN64MemToX86regByte ( int x86reg, int AddrReg ); +void MoveN64MemToX86regHalf ( int x86reg, int AddrReg ); +void MoveX86regByteToN64Mem ( int x86reg, int AddrReg ); +void MoveX86regByteToVariable ( int x86reg, void * Variable, char * VariableName ); +void MoveX86regHalfToN64Mem ( int x86reg, int AddrReg ); +void MoveX86regHalfToVariable ( int x86reg, void * Variable, char * VariableName ); +void MoveX86regToN64Mem ( int x86reg, int AddrReg ); +void MoveX86regToN64MemDisp ( int x86reg, int AddrReg, BYTE Disp ); +void MoveX86regToVariable ( int x86reg, void * Variable, char * VariableName ); +void MoveX86RegToX86Reg ( int Source, int Destination ); +void MoveVariableToX86reg ( void *Variable, char *VariableName, int x86reg ); +void MoveVariableToX86regByte ( void *Variable, char *VariableName, int x86reg ); +void MoveVariableToX86regHalf ( void *Variable, char *VariableName, int x86reg ); +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 MoveSxVariableToX86regHalf ( void *Variable, char *VariableName, int x86reg ); +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 MoveZxVariableToX86regHalf ( void *Variable, char *VariableName, int x86reg ); +void MulX86reg ( int x86reg ); +void NegateX86reg ( int x86reg ); +void OrConstToVariable ( DWORD Const, void * Variable, char * VariableName ); +void OrConstToX86Reg ( DWORD Const, int x86Reg ); +void OrVariableToX86Reg ( void * Variable, char * VariableName, int x86Reg ); +void OrVariableToX86regHalf ( void * Variable, char * VariableName, int x86Reg ); +void OrX86RegToVariable ( void * Variable, char * VariableName, int x86Reg ); +void OrX86RegToX86Reg ( int Destination, int Source ); +void Popad ( void ); +void Pushad ( void ); +void Push ( int x86reg ); +void Pop ( int x86reg ); +void PushImm32 ( char * String, DWORD Value ); +void Ret ( void ); +void Seta ( int x86reg ); +void Setae ( int x86reg ); +void Setl ( int x86reg ); +void Setb ( int x86reg ); +void Setg ( int x86reg ); +void Setz ( int x86reg ); +void Setnz ( int x86reg ); +void SetlVariable ( void * Variable, char * VariableName ); +void SetleVariable ( void * Variable, char * VariableName ); +void SetgVariable ( void * Variable, char * VariableName ); +void SetgeVariable ( void * Variable, char * VariableName ); +void SetbVariable ( void * Variable, char * VariableName ); +void SetaVariable ( void * Variable, char * VariableName ); +void SetzVariable ( void * Variable, char * VariableName ); +void SetnzVariable ( void * Variable, char * VariableName ); +void ShiftLeftSign ( int x86reg ); +void ShiftLeftSignImmed ( int x86reg, BYTE Immediate ); +void ShiftLeftSignVariableImmed ( void *Variable, char *VariableName, BYTE Immediate ); +void ShiftRightSignImmed ( int x86reg, BYTE Immediate ); +void ShiftRightSignVariableImmed ( void *Variable, char *VariableName, BYTE Immediate ); +void ShiftRightUnsign ( int x86reg ); +void ShiftRightUnsignImmed ( int x86reg, BYTE Immediate ); +void ShiftRightUnsignVariableImmed ( void *Variable, char *VariableName, BYTE Immediate ); +void ShiftLeftDoubleImmed ( int Destination, int Source, BYTE Immediate ); +void ShiftRightDoubleImmed ( int Destination, int Source, BYTE Immediate ); +void SubConstFromVariable ( DWORD Const, void *Variable, char *VariableName ); +void SubConstFromX86Reg ( int x86Reg, DWORD Const ); +void SubVariableFromX86reg ( int x86reg, void * Variable, char * VariableName ); +void SubX86RegToX86Reg ( int Destination, int Source ); +void SubX86regFromVariable ( int x86reg, void * Variable, char * VariableName ); +void SbbX86RegToX86Reg ( int Destination, int Source ); +void TestConstToVariable ( DWORD Const, void * Variable, char * VariableName ); +void TestConstToX86Reg ( DWORD Const, int x86reg ); +void TestX86RegToX86Reg ( int Destination, int Source ); +void XorConstToX86Reg ( int x86Reg, DWORD Const ); +void XorX86RegToX86Reg ( int Source, int Destination ); +void XorVariableToX86reg ( void *Variable, char *VariableName, int x86reg ); +void XorX86RegToVariable ( void *Variable, char *VariableName, int x86reg ); +void XorConstToVariable ( void *Variable, char *VariableName, DWORD Const ); + +#define _MMX_SHUFFLE(a, b, c, d) \ + ((BYTE)(((a) << 6) | ((b) << 4) | ((c) << 2) | (d))) + +void MmxMoveRegToReg ( int Dest, int Source ); +void MmxMoveQwordRegToVariable ( int Dest, void *Variable, char *VariableName ); +void MmxMoveQwordVariableToReg ( int Dest, void *Variable, char *VariableName ); +void MmxPandRegToReg ( int Dest, int Source ); +void MmxPandnRegToReg ( int Dest, int Source ); +void MmxPandVariableToReg ( void * Variable, char * VariableName, int Dest ); +void MmxPorRegToReg ( int Dest, int Source ); +void MmxPorVariableToReg ( void * Variable, char * VariableName, int Dest ); +void MmxXorRegToReg ( int Dest, int Source ); +void MmxShuffleMemoryToReg ( int Dest, void * Variable, char * VariableName, BYTE Immed ); +void MmxPmullwRegToReg ( int Dest, int Source ); +void MmxPmullwVariableToReg ( int Dest, void * Variable, char * VariableName ); +void MmxPmulhuwRegToReg ( int Dest, int Source ); +void MmxPmulhwRegToReg ( int Dest, int Source ); +void MmxPmulhwRegToVariable ( int Dest, void * Variable, char * VariableName ); +void MmxPsrlwImmed ( int Dest, BYTE Immed ); +void MmxPsrawImmed ( int Dest, BYTE Immed ); +void MmxPsllwImmed ( int Dest, BYTE Immed ); +void MmxPaddswRegToReg ( int Dest, int Source ); +void MmxPaddswVariableToReg ( int Dest, void * Variable, char * VariableName ); +void MmxPaddwRegToReg ( int Dest, int Source ); +void MmxPsubswVariableToReg ( int Dest, void * Variable, char * VariableName ); +void MmxPsubswRegToReg ( int Dest, int Source ); +void MmxPackSignedDwords ( int Dest, int Source ); +void MmxUnpackLowWord ( int Dest, int Source ); +void MmxUnpackHighWord ( int Dest, int Source ); +void MmxCompareGreaterWordRegToReg ( int Dest, int Source ); +void MmxEmptyMultimediaState ( void ); + +void SseMoveAlignedVariableToReg ( void *Variable, char *VariableName, int sseReg ); +void SseMoveAlignedRegToVariable ( int sseReg, void *Variable, char *VariableName ); +void SseMoveAlignedN64MemToReg ( int sseReg, int AddrReg ); +void SseMoveAlignedRegToN64Mem ( int sseReg, int AddrReg ); +void SseMoveUnalignedVariableToReg ( void *Variable, char *VariableName, int sseReg ); +void SseMoveUnalignedRegToVariable ( int sseReg, void *Variable, char *VariableName ); +void SseMoveUnalignedN64MemToReg ( int sseReg, int AddrReg ); +void SseMoveUnalignedRegToN64Mem ( int sseReg, int AddrReg ); +void SseMoveRegToReg ( int Dest, int Source ); +void SseXorRegToReg ( int Dest, int Source ); + +typedef struct { + union { + struct { + unsigned Reg0 : 2; + unsigned Reg1 : 2; + unsigned Reg2 : 2; + unsigned Reg3 : 2; + }; + unsigned UB:8; + }; +} SHUFFLE; + +void SseShuffleReg ( int Dest, int Source, BYTE Immed ); + +void x86_SetBranch32b(void * JumpByte, void * Destination); +void x86_SetBranch8b(void * JumpByte, void * Destination); \ No newline at end of file diff --git a/Source/RSP/breakpoint.c b/Source/RSP/breakpoint.c new file mode 100644 index 000000000..3b57c4534 --- /dev/null +++ b/Source/RSP/breakpoint.c @@ -0,0 +1,163 @@ +/* + * RSP Compiler plug in for Project 64 (A Nintendo 64 emulator). + * + * (c) Copyright 2001 jabo (jabo@emulation64.com) and + * zilmar (zilmar@emulation64.com) + * + * pj64 homepage: www.pj64.net + * + * Permission to use, copy, modify and distribute Project64 in both binary and + * source form, for non-commercial purposes, is hereby granted without fee, + * providing that this license information and copyright notice appear with + * all copies and any derived work. + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event shall the authors be held liable for any damages + * arising from the use of this software. + * + * Project64 is freeware for PERSONAL USE only. Commercial users should + * seek permission of the copyright holders first. Commercial use includes + * charging money for Project64 or software derived from Project64. + * + * The copyright holders request that bug fixes and improvements to the code + * should be forwarded to them so if they want them. + * + */ + +#include +#include +#include "rsp.h" +#include "CPU.h" +#include "breakpoint.h" + +#define IDC_LOCATION_EDIT 105 +HWND BPoint_Win_hDlg, hRSPLocation = NULL; + +void Add_BPoint ( void ) { + char Title[10]; + + GetWindowText(hRSPLocation,Title,sizeof(Title)); + if (!AddRSP_BPoint(AsciiToHex(Title),TRUE )) { + SendMessage(hRSPLocation,EM_SETSEL,(WPARAM)0,(LPARAM)-1); + SetFocus(hRSPLocation); + } +} + +int AddRSP_BPoint( DWORD Location, int Confirm ) { + int count; + + if (NoOfBpoints == MaxBPoints) { + DisplayError("Max amount of Break Points set"); + return FALSE; + } + + for (count = 0; count < NoOfBpoints; count ++) { + if (BPoint[count].Location == Location) { + DisplayError("You already have this Break Point"); + return FALSE; + } + } + + if (Confirm) { + char Message[150]; + int Response; + + sprintf(Message,"Break when:\n\nRSP's Program Counter = 0x%03X\n\nIs this correct?", + Location); + Response = MessageBox(BPoint_Win_hDlg, Message, "Breakpoint", MB_YESNO | MB_ICONINFORMATION); + if (Response == IDNO) { + return FALSE; + } + } + BPoint[NoOfBpoints].Location = Location; + NoOfBpoints += 1; + if (DebugInfo.UpdateBreakPoints) + { + DebugInfo.UpdateBreakPoints(); + } + return TRUE; +} + +int CheckForRSPBPoint ( DWORD Location ) { + int count; + + for (count = 0; count < NoOfBpoints; count ++){ + if (BPoint[count].Location == Location) { + return TRUE; + } + } + return FALSE; +} + +void CreateBPPanel ( HWND hDlg, RECT rcBox ) { + if (hRSPLocation != NULL) { return; } + + BPoint_Win_hDlg = hDlg; + + hRSPLocation = CreateWindowEx(0,"EDIT","", WS_CHILD | WS_BORDER | ES_UPPERCASE | WS_TABSTOP, + 83,90,100,17,hDlg,(HMENU)IDC_LOCATION_EDIT,RSPInfo.hInst,NULL); + if (hRSPLocation) { + char Title[20]; + SendMessage(hRSPLocation,WM_SETFONT,(WPARAM)GetStockObject(DEFAULT_GUI_FONT),0); + SendMessage(hRSPLocation,EM_SETLIMITTEXT,(WPARAM)3,(LPARAM)0); + sprintf(Title,"%03X",*PrgCount); + SetWindowText(hRSPLocation,Title); + } +} + +void HideBPPanel ( void ) { + ShowWindow(hRSPLocation,FALSE); +} + +void PaintBPPanel ( PAINTSTRUCT ps ) { + TextOut( ps.hdc, 29,60,"Break when the Program Counter equals",37); + TextOut( ps.hdc, 59,85,"0x",2); +} + +void ShowBPPanel ( void ) { + ShowWindow(hRSPLocation,TRUE); +} + +void RefreshBpoints ( HWND hList ) { + char Message[100]; + int count, location; + + for (count = 0; count < NoOfBpoints; count ++ ) { + sprintf(Message," at 0x%03X (RSP)", BPoint[count].Location); + location = SendMessage(hList,LB_ADDSTRING,0,(LPARAM)Message); + SendMessage(hList,LB_SETITEMDATA,(WPARAM)location,(LPARAM)BPoint[count].Location); + } +} + +void RemoveAllBpoint ( void ) { + NoOfBpoints = 0; +} + +void RemoveBpoint ( HWND hList, int index ) { + DWORD location; + + location = SendMessage(hList,LB_GETITEMDATA,(WPARAM)index,0); + RemoveRSPBreakPoint(location); +} + +void RemoveRSPBreakPoint (DWORD Location) { + int count, location = -1; + + for (count = 0; count < NoOfBpoints; count ++){ + if (BPoint[count].Location == Location) { + location = count; + count = NoOfBpoints; + } + } + + if (location >= 0) { + for (count = location; count < NoOfBpoints - 1; count ++ ){ + BPoint[count].Location = BPoint[count + 1].Location; + } + NoOfBpoints -= 1; + if (DebugInfo.UpdateBreakPoints) + { + DebugInfo.UpdateBreakPoints(); + } + } +} diff --git a/Source/RSP/breakpoint.h b/Source/RSP/breakpoint.h new file mode 100644 index 000000000..8a4933f66 --- /dev/null +++ b/Source/RSP/breakpoint.h @@ -0,0 +1,48 @@ +/* + * RSP Compiler plug in for Project 64 (A Nintendo 64 emulator). + * + * (c) Copyright 2001 jabo (jabo@emulation64.com) and + * zilmar (zilmar@emulation64.com) + * + * pj64 homepage: www.pj64.net + * + * Permission to use, copy, modify and distribute Project64 in both binary and + * source form, for non-commercial purposes, is hereby granted without fee, + * providing that this license information and copyright notice appear with + * all copies and any derived work. + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event shall the authors be held liable for any damages + * arising from the use of this software. + * + * Project64 is freeware for PERSONAL USE only. Commercial users should + * seek permission of the copyright holders first. Commercial use includes + * charging money for Project64 or software derived from Project64. + * + * The copyright holders request that bug fixes and improvements to the code + * should be forwarded to them so if they want them. + * + */ + +#define MaxBPoints 0x30 + +typedef struct { + unsigned int Location; +} BPOINT; + +BPOINT BPoint[MaxBPoints]; +int NoOfBpoints; + +void Add_BPoint ( void ); +void CreateBPPanel ( HWND hDlg, RECT rcBox ); +void HideBPPanel ( void ); +void PaintBPPanel ( PAINTSTRUCT ps ); +void ShowBPPanel ( void ); +void RefreshBpoints ( HWND hList ); +void RemoveBpoint ( HWND hList, int index ); +void RemoveAllBpoint ( void ); + +int AddRSP_BPoint ( DWORD Location, int Confirm ); +int CheckForRSPBPoint ( DWORD Location ); +void RemoveRSPBreakPoint (DWORD Location); + diff --git a/Source/RSP/dma.c b/Source/RSP/dma.c new file mode 100644 index 000000000..50cd378b9 --- /dev/null +++ b/Source/RSP/dma.c @@ -0,0 +1,143 @@ +/* + * RSP Compiler plug in for Project 64 (A Nintendo 64 emulator). + * + * (c) Copyright 2001 jabo (jabo@emulation64.com) and + * zilmar (zilmar@emulation64.com) + * + * pj64 homepage: www.pj64.net + * + * Permission to use, copy, modify and distribute Project64 in both binary and + * source form, for non-commercial purposes, is hereby granted without fee, + * providing that this license information and copyright notice appear with + * all copies and any derived work. + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event shall the authors be held liable for any damages + * arising from the use of this software. + * + * Project64 is freeware for PERSONAL USE only. Commercial users should + * seek permission of the copyright holders first. Commercial use includes + * charging money for Project64 or software derived from Project64. + * + * The copyright holders request that bug fixes and improvements to the code + * should be forwarded to them so if they want them. + * + */ + +#include +#include +#include "RSP.h" +#include "RSP Registers.h" +#include "memory.h" + +// #define RSP_SAFE_DMA /* unoptimized dma transfers */ + +void SP_DMA_READ (void) { + DWORD i, j, Length, Skip, Count, End; + BYTE *Dest, *Source; + + *RSPInfo.SP_DRAM_ADDR_REG &= 0x00FFFFFF; + + if (*RSPInfo.SP_DRAM_ADDR_REG > 0x800000) { + MessageBox(NULL,"SP DMA READ\nSP_DRAM_ADDR_REG not in RDRam space","Error",MB_OK); + return; + } + + if ((*RSPInfo.SP_RD_LEN_REG & 0xFFF) + 1 + (*RSPInfo.SP_MEM_ADDR_REG & 0xFFF) > 0x1000) { + MessageBox(NULL,"SP DMA READ\ncould not fit copy in memory segement","Error",MB_OK); + return; + } + + Length = ((*RSPInfo.SP_RD_LEN_REG & 0xFFF) | 7) + 1; + Skip = (*RSPInfo.SP_RD_LEN_REG >> 20) + Length; + Count = ((*RSPInfo.SP_RD_LEN_REG >> 12) & 0xFF) + 1; + End = ((*RSPInfo.SP_MEM_ADDR_REG & 0x0FFF) & ~7) + (((Count - 1) * Skip) + Length); + + if ((*RSPInfo.SP_MEM_ADDR_REG & 0x1000) != 0) { + Dest = RSPInfo.IMEM + ((*RSPInfo.SP_MEM_ADDR_REG & 0x0FFF) & ~7); + } else { + Dest = RSPInfo.DMEM + ((*RSPInfo.SP_MEM_ADDR_REG & 0x0FFF) & ~7); + } + Source = RSPInfo.RDRAM + (*RSPInfo.SP_DRAM_ADDR_REG & ~7); + +#if defined(RSP_SAFE_DMA) + for (j = 0 ; j < Count; j++) { + for (i = 0 ; i < Length; i++) { + *(BYTE *)(((DWORD)Dest + j * Length + i) ^ 3) = *(BYTE *)(((DWORD)Source + j * Skip + i) ^ 3); + } + } +#else + if ((Skip & 0x3) == 0) { + for (j = 0; j < Count; j++) { + memcpy(Dest, Source, Length); + Source += Skip; + Dest += Length; + } + } else { + for (j = 0 ; j < Count; j++) { + for (i = 0 ; i < Length; i++) { + *(BYTE *)(((DWORD)Dest + i) ^ 3) = *(BYTE *)(((DWORD)Source + i) ^ 3); + } + Source += Skip; + Dest += Length; + } + } +#endif + + /* FIXME: could this be a problem DMEM to IMEM (?) */ + if (CPUCore == RecompilerCPU && (*RSPInfo.SP_MEM_ADDR_REG & 0x1000) != 0) { + SetJumpTable(End); + } + + *RSPInfo.SP_DMA_BUSY_REG = 0; + *RSPInfo.SP_STATUS_REG &= ~SP_STATUS_DMA_BUSY; +} + +void SP_DMA_WRITE (void) { + DWORD i, j, Length, Skip, Count; + BYTE *Dest, *Source; + + *RSPInfo.SP_DRAM_ADDR_REG &= 0x00FFFFFF; + + if (*RSPInfo.SP_DRAM_ADDR_REG > 0x800000) { + MessageBox(NULL,"SP DMA WRITE\nSP_DRAM_ADDR_REG not in RDRam space","Error",MB_OK); + return; + } + + if ((*RSPInfo.SP_WR_LEN_REG & 0xFFF) + 1 + (*RSPInfo.SP_MEM_ADDR_REG & 0xFFF) > 0x1000) { + MessageBox(NULL,"SP DMA WRITE\ncould not fit copy in memory segement","Error",MB_OK); + return; + } + + Length = ((*RSPInfo.SP_WR_LEN_REG & 0xFFF) | 7) + 1; + Skip = (*RSPInfo.SP_WR_LEN_REG >> 20) + Length; + Count = ((*RSPInfo.SP_WR_LEN_REG >> 12) & 0xFF) + 1; + Dest = RSPInfo.RDRAM + (*RSPInfo.SP_DRAM_ADDR_REG & ~7); + Source = RSPInfo.DMEM + ((*RSPInfo.SP_MEM_ADDR_REG & 0x1FFF) & ~7); + +#if defined(RSP_SAFE_DMA) + for (j = 0 ; j < Count; j++) { + for (i = 0 ; i < Length; i++) { + *(BYTE *)(((DWORD)Dest + j * Skip + i) ^ 3) = *(BYTE *)(((DWORD)Source + j * Length + i) ^ 3); + } + } +#else + if ((Skip & 0x3) == 0) { + for (j = 0; j < Count; j++) { + memcpy(Dest, Source, Length); + Source += Length; + Dest += Skip; + } + } else { + for (j = 0 ; j < Count; j++) { + for (i = 0 ; i < Length; i++) { + *(BYTE *)(((DWORD)Dest + i) ^ 3) = *(BYTE *)(((DWORD)Source + i) ^ 3); + } + Source += Length; + Dest += Skip; + } + } +#endif + *RSPInfo.SP_DMA_BUSY_REG = 0; + *RSPInfo.SP_STATUS_REG &= ~SP_STATUS_DMA_BUSY; +} diff --git a/Source/RSP/dma.h b/Source/RSP/dma.h new file mode 100644 index 000000000..698bac5d5 --- /dev/null +++ b/Source/RSP/dma.h @@ -0,0 +1,29 @@ +/* + * RSP Compiler plug in for Project 64 (A Nintendo 64 emulator). + * + * (c) Copyright 2001 jabo (jabo@emulation64.com) and + * zilmar (zilmar@emulation64.com) + * + * pj64 homepage: www.pj64.net + * + * Permission to use, copy, modify and distribute Project64 in both binary and + * source form, for non-commercial purposes, is hereby granted without fee, + * providing that this license information and copyright notice appear with + * all copies and any derived work. + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event shall the authors be held liable for any damages + * arising from the use of this software. + * + * Project64 is freeware for PERSONAL USE only. Commercial users should + * seek permission of the copyright holders first. Commercial use includes + * charging money for Project64 or software derived from Project64. + * + * The copyright holders request that bug fixes and improvements to the code + * should be forwarded to them so if they want them. + * + */ + +void SP_DMA_READ ( void ); +void SP_DMA_WRITE ( void ); + diff --git a/Source/RSP/log.cpp b/Source/RSP/log.cpp new file mode 100644 index 000000000..cf0625334 --- /dev/null +++ b/Source/RSP/log.cpp @@ -0,0 +1,309 @@ +/* + * RSP Compiler plug in for Project 64 (A Nintendo 64 emulator). + * + * (c) Copyright 2001 jabo (jabo@emulation64.com) and + * zilmar (zilmar@emulation64.com) + * + * pj64 homepage: www.pj64.net + * + * Permission to use, copy, modify and distribute Project64 in both binary and + * source form, for non-commercial purposes, is hereby granted without fee, + * providing that this license information and copyright notice appear with + * all copies and any derived work. + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event shall the authors be held liable for any damages + * arising from the use of this software. + * + * Project64 is freeware for PERSONAL USE only. Commercial users should + * seek permission of the copyright holders first. Commercial use includes + * charging money for Project64 or software derived from Project64. + * + * The copyright holders request that bug fixes and improvements to the code + * should be forwarded to them so if they want them. + * + */ +#include +#include +#include + +extern "C" { +#include "Log.h" +#include "Rsp.h" +#include "Rsp Registers.h" +} + +CLog * RDPLog = NULL; +CLog * CPULog = NULL; + +void StartCPULog ( void ) +{ + if (CPULog == NULL) + { + CPULog = new CLog; + CPULog->Open("RSP_x86Log.txt"); + } +} + +void StopCPULog ( void ) +{ + if (CPULog == NULL) + { + delete CPULog; + CPULog = NULL; + } +} + +void CPU_Message ( const char * Message, ...) +{ + if (CPULog == NULL) + { + return; + } + + va_list args; + va_start(args, Message); + CPULog->LogArgs(Message,args); + va_end(args); +} + +void StartRDPLog ( void ) +{ + if (RDPLog == NULL) + { + RDPLog = new CLog; + RDPLog->Open("RDP_Log.txt"); +// RDPLog->SetFlush(true); + } +} + +void StopRDPLog ( void ) +{ + if (RDPLog == NULL) + { + delete RDPLog; + RDPLog = NULL; + } +} + +void RDP_Message ( const char * Message, ...) +{ + if (RDPLog == NULL) + { + return; + } + + va_list args; + va_start(args, Message); + RDPLog->LogArgs(Message,args); + va_end(args); +} + +void RDP_LogMT0 ( DWORD PC, int Reg, DWORD Value ) +{ + if (RDPLog == NULL) + { + return; + } + switch (Reg) { + case 0: RDP_Message("%03X: Stored 0x%08X into SP_MEM_ADDR_REG",PC,Value); break; + case 1: RDP_Message("%03X: Stored 0x%08X into SP_DRAM_ADDR_REG",PC,Value); break; + case 2: RDP_Message("%03X: Stored 0x%08X into SP_RD_LEN_REG",PC,Value); break; + case 3: RDP_Message("%03X: Stored 0x%08X into SP_WR_LEN_REG",PC,Value); break; + case 4: RDP_Message("%03X: Stored 0x%08X into SP_STATUS_REG",PC,Value); break; + case 5: RDP_Message("%03X: Stored 0x%08X into Reg 5 ???",PC,Value); break; + case 6: RDP_Message("%03X: Stored 0x%08X into Reg 6 ???",PC,Value); break; + case 7: RDP_Message("%03X: Stored 0x%08X into SP_SEMAPHORE_REG",PC,Value); break; + case 8: RDP_Message("%03X: Stored 0x%08X into DPC_START_REG",PC,Value); break; + case 9: RDP_Message("%03X: Stored 0x%08X into DPC_END_REG",PC,Value); break; + case 10: RDP_Message("%03X: Stored 0x%08X into DPC_CURRENT_REG",PC,Value); break; + case 11: RDP_Message("%03X: Stored 0x%08X into DPC_STATUS_REG",PC,Value); break; + case 12: RDP_Message("%03X: Stored 0x%08X into DPC_CLOCK_REG",PC,Value); break; + } +} + +void RDP_LogMF0 ( DWORD PC, int Reg ) +{ + switch (Reg) { + case 8: RDP_Message("%03X: Read 0x%08X from DPC_START_REG",PC,*RSPInfo.DPC_START_REG); break; + case 9: RDP_Message("%03X: Read 0x%08X from DPC_END_REG",PC,*RSPInfo.DPC_END_REG); break; + case 10: RDP_Message("%03X: Read 0x%08X from DPC_CURRENT_REG",PC,*RSPInfo.DPC_CURRENT_REG); break; + case 11: RDP_Message("%03X: Read 0x%08X from DPC_STATUS_REG",PC,*RSPInfo.DPC_STATUS_REG); break; + case 12: RDP_Message("%03X: Read 0x%08X from DPC_CLOCK_REG",PC,*RSPInfo.DPC_CLOCK_REG); break; + } +} + + +void RDP_LogDlist ( void ) +{ + if (RDPLog == NULL) + { + return; + } + RDP_Message(" Dlist length = %d bytes",*RSPInfo.DPC_END_REG - *RSPInfo.DPC_CURRENT_REG); + + DWORD Length = *RSPInfo.DPC_END_REG - *RSPInfo.DPC_CURRENT_REG; + DWORD Pos = *RSPInfo.DPC_CURRENT_REG; + while (Pos < *RSPInfo.DPC_END_REG) + { + char Hex[100], Ascii[30]; + DWORD count; + + memset(&Hex,0,sizeof(Hex)); + memset(&Ascii,0,sizeof(Ascii)); + + BYTE * Mem = RSPInfo.DMEM; + if ((*RSPInfo.DPC_STATUS_REG & DPC_STATUS_XBUS_DMEM_DMA) == 0) + { + Mem = RSPInfo.RDRAM; + } + + for (count = 0; count < 0x10; count ++, Pos++ ) { + if ((count % 4) != 0 || count == 0) { + sprintf(Hex,"%s %02X",Hex,Mem[Pos]); + } else { + sprintf(Hex,"%s - %02X",Hex,Mem[Pos]); + } + + + if (Mem[Pos] < 30 || Mem[Pos] > 127) { + strcat(Ascii,"."); + } else { + sprintf(Ascii,"%s%c",Ascii,Mem[Pos]); + } + } + RDP_Message(" %s %s",Hex, Ascii); + } +} + +void RDP_LogLoc ( DWORD PC ) +{ +// RDP_Message("%03X %08X %08X %08X %08X %08X %08X %08X %08X %08X %08X %08X %08X",PC, RSP_GPR[26].UW, *(DWORD *)&RSPInfo.IMEM[0xDBC], +// RSP_Flags[0].UW, RSP_Vect[0].UW[0],RSP_Vect[0].UW[1],RSP_Vect[0].UW[2],RSP_Vect[0].UW[3], +// RSP_Vect[28].UW[0],RSP_Vect[28].UW[1],RSP_Vect[28].UW[2],RSP_Vect[28].UW[3],RSP_Vect[31].UW[0]); +} + + +#ifdef old + +#include +#include +#include "RSP Registers.h" +#include "log.h" + +#ifdef Log_x86Code +static HANDLE hCPULogFile = NULL; +#endif + +#ifdef GenerateLog +static HANDLE hLogFile = NULL; +#endif + +#ifdef Log_x86Code +void CPU_Message (char * Message, ...) { + DWORD dwWritten; + char Msg[400]; + va_list ap; + + va_start( ap, Message ); + vsprintf( Msg, Message, ap ); + va_end( ap ); + + strcat(Msg,"\r\n"); + WriteFile( hCPULogFile,Msg,strlen(Msg),&dwWritten,NULL ); +} +#endif + +#ifdef GenerateLog +void Log_Message (char * Message, ...) { + DWORD dwWritten; + char Msg[400]; + va_list ap; + + va_start( ap, Message ); + vsprintf( Msg, Message, ap ); + va_end( ap ); + + strcat(Msg,"\r\n"); + + WriteFile( hLogFile,Msg,strlen(Msg),&dwWritten,NULL ); +} +#endif + +#ifdef Log_x86Code +void Start_x86_Log (void) { + char path_buffer[_MAX_PATH], drive[_MAX_DRIVE] ,dir[_MAX_DIR]; + char File[_MAX_PATH]; + + GetModuleFileName(NULL,path_buffer,_MAX_PATH); + _splitpath(path_buffer, drive, dir, NULL, NULL); + + sprintf(File, "%s%s\\RSPx86Log.log", drive, dir); + + hCPULogFile = CreateFile(File,GENERIC_WRITE, FILE_SHARE_READ,NULL,CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL); + SetFilePointer(hCPULogFile,0,NULL,FILE_BEGIN); +} +#endif + +#ifdef GenerateLog +void Log_MT_CP0 ( unsigned int PC, int CP0Reg, int Value ) { + switch (CP0Reg) { + //case 0: Log_Message("%03X: Stored 0x%08X in SP_MEM_ADDR_REG",PC,Value); break; + //case 1: Log_Message("%03X: Stored 0x%08X in SP_DRAM_ADDR_REG",PC,Value); break; + //case 2: Log_Message("%03X: Stored 0x%08X in SP_RD_LEN_REG",PC,Value); break; + case 3: + //Log_Message("%03X: Stored 0x%08X in SP_WR_LEN_REG",PC,Value); + Log_Message("Instruction: %08X%08X",RSP_GPR[25].UW,RSP_GPR[24].UW); + //Log_Message(""); + break; + /*case 4: Log_Message("%03X: Stored 0x%08X in SP_STATUS_REG",PC,Value); break; + case 5: Log_Message("%03X: Stored 0x%08X in SP_DMA_FULL_REG",PC,Value); break; + case 6: Log_Message("%03X: Stored 0x%08X in SP_DMA_BUSY_REG",PC,Value); break; + case 7: Log_Message("%03X: Stored 0x%08X in SP_SEMAPHORE_REG",PC,Value); break; + case 8: Log_Message("%03X: Stored 0x%08X in DPC_START_REG",PC,Value); break; + case 9: Log_Message("%03X: Stored 0x%08X in DPC_END_REG",PC,Value); break; + case 10: Log_Message("%03X: Stored 0x%08X in DPC_CURRENT_REG",PC,Value); break; + case 11: Log_Message("%03X: Stored 0x%08X in DPC_STATUS_REG",PC,Value); break; + case 12: Log_Message("%03X: Stored 0x%08X in DPC_CLOCK_REG",PC,Value); break; + case 13: Log_Message("%03X: Stored 0x%08X in DPC_BUFBUSY_REG",PC,Value); break; + case 14: Log_Message("%03X: Stored 0x%08X in DPC_PIPEBUSY_REG",PC,Value); break; + case 15: Log_Message("%03X: Stored 0x%08X in DPC_TMEM_REG",PC,Value); break; + default: + Log_Message("%03X: Unkown RSP CP0 register %d",PC,CP0Reg); + break;*/ + } +} + +void Start_Log (void) { + char path_buffer[_MAX_PATH], drive[_MAX_DRIVE] ,dir[_MAX_DIR]; + char File[_MAX_PATH]; + + GetModuleFileName(NULL,path_buffer,_MAX_PATH); + _splitpath(path_buffer, drive, dir, NULL, NULL); + + sprintf(File, "%s%s\\RSP.log", drive, dir); + + hLogFile = CreateFile(File,GENERIC_WRITE, FILE_SHARE_READ,NULL,CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL); + SetFilePointer(hLogFile,0,NULL,FILE_BEGIN); +} + +void Stop_Log (void) { + if (hLogFile) { + CloseHandle(hLogFile); + hLogFile = NULL; + } +} +#endif + +#ifdef Log_x86Code +void Stop_x86_Log (void) { + if (hCPULogFile) { + CloseHandle(hCPULogFile); + hCPULogFile = NULL; + } +} +#endif + +#endif \ No newline at end of file diff --git a/Source/RSP/log.h b/Source/RSP/log.h new file mode 100644 index 000000000..56700bfc1 --- /dev/null +++ b/Source/RSP/log.h @@ -0,0 +1,45 @@ +/* + * RSP Compiler plug in for Project 64 (A Nintendo 64 emulator). + * + * (c) Copyright 2001 jabo (jabo@emulation64.com) and + * zilmar (zilmar@emulation64.com) + * + * pj64 homepage: www.pj64.net + * + * Permission to use, copy, modify and distribute Project64 in both binary and + * source form, for non-commercial purposes, is hereby granted without fee, + * providing that this license information and copyright notice appear with + * all copies and any derived work. + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event shall the authors be held liable for any damages + * arising from the use of this software. + * + * Project64 is freeware for PERSONAL USE only. Commercial users should + * seek permission of the copyright holders first. Commercial use includes + * charging money for Project64 or software derived from Project64. + * + * The copyright holders request that bug fixes and improvements to the code + * should be forwarded to them so if they want them. + * + */ + +#ifdef __cplusplus +extern "C" { +#endif + +void StartCPULog ( void ); +void StopCPULog ( void ); +void CPU_Message ( const char * Message, ...); + +void StartRDPLog ( void ); +void StopRDPLog ( void ); +void RDP_Message ( const char * Message, ...); +void RDP_LogDlist ( void ); +void RDP_LogMT0 ( DWORD PC, int Reg, DWORD Value ); +void RDP_LogMF0 ( DWORD PC, int Reg ); +void RDP_LogLoc ( DWORD PC ); + +#ifdef __cplusplus +} +#endif diff --git a/Source/RSP/memory.c b/Source/RSP/memory.c new file mode 100644 index 000000000..8534cbb21 --- /dev/null +++ b/Source/RSP/memory.c @@ -0,0 +1,556 @@ +/* + * RSP Compiler plug in for Project 64 (A Nintendo 64 emulator). + * + * (c) Copyright 2001 jabo (jabo@emulation64.com) and + * zilmar (zilmar@emulation64.com) + * + * pj64 homepage: www.pj64.net + * + * Permission to use, copy, modify and distribute Project64 in both binary and + * source form, for non-commercial purposes, is hereby granted without fee, + * providing that this license information and copyright notice appear with + * all copies and any derived work. + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event shall the authors be held liable for any damages + * arising from the use of this software. + * + * Project64 is freeware for PERSONAL USE only. Commercial users should + * seek permission of the copyright holders first. Commercial use includes + * charging money for Project64 or software derived from Project64. + * + * The copyright holders request that bug fixes and improvements to the code + * should be forwarded to them so if they want them. + * + */ + +enum { MaxMaps = 32 }; + +#include +#include "rsp.h" +#include "RSP Registers.h" + +DWORD NoOfMaps, MapsCRC[MaxMaps], Table; +BYTE * RecompCode, * RecompCodeSecondary, * RecompPos, *JumpTables; +void ** JumpTable; + +int AllocateMemory (void) { + RecompCode=(BYTE *) VirtualAlloc( NULL, 0x00400004, MEM_RESERVE, PAGE_EXECUTE_READWRITE); + RecompCode=(BYTE *) VirtualAlloc( RecompCode, 0x00400000, MEM_COMMIT, PAGE_EXECUTE_READWRITE); + + if(RecompCode == NULL) { + DisplayError("Not enough memory for RSP RecompCode!"); + return FALSE; + } + + RecompCodeSecondary = (BYTE *)VirtualAlloc( NULL, 0x00200000, MEM_COMMIT, PAGE_EXECUTE_READWRITE ); + if(RecompCodeSecondary == NULL) { + DisplayError("Not enough memory for RSP RecompCode Secondary!"); + return FALSE; + } + + JumpTables = (BYTE *)VirtualAlloc( NULL, 0x1000 * MaxMaps, MEM_COMMIT, PAGE_READWRITE ); + if( JumpTables == NULL ) { + DisplayError("Not enough memory for Jump Table!"); + return FALSE; + } + + JumpTable = (void **)JumpTables; + RecompPos = RecompCode; + NoOfMaps = 0; + return TRUE; +} + +void FreeMemory (void) { + VirtualFree( RecompCode, 0 , MEM_RELEASE); + VirtualFree( JumpTable, 0 , MEM_RELEASE); + VirtualFree( RecompCodeSecondary, 0 , MEM_RELEASE); +} + +void ResetJumpTables ( void ) +{ + memset(JumpTables,0,0x1000 * MaxMaps); + RecompPos = RecompCode; + NoOfMaps = 0; +} + +void SetJumpTable (DWORD End) { + DWORD CRC, count; + + CRC = 0; + if (End < 0x800) + { + End = 0x800; + } + + if (End == 0x1000 && ((*RSPInfo.SP_MEM_ADDR_REG & 0x0FFF) & ~7) == 0x80) + { + End = 0x800; + } + + for (count = 0; count < End; count += 0x40) { + CRC += *(DWORD *)(RSPInfo.IMEM + count); + } + + for (count = 0; count < NoOfMaps; count++ ) { + if (CRC == MapsCRC[count]) { + JumpTable = (void **)(JumpTables + count * 0x1000); + Table = count; + return; + } + } + //DisplayError("%X %X",NoOfMaps,CRC); + if (NoOfMaps == MaxMaps) { + ResetJumpTables(); + } + MapsCRC[NoOfMaps] = CRC; + JumpTable = (void **)(JumpTables + NoOfMaps * 0x1000); + Table = NoOfMaps; + NoOfMaps += 1; +} + +void RSP_LB_DMEM ( DWORD Addr, BYTE * Value ) { + * Value = *(BYTE *)(RSPInfo.DMEM + ((Addr ^ 3) & 0xFFF)) ; +} + +void RSP_LBV_DMEM ( DWORD Addr, int vect, int element ) { + RSP_Vect[vect].B[15 - element] = *(RSPInfo.DMEM + ((Addr ^ 3) & 0xFFF)); +} + +void RSP_LDV_DMEM ( DWORD Addr, int vect, int element ) { + int length, Count; + + length = 8; + if (length > 16 - element) { + length = 16 - element; + } + for (Count = element; Count < (length + element); Count ++ ){ + RSP_Vect[vect].B[15 - Count] = *(RSPInfo.DMEM + ((Addr ^ 3) & 0xFFF)); + Addr += 1; + } + +} + +void RSP_LFV_DMEM ( DWORD Addr, int vect, int element ) { + int length, count; + VECTOR Temp; + + length = 8; + if (length > 16 - element) { + length = 16 - element; + } + + Temp.HW[7] = *(RSPInfo.DMEM + (((Addr + element) ^3) & 0xFFF)) << 7; + Temp.HW[6] = *(RSPInfo.DMEM + (((Addr + ((0x4 - element) ^ 3) & 0xf)) & 0xFFF)) << 7; + Temp.HW[5] = *(RSPInfo.DMEM + (((Addr + ((0x8 - element) ^ 3) & 0xf)) & 0xFFF)) << 7; + Temp.HW[4] = *(RSPInfo.DMEM + (((Addr + ((0xC - element) ^ 3) & 0xf)) & 0xFFF)) << 7; + Temp.HW[3] = *(RSPInfo.DMEM + (((Addr + ((0x8 - element) ^ 3) & 0xf)) & 0xFFF)) << 7; + Temp.HW[2] = *(RSPInfo.DMEM + (((Addr + ((0xC - element) ^ 3) & 0xf)) & 0xFFF)) << 7; + Temp.HW[1] = *(RSPInfo.DMEM + (((Addr + ((0x10 - element) ^ 3) & 0xf)) & 0xFFF)) << 7; + Temp.HW[0] = *(RSPInfo.DMEM + (((Addr + ((0x4 - element) ^ 3) & 0xf)) & 0xFFF)) << 7; + + for (count = element; count < (length + element); count ++ ){ + RSP_Vect[vect].B[15 - count] = Temp.B[15 - count]; + } +} + +void RSP_LH_DMEM ( DWORD Addr, WORD * Value ) { + if ((Addr & 0x1) != 0) { + if (Addr > 0xFFE) { + DisplayError("hmmmm.... Problem with:\nRSP_LH_DMEM"); + return; + } + Addr &= 0xFFF; + *Value = *(BYTE *)(RSPInfo.DMEM + (Addr^ 3)) << 8; + *Value += *(BYTE *)(RSPInfo.DMEM + ((Addr + 1)^ 3)); + return; + } + * Value = *(WORD *)(RSPInfo.DMEM + ((Addr ^ 2 ) & 0xFFF)); +} + +void RSP_LHV_DMEM ( DWORD Addr, int vect, int element ) { + RSP_Vect[vect].HW[7] = *(RSPInfo.DMEM + ((Addr + ((0x10 - element) & 0xF) ^3) & 0xFFF)) << 7; + RSP_Vect[vect].HW[6] = *(RSPInfo.DMEM + ((Addr + ((0x10 - element + 2) & 0xF) ^3) & 0xFFF)) << 7; + RSP_Vect[vect].HW[5] = *(RSPInfo.DMEM + ((Addr + ((0x10 - element + 4) & 0xF) ^3) & 0xFFF)) << 7; + RSP_Vect[vect].HW[4] = *(RSPInfo.DMEM + ((Addr + ((0x10 - element + 6) & 0xF) ^3) & 0xFFF)) << 7; + RSP_Vect[vect].HW[3] = *(RSPInfo.DMEM + ((Addr + ((0x10 - element + 8) & 0xF) ^3) & 0xFFF)) << 7; + RSP_Vect[vect].HW[2] = *(RSPInfo.DMEM + ((Addr + ((0x10 - element + 10) & 0xF) ^3) & 0xFFF)) << 7; + RSP_Vect[vect].HW[1] = *(RSPInfo.DMEM + ((Addr + ((0x10 - element + 12) & 0xF) ^3) & 0xFFF)) << 7; + RSP_Vect[vect].HW[0] = *(RSPInfo.DMEM + ((Addr + ((0x10 - element + 14) & 0xF) ^3) & 0xFFF)) << 7; +} + +void RSP_LLV_DMEM ( DWORD Addr, int vect, int element ) { + int length, Count; + + length = 4; + if (length > 16 - element) { + length = 16 - element; + } + for (Count = element; Count < (length + element); Count ++ ){ + RSP_Vect[vect].B[15 - Count] = *(RSPInfo.DMEM + ((Addr ^ 3) & 0xFFF)); + Addr += 1; + } + +} + +void RSP_LPV_DMEM ( DWORD Addr, int vect, int element ) { + RSP_Vect[vect].HW[7] = *(RSPInfo.DMEM + ((Addr + ((0x10 - element) & 0xF)^3) & 0xFFF)) << 8; + RSP_Vect[vect].HW[6] = *(RSPInfo.DMEM + ((Addr + ((0x10 - element + 1) & 0xF)^3) & 0xFFF)) << 8; + RSP_Vect[vect].HW[5] = *(RSPInfo.DMEM + ((Addr + ((0x10 - element + 2) & 0xF)^3) & 0xFFF)) << 8; + RSP_Vect[vect].HW[4] = *(RSPInfo.DMEM + ((Addr + ((0x10 - element + 3) & 0xF)^3) & 0xFFF)) << 8; + RSP_Vect[vect].HW[3] = *(RSPInfo.DMEM + ((Addr + ((0x10 - element + 4) & 0xF)^3) & 0xFFF)) << 8; + RSP_Vect[vect].HW[2] = *(RSPInfo.DMEM + ((Addr + ((0x10 - element + 5) & 0xF)^3) & 0xFFF)) << 8; + RSP_Vect[vect].HW[1] = *(RSPInfo.DMEM + ((Addr + ((0x10 - element + 6) & 0xF)^3) & 0xFFF)) << 8; + RSP_Vect[vect].HW[0] = *(RSPInfo.DMEM + ((Addr + ((0x10 - element + 7) & 0xF)^3) & 0xFFF)) << 8; +} + +void RSP_LRV_DMEM ( DWORD Addr, int vect, int element ) { + int length, Count, offset; + + offset = (Addr & 0xF) - 1; + length = (Addr & 0xF) - element; + Addr &= 0xFF0; + for (Count = element; Count < (length + element); Count ++ ){ + RSP_Vect[vect].B[offset - Count] = *(RSPInfo.DMEM + ((Addr ^ 3) & 0xFFF)); + Addr += 1; + } + +} + +void RSP_LQV_DMEM ( DWORD Addr, int vect, int element ) { + int length, Count; + + length = ((Addr + 0x10) & ~0xF) - Addr; + if (length > 16 - element) { + length = 16 - element; + } + for (Count = element; Count < (length + element); Count ++ ){ + RSP_Vect[vect].B[15 - Count] = *(RSPInfo.DMEM + ((Addr ^ 3) & 0xFFF)); + Addr += 1; + } + +} + +void RSP_LSV_DMEM ( DWORD Addr, int vect, int element ) { + int length, Count; + + length = 2; + if (length > 16 - element) { + length = 16 - element; + } + for (Count = element; Count < (length + element); Count ++ ){ + RSP_Vect[vect].B[15 - Count] = *(RSPInfo.DMEM + ((Addr ^ 3) & 0xFFF)); + Addr += 1; + } +} + +void RSP_LTV_DMEM ( DWORD Addr, int vect, int element ) { + int del, count, length; + + length = 8; + if (length > 32 - vect) { + length = 32 - vect; + } + + Addr = ((Addr + 8) & 0xFF0) + (element & 0x1); + for (count = 0; count < length; count ++) { + del = ((8 - (element >> 1) + count) << 1) & 0xF; + RSP_Vect[vect + count].B[15 - del] = *(RSPInfo.DMEM + (Addr ^ 3)); + RSP_Vect[vect + count].B[14 - del] = *(RSPInfo.DMEM + ((Addr + 1) ^ 3)); + Addr += 2; + } +} + +void RSP_LUV_DMEM ( DWORD Addr, int vect, int element ) { + RSP_Vect[vect].HW[7] = *(RSPInfo.DMEM + ((Addr + ((0x10 - element) & 0xF)^3) & 0xFFF)) << 7; + RSP_Vect[vect].HW[6] = *(RSPInfo.DMEM + ((Addr + ((0x10 - element + 1) & 0xF)^3) & 0xFFF)) << 7; + RSP_Vect[vect].HW[5] = *(RSPInfo.DMEM + ((Addr + ((0x10 - element + 2) & 0xF)^3) & 0xFFF)) << 7; + RSP_Vect[vect].HW[4] = *(RSPInfo.DMEM + ((Addr + ((0x10 - element + 3) & 0xF)^3) & 0xFFF)) << 7; + RSP_Vect[vect].HW[3] = *(RSPInfo.DMEM + ((Addr + ((0x10 - element + 4) & 0xF)^3) & 0xFFF)) << 7; + RSP_Vect[vect].HW[2] = *(RSPInfo.DMEM + ((Addr + ((0x10 - element + 5) & 0xF)^3) & 0xFFF)) << 7; + RSP_Vect[vect].HW[1] = *(RSPInfo.DMEM + ((Addr + ((0x10 - element + 6) & 0xF)^3) & 0xFFF)) << 7; + RSP_Vect[vect].HW[0] = *(RSPInfo.DMEM + ((Addr + ((0x10 - element + 7) & 0xF)^3) & 0xFFF)) << 7; +} + +void RSP_LW_DMEM ( DWORD Addr, DWORD * Value ) { + if ((Addr & 0x3) != 0) { + Addr &= 0xFFF; + if (Addr > 0xFFC) { + DisplayError("hmmmm.... Problem with:\nRSP_LW_DMEM"); + return; + } + *Value = *(BYTE *)(RSPInfo.DMEM + (Addr^ 3)) << 0x18; + *Value += *(BYTE *)(RSPInfo.DMEM + ((Addr + 1)^ 3)) << 0x10; + *Value += *(BYTE *)(RSPInfo.DMEM + ((Addr + 2)^ 3)) << 8; + *Value += *(BYTE *)(RSPInfo.DMEM + ((Addr + 3)^ 3)); + return; + } + * Value = *(DWORD *)(RSPInfo.DMEM + (Addr & 0xFFF)); +} + +void RSP_LW_IMEM ( DWORD Addr, DWORD * Value ) { + if ((Addr & 0x3) != 0) { + DisplayError("Unaligned RSP_LW_IMEM"); + } + * Value = *(DWORD *)(RSPInfo.IMEM + (Addr & 0xFFF)); +} + +void RSP_SB_DMEM ( DWORD Addr, BYTE Value ) { + *(BYTE *)(RSPInfo.DMEM + ((Addr ^ 3) & 0xFFF)) = Value; +} + +void RSP_SBV_DMEM ( DWORD Addr, int vect, int element ) { + *(RSPInfo.DMEM + ((Addr ^ 3) & 0xFFF)) = RSP_Vect[vect].B[15 - element]; +} + +void RSP_SDV_DMEM ( DWORD Addr, int vect, int element ) { + int Count; + + for (Count = element; Count < (8 + element); Count ++ ){ + *(RSPInfo.DMEM + ((Addr ^ 3) & 0xFFF)) = RSP_Vect[vect].B[15 - (Count & 0xF)]; + Addr += 1; + } +} + +void RSP_SFV_DMEM ( DWORD Addr, int vect, int element ) { + int offset = Addr & 0xF; + Addr &= 0xFF0; + + switch (element) { + case 0: + *(RSPInfo.DMEM + ((Addr + offset)^3)) = RSP_Vect[vect].UHW[7] >> 7; + *(RSPInfo.DMEM + ((Addr + ((offset + 4) & 0xF))^3)) = RSP_Vect[vect].UHW[6] >> 7; + *(RSPInfo.DMEM + ((Addr + ((offset + 8) & 0xF))^3)) = RSP_Vect[vect].UHW[5] >> 7; + *(RSPInfo.DMEM + ((Addr + ((offset + 12) & 0xF))^3)) = RSP_Vect[vect].UHW[4] >> 7; + break; + case 1: + *(RSPInfo.DMEM + ((Addr + offset)^3)) = RSP_Vect[vect].UHW[1] >> 7; + *(RSPInfo.DMEM + ((Addr + ((offset + 4) & 0xF))^3)) = RSP_Vect[vect].UHW[0] >> 7; + *(RSPInfo.DMEM + ((Addr + ((offset + 8) & 0xF))^3)) = RSP_Vect[vect].UHW[3] >> 7; + *(RSPInfo.DMEM + ((Addr + ((offset + 12) & 0xF))^3)) = RSP_Vect[vect].UHW[2] >> 7; + break; + case 2: + *(RSPInfo.DMEM + ((Addr + offset)^3)) = 0; + *(RSPInfo.DMEM + ((Addr + ((offset + 4) & 0xF))^3)) = 0; + *(RSPInfo.DMEM + ((Addr + ((offset + 8) & 0xF))^3)) = 0; + *(RSPInfo.DMEM + ((Addr + ((offset + 12) & 0xF))^3)) = 0; + break; + case 3: + *(RSPInfo.DMEM + ((Addr + offset)^3)) = 0; + *(RSPInfo.DMEM + ((Addr + ((offset + 4) & 0xF))^3)) = 0; + *(RSPInfo.DMEM + ((Addr + ((offset + 8) & 0xF))^3)) = 0; + *(RSPInfo.DMEM + ((Addr + ((offset + 12) & 0xF)^3))) = 0; + break; + case 4: + *(RSPInfo.DMEM + ((Addr + offset)^3)) = RSP_Vect[vect].UHW[6] >> 7; + *(RSPInfo.DMEM + ((Addr + ((offset + 4) & 0xF))^3)) = RSP_Vect[vect].UHW[5] >> 7; + *(RSPInfo.DMEM + ((Addr + ((offset + 8) & 0xF))^3)) = RSP_Vect[vect].UHW[4] >> 7; + *(RSPInfo.DMEM + ((Addr + ((offset + 12) & 0xF))^3)) = RSP_Vect[vect].UHW[7] >> 7; + break; + case 5: + *(RSPInfo.DMEM + ((Addr + offset)^3)) = RSP_Vect[vect].UHW[0] >> 7; + *(RSPInfo.DMEM + ((Addr + ((offset + 4) & 0xF))^3)) = RSP_Vect[vect].UHW[3] >> 7; + *(RSPInfo.DMEM + ((Addr + ((offset + 8) & 0xF))^3)) = RSP_Vect[vect].UHW[2] >> 7; + *(RSPInfo.DMEM + ((Addr + ((offset + 12) & 0xF))^3)) = RSP_Vect[vect].UHW[1] >> 7; + break; + case 6: + *(RSPInfo.DMEM + ((Addr + offset)^3)) = 0; + *(RSPInfo.DMEM + ((Addr + ((offset + 4) & 0xF))^3)) = 0; + *(RSPInfo.DMEM + ((Addr + ((offset + 8) & 0xF))^3)) = 0; + *(RSPInfo.DMEM + ((Addr + ((offset + 12) & 0xF))^3)) = 0; + break; + case 7: + *(RSPInfo.DMEM + ((Addr + offset)^3)) = 0; + *(RSPInfo.DMEM + ((Addr + ((offset + 4) & 0xF))^3)) = 0; + *(RSPInfo.DMEM + ((Addr + ((offset + 8) & 0xF))^3)) = 0; + *(RSPInfo.DMEM + ((Addr + ((offset + 12) & 0xF))^3)) = 0; + break; + case 8: + *(RSPInfo.DMEM + ((Addr + offset)^3)) = RSP_Vect[vect].UHW[3] >> 7; + *(RSPInfo.DMEM + ((Addr + ((offset + 4) & 0xF))^3)) = RSP_Vect[vect].UHW[2] >> 7; + *(RSPInfo.DMEM + ((Addr + ((offset + 8) & 0xF))^3)) = RSP_Vect[vect].UHW[1] >> 7; + *(RSPInfo.DMEM + ((Addr + ((offset + 12) & 0xF))^3)) = RSP_Vect[vect].UHW[0] >> 7; + break; + case 9: + *(RSPInfo.DMEM + ((Addr + offset)^3)) = 0; + *(RSPInfo.DMEM + ((Addr + ((offset + 4) & 0xF))^3)) = 0; + *(RSPInfo.DMEM + ((Addr + ((offset + 8) & 0xF))^3)) = 0; + *(RSPInfo.DMEM + ((Addr + ((offset + 12) & 0xF))^3)) = 0; + break; + case 10: + *(RSPInfo.DMEM + ((Addr + offset)^3)) = 0; + *(RSPInfo.DMEM + ((Addr + ((offset + 4) & 0xF))^3)) = 0; + *(RSPInfo.DMEM + ((Addr + ((offset + 8) & 0xF))^3)) = 0; + *(RSPInfo.DMEM + ((Addr + ((offset + 12) & 0xF))^3)) = 0; + break; + case 11: + *(RSPInfo.DMEM + ((Addr + offset)^3)) = RSP_Vect[vect].UHW[4] >> 7; + *(RSPInfo.DMEM + ((Addr + ((offset + 4) & 0xF))^3)) = RSP_Vect[vect].UHW[7] >> 7; + *(RSPInfo.DMEM + ((Addr + ((offset + 8) & 0xF))^3)) = RSP_Vect[vect].UHW[6] >> 7; + *(RSPInfo.DMEM + ((Addr + ((offset + 12) & 0xF))^3)) = RSP_Vect[vect].UHW[5] >> 7; + break; + case 12: + *(RSPInfo.DMEM + ((Addr + offset)^3)) = RSP_Vect[vect].UHW[2] >> 7; + *(RSPInfo.DMEM + ((Addr + ((offset + 4) & 0xF))^3)) = RSP_Vect[vect].UHW[1] >> 7; + *(RSPInfo.DMEM + ((Addr + ((offset + 8) & 0xF))^3)) = RSP_Vect[vect].UHW[0] >> 7; + *(RSPInfo.DMEM + ((Addr + ((offset + 12) & 0xF))^3)) = RSP_Vect[vect].UHW[3] >> 7; + break; + case 13: + *(RSPInfo.DMEM + ((Addr + offset)^3)) = 0; + *(RSPInfo.DMEM + ((Addr + ((offset + 4) & 0xF))^3)) = 0; + *(RSPInfo.DMEM + ((Addr + ((offset + 8) & 0xF))^3)) = 0; + *(RSPInfo.DMEM + ((Addr + ((offset + 12) & 0xF))^3)) = 0; + break; + case 14: + *(RSPInfo.DMEM + ((Addr + offset)^3)) = 0; + *(RSPInfo.DMEM + ((Addr + ((offset + 4) & 0xF))^3)) = 0; + *(RSPInfo.DMEM + ((Addr + ((offset + 8) & 0xF))^3)) = 0; + *(RSPInfo.DMEM + ((Addr + ((offset + 12) & 0xF))^3)) = 0; + break; + case 15: + *(RSPInfo.DMEM + ((Addr + offset)^3)) = RSP_Vect[vect].UHW[7] >> 7; + *(RSPInfo.DMEM + ((Addr + ((offset + 4) & 0xF))^3)) = RSP_Vect[vect].UHW[6] >> 7; + *(RSPInfo.DMEM + ((Addr + ((offset + 8) & 0xF))^3)) = RSP_Vect[vect].UHW[5] >> 7; + *(RSPInfo.DMEM + ((Addr + ((offset + 12) & 0xF))^3)) = RSP_Vect[vect].UHW[4] >> 7; + break; + } +} + +void RSP_SH_DMEM ( DWORD Addr, WORD Value ) { + if ((Addr & 0x1) != 0) { + DisplayError("Unaligned RSP_SH_DMEM"); + return; + } + *(WORD *)(RSPInfo.DMEM + ((Addr ^ 2) & 0xFFF)) = Value; +} + +void RSP_SHV_DMEM ( DWORD Addr, int vect, int element ) { + *(RSPInfo.DMEM + ((Addr^3) & 0xFFF)) = (RSP_Vect[vect].UB[(15 - element) & 0xF] << 1) + + (RSP_Vect[vect].UB[(14 - element) & 0xF] >> 7); + *(RSPInfo.DMEM + (((Addr + 2)^3) & 0xFFF)) = (RSP_Vect[vect].UB[(13 - element) & 0xF] << 1) + + (RSP_Vect[vect].UB[(12 - element) & 0xF] >> 7); + *(RSPInfo.DMEM + (((Addr + 4)^3) & 0xFFF)) = (RSP_Vect[vect].UB[(11 - element) & 0xF] << 1) + + (RSP_Vect[vect].UB[(10 - element) & 0xF] >> 7); + *(RSPInfo.DMEM + (((Addr + 6)^3) & 0xFFF)) = (RSP_Vect[vect].UB[(9 - element) & 0xF] << 1) + + (RSP_Vect[vect].UB[(8 - element) & 0xF] >> 7); + *(RSPInfo.DMEM + (((Addr + 8)^3) & 0xFFF)) = (RSP_Vect[vect].UB[(7 - element) & 0xF] << 1) + + (RSP_Vect[vect].UB[(6 - element) & 0xF] >> 7); + *(RSPInfo.DMEM + (((Addr + 10)^3) & 0xFFF)) = (RSP_Vect[vect].UB[(5 - element) & 0xF] << 1) + + (RSP_Vect[vect].UB[(4 - element) & 0xF] >> 7); + *(RSPInfo.DMEM + (((Addr + 12)^3) & 0xFFF)) = (RSP_Vect[vect].UB[(3 - element) & 0xF] << 1) + + (RSP_Vect[vect].UB[(2 - element) & 0xF] >> 7); + *(RSPInfo.DMEM + (((Addr + 14)^3) & 0xFFF)) = (RSP_Vect[vect].UB[(1 - element) & 0xF] << 1) + + (RSP_Vect[vect].UB[(0 - element) & 0xF] >> 7); +} + +void RSP_SLV_DMEM ( DWORD Addr, int vect, int element ) { + int Count; + + for (Count = element; Count < (4 + element); Count ++ ){ + *(RSPInfo.DMEM + ((Addr ^3) & 0xFFF)) = RSP_Vect[vect].B[15 - (Count & 0xF)]; + Addr += 1; + } +} + +void RSP_SPV_DMEM ( DWORD Addr, int vect, int element ) { + int Count; + + for (Count = element; Count < (8 + element); Count ++ ){ + if (((Count) & 0xF) < 8) { + *(RSPInfo.DMEM + ((Addr ^ 3) & 0xFFF)) = RSP_Vect[vect].UB[15 - ((Count & 0xF) << 1)]; + } else { + *(RSPInfo.DMEM + ((Addr ^ 3) & 0xFFF)) = (RSP_Vect[vect].UB[15 - ((Count & 0x7) << 1)] << 1) + + (RSP_Vect[vect].UB[14 - ((Count & 0x7) << 1)] >> 7); + } + Addr += 1; + } +} + +void RSP_SQV_DMEM ( DWORD Addr, int vect, int element ) { + int length, Count; + + length = ((Addr + 0x10) & ~0xF) - Addr; + for (Count = element; Count < (length + element); Count ++ ){ + *(RSPInfo.DMEM + ((Addr ^ 3) & 0xFFF)) = RSP_Vect[vect].B[15 - (Count & 0xF)]; + Addr += 1; + } +} + +void RSP_SRV_DMEM ( DWORD Addr, int vect, int element ) { + int length, Count, offset; + + length = (Addr & 0xF); + offset = (0x10 - length) & 0xF; + Addr &= 0xFF0; + for (Count = element; Count < (length + element); Count ++ ){ + *(RSPInfo.DMEM + ((Addr ^ 3) & 0xFFF)) = RSP_Vect[vect].B[15 - ((Count + offset) & 0xF)]; + Addr += 1; + } +} + +void RSP_SSV_DMEM ( DWORD Addr, int vect, int element ) { + int Count; + + for (Count = element; Count < (2 + element); Count ++ ){ + *(RSPInfo.DMEM + ((Addr ^ 3) & 0xFFF)) = RSP_Vect[vect].B[15 - (Count & 0xF)]; + Addr += 1; + } +} + +void RSP_STV_DMEM ( DWORD Addr, int vect, int element ) { + int del, count, length; + + length = 8; + if (length > 32 - vect) { + length = 32 - vect; + } + length = length << 1; + del = element >> 1; + for (count = 0; count < length; count += 2) { + *(RSPInfo.DMEM + ((Addr ^ 3) & 0xFFF)) = RSP_Vect[vect + del].UB[15 - count]; + *(RSPInfo.DMEM + (((Addr + 1) ^ 3) & 0xFFF)) = RSP_Vect[vect + del].UB[14 - count]; + del = (del + 1) & 7; + Addr += 2; + } +} + +void RSP_SUV_DMEM ( DWORD Addr, int vect, int element ) { + int Count; + + for (Count = element; Count < (8 + element); Count ++ ){ + if (((Count) & 0xF) < 8) { + *(RSPInfo.DMEM + ((Addr ^ 3) & 0xFFF)) = (RSP_Vect[vect].UB[15 - ((Count & 0x7) << 1)] << 1) + + (RSP_Vect[vect].UB[14 - ((Count & 0x7) << 1)] >> 7); + } else { + *(RSPInfo.DMEM + ((Addr ^ 3) & 0xFFF)) = RSP_Vect[vect].UB[15 - ((Count & 0x7) << 1)]; + } + Addr += 1; + } +} + +void RSP_SW_DMEM ( DWORD Addr, DWORD Value ) { + Addr &= 0xFFF; + if ((Addr & 0x3) != 0) { + if (Addr > 0xFFC) { + DisplayError("hmmmm.... Problem with:\nRSP_SW_DMEM"); + return; + } + *(BYTE *)(RSPInfo.DMEM + (Addr ^ 3)) = (BYTE)(Value >> 0x18); + *(BYTE *)(RSPInfo.DMEM + ((Addr + 1) ^ 3)) = (BYTE)(Value >> 0x10); + *(BYTE *)(RSPInfo.DMEM + ((Addr + 2) ^ 3)) = (BYTE)(Value >> 0x8); + *(BYTE *)(RSPInfo.DMEM + ((Addr + 3) ^ 3)) = (BYTE)(Value); + return; + } + *(DWORD *)(RSPInfo.DMEM + Addr) = Value; +} + +void RSP_SWV_DMEM ( DWORD Addr, int vect, int element ) { + int Count, offset; + + offset = Addr & 0xF; + Addr &= 0xFF0; + for (Count = element; Count < (16 + element); Count ++ ){ + *(RSPInfo.DMEM + ((Addr + (offset & 0xF)) ^ 3)) = RSP_Vect[vect].B[15 - (Count & 0xF)]; + offset += 1; + } +} \ No newline at end of file diff --git a/Source/RSP/memory.h b/Source/RSP/memory.h new file mode 100644 index 000000000..4a8288a0d --- /dev/null +++ b/Source/RSP/memory.h @@ -0,0 +1,64 @@ +/* + * RSP Compiler plug in for Project 64 (A Nintendo 64 emulator). + * + * (c) Copyright 2001 jabo (jabo@emulation64.com) and + * zilmar (zilmar@emulation64.com) + * + * pj64 homepage: www.pj64.net + * + * Permission to use, copy, modify and distribute Project64 in both binary and + * source form, for non-commercial purposes, is hereby granted without fee, + * providing that this license information and copyright notice appear with + * all copies and any derived work. + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event shall the authors be held liable for any damages + * arising from the use of this software. + * + * Project64 is freeware for PERSONAL USE only. Commercial users should + * seek permission of the copyright holders first. Commercial use includes + * charging money for Project64 or software derived from Project64. + * + * The copyright holders request that bug fixes and improvements to the code + * should be forwarded to them so if they want them. + * + */ + +int AllocateMemory ( void ); +void FreeMemory ( void ); +void SetJumpTable ( DWORD End ); + +extern BYTE * RecompCode, * RecompCodeSecondary, * RecompPos; +extern void ** JumpTable; +extern DWORD Table; + +void RSP_LB_DMEM ( DWORD Addr, BYTE * Value ); +void RSP_LBV_DMEM ( DWORD Addr, int vect, int element ); +void RSP_LDV_DMEM ( DWORD Addr, int vect, int element ); +void RSP_LFV_DMEM ( DWORD Addr, int vect, int element ); +void RSP_LH_DMEM ( DWORD Addr, WORD * Value ); +void RSP_LHV_DMEM ( DWORD Addr, int vect, int element ); +void RSP_LLV_DMEM ( DWORD Addr, int vect, int element ); +void RSP_LPV_DMEM ( DWORD Addr, int vect, int element ); +void RSP_LRV_DMEM ( DWORD Addr, int vect, int element ); +void RSP_LQV_DMEM ( DWORD Addr, int vect, int element ); +void RSP_LSV_DMEM ( DWORD Addr, int vect, int element ); +void RSP_LTV_DMEM ( DWORD Addr, int vect, int element ); +void RSP_LUV_DMEM ( DWORD Addr, int vect, int element ); +void RSP_LW_DMEM ( DWORD Addr, DWORD * Value ); +void RSP_LW_IMEM ( DWORD Addr, DWORD * Value ); +void RSP_SB_DMEM ( DWORD Addr, BYTE Value ); +void RSP_SBV_DMEM ( DWORD Addr, int vect, int element ); +void RSP_SDV_DMEM ( DWORD Addr, int vect, int element ); +void RSP_SFV_DMEM ( DWORD Addr, int vect, int element ); +void RSP_SH_DMEM ( DWORD Addr, WORD Value ); +void RSP_SHV_DMEM ( DWORD Addr, int vect, int element ); +void RSP_SLV_DMEM ( DWORD Addr, int vect, int element ); +void RSP_SPV_DMEM ( DWORD Addr, int vect, int element ); +void RSP_SQV_DMEM ( DWORD Addr, int vect, int element ); +void RSP_SRV_DMEM ( DWORD Addr, int vect, int element ); +void RSP_SSV_DMEM ( DWORD Addr, int vect, int element ); +void RSP_STV_DMEM ( DWORD Addr, int vect, int element ); +void RSP_SUV_DMEM ( DWORD Addr, int vect, int element ); +void RSP_SW_DMEM ( DWORD Addr, DWORD Value ); +void RSP_SWV_DMEM ( DWORD Addr, int vect, int element ); diff --git a/Source/RSP/resource.h b/Source/RSP/resource.h new file mode 100644 index 000000000..f12cf4b79 --- /dev/null +++ b/Source/RSP/resource.h @@ -0,0 +1,50 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Developer Studio generated include file. +// Used by RSP.rc +// +#define RspMenu 106 +#define IDC_CHECK_SSE 1001 +#define IDC_CHECK_MMX 1002 +#define IDC_CHECK_MMX2 1003 +#define IDC_PRIMARY_BUFFER 1006 +#define IDC_SECONDARY_BUFFER 1007 +#define IDC_COMPILER_VMULF 1018 +#define IDC_COMPILER_DEST 1019 +#define IDC_COMPILER_ACCUM 1020 +#define IDC_COMPILER_FLAGS 1021 +#define IDC_COMPILER_REORDER 1022 +#define IDC_COMPILER_SECTIONS 1023 +#define IDC_COMPILER_ALIGNGPR 1024 +#define IDC_COMPILER_ALIGNVEC 1025 +#define IDC_COMPILER_GPRCONSTANTS 1026 +#define IDC_AUDIOHLE 1027 +#define IDC_GRAPHICSHLE 1028 +#define IDC_COMPILER_BUFFERS 1030 +#define IDC_COMPILER_SELECT 1031 +#define ID_RSPCOMMANDS 5001 +#define ID_RSPREGISTERS 5002 +#define ID_PROFILING_ON 5003 +#define ID_PROFILING_OFF 5004 +#define ID_PROFILING_LOGINDIVIDUALBLOCKS 5005 +#define ID_PROFILING_RESETSTATS 5006 +#define ID_PROFILING_GENERATELOG 5007 +#define ID_DUMP_RSPCODE 5008 +#define ID_DUMP_DMEM 5009 +#define ID_SHOWCOMPILERERRORS 5011 +#define ID_COMPILER 5012 +#define ID_BREAKONSTARTOFTASK 5014 +#define ID_LOGRDPCOMMANDS 5015 +#define ID_CPUMETHOD_RECOMPILER 5016 +#define ID_CPUMETHOD_INTERPT 5017 +#define ID_SETTINGS_LOGX86CODE 5019 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 108 +#define _APS_NEXT_COMMAND_VALUE 5020 +#define _APS_NEXT_CONTROL_VALUE 1032 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/Source/Settings/Settings.cpp b/Source/Settings/Settings.cpp new file mode 100644 index 000000000..bc75215b7 --- /dev/null +++ b/Source/Settings/Settings.cpp @@ -0,0 +1,137 @@ +#include +#include +#include "Settings.h" + +enum SettingLocation { + ConstString = 0, ConstValue = 1, LocalSettings = 2, InRegistry = 3, RelativePath = 4, TemporarySetting = 5, + RomSetting = 6, CheatSetting = 7, GameSetting = 8, +}; + +enum SettingDataType { + Data_DWORD = 0, Data_String = 1, Data_CPUTYPE = 2, Data_SelfMod = 3, Data_OnOff = 4, Data_YesNo = 5, Data_SaveChip = 6 +}; + +typedef struct { + DWORD dwSize; + int DefaultStartRange; + int SettingStartRange; + int MaximumSettings; + int NoDefault; + int DefaultLocation; + void * handle; + unsigned int (*GetSetting) ( void * handle, int ID ); + const char * (*GetSettingSz) ( void * handle, int ID, char * Buffer, int BufferLen ); + void (*SetSetting) ( void * handle, int ID, unsigned int Value ); + void (*SetSettingSz) ( void * handle, int ID, const char * Value ); + void (*RegisterSetting) ( void * handle, int ID, int DefaultID, SettingDataType Type, + SettingLocation Location, const char * Category, const char * DefaultStr, DWORD Value ); + void (*UseUnregisteredSetting) (int ID); +} PLUGIN_SETTINGS; + +static PLUGIN_SETTINGS g_PluginSettings; +static bool g_PluginInitilized = false; +static char g_PluginSettingName[300]; + +extern "C" { +__declspec(dllexport) void SetSettingInfo (PLUGIN_SETTINGS * info); +} + + +__declspec(dllexport) void SetSettingInfo (PLUGIN_SETTINGS * info) +{ + g_PluginSettings = *info; + g_PluginInitilized = true; + info->UseUnregisteredSetting = UseUnregisteredSetting; +} + +BOOL SettingsInitilized ( void ) +{ + return g_PluginInitilized; +} + +void SetModuleName ( const char * Name ) +{ + _snprintf(g_PluginSettingName,sizeof(g_PluginSettingName),"%s",Name); +} + +void RegisterSetting ( short SettingID, SETTING_DATA_TYPE Type, const char * Name, const char * Category, + unsigned int DefaultDW, const char * DefaultStr ) +{ + int DefaultID = g_PluginSettings.NoDefault; + SettingLocation Location = (SettingLocation)g_PluginSettings.DefaultLocation; + char FullCategory[400]; + if (Category && Category[0] != 0) + { + _snprintf(FullCategory,sizeof(FullCategory),"%s\\%s",g_PluginSettingName,Category); + } else { + _snprintf(FullCategory,sizeof(FullCategory),"%s",g_PluginSettingName); + } + + switch (Type) + { + case Data_DWORD_Game: + case Data_String_Game: + Location = GameSetting; + break; + case Data_DWORD_RDB: + case Data_String_RDB: + Location = RomSetting; + break; + } + + switch (Type) + { + case Data_DWORD_General: + case Data_DWORD_Game: + case Data_DWORD_RDB: + if (DefaultDW != 0) + { + //create default + DefaultID = SettingID + g_PluginSettings.DefaultStartRange; + g_PluginSettings.RegisterSetting(g_PluginSettings.handle,DefaultID,g_PluginSettings.NoDefault, + Data_DWORD,ConstValue,g_PluginSettingName,"",DefaultDW); + } + + g_PluginSettings.RegisterSetting(g_PluginSettings.handle,SettingID + g_PluginSettings.SettingStartRange, + DefaultID,Data_DWORD,Location,FullCategory,Name,0); + break; + case Data_String_General: + case Data_String_Game: + case Data_String_RDB: + if (DefaultStr != NULL && strlen(DefaultStr) > 0) + { + //create default + DefaultID = SettingID + g_PluginSettings.DefaultStartRange; + g_PluginSettings.RegisterSetting(g_PluginSettings.handle,DefaultID,g_PluginSettings.NoDefault, + Data_String,ConstString,g_PluginSettingName,DefaultStr,0); + } + + g_PluginSettings.RegisterSetting(g_PluginSettings.handle,SettingID + g_PluginSettings.SettingStartRange, + DefaultID,Data_String,Location,FullCategory,Name,0); + break; + } +} + + +unsigned int GetSetting ( short SettingID ) +{ + return g_PluginSettings.GetSetting(g_PluginSettings.handle,SettingID + g_PluginSettings.SettingStartRange); +} + +const char * GetSettingSz ( short SettingID, char * Buffer, int BufferLen ) +{ + return g_PluginSettings.GetSettingSz(g_PluginSettings.handle,SettingID + g_PluginSettings.SettingStartRange,Buffer,BufferLen); +} + +void SetSetting ( short SettingID, unsigned int Value ) +{ + g_PluginSettings.SetSetting(g_PluginSettings.handle,SettingID + g_PluginSettings.SettingStartRange, Value); +} + +void SetSettingSz ( short SettingID, const char * Value ) +{ + g_PluginSettings.SetSettingSz(g_PluginSettings.handle,SettingID + g_PluginSettings.SettingStartRange, Value); +} + + + diff --git a/Source/Settings/Settings.dsp b/Source/Settings/Settings.dsp new file mode 100644 index 000000000..3ec1e5431 --- /dev/null +++ b/Source/Settings/Settings.dsp @@ -0,0 +1,100 @@ +# Microsoft Developer Studio Project File - Name="Settings" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Static Library" 0x0104 + +CFG=Settings - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "Settings.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "Settings.mak" CFG="Settings - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "Settings - Win32 Release" (based on "Win32 (x86) Static Library") +!MESSAGE "Settings - Win32 Debug" (based on "Win32 (x86) Static Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "Settings - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "../../Build/Settings/Release" +# PROP Intermediate_Dir "../../Build/Settings/Release" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c +# ADD CPP /nologo /MD /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c +# ADD BASE RSC /l 0xc09 /d "NDEBUG" +# ADD RSC /l 0xc09 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo + +!ELSEIF "$(CFG)" == "Settings - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "../../Build/Settings/Debug" +# PROP Intermediate_Dir "../../Build/Settings/Debug" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c +# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c +# ADD BASE RSC /l 0xc09 /d "_DEBUG" +# ADD RSC /l 0xc09 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo + +!ENDIF + +# Begin Target + +# Name "Settings - Win32 Release" +# Name "Settings - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=.\Settings.cpp +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Source File + +SOURCE=.\Settings.h +# End Source File +# End Group +# End Target +# End Project diff --git a/Source/Settings/Settings.h b/Source/Settings/Settings.h new file mode 100644 index 000000000..86b83d670 --- /dev/null +++ b/Source/Settings/Settings.h @@ -0,0 +1,36 @@ +#if defined(__cplusplus) +extern "C" { +#endif + +// Get Settings, take a setting id +unsigned int GetSetting ( short SettingID ); +const char * GetSettingSz ( short SettingID, char * Buffer, int BufferLen ); + +// Set a settings value +void SetSetting ( short SettingID, unsigned int Value ); +void SetSettingSz ( short SettingID, const char * Value ); + +// enum's +enum SETTING_DATA_TYPE { + Data_DWORD_General = 0, // A unsigned int setting used anywhere + Data_String_General = 1, // A string setting used anywhere + Data_DWORD_Game = 2, // A unsigned int associated with the current game + Data_String_Game = 3, // A string associated with the current game + Data_DWORD_RDB = 4, // A unsigned int associated with the current game in the rom database + Data_String_RDB = 5, // A string associated with the current game in the rom database +}; + + +// set other information about different settings +BOOL SettingsInitilized ( void ); +void SetModuleName ( const char * Name ); +void RegisterSetting ( short SettingID, SETTING_DATA_TYPE Type, const char * Name, const char * Category, + unsigned int DefaultDW, const char * DefaultStr ); + + +// this must be implemented to be notified when a setting is used but has not been set up +void UseUnregisteredSetting (int SettingID); + +#if defined(__cplusplus) +} +#endif diff --git a/Source/WTL/WTL.dsp b/Source/WTL/WTL.dsp index 8d0e41720..a509acca1 100644 --- a/Source/WTL/WTL.dsp +++ b/Source/WTL/WTL.dsp @@ -80,13 +80,89 @@ LIB32=link.exe -lib # Name "WTL - Win32 Release" # Name "WTL - Win32 Debug" -# Begin Group "Source Files" - -# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" -# End Group # Begin Group "Header Files" # PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Source File + +SOURCE=.\atlapp.h +# End Source File +# Begin Source File + +SOURCE=.\atlcrack.h +# End Source File +# Begin Source File + +SOURCE=.\atlctrls.h +# End Source File +# Begin Source File + +SOURCE=.\atlctrlw.h +# End Source File +# Begin Source File + +SOURCE=.\atlctrlx.h +# End Source File +# Begin Source File + +SOURCE=.\atlddx.h +# End Source File +# Begin Source File + +SOURCE=.\atldlgs.h +# End Source File +# Begin Source File + +SOURCE=.\atlfind.h +# End Source File +# Begin Source File + +SOURCE=.\atlframe.h +# End Source File +# Begin Source File + +SOURCE=.\atlgdi.h +# End Source File +# Begin Source File + +SOURCE=.\atlmisc.h +# End Source File +# Begin Source File + +SOURCE=.\atlprint.h +# End Source File +# Begin Source File + +SOURCE=.\atlres.h +# End Source File +# Begin Source File + +SOURCE=.\atlresce.h +# End Source File +# Begin Source File + +SOURCE=.\atlscrl.h +# End Source File +# Begin Source File + +SOURCE=.\atlsplit.h +# End Source File +# Begin Source File + +SOURCE=.\atltheme.h +# End Source File +# Begin Source File + +SOURCE=.\atluser.h +# End Source File +# Begin Source File + +SOURCE=.\atlwince.h +# End Source File +# Begin Source File + +SOURCE=.\atlwinx.h +# End Source File # End Group # End Target # End Project diff --git a/Source/WTL/vssver2.scc b/Source/WTL/vssver2.scc deleted file mode 100644 index 684177e7e..000000000 Binary files a/Source/WTL/vssver2.scc and /dev/null differ