summaryrefslogtreecommitdiff
path: root/libpcsxcore
diff options
context:
space:
mode:
authoriCatButler <i.am.catbutler@gmail.com>2016-06-07 15:57:46 +0100
committeriCatButler <i.am.catbutler@gmail.com>2016-06-07 15:57:46 +0100
commitf70082329d751ee8a358437feb34134e283b27d8 (patch)
treec97c99835067e9a20725943b4b4c63d44d4e3bdc /libpcsxcore
parent7ecfee1f664eeb92b653104f5f3c915cc6fe6bcb (diff)
downloadpcsxr-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-xlibpcsxcore/gpu.c2
-rwxr-xr-xlibpcsxcore/gte.c1
-rwxr-xr-xlibpcsxcore/ix86/iR3000A.c1158
-rw-r--r--libpcsxcore/pgxp_cpu.c737
-rw-r--r--libpcsxcore/pgxp_cpu.h115
-rw-r--r--libpcsxcore/pgxp_debug.c314
-rw-r--r--libpcsxcore/pgxp_debug.h42
-rw-r--r--libpcsxcore/pgxp_gte.c438
-rw-r--r--libpcsxcore/pgxp_gte.h21
-rw-r--r--libpcsxcore/pgxp_mem.c206
-rw-r--r--libpcsxcore/pgxp_mem.h49
-rw-r--r--libpcsxcore/pgxp_value.h116
-rwxr-xr-xlibpcsxcore/r3000a.c2
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, &regIdx);
+ strcat(szBuffer, "= ");
+ // Print inputs
+ PrintOperands(szBuffer, instr, opData.InputFlags, opData.szOpString, psx_regs, &regIdx);
+
+#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(&GTE_reg[gtr], value);
+ Validate(&GTE_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(&GTE_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(&GTE_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(&GTE_reg[gtr], value);
+ WriteMem(&GTE_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;