summaryrefslogtreecommitdiff
path: root/libpcsxcore/pgxp_gte.c
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/pgxp_gte.c
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/pgxp_gte.c')
-rw-r--r--libpcsxcore/pgxp_gte.c438
1 files changed, 22 insertions, 416 deletions
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