mirror of
https://github.com/PCSX2/pcsx2.git
synced 2025-04-02 10:52:54 -04:00
3330 lines
82 KiB
C
3330 lines
82 KiB
C
/* Pcsx2 - Pc Ps2 Emulator
|
|
* Copyright (C) 2002-2003 Pcsx2 Team
|
|
*
|
|
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
*/
|
|
|
|
/*
|
|
|
|
RAM
|
|
---
|
|
0x00100000-0x01ffffff this is the physical address for the ram.its cached there
|
|
0x20100000-0x21ffffff uncached
|
|
0x30100000-0x31ffffff uncached & acceleretade
|
|
0xa0000000-0xa1ffffff MIRROR might...???
|
|
0x80000000-0x81ffffff MIRROR might... ????
|
|
|
|
scratch pad
|
|
----------
|
|
0x70000000-0x70003fff scratch pad
|
|
|
|
BIOS
|
|
----
|
|
0x1FC00000 - 0x1FFFFFFF un-cached
|
|
0x9FC00000 - 0x9FFFFFFF cached
|
|
0xBFC00000 - 0xBFFFFFFF un-cached
|
|
*/
|
|
|
|
//////////
|
|
// Rewritten by zerofrog(@gmail.com) to add os virtual memory
|
|
//////////
|
|
|
|
|
|
#if _WIN32_WINNT < 0x0500
|
|
#define _WIN32_WINNT 0x0500
|
|
#endif
|
|
|
|
#pragma warning(disable:4799) // No EMMS at end of function
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <malloc.h>
|
|
#include <sys/stat.h>
|
|
|
|
#include "Common.h"
|
|
|
|
#ifdef PCSX2_NORECBUILD
|
|
#define REC_CLEARM(mem)
|
|
#else
|
|
#include "iR5900.h"
|
|
#endif
|
|
|
|
#include "PsxMem.h"
|
|
#include "R3000A.h"
|
|
#include "PsxHw.h"
|
|
#include "VUmicro.h"
|
|
#include "GS.h"
|
|
|
|
#ifdef ENABLECACHE
|
|
#include "Cache.h"
|
|
#endif
|
|
|
|
#include <assert.h>
|
|
|
|
extern u32 maxrecmem;
|
|
extern int rdram_devices, rdram_sdevid;
|
|
|
|
#ifndef __x86_64__
|
|
extern void * memcpy_fast(void *dest, const void *src, size_t n);
|
|
#endif
|
|
|
|
//#define FULLTLB
|
|
int MemMode = 0; // 0 is Kernel Mode, 1 is Supervisor Mode, 2 is User Mode
|
|
|
|
u16 ba0R16(u32 mem) {
|
|
#ifdef MEM_LOG
|
|
//MEM_LOG("ba00000 Memory read16 address %x\n", mem);
|
|
#endif
|
|
|
|
#ifdef PCSX2_VIRTUAL_MEM
|
|
if (mem == 0x1a000006) {
|
|
#else
|
|
if (mem == 0xba000006) {
|
|
#endif
|
|
static int ba6;
|
|
ba6++;
|
|
if (ba6 == 3) ba6 = 0;
|
|
return ba6;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/////////////////////////////
|
|
// VIRTUAL MEM START
|
|
/////////////////////////////
|
|
#ifdef PCSX2_VIRTUAL_MEM
|
|
|
|
PSMEMORYBLOCK s_psM = {0}, s_psHw = {0}, s_psS = {0}, s_psxM = {0}, s_psVuMem = {0};
|
|
|
|
#define PHYSICAL_ALLOC(ptr, size, block) { \
|
|
if(SysPhysicalAlloc(size, &block) == -1 ) \
|
|
goto eCleanupAndExit; \
|
|
if(SysVirtualPhyAlloc((void*)ptr, size, &block) == -1) \
|
|
goto eCleanupAndExit; \
|
|
} \
|
|
|
|
#define PHYSICAL_FREE(ptr, size, block) { \
|
|
SysVirtualFree(ptr, size); \
|
|
SysPhysicalFree(&block); \
|
|
} \
|
|
|
|
#ifdef _WIN32 // windows implementation of vm
|
|
|
|
PSMEMORYMAP initMemoryMap(ULONG_PTR* aPFNs, ULONG_PTR* aVFNs)
|
|
{
|
|
PSMEMORYMAP m;
|
|
m.aPFNs = aPFNs;
|
|
m.aVFNs = aVFNs;
|
|
return m;
|
|
}
|
|
|
|
// only do vm hack for release
|
|
#ifndef PCSX2_DEVBUILD
|
|
#define VM_HACK
|
|
#endif
|
|
|
|
static int XmmExtendedRegOffset = 160;
|
|
|
|
// virtual memory blocks
|
|
PSMEMORYMAP *memLUT = NULL;
|
|
|
|
#define VIRTUAL_ALLOC(base, size, Protection) { \
|
|
LPVOID lpMemReserved = VirtualAlloc( base, size, MEM_RESERVE|MEM_COMMIT, Protection ); \
|
|
if( lpMemReserved == NULL || base != lpMemReserved ) \
|
|
{ \
|
|
SysPrintf("Cannot reserve memory at 0x%8.8x(%x), error: %d.\n", base, lpMemReserved, GetLastError()); \
|
|
goto eCleanupAndExit; \
|
|
} \
|
|
} \
|
|
|
|
#define VIRTUAL_FREE(ptr, size) { \
|
|
VirtualFree(ptr, size, MEM_DECOMMIT); \
|
|
VirtualFree(ptr, 0, MEM_RELEASE); \
|
|
} \
|
|
|
|
static int s_testmem[4] = { 0xfafafafa, 0xbabababa, 0xbfa8123f, 0xa123fde0 };
|
|
|
|
INT FindXmmOffsetException(LPEXCEPTION_POINTERS pexdata)
|
|
{
|
|
int i;
|
|
u32* p = (u32*)pexdata->ContextRecord->ExtendedRegisters;
|
|
|
|
assert( pexdata->ExceptionRecord->ExceptionCode == EXCEPTION_ACCESS_VIOLATION);
|
|
|
|
XmmExtendedRegOffset = 160;
|
|
|
|
for(i = 0; i < sizeof(pexdata->ContextRecord->ExtendedRegisters)/4; ++i, ++p ) {
|
|
if( p[0] == s_testmem[0] && p[1] == s_testmem[1] && p[2] == s_testmem[2] && p[3] == s_testmem[3] ) {
|
|
XmmExtendedRegOffset = i*4;
|
|
break;
|
|
}
|
|
}
|
|
|
|
pexdata->ContextRecord->Eip += 7;
|
|
|
|
return EXCEPTION_CONTINUE_EXECUTION;
|
|
}
|
|
|
|
#if _MSC_VER < 1400
|
|
#define VC_HANDLER _except_handler3
|
|
#else
|
|
#define VC_HANDLER _except_handler4
|
|
#endif
|
|
|
|
//C's default exception handler
|
|
EXCEPTION_DISPOSITION VC_HANDLER(
|
|
struct _EXCEPTION_RECORD *ExceptionRecord,
|
|
void * EstablisherFrame,
|
|
struct _CONTEXT *ContextRecord,
|
|
void * DispatcherContext
|
|
);
|
|
|
|
char cpp_handler_instructions[5];
|
|
BOOL saved_handler_instructions = FALSE;
|
|
|
|
//Exception handler that replaces C's default handler.
|
|
EXCEPTION_DISPOSITION SysPageFaultExceptionFilter(
|
|
struct _EXCEPTION_RECORD *ExceptionRecord,
|
|
void * EstablisherFrame,
|
|
struct _CONTEXT *ContextRecord,
|
|
void * DispatcherContext
|
|
);
|
|
|
|
#pragma pack(1)
|
|
typedef struct _jmp_instr
|
|
{
|
|
unsigned char jmp;
|
|
DWORD offset;
|
|
} jmp_instr;
|
|
#pragma pack()
|
|
|
|
BOOL WriteMemory(void * loc, void * buffer, int size)
|
|
{
|
|
DWORD o2;
|
|
HANDLE hProcess = GetCurrentProcess();
|
|
|
|
//change the protection of pages containing range of memory
|
|
//[loc, loc+size] to READ WRITE
|
|
DWORD old_protection;
|
|
|
|
BOOL ret;
|
|
ret = VirtualProtectEx(hProcess, loc, size,
|
|
PAGE_READWRITE, &old_protection);
|
|
if(ret == FALSE)
|
|
return FALSE;
|
|
|
|
ret = WriteProcessMemory(hProcess, loc, buffer, size, NULL);
|
|
|
|
//restore old protection
|
|
VirtualProtectEx(hProcess, loc, size, old_protection, &o2);
|
|
|
|
return (ret == TRUE);
|
|
}
|
|
|
|
BOOL ReadMemory(void *loc, void *buffer, DWORD size)
|
|
{
|
|
HANDLE hProcess = GetCurrentProcess();
|
|
DWORD bytes_read = 0;
|
|
BOOL ret;
|
|
ret = ReadProcessMemory(hProcess, loc, buffer, size, &bytes_read);
|
|
return (ret == TRUE && bytes_read == size);
|
|
}
|
|
|
|
BOOL install_my_handler()
|
|
{
|
|
void * my_hdlr = SysPageFaultExceptionFilter;
|
|
void * cpp_hdlr = VC_HANDLER;
|
|
|
|
jmp_instr jmp_my_hdlr;
|
|
jmp_my_hdlr.jmp = 0xE9;
|
|
|
|
//We actually calculate the offset from __CxxFrameHandler+5
|
|
//as the jmp instruction is 5 byte length.
|
|
jmp_my_hdlr.offset = (char*)(my_hdlr) -
|
|
((char*)(cpp_hdlr) + 5);
|
|
|
|
if(!saved_handler_instructions)
|
|
{
|
|
if(!ReadMemory(cpp_hdlr, cpp_handler_instructions,
|
|
sizeof(cpp_handler_instructions)))
|
|
return FALSE;
|
|
saved_handler_instructions = TRUE;
|
|
}
|
|
|
|
return WriteMemory(cpp_hdlr, &jmp_my_hdlr, sizeof(jmp_my_hdlr));
|
|
}
|
|
|
|
BOOL restore_cpp_handler()
|
|
{
|
|
if(!saved_handler_instructions)
|
|
return FALSE;
|
|
else
|
|
{
|
|
void *loc = VC_HANDLER;
|
|
return WriteMemory(loc, cpp_handler_instructions,
|
|
sizeof(cpp_handler_instructions));
|
|
}
|
|
}
|
|
|
|
int memInit() {
|
|
|
|
int i;
|
|
LPVOID pExtraMem = NULL;
|
|
|
|
// release the previous reserved mem
|
|
VirtualFree(PS2MEM_BASE, 0, MEM_RELEASE);
|
|
|
|
// allocate all virtual memory
|
|
PHYSICAL_ALLOC(PS2MEM_BASE, 0x02000000, s_psM);
|
|
VIRTUAL_ALLOC(PS2MEM_ROM, 0x00400000, PAGE_READONLY);
|
|
VIRTUAL_ALLOC(PS2MEM_ROM1, 0x00040000, PAGE_READONLY);
|
|
VIRTUAL_ALLOC(PS2MEM_ROM2, 0x00080000, PAGE_READONLY);
|
|
VIRTUAL_ALLOC(PS2MEM_EROM, 0x001C0000, PAGE_READONLY);
|
|
PHYSICAL_ALLOC(PS2MEM_SCRATCH, 0x00010000, s_psS);
|
|
PHYSICAL_ALLOC(PS2MEM_HW, 0x00010000, s_psHw);
|
|
PHYSICAL_ALLOC(PS2MEM_PSX, 0x00200000, s_psxM);
|
|
PHYSICAL_ALLOC(PS2MEM_VU0MICRO, 0x00010000, s_psVuMem);
|
|
|
|
VIRTUAL_ALLOC(PS2MEM_PSXHW, 0x00010000, PAGE_READWRITE);
|
|
VIRTUAL_ALLOC(PS2MEM_PSXHW4, 0x00010000, PAGE_NOACCESS);
|
|
VIRTUAL_ALLOC(PS2MEM_GS, 0x00002000, PAGE_READWRITE);
|
|
VIRTUAL_ALLOC(PS2MEM_DEV9, 0x00010000, PAGE_NOACCESS);
|
|
VIRTUAL_ALLOC(PS2MEM_SPU2, 0x00010000, PAGE_NOACCESS);
|
|
VIRTUAL_ALLOC(PS2MEM_SPU2_, 0x00010000, PAGE_NOACCESS);
|
|
|
|
VIRTUAL_ALLOC(PS2MEM_B80, 0x00010000, PAGE_READWRITE);
|
|
VIRTUAL_ALLOC(PS2MEM_BA0, 0x00010000, PAGE_READWRITE);
|
|
|
|
// reserve the left over 224Mb, don't map
|
|
pExtraMem = VirtualAlloc(PS2MEM_BASE+0x02000000, 0x0e000000, MEM_RESERVE|MEM_PHYSICAL, PAGE_READWRITE);
|
|
if( pExtraMem != PS2MEM_BASE+0x02000000 )
|
|
goto eCleanupAndExit;
|
|
|
|
// reserve left over psx mem
|
|
pExtraMem = VirtualAlloc(PS2MEM_PSX+0x00200000, 0x00600000, MEM_RESERVE|MEM_PHYSICAL, PAGE_READWRITE);
|
|
if( pExtraMem != PS2MEM_PSX+0x00200000 )
|
|
goto eCleanupAndExit;
|
|
|
|
// reserve gs mem
|
|
pExtraMem = VirtualAlloc(PS2MEM_BASE+0x20000000, 0x10000000, MEM_RESERVE|MEM_PHYSICAL, PAGE_READWRITE);
|
|
if( pExtraMem != PS2MEM_BASE+0x20000000 )
|
|
goto eCleanupAndExit;
|
|
|
|
// special addrs mmap
|
|
VIRTUAL_ALLOC(PS2MEM_BASE+0x5fff0000, 0x10000, PAGE_READWRITE);
|
|
|
|
// alloc virtual mappings
|
|
memLUT = (PSMEMORYMAP*)_aligned_malloc(0x100000 * sizeof(PSMEMORYMAP), 16);
|
|
memset(memLUT, 0, sizeof(PSMEMORYMAP)*0x100000);
|
|
for (i=0; i<0x02000; i++) memLUT[i + 0x00000] = initMemoryMap(&s_psM.aPFNs[i], &s_psM.aVFNs[i]);
|
|
for (i=2; i<0x00010; i++) memLUT[i + 0x10000] = initMemoryMap(&s_psHw.aPFNs[i], &s_psHw.aVFNs[i]);
|
|
for (i=0; i<0x00800; i++) memLUT[i + 0x1c000] = initMemoryMap(&s_psxM.aPFNs[(i & 0x1ff)], &s_psxM.aVFNs[(i & 0x1ff)]);
|
|
for (i=0; i<0x00004; i++) memLUT[i + 0x11000] = initMemoryMap(&s_psVuMem.aPFNs[0], &s_psVuMem.aVFNs[0]);
|
|
for (i=0; i<0x00004; i++) memLUT[i + 0x11004] = initMemoryMap(&s_psVuMem.aPFNs[1], &s_psVuMem.aVFNs[1]);
|
|
for (i=0; i<0x00004; i++) memLUT[i + 0x11008] = initMemoryMap(&s_psVuMem.aPFNs[4+i], &s_psVuMem.aVFNs[4+i]);
|
|
for (i=0; i<0x00004; i++) memLUT[i + 0x1100c] = initMemoryMap(&s_psVuMem.aPFNs[8+i], &s_psVuMem.aVFNs[8+i]);
|
|
|
|
for (i=0; i<0x00004; i++) memLUT[i + 0x50000] = initMemoryMap(&s_psS.aPFNs[i], &s_psS.aVFNs[i]);
|
|
|
|
// map to other modes
|
|
memcpy(memLUT+0x80000, memLUT, 0x20000*sizeof(PSMEMORYMAP));
|
|
memcpy(memLUT+0xa0000, memLUT, 0x20000*sizeof(PSMEMORYMAP));
|
|
|
|
if (psxInit() == -1)
|
|
goto eCleanupAndExit;
|
|
|
|
// figure out xmm reg offset
|
|
// __asm movups xmm0, s_testmem
|
|
// __try {
|
|
// u8* p = 0;
|
|
// __asm {
|
|
// mov eax, dword ptr [p]
|
|
// }
|
|
// }
|
|
// __except( FindXmmOffsetException( GetExceptionInformation() ) ) {
|
|
// }
|
|
|
|
//#ifdef WIN32_FILE_MAPPING
|
|
if( !install_my_handler() ) {
|
|
SysPrintf("Failed to install custom exception handler!\n");
|
|
return -1;
|
|
}
|
|
//#endif
|
|
|
|
return 0;
|
|
|
|
eCleanupAndExit:
|
|
if( pExtraMem != NULL )
|
|
VirtualFree(pExtraMem, 0x0e000000, MEM_RELEASE);
|
|
memShutdown();
|
|
return -1;
|
|
}
|
|
|
|
void memShutdown()
|
|
{
|
|
VirtualFree(PS2MEM_BASE+0x02000000, 0, MEM_RELEASE);
|
|
VirtualFree(PS2MEM_PSX+0x00200000, 0, MEM_RELEASE);
|
|
VirtualFree(PS2MEM_BASE+0x20000000, 0, MEM_RELEASE);
|
|
|
|
PHYSICAL_FREE(PS2MEM_BASE, 0x02000000, s_psM);
|
|
VIRTUAL_FREE(PS2MEM_ROM, 0x00400000);
|
|
VIRTUAL_FREE(PS2MEM_ROM1, 0x00080000);
|
|
VIRTUAL_FREE(PS2MEM_ROM2, 0x00080000);
|
|
VIRTUAL_FREE(PS2MEM_EROM, 0x001C0000);
|
|
PHYSICAL_FREE(PS2MEM_SCRATCH, 0x00010000, s_psS);
|
|
PHYSICAL_FREE(PS2MEM_HW, 0x00010000, s_psHw);
|
|
PHYSICAL_FREE(PS2MEM_PSX, 0x00800000, s_psxM);
|
|
PHYSICAL_FREE(PS2MEM_VU0MICRO, 0x00010000, s_psVuMem);
|
|
|
|
VIRTUAL_FREE(PS2MEM_VU0MICRO, 0x00010000); // allocate for all VUs
|
|
|
|
VIRTUAL_FREE(PS2MEM_PSXHW, 0x00010000);
|
|
VIRTUAL_FREE(PS2MEM_PSXHW4, 0x00010000);
|
|
VIRTUAL_FREE(PS2MEM_GS, 0x00010000);
|
|
VIRTUAL_FREE(PS2MEM_DEV9, 0x00010000);
|
|
VIRTUAL_FREE(PS2MEM_SPU2, 0x00010000);
|
|
VIRTUAL_FREE(PS2MEM_SPU2_, 0x00010000);
|
|
|
|
VIRTUAL_FREE(PS2MEM_B80, 0x00010000);
|
|
VIRTUAL_FREE(PS2MEM_BA0, 0x00010000);
|
|
|
|
VirtualFree(PS2MEM_VU0MICRO, 0, MEM_RELEASE);
|
|
|
|
_aligned_free(memLUT); memLUT = NULL;
|
|
|
|
// reserve mem
|
|
VirtualAlloc(PS2MEM_BASE, 0x40000000, MEM_RESERVE, PAGE_NOACCESS);
|
|
}
|
|
|
|
#define GET_REGVALUE(code) *((u32*)&pexdata->ContextRecord->Eax + (((code)>>11)&7))
|
|
#define GET_XMMVALUE(xmm) ((u64*)((u8*)pexdata->ContextRecord->ExtendedRegisters + XmmExtendedRegOffset + ((xmm)<<4)))
|
|
|
|
//NOTE: A lot of the code reading depends on the registers being less than 8
|
|
// MOV8 88/8A
|
|
// MOV16 6689
|
|
// MOV32 89/8B
|
|
// SSEMtoR64 120f
|
|
// SSERtoM64 130f
|
|
// SSEMtoR128 280f
|
|
// SSERtoM128 290f
|
|
|
|
#define SKIP_WRITE(pexdata) { \
|
|
switch(code&0xff) { \
|
|
case 0x88: \
|
|
if( !(code&0x8000) ) goto DefaultHandler; \
|
|
ContextRecord->Eip += 6; \
|
|
break; \
|
|
case 0x66: \
|
|
assert( code&0x800000 ); \
|
|
assert( (code&0xffff) == 0x8966 ); \
|
|
ContextRecord->Eip += 7; \
|
|
break; \
|
|
case 0x89: \
|
|
assert( code&0x8000 ); \
|
|
ContextRecord->Eip += 6; \
|
|
break; \
|
|
case 0x0f: /* 130f, 230f*/ \
|
|
assert( (code&0xffff) == 0x290f || (code&0xffff) == 0x130f ); \
|
|
assert( code&0x800000 ); \
|
|
ContextRecord->Eip += 7; \
|
|
break; \
|
|
default: \
|
|
goto DefaultHandler; \
|
|
} \
|
|
} \
|
|
|
|
#define SKIP_READ(pexdata) { \
|
|
switch(code&0xff) { \
|
|
case 0x8A: \
|
|
if( !(code&0x8000) ) goto DefaultHandler; \
|
|
ContextRecord->Eip += 6; \
|
|
rd = (code>>(8+3))&7; \
|
|
break; \
|
|
case 0x66: \
|
|
if( (code&0x07000000) == 0x05000000 ) ContextRecord->Eip += 8; /* 8 for mem reads*/ \
|
|
else ContextRecord->Eip += 4 + ((code&0x1f000000) == 0x0c000000) + !!(code&0x40000000); \
|
|
rd = (code>>(24+3))&7; \
|
|
break; \
|
|
case 0x8B: \
|
|
if( !(code&0x8000) ) goto DefaultHandler; \
|
|
ContextRecord->Eip += 6; \
|
|
rd = (code>>(8+3))&7; \
|
|
break; \
|
|
case 0x0f: { \
|
|
assert( (code&0xffff)==0x120f || (code&0xffff)==0x280f || (code&0xffff) == 0xb60f || (code&0xffff) == 0xb70f ); \
|
|
if( !(code&0x800000) ) goto DefaultHandler; \
|
|
ContextRecord->Eip += 7; \
|
|
rd = (code>>(16+3))&7; \
|
|
break; } \
|
|
default: \
|
|
goto DefaultHandler; \
|
|
} \
|
|
} \
|
|
|
|
EXCEPTION_DISPOSITION SysPageFaultExceptionFilter(
|
|
struct _EXCEPTION_RECORD *ExceptionRecord,
|
|
void * EstablisherFrame,
|
|
struct _CONTEXT *ContextRecord,
|
|
void * DispatcherContext
|
|
)
|
|
{
|
|
u32 addr;
|
|
|
|
C_ASSERT(sizeof(ContextRecord->Eax) == 4);
|
|
|
|
// If the exception is not a page fault, exit.
|
|
if (ExceptionRecord->ExceptionCode != EXCEPTION_ACCESS_VIOLATION)
|
|
{
|
|
// call old handler
|
|
EXCEPTION_DISPOSITION d;
|
|
restore_cpp_handler();
|
|
d = VC_HANDLER(ExceptionRecord, EstablisherFrame, ContextRecord, DispatcherContext);
|
|
install_my_handler();
|
|
return d;
|
|
}
|
|
|
|
// get bad virtual address
|
|
addr = (u32)ExceptionRecord->ExceptionInformation[1];
|
|
|
|
if( addr >= (u32)PS2MEM_BASE && addr < (u32)PS2MEM_BASE+0x60000000) {
|
|
PSMEMORYMAP* pmap;
|
|
|
|
pmap = &memLUT[(addr-(u32)PS2MEM_BASE)>>12];
|
|
|
|
if( pmap->aPFNs == NULL ) {
|
|
// NOTE: this is a hack because the address is truncated and there's no way
|
|
// to tell what it's upper bits are (due to OS limitations).
|
|
pmap += 0x80000;
|
|
if( pmap->aPFNs == NULL ) {
|
|
pmap += 0x20000;
|
|
}
|
|
//else addr += 0x20000000;
|
|
}
|
|
|
|
if( pmap->aPFNs != NULL ) {
|
|
LPVOID pnewaddr;
|
|
DWORD oldaddr = pmap->aVFNs[0];
|
|
|
|
if( pmap->aVFNs[0] != 0 ) {
|
|
// delete the current mapping
|
|
SysMapUserPhysicalPages((void*)pmap->aVFNs[0], 1, NULL, 0);
|
|
}
|
|
|
|
assert( pmap->aPFNs[0] != 0 );
|
|
|
|
pmap->aVFNs[0] = addr&~0xfff;
|
|
if( SysMapUserPhysicalPages((void*)(addr&~0xfff), 1, pmap->aPFNs, 0) )
|
|
return ExceptionContinueExecution;
|
|
|
|
// try allocing the virtual mem
|
|
pnewaddr = VirtualAlloc((void*)(addr&~0xffff), 0x10000, MEM_RESERVE|MEM_PHYSICAL, PAGE_READWRITE);
|
|
|
|
if( SysMapUserPhysicalPages((void*)(addr&~0xfff), 1, pmap->aPFNs, 0) )
|
|
return ExceptionContinueExecution;
|
|
|
|
SysPrintf("Fatal error, virtual page 0x%x cannot be found %d (p:%x,v:%x)\n",
|
|
addr-(u32)PS2MEM_BASE, GetLastError(), pmap->aPFNs[0], pmap->aVFNs[0]);
|
|
}
|
|
}
|
|
else {
|
|
// check if vumem
|
|
|
|
if( (addr&0xffff4000) == 0x11000000 ) {
|
|
// vu0mem
|
|
SysMapUserPhysicalPages((void*)s_psVuMem.aVFNs[1], 1, NULL, 0);
|
|
|
|
s_psVuMem.aVFNs[1] = addr&~0xfff;
|
|
SysMapUserPhysicalPages((void*)addr, 1, s_psVuMem.aPFNs, 1);
|
|
|
|
return ExceptionContinueExecution;//EXCEPTION_CONTINUE_EXECUTION;
|
|
}
|
|
}
|
|
|
|
{
|
|
// call old handler
|
|
EXCEPTION_DISPOSITION d;
|
|
|
|
#ifdef VM_HACK
|
|
u32 code = *(u32*)ExceptionRecord->ExceptionAddress;
|
|
u32 rd = 0;
|
|
|
|
if( ExceptionRecord->ExceptionInformation[0] ) {
|
|
//SKIP_WRITE(ptrs);
|
|
// shouldn't be writing
|
|
}
|
|
else {
|
|
SysPrintf("vmhack ");
|
|
SKIP_READ(ptrs);
|
|
//((u32*)&ContextRecord->Eax)[rd] = 0;
|
|
return ExceptionContinueExecution;
|
|
}
|
|
|
|
DefaultHandler:
|
|
#endif
|
|
restore_cpp_handler();
|
|
d = VC_HANDLER(ExceptionRecord, EstablisherFrame, ContextRecord, DispatcherContext);
|
|
install_my_handler();
|
|
return d;
|
|
}
|
|
|
|
// continue execution
|
|
return EXCEPTION_CONTINUE_EXECUTION;
|
|
}
|
|
|
|
#else // linux implementation
|
|
|
|
#define VIRTUAL_ALLOC(base, size, Protection) { \
|
|
void* lpMemReserved = mmap( base, size, Protection, MAP_PRIVATE|MAP_ANONYMOUS ); \
|
|
if( lpMemReserved == NULL || base != lpMemReserved ) \
|
|
{ \
|
|
SysPrintf("Cannot reserve memory at 0x%8.8x(%x).\n", base, lpMemReserved); \
|
|
perror("err"); \
|
|
goto eCleanupAndExit; \
|
|
} \
|
|
} \
|
|
|
|
#define VIRTUAL_FREE(ptr, size) munmap(ptr, size)
|
|
|
|
uptr *memLUT = NULL;
|
|
|
|
int memInit()
|
|
{
|
|
int i;
|
|
LPVOID pExtraMem = NULL;
|
|
|
|
// release the previous reserved mem
|
|
munmap(PS2MEM_BASE, 0x40000000);
|
|
|
|
// allocate all virtual memory
|
|
PHYSICAL_ALLOC(PS2MEM_BASE, 0x02000000, s_psM);
|
|
VIRTUAL_ALLOC(PS2MEM_ROM, 0x00400000, PROT_READ);
|
|
VIRTUAL_ALLOC(PS2MEM_ROM1, 0x00040000, PROT_READ);
|
|
VIRTUAL_ALLOC(PS2MEM_ROM2, 0x00080000, PROT_READ);
|
|
VIRTUAL_ALLOC(PS2MEM_EROM, 0x001C0000, PROT_READ);
|
|
PHYSICAL_ALLOC(PS2MEM_SCRATCH, 0x00010000, s_psS);
|
|
PHYSICAL_ALLOC(PS2MEM_HW, 0x00010000, s_psHw);
|
|
PHYSICAL_ALLOC(PS2MEM_PSX, 0x00200000, s_psxM);
|
|
PHYSICAL_ALLOC(PS2MEM_VU0MICRO, 0x00010000, s_psVuMem);
|
|
|
|
VIRTUAL_ALLOC(PS2MEM_PSXHW, 0x00010000, PROT_READ|PROT_WRITE);
|
|
VIRTUAL_ALLOC(PS2MEM_PSXHW4, 0x00010000, PROT_NONE);
|
|
VIRTUAL_ALLOC(PS2MEM_GS, 0x00002000, PROT_READ|PROT_WRITE);
|
|
VIRTUAL_ALLOC(PS2MEM_DEV9, 0x00010000, PROT_NONE);
|
|
VIRTUAL_ALLOC(PS2MEM_SPU2, 0x00010000, PROT_NONE);
|
|
VIRTUAL_ALLOC(PS2MEM_SPU2_, 0x00010000, PROT_NONE);
|
|
|
|
VIRTUAL_ALLOC(PS2MEM_B80, 0x00010000, PROT_READ|PROT_WRITE);
|
|
VIRTUAL_ALLOC(PS2MEM_BA0, 0x00010000, PROT_READ|PROT_WRITE);
|
|
|
|
// special addrs mmap
|
|
VIRTUAL_ALLOC(PS2MEM_BASE+0x5fff0000, 0x10000, PROT_READ|PROT_WRITE);
|
|
|
|
// alloc virtual mappings
|
|
memLUT = (PSMEMORYMAP*)_aligned_malloc(0x100000 * sizeof(uptr), 16);
|
|
memset(memLUT, 0, sizeof(uptr)*0x100000);
|
|
for (i=0; i<0x02000; i++) memLUT[i + 0x00000] = PS2MEM_BASE+(i<<12);
|
|
for (i=2; i<0x00010; i++) memLUT[i + 0x10000] = PS2MEM_BASE+0x10000000+(i<<12);
|
|
for (i=0; i<0x00800; i++) memLUT[i + 0x1c000] = PS2MEM_BASE+0x1c000000+(i<<12);
|
|
for (i=0; i<0x00004; i++) memLUT[i + 0x11000] = PS2MEM_VU0MICRO;
|
|
for (i=0; i<0x00004; i++) memLUT[i + 0x11004] = PS2MEM_VU0MEM;
|
|
for (i=0; i<0x00004; i++) memLUT[i + 0x11008] = PS2MEM_VU1MICRO+(i<<12);
|
|
for (i=0; i<0x00004; i++) memLUT[i + 0x1100c] = PS2MEM_VU1MEM+(i<<12);
|
|
|
|
for (i=0; i<0x00004; i++) memLUT[i + 0x50000] = PS2MEM_SCRATCH+(i<<12);
|
|
|
|
// map to other modes
|
|
memcpy(memLUT+0x80000, memLUT, 0x20000*sizeof(uptr));
|
|
memcpy(memLUT+0xa0000, memLUT, 0x20000*sizeof(uptr));
|
|
|
|
if (psxInit() == -1)
|
|
goto eCleanupAndExit;
|
|
|
|
eCleanupAndExit:
|
|
memShutdown();
|
|
return -1;
|
|
}
|
|
|
|
void memShutdown()
|
|
{
|
|
VIRTUAL_FREE(PS2MEM_BASE, 0x40000000);
|
|
VIRTUAL_FREE(PS2MEM_PSX, 0x00800000);
|
|
|
|
PHYSICAL_FREE(PS2MEM_BASE, 0x02000000, s_psM);
|
|
VIRTUAL_FREE(PS2MEM_ROM, 0x00400000);
|
|
VIRTUAL_FREE(PS2MEM_ROM1, 0x00080000);
|
|
VIRTUAL_FREE(PS2MEM_ROM2, 0x00080000);
|
|
VIRTUAL_FREE(PS2MEM_EROM, 0x001C0000);
|
|
PHYSICAL_FREE(PS2MEM_SCRATCH, 0x00010000, s_psS);
|
|
PHYSICAL_FREE(PS2MEM_HW, 0x00010000, s_psHw);
|
|
PHYSICAL_FREE(PS2MEM_PSX, 0x00800000, s_psxM);
|
|
PHYSICAL_FREE(PS2MEM_VU0MICRO, 0x00010000, s_psVuMem);
|
|
|
|
VIRTUAL_FREE(PS2MEM_VU0MICRO, 0x00010000); // allocate for all VUs
|
|
|
|
VIRTUAL_FREE(PS2MEM_PSXHW, 0x00010000);
|
|
VIRTUAL_FREE(PS2MEM_PSXHW4, 0x00010000);
|
|
VIRTUAL_FREE(PS2MEM_GS, 0x00010000);
|
|
VIRTUAL_FREE(PS2MEM_DEV9, 0x00010000);
|
|
VIRTUAL_FREE(PS2MEM_SPU2, 0x00010000);
|
|
VIRTUAL_FREE(PS2MEM_SPU2_, 0x00010000);
|
|
|
|
VIRTUAL_FREE(PS2MEM_B80, 0x00010000);
|
|
VIRTUAL_FREE(PS2MEM_BA0, 0x00010000);
|
|
|
|
VirtualFree(PS2MEM_VU0MICRO, 0, MEM_RELEASE);
|
|
|
|
_aligned_free(memLUT); memLUT = NULL;
|
|
|
|
// reserve mem
|
|
if( mmap(PS2MEM_BASE, 0x40000000, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, 0, 0) != PS2MEM_BASE ) {
|
|
SysPrintf("failed to reserve mem\n");
|
|
}
|
|
}
|
|
|
|
#endif // _WIN32
|
|
|
|
// Some games read/write between different addrs but same physical memory
|
|
// this causes major slowdowns because it goes into the exception handler, so use this (zerofrog)
|
|
u32 VM_RETRANSLATE(u32 mem)
|
|
{
|
|
u8* p, *pbase;
|
|
if( (mem&0xffff0000) == 0x50000000 ) // reserved scratch pad mem
|
|
return PS2MEM_BASE_+mem;
|
|
|
|
p = (u8*)dmaGetAddrBase(mem), *pbase;
|
|
|
|
#ifdef _WIN32
|
|
// do manual LUT since IPU/SPR seems to use addrs 0x3000xxxx quite often
|
|
if( memLUT[ (p-PS2MEM_BASE)>>12 ].aPFNs == NULL ) {
|
|
return PS2MEM_BASE_+mem;
|
|
}
|
|
|
|
pbase = (u8*)memLUT[ (p-PS2MEM_BASE)>>12 ].aVFNs[0];
|
|
if( pbase != NULL )
|
|
p = pbase + ((u32)p&0xfff);
|
|
#endif
|
|
|
|
return (u32)p;
|
|
}
|
|
|
|
void memSetPageAddr(u32 vaddr, u32 paddr) {
|
|
|
|
PSMEMORYMAP* pmap;
|
|
|
|
if( vaddr == paddr )
|
|
return;
|
|
|
|
if( (vaddr>>28) != 1 && (vaddr>>28) != 9 && (vaddr>>28) != 11 ) {
|
|
#ifdef _WIN32
|
|
pmap = &memLUT[vaddr >> 12];
|
|
|
|
if( pmap->aPFNs != NULL && (pmap->aPFNs != memLUT[paddr>>12].aPFNs ||
|
|
pmap->aVFNs[0] != TRANSFORM_ADDR(vaddr)+(u32)PS2MEM_BASE) ) {
|
|
|
|
SysMapUserPhysicalPages((void*)pmap->aVFNs[0], 1, NULL, 0);
|
|
pmap->aVFNs[0] = 0;
|
|
}
|
|
|
|
*pmap = memLUT[paddr >> 12];
|
|
#else
|
|
memLUT[vaddr>>12] = memLUT[paddr>>12];
|
|
#endif
|
|
}
|
|
}
|
|
|
|
void memClearPageAddr(u32 vaddr) {
|
|
// SysPrintf("memClearPageAddr: %8.8x\n", vaddr);
|
|
|
|
if ((vaddr & 0xffffc000) == 0x70000000) return;
|
|
|
|
#ifdef _WIN32
|
|
// if( vaddr >= 0x20000000 && vaddr < 0x80000000 ) {
|
|
// Cpu->Clear(vaddr&~0xfff, 0x1000/4);
|
|
// if( memLUT[vaddr>>12].aVFNs != NULL ) {
|
|
// SysMapUserPhysicalPages((void*)memLUT[vaddr>>12].aVFNs[0], 1, NULL, 0 );
|
|
// memLUT[vaddr>>12].aVFNs = NULL;
|
|
// memLUT[vaddr>>12].aPFNs = NULL;
|
|
// }
|
|
// }
|
|
#else
|
|
if( memLUT[vaddr>>12] != NULL ) {
|
|
SysVirtualFree(memLUT[vaddr>>12], 0x1000);
|
|
memLUT[vaddr>>12] = 0;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
u8 recMemRead8()
|
|
{
|
|
register u32 mem;
|
|
__asm mov mem, ecx // already anded with ~0xa0000000
|
|
|
|
switch( (mem&~0xffff) ) {
|
|
case 0x1f400000: return psxHw4Read8(mem);
|
|
case 0x10000000: return hwRead8(mem);
|
|
case 0x1f800000: return psxHwRead8(mem);
|
|
case 0x12000000: return *(PS2MEM_BASE+(mem&~0xc00));
|
|
case 0x14000000:
|
|
{
|
|
u32 ret = DEV9read8(mem & ~0x04000000);
|
|
SysPrintf("DEV9 read8 %8.8lx: %2.2lx\n", mem & ~0x04000000, ret);
|
|
return ret;
|
|
}
|
|
|
|
default:
|
|
return *(u8*)(PS2MEM_BASE+mem);
|
|
}
|
|
|
|
#ifdef MEM_LOG
|
|
MEM_LOG("Unknown Memory read32 from address %8.8x\n", mem);
|
|
#endif
|
|
cpuTlbMissR(mem, cpuRegs.branch);
|
|
|
|
return 0;
|
|
}
|
|
|
|
void _eeReadConstMem8(int mmreg, u32 mem, int sign)
|
|
{
|
|
assert( !IS_XMMREG(mmreg));
|
|
|
|
if( IS_MMXREG(mmreg) ) {
|
|
SetMMXstate();
|
|
MOVDMtoMMX(mmreg&0xf, mem-3);
|
|
assert(0);
|
|
}
|
|
else {
|
|
if( sign ) MOVSX32M8toR(mmreg, mem);
|
|
else MOVZX32M8toR(mmreg, mem);
|
|
}
|
|
}
|
|
|
|
void _eeReadConstMem16(int mmreg, u32 mem, int sign)
|
|
{
|
|
assert( !IS_XMMREG(mmreg));
|
|
|
|
if( IS_MMXREG(mmreg) ) {
|
|
SetMMXstate();
|
|
MOVDMtoMMX(mmreg&0xf, mem-2);
|
|
assert(0);
|
|
}
|
|
else {
|
|
if( sign ) MOVSX32M16toR(mmreg, mem);
|
|
else MOVZX32M16toR(mmreg, mem);
|
|
}
|
|
}
|
|
|
|
void _eeReadConstMem32(int mmreg, u32 mem)
|
|
{
|
|
if( IS_XMMREG(mmreg) ) SSEX_MOVD_M32_to_XMM(mmreg&0xf, mem);
|
|
else if( IS_MMXREG(mmreg) ) {
|
|
SetMMXstate();
|
|
MOVDMtoMMX(mmreg&0xf, mem);
|
|
}
|
|
else MOV32MtoR(mmreg, mem);
|
|
}
|
|
|
|
void _eeReadConstMem128(int mmreg, u32 mem)
|
|
{
|
|
if( IS_MMXREG(mmreg) ) {
|
|
SetMMXstate();
|
|
MOVQMtoR((mmreg>>4)&0xf, mem+8);
|
|
MOVQMtoR(mmreg&0xf, mem);
|
|
}
|
|
else SSEX_MOVDQA_M128_to_XMM( mmreg&0xf, mem);
|
|
}
|
|
|
|
void _eeWriteConstMem8(u32 mem, int mmreg)
|
|
{
|
|
assert( !IS_XMMREG(mmreg) && !IS_MMXREG(mmreg) );
|
|
if( IS_EECONSTREG(mmreg) ) MOV8ItoM(mem, g_cpuConstRegs[((mmreg>>16)&0x1f)].UL[0]);
|
|
else if( IS_PSXCONSTREG(mmreg) ) MOV8ItoM(mem, g_psxConstRegs[((mmreg>>16)&0x1f)]);
|
|
else MOV8RtoM(mem, mmreg);
|
|
}
|
|
|
|
void _eeWriteConstMem16(u32 mem, int mmreg)
|
|
{
|
|
assert( !IS_XMMREG(mmreg) && !IS_MMXREG(mmreg) );
|
|
if( IS_EECONSTREG(mmreg) ) MOV16ItoM(mem, g_cpuConstRegs[((mmreg>>16)&0x1f)].UL[0]);
|
|
else if( IS_PSXCONSTREG(mmreg) ) MOV16ItoM(mem, g_psxConstRegs[((mmreg>>16)&0x1f)]);
|
|
else MOV16RtoM(mem, mmreg);
|
|
}
|
|
|
|
void _eeWriteConstMem16OP(u32 mem, int mmreg, int op)
|
|
{
|
|
assert( !IS_XMMREG(mmreg) && !IS_MMXREG(mmreg) );
|
|
switch(op) {
|
|
case 0: // and
|
|
if( IS_EECONSTREG(mmreg) ) AND16ItoM(mem, g_cpuConstRegs[((mmreg>>16)&0x1f)].UL[0]);
|
|
else if( IS_PSXCONSTREG(mmreg) ) AND16ItoM(mem, g_psxConstRegs[((mmreg>>16)&0x1f)]);
|
|
else AND16RtoM(mem, mmreg);
|
|
break;
|
|
case 1: // and
|
|
if( IS_EECONSTREG(mmreg) ) OR16ItoM(mem, g_cpuConstRegs[((mmreg>>16)&0x1f)].UL[0]);
|
|
else if( IS_PSXCONSTREG(mmreg) ) OR16ItoM(mem, g_psxConstRegs[((mmreg>>16)&0x1f)]);
|
|
else OR16RtoM(mem, mmreg);
|
|
break;
|
|
default: assert(0);
|
|
}
|
|
}
|
|
|
|
void _eeWriteConstMem32(u32 mem, int mmreg)
|
|
{
|
|
if( IS_XMMREG(mmreg) ) SSE2_MOVD_XMM_to_M32(mem, mmreg&0xf);
|
|
else if( IS_MMXREG(mmreg) ) {
|
|
SetMMXstate();
|
|
MOVDMMXtoM(mem, mmreg&0xf);
|
|
}
|
|
else if( IS_EECONSTREG(mmreg) ) MOV32ItoM(mem, g_cpuConstRegs[((mmreg>>16)&0x1f)].UL[0]);
|
|
else if( IS_PSXCONSTREG(mmreg) ) MOV32ItoM(mem, g_psxConstRegs[((mmreg>>16)&0x1f)]);
|
|
else MOV32RtoM(mem, mmreg);
|
|
}
|
|
|
|
void _eeWriteConstMem32OP(u32 mem, int mmreg, int op)
|
|
{
|
|
switch(op) {
|
|
case 0: // and
|
|
if( IS_XMMREG(mmreg) ) {
|
|
_deleteEEreg((mmreg>>16)&0x1f, 1);
|
|
SSE2_PAND_M128_to_XMM(mmreg&0xf, mem);
|
|
SSE2_MOVD_XMM_to_M32(mem, mmreg&0xf);
|
|
}
|
|
else if( IS_MMXREG(mmreg) ) {
|
|
_deleteEEreg((mmreg>>16)&0x1f, 1);
|
|
SetMMXstate();
|
|
PANDMtoR(mmreg&0xf, mem);
|
|
MOVDMMXtoM(mem, mmreg&0xf);
|
|
}
|
|
else if( IS_EECONSTREG(mmreg) ) {
|
|
AND32ItoM(mem, g_cpuConstRegs[((mmreg>>16)&0x1f)].UL[0]);
|
|
}
|
|
else if( IS_PSXCONSTREG(mmreg) ) {
|
|
AND32ItoM(mem, g_psxConstRegs[((mmreg>>16)&0x1f)]);
|
|
}
|
|
else {
|
|
AND32RtoM(mem, mmreg&0xf);
|
|
}
|
|
break;
|
|
|
|
case 1: // or
|
|
if( IS_XMMREG(mmreg) ) {
|
|
_deleteEEreg((mmreg>>16)&0x1f, 1);
|
|
SSE2_POR_M128_to_XMM(mmreg&0xf, mem);
|
|
SSE2_MOVD_XMM_to_M32(mem, mmreg&0xf);
|
|
}
|
|
else if( IS_MMXREG(mmreg) ) {
|
|
_deleteEEreg((mmreg>>16)&0x1f, 1);
|
|
SetMMXstate();
|
|
PORMtoR(mmreg&0xf, mem);
|
|
MOVDMMXtoM(mem, mmreg&0xf);
|
|
}
|
|
else if( IS_EECONSTREG(mmreg) ) {
|
|
OR32ItoM(mem, g_cpuConstRegs[((mmreg>>16)&0x1f)].UL[0]);
|
|
}
|
|
else if( IS_PSXCONSTREG(mmreg) ) {
|
|
OR32ItoM(mem, g_psxConstRegs[((mmreg>>16)&0x1f)]);
|
|
}
|
|
else {
|
|
OR32RtoM(mem, mmreg&0xf);
|
|
}
|
|
break;
|
|
|
|
case 2: // not and
|
|
if( mmreg & MEM_XMMTAG ) {
|
|
_deleteEEreg(mmreg>>16, 1);
|
|
SSEX_PANDN_M128_to_XMM(mmreg&0xf, mem);
|
|
SSEX_MOVD_XMM_to_M32(mem, mmreg&0xf);
|
|
}
|
|
else if( mmreg & MEM_MMXTAG ) {
|
|
_deleteEEreg(mmreg>>16, 1);
|
|
PANDNMtoR(mmreg&0xf, mem);
|
|
MOVDMMXtoM(mem, mmreg&0xf);
|
|
}
|
|
else if( IS_EECONSTREG(mmreg) ) {
|
|
AND32ItoM(mem, ~g_cpuConstRegs[((mmreg>>16)&0x1f)].UL[0]);
|
|
}
|
|
else if( IS_PSXCONSTREG(mmreg) ) {
|
|
AND32ItoM(mem, ~g_psxConstRegs[((mmreg>>16)&0x1f)]);
|
|
}
|
|
else {
|
|
NOT32R(mmreg&0xf);
|
|
AND32RtoM(mem, mmreg&0xf);
|
|
}
|
|
break;
|
|
|
|
default: assert(0);
|
|
}
|
|
}
|
|
|
|
void _eeWriteConstMem64(u32 mem, int mmreg)
|
|
{
|
|
if( IS_XMMREG(mmreg) ) SSE_MOVLPS_XMM_to_M64(mem, mmreg&0xf);
|
|
else if( IS_MMXREG(mmreg) ) {
|
|
SetMMXstate();
|
|
MOVQRtoM(mem, mmreg&0xf);
|
|
}
|
|
else if( IS_EECONSTREG(mmreg) ) {
|
|
MOV32ItoM(mem, g_cpuConstRegs[((mmreg>>16)&0x1f)].UL[0]);
|
|
MOV32ItoM(mem+4, g_cpuConstRegs[((mmreg>>16)&0x1f)].UL[1]);
|
|
}
|
|
else assert(0);
|
|
}
|
|
|
|
void _eeWriteConstMem128(u32 mem, int mmreg)
|
|
{
|
|
assert( cpucaps.hasStreamingSIMDExtensions );
|
|
if( IS_MMXREG(mmreg) ) {
|
|
SetMMXstate();
|
|
MOVQRtoM(mem, mmreg&0xf);
|
|
MOVQRtoM(mem+8, (mmreg>>4)&0xf);
|
|
}
|
|
else if( IS_EECONSTREG(mmreg) ) {
|
|
SetMMXstate();
|
|
MOV32ItoM(mem, g_cpuConstRegs[((mmreg>>16)&0x1f)].UL[0]);
|
|
MOV32ItoM(mem+4, g_cpuConstRegs[((mmreg>>16)&0x1f)].UL[1]);
|
|
MOVQRtoM(mem+8, mmreg&0xf);
|
|
}
|
|
else SSEX_MOVDQA_XMM_to_M128(mem, mmreg&0xf);
|
|
}
|
|
|
|
void _eeMoveMMREGtoR(x86IntRegType to, int mmreg)
|
|
{
|
|
if( IS_XMMREG(mmreg) ) SSE2_MOVD_XMM_to_R(to, mmreg&0xf);
|
|
else if( IS_MMXREG(mmreg) ) {
|
|
SetMMXstate();
|
|
MOVD32MMXtoR(to, mmreg&0xf);
|
|
}
|
|
else if( IS_EECONSTREG(mmreg) ) MOV32ItoR(to, g_cpuConstRegs[((mmreg>>16)&0x1f)].UL[0]);
|
|
else if( IS_PSXCONSTREG(mmreg) ) MOV32ItoR(to, g_psxConstRegs[((mmreg>>16)&0x1f)]);
|
|
else if( mmreg != to ) MOV32RtoR(to, mmreg);
|
|
}
|
|
|
|
int recMemConstRead8(u32 x86reg, u32 mem, u32 sign)
|
|
{
|
|
mem = TRANSFORM_ADDR(mem);
|
|
|
|
switch( mem>>16 ) {
|
|
case 0x1f40: return psxHw4ConstRead8(x86reg, mem, sign);
|
|
case 0x1000: return hwConstRead8(x86reg, mem, sign);
|
|
case 0x1f80: return psxHwConstRead8(x86reg, mem, sign);
|
|
case 0x1200: return gsConstRead8(x86reg, mem, sign);
|
|
case 0x1400:
|
|
{
|
|
iFlushCall(0);
|
|
PUSH32I(mem & ~0x04000000);
|
|
CALLFunc((u32)DEV9read8);
|
|
if( sign ) MOVSX32R8toR(EAX, EAX);
|
|
else MOVZX32R8toR(EAX, EAX);
|
|
return 1;
|
|
}
|
|
|
|
default:
|
|
_eeReadConstMem8(x86reg, VM_RETRANSLATE(mem), sign);
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
u16 recMemRead16() {
|
|
|
|
register u32 mem;
|
|
__asm mov mem, ecx // already anded with ~0xa0000000
|
|
|
|
switch( mem>>16 ) {
|
|
case 0x1000: return hwRead16(mem);
|
|
case 0x1f80: return psxHwRead16(mem);
|
|
case 0x1200: return *(u16*)(PS2MEM_BASE+(mem&~0xc00));
|
|
case 0x1800: return 0;
|
|
case 0x1a00: return ba0R16(mem);
|
|
case 0x1f90:
|
|
case 0x1f00:
|
|
return SPU2read(mem);
|
|
case 0x1400:
|
|
{
|
|
u32 ret = DEV9read16(mem & ~0x04000000);
|
|
SysPrintf("DEV9 read8 %8.8lx: %2.2lx\n", mem & ~0x04000000, ret);
|
|
return ret;
|
|
}
|
|
|
|
default:
|
|
return *(u16*)(PS2MEM_BASE+mem);
|
|
}
|
|
|
|
#ifdef MEM_LOG
|
|
MEM_LOG("Unknown Memory read16 from address %8.8x\n", mem);
|
|
#endif
|
|
cpuTlbMissR(mem, cpuRegs.branch);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int recMemConstRead16(u32 x86reg, u32 mem, u32 sign)
|
|
{
|
|
mem = TRANSFORM_ADDR(mem);
|
|
|
|
switch( mem>>16 ) {
|
|
case 0x1000: return hwConstRead16(x86reg, mem, sign);
|
|
case 0x1f80: return psxHwConstRead16(x86reg, mem, sign);
|
|
case 0x1200: return gsConstRead16(x86reg, mem, sign);
|
|
case 0x1800:
|
|
if( IS_MMXREG(x86reg) ) PXORRtoR(x86reg&0xf, x86reg&0xf);
|
|
else XOR32RtoR(x86reg, x86reg);
|
|
return 0;
|
|
case 0x1a00:
|
|
iFlushCall(0);
|
|
PUSH32I(mem);
|
|
CALLFunc((u32)ba0R16);
|
|
ADD32ItoR(ESP, 4);
|
|
if( sign ) MOVSX32R16toR(EAX, EAX);
|
|
else MOVZX32R16toR(EAX, EAX);
|
|
return 1;
|
|
|
|
case 0x1f90:
|
|
case 0x1f00:
|
|
iFlushCall(0);
|
|
PUSH32I(mem);
|
|
CALLFunc((u32)SPU2read);
|
|
if( sign ) MOVSX32R16toR(EAX, EAX);
|
|
else MOVZX32R16toR(EAX, EAX);
|
|
return 1;
|
|
|
|
case 0x1400:
|
|
iFlushCall(0);
|
|
PUSH32I(mem & ~0x04000000);
|
|
CALLFunc((u32)DEV9read16);
|
|
if( sign ) MOVSX32R16toR(EAX, EAX);
|
|
else MOVZX32R16toR(EAX, EAX);
|
|
return 1;
|
|
|
|
default:
|
|
_eeReadConstMem16(x86reg, VM_RETRANSLATE(mem), sign);
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
__declspec(naked)
|
|
u32 recMemRead32() {
|
|
// ecx is address - already anded with ~0xa0000000
|
|
__asm {
|
|
|
|
mov edx, ecx
|
|
shr edx, 16
|
|
cmp dx, 0x1000
|
|
je hwread
|
|
cmp dx, 0x1f80
|
|
je psxhwread
|
|
cmp dx, 0x1200
|
|
je gsread
|
|
cmp dx, 0x1400
|
|
je devread
|
|
|
|
// default read
|
|
mov eax, dword ptr [ecx+PS2MEM_BASE_]
|
|
ret
|
|
}
|
|
|
|
hwread:
|
|
{
|
|
__asm {
|
|
cmp ecx, 0x10002000
|
|
jb counterread
|
|
|
|
cmp ecx, 0x1000f260
|
|
je hwsifpresetread
|
|
cmp ecx, 0x1000f240
|
|
je hwsifsyncread
|
|
cmp ecx, 0x1000f440
|
|
je hwmch_drd
|
|
cmp ecx, 0x1000f430
|
|
je hwmch_ricm
|
|
|
|
cmp ecx, 0x10003000
|
|
jb hwdefread2
|
|
mov eax, dword ptr [ecx+PS2MEM_BASE_]
|
|
ret
|
|
|
|
// ipu
|
|
hwdefread2:
|
|
push ecx
|
|
call ipuRead32
|
|
add esp, 4
|
|
ret
|
|
|
|
// sif
|
|
hwsifpresetread:
|
|
xor eax, eax
|
|
ret
|
|
hwsifsyncread:
|
|
mov eax, 0x1000F240
|
|
mov eax, dword ptr [eax+PS2MEM_BASE_]
|
|
or eax, 0xF0000102
|
|
ret
|
|
}
|
|
|
|
counterread:
|
|
{
|
|
static u32 mem, index;
|
|
|
|
// counters
|
|
__asm mov mem, ecx
|
|
index = (mem>>11)&3;
|
|
|
|
if( (mem&0x7ff) == 0 ) {
|
|
__asm {
|
|
push index
|
|
call rcntRcount
|
|
add esp, 4
|
|
and eax, 0xffff
|
|
ret
|
|
}
|
|
}
|
|
|
|
index = (u32)&counters[index] + ((mem>>2)&0xc);
|
|
|
|
__asm {
|
|
mov eax, index
|
|
mov eax, dword ptr [eax]
|
|
movzx eax, ax
|
|
ret
|
|
}
|
|
}
|
|
|
|
hwmch_drd: // MCH_DRD
|
|
__asm {
|
|
mov eax, dword ptr [ecx+PS2MEM_BASE_-0x10]
|
|
shr eax, 6
|
|
test eax, 0xf
|
|
jz mch_drd_2
|
|
hwmch_ricm:
|
|
xor eax, eax
|
|
ret
|
|
|
|
mch_drd_2:
|
|
shr eax, 10
|
|
and eax, 0xfff
|
|
cmp eax, 0x21 // INIT
|
|
je mch_drd_init
|
|
cmp eax, 0x23 // CNFGA
|
|
je mch_drd_cnfga
|
|
cmp eax, 0x24 // CNFGB
|
|
je mch_drd_cnfgb
|
|
cmp eax, 0x40 // DEVID
|
|
je mch_drd_devid
|
|
xor eax, eax
|
|
ret
|
|
|
|
mch_drd_init:
|
|
mov edx, rdram_devices
|
|
xor eax, eax
|
|
cmp edx, rdram_sdevid
|
|
setg al
|
|
add rdram_sdevid, eax
|
|
imul eax, 0x1f
|
|
ret
|
|
|
|
mch_drd_cnfga:
|
|
mov eax, 0x0D0D
|
|
ret
|
|
|
|
mch_drd_cnfgb:
|
|
mov eax, 0x0090
|
|
ret
|
|
|
|
mch_drd_devid:
|
|
mov eax, dword ptr [ecx+PS2MEM_BASE_-0x10]
|
|
and eax, 0x1f
|
|
ret
|
|
}
|
|
}
|
|
|
|
psxhwread:
|
|
__asm {
|
|
push ecx
|
|
call psxHwRead32
|
|
add esp, 4
|
|
ret
|
|
}
|
|
|
|
gsread:
|
|
__asm {
|
|
and ecx, 0xfffff3ff
|
|
mov eax, dword ptr [ecx+PS2MEM_BASE_]
|
|
ret
|
|
}
|
|
|
|
devread:
|
|
__asm {
|
|
and ecx, 0xfbffffff
|
|
push ecx
|
|
call DEV9read32
|
|
add esp, 4
|
|
ret
|
|
}
|
|
}
|
|
|
|
int recMemConstRead32(u32 x86reg, u32 mem)
|
|
{
|
|
mem = TRANSFORM_ADDR(mem);
|
|
|
|
switch( (mem&~0xffff) ) {
|
|
case 0x10000000: return hwConstRead32(x86reg, mem);
|
|
case 0x1f800000: return psxHwConstRead32(x86reg, mem);
|
|
case 0x12000000: return gsConstRead32(x86reg, mem);
|
|
case 0x14000000:
|
|
iFlushCall(0);
|
|
PUSH32I(mem & ~0x04000000);
|
|
CALLFunc((u32)DEV9read32);
|
|
return 1;
|
|
|
|
default:
|
|
_eeReadConstMem32(x86reg, VM_RETRANSLATE(mem));
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
void recMemRead64(u64 *out)
|
|
{
|
|
register u32 mem;
|
|
__asm mov mem, ecx // already anded with ~0xa0000000
|
|
|
|
switch( (mem&0xffff0000) ) {
|
|
case 0x10000000: *out = hwRead64(mem); return;
|
|
case 0x11000000: *out = *(u64*)(PS2MEM_BASE+mem); return;
|
|
case 0x12000000: *out = *(u64*)(PS2MEM_BASE+(mem&~0xc00)); return;
|
|
|
|
default:
|
|
//assert(0);
|
|
*out = *(u64*)(PS2MEM_BASE+mem);
|
|
return;
|
|
}
|
|
|
|
#ifdef PCSX2_DEVBUILD
|
|
MEM_LOG("Unknown Memory read32 from address %8.8x (Status=%8.8x)\n", mem, cpuRegs.CP0.n.Status);
|
|
#endif
|
|
cpuTlbMissR(mem, cpuRegs.branch);
|
|
}
|
|
|
|
void recMemConstRead64(u32 mem, int mmreg)
|
|
{
|
|
mem = TRANSFORM_ADDR(mem);
|
|
|
|
switch( (mem&0xffff0000) ) {
|
|
case 0x10000000: hwConstRead64(mem, mmreg); return;
|
|
case 0x12000000: gsConstRead64(mem, mmreg); return;
|
|
default:
|
|
if( IS_XMMREG(mmreg) ) SSE_MOVLPS_M64_to_XMM(mmreg&0xff, VM_RETRANSLATE(mem));
|
|
else {
|
|
MOVQMtoR(mmreg, VM_RETRANSLATE(mem));
|
|
SetMMXstate();
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
|
|
void recMemRead128(u64 *out) {
|
|
|
|
register u32 mem;
|
|
__asm mov mem, ecx // already anded with ~0xa0000000
|
|
|
|
switch( (mem&0xffff0000) ) {
|
|
case 0x10000000:
|
|
hwRead128(mem, out);
|
|
return;
|
|
case 0x12000000:
|
|
out[0] = *(u64*)(PS2MEM_BASE+(mem&~0xc00));
|
|
out[1] = *(u64*)(PS2MEM_BASE+(mem&~0xc00)+8);
|
|
return;
|
|
case 0x11000000:
|
|
out[0] = *(u64*)(PS2MEM_BASE+mem);
|
|
out[1] = *(u64*)(PS2MEM_BASE+mem+8);
|
|
return;
|
|
default:
|
|
//assert(0);
|
|
out[0] = *(u64*)(PS2MEM_BASE+mem);
|
|
out[1] = *(u64*)(PS2MEM_BASE+mem+8);
|
|
return;
|
|
}
|
|
|
|
#ifdef PCSX2_DEVBUILD
|
|
MEM_LOG("Unknown Memory read32 from address %8.8x (Status=%8.8x)\n", mem, cpuRegs.CP0.n.Status);
|
|
#endif
|
|
cpuTlbMissR(mem, cpuRegs.branch);
|
|
}
|
|
|
|
void recMemConstRead128(u32 mem, int xmmreg)
|
|
{
|
|
mem = TRANSFORM_ADDR(mem);
|
|
|
|
switch( (mem&0xffff0000) ) {
|
|
case 0x10000000: hwConstRead128(mem, xmmreg); return;
|
|
case 0x12000000: gsConstRead128(mem, xmmreg); return;
|
|
default:
|
|
_eeReadConstMem128(xmmreg, VM_RETRANSLATE(mem));
|
|
return;
|
|
}
|
|
}
|
|
|
|
void errwrite()
|
|
{
|
|
int i, bit, tempeax;
|
|
__asm mov i, ecx
|
|
__asm mov tempeax, eax
|
|
__asm mov bit, edx
|
|
SysPrintf("Error write%d at %x\n", bit, i);
|
|
assert(0);
|
|
__asm mov eax, tempeax
|
|
__asm mov ecx, i
|
|
}
|
|
|
|
void recMemWrite8()
|
|
{
|
|
register u32 mem;
|
|
register u8 value;
|
|
__asm mov mem, ecx // already anded with ~0xa0000000
|
|
__asm mov value, al
|
|
|
|
switch( mem>>16 ) {
|
|
case 0x1f40: psxHw4Write8(mem, value); return;
|
|
case 0x1000: hwWrite8(mem, value); return;
|
|
case 0x1f80: psxHwWrite8(mem, value); return;
|
|
case 0x1200: gsWrite8(mem, value); return;
|
|
case 0x1400:
|
|
DEV9write8(mem & ~0x04000000, value);
|
|
SysPrintf("DEV9 write8 %8.8lx: %2.2lx\n", mem & ~0x04000000, value);
|
|
return;
|
|
|
|
#ifdef _DEBUG
|
|
case 0x1100: assert(0);
|
|
#endif
|
|
default:
|
|
// vus, bad addrs, etc
|
|
*(u8*)(PS2MEM_BASE+mem) = value;
|
|
return;
|
|
}
|
|
|
|
#ifdef MEM_LOG
|
|
MEM_LOG("Unknown Memory write8 to address %x with data %2.2x\n", mem, value);
|
|
#endif
|
|
cpuTlbMissW(mem, cpuRegs.branch);
|
|
}
|
|
|
|
int recMemConstWrite8(u32 mem, int mmreg)
|
|
{
|
|
mem = TRANSFORM_ADDR(mem);
|
|
|
|
switch( mem>>16 ) {
|
|
case 0x1f40: psxHw4ConstWrite8(mem, mmreg); return 0;
|
|
case 0x1000: hwConstWrite8(mem, mmreg); return 0;
|
|
case 0x1f80: psxHwConstWrite8(mem, mmreg); return 0;
|
|
case 0x1200: gsConstWrite8(mem, mmreg); return 0;
|
|
case 0x1400:
|
|
_recPushReg(mmreg);
|
|
iFlushCall(0);
|
|
PUSH32I(mem & ~0x04000000);
|
|
CALLFunc((u32)DEV9write8);
|
|
return 0;
|
|
|
|
case 0x1100:
|
|
_eeWriteConstMem8(PS2MEM_BASE_+mem, mmreg);
|
|
|
|
if( mem < 0x11004000 ) {
|
|
PUSH32I(1);
|
|
PUSH32I(mem&0x3ff8);
|
|
CALLFunc((u32)Cpu->ClearVU0);
|
|
ADD32ItoR(ESP, 8);
|
|
}
|
|
else if( mem >= 0x11008000 && mem < 0x1100c000 ) {
|
|
PUSH32I(1);
|
|
PUSH32I(mem&0x3ff8);
|
|
CALLFunc((u32)Cpu->ClearVU1);
|
|
ADD32ItoR(ESP, 8);
|
|
}
|
|
return 0;
|
|
|
|
default:
|
|
_eeWriteConstMem8(PS2MEM_BASE_+mem, mmreg);
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
void recMemWrite16() {
|
|
|
|
register u32 mem;
|
|
register u16 value;
|
|
__asm mov mem, ecx // already anded with ~0xa0000000
|
|
__asm mov value, ax
|
|
|
|
switch( mem>>16 ) {
|
|
case 0x1000: hwWrite16(mem, value); return;
|
|
case 0x1600:
|
|
//HACK: DEV9 VM crash fix
|
|
return;
|
|
case 0x1f80: psxHwWrite16(mem, value); return;
|
|
case 0x1200: gsWrite16(mem, value); return;
|
|
case 0x1f90:
|
|
case 0x1f00: SPU2write(mem, value); return;
|
|
case 0x1400:
|
|
DEV9write16(mem & ~0x04000000, value);
|
|
SysPrintf("DEV9 write16 %8.8lx: %4.4lx\n", mem & ~0x04000000, value);
|
|
return;
|
|
|
|
#ifdef _DEBUG
|
|
case 0x1100: assert(0);
|
|
#endif
|
|
default:
|
|
// vus, bad addrs, etc
|
|
*(u16*)(PS2MEM_BASE+mem) = value;
|
|
return;
|
|
}
|
|
|
|
#ifdef MEM_LOG
|
|
MEM_LOG("Unknown Memory write16 to address %x with data %4.4x\n", mem, value);
|
|
#endif
|
|
cpuTlbMissW(mem, cpuRegs.branch);
|
|
}
|
|
|
|
int recMemConstWrite16(u32 mem, int mmreg)
|
|
{
|
|
mem = TRANSFORM_ADDR(mem);
|
|
|
|
switch( mem>>16 ) {
|
|
case 0x1000: hwConstWrite16(mem, mmreg); return 0;
|
|
case 0x1600:
|
|
//HACK: DEV9 VM crash fix
|
|
return 0;
|
|
case 0x1f80: psxHwConstWrite16(mem, mmreg); return 0;
|
|
case 0x1200: gsConstWrite16(mem, mmreg); return 0;
|
|
case 0x1f90:
|
|
case 0x1f00:
|
|
_recPushReg(mmreg);
|
|
iFlushCall(0);
|
|
PUSH32I(mem);
|
|
CALLFunc((u32)SPU2write);
|
|
return 0;
|
|
case 0x1400:
|
|
_recPushReg(mmreg);
|
|
iFlushCall(0);
|
|
PUSH32I(mem & ~0x04000000);
|
|
CALLFunc((u32)DEV9write16);
|
|
return 0;
|
|
|
|
case 0x1100:
|
|
_eeWriteConstMem16(PS2MEM_BASE_+mem, mmreg);
|
|
|
|
if( mem < 0x11004000 ) {
|
|
PUSH32I(1);
|
|
PUSH32I(mem&0x3ff8);
|
|
CALLFunc((u32)Cpu->ClearVU0);
|
|
ADD32ItoR(ESP, 8);
|
|
}
|
|
else if( mem >= 0x11008000 && mem < 0x1100c000 ) {
|
|
PUSH32I(1);
|
|
PUSH32I(mem&0x3ff8);
|
|
CALLFunc((u32)Cpu->ClearVU1);
|
|
ADD32ItoR(ESP, 8);
|
|
}
|
|
return 0;
|
|
|
|
default:
|
|
_eeWriteConstMem16(PS2MEM_BASE_+mem, mmreg);
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
C_ASSERT( sizeof(BASEBLOCK) == 8 );
|
|
|
|
__declspec(naked)
|
|
void recMemWrite32()
|
|
{
|
|
// ecx is address - already anded with ~0xa0000000
|
|
__asm {
|
|
|
|
mov edx, ecx
|
|
shr edx, 16
|
|
cmp dx, 0x1000
|
|
je hwwrite
|
|
cmp dx, 0x1f80
|
|
je psxwrite
|
|
cmp dx, 0x1200
|
|
je gswrite
|
|
cmp dx, 0x1400
|
|
je devwrite
|
|
cmp dx, 0x1100
|
|
je vuwrite
|
|
}
|
|
|
|
__asm {
|
|
// default write
|
|
mov dword ptr [ecx+PS2MEM_BASE_], eax
|
|
ret
|
|
|
|
hwwrite:
|
|
push eax
|
|
push ecx
|
|
call hwWrite32
|
|
add esp, 8
|
|
ret
|
|
psxwrite:
|
|
push eax
|
|
push ecx
|
|
call psxHwWrite32
|
|
add esp, 8
|
|
ret
|
|
gswrite:
|
|
push eax
|
|
push ecx
|
|
call gsWrite32
|
|
add esp, 8
|
|
ret
|
|
devwrite:
|
|
and ecx, 0xfbffffff
|
|
push eax
|
|
push ecx
|
|
call DEV9write32
|
|
add esp, 8
|
|
ret
|
|
vuwrite:
|
|
// default write
|
|
mov dword ptr [ecx+PS2MEM_BASE_], eax
|
|
|
|
cmp ecx, 0x11004000
|
|
jge vu1write
|
|
and ecx, 0x3ff8
|
|
// clear vu0mem
|
|
mov eax, Cpu
|
|
push 1
|
|
push ecx
|
|
call [eax]Cpu.ClearVU0
|
|
add esp, 8
|
|
ret
|
|
|
|
vu1write:
|
|
cmp ecx, 0x11008000
|
|
jl vuend
|
|
cmp ecx, 0x1100c000
|
|
jge vuend
|
|
// clear vu1mem
|
|
and ecx, 0x3ff8
|
|
mov eax, Cpu
|
|
push 1
|
|
push ecx
|
|
call [eax]Cpu.ClearVU1
|
|
add esp, 8
|
|
vuend:
|
|
ret
|
|
}
|
|
}
|
|
|
|
int recMemConstWrite32(u32 mem, int mmreg)
|
|
{
|
|
mem = TRANSFORM_ADDR(mem);
|
|
|
|
switch( mem&0xffff0000 ) {
|
|
case 0x10000000: hwConstWrite32(mem, mmreg); return 0;
|
|
case 0x1f800000: psxHwConstWrite32(mem, mmreg); return 0;
|
|
case 0x12000000: gsConstWrite32(mem, mmreg); return 0;
|
|
case 0x1f900000:
|
|
case 0x1f000000:
|
|
_recPushReg(mmreg);
|
|
iFlushCall(0);
|
|
PUSH32I(mem);
|
|
CALLFunc((u32)SPU2write);
|
|
return 0;
|
|
case 0x14000000:
|
|
_recPushReg(mmreg);
|
|
iFlushCall(0);
|
|
PUSH32I(mem & ~0x04000000);
|
|
CALLFunc((u32)DEV9write32);
|
|
return 0;
|
|
|
|
case 0x1100:
|
|
_eeWriteConstMem32(PS2MEM_BASE_+mem, mmreg);
|
|
|
|
if( mem < 0x11004000 ) {
|
|
PUSH32I(1);
|
|
PUSH32I(mem&0x3ff8);
|
|
CALLFunc((u32)Cpu->ClearVU0);
|
|
ADD32ItoR(ESP, 8);
|
|
}
|
|
else if( mem >= 0x11008000 && mem < 0x1100c0000 ) {
|
|
PUSH32I(1);
|
|
PUSH32I(mem&0x3ff8);
|
|
CALLFunc((u32)Cpu->ClearVU1);
|
|
ADD32ItoR(ESP, 8);
|
|
}
|
|
return 0;
|
|
|
|
default:
|
|
_eeWriteConstMem32(PS2MEM_BASE_+mem, mmreg);
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
__declspec(naked) void recMemWrite64()
|
|
{
|
|
__asm {
|
|
mov edx, ecx
|
|
shr edx, 16
|
|
cmp dx, 0x1000
|
|
je hwwrite
|
|
cmp dx, 0x1200
|
|
je gswrite
|
|
cmp dx, 0x1100
|
|
je vuwrite
|
|
}
|
|
|
|
__asm {
|
|
// default write
|
|
mov edx, 64
|
|
call errwrite
|
|
|
|
hwwrite:
|
|
push dword ptr [eax+4]
|
|
push dword ptr [eax]
|
|
push ecx
|
|
call hwWrite64
|
|
add esp, 12
|
|
ret
|
|
|
|
gswrite:
|
|
push dword ptr [eax+4]
|
|
push dword ptr [eax]
|
|
push ecx
|
|
call gsWrite64
|
|
add esp, 12
|
|
ret
|
|
|
|
vuwrite:
|
|
mov ebx, dword ptr [eax]
|
|
mov edx, dword ptr [eax+4]
|
|
mov dword ptr [ecx+PS2MEM_BASE_], ebx
|
|
mov dword ptr [ecx+PS2MEM_BASE_+4], edx
|
|
|
|
cmp ecx, 0x11004000
|
|
jge vu1write
|
|
and ecx, 0x3ff8
|
|
// clear vu0mem
|
|
mov eax, Cpu
|
|
push 2
|
|
push ecx
|
|
call [eax]Cpu.ClearVU0
|
|
add esp, 8
|
|
ret
|
|
|
|
vu1write:
|
|
cmp ecx, 0x11008000
|
|
jl vuend
|
|
cmp ecx, 0x1100c000
|
|
jge vuend
|
|
// clear vu1mem
|
|
and ecx, 0x3ff8
|
|
mov eax, Cpu
|
|
push 2
|
|
push ecx
|
|
call [eax]Cpu.ClearVU1
|
|
add esp, 8
|
|
vuend:
|
|
ret
|
|
}
|
|
}
|
|
|
|
int recMemConstWrite64(u32 mem, int mmreg)
|
|
{
|
|
mem = TRANSFORM_ADDR(mem);
|
|
|
|
switch( (mem>>16) ) {
|
|
case 0x1000: hwConstWrite64(mem, mmreg); return 0;
|
|
case 0x1200: gsConstWrite64(mem, mmreg); return 0;
|
|
|
|
case 0x1100:
|
|
_eeWriteConstMem64(PS2MEM_BASE_+mem, mmreg);
|
|
|
|
if( mem < 0x11004000 ) {
|
|
PUSH32I(2);
|
|
PUSH32I(mem&0x3ff8);
|
|
CALLFunc((u32)Cpu->ClearVU0);
|
|
ADD32ItoR(ESP, 8);
|
|
}
|
|
else if( mem >= 0x11008000 && mem < 0x1100c000 ) {
|
|
PUSH32I(2);
|
|
PUSH32I(mem&0x3ff8);
|
|
CALLFunc((u32)Cpu->ClearVU1);
|
|
ADD32ItoR(ESP, 8);
|
|
}
|
|
return 0;
|
|
|
|
default:
|
|
_eeWriteConstMem64(PS2MEM_BASE_+mem, mmreg);
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
__declspec(naked)
|
|
void recMemWrite128()
|
|
{
|
|
__asm {
|
|
|
|
mov edx, ecx
|
|
shr edx, 16
|
|
cmp dx, 0x1000
|
|
je hwwrite
|
|
cmp dx, 0x1200
|
|
je gswrite
|
|
cmp dx, 0x1100
|
|
je vuwrite
|
|
}
|
|
|
|
__asm {
|
|
mov edx, 128
|
|
call errwrite
|
|
|
|
hwwrite:
|
|
|
|
push eax
|
|
push ecx
|
|
call hwWrite128
|
|
add esp, 8
|
|
ret
|
|
|
|
vuwrite:
|
|
mov ebx, dword ptr [eax]
|
|
mov edx, dword ptr [eax+4]
|
|
mov edi, dword ptr [eax+8]
|
|
mov eax, dword ptr [eax+12]
|
|
mov dword ptr [ecx+PS2MEM_BASE_], ebx
|
|
mov dword ptr [ecx+PS2MEM_BASE_+4], edx
|
|
mov dword ptr [ecx+PS2MEM_BASE_+8], edi
|
|
mov dword ptr [ecx+PS2MEM_BASE_+12], eax
|
|
|
|
cmp ecx, 0x11004000
|
|
jge vu1write
|
|
and ecx, 0x3ff8
|
|
// clear vu0mem
|
|
mov eax, Cpu
|
|
push 4
|
|
push ecx
|
|
call [eax]Cpu.ClearVU0
|
|
add esp, 8
|
|
ret
|
|
|
|
vu1write:
|
|
cmp ecx, 0x11008000
|
|
jl vuend
|
|
cmp ecx, 0x1100c000
|
|
jge vuend
|
|
// clear vu1mem
|
|
and ecx, 0x3ff8
|
|
mov eax, Cpu
|
|
push 4
|
|
push ecx
|
|
call [eax]Cpu.ClearVU1
|
|
add esp, 8
|
|
vuend:
|
|
|
|
// default write
|
|
//movaps xmm7, qword ptr [eax]
|
|
|
|
// removes possible exceptions and saves on remapping memory
|
|
// *might* be faster for certain games, no way to tell
|
|
// cmp ecx, 0x20000000
|
|
// jb Write128
|
|
//
|
|
// // look for better mapping
|
|
// mov edx, ecx
|
|
// shr edx, 12
|
|
// shl edx, 3
|
|
// add edx, memLUT
|
|
// mov edx, dword ptr [edx + 4]
|
|
// cmp edx, 0
|
|
// je Write128
|
|
// mov edx, dword ptr [edx]
|
|
// cmp edx, 0
|
|
// je Write128
|
|
// and ecx, 0xfff
|
|
// movaps qword ptr [ecx+edx], xmm7
|
|
// jmp CheckOverwrite
|
|
//Write128:
|
|
//movaps qword ptr [ecx+PS2MEM_BASE_], xmm7
|
|
ret
|
|
|
|
gswrite:
|
|
sub esp, 8
|
|
movlps xmm7, qword ptr [eax]
|
|
movlps qword ptr [esp], xmm7
|
|
push ecx
|
|
call gsWrite64
|
|
|
|
// call again for upper 8 bytes
|
|
movlps xmm7, qword ptr [eax+8]
|
|
movlps qword ptr [esp+4], xmm7
|
|
add [esp], 8
|
|
call gsWrite64
|
|
add esp, 12
|
|
ret
|
|
}
|
|
}
|
|
|
|
int recMemConstWrite128(u32 mem, int mmreg)
|
|
{
|
|
mem = TRANSFORM_ADDR(mem);
|
|
|
|
switch( (mem&0xffff0000) ) {
|
|
case 0x10000000: hwConstWrite128(mem, mmreg); return 0;
|
|
case 0x12000000: gsConstWrite128(mem, mmreg); return 0;
|
|
|
|
case 0x1100:
|
|
_eeWriteConstMem128(PS2MEM_BASE_+mem, mmreg);
|
|
|
|
if( mem < 0x11004000 ) {
|
|
PUSH32I(4);
|
|
PUSH32I(mem&0x3ff8);
|
|
CALLFunc((u32)Cpu->ClearVU0);
|
|
ADD32ItoR(ESP, 8);
|
|
}
|
|
else if( mem >= 0x11008000 && mem < 0x1100c000 ) {
|
|
PUSH32I(4);
|
|
PUSH32I(mem&0x3ff8);
|
|
CALLFunc((u32)Cpu->ClearVU1);
|
|
ADD32ItoR(ESP, 8);
|
|
}
|
|
return 0;
|
|
|
|
default:
|
|
_eeWriteConstMem128(PS2MEM_BASE_+mem, mmreg);
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
int memRead8 (u32 mem, u8 *out) {
|
|
|
|
mem = TRANSFORM_ADDR(mem);
|
|
switch( (mem&~0xffff) ) {
|
|
case 0x1f400000: *out = psxHw4Read8(mem); return 0;
|
|
case 0x10000000: *out = hwRead8(mem); return 0;
|
|
case 0x1f800000: *out = psxHwRead8(mem); return 0;
|
|
case 0x12000000: *out = gsRead8(mem); return 0;
|
|
case 0x14000000:
|
|
*out = DEV9read8(mem & ~0x04000000);
|
|
SysPrintf("DEV9 read8 %8.8lx: %2.2lx\n", mem & ~0x04000000, *out);
|
|
return 0;
|
|
|
|
default:
|
|
*out = *(u8*)(PS2MEM_BASE+mem);
|
|
return 0;
|
|
}
|
|
|
|
#ifdef MEM_LOG
|
|
MEM_LOG("Unknown Memory read32 from address %8.8x\n", mem);
|
|
#endif
|
|
cpuTlbMissR(mem, cpuRegs.branch);
|
|
|
|
return -1;
|
|
}
|
|
|
|
int memRead8RS (u32 mem, u64 *out)
|
|
{
|
|
mem = TRANSFORM_ADDR(mem);
|
|
switch( (mem&~0xffff) ) {
|
|
case 0x1f400000: *out = (s8)psxHw4Read8(mem); return 0;
|
|
case 0x10000000: *out = (s8)hwRead8(mem); return 0;
|
|
case 0x1f800000: *out = (s8)psxHwRead8(mem); return 0;
|
|
case 0x12000000: *out = (s8)gsRead8(mem); return 0;
|
|
case 0x14000000:
|
|
*out = (s8)DEV9read8(mem & ~0x04000000);
|
|
SysPrintf("DEV9 read8 %8.8lx: %2.2lx\n", mem & ~0x04000000, *out);
|
|
return 0;
|
|
|
|
default:
|
|
*out = *(s8*)(PS2MEM_BASE+mem);
|
|
return 0;
|
|
}
|
|
|
|
#ifdef MEM_LOG
|
|
MEM_LOG("Unknown Memory read32 from address %8.8x\n", mem);
|
|
#endif
|
|
cpuTlbMissR(mem, cpuRegs.branch);
|
|
|
|
return -1;
|
|
}
|
|
|
|
int memRead8RU (u32 mem, u64 *out)
|
|
{
|
|
mem = TRANSFORM_ADDR(mem);
|
|
switch( (mem&~0xffff) ) {
|
|
case 0x1f400000: *out = (u8)psxHw4Read8(mem); return 0;
|
|
case 0x10000000: *out = (u8)hwRead8(mem); return 0;
|
|
case 0x1f800000: *out = (u8)psxHwRead8(mem); return 0;
|
|
case 0x12000000: *out = (u8)gsRead8(mem); return 0;
|
|
case 0x14000000:
|
|
*out = (u8)DEV9read8(mem & ~0x04000000);
|
|
SysPrintf("DEV9 read8 %8.8lx: %2.2lx\n", mem & ~0x04000000, *out);
|
|
return 0;
|
|
|
|
default:
|
|
*out = *(u8*)(PS2MEM_BASE+mem);
|
|
return 0;
|
|
}
|
|
|
|
#ifdef MEM_LOG
|
|
MEM_LOG("Unknown Memory read32 from address %8.8x\n", mem);
|
|
#endif
|
|
cpuTlbMissR(mem, cpuRegs.branch);
|
|
|
|
return -1;
|
|
}
|
|
|
|
int memRead16(u32 mem, u16 *out) {
|
|
|
|
mem = TRANSFORM_ADDR(mem);
|
|
switch( (mem&~0xffff) ) {
|
|
case 0x10000000: *out = hwRead16(mem); return 0;
|
|
case 0x1f800000: *out = psxHwRead16(mem); return 0;
|
|
case 0x12000000: *out = gsRead16(mem); return 0;
|
|
case 0x18000000: *out = 0; return 0;
|
|
case 0x1a000000: *out = ba0R16(mem); return 0;
|
|
case 0x1f900000:
|
|
case 0x1f000000:
|
|
*out = SPU2read(mem); return 0;
|
|
break;
|
|
case 0x14000000:
|
|
*out = DEV9read16(mem & ~0x04000000);
|
|
SysPrintf("DEV9 read8 %8.8lx: %2.2lx\n", mem & ~0x04000000, *out);
|
|
return 0;
|
|
|
|
default:
|
|
*out = *(u16*)(PS2MEM_BASE+mem);
|
|
return 0;
|
|
}
|
|
|
|
#ifdef MEM_LOG
|
|
MEM_LOG("Unknown Memory read16 from address %8.8x\n", mem);
|
|
#endif
|
|
cpuTlbMissR(mem, cpuRegs.branch);
|
|
|
|
return -1;
|
|
}
|
|
|
|
int memRead16RS(u32 mem, u64 *out) {
|
|
|
|
mem = TRANSFORM_ADDR(mem);
|
|
switch( (mem&~0xffff) ) {
|
|
case 0x10000000: *out = (s16)hwRead16(mem); return 0;
|
|
case 0x1f800000: *out = (s16)psxHwRead16(mem); return 0;
|
|
case 0x12000000: *out = (s16)gsRead16(mem); return 0;
|
|
case 0x18000000: *out = 0; return 0;
|
|
case 0x1a000000: *out = (s16)ba0R16(mem); return 0;
|
|
case 0x1f900000:
|
|
case 0x1f000000:
|
|
*out = (s16)SPU2read(mem); return 0;
|
|
break;
|
|
case 0x14000000:
|
|
*out = (s16)DEV9read16(mem & ~0x04000000);
|
|
SysPrintf("DEV9 read8 %8.8lx: %2.2lx\n", mem & ~0x04000000, *out);
|
|
return 0;
|
|
|
|
default:
|
|
*out = *(s16*)(PS2MEM_BASE+mem);
|
|
return 0;
|
|
}
|
|
|
|
#ifdef MEM_LOG
|
|
MEM_LOG("Unknown Memory read16 from address %8.8x\n", mem);
|
|
#endif
|
|
cpuTlbMissR(mem, cpuRegs.branch);
|
|
|
|
return -1;
|
|
}
|
|
|
|
int memRead16RU(u32 mem, u64 *out) {
|
|
|
|
mem = TRANSFORM_ADDR(mem);
|
|
switch( (mem&~0xffff) ) {
|
|
case 0x10000000: *out = (u16)hwRead16(mem ); return 0;
|
|
case 0x1f800000: *out = (u16)psxHwRead16(mem ); return 0;
|
|
case 0x12000000: *out = (u16)gsRead16(mem); return 0;
|
|
case 0x18000000: *out = 0; return 0;
|
|
case 0x1a000000: *out = (u16)ba0R16(mem); return 0;
|
|
case 0x1f900000:
|
|
case 0x1f000000:
|
|
*out = (u16)SPU2read(mem ); return 0;
|
|
break;
|
|
case 0x14000000:
|
|
*out = (u16)DEV9read16(mem & ~0x04000000);
|
|
SysPrintf("DEV9 read8 %8.8lx: %2.2lx\n", mem & ~0x04000000, *out);
|
|
return 0;
|
|
|
|
default:
|
|
*out = *(u16*)(PS2MEM_BASE+mem);
|
|
return 0;
|
|
}
|
|
|
|
#ifdef MEM_LOG
|
|
MEM_LOG("Unknown Memory read16 from address %8.8x\n", mem);
|
|
#endif
|
|
cpuTlbMissR(mem, cpuRegs.branch);
|
|
|
|
return -1;
|
|
}
|
|
|
|
int memRead32(u32 mem, u32 *out) {
|
|
|
|
mem = TRANSFORM_ADDR(mem);
|
|
switch( (mem&~0xffff) ) {
|
|
case 0x10000000: *out = hwRead32(mem); return 0;
|
|
case 0x1f800000: *out = psxHwRead32(mem); return 0;
|
|
case 0x12000000: *out = gsRead32(mem); return 0;
|
|
case 0x14000000:
|
|
*out = (u32)DEV9read32(mem & ~0x04000000);
|
|
SysPrintf("DEV9 read8 %8.8lx: %2.2lx\n", mem & ~0x04000000, *out);
|
|
return 0;
|
|
|
|
default:
|
|
*out = *(u32*)(PS2MEM_BASE+mem);
|
|
return 0;
|
|
}
|
|
|
|
#ifdef PCSX2_DEVBUILD
|
|
MEM_LOG("Unknown Memory read32 from address %8.8x (Status=%8.8x)\n", mem, cpuRegs.CP0.n.Status);
|
|
#endif
|
|
cpuTlbMissR(mem, cpuRegs.branch);
|
|
|
|
return -1;
|
|
}
|
|
|
|
int memRead32RS(u32 mem, u64 *out)
|
|
{
|
|
mem = TRANSFORM_ADDR(mem);
|
|
switch( (mem&~0xffff) ) {
|
|
case 0x10000000: *out = (s32)hwRead32(mem); return 0;
|
|
case 0x1f800000: *out = (s32)psxHwRead32(mem); return 0;
|
|
case 0x12000000: *out = (s32)gsRead32(mem); return 0;
|
|
case 0x14000000:
|
|
*out = (s32)DEV9read32(mem & ~0x04000000);
|
|
SysPrintf("DEV9 read8 %8.8lx: %2.2lx\n", mem & ~0x04000000, *out);
|
|
return 0;
|
|
|
|
default:
|
|
*out = *(s32*)(PS2MEM_BASE+mem);
|
|
return 0;
|
|
}
|
|
|
|
#ifdef PCSX2_DEVBUILD
|
|
MEM_LOG("Unknown Memory read32 from address %8.8x (Status=%8.8x)\n", mem, cpuRegs.CP0.n.Status);
|
|
#endif
|
|
cpuTlbMissR(mem, cpuRegs.branch);
|
|
|
|
return -1;
|
|
}
|
|
|
|
int memRead32RU(u32 mem, u64 *out)
|
|
{
|
|
mem = TRANSFORM_ADDR(mem);
|
|
switch( (mem&~0xffff) ) {
|
|
case 0x10000000: *out = (u32)hwRead32(mem); return 0;
|
|
case 0x1f800000: *out = (u32)psxHwRead32(mem); return 0;
|
|
case 0x12000000: *out = (u32)gsRead32(mem); return 0;
|
|
case 0x14000000:
|
|
*out = (u32)DEV9read32(mem & ~0x04000000);
|
|
SysPrintf("DEV9 read8 %8.8lx: %2.2lx\n", mem & ~0x04000000, *out);
|
|
return 0;
|
|
|
|
default:
|
|
*out = *(u32*)(PS2MEM_BASE+mem);
|
|
return 0;
|
|
}
|
|
|
|
#ifdef PCSX2_DEVBUILD
|
|
MEM_LOG("Unknown Memory read32 from address %8.8x (Status=%8.8x)\n", mem, cpuRegs.CP0.n.Status);
|
|
#endif
|
|
cpuTlbMissR(mem, cpuRegs.branch);
|
|
|
|
return -1;
|
|
}
|
|
|
|
int memRead64(u32 mem, u64 *out) {
|
|
mem = TRANSFORM_ADDR(mem);
|
|
switch( (mem&~0xffff) ) {
|
|
case 0x10000000: *out = hwRead64(mem); return 0;
|
|
case 0x12000000: *out = gsRead64(mem); return 0;
|
|
|
|
default:
|
|
*out = *(u64*)(PS2MEM_BASE+mem);
|
|
return 0;
|
|
}
|
|
|
|
#ifdef PCSX2_DEVBUILD
|
|
MEM_LOG("Unknown Memory read32 from address %8.8x (Status=%8.8x)\n", mem, cpuRegs.CP0.n.Status);
|
|
#endif
|
|
cpuTlbMissR(mem, cpuRegs.branch);
|
|
|
|
return -1;
|
|
}
|
|
|
|
int memRead128(u32 mem, u64 *out) {
|
|
|
|
mem = TRANSFORM_ADDR(mem);
|
|
switch( (mem&~0xffff) ) {
|
|
case 0x10000000:
|
|
hwRead128(mem, out);
|
|
return 0;
|
|
case 0x12000000:
|
|
out[0] = gsRead64(mem);
|
|
out[1] = gsRead64(mem + 8);
|
|
return 0;
|
|
|
|
default:
|
|
out[0] = *(u64*)(PS2MEM_BASE+mem);
|
|
out[1] = *(u64*)(PS2MEM_BASE+mem+8);
|
|
return 0;
|
|
}
|
|
|
|
#ifdef PCSX2_DEVBUILD
|
|
MEM_LOG("Unknown Memory read32 from address %8.8x (Status=%8.8x)\n", mem, cpuRegs.CP0.n.Status);
|
|
#endif
|
|
cpuTlbMissR(mem, cpuRegs.branch);
|
|
|
|
return -1;
|
|
}
|
|
|
|
void memWrite8 (u32 mem, u8 value) {
|
|
|
|
mem = TRANSFORM_ADDR(mem);
|
|
switch( (mem&~0xffff) ) {
|
|
case 0x1f400000: psxHw4Write8(mem, value); return;
|
|
case 0x10000000: hwWrite8(mem, value); return;
|
|
case 0x1f800000: psxHwWrite8(mem, value); return;
|
|
case 0x12000000: gsWrite8(mem, value); return;
|
|
case 0x14000000:
|
|
DEV9write8(mem & ~0x04000000, value);
|
|
SysPrintf("DEV9 write8 %8.8lx: %2.2lx\n", mem & ~0x04000000, value);
|
|
return;
|
|
|
|
default:
|
|
*(u8*)(PS2MEM_BASE+mem) = value;
|
|
|
|
if (CHECK_EEREC) {
|
|
REC_CLEARM(mem&~3);
|
|
}
|
|
return;
|
|
}
|
|
|
|
#ifdef MEM_LOG
|
|
MEM_LOG("Unknown Memory write8 to address %x with data %2.2x\n", mem, value);
|
|
#endif
|
|
cpuTlbMissW(mem, cpuRegs.branch);
|
|
}
|
|
|
|
void memWrite16(u32 mem, u16 value) {
|
|
|
|
mem = TRANSFORM_ADDR(mem);
|
|
switch( (mem&~0xffff) ) {
|
|
case 0x10000000: hwWrite16(mem, value); return;
|
|
case 0x1f800000: psxHwWrite16(mem, value); return;
|
|
case 0x12000000: gsWrite16(mem, value); return;
|
|
case 0x1f900000:
|
|
case 0x1f000000: SPU2write(mem, value); return;
|
|
case 0x14000000:
|
|
DEV9write16(mem & ~0x04000000, value);
|
|
SysPrintf("DEV9 write16 %8.8lx: %4.4lx\n", mem & ~0x04000000, value);
|
|
return;
|
|
|
|
default:
|
|
*(u16*)(PS2MEM_BASE+mem) = value;
|
|
if (CHECK_EEREC) {
|
|
REC_CLEARM(mem&~3);
|
|
}
|
|
return;
|
|
}
|
|
|
|
#ifdef MEM_LOG
|
|
MEM_LOG("Unknown Memory write16 to address %x with data %4.4x\n", mem, value);
|
|
#endif
|
|
cpuTlbMissW(mem, cpuRegs.branch);
|
|
}
|
|
|
|
void memWrite32(u32 mem, u32 value)
|
|
{
|
|
mem = TRANSFORM_ADDR(mem);
|
|
switch( (mem&~0xffff) ) {
|
|
case 0x10000000: hwWrite32(mem, value); return;
|
|
case 0x1f800000: psxHwWrite32(mem, value); return;
|
|
case 0x12000000: gsWrite32(mem, value); return;
|
|
case 0x1f900000:
|
|
case 0x1f000000: SPU2write(mem, value); return;
|
|
case 0x14000000:
|
|
DEV9write32(mem & ~0x4000000, value);
|
|
SysPrintf("DEV9 write32 %8.8lx: %8.8lx\n", mem & ~0x4000000, value);
|
|
return;
|
|
|
|
default:
|
|
*(u32*)(PS2MEM_BASE+mem) = value;
|
|
|
|
if (CHECK_EEREC) {
|
|
REC_CLEARM(mem);
|
|
}
|
|
return;
|
|
}
|
|
|
|
#ifdef MEM_LOG
|
|
MEM_LOG("Unknown Memory write32 to address %x with data %8.8x\n", mem, value);
|
|
#endif
|
|
cpuTlbMissW(mem, cpuRegs.branch);
|
|
}
|
|
|
|
void memWrite64(u32 mem, u64 value) {
|
|
|
|
mem = TRANSFORM_ADDR(mem);
|
|
switch( (mem&~0xffff) ) {
|
|
case 0x10000000: hwWrite64(mem, value); return;
|
|
case 0x12000000: gsWrite64(mem, value); return;
|
|
|
|
default:
|
|
*(u64*)(PS2MEM_BASE+mem) = value;
|
|
|
|
if (CHECK_EEREC) {
|
|
REC_CLEARM(mem);
|
|
REC_CLEARM(mem+4);
|
|
}
|
|
return;
|
|
}
|
|
|
|
#ifdef MEM_LOG
|
|
MEM_LOG("Unknown Memory write64 to address %x with data %8.8x_%8.8x\n", mem, (u32)(value>>32), (u32)value);
|
|
#endif
|
|
cpuTlbMissW(mem, cpuRegs.branch);
|
|
}
|
|
|
|
void memWrite128(u32 mem, u64 *value) {
|
|
|
|
mem = TRANSFORM_ADDR(mem);
|
|
switch( (mem&~0xffff) ) {
|
|
case 0x10000000: hwWrite128(mem, value); return;
|
|
case 0x12000000:
|
|
gsWrite64(mem, value[0]);
|
|
gsWrite64(mem + 8, value[1]);
|
|
return;
|
|
|
|
default:
|
|
*(u64*)(PS2MEM_BASE+mem) = value[0];
|
|
*(u64*)(PS2MEM_BASE+mem+8) = value[1];
|
|
|
|
if (CHECK_EEREC) {
|
|
REC_CLEARM(mem);
|
|
REC_CLEARM(mem+4);
|
|
REC_CLEARM(mem+8);
|
|
REC_CLEARM(mem+12);
|
|
}
|
|
return;
|
|
}
|
|
|
|
#ifdef MEM_LOG
|
|
MEM_LOG("Unknown Memory write128 to address %x with data %8.8x_%8.8x_%8.8x_%8.8x\n", mem, ((u32*)value)[3], ((u32*)value)[2], ((u32*)value)[1], ((u32*)value)[0]);
|
|
#endif
|
|
cpuTlbMissW(mem, cpuRegs.branch);
|
|
}
|
|
|
|
#else
|
|
|
|
u8 *psM; //32mb Main Ram
|
|
u8 *psR; //4mb rom area
|
|
u8 *psR1; //256kb rom1 area (actually 196kb, but can't mask this)
|
|
u8 *psR2; // 0x00080000
|
|
u8 *psER; // 0x001C0000
|
|
u8 *psS; //0.015 mb, scratch pad
|
|
|
|
uptr *memLUTR;
|
|
uptr *memLUTW;
|
|
uptr *memLUTRK;
|
|
uptr *memLUTWK;
|
|
uptr *memLUTRU;
|
|
uptr *memLUTWU;
|
|
|
|
#define CHECK_MEM(mem) //MyMemCheck(mem)
|
|
|
|
void MyMemCheck(u32 mem)
|
|
{
|
|
if( mem == 0x1c02f2a0 )
|
|
SysPrintf("yo\n");
|
|
}
|
|
|
|
/////////////////////////////
|
|
// REGULAR MEM START
|
|
/////////////////////////////
|
|
|
|
void memMapMem(u32 base) {
|
|
int i;
|
|
|
|
for (i=0; i<0x02000; i++) memLUTRK[i + 0x00000 + base] = (uptr)&psM[i << 12];
|
|
for (i=0; i<0x00400; i++) memLUTRK[i + 0x1fc00 + base] = (uptr)&psR[i << 12];
|
|
for (i=0; i<0x00040; i++) memLUTRK[i + 0x1e000 + base] = (uptr)&psR1[i << 12];
|
|
for (i=0; i<0x00080; i++) memLUTRK[i + 0x1e400 + base] = (uptr)&psR2[i << 12];
|
|
for (i=0; i<0x001C0; i++) memLUTRK[i + 0x1e040 + base] = (uptr)&psER[i << 12];
|
|
for (i=0; i<0x00800; i++) memLUTRK[i + 0x1c000 + base] = (uptr)&psxM[(i & 0x1ff) << 12];
|
|
for (i=0; i<0x00004; i++) memLUTRK[i + 0x11000 + base] = (uptr)VU0.Micro;
|
|
for (i=0; i<0x00004; i++) memLUTRK[i + 0x11004 + base] = (uptr)VU0.Mem;
|
|
for (i=0; i<0x00004; i++) memLUTRK[i + 0x11008 + base] = (uptr)&VU1.Micro[i << 12];
|
|
for (i=0; i<0x00004; i++) memLUTRK[i + 0x1100c + base] = (uptr)&VU1.Mem[i << 12];
|
|
|
|
for (i=0; i<0x02000; i++) memLUTWK[i + 0x00000 + base] = (uptr)&psM[i << 12];
|
|
for (i=0; i<0x00400; i++) memLUTWK[i + 0x1fc00 + base] = (uptr)&psR[i << 12];
|
|
for (i=0; i<0x00040; i++) memLUTWK[i + 0x1e000 + base] = (uptr)&psR1[i << 12];
|
|
for (i=0; i<0x00080; i++) memLUTWK[i + 0x1e400 + base] = (uptr)&psR2[i << 12];
|
|
for (i=0; i<0x001C0; i++) memLUTWK[i + 0x1e040 + base] = (uptr)&psER[i << 12];
|
|
for (i=0; i<0x00800; i++) memLUTWK[i + 0x1c000 + base] = (uptr)&psxM[(i & 0x1ff) << 12];
|
|
for (i=0; i<0x00004; i++) memLUTWK[i + 0x11000 + base] = (uptr)VU0.Micro;
|
|
for (i=0; i<0x00004; i++) memLUTWK[i + 0x11004 + base] = (uptr)VU0.Mem;
|
|
for (i=0; i<0x00004; i++) memLUTWK[i + 0x11008 + base] = (uptr)&VU1.Micro[i << 12];
|
|
for (i=0; i<0x00004; i++) memLUTWK[i + 0x1100c + base] = (uptr)&VU1.Mem[i << 12];
|
|
|
|
assert( ((uptr)VU0.Mem&15)==0 && ((uptr)VU0.Micro&15)==0);
|
|
for (i=0; i<0x00010; i++) memLUTRK[i + 0x10000 + base] = 1; // hwm
|
|
for (i=0; i<0x00010; i++) memLUTRK[i + 0x1f800 + base] = 2; // psh
|
|
for (i=0; i<0x00010; i++) memLUTRK[i + 0x1f400 + base] = 3; // psh4
|
|
for (i=0; i<0x00010; i++) memLUTRK[i + 0x18000 + base] = 4; // b80
|
|
for (i=0; i<0x00010; i++) memLUTRK[i + 0x1a000 + base] = 5; // ba0
|
|
for (i=0; i<0x00010; i++) memLUTRK[i + 0x12000 + base] = 6; // gsm
|
|
for (i=0; i<0x00010; i++) memLUTRK[i + 0x14000 + base] = 7; // dev9
|
|
for (i=0; i<0x00010; i++) memLUTRK[i + 0x1f900 + base] = 8; // spu2
|
|
for (i=0; i<0x00010; i++) memLUTRK[i + 0x1f000 + base] = 8; // spu2 (not sure)
|
|
|
|
for (i=0; i<0x00010; i++) memLUTWK[i + 0x10000 + base] = 1; // hwm
|
|
for (i=0; i<0x00010; i++) memLUTWK[i + 0x1f800 + base] = 2; // psh
|
|
for (i=0; i<0x00010; i++) memLUTWK[i + 0x1f400 + base] = 3; // psh4
|
|
for (i=0; i<0x00010; i++) memLUTWK[i + 0x1a000 + base] = 5; // ba0
|
|
for (i=0; i<0x00010; i++) memLUTWK[i + 0x12000 + base] = 6; // gsm
|
|
for (i=0; i<0x00010; i++) memLUTWK[i + 0x14000 + base] = 7; // dev9
|
|
for (i=0; i<0x00010; i++) memLUTWK[i + 0x1f900 + base] = 8; // spu2
|
|
for (i=0; i<0x00010; i++) memLUTWK[i + 0x1f000 + base] = 8; // spu2 (not sure)
|
|
}
|
|
|
|
void memMapKernelMem() {
|
|
memMapMem(0xa0000);
|
|
memMapMem(0x80000);
|
|
memMapMem(0x00000);
|
|
}
|
|
|
|
void memMapSupervisorMem() {
|
|
}
|
|
|
|
void memMapUserMem() {
|
|
}
|
|
|
|
int memInit() {
|
|
int i;
|
|
|
|
psR = (u8*)_aligned_malloc(0x00400010, 16);
|
|
psR1 = (u8*)_aligned_malloc(0x00080010, 16);
|
|
psR2 = (u8*)_aligned_malloc(0x00080010, 16);
|
|
|
|
if (psxInit() == -1)
|
|
return -1;
|
|
|
|
memLUTRK = (uptr*)_aligned_malloc(0x100000 * sizeof(uptr), 16);
|
|
memLUTWK = (uptr*)_aligned_malloc(0x100000 * sizeof(uptr), 16);
|
|
memLUTRU = (uptr*)_aligned_malloc(0x100000 * sizeof(uptr), 16);
|
|
memLUTWU = (uptr*)_aligned_malloc(0x100000 * sizeof(uptr), 16);
|
|
|
|
psM = (u8*)_aligned_malloc(0x02000010, 16);
|
|
psER = (u8*)_aligned_malloc(0x001C0010, 16);
|
|
psS = (u8*)_aligned_malloc(0x00004010, 16);
|
|
if (memLUTRK == NULL || memLUTWK == NULL ||
|
|
memLUTRU == NULL || memLUTWU == NULL ||
|
|
psM == NULL || psR == NULL || psR1 == NULL ||
|
|
psR2 == NULL || psER == NULL || psS == NULL) {
|
|
SysMessage(_("Error allocating memory")); return -1;
|
|
}
|
|
|
|
memset(memLUTRK, 0, 0x100000 * 4);
|
|
memset(memLUTWK, 0, 0x100000 * 4);
|
|
memset(memLUTRU, 0, 0x100000 * 4);
|
|
memset(memLUTWU, 0, 0x100000 * 4);
|
|
|
|
memset(psM, 0, 0x02000010);
|
|
memset(psR, 0, 0x00400010);
|
|
memset(psR1, 0, 0x00080010);
|
|
memset(psR2, 0, 0x00080010);
|
|
memset(psER, 0, 0x001C0010);
|
|
memset(psS, 0, 0x00004010);
|
|
|
|
for (i=0x00000; i<0x00004; i++) memLUTRK[i + 0x70000] = (uptr)&psS[i << 12];
|
|
for (i=0x00000; i<0x00004; i++) memLUTWK[i + 0x70000] = (uptr)&psS[i << 12];
|
|
|
|
for (i=0x00000; i<0x00004; i++) memLUTRU[i + 0x70000] = (uptr)&psS[i << 12];
|
|
for (i=0x00000; i<0x00004; i++) memLUTWU[i + 0x70000] = (uptr)&psS[i << 12];
|
|
|
|
|
|
memMapKernelMem();
|
|
memMapSupervisorMem();
|
|
memMapUserMem();
|
|
|
|
memSetKernelMode();
|
|
|
|
#ifdef ENABLECACHE
|
|
memset(pCache,0,sizeof(_cacheS)*64);
|
|
#endif
|
|
|
|
return 0;
|
|
}
|
|
|
|
void memShutdown() {
|
|
FREE(psM);
|
|
FREE(psR);
|
|
FREE(psR1);
|
|
FREE(psR2);
|
|
FREE(psER);
|
|
FREE(psS);
|
|
FREE(memLUTRK);
|
|
FREE(memLUTWK);
|
|
FREE(memLUTRU);
|
|
FREE(memLUTWU);
|
|
}
|
|
|
|
void memSetPageAddr(u32 vaddr, u32 paddr) {
|
|
// SysPrintf("memSetPageAddr: %8.8x -> %8.8x\n", vaddr, paddr);
|
|
|
|
memLUTRU[vaddr >> 12] = memLUTRK[paddr >> 12];
|
|
memLUTWU[vaddr >> 12] = memLUTWK[paddr >> 12];
|
|
|
|
memLUTRK[vaddr >> 12] = memLUTRK[paddr >> 12];
|
|
memLUTWK[vaddr >> 12] = memLUTWK[paddr >> 12];
|
|
}
|
|
|
|
void memClearPageAddr(u32 vaddr) {
|
|
// SysPrintf("memClearPageAddr: %8.8x\n", vaddr);
|
|
|
|
if ((vaddr & 0xffffc000) == 0x70000000) return;
|
|
memLUTRU[vaddr >> 12] = 0;
|
|
memLUTWU[vaddr >> 12] = 0;
|
|
|
|
#ifdef FULLTLB
|
|
memLUTRK[vaddr >> 12] = 0;
|
|
memLUTWK[vaddr >> 12] = 0;
|
|
#endif
|
|
}
|
|
|
|
int memRead8 (u32 mem, u8 *out) {
|
|
char *p;
|
|
|
|
p = (char *)(memLUTR[mem >> 12]);
|
|
if ((uptr)p > 0x10) {
|
|
#ifdef ENABLECACHE
|
|
if ((mem & 0x20000000) == 0 &&
|
|
(cpuRegs.CP0.r[16] & 0x10000) && !(cpuRegs.CP0.n.Status.val & 0x4)) {
|
|
u8 *tmp = readCache(mem);
|
|
*out = *(u8 *)(tmp+(mem&0xf));
|
|
return 0;
|
|
}
|
|
#endif
|
|
*out = *(u8 *)(p + (mem & 0xfff));
|
|
return 0;
|
|
}
|
|
|
|
switch ((int)(uptr)p) {
|
|
case 1: // hwm
|
|
*out = hwRead8(mem & ~0xa0000000); return 0;
|
|
case 2: // psh
|
|
*out = psxHwRead8(mem & ~0xa0000000); return 0;
|
|
case 3: // psh4
|
|
*out = psxHw4Read8(mem & ~0xa0000000); return 0;
|
|
case 6: // gsm
|
|
*out = gsRead8(mem & ~0xa0000000); return 0;
|
|
case 7: // dev9
|
|
*out = DEV9read8(mem & ~0xa4000000);
|
|
SysPrintf("DEV9 read8 %8.8lx: %2.2lx\n", mem & ~0xa4000000, *out);
|
|
return 0;
|
|
}
|
|
|
|
#ifdef MEM_LOG
|
|
MEM_LOG("Unknown Memory read32 from address %8.8x\n", mem);
|
|
#endif
|
|
cpuTlbMissR(mem, cpuRegs.branch);
|
|
|
|
return -1;
|
|
}
|
|
|
|
int memRead8RS (u32 mem, u64 *out) {
|
|
char *p;
|
|
|
|
p = (char *)(memLUTR[mem >> 12]);
|
|
if ((uptr)p > 0x10) {
|
|
#ifdef ENABLECACHE
|
|
if ((mem & 0x20000000) == 0 &&
|
|
(cpuRegs.CP0.r[16] & 0x10000) && !(cpuRegs.CP0.n.Status.val & 0x4)) {
|
|
char *tmp = (char*)readCache(mem);
|
|
*out = *(s8 *)(tmp+(mem&0xf));
|
|
return 0;
|
|
}
|
|
#endif
|
|
*out = *(s8 *)(p + (mem & 0xfff));
|
|
return 0;
|
|
}
|
|
|
|
switch ((int)(uptr)p) {
|
|
case 1: // hwm
|
|
*out = (s8)hwRead8(mem & ~0xa0000000); return 0;
|
|
case 2: // psh
|
|
*out = (s8)psxHwRead8(mem & ~0xa0000000); return 0;
|
|
case 3: // psh4
|
|
*out = (s8)psxHw4Read8(mem & ~0xa0000000); return 0;
|
|
case 6: // gsm
|
|
*out = (s8)gsRead8(mem & ~0xa0000000); return 0;
|
|
case 7: // dev9
|
|
*out = (s8)DEV9read8(mem & ~0xa4000000);
|
|
SysPrintf("DEV9 read8 %8.8lx: %2.2lx\n", mem & ~0xa4000000, *out);
|
|
return 0;
|
|
}
|
|
|
|
#ifdef MEM_LOG
|
|
MEM_LOG("Unknown Memory read32 from address %8.8x\n", mem);
|
|
#endif
|
|
cpuTlbMissR(mem, cpuRegs.branch);
|
|
|
|
return -1;
|
|
}
|
|
|
|
int memRead8RU (u32 mem, u64 *out) {
|
|
char *p;
|
|
|
|
p = (char *)(memLUTR[mem >> 12]);
|
|
if ((uptr)p > 0x10) {
|
|
#ifdef ENABLECACHE
|
|
if ((mem & 0x20000000) == 0 &&
|
|
(cpuRegs.CP0.r[16] & 0x10000) && !(cpuRegs.CP0.n.Status.val & 0x4)) {
|
|
char *tmp = (char*)readCache(mem);
|
|
*out = *(u8 *)(tmp+(mem&0xf));
|
|
return 0;
|
|
}
|
|
#endif
|
|
*out = *(u8 *)(p + (mem & 0xfff));
|
|
return 0;
|
|
}
|
|
|
|
switch ((int)(uptr)p) {
|
|
case 1: // hwm
|
|
*out = (u8)hwRead8(mem & ~0xa0000000); return 0;
|
|
case 2: // psh
|
|
*out = (u8)psxHwRead8(mem & ~0xa0000000); return 0;
|
|
case 3: // psh4
|
|
*out = (u8)psxHw4Read8(mem & ~0xa0000000); return 0;
|
|
case 6: // gsm
|
|
*out = (u8)gsRead8(mem & ~0xa0000000); return 0;
|
|
case 7: // dev9
|
|
*out = (u8)DEV9read8(mem & ~0xa4000000);
|
|
SysPrintf("DEV9 read8 %8.8lx: %2.2lx\n", mem & ~0xa4000000, *out);
|
|
return 0;
|
|
}
|
|
|
|
#ifdef MEM_LOG
|
|
MEM_LOG("Unknown Memory read32 from address %8.8x\n", mem);
|
|
#endif
|
|
cpuTlbMissR(mem, cpuRegs.branch);
|
|
|
|
return -1;
|
|
}
|
|
|
|
int memRead16(u32 mem, u16 *out) {
|
|
char *p;
|
|
|
|
p = (char *)(memLUTR[mem >> 12]);
|
|
if ((uptr)p > 0x10) {
|
|
#ifdef ENABLECACHE
|
|
if ((mem & 0x20000000) == 0 &&
|
|
(cpuRegs.CP0.r[16] & 0x10000) && !(cpuRegs.CP0.n.Status.val & 0x4)) {
|
|
u8 *tmp = readCache(mem);
|
|
*out = *(u16 *)(tmp+(mem&0xf));
|
|
return 0;
|
|
}
|
|
#endif
|
|
*out = *(u16*)(p + (mem & 0xfff));
|
|
return 0;
|
|
}
|
|
|
|
switch ((int)(uptr)p) {
|
|
case 1: // hwm
|
|
*out = hwRead16(mem & ~0xa0000000); return 0;
|
|
case 2: // psh
|
|
*out = psxHwRead16(mem & ~0xa0000000); return 0;
|
|
case 4: // b80
|
|
#ifdef MEM_LOG
|
|
MEM_LOG("b800000 Memory read16 address %x\n", mem);
|
|
#endif
|
|
*out = 0; return 0;
|
|
case 5: // ba0
|
|
*out = ba0R16(mem); return 0;
|
|
case 6: // gsm
|
|
*out = gsRead16(mem & ~0xa0000000); return 0;
|
|
case 7: // dev9
|
|
*out = DEV9read16(mem & ~0xa4000000);
|
|
SysPrintf("DEV9 read16 %8.8lx: %4.4lx\n", mem & ~0xa4000000, *out);
|
|
return 0;
|
|
case 8: // spu2
|
|
*out = SPU2read(mem & ~0xa0000000); return 0;
|
|
}
|
|
|
|
#ifdef MEM_LOG
|
|
MEM_LOG("Unknown Memory read16 from address %8.8x\n", mem);
|
|
#endif
|
|
cpuTlbMissR(mem, cpuRegs.branch);
|
|
|
|
return -1;
|
|
}
|
|
|
|
int memRead16RS(u32 mem, u64 *out) {
|
|
char *p;
|
|
|
|
p = (char *)(memLUTR[mem >> 12]);
|
|
if ((uptr)p > 0x10) {
|
|
#ifdef ENABLECACHE
|
|
if ((mem & 0x20000000) == 0 &&
|
|
(cpuRegs.CP0.r[16] & 0x10000) && !(cpuRegs.CP0.n.Status.val & 0x4)) {
|
|
char *tmp = (char*)readCache(mem);
|
|
*out = *(s16*)(tmp+(mem&0xf));
|
|
return 0;
|
|
}
|
|
#endif
|
|
*out = *(s16*)(p + (mem & 0xfff));
|
|
return 0;
|
|
}
|
|
|
|
switch ((int)(uptr)p) {
|
|
case 1: // hwm
|
|
*out = (s16)hwRead16(mem & ~0xa0000000); return 0;
|
|
case 2: // psh
|
|
*out = (s16)psxHwRead16(mem & ~0xa0000000); return 0;
|
|
case 4: // b80
|
|
#ifdef MEM_LOG
|
|
MEM_LOG("b800000 Memory read16 address %x\n", mem);
|
|
#endif
|
|
*out = 0; return 0;
|
|
case 5: // ba0
|
|
*out = (s16)ba0R16(mem); return 0;
|
|
case 6: // gsm
|
|
*out = (s16)gsRead16(mem & ~0xa0000000); return 0;
|
|
case 7: // dev9
|
|
*out = (s16)DEV9read16(mem & ~0xa4000000);
|
|
SysPrintf("DEV9 read16 %8.8lx: %4.4lx\n", mem & ~0xa4000000, *out);
|
|
return 0;
|
|
case 8: // spu2
|
|
*out = (s16)SPU2read(mem & ~0xa0000000); return 0;
|
|
}
|
|
|
|
#ifdef MEM_LOG
|
|
MEM_LOG("Unknown Memory read16 from address %8.8x\n", mem);
|
|
#endif
|
|
cpuTlbMissR(mem, cpuRegs.branch);
|
|
|
|
return -1;
|
|
}
|
|
|
|
int memRead16RU(u32 mem, u64 *out) {
|
|
char *p;
|
|
|
|
p = (char *)(memLUTR[mem >> 12]);
|
|
if ((uptr)p > 0x10) {
|
|
#ifdef ENABLECACHE
|
|
if ((mem & 0x20000000) == 0 &&
|
|
(cpuRegs.CP0.r[16] & 0x10000) && !(cpuRegs.CP0.n.Status.val & 0x4)) {
|
|
char *tmp = (char*)readCache(mem);
|
|
*out = *(u16*)(tmp+(mem&0xf));
|
|
return 0;
|
|
}
|
|
#endif
|
|
*out = *(u16*)(p + (mem & 0xfff));
|
|
return 0;
|
|
}
|
|
|
|
switch ((int)(uptr)p) {
|
|
case 1: // hwm
|
|
*out = (u16)hwRead16(mem & ~0xa0000000); return 0;
|
|
case 2: // psh
|
|
*out = (u16)psxHwRead16(mem & ~0xa0000000); return 0;
|
|
case 4: // b80
|
|
#ifdef MEM_LOG
|
|
MEM_LOG("b800000 Memory read16 address %x\n", mem);
|
|
#endif
|
|
*out = 0; return 0;
|
|
case 5: // ba0
|
|
*out = (u16)ba0R16(mem); return 0;
|
|
case 6: // gsm
|
|
*out = (u16)gsRead16(mem & ~0xa0000000); return 0;
|
|
case 7: // dev9
|
|
*out = (u16)DEV9read16(mem & ~0xa4000000);
|
|
SysPrintf("DEV9 read16 %8.8lx: %4.4lx\n", mem & ~0xa4000000, *out);
|
|
return 0;
|
|
case 8: // spu2
|
|
*out = (u16)SPU2read(mem & ~0xa0000000); return 0;
|
|
}
|
|
|
|
#ifdef MEM_LOG
|
|
MEM_LOG("Unknown Memory read16 from address %8.8x\n", mem);
|
|
#endif
|
|
cpuTlbMissR(mem, cpuRegs.branch);
|
|
|
|
return -1;
|
|
}
|
|
|
|
int memRead32(u32 mem, u32 *out) {
|
|
char *p;
|
|
|
|
CHECK_MEM(mem);
|
|
|
|
p = (char *)(memLUTR[mem >> 12]);
|
|
if ((uptr)p > 0x10) {
|
|
#ifdef ENABLECACHE
|
|
if ((mem & 0x20000000) == 0 &&
|
|
(cpuRegs.CP0.r[16] & 0x10000) && !(cpuRegs.CP0.n.Status.val & 0x4)) {
|
|
u8 *tmp = readCache(mem);
|
|
*out = *(u32 *)(tmp+(mem&0xf));
|
|
return 0;
|
|
}
|
|
#endif
|
|
*out = *(u32*)(p + (mem & 0xfff));
|
|
return 0;
|
|
}
|
|
assert( (int)(uptr)p < 8 );
|
|
|
|
switch ((int)(uptr)p) {
|
|
case 1: // hwm
|
|
*out = hwRead32(mem & ~0xa0000000); return 0;
|
|
case 2: // psh
|
|
*out = psxHwRead32(mem & ~0xa0000000); return 0;
|
|
case 6: // gsm
|
|
*out = gsRead32(mem & ~0xa0000000); return 0;
|
|
case 7: // dev9
|
|
*out = DEV9read32(mem & ~0xa4000000);
|
|
SysPrintf("DEV9 read32 %8.8lx: %8.8lx\n", mem & ~0xa4000000, *out);
|
|
return 0;
|
|
}
|
|
|
|
#ifdef PCSX2_DEVBUILD
|
|
MEM_LOG("Unknown Memory read32 from address %8.8x (Status=%8.8x)\n", mem, cpuRegs.CP0.n.Status);
|
|
#endif
|
|
cpuTlbMissR(mem, cpuRegs.branch);
|
|
|
|
return -1;
|
|
}
|
|
|
|
int memRead32RS(u32 mem, u64 *out) {
|
|
char *p;
|
|
|
|
CHECK_MEM(mem);
|
|
|
|
p = (char *)(memLUTR[mem >> 12]);
|
|
if ((uptr)p > 0x10) {
|
|
#ifdef ENABLECACHE
|
|
if ((mem & 0x20000000) == 0 &&
|
|
(cpuRegs.CP0.r[16] & 0x10000) && !(cpuRegs.CP0.n.Status.val & 0x4)) {
|
|
char *tmp = (char*)readCache(mem);
|
|
*out = *(s32*)(tmp+(mem&0xf));
|
|
return 0;
|
|
}
|
|
#endif
|
|
*out = *(s32*)(p + (mem & 0xfff));
|
|
return 0;
|
|
}
|
|
|
|
switch ((int)(uptr)p) {
|
|
case 1: // hwm
|
|
*out = (s32)hwRead32(mem & ~0xa0000000); return 0;
|
|
case 2: // psh
|
|
*out = (s32)psxHwRead32(mem & ~0xa0000000); return 0;
|
|
case 6: // gsm
|
|
*out = (s32)gsRead32(mem & ~0xa0000000); return 0;
|
|
case 7: // dev9
|
|
*out = (s32)DEV9read32(mem & ~0xa4000000);
|
|
SysPrintf("DEV9 read32 %8.8lx: %8.8lx\n", mem & ~0xa4000000, *out);
|
|
return 0;
|
|
}
|
|
|
|
#ifdef PCSX2_DEVBUILD
|
|
MEM_LOG("Unknown Memory read32 from address %8.8x (Status=%8.8x)\n", mem, cpuRegs.CP0.n.Status);
|
|
#endif
|
|
cpuTlbMissR(mem, cpuRegs.branch);
|
|
|
|
return -1;
|
|
}
|
|
|
|
int memRead32RU(u32 mem, u64 *out) {
|
|
char *p;
|
|
|
|
CHECK_MEM(mem);
|
|
|
|
p = (char *)(memLUTR[mem >> 12]);
|
|
if ((uptr)p > 0x10) {
|
|
#ifdef ENABLECACHE
|
|
if ((mem & 0x20000000) == 0 &&
|
|
(cpuRegs.CP0.r[16] & 0x10000) && !(cpuRegs.CP0.n.Status.val & 0x4)) {
|
|
char *tmp = (char*)readCache(mem);
|
|
*out = *(u32*)(tmp+(mem&0xf));
|
|
return 0;
|
|
}
|
|
#endif
|
|
*out = *(u32*)(p + (mem & 0xfff));
|
|
return 0;
|
|
}
|
|
|
|
switch ((int)(uptr)p) {
|
|
case 1: // hwm
|
|
*out = (u32)hwRead32(mem & ~0xa0000000); return 0;
|
|
case 2: // psh
|
|
*out = (u32)psxHwRead32(mem & ~0xa0000000); return 0;
|
|
case 6: // gsm
|
|
*out = (u32)gsRead32(mem & ~0xa0000000); return 0;
|
|
case 7: // dev9
|
|
*out = (u32)DEV9read32(mem & ~0xa4000000);
|
|
SysPrintf("DEV9 read32 %8.8lx: %8.8lx\n", mem & ~0xa4000000, *out);
|
|
return 0;
|
|
}
|
|
|
|
#ifdef PCSX2_DEVBUILD
|
|
MEM_LOG("Unknown Memory read32 from address %8.8x (Status=%8.8x)\n", mem, cpuRegs.CP0.n.Status);
|
|
#endif
|
|
cpuTlbMissR(mem, cpuRegs.branch);
|
|
|
|
return -1;
|
|
}
|
|
|
|
int memRead64(u32 mem, u64 *out) {
|
|
char *p;
|
|
|
|
CHECK_MEM(mem);
|
|
|
|
p = (char *)(memLUTR[mem >> 12]);
|
|
if ((uptr)p > 0x10) {
|
|
#ifdef ENABLECACHE
|
|
if ((mem & 0x20000000) == 0 &&
|
|
(cpuRegs.CP0.r[16] & 0x10000) && !(cpuRegs.CP0.n.Status.val & 0x4)) {
|
|
u8 *tmp = readCache(mem);
|
|
*out = *(u64*)(tmp+(mem&0xf));
|
|
return 0;
|
|
}
|
|
#endif
|
|
*out = *(u64*)(p + (mem & 0xfff));
|
|
return 0;
|
|
}
|
|
|
|
switch ((int)(uptr)p) {
|
|
case 1: // hwm
|
|
*out = hwRead64(mem & ~0xa0000000); return 0;
|
|
case 6: // gsm
|
|
*out = gsRead64(mem & ~0xa0000000); return 0;
|
|
}
|
|
|
|
#ifdef MEM_LOG
|
|
MEM_LOG("Unknown Memory read64 from address %8.8x\n", mem);
|
|
#endif
|
|
cpuTlbMissR(mem, cpuRegs.branch);
|
|
|
|
return -1;
|
|
}
|
|
|
|
int memRead128(u32 mem, u64 *out) {
|
|
char *p;
|
|
|
|
CHECK_MEM(mem);
|
|
|
|
p = (char *)(memLUTR[mem >> 12]);
|
|
if ((uptr)p > 0x10) {
|
|
#ifdef ENABLECACHE
|
|
if ((mem & 0x20000000) == 0 &&
|
|
(cpuRegs.CP0.r[16] & 0x10000) && !(cpuRegs.CP0.n.Status.val & 0x4)) {
|
|
u64 *tmp = (u64*)readCache(mem);
|
|
out[0] = tmp[0];
|
|
out[1] = tmp[1];
|
|
return 0;
|
|
}
|
|
#endif
|
|
p+= mem & 0xfff;
|
|
out[0] = ((u64*)p)[0];
|
|
out[1] = ((u64*)p)[1];
|
|
return 0;
|
|
}
|
|
|
|
switch ((int)(uptr)p) {
|
|
case 1: // hwm
|
|
hwRead128(mem & ~0xa0000000, out); return 0;
|
|
case 6: // gsm
|
|
out[0] = gsRead64((mem ) & ~0xa0000000);
|
|
out[1] = gsRead64((mem+8) & ~0xa0000000); return 0;
|
|
}
|
|
|
|
#ifdef MEM_LOG
|
|
MEM_LOG("Unknown Memory read128 from address %8.8x\n", mem);
|
|
#endif
|
|
cpuTlbMissR(mem, cpuRegs.branch);
|
|
|
|
return -1;
|
|
}
|
|
|
|
#define CHECK_VUMEM(size) { \
|
|
if( mem >= 0x11000000 && mem < 0x11004000 ) \
|
|
Cpu->ClearVU0(mem&0x3ff8, size); \
|
|
else if( mem >= 0x11008000 && mem < 0x1100c000 ) \
|
|
Cpu->ClearVU1(mem&0x3ff8, size); \
|
|
}
|
|
|
|
void memWrite8 (u32 mem, u8 value) {
|
|
char *p;
|
|
|
|
p = (char *)(memLUTW[mem >> 12]);
|
|
if ((uptr)p > 0x10) {
|
|
#ifdef ENABLECACHE
|
|
if ((mem & 0x20000000) == 0 && (cpuRegs.CP0.r[16] & 0x10000)) {
|
|
writeCache8(mem, value);
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
*(u8 *)(p + (mem & 0xfff)) = value;
|
|
if (CHECK_EEREC) {
|
|
CHECK_VUMEM(1);
|
|
REC_CLEARM(mem&(~3));
|
|
// PSXREC_CLEARM(mem & 0x1ffffc);
|
|
}
|
|
return;
|
|
}
|
|
|
|
switch ((int)(uptr)p) {
|
|
case 1: // hwm
|
|
hwWrite8(mem & ~0xa0000000, value);
|
|
return;
|
|
case 2: // psh
|
|
psxHwWrite8(mem & ~0xa0000000, value); return;
|
|
case 3: // psh4
|
|
psxHw4Write8(mem & ~0xa0000000, value); return;
|
|
case 6: // gsm
|
|
gsWrite8(mem & ~0xa0000000, value); return;
|
|
case 7: // dev9
|
|
DEV9write8(mem & ~0xa4000000, value);
|
|
SysPrintf("DEV9 write8 %8.8lx: %2.2lx\n", mem & ~0xa4000000, value);
|
|
return;
|
|
}
|
|
|
|
#ifdef MEM_LOG
|
|
MEM_LOG("Unknown Memory write8 to address %x with data %2.2x\n", mem, value);
|
|
#endif
|
|
cpuTlbMissW(mem, cpuRegs.branch);
|
|
}
|
|
|
|
void memWrite16(u32 mem, u16 value) {
|
|
char *p;
|
|
|
|
p = (char *)(memLUTW[mem >> 12]);
|
|
if ((uptr)p > 0x10) {
|
|
#ifdef ENABLECACHE
|
|
if ((mem & 0x20000000) == 0 && (cpuRegs.CP0.r[16] & 0x10000)) {
|
|
writeCache16(mem, value);
|
|
return;
|
|
}
|
|
#endif
|
|
*(u16*)(p + (mem & 0xfff)) = value;
|
|
if (CHECK_EEREC) {
|
|
CHECK_VUMEM(1);
|
|
REC_CLEARM(mem&~1);
|
|
//PSXREC_CLEARM(mem & 0x1ffffe);
|
|
}
|
|
return;
|
|
}
|
|
|
|
switch ((int)(uptr)p) {
|
|
case 1: // hwm
|
|
hwWrite16(mem & ~0xa0000000, value);
|
|
return;
|
|
case 2: // psh
|
|
psxHwWrite16(mem & ~0xa0000000, value); return;
|
|
case 5: // ba0
|
|
#ifdef MEM_LOG
|
|
MEM_LOG("ba00000 Memory write16 to address %x with data %x\n", mem, value);
|
|
#endif
|
|
return;
|
|
case 6: // gsm
|
|
gsWrite16(mem & ~0xa0000000, value); return;
|
|
case 7: // dev9
|
|
DEV9write16(mem & ~0xa4000000, value);
|
|
SysPrintf("DEV9 write16 %8.8lx: %4.4lx\n", mem & ~0xa4000000, value);
|
|
return;
|
|
case 8: // spu2
|
|
SPU2write(mem & ~0xa0000000, value); return;
|
|
}
|
|
|
|
#ifdef MEM_LOG
|
|
MEM_LOG("Unknown Memory write16 to address %x with data %4.4x\n", mem, value);
|
|
#endif
|
|
cpuTlbMissW(mem, cpuRegs.branch);
|
|
}
|
|
|
|
void memWrite32(u32 mem, u32 value)
|
|
{
|
|
char *p;
|
|
p = (char *)(memLUTW[mem >> 12]);
|
|
if ((uptr)p > 0x10) {
|
|
#ifdef ENABLECACHE
|
|
if ((mem & 0x20000000) == 0 && (cpuRegs.CP0.r[16] & 0x10000))
|
|
{
|
|
writeCache32(mem, value);
|
|
return;
|
|
}
|
|
#endif
|
|
*(u32*)(p + (mem & 0xfff)) = value;
|
|
if (CHECK_EEREC) {
|
|
CHECK_VUMEM(1);
|
|
REC_CLEARM(mem);
|
|
// PSXREC_CLEARM(mem & 0x1fffff);
|
|
}
|
|
return;
|
|
}
|
|
|
|
switch ((int)(uptr)p) {
|
|
case 1: // hwm
|
|
hwWrite32(mem & ~0xa0000000, value);
|
|
return;
|
|
case 2: // psh
|
|
psxHwWrite32(mem & ~0xa0000000, value); return;
|
|
case 6: // gsm
|
|
gsWrite32(mem & ~0xa0000000, value); return;
|
|
case 7: // dev9
|
|
DEV9write32(mem & ~0xa4000000, value);
|
|
SysPrintf("DEV9 write32 %8.8lx: %8.8lx\n", mem & ~0xa4000000, value);
|
|
return;
|
|
}
|
|
#ifdef MEM_LOG
|
|
MEM_LOG("Unknown Memory write32 to address %x with data %8.8x\n", mem, value);
|
|
#endif
|
|
cpuTlbMissW(mem, cpuRegs.branch);
|
|
}
|
|
|
|
void memWrite64(u32 mem, u64 value) {
|
|
char *p;
|
|
|
|
p = (char *)(memLUTW[mem >> 12]);
|
|
if ((uptr)p > 0x10) {
|
|
#ifdef ENABLECACHE
|
|
if ((mem & 0x20000000) == 0 && (cpuRegs.CP0.r[16] & 0x10000)) {
|
|
writeCache64(mem, value);
|
|
return;
|
|
}
|
|
#endif
|
|
/* __asm __volatile (
|
|
"movq %1, %%mm0\n"
|
|
"movq %%mm0, %0\n"
|
|
"emms\n"
|
|
: "=m"(*(u64*)(p + (mem & 0xfff))) : "m"(value)
|
|
);*/
|
|
*(u64*)(p + (mem & 0xfff)) = value;
|
|
if (CHECK_EEREC) {
|
|
CHECK_VUMEM(2);
|
|
REC_CLEARM(mem);
|
|
REC_CLEARM(mem+4);
|
|
}
|
|
return;
|
|
}
|
|
|
|
|
|
switch ((int)(uptr)p) {
|
|
case 1: // hwm
|
|
hwWrite64(mem & ~0xa0000000, value);
|
|
return;
|
|
case 6: // gsm
|
|
gsWrite64(mem & ~0xa0000000, value); return;
|
|
}
|
|
|
|
#ifdef MEM_LOG
|
|
MEM_LOG("Unknown Memory write64 to address %x with data %8.8x_%8.8x\n", mem, (u32)(value>>32), (u32)value);
|
|
#endif
|
|
cpuTlbMissW(mem, cpuRegs.branch);
|
|
}
|
|
|
|
void memWrite128(u32 mem, u64 *value) {
|
|
char *p;
|
|
|
|
p = (char *)(memLUTW[mem >> 12]);
|
|
if ((uptr)p > 0x10) {
|
|
#ifdef ENABLECACHE
|
|
if ((mem & 0x20000000) == 0 && (cpuRegs.CP0.r[16] & 0x10000)) {
|
|
writeCache128(mem, value);
|
|
return;
|
|
}
|
|
#endif
|
|
p+= mem & 0xfff;
|
|
((u64*)p)[0] = value[0];
|
|
((u64*)p)[1] = value[1];
|
|
if (CHECK_EEREC) {
|
|
CHECK_VUMEM(4);
|
|
REC_CLEARM(mem);
|
|
REC_CLEARM(mem+4);
|
|
REC_CLEARM(mem+8);
|
|
REC_CLEARM(mem+12);
|
|
|
|
/* PSXREC_CLEARM((mem) & 0x1fffff);
|
|
PSXREC_CLEARM((mem+4) & 0x1fffff);
|
|
PSXREC_CLEARM((mem+8) & 0x1fffff);
|
|
PSXREC_CLEARM((mem+12) & 0x1fffff);*/
|
|
}
|
|
return;
|
|
}
|
|
|
|
switch ((int)(uptr)p) {
|
|
case 1: // hwm
|
|
hwWrite128(mem & ~0xa0000000, value);
|
|
return;
|
|
case 6: // gsm
|
|
mem &= ~0xa0000000;
|
|
gsWrite64(mem, value[0]);
|
|
gsWrite64(mem+8, value[1]); return;
|
|
}
|
|
|
|
#ifdef MEM_LOG
|
|
MEM_LOG("Unknown Memory write128 to address %x with data %8.8x_%8.8x_%8.8x_%8.8x\n", mem, ((u32*)value)[3], ((u32*)value)[2], ((u32*)value)[1], ((u32*)value)[0]);
|
|
#endif
|
|
cpuTlbMissW(mem, cpuRegs.branch);
|
|
}
|
|
|
|
|
|
#endif // PCSX2_VIRTUAL_MEM
|
|
|
|
void loadBiosRom(char *ext, u8 *dest) {
|
|
struct stat buf;
|
|
char Bios1[256];
|
|
char Bios[256];
|
|
FILE *fp;
|
|
char *ptr;
|
|
int i;
|
|
|
|
strcpy(Bios, Config.BiosDir);
|
|
strcat(Bios, Config.Bios);
|
|
|
|
sprintf(Bios1, "%s.%s", Bios, ext);
|
|
if (stat(Bios1, &buf) != -1) {
|
|
fp = fopen(Bios1, "rb");
|
|
fread(dest, 1, buf.st_size, fp);
|
|
fclose(fp);
|
|
return;
|
|
}
|
|
|
|
sprintf(Bios1, "%s", Bios);
|
|
ptr = Bios1; i = strlen(Bios1);
|
|
while (i > 0) { if (ptr[i] == '.') break; i--; }
|
|
ptr[i+1] = 0;
|
|
strcat(Bios1, ext);
|
|
if (stat(Bios1, &buf) != -1) {
|
|
fp = fopen(Bios1, "rb");
|
|
fread(dest, 1, buf.st_size, fp);
|
|
fclose(fp);
|
|
return;
|
|
}
|
|
|
|
sprintf(Bios1, "%s%s.bin", Config.BiosDir, ext);
|
|
if (stat(Bios1, &buf) != -1) {
|
|
fp = fopen(Bios1, "rb");
|
|
fread(dest, 1, buf.st_size, fp);
|
|
fclose(fp);
|
|
return;
|
|
}
|
|
SysPrintf("\n\n\n");
|
|
SysPrintf("**************\n");
|
|
SysPrintf("%s NOT FOUND\n", ext);
|
|
SysPrintf("**************\n\n\n");
|
|
}
|
|
|
|
void memReset() {
|
|
struct stat buf;
|
|
char Bios[256];
|
|
FILE *fp;
|
|
|
|
#ifdef PCSX2_VIRTUAL_MEM
|
|
DWORD OldProtect;
|
|
memset(PS2MEM_BASE, 0, 0x02000000);
|
|
memset(PS2MEM_SCRATCH, 0, 0x00004000);
|
|
#else
|
|
memset(psM, 0, 0x02000000);
|
|
memset(psS, 0, 0x00004000);
|
|
#endif
|
|
|
|
strcpy(Bios, Config.BiosDir);
|
|
strcat(Bios, Config.Bios);
|
|
|
|
if (stat(Bios, &buf) == -1) {
|
|
SysMessage(_("Unable to load bios: '%s', PCSX2 can't run without that"), Bios);
|
|
return;
|
|
}
|
|
|
|
#ifdef PCSX2_VIRTUAL_MEM
|
|
|
|
#ifdef _WIN32
|
|
// make sure can write
|
|
VirtualProtect(PS2MEM_ROM, 0x00400000, PAGE_READWRITE, &OldProtect);
|
|
VirtualProtect(PS2MEM_ROM1, 0x00040000, PAGE_READWRITE, &OldProtect);
|
|
VirtualProtect(PS2MEM_ROM2, 0x00080000, PAGE_READWRITE, &OldProtect);
|
|
VirtualProtect(PS2MEM_EROM, 0x001C0000, PAGE_READWRITE, &OldProtect);
|
|
#else
|
|
mprotect(PS2EMEM_ROM, 0x00400000, PROT_READ|PROT_WRITE);
|
|
mprotect(PS2EMEM_ROM1, 0x00400000, PROT_READ|PROT_WRITE);
|
|
mprotect(PS2EMEM_ROM2, 0x00800000, PROT_READ|PROT_WRITE);
|
|
mprotect(PS2EMEM_EROM, 0x001C0000, PROT_READ|PROT_WRITE);
|
|
#endif
|
|
|
|
#endif
|
|
|
|
fp = fopen(Bios, "rb");
|
|
fread(PS2MEM_ROM, 1, buf.st_size, fp);
|
|
fclose(fp);
|
|
|
|
BiosVersion = GetBiosVersion();
|
|
SysPrintf("Bios Version %d.%d\n", BiosVersion >> 8, BiosVersion & 0xff);
|
|
|
|
//injectIRX("host.irx"); //not fully tested; still buggy
|
|
|
|
// reset memLUT
|
|
|
|
loadBiosRom("rom1", PS2MEM_ROM1);
|
|
loadBiosRom("rom2", PS2MEM_ROM2);
|
|
loadBiosRom("erom", PS2MEM_EROM);
|
|
|
|
#ifdef PCSX2_VIRTUAL_MEM
|
|
|
|
#ifdef _WIN32
|
|
VirtualProtect(PS2MEM_ROM, 0x00400000, PAGE_READONLY, &OldProtect);
|
|
VirtualProtect(PS2MEM_ROM1, 0x00040000, PAGE_READONLY, &OldProtect);
|
|
VirtualProtect(PS2MEM_ROM2, 0x00080000, PAGE_READONLY, &OldProtect);
|
|
VirtualProtect(PS2MEM_EROM, 0x001C0000, PAGE_READONLY, &OldProtect);
|
|
#else
|
|
mprotect(PS2EMEM_ROM, 0x00400000, PROT_READ);
|
|
mprotect(PS2EMEM_ROM1, 0x00400000, PROT_READ);
|
|
mprotect(PS2EMEM_ROM2, 0x00800000, PROT_READ);
|
|
mprotect(PS2EMEM_EROM, 0x001C0000, PROT_READ);
|
|
#endif
|
|
|
|
#endif
|
|
}
|
|
|
|
void memSetKernelMode() {
|
|
#ifndef PCSX2_VIRTUAL_MEM
|
|
memLUTR = memLUTRK;
|
|
memLUTW = memLUTWK;
|
|
#endif
|
|
MemMode = 0;
|
|
}
|
|
|
|
void memSetSupervisorMode() {
|
|
}
|
|
|
|
void memSetUserMode() {
|
|
#ifdef FULLTLB
|
|
#ifndef PCSX2_VIRTUAL_MEM
|
|
memLUTR = memLUTRU;
|
|
memLUTW = memLUTWU;
|
|
#endif
|
|
MemMode = 2;
|
|
#endif
|
|
}
|
|
|