From f70082329d751ee8a358437feb34134e283b27d8 Mon Sep 17 00:00:00 2001 From: iCatButler Date: Tue, 7 Jun 2016 15:57:46 +0100 Subject: 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) --- libpcsxcore/pgxp_gte.c | 438 +++---------------------------------------------- 1 file changed, 22 insertions(+), 416 deletions(-) (limited to 'libpcsxcore/pgxp_gte.c') diff --git a/libpcsxcore/pgxp_gte.c b/libpcsxcore/pgxp_gte.c index c130d32c..5fa021c8 100644 --- a/libpcsxcore/pgxp_gte.c +++ b/libpcsxcore/pgxp_gte.c @@ -26,163 +26,16 @@ ***************************************************************************/ #include "pgxp_gte.h" +#include "pgxp_value.h" +#include "pgxp_mem.h" +#include "pgxp_debug.h" +#include "pgxp_cpu.h" + #include "psxcommon.h" #include "psxmem.h" #include "r3000a.h" -typedef struct -{ - float x; - float y; - float z; - unsigned int valid; - unsigned int count; - unsigned int value; -} precise_value; - -typedef union -{ - struct - { - s16 x; - s16 y; - }; - u32 word; -} low_value; - -#define tolerance 1.0f - -precise_value GTE_reg[32]; -precise_value CPU_reg[32]; - -precise_value Mem[3 * 2048 * 1024 / 4]; // mirror 2MB in 32-bit words * 3 -const u32 UserMemOffset = 0; -const u32 ScratchOffset = 2048 * 1024 / 4; -const u32 RegisterOffset = 2 * 2048 * 1024 / 4; -const u32 InvalidAddress = 3 * 2048 * 1024 / 4; - -unsigned int pgxp_debug = 0; - -//precise_value Scratch[2048 * 1024 / 4]; // mirror 2MB in 32-bit words -//precise_value Registers[2048 * 1024 / 4]; // mirror 2MB in 32-bit words - -void PGXP_Init() -{ - memset(Mem, 0, sizeof(Mem)); -} - -char* PGXP_GetMem() -{ - return Config.PGXP_GTE ? (char*)(Mem) : NULL; -} - -/* Playstation Memory Map (from Playstation doc by Joshua Walker) -0x0000_0000-0x0000_ffff Kernel (64K) -0x0001_0000-0x001f_ffff User Memory (1.9 Meg) - -0x1f00_0000-0x1f00_ffff Parallel Port (64K) - -0x1f80_0000-0x1f80_03ff Scratch Pad (1024 bytes) - -0x1f80_1000-0x1f80_2fff Hardware Registers (8K) - -0x1fc0_0000-0x1fc7_ffff BIOS (512K) - -0x8000_0000-0x801f_ffff Kernel and User Memory Mirror (2 Meg) Cached -0x9fc0_0000-0x9fc7_ffff BIOS Mirror (512K) Cached - -0xa000_0000-0xa01f_ffff Kernel and User Memory Mirror (2 Meg) Uncached -0xbfc0_0000-0xbfc7_ffff BIOS Mirror (512K) Uncached -*/ -void ValidateAddress(u32 addr) -{ - int* pi = NULL; - - if ((addr >= 0x00000000) && (addr <= 0x007fffff)) {} // Kernel + User Memory x 8 - else if ((addr >= 0x1f000000) && (addr <= 0x1f00ffff)) {} // Parallel Port - else if ((addr >= 0x1f800000) && (addr <= 0x1f8003ff)) {} // Scratch Pad - else if ((addr >= 0x1f801000) && (addr <= 0x1f802fff)) {} // Hardware Registers - else if ((addr >= 0x1fc00000) && (addr <= 0x1fc7ffff)) {} // Bios - else if ((addr >= 0x80000000) && (addr <= 0x807fffff)) {} // Kernel + User Memory x 8 Cached mirror - else if ((addr >= 0x9fc00000) && (addr <= 0x9fc7ffff)) {} // Bios Cached Mirror - else if ((addr >= 0xa0000000) && (addr <= 0xa07fffff)) {} // Kernel + User Memory x 8 Uncached mirror - else if ((addr >= 0xbfc00000) && (addr <= 0xbfc7ffff)) {} // Bios Uncached Mirror - else if (addr == 0xfffe0130) {} // Used for cache flushing - else - { - // *pi = 5; - } - -} - -u32 PGXP_ConvertAddress(u32 addr) -{ - u32 memOffs = 0; - u32 paddr = addr; - - ValidateAddress(addr); - - switch (paddr >> 24) - { - case 0x80: - case 0xa0: - case 0x00: - // RAM further mirrored over 8MB - paddr = ((paddr & 0x7FFFFF) % 0x200000) >> 2; - paddr = UserMemOffset + paddr; - break; - default: - if ((paddr >> 20) == 0x1f8) - { - if (paddr >= 0x1f801000) - { - // paddr = ((paddr & 0xFFFF) - 0x1000); - // paddr = (paddr % 0x2000) >> 2; - paddr = ((paddr & 0xFFFF) - 0x1000) >> 2; - paddr = RegisterOffset + paddr; - break; - } - else - { - //paddr = ((paddr & 0xFFF) % 0x400) >> 2; - paddr = (paddr & 0x3FF) >> 2; - paddr = ScratchOffset + paddr; - break; - } - } - - paddr = InvalidAddress; - break; - } - -#ifdef GTE_LOG - //GTE_LOG("PGXP_Read %x [%x] |", addr, paddr); -#endif - - return paddr; -} - -precise_value* GetPtr(u32 addr) -{ - addr = PGXP_ConvertAddress(addr); - - if (addr != InvalidAddress) - return &Mem[addr]; - return NULL; -} - -precise_value* ReadMem(u32 addr) -{ - return GetPtr(addr); -} - -void WriteMem(precise_value value, u32 addr) -{ - precise_value* pMem = GetPtr(addr); - - if (pMem) - *pMem = value; -} +PGXP_value GTE_reg[32]; #define SX0 (GTE_reg[ 12 ].x) #define SY0 (GTE_reg[ 12 ].y) @@ -196,67 +49,6 @@ void WriteMem(precise_value value, u32 addr) #define SXY2 (GTE_reg[ 14 ]) #define SXYP (GTE_reg[ 15 ]) -unsigned int PGXP_validate(float high, s16 low) -{ - if (fabs(high - (float)(low)) < tolerance) - return 1; - return 0; -} - -// Check that value is still within tolerance of low precision value and invalidate if not -precise_value PGXP_validateXY(precise_value *high, u32 low) -{ - low_value temp; - precise_value ret; - - ret.valid = 0; - temp.word = low; - - if (!high) - return ret; - - high->valid = (high->valid) && (high->value == low);//(high->valid && PGXP_validate(high->x, temp.x) && PGXP_validate(high->y, temp.y)); - - // Cheat - //if (!high->valid) - //{ - // high->x = temp.x; - // high->y = temp.y; - // high->valid = 1; - // high->value = low; - //} - - return *high; -} - -u32 PGXP_compareXY(precise_value high, u32 low) -{ - low_value temp; - temp.word = low; - - if (PGXP_validate(high.x, temp.x) && PGXP_validate(high.y, temp.y)) - return 1; - return 0; -} - -precise_value PGXP_copyXY(u32 low) -{ - low_value temp; - precise_value ret; - - ret.valid = 0; - temp.word = low; - - ret.z= 1; - ret.x = temp.x; - ret.y = temp.y; - ret.count = 0; - ret.valid = 1; - ret.value = low; - - return ret; -} - void PGXP_pushSXYZ2f(float _x, float _y, float _z, unsigned int _v) { static unsigned int uCount = 0; @@ -280,7 +72,7 @@ void PGXP_pushSXYZ2f(float _x, float _y, float _z, unsigned int _v) GPU_pgxpCacheVertex(0, 0, NULL); #ifdef GTE_LOG - GTE_LOG("PGPR_PUSH (%f, %f) %u %u|", SXY2.x, SXY2.y, SXY2.valid, SXY2.count); + GTE_LOG("PGXP_PUSH (%f, %f) %u %u|", SXY2.x, SXY2.y, SXY2.valid, SXY2.count); #endif } @@ -393,7 +185,7 @@ float PGXP_NCLIP() return nclip; } -static precise_value PGXP_MFC2_int(u32 reg) +static PGXP_value PGXP_MFC2_int(u32 reg) { switch (reg) { @@ -406,7 +198,7 @@ static precise_value PGXP_MFC2_int(u32 reg) } -static void PGXP_MTC2_int(precise_value value, u32 reg) +static void PGXP_MTC2_int(PGXP_value value, u32 reg) { switch(reg) { @@ -433,7 +225,8 @@ void PGXP_MFC2(u32 gpr, u32 gtr, u32 value) GTE_LOG("PGXP_MFC2 [%x]<-[%x] %x (%u %u)|", gpr, gtr, value, GTE_reg[gtr].valid, GTE_reg[gtr].count); #endif - CPU_reg[gpr] = PGXP_validateXY(>E_reg[gtr], value); + Validate(>E_reg[gtr], value); + CPU_reg[gpr] = GTE_reg[gtr]; } // copy GPR reg to GTE data reg (MTC2) @@ -442,15 +235,18 @@ void PGXP_MTC2(u32 gpr, u32 gtr, u32 value) #ifdef GTE_LOG GTE_LOG("PGXP_MTC2 [%x]->[%x] %x (%u %u)|", gpr, gtr, value, CPU_reg[gpr].valid, CPU_reg[gpr].count); #endif - PGXP_MTC2_int(PGXP_validateXY(&CPU_reg[gpr], value), gtr); + Validate(&CPU_reg[gpr], value); + PGXP_MTC2_int(CPU_reg[gpr], gtr); } // copy memory to GTE reg void PGXP_LWC2(u32 addr, u32 gtr, u32 value) { + PGXP_value val; + ValidateAndCopyMem(&val, addr, value); #ifdef GTE_LOG - precise_value* pp = ReadMem(addr); - precise_value p; + PGXP_value* pp = ReadMem(addr); + PGXP_value p; low_value temp; temp.word = value; @@ -461,7 +257,7 @@ void PGXP_LWC2(u32 addr, u32 gtr, u32 value) GTE_LOG("PGXP_LWC2 %x [%x] %x (%d, %d) (%f, %f) %u %u|", addr, gtr, value, temp.x, temp.y, p.x, p.y, p.valid, p.count); #endif - PGXP_MTC2_int(PGXP_validateXY(ReadMem(addr), value), gtr); + PGXP_MTC2_int(val, gtr); } //copy GTE reg to memory @@ -471,200 +267,10 @@ void PGXP_SWC2(u32 addr, u32 gtr, u32 value) low_value temp; temp.word = value; - if (PGXP_compareXY(GTE_reg[gtr], value)) - GTE_LOG("PGPR_SWC2 %x [%x] %x (%d, %d) (%f, %f) %u %u|", addr, gtr, value, temp.x, temp.y, GTE_reg[gtr].x, GTE_reg[gtr].y, GTE_reg[gtr].valid, GTE_reg[gtr].count); -#endif - WriteMem(PGXP_validateXY(>E_reg[gtr], value), addr); -} - -// load 32bit word -void PGPR_L32(u32 addr, u32 code, u32 value) -{ - u32 reg = ((code >> 16) & 0x1F); // The rt part of the instruction register - u32 op = ((code >> 26)); - precise_value p; - - low_value temp; - temp.word = value; - - p.x = p.y = p.valid = p.count = 0; - - switch (op) - { - case 34: //LWL - CPU_reg[reg] = PGXP_validateXY(ReadMem(addr), value); - break; - case 35: //LW - CPU_reg[reg] = PGXP_validateXY(ReadMem(addr), value); - break; - case 38: //LWR - CPU_reg[reg] = PGXP_validateXY(ReadMem(addr), value); - break; - case 50: //LWC2 (GTE vertex reads) - GTE_reg[reg] = PGXP_validateXY(ReadMem(addr), value); - break; - default: - // invalidate register - // CPU_reg[reg] = p; - break; - } - -#ifdef GTE_LOG - GTE_LOG("PGPR_L32 %u: %x %x[%x %x] (%d, %d) (%f, %f) %x %u|", op, addr, value, code, reg, temp.x, temp.y, CPU_reg[reg].x, CPU_reg[reg].y, CPU_reg[reg].valid, CPU_reg[reg].count); -#endif -} - -// store 32bit word -void PGPR_S32(u32 addr, u32 code, u32 value) -{ - u32 reg = ((code >> 16) & 0x1F); // The rt part of the instruction register - u32 op = ((code >> 26)); - precise_value p; - - low_value temp; - temp.word = value; - - p.x = p.y = p.valid = p.count = 0; - -#ifdef GTE_LOG - GTE_LOG("PGPR_S32 %u: %x %x[%x %x] (%d, %d) (%f, %f) %x %u|", op, addr, value, code, reg, temp.x, temp.y, CPU_reg[reg].x, CPU_reg[reg].y, CPU_reg[reg].valid, CPU_reg[reg].count); -#endif - - switch (op) - { - case 42: //SWL - WriteMem(PGXP_validateXY(&CPU_reg[reg], value), addr); - break; - case 43: //SW - WriteMem(PGXP_validateXY(&CPU_reg[reg], value), addr); - break; - case 46: //SWR - WriteMem(PGXP_validateXY(&CPU_reg[reg], value), addr); - break; - case 58: //SWC2 (GTE vertex writes) - WriteMem(PGXP_validateXY(>E_reg[reg], value), addr); - break; - default: - // invalidate memory - // WriteMem(p, addr); - break; - } -} - -// invalidate register (invalid 8/16 bit read) -void PGPR_InvalidLoad(u32 addr, u32 code, u32 value) -{ - u32 reg = ((code >> 16) & 0x1F); // The rt part of the instruction register - precise_value* pD = NULL; - precise_value p; - - p.x = p.y = -1337; // default values - - //p.valid = 0; - //p.count = value; - pD = ReadMem(addr); - - if (pD) - { - p.count = addr; - p = *pD; - } - else - { - p.count = value; - } - - p.valid = 0; - - // invalidate register - CPU_reg[reg] = p; -} - -// invalidate memory address (invalid 8/16 bit write) -void PGPR_InvalidStore(u32 addr, u32 code, u32 value) -{ - u32 reg = ((code >> 16) & 0x1F); // The rt part of the instruction register - precise_value* pD = NULL; - precise_value p; - - pD = ReadMem(addr); - - p.x = p.y = -2337; - - if (pD) - p = *pD; - - p.valid = 0; - p.count = (reg * 1000) + value; - - // invalidate memory - WriteMem(p, addr); -} - -u32 PGXP_psxMemRead32Trace(u32 mem, u32 code) -{ - u32 value = psxMemRead32(mem); - PGPR_L32(mem, code, value); - return value; -} - -void PGXP_psxMemWrite32Trace(u32 mem, u32 value, u32 code) -{ - PGPR_S32(mem, code, value); - psxMemWrite32(mem, value); -} - -u16 PGXP_psxMemRead16Trace(u32 mem, u32 code) -{ - u16 value = psxMemRead16(mem); -#ifdef GTE_LOG - u32 reg = ((code >> 16) & 0x1F); // The rt part of the instruction register - GTE_LOG("PGPR_L16 %x %x[%x %x]|", mem, value, code, reg); +// if (PGXP_compareXY(GTE_reg[gtr], value)) + GTE_LOG("PGXP_SWC2 %x [%x] %x (%d, %d) (%f, %f) %u %u|", addr, gtr, value, temp.x, temp.y, GTE_reg[gtr].x, GTE_reg[gtr].y, GTE_reg[gtr].valid, GTE_reg[gtr].count); #endif - PGPR_InvalidLoad(mem, code, 116); - return value; + Validate(>E_reg[gtr], value); + WriteMem(>E_reg[gtr], addr); } -void PGXP_psxMemWrite16Trace(u32 mem, u16 value, u32 code) -{ - PGPR_InvalidStore(mem, code, 216); -#ifdef GTE_LOG - u32 reg = ((code >> 16) & 0x1F); // The rt part of the instruction register - GTE_LOG("PGPR_S16 %x %x[%x %x]|", mem, value, code, reg); -#endif - psxMemWrite16(mem, value); -} - -u8 PGXP_psxMemRead8Trace(u32 mem, u32 code) -{ - u8 value = psxMemRead8(mem); -#ifdef GTE_LOG - u32 reg = ((code >> 16) & 0x1F); // The rt part of the instruction register - GTE_LOG("PGPR_L8 %x %x[%x %x]|", mem, value, code, reg); -#endif - PGPR_InvalidLoad(mem, code, 18); - return value; -} - -void PGXP_psxMemWrite8Trace(u32 mem, u8 value, u32 code) -{ - PGPR_InvalidStore(mem, code, 28); -#ifdef GTE_LOG - u32 reg = ((code >> 16) & 0x1F); // The rt part of the instruction register - GTE_LOG("PGPR_S8 %x %x[%x %x]|", mem, value, code, reg); -#endif - psxMemWrite8(mem, value); -} - -void PGXP_psxTrace(u32 code, u32 rtv) -{ -#ifdef GTE_LOG -//u32 reg = ((code >> 16) & 0x1F); // The rt part of the instruction register - u32 op = ((code >> 26)); - u32 func = ((code ) & 0x3F); // The funct part of the instruction register - u32 rd = ((code >> 11) & 0x1F); // The rd part of the instruction register - u32 rt = ((code >> 16) & 0x1F); // The rt part of the instruction register - u32 rs = ((code >> 21) & 0x1F); // The rs part of the instruction register - GTE_LOG("PGPR_Trace op:%u func:%u [rt:%x (%x) rs:%x rd:%x] %x|", op, func, rt, rtv, rs, rd, code); -#endif -} \ No newline at end of file -- cgit v1.2.3