summaryrefslogtreecommitdiff
path: root/libpcsxcore/pgxp_mem.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_mem.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_mem.c')
-rw-r--r--libpcsxcore/pgxp_mem.c206
1 files changed, 206 insertions, 0 deletions
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 (?)
+ }
+}