diff options
| author | iCatButler <i.am.catbutler@gmail.com> | 2016-06-07 15:57:46 +0100 |
|---|---|---|
| committer | iCatButler <i.am.catbutler@gmail.com> | 2016-06-07 15:57:46 +0100 |
| commit | f70082329d751ee8a358437feb34134e283b27d8 (patch) | |
| tree | c97c99835067e9a20725943b4b4c63d44d4e3bdc /libpcsxcore | |
| parent | 7ecfee1f664eeb92b653104f5f3c915cc6fe6bcb (diff) | |
| download | pcsxr-f70082329d751ee8a358437feb34134e283b27d8.tar.gz | |
Initial PGXP CPU commit
- Restructured project to base interface on PSX instructions
- Support for all relevant CPU arithmetic and logic instructions
- Debug output available via deferred PGXP calls
- Remove most dependencies on PCSXR
- Still very much a work in progress (lots of errors)
- Add extra debug information to GPU plugin (w values)
Diffstat (limited to 'libpcsxcore')
| -rwxr-xr-x | libpcsxcore/gpu.c | 2 | ||||
| -rwxr-xr-x | libpcsxcore/gte.c | 1 | ||||
| -rwxr-xr-x | libpcsxcore/ix86/iR3000A.c | 1158 | ||||
| -rw-r--r-- | libpcsxcore/pgxp_cpu.c | 737 | ||||
| -rw-r--r-- | libpcsxcore/pgxp_cpu.h | 115 | ||||
| -rw-r--r-- | libpcsxcore/pgxp_debug.c | 314 | ||||
| -rw-r--r-- | libpcsxcore/pgxp_debug.h | 42 | ||||
| -rw-r--r-- | libpcsxcore/pgxp_gte.c | 438 | ||||
| -rw-r--r-- | libpcsxcore/pgxp_gte.h | 21 | ||||
| -rw-r--r-- | libpcsxcore/pgxp_mem.c | 206 | ||||
| -rw-r--r-- | libpcsxcore/pgxp_mem.h | 49 | ||||
| -rw-r--r-- | libpcsxcore/pgxp_value.h | 116 | ||||
| -rwxr-xr-x | libpcsxcore/r3000a.c | 2 |
13 files changed, 2715 insertions, 486 deletions
diff --git a/libpcsxcore/gpu.c b/libpcsxcore/gpu.c index 4ab01166..37367363 100755 --- a/libpcsxcore/gpu.c +++ b/libpcsxcore/gpu.c @@ -19,7 +19,7 @@ #include "psxhw.h" #include "gpu.h" #include "psxdma.h" -#include "pgxp_gte.h" +#include "pgxp_mem.h" #define GPUSTATUS_ODDLINES 0x80000000 #define GPUSTATUS_DMABITS 0x60000000 // Two bits diff --git a/libpcsxcore/gte.c b/libpcsxcore/gte.c index a1f3a35a..b902ea48 100755 --- a/libpcsxcore/gte.c +++ b/libpcsxcore/gte.c @@ -8,6 +8,7 @@ #include "gte.h" #include "psxmem.h" #include "pgxp_gte.h" +#include "pgxp_debug.h" #define GTE_SF(op) ((op >> 19) & 1) #define GTE_MX(op) ((op >> 17) & 3) diff --git a/libpcsxcore/ix86/iR3000A.c b/libpcsxcore/ix86/iR3000A.c index f835db37..726dbc3c 100755 --- a/libpcsxcore/ix86/iR3000A.c +++ b/libpcsxcore/ix86/iR3000A.c @@ -25,7 +25,8 @@ #include "ix86.h" #include <sys/mman.h> -#include "pgxp_gte.h" +#include "pgxp_cpu.h" +#include "pgxp_debug.h" #ifndef MAP_ANONYMOUS #define MAP_ANONYMOUS MAP_ANON @@ -553,6 +554,15 @@ static void recADDIU() { // iFlushRegs(); + #if PGXP_TRACE >= 1 // iCB: Tracing + if (IsConst(_Rs_)) + PUSH32I(iRegs[_Rs_].k); + else + PUSH32M((u32)&psxRegs.GPR.r[_Rs_]); + #endif // iCB: /Tracing + + + if (_Rs_ == _Rt_) { if (IsConst(_Rt_)) { iRegs[_Rt_].k+= _Imm_; @@ -582,11 +592,89 @@ static void recADDIU() { MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX); } } + + #if PGXP_TRACE >= 1 // iCB: Tracing + if (IsConst(_Rt_)) + PUSH32I(iRegs[_Rt_].k); + else + PUSH32M((u32)&psxRegs.GPR.r[_Rt_]); + + PUSH32I(psxRegs.code); +#ifdef PGXP_CPU_DEBUG + CALLFunc((u32)PGXP_psxTraceOp2); +#else + CALLFunc((u32)PGXP_CPU_ADDI); +#endif + resp += 12; + #endif // iCB: /Tracing } static void recADDI() { -// Rt = Rs + Im - recADDIU(); + // Rt = Rs + Im + if (!_Rt_) return; + + // iFlushRegs(); + +#if PGXP_TRACE >= 1 // iCB: Tracing + if (IsConst(_Rs_)) + PUSH32I(iRegs[_Rs_].k); + else + PUSH32M((u32)&psxRegs.GPR.r[_Rs_]); +#endif // iCB: /Tracing + + + + if (_Rs_ == _Rt_) { + if (IsConst(_Rt_)) { + iRegs[_Rt_].k += _Imm_; + } + else { + if (_Imm_ == 1) { + INC32M((u32)&psxRegs.GPR.r[_Rt_]); + } + else if (_Imm_ == -1) { + DEC32M((u32)&psxRegs.GPR.r[_Rt_]); + } + else if (_Imm_) { + ADD32ItoM((u32)&psxRegs.GPR.r[_Rt_], _Imm_); + } + } + } + else { + if (IsConst(_Rs_)) { + MapConst(_Rt_, iRegs[_Rs_].k + _Imm_); + } + else { + iRegs[_Rt_].state = ST_UNK; + + MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]); + if (_Imm_ == 1) { + INC32R(EAX); + } + else if (_Imm_ == -1) { + DEC32R(EAX); + } + else if (_Imm_) { + ADD32ItoR(EAX, _Imm_); + } + MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX); + } + } + +#if PGXP_TRACE >= 1 // iCB: Tracing + if (IsConst(_Rt_)) + PUSH32I(iRegs[_Rt_].k); + else + PUSH32M((u32)&psxRegs.GPR.r[_Rt_]); + + PUSH32I(psxRegs.code); +#ifdef PGXP_CPU_DEBUG + CALLFunc((u32)PGXP_psxTraceOp2); +#else + CALLFunc((u32)PGXP_CPU_ADDIU); +#endif + resp += 12; +#endif // iCB: /Tracing } static void recSLTI() { @@ -595,6 +683,13 @@ static void recSLTI() { // iFlushRegs(); + #if PGXP_TRACE >= 1 // iCB: Tracing + if (IsConst(_Rs_)) + PUSH32I(iRegs[_Rs_].k); + else + PUSH32M((u32)&psxRegs.GPR.r[_Rs_]); + #endif // iCB: /Tracing + if (IsConst(_Rs_)) { MapConst(_Rt_, (s32)iRegs[_Rs_].k < _Imm_); } else { @@ -606,6 +701,21 @@ static void recSLTI() { AND32ItoR(EAX, 0xff); MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX); } + + #if PGXP_TRACE >= 1 // iCB: Tracing + if (IsConst(_Rt_)) + PUSH32I(iRegs[_Rt_].k); + else + PUSH32M((u32)&psxRegs.GPR.r[_Rt_]); + + PUSH32I(psxRegs.code); +#ifdef PGXP_CPU_DEBUG + CALLFunc((u32)PGXP_psxTraceOp2); +#else + CALLFunc((u32)PGXP_CPU_SLTI); +#endif + resp += 12; + #endif // iCB: /Tracing } static void recSLTIU() { @@ -614,6 +724,13 @@ static void recSLTIU() { // iFlushRegs(); + #if PGXP_TRACE >= 1 // iCB: Tracing + if (IsConst(_Rs_)) + PUSH32I(iRegs[_Rs_].k); + else + PUSH32M((u32)&psxRegs.GPR.r[_Rs_]); + #endif // iCB: /Tracing + if (IsConst(_Rs_)) { MapConst(_Rt_, iRegs[_Rs_].k < _ImmU_); } else { @@ -625,6 +742,21 @@ static void recSLTIU() { AND32ItoR(EAX, 0xff); MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX); } + + #if PGXP_TRACE >= 1 // iCB: Tracing + if (IsConst(_Rt_)) + PUSH32I(iRegs[_Rt_].k); + else + PUSH32M((u32)&psxRegs.GPR.r[_Rt_]); + + PUSH32I(psxRegs.code); +#ifdef PGXP_CPU_DEBUG + CALLFunc((u32)PGXP_psxTraceOp2); +#else + CALLFunc((u32)PGXP_CPU_SLTIU); +#endif + resp += 12; + #endif // iCB: /Tracing } static void recANDI() { @@ -633,6 +765,13 @@ static void recANDI() { // iFlushRegs(); + #if PGXP_TRACE >= 1 // iCB: Tracing + if (IsConst(_Rs_)) + PUSH32I(iRegs[_Rs_].k); + else + PUSH32M((u32)&psxRegs.GPR.r[_Rs_]); + #endif // iCB: /Tracing + if (_Rs_ == _Rt_) { if (IsConst(_Rt_)) { iRegs[_Rt_].k&= _ImmU_; @@ -650,13 +789,33 @@ static void recANDI() { MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX); } } + + #if PGXP_TRACE >= 1 // iCB: Tracing + if (IsConst(_Rt_)) + PUSH32I(iRegs[_Rt_].k); + else + PUSH32M((u32)&psxRegs.GPR.r[_Rt_]); + + PUSH32I(psxRegs.code); +#ifdef PGXP_CPU_DEBUG + CALLFunc((u32)PGXP_psxTraceOp2); +#else + CALLFunc((u32)PGXP_CPU_ANDI); +#endif + resp += 12; + #endif // iCB: /Tracing } static void recORI() { // Rt = Rs Or Im if (!_Rt_) return; -// iFlushRegs(); + #if PGXP_TRACE >= 1 // iCB: Tracing + if (IsConst(_Rs_)) + PUSH32I(iRegs[_Rs_].k); + else + PUSH32M((u32)&psxRegs.GPR.r[_Rs_]); + #endif // iCB: /Tracing if (_Rs_ == _Rt_) { if (IsConst(_Rt_)) { @@ -675,13 +834,33 @@ static void recORI() { MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX); } } + + #if PGXP_TRACE >= 1 // iCB: Tracing + if (IsConst(_Rt_)) + PUSH32I(iRegs[_Rt_].k); + else + PUSH32M((u32)&psxRegs.GPR.r[_Rt_]); + + PUSH32I(psxRegs.code); +#ifdef PGXP_CPU_DEBUG + CALLFunc((u32)PGXP_psxTraceOp2); +#else + CALLFunc((u32)PGXP_CPU_ORI); +#endif + resp += 12; + #endif // iCB: /Tracing } static void recXORI() { // Rt = Rs Xor Im if (!_Rt_) return; -// iFlushRegs(); + #if PGXP_TRACE >= 1 // iCB: Tracing + if (IsConst(_Rs_)) + PUSH32I(iRegs[_Rs_].k); + else + PUSH32M((u32)&psxRegs.GPR.r[_Rs_]); + #endif // iCB: /Tracing if (_Rs_ == _Rt_) { if (IsConst(_Rt_)) { @@ -700,6 +879,21 @@ static void recXORI() { MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX); } } + + #if PGXP_TRACE >= 1 // iCB: Tracing + if (IsConst(_Rt_)) + PUSH32I(iRegs[_Rt_].k); + else + PUSH32M((u32)&psxRegs.GPR.r[_Rt_]); + + PUSH32I(psxRegs.code); +#ifdef PGXP_CPU_DEBUG + CALLFunc((u32)PGXP_psxTraceOp2); +#else + CALLFunc((u32)PGXP_CPU_XORI); +#endif + resp += 12; + #endif // iCB: /Tracing } //#endif //end of * Arithmetic with immediate operand @@ -715,6 +909,21 @@ static void recLUI() { if (!_Rt_) return; MapConst(_Rt_, psxRegs.code << 16); + + #if PGXP_TRACE >= 2 // iCB: Tracing + if (IsConst(_Rt_)) + PUSH32I(iRegs[_Rt_].k); + else + PUSH32M((u32)&psxRegs.GPR.r[_Rt_]); + + PUSH32I(psxRegs.code); +#ifdef PGXP_CPU_DEBUG + CALLFunc((u32)PGXP_psxTraceOp1); +#else + CALLFunc((u32)PGXP_CPU_LUI); +#endif + resp += 8; + #endif // iCB: /Tracing } //#endif //End of Load Higher ..... @@ -743,6 +952,19 @@ static void recADDU() { // iFlushRegs(); + #if PGXP_TRACE >= 3 // iCB: Tracing + if (IsConst(_Rt_)) + PUSH32I(iRegs[_Rt_].k); + else + PUSH32M((u32)&psxRegs.GPR.r[_Rt_]); + + if (IsConst(_Rs_)) + PUSH32I(iRegs[_Rs_].k); + else + PUSH32M((u32)&psxRegs.GPR.r[_Rs_]); + #endif // iCB: /Tracing + + if (IsConst(_Rs_) && IsConst(_Rt_)) { MapConst(_Rd_, iRegs[_Rs_].k + iRegs[_Rt_].k); } else if (IsConst(_Rs_)) { @@ -804,6 +1026,21 @@ static void recADDU() { MOV32RtoM((u32)&psxRegs.GPR.r[_Rd_], EAX); } } + + #if PGXP_TRACE >= 3 // iCB: Tracing + if (IsConst(_Rd_)) + PUSH32I(iRegs[_Rd_].k); + else + PUSH32M((u32)&psxRegs.GPR.r[_Rd_]); + + PUSH32I(psxRegs.code); +#ifdef PGXP_CPU_DEBUG + CALLFunc((u32)PGXP_psxTraceOp3); +#else + CALLFunc((u32)PGXP_CPU_ADDU); +#endif + resp += 16; + #endif // iCB: /Tracing } static void recADD() { @@ -817,6 +1054,18 @@ static void recSUBU() { // iFlushRegs(); + #if PGXP_TRACE >= 3 // iCB: Tracing + if (IsConst(_Rt_)) + PUSH32I(iRegs[_Rt_].k); + else + PUSH32M((u32)&psxRegs.GPR.r[_Rt_]); + + if (IsConst(_Rs_)) + PUSH32I(iRegs[_Rs_].k); + else + PUSH32M((u32)&psxRegs.GPR.r[_Rs_]); + #endif // iCB: /Tracing + if (IsConst(_Rs_) && IsConst(_Rt_)) { MapConst(_Rd_, iRegs[_Rs_].k - iRegs[_Rt_].k); } else if (IsConst(_Rs_)) { @@ -838,6 +1087,21 @@ static void recSUBU() { SUB32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rt_]); MOV32RtoM((u32)&psxRegs.GPR.r[_Rd_], EAX); } + + #if PGXP_TRACE >= 3 // iCB: Tracing + if (IsConst(_Rd_)) + PUSH32I(iRegs[_Rd_].k); + else + PUSH32M((u32)&psxRegs.GPR.r[_Rd_]); + + PUSH32I(psxRegs.code); +#ifdef PGXP_CPU_DEBUG + CALLFunc((u32)PGXP_psxTraceOp3); +#else + CALLFunc((u32)PGXP_CPU_SUBU); +#endif + resp += 16; + #endif // iCB: /Tracing } static void recSUB() { @@ -851,6 +1115,18 @@ static void recAND() { // iFlushRegs(); + #if PGXP_TRACE >= 3 // iCB: Tracing + if (IsConst(_Rt_)) + PUSH32I(iRegs[_Rt_].k); + else + PUSH32M((u32)&psxRegs.GPR.r[_Rt_]); + + if (IsConst(_Rs_)) + PUSH32I(iRegs[_Rs_].k); + else + PUSH32M((u32)&psxRegs.GPR.r[_Rs_]); + #endif // iCB: /Tracing + if (IsConst(_Rs_) && IsConst(_Rt_)) { MapConst(_Rd_, iRegs[_Rs_].k & iRegs[_Rt_].k); } else if (IsConst(_Rs_)) { @@ -888,6 +1164,21 @@ static void recAND() { MOV32RtoM((u32)&psxRegs.GPR.r[_Rd_], EAX); } } + + #if PGXP_TRACE >= 3 // iCB: Tracing + if (IsConst(_Rd_)) + PUSH32I(iRegs[_Rd_].k); + else + PUSH32M((u32)&psxRegs.GPR.r[_Rd_]); + + PUSH32I(psxRegs.code); +#ifdef PGXP_CPU_DEBUG + CALLFunc((u32)PGXP_psxTraceOp3); +#else + CALLFunc((u32)PGXP_CPU_AND); +#endif + resp += 16; + #endif // iCB: /Tracing } static void recOR() { @@ -896,6 +1187,18 @@ static void recOR() { // iFlushRegs(); + #if PGXP_TRACE >= 3 // iCB: Tracing + if (IsConst(_Rt_)) + PUSH32I(iRegs[_Rt_].k); + else + PUSH32M((u32)&psxRegs.GPR.r[_Rt_]); + + if (IsConst(_Rs_)) + PUSH32I(iRegs[_Rs_].k); + else + PUSH32M((u32)&psxRegs.GPR.r[_Rs_]); + #endif // iCB: /Tracing + if (IsConst(_Rs_) && IsConst(_Rt_)) { MapConst(_Rd_, iRegs[_Rs_].k | iRegs[_Rt_].k); } else if (IsConst(_Rs_)) { @@ -917,6 +1220,21 @@ static void recOR() { OR32MtoR (EAX, (u32)&psxRegs.GPR.r[_Rt_]); MOV32RtoM((u32)&psxRegs.GPR.r[_Rd_], EAX); } + + #if PGXP_TRACE >= 3 // iCB: Tracing + if (IsConst(_Rd_)) + PUSH32I(iRegs[_Rd_].k); + else + PUSH32M((u32)&psxRegs.GPR.r[_Rd_]); + + PUSH32I(psxRegs.code); +#ifdef PGXP_CPU_DEBUG + CALLFunc((u32)PGXP_psxTraceOp3); +#else + CALLFunc((u32)PGXP_CPU_OR); +#endif + resp += 16; + #endif // iCB: /Tracing } static void recXOR() { @@ -925,6 +1243,18 @@ static void recXOR() { // iFlushRegs(); + #if PGXP_TRACE >= 3 // iCB: Tracing + if (IsConst(_Rt_)) + PUSH32I(iRegs[_Rt_].k); + else + PUSH32M((u32)&psxRegs.GPR.r[_Rt_]); + + if (IsConst(_Rs_)) + PUSH32I(iRegs[_Rs_].k); + else + PUSH32M((u32)&psxRegs.GPR.r[_Rs_]); + #endif // iCB: /Tracing + if (IsConst(_Rs_) && IsConst(_Rt_)) { MapConst(_Rd_, iRegs[_Rs_].k ^ iRegs[_Rt_].k); } else if (IsConst(_Rs_)) { @@ -946,6 +1276,21 @@ static void recXOR() { XOR32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rt_]); MOV32RtoM((u32)&psxRegs.GPR.r[_Rd_], EAX); } + + #if PGXP_TRACE >= 3 // iCB: Tracing + if (IsConst(_Rd_)) + PUSH32I(iRegs[_Rd_].k); + else + PUSH32M((u32)&psxRegs.GPR.r[_Rd_]); + + PUSH32I(psxRegs.code); +#ifdef PGXP_CPU_DEBUG + CALLFunc((u32)PGXP_psxTraceOp3); +#else + CALLFunc((u32)PGXP_CPU_XOR); +#endif + resp += 16; + #endif // iCB: /Tracing } static void recNOR() { @@ -954,6 +1299,18 @@ static void recNOR() { // iFlushRegs(); + #if PGXP_TRACE >= 3 // iCB: Tracing + if (IsConst(_Rt_)) + PUSH32I(iRegs[_Rt_].k); + else + PUSH32M((u32)&psxRegs.GPR.r[_Rt_]); + + if (IsConst(_Rs_)) + PUSH32I(iRegs[_Rs_].k); + else + PUSH32M((u32)&psxRegs.GPR.r[_Rs_]); + #endif // iCB: /Tracing + if (IsConst(_Rs_) && IsConst(_Rt_)) { MapConst(_Rd_, ~(iRegs[_Rs_].k | iRegs[_Rt_].k)); } else if (IsConst(_Rs_)) { @@ -978,6 +1335,21 @@ static void recNOR() { NOT32R (EAX); MOV32RtoM((u32)&psxRegs.GPR.r[_Rd_], EAX); } + + #if PGXP_TRACE >= 3 // iCB: Tracing + if (IsConst(_Rd_)) + PUSH32I(iRegs[_Rd_].k); + else + PUSH32M((u32)&psxRegs.GPR.r[_Rd_]); + + PUSH32I(psxRegs.code); +#ifdef PGXP_CPU_DEBUG + CALLFunc((u32)PGXP_psxTraceOp3); +#else + CALLFunc((u32)PGXP_CPU_NOR); +#endif + resp += 16; + #endif // iCB: /Tracing } static void recSLT() { @@ -986,6 +1358,18 @@ static void recSLT() { // iFlushRegs(); + #if PGXP_TRACE >= 3 // iCB: Tracing + if (IsConst(_Rt_)) + PUSH32I(iRegs[_Rt_].k); + else + PUSH32M((u32)&psxRegs.GPR.r[_Rt_]); + + if (IsConst(_Rs_)) + PUSH32I(iRegs[_Rs_].k); + else + PUSH32M((u32)&psxRegs.GPR.r[_Rs_]); + #endif // iCB: /Tracing + if (IsConst(_Rs_) && IsConst(_Rt_)) { MapConst(_Rd_, (s32)iRegs[_Rs_].k < (s32)iRegs[_Rt_].k); } else if (IsConst(_Rs_)) { @@ -1013,6 +1397,21 @@ static void recSLT() { AND32ItoR(EAX, 0xff); MOV32RtoM((u32)&psxRegs.GPR.r[_Rd_], EAX); } + + #if PGXP_TRACE >= 3 // iCB: Tracing + if (IsConst(_Rd_)) + PUSH32I(iRegs[_Rd_].k); + else + PUSH32M((u32)&psxRegs.GPR.r[_Rd_]); + + PUSH32I(psxRegs.code); +#ifdef PGXP_CPU_DEBUG + CALLFunc((u32)PGXP_psxTraceOp3); +#else + CALLFunc((u32)PGXP_CPU_SLT); +#endif + resp += 16; + #endif // iCB: /Tracing } static void recSLTU() { @@ -1021,6 +1420,18 @@ static void recSLTU() { // iFlushRegs(); + #if PGXP_TRACE >= 3 // iCB: Tracing + if (IsConst(_Rt_)) + PUSH32I(iRegs[_Rt_].k); + else + PUSH32M((u32)&psxRegs.GPR.r[_Rt_]); + + if (IsConst(_Rs_)) + PUSH32I(iRegs[_Rs_].k); + else + PUSH32M((u32)&psxRegs.GPR.r[_Rs_]); + #endif // iCB: /Tracing + if (IsConst(_Rs_) && IsConst(_Rt_)) { MapConst(_Rd_, iRegs[_Rs_].k < iRegs[_Rt_].k); } else if (IsConst(_Rs_)) { @@ -1048,6 +1459,21 @@ static void recSLTU() { NEG32R (EAX); MOV32RtoM((u32)&psxRegs.GPR.r[_Rd_], EAX); } + + #if PGXP_TRACE >= 3 // iCB: Tracing + if (IsConst(_Rd_)) + PUSH32I(iRegs[_Rd_].k); + else + PUSH32M((u32)&psxRegs.GPR.r[_Rd_]); + + PUSH32I(psxRegs.code); +#ifdef PGXP_CPU_DEBUG + CALLFunc((u32)PGXP_psxTraceOp3); +#else + CALLFunc((u32)PGXP_CPU_SLTU); +#endif + resp += 16; + #endif // iCB: /Tracing } //#endif //End of * Register arithmetic @@ -1067,11 +1493,35 @@ static void recMULT() { // iFlushRegs(); + #if PGXP_TRACE >= 4 // iCB: Tracing + if (IsConst(_Rt_)) + PUSH32I(iRegs[_Rt_].k); + else + PUSH32M((u32)&psxRegs.GPR.r[_Rt_]); + if (IsConst(_Rs_)) + PUSH32I(iRegs[_Rs_].k); + else + PUSH32M((u32)&psxRegs.GPR.r[_Rs_]); + #endif // iCB: /Tracing + if ((IsConst(_Rs_) && iRegs[_Rs_].k == 0) || (IsConst(_Rt_) && iRegs[_Rt_].k == 0)) { XOR32RtoR(EAX, EAX); MOV32RtoM((u32)&psxRegs.GPR.n.lo, EAX); MOV32RtoM((u32)&psxRegs.GPR.n.hi, EAX); + + #if PGXP_TRACE >= 4 // iCB: Tracing + PUSH32M((u32)&psxRegs.GPR.n.lo); + PUSH32M((u32)&psxRegs.GPR.n.hi); + + PUSH32I(psxRegs.code); +#ifdef PGXP_CPU_DEBUG + CALLFunc((u32)PGXP_psxTraceOp4); +#else + CALLFunc((u32)PGXP_CPU_MULT); +#endif + resp += 20; + #endif // iCB: /Tracing return; } @@ -1088,6 +1538,19 @@ static void recMULT() { } MOV32RtoM((u32)&psxRegs.GPR.n.lo, EAX); MOV32RtoM((u32)&psxRegs.GPR.n.hi, EDX); + + #if PGXP_TRACE >= 4 // iCB: Tracing + PUSH32M((u32)&psxRegs.GPR.n.lo); + PUSH32M((u32)&psxRegs.GPR.n.hi); + + PUSH32I(psxRegs.code); +#ifdef PGXP_CPU_DEBUG + CALLFunc((u32)PGXP_psxTraceOp4); +#else + CALLFunc((u32)PGXP_CPU_MULT); +#endif + resp += 20; + #endif // iCB: /Tracing } static void recMULTU() { @@ -1095,11 +1558,36 @@ static void recMULTU() { // iFlushRegs(); + #if PGXP_TRACE >= 4 // iCB: Tracing + if (IsConst(_Rt_)) + PUSH32I(iRegs[_Rt_].k); + else + PUSH32M((u32)&psxRegs.GPR.r[_Rt_]); + if (IsConst(_Rs_)) + PUSH32I(iRegs[_Rs_].k); + else + PUSH32M((u32)&psxRegs.GPR.r[_Rs_]); + #endif // iCB: /Tracing + + if ((IsConst(_Rs_) && iRegs[_Rs_].k == 0) || (IsConst(_Rt_) && iRegs[_Rt_].k == 0)) { XOR32RtoR(EAX, EAX); MOV32RtoM((u32)&psxRegs.GPR.n.lo, EAX); MOV32RtoM((u32)&psxRegs.GPR.n.hi, EAX); + + #if PGXP_TRACE >= 4 // iCB: Tracing + PUSH32M((u32)&psxRegs.GPR.n.lo); + PUSH32M((u32)&psxRegs.GPR.n.hi); + + PUSH32I(psxRegs.code); +#ifdef PGXP_CPU_DEBUG + CALLFunc((u32)PGXP_psxTraceOp4); +#else + CALLFunc((u32)PGXP_CPU_MULTU); +#endif + resp += 20; + #endif // iCB: /Tracing return; } @@ -1116,6 +1604,19 @@ static void recMULTU() { } MOV32RtoM((u32)&psxRegs.GPR.n.lo, EAX); MOV32RtoM((u32)&psxRegs.GPR.n.hi, EDX); + + #if PGXP_TRACE >= 4 // iCB: Tracing + PUSH32M((u32)&psxRegs.GPR.n.lo); + PUSH32M((u32)&psxRegs.GPR.n.hi); + + PUSH32I(psxRegs.code); +#ifdef PGXP_CPU_DEBUG + CALLFunc((u32)PGXP_psxTraceOp4); +#else + CALLFunc((u32)PGXP_CPU_MULTU); +#endif + resp += 20; + #endif // iCB: /Tracing } static void recDIV() { @@ -1123,6 +1624,18 @@ static void recDIV() { // iFlushRegs(); + #if PGXP_TRACE >= 4 // iCB: Tracing + if (IsConst(_Rt_)) + PUSH32I(iRegs[_Rt_].k); + else + PUSH32M((u32)&psxRegs.GPR.r[_Rt_]); + if (IsConst(_Rs_)) + PUSH32I(iRegs[_Rs_].k); + else + PUSH32M((u32)&psxRegs.GPR.r[_Rs_]); + #endif // iCB: /Tracing + + if (IsConst(_Rt_)) { if (iRegs[_Rt_].k == 0) { MOV32ItoM((u32)&psxRegs.GPR.n.lo, 0xffffffff); @@ -1132,6 +1645,19 @@ static void recDIV() { MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]); MOV32RtoM((u32)&psxRegs.GPR.n.hi, EAX); } + + #if PGXP_TRACE >= 4 // iCB: Tracing + PUSH32M((u32)&psxRegs.GPR.n.lo); + PUSH32M((u32)&psxRegs.GPR.n.hi); + + PUSH32I(psxRegs.code); +#ifdef PGXP_CPU_DEBUG + CALLFunc((u32)PGXP_psxTraceOp4); +#else + CALLFunc((u32)PGXP_CPU_DIV); +#endif + resp += 20; + #endif // iCB: /Tracing return; } MOV32ItoR(ECX, iRegs[_Rt_].k);// printf("divrtk %x\n", iRegs[_Rt_].k); @@ -1165,6 +1691,19 @@ static void recDIV() { x86SetJ8(j8Ptr[1]); } + + #if PGXP_TRACE >= 4 // iCB: Tracing + PUSH32M((u32)&psxRegs.GPR.n.lo); + PUSH32M((u32)&psxRegs.GPR.n.hi); + + PUSH32I(psxRegs.code); +#ifdef PGXP_CPU_DEBUG + CALLFunc((u32)PGXP_psxTraceOp4); +#else + CALLFunc((u32)PGXP_CPU_DIV); +#endif + resp += 20; + #endif // iCB: /Tracing } static void recDIVU() { @@ -1172,6 +1711,18 @@ static void recDIVU() { // iFlushRegs(); + #if PGXP_TRACE >= 4 // iCB: Tracing + if (IsConst(_Rt_)) + PUSH32I(iRegs[_Rt_].k); + else + PUSH32M((u32)&psxRegs.GPR.r[_Rt_]); + if (IsConst(_Rs_)) + PUSH32I(iRegs[_Rs_].k); + else + PUSH32M((u32)&psxRegs.GPR.r[_Rs_]); + #endif // iCB: /Tracing + + if (IsConst(_Rt_)) { if (iRegs[_Rt_].k == 0) { MOV32ItoM((u32)&psxRegs.GPR.n.lo, 0xffffffff); @@ -1181,6 +1732,19 @@ static void recDIVU() { MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]); MOV32RtoM((u32)&psxRegs.GPR.n.hi, EAX); } + + #if PGXP_TRACE >= 4 // iCB: Tracing + PUSH32M((u32)&psxRegs.GPR.n.lo); + PUSH32M((u32)&psxRegs.GPR.n.hi); + + PUSH32I(psxRegs.code); +#ifdef PGXP_CPU_DEBUG + CALLFunc((u32)PGXP_psxTraceOp4); +#else + CALLFunc((u32)PGXP_CPU_DIVU); +#endif + resp += 20; + #endif // iCB: /Tracing return; } MOV32ItoR(ECX, iRegs[_Rt_].k);// printf("divurtk %x\n", iRegs[_Rt_].k); @@ -1214,6 +1778,19 @@ static void recDIVU() { x86SetJ8(j8Ptr[1]); } + + #if PGXP_TRACE >= 4 // iCB: Tracing + PUSH32M((u32)&psxRegs.GPR.n.lo); + PUSH32M((u32)&psxRegs.GPR.n.hi); + + PUSH32I(psxRegs.code); +#ifdef PGXP_CPU_DEBUG + CALLFunc((u32)PGXP_psxTraceOp4); +#else + CALLFunc((u32)PGXP_CPU_DIVU); +#endif + resp += 20; + #endif // iCB: /Tracing } //#endif //End of * Register mult/div & Register trap logic @@ -1248,6 +1825,17 @@ static void iPushOfB() { } } +u8 PGXP_LB_psxMemRead8(u32 mem, u32 code) +{ + u8 value = psxMemRead8(mem); +#ifdef PGXP_CPU_DEBUG + PGXP_psxTraceOp2(code, value, mem); +#else + PGXP_CPU_LB(code, value, mem); +#endif + return value; +} + //#if 0 static void recLB() { // Rt = mem[Rs + Im] (signed) @@ -1270,6 +1858,18 @@ static void recLB() { MOVSX32M8toR(EAX, (u32)&psxM[addr & 0x1fffff]); MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX); + + // iCB: PGXP hook + PUSH32I(addr); + PUSH32M((u32)&psxRegs.GPR.r[_Rt_]); + PUSH32I(psxRegs.code); // iCB: Needed to extract reg and opcode +#ifdef PGXP_CPU_DEBUG + CALLFunc((u32)PGXP_psxTraceOp2); +#else + CALLFunc((u32)PGXP_CPU_LB); +#endif + resp += 12; + // iCB: PGXP /hook return; } if (t == 0x1f80 && addr < 0x1f801000) { @@ -1278,6 +1878,18 @@ static void recLB() { MOVSX32M8toR(EAX, (u32)&psxH[addr & 0xfff]); MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX); + + // iCB: PGXP hook + PUSH32I(addr); + PUSH32M((u32)&psxRegs.GPR.r[_Rt_]); + PUSH32I(psxRegs.code); // iCB: Needed to extract reg and opcode +#ifdef PGXP_CPU_DEBUG + CALLFunc((u32)PGXP_psxTraceOp2); +#else + CALLFunc((u32)PGXP_CPU_LB); +#endif + resp += 12; + // iCB: PGXP /hook return; } // SysPrintf("unhandled r8 %x\n", addr); @@ -1285,7 +1897,7 @@ static void recLB() { PUSH32I(psxRegs.code); // iCB: Needed to extract reg and opcode iPushOfB(); - CALLFunc((u32)PGXP_psxMemRead8Trace); + CALLFunc((u32)PGXP_LB_psxMemRead8); if (_Rt_) { iRegs[_Rt_].state = ST_UNK; MOVSX32R8toR(EAX, EAX); @@ -1295,6 +1907,17 @@ static void recLB() { resp+= 8; } +u8 PGXP_LBU_psxMemRead8(u32 mem, u32 code) +{ + u8 value = psxMemRead8(mem); +#ifdef PGXP_CPU_DEBUG + PGXP_psxTraceOp2(code, value, mem); +#else + PGXP_CPU_LBU(code, value, mem); +#endif + return value; +} + static void recLBU() { // Rt = mem[Rs + Im] (unsigned) @@ -1316,6 +1939,18 @@ static void recLBU() { MOVZX32M8toR(EAX, (u32)&psxM[addr & 0x1fffff]); MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX); + + // iCB: PGXP hook + PUSH32I(addr); + PUSH32M((u32)&psxRegs.GPR.r[_Rt_]); + PUSH32I(psxRegs.code); // iCB: Needed to extract reg and opcode +#ifdef PGXP_CPU_DEBUG + CALLFunc((u32)PGXP_psxTraceOp2); +#else + CALLFunc((u32)PGXP_CPU_LBU); +#endif + resp += 12; + // iCB: PGXP /hook return; } if (t == 0x1f80 && addr < 0x1f801000) { @@ -1324,6 +1959,18 @@ static void recLBU() { MOVZX32M8toR(EAX, (u32)&psxH[addr & 0xfff]); MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX); + + // iCB: PGXP hook + PUSH32I(addr); + PUSH32M((u32)&psxRegs.GPR.r[_Rt_]); + PUSH32I(psxRegs.code); // iCB: Needed to extract reg and opcode +#ifdef PGXP_CPU_DEBUG + CALLFunc((u32)PGXP_psxTraceOp2); +#else + CALLFunc((u32)PGXP_CPU_LBU); +#endif + resp += 12; + // iCB: PGXP /hook return; } // SysPrintf("unhandled r8u %x\n", addr); @@ -1331,7 +1978,7 @@ static void recLBU() { PUSH32I(psxRegs.code); // iCB: Needed to extract reg and opcode iPushOfB(); - CALLFunc((u32)PGXP_psxMemRead8Trace); + CALLFunc((u32)PGXP_LBU_psxMemRead8); if (_Rt_) { iRegs[_Rt_].state = ST_UNK; MOVZX32R8toR(EAX, EAX); @@ -1341,6 +1988,17 @@ static void recLBU() { resp+= 8; } +u16 PGXP_LH_psxMemRead16(u32 mem, u32 code) +{ + u16 value = psxMemRead16(mem); +#ifdef PGXP_CPU_DEBUG + PGXP_psxTraceOp2(code, value, mem); +#else + PGXP_CPU_LH(code, value, mem); +#endif + return value; +} + static void recLH() { // Rt = mem[Rs + Im] (signed) @@ -1362,6 +2020,18 @@ static void recLH() { MOVSX32M16toR(EAX, (u32)&psxM[addr & 0x1fffff]); MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX); + + // iCB: PGXP hook + PUSH32I(addr); + PUSH32M((u32)&psxRegs.GPR.r[_Rt_]); + PUSH32I(psxRegs.code); // iCB: Needed to extract reg and opcode +#ifdef PGXP_CPU_DEBUG + CALLFunc((u32)PGXP_psxTraceOp2); +#else + CALLFunc((u32)PGXP_CPU_LH); +#endif + resp += 12; + // iCB: PGXP /hook return; } if (t == 0x1f80 && addr < 0x1f801000) { @@ -1370,6 +2040,18 @@ static void recLH() { MOVSX32M16toR(EAX, (u32)&psxH[addr & 0xfff]); MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX); + + // iCB: PGXP hook + PUSH32I(addr); + PUSH32M((u32)&psxRegs.GPR.r[_Rt_]); + PUSH32I(psxRegs.code); // iCB: Needed to extract reg and opcode +#ifdef PGXP_CPU_DEBUG + CALLFunc((u32)PGXP_psxTraceOp2); +#else + CALLFunc((u32)PGXP_CPU_LH); +#endif + resp += 12; + // iCB: PGXP /hook return; } // SysPrintf("unhandled r16 %x\n", addr); @@ -1377,7 +2059,7 @@ static void recLH() { PUSH32I(psxRegs.code); // iCB: Needed to extract reg and opcode iPushOfB(); - CALLFunc((u32)PGXP_psxMemRead16Trace); + CALLFunc((u32)PGXP_LH_psxMemRead16); if (_Rt_) { iRegs[_Rt_].state = ST_UNK; MOVSX32R16toR(EAX, EAX); @@ -1387,6 +2069,17 @@ static void recLH() { resp+= 8; } +u16 PGXP_LHU_psxMemRead16(u32 mem, u32 code) +{ + u16 value = psxMemRead16(mem); +#ifdef PGXP_CPU_DEBUG + PGXP_psxTraceOp2(code, value, mem); +#else + PGXP_CPU_LHU(code, value, mem); +#endif + return value; +} + static void recLHU() { // Rt = mem[Rs + Im] (unsigned) @@ -1408,6 +2101,18 @@ static void recLHU() { MOVZX32M16toR(EAX, (u32)&psxM[addr & 0x1fffff]); MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX); + + // iCB: PGXP hook + PUSH32I(addr); + PUSH32M((u32)&psxRegs.GPR.r[_Rt_]); + PUSH32I(psxRegs.code); // iCB: Needed to extract reg and opcode +#ifdef PGXP_CPU_DEBUG + CALLFunc((u32)PGXP_psxTraceOp2); +#else + CALLFunc((u32)PGXP_CPU_LHU); +#endif + resp += 12; + // iCB: PGXP /hook return; } if (t == 0x1f80 && addr < 0x1f801000) { @@ -1416,6 +2121,18 @@ static void recLHU() { MOVZX32M16toR(EAX, (u32)&psxH[addr & 0xfff]); MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX); + + // iCB: PGXP hook + PUSH32I(addr); + PUSH32M((u32)&psxRegs.GPR.r[_Rt_]); + PUSH32I(psxRegs.code); // iCB: Needed to extract reg and opcode +#ifdef PGXP_CPU_DEBUG + CALLFunc((u32)PGXP_psxTraceOp2); +#else + CALLFunc((u32)PGXP_CPU_LHU); +#endif + resp += 12; + // iCB: PGXP /hook return; } if (t == 0x1f80) { @@ -1472,7 +2189,7 @@ static void recLHU() { PUSH32I(psxRegs.code); // iCB: Needed to extract reg and opcode iPushOfB(); - CALLFunc((u32)PGXP_psxMemRead16Trace); + CALLFunc((u32)PGXP_LHU_psxMemRead16); if (_Rt_) { iRegs[_Rt_].state = ST_UNK; MOVZX32R16toR(EAX, EAX); @@ -1482,6 +2199,17 @@ static void recLHU() { resp+= 8; } +u32 PGXP_LW_psxMemRead32(u32 mem, u32 code) +{ + u32 value = psxMemRead32(mem); +#ifdef PGXP_CPU_DEBUG + PGXP_psxTraceOp2(code, value, mem); +#else + PGXP_CPU_LW(code, value, mem); +#endif + return value; +} + static void recLW() { // Rt = mem[Rs + Im] (unsigned) @@ -1513,10 +2241,15 @@ static void recLW() { MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX); // iCB: PGXP hook - PUSH32I(psxRegs.code); // iCB: Needed to extract reg and opcode PUSH32I(addr); - CALLFunc((u32)PGXP_psxMemRead32Trace); - resp += 8; + PUSH32M((u32)&psxRegs.GPR.r[_Rt_]); + PUSH32I(psxRegs.code); // iCB: Needed to extract reg and opcode +#ifdef PGXP_CPU_DEBUG + CALLFunc((u32)PGXP_psxTraceOp2); +#else + CALLFunc((u32)PGXP_CPU_LW); +#endif + resp += 12; // iCB: PGXP /hook return; } @@ -1538,10 +2271,15 @@ static void recLW() { MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX); // iCB: PGXP hook - PUSH32I(psxRegs.code); // iCB: Needed to extract reg and opcode PUSH32I(addr); - CALLFunc((u32)PGXP_psxMemRead32Trace); - resp += 8; + PUSH32M((u32)&psxRegs.GPR.r[_Rt_]); + PUSH32I(psxRegs.code); // iCB: Needed to extract reg and opcode +#ifdef PGXP_CPU_DEBUG + CALLFunc((u32)PGXP_psxTraceOp2); +#else + CALLFunc((u32)PGXP_CPU_LW); +#endif + resp += 12; // iCB: PGXP /hook return; @@ -1567,7 +2305,7 @@ static void recLW() { PUSH32I(psxRegs.code); // iCB: Needed to extract reg and opcode iPushOfB(); - CALLFunc((u32)PGXP_psxMemRead32Trace); + CALLFunc((u32)PGXP_LW_psxMemRead32); if (_Rt_) { iRegs[_Rt_].state = ST_UNK; MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX); @@ -1590,6 +2328,17 @@ void iLWLk(u32 shift) { OR32RtoR (EAX, ECX); } +u32 PGXP_LWL_psxMemRead32(u32 mem, u32 code) +{ + u32 value = psxMemRead32(mem); +#ifdef PGXP_CPU_DEBUG + PGXP_psxTraceOp2(code, value, mem); +#else + PGXP_CPU_LWL(code, value, mem); +#endif + return value; +} + void recLWL() { // Rt = Rt Merge mem[Rs + Im] @@ -1613,10 +2362,15 @@ void recLWL() { MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX); // iCB: PGXP hook - PUSH32I(psxRegs.code); // iCB: Needed to extract reg and opcode PUSH32I(addr); - CALLFunc((u32)PGXP_psxMemRead32Trace); - resp += 8; + PUSH32M((u32)&psxRegs.GPR.r[_Rt_]); + PUSH32I(psxRegs.code); // iCB: Needed to extract reg and opcode +#ifdef PGXP_CPU_DEBUG + CALLFunc((u32)PGXP_psxTraceOp2); +#else + CALLFunc((u32)PGXP_CPU_LWL); +#endif + resp += 12; // iCB: PGXP /hook return; } @@ -1631,7 +2385,7 @@ void recLWL() { PUSH32I(psxRegs.code); // iCB: Needed to extract reg and opcode AND32ItoR(EAX, ~3); PUSH32R (EAX); - CALLFunc((u32)PGXP_psxMemRead32Trace); + CALLFunc((u32)PGXP_LWL_psxMemRead32); if (_Rt_) { ADD32ItoR(ESP, 8); @@ -1752,6 +2506,17 @@ void iLWRk(u32 shift) { OR32RtoR(EAX, ECX); } +u32 PGXP_LWR_psxMemRead32(u32 mem, u32 code) +{ + u32 value = psxMemRead32(mem); +#ifdef PGXP_CPU_DEBUG + PGXP_psxTraceOp2(code, value, mem); +#else + PGXP_CPU_LWR(code, value, mem); +#endif + return value; +} + void recLWR() { // Rt = Rt Merge mem[Rs + Im] @@ -1775,10 +2540,15 @@ void recLWR() { MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX); // iCB: PGXP hook - PUSH32I(psxRegs.code); // iCB: Needed to extract reg and opcode PUSH32I(addr); - CALLFunc((u32)PGXP_psxMemRead32Trace); - resp += 8; + PUSH32M((u32)&psxRegs.GPR.r[_Rt_]); + PUSH32I(psxRegs.code); // iCB: Needed to extract reg and opcode +#ifdef PGXP_CPU_DEBUG + CALLFunc((u32)PGXP_psxTraceOp2); +#else + CALLFunc((u32)PGXP_CPU_LWR); +#endif + resp += 12; // iCB: PGXP /hook return; } @@ -1794,7 +2564,7 @@ void recLWR() { PUSH32I(psxRegs.code); // iCB: Needed to extract reg and opcode AND32ItoR(EAX, ~3); PUSH32R (EAX); - CALLFunc((u32)PGXP_psxMemRead32Trace); + CALLFunc((u32)PGXP_LWR_psxMemRead32); if (_Rt_) { ADD32ItoR(ESP, 8); @@ -1825,6 +2595,16 @@ void recLWR() { } } +void PGXP_SB_psxMemWrite8(u32 addr, u16 value, u32 code) +{ +#ifdef PGXP_CPU_DEBUG + PGXP_psxTraceOp2(code, value, addr); +#else + PGXP_CPU_SH(code, value, addr); +#endif + psxMemWrite8(addr, value); +} + static void recSB() { // mem[Rs + Im] = Rt @@ -1856,6 +2636,23 @@ static void recSB() { MOV8MtoR(EAX, (u32)&psxRegs.GPR.r[_Rt_]); MOV8RtoM((u32)&psxH[addr & 0xfff], EAX); } + + // iCB: PGXP hook + PUSH32I(addr); + if (IsConst(_Rt_)) { + PUSH32I(iRegs[_Rt_].k); + } + else { + PUSH32M((u32)&psxRegs.GPR.r[_Rt_]); + } + PUSH32I(psxRegs.code); // iCB: Needed to extract reg and opcode +#ifdef PGXP_CPU_DEBUG + CALLFunc((u32)PGXP_psxTraceOp2); +#else + CALLFunc((u32)PGXP_CPU_SB); +#endif + resp += 12; + // iCB: PGXP /hook return; } // SysPrintf("unhandled w8 %x\n", addr); @@ -1868,11 +2665,21 @@ static void recSB() { PUSH32M ((u32)&psxRegs.GPR.r[_Rt_]); } iPushOfB(); - CALLFunc((u32)PGXP_psxMemWrite8Trace); + CALLFunc((u32)PGXP_SB_psxMemWrite8); // ADD32ItoR(ESP, 8); resp+= 12; } +void PGXP_SH_psxMemWrite16(u32 addr, u16 value, u32 code) +{ +#ifdef PGXP_CPU_DEBUG + PGXP_psxTraceOp2(code, value, addr); +#else + PGXP_CPU_SH(code, value, addr); +#endif + psxMemWrite16(addr, value); +} + static void recSH() { // mem[Rs + Im] = Rt @@ -1904,6 +2711,23 @@ static void recSH() { MOV16MtoR(EAX, (u32)&psxRegs.GPR.r[_Rt_]); MOV16RtoM((u32)&psxH[addr & 0xfff], EAX); } + + // iCB: PGXP hook + PUSH32I(addr); + if (IsConst(_Rt_)) { + PUSH32I(iRegs[_Rt_].k); + } + else { + PUSH32M((u32)&psxRegs.GPR.r[_Rt_]); + } + PUSH32I(psxRegs.code); // iCB: Needed to extract reg and opcode +#ifdef PGXP_CPU_DEBUG + CALLFunc((u32)PGXP_psxTraceOp2); +#else + CALLFunc((u32)PGXP_CPU_SH); +#endif + resp += 12; + // iCB: PGXP /hook return; } if (t == 0x1f80) { @@ -1931,11 +2755,21 @@ static void recSH() { PUSH32M ((u32)&psxRegs.GPR.r[_Rt_]); } iPushOfB(); - CALLFunc((u32)PGXP_psxMemWrite16Trace); + CALLFunc((u32)PGXP_SH_psxMemWrite16); // ADD32ItoR(ESP, 8); resp+= 12; } +void PGXP_SW_psxMemWrite32(u32 addr, u32 value, u32 code) +{ +#ifdef PGXP_CPU_DEBUG + PGXP_psxTraceOp2(code, value, addr); +#else + PGXP_CPU_SW(code, value, addr); +#endif + psxMemWrite32(addr, value); +} + static void recSW() { // mem[Rs + Im] = Rt @@ -1969,15 +2803,19 @@ static void recSW() { } // iCB: PGXP hook - PUSH32I(psxRegs.code); // iCB: Needed to extract reg and opcode + PUSH32I(addr); if (IsConst(_Rt_)) { PUSH32I(iRegs[_Rt_].k); } else { PUSH32M((u32)&psxRegs.GPR.r[_Rt_]); } - PUSH32I(addr); - CALLFunc((u32)PGXP_psxMemWrite32Trace); + PUSH32I(psxRegs.code); // iCB: Needed to extract reg and opcode +#ifdef PGXP_CPU_DEBUG + CALLFunc((u32)PGXP_psxTraceOp2); +#else + CALLFunc((u32)PGXP_CPU_SW); +#endif resp += 12; // iCB: PGXP /hook return; @@ -2001,15 +2839,19 @@ static void recSW() { } // iCB: PGXP hook - PUSH32I(psxRegs.code); // iCB: Needed to extract reg and opcode + PUSH32I(addr); if (IsConst(_Rt_)) { PUSH32I(iRegs[_Rt_].k); } else { PUSH32M((u32)&psxRegs.GPR.r[_Rt_]); } - PUSH32I(addr); - CALLFunc((u32)PGXP_psxMemWrite32Trace); + PUSH32I(psxRegs.code); // iCB: Needed to extract reg and opcode +#ifdef PGXP_CPU_DEBUG + CALLFunc((u32)PGXP_psxTraceOp2); +#else + CALLFunc((u32)PGXP_CPU_SW); +#endif resp += 12; // iCB: PGXP /hook return; @@ -2049,7 +2891,7 @@ static void recSW() { PUSH32M ((u32)&psxRegs.GPR.r[_Rt_]); } iPushOfB(); - CALLFunc((u32)PGXP_psxMemWrite32Trace); + CALLFunc((u32)PGXP_SW_psxMemWrite32); // ADD32ItoR(ESP, 8); resp+= 12; } @@ -2139,6 +2981,16 @@ void iSWLk(u32 shift) { OR32RtoR (EAX, ECX); } +void PGXP_SWL_psxMemWrite32(u32 addr, u32 value, u32 code) +{ +#ifdef PGXP_CPU_DEBUG + PGXP_psxTraceOp2(code, value, addr); +#else + PGXP_CPU_SWL(code, value, addr); +#endif + psxMemWrite32(addr, value); +} + void recSWL() { // mem[Rs + Im] = Rt Merge mem[Rs + Im] @@ -2160,15 +3012,19 @@ void recSWL() { MOV32RtoM((u32)&psxH[addr & 0xffc], EAX); // iCB: PGXP hook - PUSH32I(psxRegs.code); // iCB: Needed to extract reg and opcode + PUSH32I(addr); if (IsConst(_Rt_)) { PUSH32I(iRegs[_Rt_].k); } else { PUSH32M((u32)&psxRegs.GPR.r[_Rt_]); } - PUSH32I(addr); - CALLFunc((u32)PGXP_psxMemWrite32Trace); + PUSH32I(psxRegs.code); // iCB: Needed to extract reg and opcode +#ifdef PGXP_CPU_DEBUG + CALLFunc((u32)PGXP_psxTraceOp2); +#else + CALLFunc((u32)PGXP_CPU_SWL); +#endif resp += 12; // iCB: PGXP /hook return; @@ -2182,13 +3038,12 @@ void recSWL() { if (_Imm_) ADD32ItoR(EAX, _Imm_); } PUSH32R (EAX); - PUSH32I(psxRegs.code); // iCB: Needed to extract reg and opcode AND32ItoR(EAX, ~3); PUSH32R (EAX); - CALLFunc((u32)PGXP_psxMemRead32Trace); + CALLFunc((u32)psxMemRead32); - ADD32ItoR(ESP, 8); + ADD32ItoR(ESP, 4); POP32R (EDX); AND32ItoR(EDX, 0x3); // shift = addr & 3; @@ -2218,7 +3073,7 @@ void recSWL() { AND32ItoR(EAX, ~3); PUSH32R (EAX); - CALLFunc((u32)PGXP_psxMemWrite32Trace); + CALLFunc((u32)PGXP_SWL_psxMemWrite32); // ADD32ItoR(ESP, 8); resp+= 12; } @@ -2237,6 +3092,16 @@ void iSWRk(u32 shift) { OR32RtoR (EAX, ECX); } +void PGXP_SWR_psxMemWrite32(u32 addr, u32 value, u32 code) +{ +#ifdef PGXP_CPU_DEBUG + PGXP_psxTraceOp2(code, value, addr); +#else + PGXP_CPU_SWR(code, value, addr); +#endif + psxMemWrite32(addr, value); +} + void recSWR() { // mem[Rs + Im] = Rt Merge mem[Rs + Im] @@ -2258,15 +3123,19 @@ void recSWR() { MOV32RtoM((u32)&psxH[addr & 0xffc], EAX); // iCB: PGXP hook - PUSH32I(psxRegs.code); // iCB: Needed to extract reg and opcode + PUSH32I(addr); if (IsConst(_Rt_)) { PUSH32I(iRegs[_Rt_].k); } else { PUSH32M((u32)&psxRegs.GPR.r[_Rt_]); } - PUSH32I(addr); - CALLFunc((u32)PGXP_psxMemWrite32Trace); + PUSH32I(psxRegs.code); // iCB: Needed to extract reg and opcode +#ifdef PGXP_CPU_DEBUG + CALLFunc((u32)PGXP_psxTraceOp2); +#else + CALLFunc((u32)PGXP_CPU_SWR); +#endif resp += 12; // iCB: PGXP /hook return; @@ -2280,13 +3149,12 @@ void recSWR() { if (_Imm_) ADD32ItoR(EAX, _Imm_); } PUSH32R (EAX); - PUSH32I(psxRegs.code); // iCB: Needed to extract reg and opcode AND32ItoR(EAX, ~3); PUSH32R (EAX); - CALLFunc((u32)PGXP_psxMemRead32Trace); + CALLFunc((u32)psxMemRead32); - ADD32ItoR(ESP, 8); + ADD32ItoR(ESP, 4); POP32R (EDX); AND32ItoR(EDX, 0x3); // shift = addr & 3; @@ -2316,7 +3184,7 @@ void recSWR() { AND32ItoR(EAX, ~3); PUSH32R (EAX); - CALLFunc((u32)PGXP_psxMemWrite32Trace); + CALLFunc((u32)PGXP_SWR_psxMemWrite32); // ADD32ItoR(ESP, 8); resp += 12; } @@ -2332,6 +3200,14 @@ static void recSLL() { // iFlushRegs(); + #if PGXP_TRACE >= 5 // iCB: Tracing + if (IsConst(_Rt_)) + PUSH32I(iRegs[_Rt_].k); + else + PUSH32M((u32)&psxRegs.GPR.r[_Rt_]); + #endif // iCB: /Tracing + + if (IsConst(_Rt_)) { MapConst(_Rd_, iRegs[_Rt_].k << _Sa_); } else { @@ -2341,6 +3217,18 @@ static void recSLL() { if (_Sa_) SHL32ItoR(EAX, _Sa_); MOV32RtoM((u32)&psxRegs.GPR.r[_Rd_], EAX); } + + #if PGXP_TRACE >= 5 // iCB: Tracing + PUSH32M((u32)&psxRegs.GPR.r[_Rd_]); + + PUSH32I(psxRegs.code); +#ifdef PGXP_CPU_DEBUG + CALLFunc((u32)PGXP_psxTraceOp2); +#else + CALLFunc((u32)PGXP_CPU_SLL); +#endif + resp += 12; + #endif // iCB: /Tracing } static void recSRL() { @@ -2350,6 +3238,13 @@ static void recSRL() { // iFlushRegs(); + #if PGXP_TRACE >= 5 // iCB: Tracing + if (IsConst(_Rt_)) + PUSH32I(iRegs[_Rt_].k); + else + PUSH32M((u32)&psxRegs.GPR.r[_Rt_]); + #endif // iCB: /Tracing + if (IsConst(_Rt_)) { MapConst(_Rd_, iRegs[_Rt_].k >> _Sa_); } else { @@ -2359,6 +3254,18 @@ static void recSRL() { if (_Sa_) SHR32ItoR(EAX, _Sa_); MOV32RtoM((u32)&psxRegs.GPR.r[_Rd_], EAX); } + + #if PGXP_TRACE >= 5 // iCB: Tracing + PUSH32M((u32)&psxRegs.GPR.r[_Rd_]); + + PUSH32I(psxRegs.code); +#ifdef PGXP_CPU_DEBUG + CALLFunc((u32)PGXP_psxTraceOp2); +#else + CALLFunc((u32)PGXP_CPU_SRL); +#endif + resp += 12; + #endif // iCB: /Tracing } static void recSRA() { @@ -2368,6 +3275,13 @@ static void recSRA() { // iFlushRegs(); + #if PGXP_TRACE >= 5 // iCB: Tracing + if (IsConst(_Rt_)) + PUSH32I(iRegs[_Rt_].k); + else + PUSH32M((u32)&psxRegs.GPR.r[_Rt_]); + #endif // iCB: /Tracing + if (IsConst(_Rt_)) { MapConst(_Rd_, (s32)iRegs[_Rt_].k >> _Sa_); } else { @@ -2377,6 +3291,18 @@ static void recSRA() { if (_Sa_) SAR32ItoR(EAX, _Sa_); MOV32RtoM((u32)&psxRegs.GPR.r[_Rd_], EAX); } + + #if PGXP_TRACE >= 5 // iCB: Tracing + PUSH32M((u32)&psxRegs.GPR.r[_Rd_]); + + PUSH32I(psxRegs.code); +#ifdef PGXP_CPU_DEBUG + CALLFunc((u32)PGXP_psxTraceOp2); +#else + CALLFunc((u32)PGXP_CPU_SRA); +#endif + resp += 12; + #endif // iCB: /Tracing } //#endif @@ -2391,6 +3317,17 @@ static void recSLLV() { // iFlushRegs(); + #if PGXP_TRACE >= 6 // iCB: Tracing + if (IsConst(_Rs_)) + PUSH32I(iRegs[_Rs_].k); + else + PUSH32M((u32)&psxRegs.GPR.r[_Rs_]); + if (IsConst(_Rt_)) + PUSH32I(iRegs[_Rt_].k); + else + PUSH32M((u32)&psxRegs.GPR.r[_Rt_]); + #endif // iCB: /Tracing + if (IsConst(_Rt_) && IsConst(_Rs_)) { MapConst(_Rd_, iRegs[_Rt_].k << iRegs[_Rs_].k); } else if (IsConst(_Rs_)) { @@ -2415,6 +3352,18 @@ static void recSLLV() { SHL32CLtoR(EAX); MOV32RtoM((u32)&psxRegs.GPR.r[_Rd_], EAX); } + + #if PGXP_TRACE >= 6 // iCB: Tracing + PUSH32M((u32)&psxRegs.GPR.r[_Rd_]); + + PUSH32I(psxRegs.code); +#ifdef PGXP_CPU_DEBUG + CALLFunc((u32)PGXP_psxTraceOp3); +#else + CALLFunc((u32)PGXP_CPU_SLLV); +#endif + resp += 16; + #endif // iCB: /Tracing } static void recSRLV() { @@ -2423,6 +3372,17 @@ static void recSRLV() { // iFlushRegs(); + #if PGXP_TRACE >= 6 // iCB: Tracing + if (IsConst(_Rs_)) + PUSH32I(iRegs[_Rs_].k); + else + PUSH32M((u32)&psxRegs.GPR.r[_Rs_]); + if (IsConst(_Rt_)) + PUSH32I(iRegs[_Rt_].k); + else + PUSH32M((u32)&psxRegs.GPR.r[_Rt_]); + #endif // iCB: /Tracing + if (IsConst(_Rt_) && IsConst(_Rs_)) { MapConst(_Rd_, iRegs[_Rt_].k >> iRegs[_Rs_].k); } else if (IsConst(_Rs_)) { @@ -2447,6 +3407,18 @@ static void recSRLV() { SHR32CLtoR(EAX); MOV32RtoM((u32)&psxRegs.GPR.r[_Rd_], EAX); } + + #if PGXP_TRACE >= 6 // iCB: Tracing + PUSH32M((u32)&psxRegs.GPR.r[_Rd_]); + + PUSH32I(psxRegs.code); +#ifdef PGXP_CPU_DEBUG + CALLFunc((u32)PGXP_psxTraceOp3); +#else + CALLFunc((u32)PGXP_CPU_SRLV); +#endif + resp += 16; + #endif // iCB: /Tracing } static void recSRAV() { @@ -2456,6 +3428,17 @@ static void recSRAV() { // iFlushRegs(); + #if PGXP_TRACE >= 6 // iCB: Tracing + if (IsConst(_Rs_)) + PUSH32I(iRegs[_Rs_].k); + else + PUSH32M((u32)&psxRegs.GPR.r[_Rs_]); + if (IsConst(_Rt_)) + PUSH32I(iRegs[_Rt_].k); + else + PUSH32M((u32)&psxRegs.GPR.r[_Rt_]); + #endif // iCB: /Tracing + if (IsConst(_Rt_) && IsConst(_Rs_)) { MapConst(_Rd_, (s32)iRegs[_Rt_].k >> iRegs[_Rs_].k); } else if (IsConst(_Rs_)) { @@ -2480,6 +3463,18 @@ static void recSRAV() { SAR32CLtoR(EAX); MOV32RtoM((u32)&psxRegs.GPR.r[_Rd_], EAX); } + + #if PGXP_TRACE >= 6 // iCB: Tracing + PUSH32M((u32)&psxRegs.GPR.r[_Rd_]); + + PUSH32I(psxRegs.code); +#ifdef PGXP_CPU_DEBUG + CALLFunc((u32)PGXP_psxTraceOp3); +#else + CALLFunc((u32)PGXP_CPU_SRAV); +#endif + resp += 16; + #endif // iCB: /Tracing } //#endif @@ -2517,20 +3512,55 @@ static void recMFHI() { if (!_Rd_) return; + #if PGXP_TRACE >= 7 // iCB: Tracing + PUSH32M((u32)&psxRegs.GPR.n.hi); + #endif // iCB: /Tracing + iRegs[_Rd_].state = ST_UNK; MOV32MtoR(EAX, (u32)&psxRegs.GPR.n.hi); MOV32RtoM((u32)&psxRegs.GPR.r[_Rd_], EAX); + + #if PGXP_TRACE >= 7 // iCB: Tracing + PUSH32M((u32)&psxRegs.GPR.r[_Rd_]); + + PUSH32I(psxRegs.code); +#ifdef PGXP_CPU_DEBUG + CALLFunc((u32)PGXP_psxTraceOp2); +#else + CALLFunc((u32)PGXP_CPU_MFHI); +#endif + resp += 12; + #endif // iCB: /Tracing } static void recMTHI() { // Hi = Rs + #if PGXP_TRACE >= 7 // iCB: Tracing + if (IsConst(_Rs_)) + PUSH32I(iRegs[_Rs_].k); + else + PUSH32M((u32)&psxRegs.GPR.r[_Rs_]); + #endif // iCB: /Tracing + if (IsConst(_Rs_)) { MOV32ItoM((u32)&psxRegs.GPR.n.hi, iRegs[_Rs_].k); } else { MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]); MOV32RtoM((u32)&psxRegs.GPR.n.hi, EAX); } + + #if PGXP_TRACE >= 7 // iCB: Tracing + PUSH32M((u32)&psxRegs.GPR.n.hi); + + PUSH32I(psxRegs.code); +#ifdef PGXP_CPU_DEBUG + CALLFunc((u32)PGXP_psxTraceOp2); +#else + CALLFunc((u32)PGXP_CPU_MTHI); +#endif + resp += 12; + #endif // iCB: /Tracing } static void recMFLO() { @@ -2538,20 +3568,54 @@ static void recMFLO() { if (!_Rd_) return; + #if PGXP_TRACE >= 7 // iCB: Tracing + PUSH32M((u32)&psxRegs.GPR.n.lo); + #endif // iCB: /Tracing + iRegs[_Rd_].state = ST_UNK; MOV32MtoR(EAX, (u32)&psxRegs.GPR.n.lo); MOV32RtoM((u32)&psxRegs.GPR.r[_Rd_], EAX); + + #if PGXP_TRACE >= 7 // iCB: Tracing + PUSH32M((u32)&psxRegs.GPR.r[_Rd_]); + PUSH32I(psxRegs.code); +#ifdef PGXP_CPU_DEBUG + CALLFunc((u32)PGXP_psxTraceOp2); +#else + CALLFunc((u32)PGXP_CPU_MFLO); +#endif + resp += 12; + #endif // iCB: /Tracing } static void recMTLO() { // Lo = Rs + #if PGXP_TRACE >= 7 // iCB: Tracing + if (IsConst(_Rs_)) + PUSH32I(iRegs[_Rs_].k); + else + PUSH32M((u32)&psxRegs.GPR.r[_Rs_]); + #endif // iCB: /Tracing + if (IsConst(_Rs_)) { MOV32ItoM((u32)&psxRegs.GPR.n.lo, iRegs[_Rs_].k); } else { MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]); MOV32RtoM((u32)&psxRegs.GPR.n.lo, EAX); } + + #if PGXP_TRACE >= 7 // iCB: Tracing + PUSH32M((u32)&psxRegs.GPR.n.lo); + + PUSH32I(psxRegs.code); +#ifdef PGXP_CPU_DEBUG + CALLFunc((u32)PGXP_psxTraceOp2); +#else + CALLFunc((u32)PGXP_CPU_MTLO); +#endif + resp += 12; + #endif // iCB: /Tracing } //#endif diff --git a/libpcsxcore/pgxp_cpu.c b/libpcsxcore/pgxp_cpu.c new file mode 100644 index 00000000..60e623e5 --- /dev/null +++ b/libpcsxcore/pgxp_cpu.c @@ -0,0 +1,737 @@ + +#include "pgxp_cpu.h" +#include "pgxp_value.h" +#include "pgxp_mem.h" + +// CPU registers +PGXP_value CPU_reg_mem[34]; +//PGXP_value CPU_Hi, CPU_Lo; + +PGXP_value* CPU_reg = CPU_reg_mem; + +// Instruction register decoding +#define op(_instr) (_instr >> 26) // The op part of the instruction register +#define func(_instr) ((_instr) & 0x3F) // The funct part of the instruction register +#define sa(_instr) ((_instr >> 6) & 0x1F) // The sa part of the instruction register +#define rd(_instr) ((_instr >> 11) & 0x1F) // The rd part of the instruction register +#define rt(_instr) ((_instr >> 16) & 0x1F) // The rt part of the instruction register +#define rs(_instr) ((_instr >> 21) & 0x1F) // The rs part of the instruction register +#define imm(_instr) (_instr & 0xFFFF) // The immediate part of the instruction register + +// invalidate register (invalid 8 bit read) +void InvalidLoad(u32 addr, u32 code, u32 value) +{ + u32 reg = ((code >> 16) & 0x1F); // The rt part of the instruction register + PGXP_value* pD = NULL; + PGXP_value p; + + p.x = p.y = -1337; // default values + + //p.valid = 0; + //p.count = value; + pD = ReadMem(addr); + + if (pD) + { + p.count = addr; + p = *pD; + } + else + { + p.count = value; + } + + p.valid = 0; + + // invalidate register + CPU_reg[reg] = p; +} + +// invalidate memory address (invalid 8 bit write) +void InvalidStore(u32 addr, u32 code, u32 value) +{ + u32 reg = ((code >> 16) & 0x1F); // The rt part of the instruction register + PGXP_value* pD = NULL; + PGXP_value p; + + pD = ReadMem(addr); + + p.x = p.y = -2337; + + if (pD) + p = *pD; + + p.valid = 0; + p.count = (reg * 1000) + value; + + // invalidate memory + WriteMem(&p, addr); +} + +//////////////////////////////////// +// Arithmetic with immediate value +//////////////////////////////////// +void PGXP_CPU_ADDI(u32 instr, u32 rtVal, u32 rsVal) +{ + // Rt = Rs + Imm (signed) + psx_value tempImm; + + Validate(&CPU_reg[rs(instr)], rsVal); + CPU_reg[rt(instr)] = CPU_reg[rs(instr)]; + + tempImm.w.h = imm(instr); + CPU_reg[rt(instr)].x += tempImm.sw.h; + // handle x overflow in to y? + + CPU_reg[rt(instr)].value = rtVal; +} + +void PGXP_CPU_ADDIU(u32 instr, u32 rtVal, u32 rsVal) +{ + // Rt = Rs + Imm (signed) (unsafe?) + psx_value tempImm; + + Validate(&CPU_reg[rs(instr)], rsVal); + CPU_reg[rt(instr)] = CPU_reg[rs(instr)]; + + tempImm.w.h = imm(instr); + CPU_reg[rt(instr)].x += tempImm.sw.h; + // handle x overflow in to y? + + CPU_reg[rt(instr)].value = rtVal; +} + +void PGXP_CPU_ANDI(u32 instr, u32 rtVal, u32 rsVal) +{ + // Rt = Rs & Imm + Validate(&CPU_reg[rs(instr)], rsVal); + CPU_reg[rt(instr)] = CPU_reg[rs(instr)]; + + CPU_reg[rt(instr)].y = 0.f; // remove upper 16-bits + + switch (imm(instr)) + { + case 0: + // if 0 then x == 0 + CPU_reg[rt(instr)].x = 0.f; + break; + case 0xFFFF: + // if saturated then x = x + break; + default: + // x is undefined, invalidate value + CPU_reg[rt(instr)].valid = 0; + } + + CPU_reg[rt(instr)].value = rtVal; +} + +void PGXP_CPU_ORI(u32 instr, u32 rtVal, u32 rsVal) +{ + // Rt = Rs | Imm + Validate(&CPU_reg[rs(instr)], rsVal); + CPU_reg[rt(instr)] = CPU_reg[rs(instr)]; + + // Invalidate on non-zero values for now + if (imm(instr) != 0) + CPU_reg[rt(instr)].valid = 0; + + CPU_reg[rt(instr)].value = rtVal; +} + +void PGXP_CPU_XORI(u32 instr, u32 rtVal, u32 rsVal) +{ + // Rt = Rs ^ Imm + Validate(&CPU_reg[rs(instr)], rsVal); + CPU_reg[rt(instr)] = CPU_reg[rs(instr)]; + + // Invalidate on non-zero values for now + if (imm(instr) != 0) + CPU_reg[rt(instr)].valid = 0; + + CPU_reg[rt(instr)].value = rtVal; +} + +void PGXP_CPU_SLTI(u32 instr, u32 rtVal, u32 rsVal) +{ + // Rt = Rs < Imm (signed) + psx_value tempImm; + + Validate(&CPU_reg[rs(instr)], rsVal); + CPU_reg[rt(instr)] = CPU_reg[rs(instr)]; + + tempImm.w.h = imm(instr); + CPU_reg[rt(instr)].y = 0.f; + CPU_reg[rt(instr)].x = (CPU_reg[rs(instr)].x < tempImm.sw.h) ? 1.f : 0.f; + + CPU_reg[rt(instr)].value = rtVal; +} + +void PGXP_CPU_SLTIU(u32 instr, u32 rtVal, u32 rsVal) +{ + // Rt = Rs < Imm (signed) + Validate(&CPU_reg[rs(instr)], rsVal); + CPU_reg[rt(instr)] = CPU_reg[rs(instr)]; + + CPU_reg[rt(instr)].y = 0.f; + CPU_reg[rt(instr)].x = (fabs(CPU_reg[rs(instr)].x) < (u32)imm(instr)) ? 1.f : 0.f; + + CPU_reg[rt(instr)].value = rtVal; +} + +//////////////////////////////////// +// Load Upper +//////////////////////////////////// +void PGXP_CPU_LUI(u32 instr, u32 rtVal) +{ + //Rt = Imm << 16 + CPU_reg[rt(instr)] = PGXP_value_zero; + CPU_reg[rt(instr)].y = (float)(s16)imm(instr); + CPU_reg[rt(instr)].hFlags = VALID_HALF; + CPU_reg[rt(instr)].value = rtVal; +} + +//////////////////////////////////// +// Register Arithmetic +//////////////////////////////////// +void PGXP_CPU_ADD(u32 instr, u32 rdVal, u32 rsVal, u32 rtVal) +{ + // Rd = Rs + Rt (signed) + Validate(&CPU_reg[rs(instr)], rsVal); + Validate(&CPU_reg[rt(instr)], rtVal); + + // iCB: Only require one valid input + if (!(CPU_reg[rs(instr)].valid && CPU_reg[rt(instr)].valid) && (CPU_reg[rs(instr)].valid || CPU_reg[rt(instr)].valid)) + { + MakeValid(&CPU_reg[rs(instr)], rsVal); + MakeValid(&CPU_reg[rt(instr)], rtVal); + } + + CPU_reg[rd(instr)] = CPU_reg[rs(instr)]; + + CPU_reg[rd(instr)].x += CPU_reg[rt(instr)].x; + CPU_reg[rd(instr)].y += CPU_reg[rt(instr)].y; + + CPU_reg[rd(instr)].valid &= CPU_reg[rt(instr)].valid; + CPU_reg[rd(instr)].gFlags |= CPU_reg[rt(instr)].gFlags; + CPU_reg[rd(instr)].lFlags |= CPU_reg[rt(instr)].lFlags; + CPU_reg[rd(instr)].hFlags |= CPU_reg[rt(instr)].hFlags; + + CPU_reg[rd(instr)].value = rdVal; +} + +void PGXP_CPU_ADDU(u32 instr, u32 rdVal, u32 rsVal, u32 rtVal) +{ + // Rd = Rs + Rt (signed) (unsafe?) + PGXP_CPU_ADD(instr, rdVal, rsVal, rtVal); +} + +void PGXP_CPU_SUB(u32 instr, u32 rdVal, u32 rsVal, u32 rtVal) +{ + // Rd = Rs - Rt (signed) + Validate(&CPU_reg[rs(instr)], rsVal); + Validate(&CPU_reg[rt(instr)], rtVal); + + // iCB: Only require one valid input + //if (!(CPU_reg[rs(instr)].valid && CPU_reg[rt(instr)].valid) && (CPU_reg[rs(instr)].valid || CPU_reg[rt(instr)].valid)) + //{ + // MakeValid(&CPU_reg[rs(instr)], rsVal); + // MakeValid(&CPU_reg[rt(instr)], rtVal); + //} + + CPU_reg[rd(instr)] = CPU_reg[rs(instr)]; + + CPU_reg[rd(instr)].x -= CPU_reg[rt(instr)].x; + CPU_reg[rd(instr)].y -= CPU_reg[rt(instr)].y; + + CPU_reg[rd(instr)].valid &= CPU_reg[rt(instr)].valid; + CPU_reg[rd(instr)].gFlags |= CPU_reg[rt(instr)].gFlags; + CPU_reg[rd(instr)].lFlags |= CPU_reg[rt(instr)].lFlags; + CPU_reg[rd(instr)].hFlags |= CPU_reg[rt(instr)].hFlags; + + CPU_reg[rd(instr)].value = rdVal; +} + +void PGXP_CPU_SUBU(u32 instr, u32 rdVal, u32 rsVal, u32 rtVal) +{ + // Rd = Rs - Rt (signed) (unsafe?) + PGXP_CPU_SUB(instr, rdVal, rsVal, rtVal); +} + +void PGXP_CPU_AND(u32 instr, u32 rdVal, u32 rsVal, u32 rtVal) +{ + // Rd = Rs & Rt + psx_value vald, vals, valt; + + Validate(&CPU_reg[rs(instr)], rsVal); + Validate(&CPU_reg[rt(instr)], rtVal); + + // iCB: Only require one valid input + //if (!(CPU_reg[rs(instr)].valid && CPU_reg[rt(instr)].valid) && (CPU_reg[rs(instr)].valid || CPU_reg[rt(instr)].valid)) + //{ + // MakeValid(&CPU_reg[rs(instr)], rsVal); + // MakeValid(&CPU_reg[rt(instr)], rtVal); + //} + + vald.d = rdVal; + vals.d = rsVal; + valt.d = rtVal; + + // CPU_reg[rd(instr)].valid = CPU_reg[rs(instr)].valid && CPU_reg[rt(instr)].valid; + CPU_reg[rd(instr)].valid = 1; + + if (vald.w.l == 0) + { + CPU_reg[rd(instr)].x = 0.f; + CPU_reg[rd(instr)].lFlags = VALID_HALF; + } + else if (vald.w.l == vals.w.l) + { + CPU_reg[rd(instr)].x = CPU_reg[rs(instr)].x; + CPU_reg[rd(instr)].lFlags = CPU_reg[rs(instr)].lFlags; + CPU_reg[rd(instr)].valid &= CPU_reg[rs(instr)].valid; + } + else if (vald.w.l == valt.w.l) + { + CPU_reg[rd(instr)].x = CPU_reg[rt(instr)].x; + CPU_reg[rd(instr)].lFlags = CPU_reg[rt(instr)].lFlags; + CPU_reg[rd(instr)].valid &= CPU_reg[rt(instr)].valid; + } + else + { + CPU_reg[rd(instr)].valid = 0; + CPU_reg[rd(instr)].lFlags = 0; + } + + if (vald.w.h == 0) + { + CPU_reg[rd(instr)].y = 0.f; + CPU_reg[rd(instr)].hFlags = VALID_HALF; + } + else if (vald.w.h == vals.w.h) + { + CPU_reg[rd(instr)].y = CPU_reg[rs(instr)].y; + CPU_reg[rd(instr)].hFlags = CPU_reg[rs(instr)].hFlags; + CPU_reg[rd(instr)].valid &= CPU_reg[rs(instr)].valid; + } + else if (vald.w.h == valt.w.h) + { + CPU_reg[rd(instr)].y = CPU_reg[rt(instr)].y; + CPU_reg[rd(instr)].hFlags = CPU_reg[rt(instr)].hFlags; + CPU_reg[rd(instr)].valid &= CPU_reg[rt(instr)].valid; + } + else + { + CPU_reg[rd(instr)].valid = 0; + CPU_reg[rd(instr)].hFlags = 0; + } + + // iCB Hack: Force validity if even one half is valid + if ((CPU_reg[rd(instr)].hFlags & VALID_HALF) || (CPU_reg[rd(instr)].lFlags & VALID_HALF)) + CPU_reg[rd(instr)].valid = 1; + // /iCB Hack + + CPU_reg[rd(instr)].value = rdVal; +} + +void PGXP_CPU_OR(u32 instr, u32 rdVal, u32 rsVal, u32 rtVal) +{ + // Rd = Rs | Rt + PGXP_CPU_AND(instr, rdVal, rsVal, rtVal); +} + +void PGXP_CPU_XOR(u32 instr, u32 rdVal, u32 rsVal, u32 rtVal) +{ + // Rd = Rs ^ Rt + PGXP_CPU_AND(instr, rdVal, rsVal, rtVal); +} + +void PGXP_CPU_NOR(u32 instr, u32 rdVal, u32 rsVal, u32 rtVal) +{ + // Rd = Rs NOR Rt + PGXP_CPU_AND(instr, rdVal, rsVal, rtVal); +} + +void PGXP_CPU_SLT(u32 instr, u32 rdVal, u32 rsVal, u32 rtVal) +{ + // Rd = Rs < Rt (signed) + Validate(&CPU_reg[rs(instr)], rsVal); + Validate(&CPU_reg[rt(instr)], rtVal); + + // iCB: Only require one valid input + //if (!(CPU_reg[rs(instr)].valid && CPU_reg[rt(instr)].valid) && (CPU_reg[rs(instr)].valid || CPU_reg[rt(instr)].valid)) + //{ + // MakeValid(&CPU_reg[rs(instr)], rsVal); + // MakeValid(&CPU_reg[rt(instr)], rtVal); + //} + + CPU_reg[rd(instr)] = CPU_reg[rs(instr)]; + + // TODO: fix for single or double values? + CPU_reg[rd(instr)].y = 0.f; + CPU_reg[rd(instr)].x = (CPU_reg[rs(instr)].x < CPU_reg[rt(instr)].x) ? 1.f : 0.f; + + CPU_reg[rd(instr)].value = rdVal; +} + +void PGXP_CPU_SLTU(u32 instr, u32 rdVal, u32 rsVal, u32 rtVal) +{ + // Rd = Rs < Rt (unsigned) + Validate(&CPU_reg[rs(instr)], rsVal); + Validate(&CPU_reg[rt(instr)], rtVal); + + // iCB: Only require one valid input + //if (!(CPU_reg[rs(instr)].valid && CPU_reg[rt(instr)].valid) && (CPU_reg[rs(instr)].valid || CPU_reg[rt(instr)].valid)) + //{ + // MakeValid(&CPU_reg[rs(instr)], rsVal); + // MakeValid(&CPU_reg[rt(instr)], rtVal); + //} + + CPU_reg[rd(instr)] = CPU_reg[rs(instr)]; + + CPU_reg[rd(instr)].y = 0.f; + CPU_reg[rd(instr)].x = (fabs(CPU_reg[rs(instr)].x) < fabs(CPU_reg[rt(instr)].x)) ? 1.f : 0.f; + + CPU_reg[rd(instr)].value = rdVal; +} + +//////////////////////////////////// +// Register mult/div +//////////////////////////////////// +void PGXP_CPU_MULT(u32 instr, u32 hiVal, u32 loVal, u32 rsVal, u32 rtVal) +{ + // Hi/Lo = Rs * Rt (signed) + Validate(&CPU_reg[rs(instr)], rsVal); + Validate(&CPU_reg[rt(instr)], rtVal); + + // iCB: Only require one valid input + if (!(CPU_reg[rs(instr)].valid && CPU_reg[rt(instr)].valid) && (CPU_reg[rs(instr)].valid || CPU_reg[rt(instr)].valid)) + { + MakeValid(&CPU_reg[rs(instr)], rsVal); + MakeValid(&CPU_reg[rt(instr)], rtVal); + } + + float vs = CPU_reg[rs(instr)].y + (CPU_reg[rs(instr)].x / (float)(1 << 16)); + float vt = CPU_reg[rt(instr)].y + (CPU_reg[rt(instr)].x / (float)(1 << 16)); + + CPU_Lo.x = 0;// CPU_reg[rs(instr)].x * CPU_reg[rt(instr)].x; + CPU_Hi.x = vs * vt;// CPU_reg[rs(instr)].y * CPU_reg[rt(instr)].y; + + CPU_Lo.valid = CPU_Hi.valid = CPU_reg[rs(instr)].valid && CPU_reg[rt(instr)].valid; + + CPU_Lo.value = loVal; + CPU_Hi.value = hiVal; +} + +void PGXP_CPU_MULTU(u32 instr, u32 hiVal, u32 loVal, u32 rsVal, u32 rtVal) +{ + // Hi/Lo = Rs * Rt (unsigned) + Validate(&CPU_reg[rs(instr)], rsVal); + Validate(&CPU_reg[rt(instr)], rtVal); + + // iCB: Only require one valid input + if (!(CPU_reg[rs(instr)].valid && CPU_reg[rt(instr)].valid) && (CPU_reg[rs(instr)].valid || CPU_reg[rt(instr)].valid)) + { + MakeValid(&CPU_reg[rs(instr)], rsVal); + MakeValid(&CPU_reg[rt(instr)], rtVal); + } + + float vs = fabs(CPU_reg[rs(instr)].y) + (fabs(CPU_reg[rs(instr)].x) / (float)(1 << 16)); + float vt = fabs(CPU_reg[rt(instr)].y) + (fabs(CPU_reg[rt(instr)].x) / (float)(1 << 16)); + + CPU_Lo.x = 0;// fabs(CPU_reg[rs(instr)].x) * fabs(CPU_reg[rt(instr)].x); + CPU_Hi.x = vs * vt;// fabs(CPU_reg[rs(instr)].y) * fabs(CPU_reg[rt(instr)].y); + + CPU_Lo.valid = CPU_Hi.valid = CPU_reg[rs(instr)].valid && CPU_reg[rt(instr)].valid; + + CPU_Lo.value = loVal; + CPU_Hi.value = hiVal; +} + +void PGXP_CPU_DIV(u32 instr, u32 hiVal, u32 loVal, u32 rsVal, u32 rtVal) +{ + // Hi = Rs / Rt (signed) + // Lo = Rs % Rt (signed) + Validate(&CPU_reg[rs(instr)], rsVal); + Validate(&CPU_reg[rt(instr)], rtVal); + + // iCB: Only require one valid input + //if (!(CPU_reg[rs(instr)].valid && CPU_reg[rt(instr)].valid) && (CPU_reg[rs(instr)].valid || CPU_reg[rt(instr)].valid)) + //{ + // MakeValid(&CPU_reg[rs(instr)], rsVal); + // MakeValid(&CPU_reg[rt(instr)], rtVal); + //} + + CPU_Lo.x = CPU_reg[rs(instr)].x / CPU_reg[rt(instr)].x; + CPU_Hi.x = fmod(CPU_reg[rs(instr)].x, CPU_reg[rt(instr)].x); + CPU_Lo.x -= CPU_Hi.x; + + CPU_Lo.valid = CPU_Hi.valid = CPU_reg[rs(instr)].valid && CPU_reg[rt(instr)].valid; + + CPU_Lo.value = loVal; + CPU_Hi.value = hiVal; +} + +void PGXP_CPU_DIVU(u32 instr, u32 hiVal, u32 loVal, u32 rsVal, u32 rtVal) +{ + // Hi = Rs / Rt (unsigned) + // Lo = Rs % Rt (unsigned) + Validate(&CPU_reg[rs(instr)], rsVal); + Validate(&CPU_reg[rt(instr)], rtVal); + + // iCB: Only require one valid input + //if (!(CPU_reg[rs(instr)].valid && CPU_reg[rt(instr)].valid) && (CPU_reg[rs(instr)].valid || CPU_reg[rt(instr)].valid)) + //{ + // MakeValid(&CPU_reg[rs(instr)], rsVal); + // MakeValid(&CPU_reg[rt(instr)], rtVal); + //} + + CPU_Lo.x = fabs(CPU_reg[rs(instr)].x) / fabs(CPU_reg[rt(instr)].x); + CPU_Hi.x = fmod(fabs(CPU_reg[rs(instr)].x), fabs(CPU_reg[rt(instr)].x)); + CPU_Lo.x -= CPU_Hi.x; + + CPU_Lo.valid = CPU_Hi.valid = CPU_reg[rs(instr)].valid && CPU_reg[rt(instr)].valid; + + CPU_Lo.value = loVal; + CPU_Hi.value = hiVal; +} + +//////////////////////////////////// +// Shift operations (sa) +//////////////////////////////////// +void PGXP_CPU_SLL(u32 instr, u32 rdVal, u32 rtVal) +{ + // Rd = Rt << Sa + Validate(&CPU_reg[rt(instr)], rtVal); + CPU_reg[rd(instr)] = CPU_reg[rt(instr)]; + + // Shift y into x? + if (sa(instr) == 16) + { + CPU_reg[rd(instr)].y = CPU_reg[rd(instr)].x; + CPU_reg[rd(instr)].x = 0; + CPU_reg[rd(instr)].hFlags = CPU_reg[rd(instr)].lFlags; + CPU_reg[rd(instr)].lFlags = 0; + } + else + { + // assume multiply with no overflow + CPU_reg[rd(instr)].x *= (float)(1 << sa(instr)); + CPU_reg[rd(instr)].y *= (float)(1 << sa(instr)); + } + + CPU_reg[rd(instr)].value = rdVal; +} + +void PGXP_CPU_SRL(u32 instr, u32 rdVal, u32 rtVal) +{ + // Rd = Rt >> Sa + Validate(&CPU_reg[rt(instr)], rtVal); + CPU_reg[rd(instr)] = CPU_reg[rt(instr)]; + + // Shift x into y? + if (sa(instr) == 16) + { + CPU_reg[rd(instr)].x = CPU_reg[rd(instr)].y; + CPU_reg[rd(instr)].y = 0; + CPU_reg[rd(instr)].lFlags = CPU_reg[rd(instr)].hFlags; + CPU_reg[rd(instr)].hFlags = 0; + } + else + { + // assume divide with no overflow + CPU_reg[rd(instr)].x /= (float)(1 << sa(instr)); + CPU_reg[rd(instr)].y /= (float)(1 << sa(instr)); + } + + CPU_reg[rd(instr)].value = rdVal; +} + +void PGXP_CPU_SRA(u32 instr, u32 rdVal, u32 rtVal) +{ + // Rd = Rt >> Sa + PGXP_CPU_SRL(instr, rdVal, rtVal); +} + +//////////////////////////////////// +// Shift operations variable +//////////////////////////////////// +void PGXP_CPU_SLLV(u32 instr, u32 rdVal, u32 rtVal, u32 rsVal) +{ + // Rd = Rt << Rs + Validate(&CPU_reg[rt(instr)], rtVal); + Validate(&CPU_reg[rs(instr)], rsVal); + + CPU_reg[rd(instr)] = CPU_reg[rt(instr)]; + + // Shift y into x? + if ((rsVal & 0x1F) == 16) + { + CPU_reg[rd(instr)].y = CPU_reg[rd(instr)].x; + CPU_reg[rd(instr)].x = 0; + CPU_reg[rd(instr)].hFlags = CPU_reg[rd(instr)].lFlags; + CPU_reg[rd(instr)].lFlags = 0; + } + else + { + // assume multiply with no overflow + CPU_reg[rd(instr)].x *= (float)(1 << (rsVal & 0x1F)); + CPU_reg[rd(instr)].y *= (float)(1 << (rsVal & 0x1F)); + } + + CPU_reg[rd(instr)].value = rdVal; +} + +void PGXP_CPU_SRLV(u32 instr, u32 rdVal, u32 rtVal, u32 rsVal) +{ + // Rd = Rt >> Sa + Validate(&CPU_reg[rt(instr)], rtVal); + Validate(&CPU_reg[rs(instr)], rsVal); + + CPU_reg[rd(instr)] = CPU_reg[rt(instr)]; + + // Shift x into y? + if ((rsVal & 0x1F) == 16) + { + CPU_reg[rd(instr)].x = CPU_reg[rd(instr)].y; + CPU_reg[rd(instr)].y = 0; + CPU_reg[rd(instr)].lFlags = CPU_reg[rd(instr)].hFlags; + CPU_reg[rd(instr)].hFlags = 0; + } + else + { + // assume divide with no overflow + CPU_reg[rd(instr)].x /= (float)(1 << (rsVal & 0x1F)); + CPU_reg[rd(instr)].y /= (float)(1 << (rsVal & 0x1F)); + } + + CPU_reg[rd(instr)].value = rdVal; +} + +void PGXP_CPU_SRAV(u32 instr, u32 rdVal, u32 rtVal, u32 rsVal) +{ + PGXP_CPU_SRLV(instr, rdVal, rtVal, rsVal); +} + +//////////////////////////////////// +// Move registers +//////////////////////////////////// +void PGXP_CPU_MFHI(u32 instr, u32 rdVal, u32 hiVal) +{ + // Rd = Hi + Validate(&CPU_Hi, hiVal); + + CPU_reg[rd(instr)] = CPU_Hi; +} + +void PGXP_CPU_MTHI(u32 instr, u32 hiVal, u32 rdVal) +{ + // Hi = Rd + Validate(&CPU_reg[rd(instr)], rdVal); + + CPU_Hi = CPU_reg[rd(instr)]; +} + +void PGXP_CPU_MFLO(u32 instr, u32 rdVal, u32 loVal) +{ + // Rd = Lo + Validate(&CPU_Lo, loVal); + + CPU_reg[rd(instr)] = CPU_Lo; +} + +void PGXP_CPU_MTLO(u32 instr, u32 loVal, u32 rdVal) +{ + // Lo = Rd + Validate(&CPU_reg[rd(instr)], rdVal); + + CPU_Lo = CPU_reg[rd(instr)]; +} + +//////////////////////////////////// +// Memory Access +//////////////////////////////////// + +// Load 32-bit word +void PGXP_CPU_LWL(u32 instr, u32 rtVal, u32 addr) +{ + // Rt = Mem[Rs + Im] + PGXP_CPU_LW(instr, rtVal, addr); +} + +void PGXP_CPU_LW(u32 instr, u32 rtVal, u32 addr) +{ + // Rt = Mem[Rs + Im] + ValidateAndCopyMem(&CPU_reg[rt(instr)], addr, rtVal); + //CPU_reg[rt(instr)] = PGXP_validateXY(ReadMem(addr), rtVal); +} + +void PGXP_CPU_LWR(u32 instr, u32 rtVal, u32 addr) +{ + // Rt = Mem[Rs + Im] + PGXP_CPU_LW(instr, rtVal, addr); +} + +// Load 16-bit +void PGXP_CPU_LH(u32 instr, u16 rtVal, u32 addr) +{ + // Rt = Mem[Rs + Im] (sign extended) + psx_value val; + val.sd = (s32)(s16)rtVal; + ValidateAndCopyMem16(&CPU_reg[rt(instr)], addr, val.d); +} + +void PGXP_CPU_LHU(u32 instr, u16 rtVal, u32 addr) +{ + // Rt = Mem[Rs + Im] (zero extended) + psx_value val; + val.d = rtVal; + val.w.h = 0; + ValidateAndCopyMem16(&CPU_reg[rt(instr)], addr, val.d); +} + +// Load 8-bit +void PGXP_CPU_LB(u32 instr, u8 rtVal, u32 addr) +{ + InvalidLoad(addr, instr, 116); +} + +void PGXP_CPU_LBU(u32 instr, u8 rtVal, u32 addr) +{ + InvalidLoad(addr, instr, 116); +} + +// Store 32-bit word +void PGXP_CPU_SWL(u32 instr, u32 rtVal, u32 addr) +{ + // Mem[Rs + Im] = Rt + PGXP_CPU_SW(instr, rtVal, addr); +} + +void PGXP_CPU_SW(u32 instr, u32 rtVal, u32 addr) +{ + // Mem[Rs + Im] = Rt + Validate(&CPU_reg[rt(instr)], rtVal); + WriteMem(&CPU_reg[rt(instr)], addr); + //WriteMemOld(PGXP_validateXY(&CPU_reg[rt(instr)], rtVal), addr); +} + +void PGXP_CPU_SWR(u32 instr, u32 rtVal, u32 addr) +{ + // Mem[Rs + Im] = Rt + PGXP_CPU_SW(instr, rtVal, addr); +} + +// Store 16-bit +void PGXP_CPU_SH(u32 instr, u16 rtVal, u32 addr) +{ + Validate(&CPU_reg[rt(instr)], rtVal); + WriteMem16(&CPU_reg[rt(instr)], addr); +} + +// Store 8-bit +void PGXP_CPU_SB(u32 instr, u8 rtVal, u32 addr) +{ + InvalidStore(addr, instr, 208); +} + diff --git a/libpcsxcore/pgxp_cpu.h b/libpcsxcore/pgxp_cpu.h new file mode 100644 index 00000000..c97929b1 --- /dev/null +++ b/libpcsxcore/pgxp_cpu.h @@ -0,0 +1,115 @@ +/*************************************************************************** +* Copyright (C) 2016 by iCatButler * +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 2 of the License, or * +* (at your option) any later version. * +* * +* This program is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU General Public License for more details. * +* * +* You should have received a copy of the GNU General Public License * +* along with this program; if not, write to the * +* Free Software Foundation, Inc., * +* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * +***************************************************************************/ + +/************************************************************************** +* pgxp_cpu.h +* PGXP - Parallel/Precision Geometry Xform Pipeline +* +* Created on: 07 Jun 2016 +* Author: iCatButler +***************************************************************************/ + +#ifndef _PGXP_CPU_H_ +#define _PGXP_CPU_H_ + +#include "psxcommon.h" + +#define PGXP_TRACE 9 +#define PGXP_CPU_DEBUG + +struct PGXP_value_Tag; +typedef struct PGXP_value_Tag PGXP_value; + +extern PGXP_value* CPU_reg; +#define CPU_Hi CPU_reg[33] +#define CPU_Lo CPU_reg[34] + +// -- CPU functions + +// Load 32-bit word +void PGXP_CPU_LWL(u32 instr, u32 rtVal, u32 addr); +void PGXP_CPU_LW(u32 instr, u32 rtVal, u32 addr); +void PGXP_CPU_LWR(u32 instr, u32 rtVal, u32 addr); + +// Load 16-bit +void PGXP_CPU_LH(u32 instr, u16 rtVal, u32 addr); +void PGXP_CPU_LHU(u32 instr, u16 rtVal, u32 addr); + +// Load 8-bit +void PGXP_CPU_LB(u32 instr, u8 rtVal, u32 addr); +void PGXP_CPU_LBU(u32 instr, u8 rtVal, u32 addr); + +// Store 32-bit word +void PGXP_CPU_SWL(u32 instr, u32 rtVal, u32 addr); +void PGXP_CPU_SW(u32 instr, u32 rtVal, u32 addr); +void PGXP_CPU_SWR(u32 instr, u32 rtVal, u32 addr); + +// Store 16-bit +void PGXP_CPU_SH(u32 instr, u16 rtVal, u32 addr); + +// Store 8-bit +void PGXP_CPU_SB(u32 instr, u8 rtVal, u32 addr); + +// Arithmetic with immediate value +void PGXP_CPU_ADDI(u32 instr, u32 rtVal, u32 rsVal); +void PGXP_CPU_ADDIU(u32 instr, u32 rtVal, u32 rsVal); +void PGXP_CPU_ANDI(u32 instr, u32 rtVal, u32 rsVal); +void PGXP_CPU_ORI(u32 instr, u32 rtVal, u32 rsVal); +void PGXP_CPU_XORI(u32 instr, u32 rtVal, u32 rsVal); +void PGXP_CPU_SLTI(u32 instr, u32 rtVal, u32 rsVal); +void PGXP_CPU_SLTIU(u32 instr, u32 rtVal, u32 rsVal); + +// Load Upper +void PGXP_CPU_LUI(u32 instr, u32 rtVal); + +// Register Arithmetic +void PGXP_CPU_ADD(u32 instr, u32 rdVal, u32 rsVal, u32 rtVal); +void PGXP_CPU_ADDU(u32 instr, u32 rdVal, u32 rsVal, u32 rtVal); +void PGXP_CPU_SUB(u32 instr, u32 rdVal, u32 rsVal, u32 rtVal); +void PGXP_CPU_SUBU(u32 instr, u32 rdVal, u32 rsVal, u32 rtVal); +void PGXP_CPU_AND(u32 instr, u32 rdVal, u32 rsVal, u32 rtVal); +void PGXP_CPU_OR(u32 instr, u32 rdVal, u32 rsVal, u32 rtVal); +void PGXP_CPU_XOR(u32 instr, u32 rdVal, u32 rsVal, u32 rtVal); +void PGXP_CPU_NOR(u32 instr, u32 rdVal, u32 rsVal, u32 rtVal); +void PGXP_CPU_SLT(u32 instr, u32 rdVal, u32 rsVal, u32 rtVal); +void PGXP_CPU_SLTU(u32 instr, u32 rdVal, u32 rsVal, u32 rtVal); + +// Register mult/div +void PGXP_CPU_MULT(u32 instr, u32 hiVal, u32 loVal, u32 rsVal, u32 rtVal); +void PGXP_CPU_MULTU(u32 instr, u32 hiVal, u32 loVal, u32 rsVal, u32 rtVal); +void PGXP_CPU_DIV(u32 instr, u32 hiVal, u32 loVal, u32 rsVal, u32 rtVal); +void PGXP_CPU_DIVU(u32 instr, u32 hiVal, u32 loVal, u32 rsVal, u32 rtVal); + +// Shift operations (sa) +void PGXP_CPU_SLL(u32 instr, u32 rdVal, u32 rtVal); +void PGXP_CPU_SRL(u32 instr, u32 rdVal, u32 rtVal); +void PGXP_CPU_SRA(u32 instr, u32 rdVal, u32 rtVal); + +// Shift operations variable +void PGXP_CPU_SLLV(u32 instr, u32 rdVal, u32 rtVal, u32 rsVal); +void PGXP_CPU_SRLV(u32 instr, u32 rdVal, u32 rtVal, u32 rsVal); +void PGXP_CPU_SRAV(u32 instr, u32 rdVal, u32 rtVal, u32 rsVal); + +// Move registers +void PGXP_CPU_MFHI(u32 instr, u32 rdVal, u32 hiVal); +void PGXP_CPU_MTHI(u32 instr, u32 hiVal, u32 rdVal); +void PGXP_CPU_MFLO(u32 instr, u32 rdVal, u32 loVal); +void PGXP_CPU_MTLO(u32 instr, u32 loVal, u32 rdVal); + +#endif //_PGXP_CPU_H_
\ No newline at end of file diff --git a/libpcsxcore/pgxp_debug.c b/libpcsxcore/pgxp_debug.c new file mode 100644 index 00000000..da8cacae --- /dev/null +++ b/libpcsxcore/pgxp_debug.c @@ -0,0 +1,314 @@ +#include "pgxp_debug.h" +#include "pgxp_cpu.h" +#include "pgxp_value.h" + +unsigned int pgxp_debug = 0; + +// Instruction register decoding +#define op(_instr) (_instr >> 26) // The op part of the instruction register +#define func(_instr) ((_instr) & 0x3F) // The funct part of the instruction register +#define sa(_instr) ((_instr >> 6) & 0x1F) // The sa part of the instruction register +#define rd(_instr) ((_instr >> 11) & 0x1F) // The rd part of the instruction register +#define rt(_instr) ((_instr >> 16) & 0x1F) // The rt part of the instruction register +#define rs(_instr) ((_instr >> 21) & 0x1F) // The rs part of the instruction register +#define imm(_instr) (_instr & 0xFFFF) // The immediate part of the instruction register + +// Operand ID flags +typedef enum +{ + fOp_Hi = 1 << 0, + fOp_Lo = 1 << 1, + fOp_Rd = 1 << 2, + fOp_Rs = 1 << 3, + fOp_Rt = 1 << 4, + fOp_Sa = 1 << 5, + fOp_Im = 1 << 6, + fOp_Ad = 1 << 7 +} PGXP_CPU_OperandIDs; + +typedef struct +{ + unsigned char OutputFlags; + unsigned char InputFlags; + unsigned char numRegisters; + unsigned char numArgs; + const char* szOpString; + const char* szOpName; + void(*funcPtr)(); +} PGXP_CPU_OpData; + +#define PGXP_Data_NULL { 0, 0, 0, 0, NULL } +#define PGXP_Data_SPECIAL { 0, 0, 0, 0, NULL } +#define PGXP_Data_COP0 { 0, 0, 0, 0, NULL } +#define PGXP_Data_COP2 { 0, 0, 0, 0, NULL } +#define PGXP_Data_LWC2 { 0, 0, 0, 0, NULL } +#define PGXP_Data_SWC2 { 0, 0, 0, 0, NULL } +#define PGXP_Data_HLE { 0, 0, 0, 0, NULL } + +// Arithmetic with immediate value +#define PGXP_Data_ADDI { fOp_Rt, fOp_Rs | fOp_Im, 2, 2, "+", "ADDI", (void(*)())PGXP_CPU_ADDI } +#define PGXP_Data_ADDIU { fOp_Rt, fOp_Rs | fOp_Im, 2, 2, "+", "ADDIU", (void(*)())PGXP_CPU_ADDIU } +#define PGXP_Data_ANDI { fOp_Rt, fOp_Rs | fOp_Im, 2, 2, "&", "ANDI", (void(*)())PGXP_CPU_ANDI } +#define PGXP_Data_ORI { fOp_Rt, fOp_Rs | fOp_Im, 2, 2, "|", "ORI", (void(*)())PGXP_CPU_ORI } +#define PGXP_Data_XORI { fOp_Rt, fOp_Rs | fOp_Im, 2, 2, "^", "XORI", (void(*)())PGXP_CPU_XORI } +#define PGXP_Data_SLTI { fOp_Rt, fOp_Rs | fOp_Im, 2, 2, "<", "SLTI", (void(*)())PGXP_CPU_SLTI } +#define PGXP_Data_SLTIU { fOp_Rt, fOp_Rs | fOp_Im, 2, 2, "<", "SLTIU", (void(*)())PGXP_CPU_SLTIU } +// Load Upper +#define PGXP_Data_LUI { fOp_Rt, fOp_Im, 1, 1, "<<", "LUI", (void(*)())PGXP_CPU_LUI } + +// Load/Store +#define PGXP_Data_LWL { fOp_Rt, fOp_Ad, 1, 2, "", "LWL", (void(*)())PGXP_CPU_LWL } // 32-bit Loads +#define PGXP_Data_LW { fOp_Rt, fOp_Ad, 1, 2, "", "LW", (void(*)())PGXP_CPU_LW } +#define PGXP_Data_LWR { fOp_Rt, fOp_Ad, 1, 2, "", "LWR", (void(*)())PGXP_CPU_LWR } +#define PGXP_Data_LH { fOp_Rt, fOp_Ad, 1, 2, "", "LH", (void(*)())PGXP_CPU_LH } // 16-bit Loads +#define PGXP_Data_LHU { fOp_Rt, fOp_Ad, 1, 2, "", "LHU", (void(*)())PGXP_CPU_LHU } +#define PGXP_Data_LB { fOp_Rt, fOp_Ad, 1, 2, "", "LB", (void(*)())PGXP_CPU_LB } // 8-bit Loads +#define PGXP_Data_LBU { fOp_Rt, fOp_Ad, 1, 2, "", "LBU", (void(*)())PGXP_CPU_LBU } +#define PGXP_Data_SWL { fOp_Ad, fOp_Rt, 1, 2, "", "SWL", (void(*)())PGXP_CPU_SWL } // 32-bit Store +#define PGXP_Data_SW { fOp_Ad, fOp_Rt, 1, 2, "", "SW", (void(*)())PGXP_CPU_SW } +#define PGXP_Data_SWR { fOp_Ad, fOp_Rt, 1, 2, "", "SWR", (void(*)())PGXP_CPU_SWR } +#define PGXP_Data_SH { fOp_Ad, fOp_Rt, 1, 2, "", "SH", (void(*)())PGXP_CPU_SH } // 16-bit Store +#define PGXP_Data_SB { fOp_Ad, fOp_Rt, 1, 2, "", "SU", (void(*)())PGXP_CPU_SB } // 8-bit Store + +static PGXP_CPU_OpData PGXP_BSC_LUT[64] = { + PGXP_Data_SPECIAL, PGXP_Data_NULL , PGXP_Data_NULL, PGXP_Data_NULL , PGXP_Data_NULL, PGXP_Data_NULL, PGXP_Data_NULL, PGXP_Data_NULL, + PGXP_Data_ADDI , PGXP_Data_ADDIU , PGXP_Data_SLTI, PGXP_Data_SLTIU, PGXP_Data_ANDI, PGXP_Data_ORI , PGXP_Data_XORI, PGXP_Data_LUI , + PGXP_Data_COP0 , PGXP_Data_NULL , PGXP_Data_COP2, PGXP_Data_NULL , PGXP_Data_NULL, PGXP_Data_NULL, PGXP_Data_NULL, PGXP_Data_NULL, + PGXP_Data_NULL , PGXP_Data_NULL , PGXP_Data_NULL, PGXP_Data_NULL , PGXP_Data_NULL, PGXP_Data_NULL, PGXP_Data_NULL, PGXP_Data_NULL, + PGXP_Data_LB , PGXP_Data_LH , PGXP_Data_LWL , PGXP_Data_LW , PGXP_Data_LBU , PGXP_Data_LHU , PGXP_Data_LWR , PGXP_Data_NULL, + PGXP_Data_SB , PGXP_Data_SH , PGXP_Data_SWL , PGXP_Data_SW , PGXP_Data_NULL, PGXP_Data_NULL, PGXP_Data_SWR , PGXP_Data_NULL, + PGXP_Data_NULL , PGXP_Data_NULL , PGXP_Data_LWC2, PGXP_Data_NULL , PGXP_Data_NULL, PGXP_Data_NULL, PGXP_Data_NULL, PGXP_Data_NULL, + PGXP_Data_NULL , PGXP_Data_NULL , PGXP_Data_SWC2, PGXP_Data_HLE , PGXP_Data_NULL, PGXP_Data_NULL, PGXP_Data_NULL, PGXP_Data_NULL +}; + +// Register Arithmetic +#define PGXP_Data_ADD { fOp_Rd, fOp_Rs | fOp_Rt, 3, 3, "+", "ADD", (void(*)())PGXP_CPU_ADD } +#define PGXP_Data_ADDU { fOp_Rd, fOp_Rs | fOp_Rt, 3, 3, "+", "ADDU", (void(*)())PGXP_CPU_ADDU } +#define PGXP_Data_SUB { fOp_Rd, fOp_Rs | fOp_Rt, 3, 3, "+", "SUB", (void(*)())PGXP_CPU_SUB } +#define PGXP_Data_SUBU { fOp_Rd, fOp_Rs | fOp_Rt, 3, 3, "+", "SUBU", (void(*)())PGXP_CPU_SUBU } +#define PGXP_Data_AND { fOp_Rd, fOp_Rs | fOp_Rt, 3, 3, "&", "AND", (void(*)())PGXP_CPU_AND } +#define PGXP_Data_OR { fOp_Rd, fOp_Rs | fOp_Rt, 3, 3, "|", "OR", (void(*)())PGXP_CPU_OR } +#define PGXP_Data_XOR { fOp_Rd, fOp_Rs | fOp_Rt, 3, 3, "^", "XOR", (void(*)())PGXP_CPU_XOR } +#define PGXP_Data_NOR { fOp_Rd, fOp_Rs | fOp_Rt, 3, 3, "^", "NOR", (void(*)())PGXP_CPU_NOR } +#define PGXP_Data_SLT { fOp_Rd, fOp_Rs | fOp_Rt, 3, 3, "<", "SLT", (void(*)())PGXP_CPU_SLT } +#define PGXP_Data_SLTU { fOp_Rd, fOp_Rs | fOp_Rt, 3, 3, "<", "SLTU", (void(*)())PGXP_CPU_SLTU } + +// Register mult/div +#define PGXP_Data_MULT { fOp_Hi | fOp_Lo, fOp_Rs | fOp_Rt, 4, 4, "*", "MULT", (void(*)())PGXP_CPU_MULT } +#define PGXP_Data_MULTU { fOp_Hi | fOp_Lo, fOp_Rs | fOp_Rt, 4, 4, "*", "MULTU", (void(*)())PGXP_CPU_MULTU } +#define PGXP_Data_DIV { fOp_Hi | fOp_Lo, fOp_Rs | fOp_Rt, 4, 4, "/", "DIV", (void(*)())PGXP_CPU_DIV } +#define PGXP_Data_DIVU { fOp_Hi | fOp_Lo, fOp_Rs | fOp_Rt, 4, 4, "/", "DIVU", (void(*)())PGXP_CPU_DIVU } + +// Shift operations (sa) +#define PGXP_Data_SLL { fOp_Rd, fOp_Rt | fOp_Sa, 2, 2, ">>", "SLL", (void(*)())PGXP_CPU_SLL } +#define PGXP_Data_SRL { fOp_Rd, fOp_Rt | fOp_Sa, 2, 2, "<<", "SRL", (void(*)())PGXP_CPU_SRL } +#define PGXP_Data_SRA { fOp_Rd, fOp_Rt | fOp_Sa, 2, 2, "<<", "SRA", (void(*)())PGXP_CPU_SRA } + +// Shift operations variable +#define PGXP_Data_SLLV { fOp_Rd, fOp_Rt | fOp_Rs, 3, 3, ">>", "SLLV", (void(*)())PGXP_CPU_SLLV } +#define PGXP_Data_SRLV { fOp_Rd, fOp_Rt | fOp_Rs, 3, 3, "<<", "SRLV", (void(*)())PGXP_CPU_SRLV } +#define PGXP_Data_SRAV { fOp_Rd, fOp_Rt | fOp_Rs, 3, 3, "<<", "SRAV", (void(*)())PGXP_CPU_SRAV } + +// Move registers +#define PGXP_Data_MFHI { fOp_Rd, fOp_Hi, 2, 2, "<-", "MFHI", (void(*)())PGXP_CPU_MFHI } +#define PGXP_Data_MTHI { fOp_Hi, fOp_Rd, 2, 2, "<-", "MTHI", (void(*)())PGXP_CPU_MTHI } +#define PGXP_Data_MFLO { fOp_Rd, fOp_Lo, 2, 2, "<-", "MFLO", (void(*)())PGXP_CPU_MFLO } +#define PGXP_Data_MTLO { fOp_Lo, fOp_Rd, 2, 2, "<-", "MFHI", (void(*)())PGXP_CPU_MTLO } + +static PGXP_CPU_OpData PGXP_SPC_LUT[64] = { + PGXP_Data_SLL , PGXP_Data_NULL, PGXP_Data_SRL , PGXP_Data_SRA , PGXP_Data_SLLV , PGXP_Data_NULL , PGXP_Data_SRLV, PGXP_Data_SRAV, + PGXP_Data_NULL, PGXP_Data_NULL, PGXP_Data_NULL, PGXP_Data_NULL, PGXP_Data_NULL , PGXP_Data_NULL , PGXP_Data_NULL, PGXP_Data_NULL, + PGXP_Data_MFHI, PGXP_Data_MTHI, PGXP_Data_MFLO, PGXP_Data_MTLO, PGXP_Data_NULL , PGXP_Data_NULL , PGXP_Data_NULL, PGXP_Data_NULL, + PGXP_Data_MULT, PGXP_Data_MULTU, PGXP_Data_DIV, PGXP_Data_DIVU, PGXP_Data_NULL , PGXP_Data_NULL , PGXP_Data_NULL, PGXP_Data_NULL, + PGXP_Data_ADD , PGXP_Data_ADDU, PGXP_Data_SUB , PGXP_Data_SUBU, PGXP_Data_AND , PGXP_Data_OR , PGXP_Data_XOR , PGXP_Data_NOR , + PGXP_Data_NULL, PGXP_Data_NULL, PGXP_Data_SLT , PGXP_Data_SLTU, PGXP_Data_NULL , PGXP_Data_NULL , PGXP_Data_NULL, PGXP_Data_NULL, + PGXP_Data_NULL, PGXP_Data_NULL, PGXP_Data_NULL, PGXP_Data_NULL, PGXP_Data_NULL , PGXP_Data_NULL , PGXP_Data_NULL, PGXP_Data_NULL, + PGXP_Data_NULL, PGXP_Data_NULL, PGXP_Data_NULL, PGXP_Data_NULL, PGXP_Data_NULL , PGXP_Data_NULL , PGXP_Data_NULL, PGXP_Data_NULL +}; + +PGXP_CPU_OpData GetOpData(u32 instr) +{ + PGXP_CPU_OpData pOpData = PGXP_Data_NULL; + switch (op(instr)) + { + case 0: + pOpData = PGXP_SPC_LUT[func(instr)]; + break; + case 1: + //pOpData = PGXP_BCOND_LUT[rt(instr)]; + break; + case 16: + //pOpData = PGXP_COP0_LUT[rs(instr)]; + break; + case 18: + //if (func(instr) == 1) + // pOpData = PGXP_CO2BSC_LUT[rs(instr)]; + //else + // pOpData = PGXP_COP2_LUT[func(instr)]; + break; + default: + pOpData = PGXP_BSC_LUT[op(instr)]; + break; + } + + return pOpData; +} + +void PrintOperands(char* szBuffer, u32 instr, u32 flags, const char* szDelim, psx_value* psx_regs, u32* regIdx) +{ + char szTempBuffer[256]; + PGXP_value* pReg = NULL; + psx_value psx_reg; + char szOpdName[8]; + const char* szPre = ""; + + memset(szTempBuffer, 0, sizeof(szTempBuffer)); + for (u32 opdIdx = 0; opdIdx < 8; opdIdx++) + { + u32 flag = 1 << opdIdx; + + // iCB Hack: reorder Rs and Rt for SLLV SRLV and SRAV + if ((op(instr) < 8) && (op(instr) > 3)) + flag = (flag == fOp_Rs) ? fOp_Rt : ((flag == fOp_Rt) ? fOp_Rs : flag); + // /iCB Hack + + if (flags & flag) + { + switch (flag) + { + case fOp_Hi: + pReg = &CPU_Hi; + sprintf(szOpdName, "Hi"); + psx_reg = psx_regs[(*regIdx)++]; + break; + case fOp_Lo: + pReg = &CPU_Lo; + sprintf(szOpdName, "Lo"); + psx_reg = psx_regs[(*regIdx)++]; + break; + case fOp_Rd: + pReg = &CPU_reg[rd(instr)]; + sprintf(szOpdName, "Rd[%d]", rd(instr)); + psx_reg = psx_regs[(*regIdx)++]; + break; + case fOp_Rs: + pReg = &CPU_reg[rs(instr)]; + sprintf(szOpdName, "Rs[%d]", rs(instr)); + psx_reg = psx_regs[(*regIdx)++]; + break; + case fOp_Rt: + pReg = &CPU_reg[rt(instr)]; + sprintf(szOpdName, "Rt[%d]", rt(instr)); + psx_reg = psx_regs[(*regIdx)++]; + break; + case fOp_Sa: + pReg = NULL; + sprintf(szOpdName, "Sa"); + psx_reg.d = sa(instr); + break; + case fOp_Im: + pReg = NULL; + sprintf(szOpdName, "Imm"); + psx_reg.d = imm(instr); + break; + case fOp_Ad: + pReg = NULL; + sprintf(szOpdName, "Addr"); + psx_reg = psx_regs[(*regIdx)++]; + break; + } + + if (pReg) + { + sprintf(szTempBuffer, "%s %s [%x(%d, %d) %x(%.2f, %.2f, %.2f)%x : %x] ", szPre, szOpdName, + psx_reg.d, psx_reg.sw.l, psx_reg.sw.h, + pReg->value, pReg->x, pReg->y, pReg->z, pReg->count, pReg->valid); + strcat(szBuffer, szTempBuffer); + } + else + { + sprintf(szTempBuffer, "%s %s [%x(%d, %d)] ", szPre, szOpdName, + psx_reg.d, psx_reg.sw.l, psx_reg.sw.h); + strcat(szBuffer, szTempBuffer); + } + + szPre = szDelim; + } + } +} + +void PGXP_CPU_DebugOutput(u32 instr, u32 numOps, u32 op1, u32 op2, u32 op3, u32 op4) +{ + char szBuffer[512]; + PGXP_CPU_OpData opData = GetOpData(instr); + psx_value psx_regs[4]; + u32 regIdx = 0; + psx_regs[0].d = op1; + psx_regs[1].d = op2; + psx_regs[2].d = op3; + psx_regs[3].d = op4; + + // iCB Hack: Switch operands around for store functions + if ((op(instr) >= 40) && (op(instr) < 48)) + { + psx_regs[0].d = op2; + psx_regs[1].d = op1; + } + // /iCB Hack + + if (!pgxp_debug) + return; + + memset(szBuffer, 0, sizeof(szBuffer)); + // Print operation details + sprintf(szBuffer, "%s %x %x: ", opData.szOpName, op(instr), func(instr)); + // Print outputs + PrintOperands(szBuffer, instr, opData.OutputFlags, "/", psx_regs, ®Idx); + strcat(szBuffer, "= "); + // Print inputs + PrintOperands(szBuffer, instr, opData.InputFlags, opData.szOpString, psx_regs, ®Idx); + +#ifdef GTE_LOG + GTE_LOG("PGXP_Trace: %s |", szBuffer); +#endif +} + +void PGXP_psxTrace(u32 instr) +{ + PGXP_CPU_OpData opData = GetOpData(instr); + if (opData.funcPtr && (opData.numArgs == 0)) + ((void(*)(u32))opData.funcPtr)(instr); + PGXP_CPU_DebugOutput(instr, 0, 0, 0, 0, 0); +} + +void PGXP_psxTraceOp1(u32 instr, u32 op1) +{ + PGXP_CPU_OpData opData = GetOpData(instr); + if (opData.funcPtr && (opData.numArgs == 1)) + ((void(*)(u32, u32))opData.funcPtr)(instr, op1); + PGXP_CPU_DebugOutput(instr, 1, op1, 0, 0, 0); +} + +void PGXP_psxTraceOp2(u32 instr, u32 op1, u32 op2) +{ + PGXP_CPU_OpData opData = GetOpData(instr); + if (opData.funcPtr && (opData.numArgs == 2)) + ((void(*)(u32, u32, u32))opData.funcPtr)(instr, op1, op2); + PGXP_CPU_DebugOutput(instr, 2, op1, op2, 0, 0); +} + +void PGXP_psxTraceOp3(u32 instr, u32 op1, u32 op2, u32 op3) +{ + PGXP_CPU_OpData opData = GetOpData(instr); + if (opData.funcPtr && (opData.numArgs == 3)) + ((void(*)(u32, u32, u32, u32))opData.funcPtr)(instr, op1, op2, op3); + PGXP_CPU_DebugOutput(instr, 3, op1, op2, op3, 0); +} + +void PGXP_psxTraceOp4(u32 instr, u32 op1, u32 op2, u32 op3, u32 op4) +{ + PGXP_CPU_OpData opData = GetOpData(instr); + if (opData.funcPtr && (opData.numArgs == 4)) + ((void(*)(u32, u32, u32, u32, u32))opData.funcPtr)(instr, op1, op2, op3, op4); + PGXP_CPU_DebugOutput(instr, 4, op1, op2, op3, op4); +}
\ No newline at end of file diff --git a/libpcsxcore/pgxp_debug.h b/libpcsxcore/pgxp_debug.h new file mode 100644 index 00000000..caea2b67 --- /dev/null +++ b/libpcsxcore/pgxp_debug.h @@ -0,0 +1,42 @@ +/*************************************************************************** +* Copyright (C) 2016 by iCatButler * +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 2 of the License, or * +* (at your option) any later version. * +* * +* This program is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU General Public License for more details. * +* * +* You should have received a copy of the GNU General Public License * +* along with this program; if not, write to the * +* Free Software Foundation, Inc., * +* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * +***************************************************************************/ + +/************************************************************************** +* pgxp_debug.h +* PGXP - Parallel/Precision Geometry Xform Pipeline +* +* Created on: 07 Jun 2016 +* Author: iCatButler +***************************************************************************/ + +#ifndef _PGXP_DEBUG_H_ +#define _PGXP_DEBUG_H_ + +#include "psxcommon.h" + +// Debug wrappers +void PGXP_psxTrace(u32 code); +void PGXP_psxTraceOp1(u32 code, u32 op1); +void PGXP_psxTraceOp2(u32 code, u32 op1, u32 op2); +void PGXP_psxTraceOp3(u32 code, u32 op1, u32 op2, u32 op3); +void PGXP_psxTraceOp4(u32 code, u32 op1, u32 op2, u32 op3, u32 op4); + +extern unsigned int pgxp_debug; + +#endif//_PGXP_DEBUG_H_
\ No newline at end of file diff --git a/libpcsxcore/pgxp_gte.c b/libpcsxcore/pgxp_gte.c index c130d32c..5fa021c8 100644 --- a/libpcsxcore/pgxp_gte.c +++ b/libpcsxcore/pgxp_gte.c @@ -26,163 +26,16 @@ ***************************************************************************/
#include "pgxp_gte.h"
+#include "pgxp_value.h"
+#include "pgxp_mem.h"
+#include "pgxp_debug.h"
+#include "pgxp_cpu.h"
+
#include "psxcommon.h"
#include "psxmem.h"
#include "r3000a.h"
-typedef struct
-{
- float x;
- float y;
- float z;
- unsigned int valid;
- unsigned int count;
- unsigned int value;
-} precise_value;
-
-typedef union
-{
- struct
- {
- s16 x;
- s16 y;
- };
- u32 word;
-} low_value;
-
-#define tolerance 1.0f
-
-precise_value GTE_reg[32];
-precise_value CPU_reg[32];
-
-precise_value Mem[3 * 2048 * 1024 / 4]; // mirror 2MB in 32-bit words * 3
-const u32 UserMemOffset = 0;
-const u32 ScratchOffset = 2048 * 1024 / 4;
-const u32 RegisterOffset = 2 * 2048 * 1024 / 4;
-const u32 InvalidAddress = 3 * 2048 * 1024 / 4;
-
-unsigned int pgxp_debug = 0;
-
-//precise_value Scratch[2048 * 1024 / 4]; // mirror 2MB in 32-bit words
-//precise_value Registers[2048 * 1024 / 4]; // mirror 2MB in 32-bit words
-
-void PGXP_Init()
-{
- memset(Mem, 0, sizeof(Mem));
-}
-
-char* PGXP_GetMem()
-{
- return Config.PGXP_GTE ? (char*)(Mem) : NULL;
-}
-
-/* Playstation Memory Map (from Playstation doc by Joshua Walker)
-0x0000_0000-0x0000_ffff Kernel (64K)
-0x0001_0000-0x001f_ffff User Memory (1.9 Meg)
-
-0x1f00_0000-0x1f00_ffff Parallel Port (64K)
-
-0x1f80_0000-0x1f80_03ff Scratch Pad (1024 bytes)
-
-0x1f80_1000-0x1f80_2fff Hardware Registers (8K)
-
-0x1fc0_0000-0x1fc7_ffff BIOS (512K)
-
-0x8000_0000-0x801f_ffff Kernel and User Memory Mirror (2 Meg) Cached
-0x9fc0_0000-0x9fc7_ffff BIOS Mirror (512K) Cached
-
-0xa000_0000-0xa01f_ffff Kernel and User Memory Mirror (2 Meg) Uncached
-0xbfc0_0000-0xbfc7_ffff BIOS Mirror (512K) Uncached
-*/
-void ValidateAddress(u32 addr)
-{
- int* pi = NULL;
-
- if ((addr >= 0x00000000) && (addr <= 0x007fffff)) {} // Kernel + User Memory x 8
- else if ((addr >= 0x1f000000) && (addr <= 0x1f00ffff)) {} // Parallel Port
- else if ((addr >= 0x1f800000) && (addr <= 0x1f8003ff)) {} // Scratch Pad
- else if ((addr >= 0x1f801000) && (addr <= 0x1f802fff)) {} // Hardware Registers
- else if ((addr >= 0x1fc00000) && (addr <= 0x1fc7ffff)) {} // Bios
- else if ((addr >= 0x80000000) && (addr <= 0x807fffff)) {} // Kernel + User Memory x 8 Cached mirror
- else if ((addr >= 0x9fc00000) && (addr <= 0x9fc7ffff)) {} // Bios Cached Mirror
- else if ((addr >= 0xa0000000) && (addr <= 0xa07fffff)) {} // Kernel + User Memory x 8 Uncached mirror
- else if ((addr >= 0xbfc00000) && (addr <= 0xbfc7ffff)) {} // Bios Uncached Mirror
- else if (addr == 0xfffe0130) {} // Used for cache flushing
- else
- {
- // *pi = 5;
- }
-
-}
-
-u32 PGXP_ConvertAddress(u32 addr)
-{
- u32 memOffs = 0;
- u32 paddr = addr;
-
- ValidateAddress(addr);
-
- switch (paddr >> 24)
- {
- case 0x80:
- case 0xa0:
- case 0x00:
- // RAM further mirrored over 8MB
- paddr = ((paddr & 0x7FFFFF) % 0x200000) >> 2;
- paddr = UserMemOffset + paddr;
- break;
- default:
- if ((paddr >> 20) == 0x1f8)
- {
- if (paddr >= 0x1f801000)
- {
- // paddr = ((paddr & 0xFFFF) - 0x1000);
- // paddr = (paddr % 0x2000) >> 2;
- paddr = ((paddr & 0xFFFF) - 0x1000) >> 2;
- paddr = RegisterOffset + paddr;
- break;
- }
- else
- {
- //paddr = ((paddr & 0xFFF) % 0x400) >> 2;
- paddr = (paddr & 0x3FF) >> 2;
- paddr = ScratchOffset + paddr;
- break;
- }
- }
-
- paddr = InvalidAddress;
- break;
- }
-
-#ifdef GTE_LOG
- //GTE_LOG("PGXP_Read %x [%x] |", addr, paddr);
-#endif
-
- return paddr;
-}
-
-precise_value* GetPtr(u32 addr)
-{
- addr = PGXP_ConvertAddress(addr);
-
- if (addr != InvalidAddress)
- return &Mem[addr];
- return NULL;
-}
-
-precise_value* ReadMem(u32 addr)
-{
- return GetPtr(addr);
-}
-
-void WriteMem(precise_value value, u32 addr)
-{
- precise_value* pMem = GetPtr(addr);
-
- if (pMem)
- *pMem = value;
-}
+PGXP_value GTE_reg[32];
#define SX0 (GTE_reg[ 12 ].x)
#define SY0 (GTE_reg[ 12 ].y)
@@ -196,67 +49,6 @@ void WriteMem(precise_value value, u32 addr) #define SXY2 (GTE_reg[ 14 ])
#define SXYP (GTE_reg[ 15 ])
-unsigned int PGXP_validate(float high, s16 low)
-{
- if (fabs(high - (float)(low)) < tolerance)
- return 1;
- return 0;
-}
-
-// Check that value is still within tolerance of low precision value and invalidate if not
-precise_value PGXP_validateXY(precise_value *high, u32 low)
-{
- low_value temp;
- precise_value ret;
-
- ret.valid = 0;
- temp.word = low;
-
- if (!high)
- return ret;
-
- high->valid = (high->valid) && (high->value == low);//(high->valid && PGXP_validate(high->x, temp.x) && PGXP_validate(high->y, temp.y));
-
- // Cheat
- //if (!high->valid)
- //{
- // high->x = temp.x;
- // high->y = temp.y;
- // high->valid = 1;
- // high->value = low;
- //}
-
- return *high;
-}
-
-u32 PGXP_compareXY(precise_value high, u32 low)
-{
- low_value temp;
- temp.word = low;
-
- if (PGXP_validate(high.x, temp.x) && PGXP_validate(high.y, temp.y))
- return 1;
- return 0;
-}
-
-precise_value PGXP_copyXY(u32 low)
-{
- low_value temp;
- precise_value ret;
-
- ret.valid = 0;
- temp.word = low;
-
- ret.z= 1;
- ret.x = temp.x;
- ret.y = temp.y;
- ret.count = 0;
- ret.valid = 1;
- ret.value = low;
-
- return ret;
-}
-
void PGXP_pushSXYZ2f(float _x, float _y, float _z, unsigned int _v)
{
static unsigned int uCount = 0;
@@ -280,7 +72,7 @@ void PGXP_pushSXYZ2f(float _x, float _y, float _z, unsigned int _v) GPU_pgxpCacheVertex(0, 0, NULL);
#ifdef GTE_LOG
- GTE_LOG("PGPR_PUSH (%f, %f) %u %u|", SXY2.x, SXY2.y, SXY2.valid, SXY2.count);
+ GTE_LOG("PGXP_PUSH (%f, %f) %u %u|", SXY2.x, SXY2.y, SXY2.valid, SXY2.count);
#endif
}
@@ -393,7 +185,7 @@ float PGXP_NCLIP() return nclip;
}
-static precise_value PGXP_MFC2_int(u32 reg)
+static PGXP_value PGXP_MFC2_int(u32 reg)
{
switch (reg)
{
@@ -406,7 +198,7 @@ static precise_value PGXP_MFC2_int(u32 reg) }
-static void PGXP_MTC2_int(precise_value value, u32 reg)
+static void PGXP_MTC2_int(PGXP_value value, u32 reg)
{
switch(reg)
{
@@ -433,7 +225,8 @@ void PGXP_MFC2(u32 gpr, u32 gtr, u32 value) GTE_LOG("PGXP_MFC2 [%x]<-[%x] %x (%u %u)|", gpr, gtr, value, GTE_reg[gtr].valid, GTE_reg[gtr].count);
#endif
- CPU_reg[gpr] = PGXP_validateXY(>E_reg[gtr], value);
+ Validate(>E_reg[gtr], value);
+ CPU_reg[gpr] = GTE_reg[gtr];
}
// copy GPR reg to GTE data reg (MTC2)
@@ -442,15 +235,18 @@ void PGXP_MTC2(u32 gpr, u32 gtr, u32 value) #ifdef GTE_LOG
GTE_LOG("PGXP_MTC2 [%x]->[%x] %x (%u %u)|", gpr, gtr, value, CPU_reg[gpr].valid, CPU_reg[gpr].count);
#endif
- PGXP_MTC2_int(PGXP_validateXY(&CPU_reg[gpr], value), gtr);
+ Validate(&CPU_reg[gpr], value);
+ PGXP_MTC2_int(CPU_reg[gpr], gtr);
}
// copy memory to GTE reg
void PGXP_LWC2(u32 addr, u32 gtr, u32 value)
{
+ PGXP_value val;
+ ValidateAndCopyMem(&val, addr, value);
#ifdef GTE_LOG
- precise_value* pp = ReadMem(addr);
- precise_value p;
+ PGXP_value* pp = ReadMem(addr);
+ PGXP_value p;
low_value temp;
temp.word = value;
@@ -461,7 +257,7 @@ void PGXP_LWC2(u32 addr, u32 gtr, u32 value) GTE_LOG("PGXP_LWC2 %x [%x] %x (%d, %d) (%f, %f) %u %u|", addr, gtr, value, temp.x, temp.y, p.x, p.y, p.valid, p.count);
#endif
- PGXP_MTC2_int(PGXP_validateXY(ReadMem(addr), value), gtr);
+ PGXP_MTC2_int(val, gtr);
}
//copy GTE reg to memory
@@ -471,200 +267,10 @@ void PGXP_SWC2(u32 addr, u32 gtr, u32 value) low_value temp;
temp.word = value;
- if (PGXP_compareXY(GTE_reg[gtr], value))
- GTE_LOG("PGPR_SWC2 %x [%x] %x (%d, %d) (%f, %f) %u %u|", addr, gtr, value, temp.x, temp.y, GTE_reg[gtr].x, GTE_reg[gtr].y, GTE_reg[gtr].valid, GTE_reg[gtr].count);
-#endif
- WriteMem(PGXP_validateXY(>E_reg[gtr], value), addr);
-}
-
-// load 32bit word
-void PGPR_L32(u32 addr, u32 code, u32 value)
-{
- u32 reg = ((code >> 16) & 0x1F); // The rt part of the instruction register
- u32 op = ((code >> 26));
- precise_value p;
-
- low_value temp;
- temp.word = value;
-
- p.x = p.y = p.valid = p.count = 0;
-
- switch (op)
- {
- case 34: //LWL
- CPU_reg[reg] = PGXP_validateXY(ReadMem(addr), value);
- break;
- case 35: //LW
- CPU_reg[reg] = PGXP_validateXY(ReadMem(addr), value);
- break;
- case 38: //LWR
- CPU_reg[reg] = PGXP_validateXY(ReadMem(addr), value);
- break;
- case 50: //LWC2 (GTE vertex reads)
- GTE_reg[reg] = PGXP_validateXY(ReadMem(addr), value);
- break;
- default:
- // invalidate register
- // CPU_reg[reg] = p;
- break;
- }
-
-#ifdef GTE_LOG
- GTE_LOG("PGPR_L32 %u: %x %x[%x %x] (%d, %d) (%f, %f) %x %u|", op, addr, value, code, reg, temp.x, temp.y, CPU_reg[reg].x, CPU_reg[reg].y, CPU_reg[reg].valid, CPU_reg[reg].count);
-#endif
-}
-
-// store 32bit word
-void PGPR_S32(u32 addr, u32 code, u32 value)
-{
- u32 reg = ((code >> 16) & 0x1F); // The rt part of the instruction register
- u32 op = ((code >> 26));
- precise_value p;
-
- low_value temp;
- temp.word = value;
-
- p.x = p.y = p.valid = p.count = 0;
-
-#ifdef GTE_LOG
- GTE_LOG("PGPR_S32 %u: %x %x[%x %x] (%d, %d) (%f, %f) %x %u|", op, addr, value, code, reg, temp.x, temp.y, CPU_reg[reg].x, CPU_reg[reg].y, CPU_reg[reg].valid, CPU_reg[reg].count);
-#endif
-
- switch (op)
- {
- case 42: //SWL
- WriteMem(PGXP_validateXY(&CPU_reg[reg], value), addr);
- break;
- case 43: //SW
- WriteMem(PGXP_validateXY(&CPU_reg[reg], value), addr);
- break;
- case 46: //SWR
- WriteMem(PGXP_validateXY(&CPU_reg[reg], value), addr);
- break;
- case 58: //SWC2 (GTE vertex writes)
- WriteMem(PGXP_validateXY(>E_reg[reg], value), addr);
- break;
- default:
- // invalidate memory
- // WriteMem(p, addr);
- break;
- }
-}
-
-// invalidate register (invalid 8/16 bit read)
-void PGPR_InvalidLoad(u32 addr, u32 code, u32 value)
-{
- u32 reg = ((code >> 16) & 0x1F); // The rt part of the instruction register
- precise_value* pD = NULL;
- precise_value p;
-
- p.x = p.y = -1337; // default values
-
- //p.valid = 0;
- //p.count = value;
- pD = ReadMem(addr);
-
- if (pD)
- {
- p.count = addr;
- p = *pD;
- }
- else
- {
- p.count = value;
- }
-
- p.valid = 0;
-
- // invalidate register
- CPU_reg[reg] = p;
-}
-
-// invalidate memory address (invalid 8/16 bit write)
-void PGPR_InvalidStore(u32 addr, u32 code, u32 value)
-{
- u32 reg = ((code >> 16) & 0x1F); // The rt part of the instruction register
- precise_value* pD = NULL;
- precise_value p;
-
- pD = ReadMem(addr);
-
- p.x = p.y = -2337;
-
- if (pD)
- p = *pD;
-
- p.valid = 0;
- p.count = (reg * 1000) + value;
-
- // invalidate memory
- WriteMem(p, addr);
-}
-
-u32 PGXP_psxMemRead32Trace(u32 mem, u32 code)
-{
- u32 value = psxMemRead32(mem);
- PGPR_L32(mem, code, value);
- return value;
-}
-
-void PGXP_psxMemWrite32Trace(u32 mem, u32 value, u32 code)
-{
- PGPR_S32(mem, code, value);
- psxMemWrite32(mem, value);
-}
-
-u16 PGXP_psxMemRead16Trace(u32 mem, u32 code)
-{
- u16 value = psxMemRead16(mem);
-#ifdef GTE_LOG
- u32 reg = ((code >> 16) & 0x1F); // The rt part of the instruction register
- GTE_LOG("PGPR_L16 %x %x[%x %x]|", mem, value, code, reg);
+// if (PGXP_compareXY(GTE_reg[gtr], value))
+ GTE_LOG("PGXP_SWC2 %x [%x] %x (%d, %d) (%f, %f) %u %u|", addr, gtr, value, temp.x, temp.y, GTE_reg[gtr].x, GTE_reg[gtr].y, GTE_reg[gtr].valid, GTE_reg[gtr].count);
#endif
- PGPR_InvalidLoad(mem, code, 116);
- return value;
+ Validate(>E_reg[gtr], value);
+ WriteMem(>E_reg[gtr], addr);
}
-void PGXP_psxMemWrite16Trace(u32 mem, u16 value, u32 code)
-{
- PGPR_InvalidStore(mem, code, 216);
-#ifdef GTE_LOG
- u32 reg = ((code >> 16) & 0x1F); // The rt part of the instruction register
- GTE_LOG("PGPR_S16 %x %x[%x %x]|", mem, value, code, reg);
-#endif
- psxMemWrite16(mem, value);
-}
-
-u8 PGXP_psxMemRead8Trace(u32 mem, u32 code)
-{
- u8 value = psxMemRead8(mem);
-#ifdef GTE_LOG
- u32 reg = ((code >> 16) & 0x1F); // The rt part of the instruction register
- GTE_LOG("PGPR_L8 %x %x[%x %x]|", mem, value, code, reg);
-#endif
- PGPR_InvalidLoad(mem, code, 18);
- return value;
-}
-
-void PGXP_psxMemWrite8Trace(u32 mem, u8 value, u32 code)
-{
- PGPR_InvalidStore(mem, code, 28);
-#ifdef GTE_LOG
- u32 reg = ((code >> 16) & 0x1F); // The rt part of the instruction register
- GTE_LOG("PGPR_S8 %x %x[%x %x]|", mem, value, code, reg);
-#endif
- psxMemWrite8(mem, value);
-}
-
-void PGXP_psxTrace(u32 code, u32 rtv)
-{
-#ifdef GTE_LOG
-//u32 reg = ((code >> 16) & 0x1F); // The rt part of the instruction register
- u32 op = ((code >> 26));
- u32 func = ((code ) & 0x3F); // The funct part of the instruction register
- u32 rd = ((code >> 11) & 0x1F); // The rd part of the instruction register
- u32 rt = ((code >> 16) & 0x1F); // The rt part of the instruction register
- u32 rs = ((code >> 21) & 0x1F); // The rs part of the instruction register
- GTE_LOG("PGPR_Trace op:%u func:%u [rt:%x (%x) rs:%x rd:%x] %x|", op, func, rt, rtv, rs, rd, code);
-#endif
-}
\ No newline at end of file diff --git a/libpcsxcore/pgxp_gte.h b/libpcsxcore/pgxp_gte.h index f9c1b618..9df36b19 100644 --- a/libpcsxcore/pgxp_gte.h +++ b/libpcsxcore/pgxp_gte.h @@ -30,10 +30,6 @@ #include "psxcommon.h"
-void PGXP_Init(); // initialise memory
-char* PGXP_GetMem(); // return pointer to precision memory
-u32 PGXP_ConvertAddress(u32 addr);
-
// -- GTE functions
// Transforms
void PGXP_pushSXYZ2f(float _x, float _y, float _z, unsigned int _v);
@@ -50,23 +46,6 @@ void PGXP_MTC2(u32 gpr, u32 gtr, u32 value); // copy GPR reg to GTR reg (MTC2) void PGXP_LWC2(u32 addr, u32 gtr, u32 value); // copy memory to GTE reg
void PGXP_SWC2(u32 addr, u32 gtr, u32 value); // copy GTE reg to memory
-// -- CPU functions
-// Data transfer tracking
-void PGPR_L32(u32 addr, u32 code, u32 value); // load 32bit word
-void PGPR_S32(u32 addr, u32 code, u32 value); // store 32bit word
-
-// Memory Read/Write hooks
-u32 PGXP_psxMemRead32Trace(u32 mem, u32 code);
-void PGXP_psxMemWrite32Trace(u32 mem, u32 value, u32 code);
-
-u16 PGXP_psxMemRead16Trace(u32 mem, u32 code);
-void PGXP_psxMemWrite16Trace(u32 mem, u16 value, u32 code);
-
-u8 PGXP_psxMemRead8Trace(u32 mem, u32 code);
-void PGXP_psxMemWrite8Trace(u32 mem, u8 value, u32 code);
-
-void PGXP_psxTrace(u32 code, u32 rtv);
-
#ifndef max
# define max(a, b) ((a) > (b) ? (a) : (b))
#endif
diff --git a/libpcsxcore/pgxp_mem.c b/libpcsxcore/pgxp_mem.c new file mode 100644 index 00000000..4dfb4bd5 --- /dev/null +++ b/libpcsxcore/pgxp_mem.c @@ -0,0 +1,206 @@ +#include "pgxp_mem.h" +#include "pgxp_value.h" + +PGXP_value Mem[3 * 2048 * 1024 / 4]; // mirror 2MB in 32-bit words * 3 +const u32 UserMemOffset = 0; +const u32 ScratchOffset = 2048 * 1024 / 4; +const u32 RegisterOffset = 2 * 2048 * 1024 / 4; +const u32 InvalidAddress = 3 * 2048 * 1024 / 4; + +void PGXP_Init() +{ + memset(Mem, 0, sizeof(Mem)); +} + +char* PGXP_GetMem() +{ + return Config.PGXP_GTE ? (char*)(Mem) : NULL; +} + +/* Playstation Memory Map (from Playstation doc by Joshua Walker) +0x0000_0000-0x0000_ffff Kernel (64K) +0x0001_0000-0x001f_ffff User Memory (1.9 Meg) + +0x1f00_0000-0x1f00_ffff Parallel Port (64K) + +0x1f80_0000-0x1f80_03ff Scratch Pad (1024 bytes) + +0x1f80_1000-0x1f80_2fff Hardware Registers (8K) + +0x1fc0_0000-0x1fc7_ffff BIOS (512K) + +0x8000_0000-0x801f_ffff Kernel and User Memory Mirror (2 Meg) Cached +0x9fc0_0000-0x9fc7_ffff BIOS Mirror (512K) Cached + +0xa000_0000-0xa01f_ffff Kernel and User Memory Mirror (2 Meg) Uncached +0xbfc0_0000-0xbfc7_ffff BIOS Mirror (512K) Uncached +*/ +void ValidateAddress(u32 addr) +{ + int* pi = NULL; + + if ((addr >= 0x00000000) && (addr <= 0x007fffff)) {} // Kernel + User Memory x 8 + else if ((addr >= 0x1f000000) && (addr <= 0x1f00ffff)) {} // Parallel Port + else if ((addr >= 0x1f800000) && (addr <= 0x1f8003ff)) {} // Scratch Pad + else if ((addr >= 0x1f801000) && (addr <= 0x1f802fff)) {} // Hardware Registers + else if ((addr >= 0x1fc00000) && (addr <= 0x1fc7ffff)) {} // Bios + else if ((addr >= 0x80000000) && (addr <= 0x807fffff)) {} // Kernel + User Memory x 8 Cached mirror + else if ((addr >= 0x9fc00000) && (addr <= 0x9fc7ffff)) {} // Bios Cached Mirror + else if ((addr >= 0xa0000000) && (addr <= 0xa07fffff)) {} // Kernel + User Memory x 8 Uncached mirror + else if ((addr >= 0xbfc00000) && (addr <= 0xbfc7ffff)) {} // Bios Uncached Mirror + else if (addr == 0xfffe0130) {} // Used for cache flushing + else + { + // *pi = 5; + } + +} + +u32 PGXP_ConvertAddress(u32 addr) +{ + u32 memOffs = 0; + u32 paddr = addr; + + ValidateAddress(addr); + + switch (paddr >> 24) + { + case 0x80: + case 0xa0: + case 0x00: + // RAM further mirrored over 8MB + paddr = ((paddr & 0x7FFFFF) % 0x200000) >> 2; + paddr = UserMemOffset + paddr; + break; + default: + if ((paddr >> 20) == 0x1f8) + { + if (paddr >= 0x1f801000) + { + // paddr = ((paddr & 0xFFFF) - 0x1000); + // paddr = (paddr % 0x2000) >> 2; + paddr = ((paddr & 0xFFFF) - 0x1000) >> 2; + paddr = RegisterOffset + paddr; + break; + } + else + { + //paddr = ((paddr & 0xFFF) % 0x400) >> 2; + paddr = (paddr & 0x3FF) >> 2; + paddr = ScratchOffset + paddr; + break; + } + } + + paddr = InvalidAddress; + break; + } + +#ifdef GTE_LOG + //GTE_LOG("PGXP_Read %x [%x] |", addr, paddr); +#endif + + return paddr; +} + +PGXP_value* GetPtr(u32 addr) +{ + addr = PGXP_ConvertAddress(addr); + + if (addr != InvalidAddress) + return &Mem[addr]; + return NULL; +} + +PGXP_value* ReadMem(u32 addr) +{ + return GetPtr(addr); +} + +void ValidateAndCopyMem(PGXP_value* dest, u32 addr, u32 value) +{ + PGXP_value* pMem = GetPtr(addr); + if (pMem != NULL) + { + Validate(pMem, value); + *dest = *pMem; + return; + } + + *dest = PGXP_value_invalid_address; +} + +void ValidateAndCopyMem16(PGXP_value* dest, u32 addr, u32 value) +{ + psx_value val, mask; + PGXP_value* pMem = GetPtr(addr); + if (pMem != NULL) + { + mask.d = val.d = 0; + // determine if high or low word + if ((addr % 4) == 2) + { + val.w.h = value; + mask.w.h = 0xFFFF; + } + else + { + val.w.l = value; + mask.w.l = 0xFFFF; + } + + // validate and copy whole value + MaskValidate(pMem, val.d, mask.d); + *dest = *pMem; + + // if high word then shift + if ((addr % 4) == 2) + { + dest->x = dest->y; + dest->lFlags = dest->hFlags; + } + + // truncate value + dest->y = 0.f; + dest->hFlags = 0; + dest->value = value; + return; + } + + *dest = PGXP_value_invalid_address; +} + +void WriteMem(PGXP_value* value, u32 addr) +{ + PGXP_value* pMem = GetPtr(addr); + + if (pMem) + *pMem = *value; +} + +void WriteMem16(PGXP_value* src, u32 addr) +{ + PGXP_value* dest = GetPtr(addr); + psx_value* pVal = NULL; + + if (dest) + { + pVal = &dest->value; + // determine if high or low word + if ((addr % 4) == 2) + { + dest->y = src->x; + dest->hFlags = src->lFlags; + pVal->w.h = (u16)src->value; + } + else + { + dest->x = src->x; + dest->lFlags = src->lFlags; + pVal->w.l = (u16)src->value; + } + + dest->valid = dest->valid && src->valid; + dest->gFlags |= src->gFlags; // inherit flags from both values (?) + } +} diff --git a/libpcsxcore/pgxp_mem.h b/libpcsxcore/pgxp_mem.h new file mode 100644 index 00000000..5f79a166 --- /dev/null +++ b/libpcsxcore/pgxp_mem.h @@ -0,0 +1,49 @@ +/*************************************************************************** +* Copyright (C) 2016 by iCatButler * +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 2 of the License, or * +* (at your option) any later version. * +* * +* This program is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU General Public License for more details. * +* * +* You should have received a copy of the GNU General Public License * +* along with this program; if not, write to the * +* Free Software Foundation, Inc., * +* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * +***************************************************************************/ + +/************************************************************************** +* pgxp_mem.h +* PGXP - Parallel/Precision Geometry Xform Pipeline +* +* Created on: 07 Jun 2016 +* Author: iCatButler +***************************************************************************/ + +#ifndef _PGXP_MEM_H_ +#define _PGXP_MEM_H_ + +#include "psxcommon.h" + +void PGXP_Init(); // initialise memory +char* PGXP_GetMem(); // return pointer to precision memory +u32 PGXP_ConvertAddress(u32 addr); + +struct PGXP_value_Tag; +typedef struct PGXP_value_Tag PGXP_value; + +PGXP_value* GetPtr(u32 addr); +PGXP_value* ReadMem(u32 addr); + +void ValidateAndCopyMem(PGXP_value* dest, u32 addr, u32 value); +void ValidateAndCopyMem16(PGXP_value* dest, u32 addr, u32 value); + +void WriteMem(PGXP_value* value, u32 addr); +void WriteMem16(PGXP_value* src, u32 addr); + +#endif//_PGXP_MEM_H_
\ No newline at end of file diff --git a/libpcsxcore/pgxp_value.h b/libpcsxcore/pgxp_value.h new file mode 100644 index 00000000..09bd8925 --- /dev/null +++ b/libpcsxcore/pgxp_value.h @@ -0,0 +1,116 @@ +/*************************************************************************** +* Copyright (C) 2016 by iCatButler * +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 2 of the License, or * +* (at your option) any later version. * +* * +* This program is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU General Public License for more details. * +* * +* You should have received a copy of the GNU General Public License * +* along with this program; if not, write to the * +* Free Software Foundation, Inc., * +* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * +***************************************************************************/ + +/************************************************************************** +* pgxp_value.h +* PGXP - Parallel/Precision Geometry Xform Pipeline +* +* Created on: 07 Jun 2016 +* Author: iCatButler +***************************************************************************/ + +#ifndef _PGXP_VALUE_H_ +#define _PGXP_VALUE_H_ + +#include "psxcommon.h" + +typedef union { +#if defined(__BIGENDIAN__) + struct { u8 h3, h2, h, l; } b; + struct { s8 h3, h2, h, l; } sb; + struct { u16 h, l; } w; + struct { s16 h, l; } sw; +#else + struct { u8 l, h, h2, h3; } b; + struct { u16 l, h; } w; + struct { s8 l, h, h2, h3; } sb; + struct { s16 l, h; } sw; +#endif + u32 d; + s32 sd; +} psx_value; + +typedef struct PGXP_value_Tag +{ + float x; + float y; + float z; + unsigned int valid; + unsigned int count; + unsigned int value; + + unsigned short gFlags; + unsigned char lFlags; + unsigned char hFlags; +} PGXP_value; + +typedef enum +{ + INVALID_ADDRESS = (1 << 1), +} PGXP_value_flags; + +typedef enum +{ + VALID_HALF = (1 << 0) +} PGXP_half_flags; + +static const PGXP_value PGXP_value_invalid_address = { 0.f, 0.f, 0.f, 0, 0, 0, INVALID_ADDRESS, 0, 0 }; +static const PGXP_value PGXP_value_zero = { 0.f, 0.f, 0.f, 0, 0, 1, 0, 0, 0 }; + +inline void MakeValid(PGXP_value *pV, u32 psxV) +{ + psx_value psx; + psx.d = psxV; + if (!pV->valid) + { + pV->x = (float)psx.sw.l; + pV->y = (float)psx.sw.h; + pV->valid = 1; + pV->value = psx.d; + } +} + +inline void Validate(PGXP_value *pV, u32 psxV) +{ + // assume pV is not NULL + pV->valid = (pV->valid) && (pV->value == psxV); +} + +inline void MaskValidate(PGXP_value *pV, u32 psxV, u32 mask) +{ + // assume pV is not NULL + pV->valid = (pV->valid) && ((pV->value & mask) == (psxV & mask)); +} + +typedef union +{ + struct + { + s16 x; + s16 y; + }; + struct + { + u16 ux; + u16 uy; + }; + u32 word; +} low_value; + +#endif//_PGX_VALUE_H_ diff --git a/libpcsxcore/r3000a.c b/libpcsxcore/r3000a.c index be49540e..437d0b15 100755 --- a/libpcsxcore/r3000a.c +++ b/libpcsxcore/r3000a.c @@ -26,7 +26,7 @@ #include "mdec.h" #include "gpu.h" #include "gte.h" -#include "pgxp_gte.h" +#include "pgxp_mem.h" R3000Acpu *psxCpu = NULL; psxRegisters psxRegs; |
