Improved EE/VTLB memory management: Removes various psM/psR/psS/psH pointers and replaces them with a single unified eeMem pointer. Members of eeMem correspond to Main, Scratchpad, Hardware, etc. This simplifies the EE's memory allocation, improves compiler optimization, gets rid of some macro mess, and allows templated code to deduce the size of memory buffers automatically.

* Includes a minor tweak to DMAC.h - removed tDMA_TADR / tDMA_MADR / etc. and replaced them with a single tDMAC_ADDR class.

git-svn-id: http://pcsx2.googlecode.com/svn/trunk@3644 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
Jake.Stine 2010-08-16 15:57:01 +00:00
parent 91851c6222
commit a8e406523b
40 changed files with 772 additions and 808 deletions

View File

@ -289,7 +289,7 @@ void EmitSibMagic( uint regfield, const xIndirectVoid& info )
int displacement_size = (info.Displacement == 0) ? 0 :
( ( info.IsByteSizeDisp() ) ? 1 : 2 );
assert(!info.Base.IsEmpty() || !info.Index.IsEmpty() || displacement_size == 2);
pxAssert(!info.Base.IsEmpty() || !info.Index.IsEmpty() || displacement_size == 2);
if( !NeedsSibMagic( info ) )
{

View File

@ -345,9 +345,7 @@ static __fi void _reloadElfInfo(wxString elfpath)
// Now's a good time to reload the ELF info...
ScopedLock locker( Mutex_NewDiskCB );
if (elfpath == LastELF)
return;
if (elfpath == LastELF) return;
LastELF = elfpath;
wxString fname = elfpath.AfterLast('\\');
@ -361,10 +359,8 @@ static __fi void _reloadElfInfo(wxString elfpath)
elfptr = loadElf(elfpath);
ElfCRC = elfptr->getCRC();
Console.WriteLn("ELF (%s) CRC = %8.8X", elfpath.ToUTF8().data(), ElfCRC);
ElfEntry = elfptr->header.e_entry;
Console.WriteLn("Entry point = 0x%08x", ElfEntry);
Console.WriteLn(L"ELF (%s) CRC=0x%08X, EntryPoint=0x%08X", elfpath.c_str(), ElfCRC, ElfEntry);
// Note: Do not load game database info here. This code is generic and called from
// BIOS key encryption as well as eeloadReplaceOSDSYS. The first is actually still executing
@ -424,39 +420,42 @@ static __fi s32 StrToS32(const wxString& str, int base = 10)
return l;
}
void cdvdReadKey(u8 arg0, u16 arg1, u32 arg2, u8* key)
void cdvdReadKey(u8, u16, u32 arg2, u8* key)
{
s32 numbers, letters;
s32 numbers=0, letters=0;
u32 key_0_3;
u8 key_4, key_14;
cdvdReloadElfInfo();
// convert the number characters to a real 32 bit number
numbers = StrToS32(DiscSerial(5,5));
// clear key values
memzero_ptr<16>(key);
// combine the lower 7 bits of each char
// to make the 4 letters fit into a single u32
letters = (s32)((DiscSerial[3]&0x7F)<< 0) |
(s32)((DiscSerial[2]&0x7F)<< 7) |
(s32)((DiscSerial[1]&0x7F)<<14) |
(s32)((DiscSerial[0]&0x7F)<<21);
if (!DiscSerial.IsEmpty())
{
// convert the number characters to a real 32 bit number
numbers = StrToS32(DiscSerial(5,5));
// combine the lower 7 bits of each char
// to make the 4 letters fit into a single u32
letters = (s32)((DiscSerial[3]&0x7F)<< 0) |
(s32)((DiscSerial[2]&0x7F)<< 7) |
(s32)((DiscSerial[1]&0x7F)<<14) |
(s32)((DiscSerial[0]&0x7F)<<21);
}
// calculate magic numbers
key_0_3 = ((numbers & 0x1FC00) >> 10) | ((0x01FFFFFF & letters) << 7); // numbers = 7F letters = FFFFFF80
key_4 = ((numbers & 0x0001F) << 3) | ((0x0E000000 & letters) >> 25); // numbers = F8 letters = 07
key_14 = ((numbers & 0x003E0) >> 2) | 0x04; // numbers = F8 extra = 04 unused = 03
// clear key values
memzero_ptr<16>(key);
// store key values
key[ 0] = (key_0_3&0x000000FF)>> 0;
key[ 1] = (key_0_3&0x0000FF00)>> 8;
key[ 2] = (key_0_3&0x00FF0000)>>16;
key[ 3] = (key_0_3&0xFF000000)>>24;
key[ 4] = key_4;
switch (arg2)
{
case 75:
@ -483,7 +482,7 @@ void cdvdReadKey(u8 arg0, u16 arg1, u32 arg2, u8* key)
break;
}
Console.WriteLn( "CDVD.KEY = %02X,%02X,%02X,%02X,%02X,%02X,%02X",
DevCon.WriteLn( "CDVD.KEY = %02X,%02X,%02X,%02X,%02X,%02X,%02X",
cdvd.Key[0],cdvd.Key[1],cdvd.Key[2],cdvd.Key[3],cdvd.Key[4],cdvd.Key[14],cdvd.Key[15] );
}

View File

@ -51,7 +51,7 @@ void MapTLB(int i)
if (tlb[i].S)
{
DevCon.WriteLn("OMG SPRAM MAPPING %08X %08X\n", tlb[i].VPN2,tlb[i].Mask);
vtlb_VMapBuffer(tlb[i].VPN2, psS, 0x4000);
vtlb_VMapBuffer(tlb[i].VPN2, eeMem->Scratch, 0x4000);
}
if (tlb[i].VPN2 == 0x70000000) return; //uh uhh right ...

View File

@ -465,8 +465,8 @@ TraceLogFilters& SetTraceConfig();
#define CHECK_MICROVU0 (EmuConfig.Cpu.Recompiler.UseMicroVU0)
#define CHECK_MICROVU1 (EmuConfig.Cpu.Recompiler.UseMicroVU1)
#define CHECK_EEREC (EmuConfig.Cpu.Recompiler.EnableEE && GetSysCoreAlloc().IsRecAvailable_EE())
#define CHECK_IOPREC (EmuConfig.Cpu.Recompiler.EnableIOP && GetSysCoreAlloc().IsRecAvailable_IOP())
#define CHECK_EEREC (EmuConfig.Cpu.Recompiler.EnableEE && GetCpuProviders().IsRecAvailable_EE())
#define CHECK_IOPREC (EmuConfig.Cpu.Recompiler.EnableIOP && GetCpuProviders().IsRecAvailable_IOP())
//------------ SPECIAL GAME FIXES!!! ---------------
#define CHECK_VUADDSUBHACK (EmuConfig.Gamefixes.VuAddSubHack) // Special Fix for Tri-ace games, they use an encryption algorithm that requires VU addi opcode to be bit-accurate.

View File

@ -15,8 +15,6 @@
#pragma once
extern u8 *psH; // hw mem
// Useful enums for some of the fields.
enum pce_values
{
@ -156,65 +154,23 @@ union tDMA_SADR {
void reset() { _u32 = 0; }
wxString desc() const { return wxsFormat(L"Sadr: 0x%x", _u32); }
tDMA_TAG tag() { return (tDMA_TAG)_u32; }
};
union tDMA_MADR {
struct {
u32 ADDR : 31; // Transfer memory address
u32 SPR : 1; // Memory/SPR Address
};
u32 _u32;
tDMA_MADR(u32 val) { _u32 = val; }
void reset() { _u32 = 0; }
wxString desc() const { return wxsFormat(L"Madr: 0x%x", _u32); }
tDMA_TAG tag() { return (tDMA_TAG)_u32; }
};
union tDMA_TADR {
struct {
u32 ADDR : 31; // Next Tag address
u32 SPR : 1; // Memory/SPR Address
};
u32 _u32;
tDMA_TADR(u32 val) { _u32 = val; }
void reset() { _u32 = 0; }
wxString desc() const { return wxsFormat(L"Tadr: 0x%x", _u32); }
tDMA_TAG tag() { return (tDMA_TAG)_u32; }
};
// The Address Stack Register
union tDMA_ASR {
struct {
u32 ADDR : 31; // Tag memory address
u32 SPR : 1; // Memory/SPR Address
};
u32 _u32;
tDMA_ASR(u32 val) { _u32 = val; }
void reset() { _u32 = 0; }
wxString desc() const { return wxsFormat(L"Asr: 0x%x", _u32); }
tDMA_TAG tag() { return (tDMA_TAG)_u32; }
tDMA_TAG tag() const { return (tDMA_TAG)_u32; }
};
union tDMA_QWC {
struct {
u32 QWC : 16;
u32 _reserved2 : 16;
u16 QWC;
u16 _unused;
};
u32 _u32;
tDMA_QWC(u32 val) { _u32 = val; }
void reset() { _u32 = 0; }
wxString desc() const { return wxsFormat(L"QWC: 0x%x", _u32); }
tDMA_TAG tag() { return (tDMA_TAG)_u32; }
wxString desc() const { return wxsFormat(L"QWC: 0x%04x", QWC); }
tDMA_TAG tag() const { return (tDMA_TAG)_u32; }
};
static void setDmacStat(u32 num);
static tDMA_TAG *dmaGetAddr(u32 addr, bool write);
static void throwBusError(const char *s);
@ -450,10 +406,7 @@ union tDMAC_STAT {
u32 _reserved3 : 1;
};
u32 _u32;
struct {
u16 _u16lo;
u16 _u16hi;
};
u16 _u16[2];
tDMAC_STAT(u32 val) { _u32 = val; }
@ -465,7 +418,7 @@ union tDMAC_STAT {
bool TestForInterrupt() const
{
return ((_u16lo & _u16hi) != 0) || BEIS;
return ((_u16[0] & _u16[1]) != 0) || BEIS;
}
};
@ -532,20 +485,49 @@ union tDMAC_RBOR {
wxString desc() const { return wxsFormat(L"Rbor: 0x%x", _u32); }
};
union tDMAC_STADR {
// --------------------------------------------------------------------------------------
// tDMAC_ADDR
// --------------------------------------------------------------------------------------
// This struct is used for several DMA address types, including some that do not have
// effective SPR bit (the bit is ignored for all addresses that are not "allowed" to access
// the scratchpad, including STADR, toSPR.MADR, fromSPR.MADR, etc.).
//
union tDMAC_ADDR
{
struct {
u32 ADDR : 31;
u32 reserved1 : 1;
u32 ADDR : 31; // Transfer memory address
u32 SPR : 1; // Memory/SPR Address (only effective for MADR and TADR of non-SPR DMAs)
};
u32 _u32;
tDMAC_STADR(u32 val) { _u32 = val; }
tDMAC_ADDR() {}
tDMAC_ADDR(u32 val) { _u32 = val; }
void reset() { _u32 = 0; }
wxString desc() const { return wxsFormat(L"Stadr: 0x%x", _u32); }
void clear() { _u32 = 0; }
void AssignADDR(uint addr)
{
ADDR = addr;
if (SPR) ADDR &= (Ps2MemSize::Scratch-1);
}
void IncrementQWC(uint incval = 1)
{
ADDR += incval;
if (SPR) ADDR &= (Ps2MemSize::Scratch-1);
}
wxString ToString(bool sprIsValid=true) const
{
return pxsFmt((sprIsValid && SPR) ? L"0x%04X(SPR)" : L"0x%08X", ADDR);
}
wxCharBuffer ToUTF8(bool sprIsValid=true) const
{
return FastFormatAscii().Write((sprIsValid && SPR) ? "0x%04X(SPR)" : "0x%08X", ADDR).GetResult();
}
};
struct DMACregisters
{
tDMAC_CTRL ctrl;
@ -561,7 +543,8 @@ struct DMACregisters
u32 _padding4[3];
tDMAC_RBOR rbor;
u32 _padding5[3];
tDMAC_STADR stadr;
tDMAC_ADDR stadr;
u32 _padding6[3];
};
// Currently guesswork.
@ -600,12 +583,13 @@ union tINTC_MASK {
struct INTCregisters
{
tINTC_STAT stat;
u32 _padding[3];
u32 _padding1[3];
tINTC_MASK mask;
u32 _padding2[3];
};
#define dmacRegs ((DMACregisters*)(PS2MEM_HW+0xE000))
#define intcRegs ((INTCregisters*)(PS2MEM_HW+0xF000))
#define dmacRegs ((DMACregisters*)(eeMem->HW+0xE000))
#define intcRegs ((INTCregisters*)(eeMem->HW+0xF000))
static __fi void throwBusError(const char *s)
{
@ -626,7 +610,7 @@ static __fi tDMA_TAG *SPRdmaGetAddr(u32 addr, bool write)
//For some reason Getaway references SPR Memory from itself using SPR0, oh well, let it i guess...
if((addr & 0x70000000) == 0x70000000)
{
return (tDMA_TAG*)&psS[addr & 0x3ff0];
return (tDMA_TAG*)&eeMem->Scratch[addr & 0x3ff0];
}
// FIXME: Why??? DMA uses physical addresses
@ -634,11 +618,11 @@ static __fi tDMA_TAG *SPRdmaGetAddr(u32 addr, bool write)
if (addr < Ps2MemSize::Base)
{
return (tDMA_TAG*)&psM[addr];
return (tDMA_TAG*)&eeMem->Main[addr];
}
else if (addr < 0x10000000)
{
return (tDMA_TAG*)(write ? psMHW : psMHR);
return (tDMA_TAG*)(write ? eeMem->ZeroWrite : eeMem->ZeroRead);
}
else if ((addr >= 0x11004000) && (addr < 0x11010000))
{
@ -656,24 +640,24 @@ static __fi tDMA_TAG *SPRdmaGetAddr(u32 addr, bool write)
static __ri tDMA_TAG *dmaGetAddr(u32 addr, bool write)
{
// if (addr & 0xf) { DMA_LOG("*PCSX2*: DMA address not 128bit aligned: %8.8x", addr); }
if (DMA_TAG(addr).SPR) return (tDMA_TAG*)&psS[addr & 0x3ff0];
if (DMA_TAG(addr).SPR) return (tDMA_TAG*)&eeMem->Scratch[addr & 0x3ff0];
// FIXME: Why??? DMA uses physical addresses
addr &= 0x1ffffff0;
if (addr < Ps2MemSize::Base)
{
return (tDMA_TAG*)&psM[addr];
return (tDMA_TAG*)&eeMem->Main[addr];
}
else if (addr < 0x10000000)
{
return (tDMA_TAG*)(write ? psMHW : psMHR);
return (tDMA_TAG*)(write ? eeMem->ZeroWrite : eeMem->ZeroRead);
}
else if (addr < 0x10004000)
{
// Secret scratchpad address for DMA = end of maximum main memory?
//Console.Warning("Writing to the scratchpad without the SPR flag set!");
return (tDMA_TAG*)&psS[addr & 0x3ff0];
return (tDMA_TAG*)&eeMem->Scratch[addr & 0x3ff0];
}
else
{

View File

@ -129,7 +129,7 @@ void iDumpRegisters(u32 startpc, u32 temp)
__Log("gif: %x %x %x", psHu32(0x3000), psHu32(0x3010), psHu32(0x3020));
for(i = 0; i < ArraySize(dmacs); ++i) {
DMACh* p = (DMACh*)(PS2MEM_HW+dmacs[i]);
DMACh* p = (DMACh*)(&eeMem->HW[dmacs[i]]);
__Log("dma%d c%x m%x q%x t%x s%x", i, p->chcr._u32, p->madr, p->qwc, p->tadr, p->sadr);
}
__Log(L"dmac " + dmacRegs->ctrl.desc() + L" " + dmacRegs->stat.desc() + L" " + dmacRegs->rbsr.desc() + L" " + dmacRegs->rbor.desc());

View File

@ -37,7 +37,7 @@ uptr args_ptr; //a big value; in fact, it is an address
static bool isEmpty(int addr)
{
return ((PS2MEM_BASE[addr] == 0) || (PS2MEM_BASE[addr] == 32));
return ((eeMem->Main[addr] == 0) || (eeMem->Main[addr] == 32));
}
//in a0 is passed the address of the command line args,
@ -70,8 +70,8 @@ static uint parseCommandLine( const wxString& filename )
// Copy the parameters into the section of memory at args_ptr,
// then zero out anything past the end of args till 256 chars is reached.
memcpy( &PS2MEM_BASE[ args_ptr ], args, 256 );
memset( &PS2MEM_BASE[ args_ptr + strlen( args ) ], 0, 256 - strlen( args ) );
memcpy( &eeMem->Main[ args_ptr ], args, 256 );
memset( &eeMem->Main[ args_ptr + strlen( args ) ], 0, 256 - strlen( args ) );
args_end = args_ptr + strlen( args );
// Set p to just the filename, no path.
@ -90,7 +90,7 @@ static uint parseCommandLine( const wxString& filename )
args_ptr -= strlen( p ) + 1;
//fill param 0; i.e. name of the program
strcpy( (char*)&PS2MEM_BASE[ args_ptr ], p );
strcpy( (char*)&eeMem->Main[ args_ptr ], p );
// Start from the end of where we wrote to, not including all the zero'd out area.
for ( i = args_end - args_ptr + 1, argc = 0; i > 0; i-- )
@ -98,7 +98,7 @@ static uint parseCommandLine( const wxString& filename )
while (i && isEmpty(args_ptr + i )) { i--; }
// If the last char is a space, set it to 0.
if ( PS2MEM_BASE[ args_ptr + i + 1 ] == ' ') PS2MEM_BASE[ args_ptr + i + 1 ] = 0;
if ( eeMem->Main[ args_ptr + i + 1 ] == ' ') eeMem->Main[ args_ptr + i + 1 ] = 0;
while (i && !isEmpty(args_ptr + i )) { i--; }
@ -111,7 +111,7 @@ static uint parseCommandLine( const wxString& filename )
ret = args_ptr - 4 - 4 - argc * 4;
if (ret < 0 ) return 0;
((u32*)PS2MEM_BASE)[ args_ptr / 4 - argc ] = args_ptr + i;
((u32*)eeMem->Main)[ args_ptr / 4 - argc ] = args_ptr + i;
}
else
{
@ -122,14 +122,14 @@ static uint parseCommandLine( const wxString& filename )
ret = args_ptr - 4 - 4 - argc * 4;
if (ret < 0 ) return 0;
((u32*)PS2MEM_BASE)[ args_ptr / 4 - argc ] = args_ptr + i + 1;
((u32*)eeMem->Main)[ args_ptr / 4 - argc ] = args_ptr + i + 1;
}
}
}
// Pass the number of arguments, and if we have arguments.
((u32*)PS2MEM_BASE)[ args_ptr /4 - argc - 1 ] = argc; //how many args
((u32*)PS2MEM_BASE)[ args_ptr /4 - argc - 2 ] = ( argc > 0); //have args? //not used, cannot be filled at all
((u32*)eeMem->Main)[ args_ptr /4 - argc - 1 ] = argc; //how many args
((u32*)eeMem->Main)[ args_ptr /4 - argc - 2 ] = ( argc > 0); //have args? //not used, cannot be filled at all
return ret;
}
@ -318,7 +318,7 @@ void ElfObject::loadProgramHeaders()
// used to be paddr
memcpy_fast(
&PS2MEM_BASE[proghead[ i ].p_vaddr & 0x1ffffff],
&eeMem->Main[proghead[ i ].p_vaddr & 0x1ffffff],
data.GetPtr(proghead[ i ].p_offset), size
);
@ -431,7 +431,6 @@ int GetPS2ElfName( wxString& name )
int size = file.getLength();
if( size == 0 ) return 0;
while( !file.eof() )
{
const wxString original( fromUTF8(file.readLine().c_str()) );

View File

@ -277,7 +277,7 @@ struct GIFregisters
u32 padding9[3];
};
#define gifRegs ((GIFregisters*)(PS2MEM_HW+0x3000))
#define gifRegs ((GIFregisters*)(eeMem->HW+0x3000))
extern tGSTransferStatus GSTransferStatus;

View File

@ -21,8 +21,6 @@
using namespace R5900;
u8 *psH; // hw mem
const int rdram_devices = 2; // put 8 for TOOL and 2 for PS2 and PSX
int rdram_sdevid = 0;
@ -56,8 +54,8 @@ void hwReset()
{
hwInit();
memzero_ptr<Ps2MemSize::Hardware>( PS2MEM_HW );
//memset(PS2MEM_HW+0x2000, 0, 0x0000e000);
memzero_ptr<Ps2MemSize::Hardware>( eeMem->HW );
//memset(eeMem->HW+0x2000, 0, 0x0000e000);
psHu32(SBUS_F260) = 0x1D000060;

View File

@ -20,11 +20,11 @@
//////////////////////////////////////////////////////////////////////////
// Hardware FIFOs (128 bit access only!)
//
// VIF0 -- 0x10004000 -- PS2MEM_HW[0x4000]
// VIF1 -- 0x10005000 -- PS2MEM_HW[0x5000]
// GIF -- 0x10006000 -- PS2MEM_HW[0x6000]
// IPUout -- 0x10007000 -- PS2MEM_HW[0x7000]
// IPUin -- 0x10007010 -- PS2MEM_HW[0x7010]
// VIF0 -- 0x10004000 -- eeMem->HW[0x4000]
// VIF1 -- 0x10005000 -- eeMem->HW[0x5000]
// GIF -- 0x10006000 -- eeMem->HW[0x6000]
// IPUout -- 0x10007000 -- eeMem->HW[0x7000]
// IPUin -- 0x10007010 -- eeMem->HW[0x7010]
void __fastcall ReadFIFO_page_4(u32 mem, mem128_t *out);
void __fastcall ReadFIFO_page_5(u32 mem, mem128_t *out);

View File

@ -270,7 +270,7 @@ mem32_t __fastcall hwRead32_page_00(u32 mem)
case 0x830: return (u16)counters[1].hold;
}
return *((u32*)&PS2MEM_HW[mem]);
return *((u32*)&eeMem->HW[mem]);
}
// Reads hardware registers for page 1 (counters 2 and 3)
@ -288,7 +288,7 @@ mem32_t __fastcall hwRead32_page_01(u32 mem)
case 0x1820: return (u16)counters[3].target;
}
return *((u32*)&PS2MEM_HW[mem]);
return *((u32*)&eeMem->HW[mem]);
}
// Reads hardware registers for page 15 (0x0F).
@ -309,7 +309,7 @@ static __fi mem32_t __hwRead32_page_0F( u32 mem, bool intchack )
if( mem == ics ) // INTC_STAT
{
if( intchack ) IntCHackCheck();
return *((u32*)&PS2MEM_HW[ics]);
return *((u32*)&eeMem->HW[ics]);
}
switch( mem )
@ -355,7 +355,7 @@ static __fi mem32_t __hwRead32_page_0F( u32 mem, bool intchack )
}
return 0;
}
return *((u32*)&PS2MEM_HW[mem]);
return *((u32*)&eeMem->HW[mem]);
}
mem32_t __fastcall hwRead32_page_0F(u32 mem)
@ -435,7 +435,7 @@ mem32_t __fastcall hwRead32_generic(u32 mem)
jNO_DEFAULT;
}
return *((u32*)&PS2MEM_HW[masked_mem]);
return *((u32*)&eeMem->HW[masked_mem]);
}
/////////////////////////////////////////////////////////////////////////

View File

@ -750,7 +750,7 @@ void __fastcall hwWrite32_page_00( u32 mem, u32 value )
case 0x830: rcntWhold(1, value); return;
}
*((u32*)&PS2MEM_HW[mem]) = value;
*((u32*)&eeMem->HW[mem]) = value;
}
// Page 1 of HW memory houses registers for Counters 2 and 3
@ -768,7 +768,7 @@ void __fastcall hwWrite32_page_01( u32 mem, u32 value )
case 0x1820: rcntWtarget(3, value); return;
}
*((u32*)&PS2MEM_HW[mem]) = value;
*((u32*)&eeMem->HW[mem]) = value;
}
// page 2 is the IPU register space!

View File

@ -245,7 +245,7 @@ struct IPUregisters {
u32 dummy3[2];
};
#define ipuRegs ((IPUregisters*)(PS2MEM_HW+0x2000))
#define ipuRegs ((IPUregisters*)(&eeMem->HW[0x2000]))
struct tIPU_cmd
{

View File

@ -87,12 +87,12 @@ void psxMemReset()
// Read-only memory areas, so don't map WLUT for these...
for (int i=0; i<0x0040; i++)
{
psxMemWLUT[i + 0x2000 + 0x1fc0] = (uptr)&PS2MEM_ROM[i << 16];
psxMemWLUT[i + 0x2000 + 0x1fc0] = (uptr)&eeMem->ROM[i << 16];
}
for (int i=0; i<0x0004; i++)
{
psxMemWLUT[i + 0x2000 + 0x1e00] = (uptr)&PS2MEM_ROM1[i << 16];
psxMemWLUT[i + 0x2000 + 0x1e00] = (uptr)&eeMem->ROM1[i << 16];
}
// sif!! (which is read only? (air))
@ -468,7 +468,7 @@ void __fastcall iopMemWrite32(u32 mem, u32 value)
// wtf? why were we writing to the EE's sif space? Commenting this out doesn't
// break any of my games, and should be more correct, but I guess we'll see. --air
//*(u32*)(PS2MEM_HW+0xf200+(mem&0xf0)) = value;
//*(u32*)(eeMem->HW+0xf200+(mem&0xf0)) = value;
return;
}
else if (t == 0x1000)

View File

@ -77,23 +77,6 @@ u16 ba0R16(u32 mem)
return 0;
}
u8 *psM = NULL; //32mb Main Ram
u8 *psR = NULL; //4mb rom area
u8 *psR1 = NULL; //256kb rom1 area (actually 196kb, but can't mask this)
u8 *psR2 = NULL; // 0x00080000
u8 *psER = NULL; // 0x001C0000
u8 *psS = NULL; //0.015 mb, scratch pad
// Two 1 megabyte (max DMA) buffers for reading and writing to high memory (>32MB).
// Such accesses are not documented as causing bus errors but as the memory does
// not exist, reads should continue to return 0 and writes should be discarded.
// Probably.
static __aligned16 u8 highmem[0x200000];
u8 *psMHR = &highmem[0];
u8 *psMHW = &highmem[0x100000];
#define CHECK_MEM(mem) //MyMemCheck(mem)
void MyMemCheck(u32 mem)
@ -155,15 +138,15 @@ void memMapVUmicro()
void memMapPhy()
{
// Main memory
vtlb_MapBlock(psM, 0x00000000,Ps2MemSize::Base);//mirrored on first 256 mb ?
vtlb_MapBlock(eeMem->Main, 0x00000000,Ps2MemSize::Base);//mirrored on first 256 mb ?
// High memory, uninstalled on the configuration we emulate
vtlb_MapHandler(null_handler, Ps2MemSize::Base, 0x10000000 - Ps2MemSize::Base);
// Various ROMs (all read-only)
vtlb_MapBlock(psR, 0x1fc00000,Ps2MemSize::Rom);
vtlb_MapBlock(psR1, 0x1e000000,Ps2MemSize::Rom1);
vtlb_MapBlock(psR2, 0x1e400000,Ps2MemSize::Rom2);
vtlb_MapBlock(psER, 0x1e040000,Ps2MemSize::ERom);
vtlb_MapBlock(eeMem->ROM, 0x1fc00000,Ps2MemSize::Rom);
vtlb_MapBlock(eeMem->ROM1, 0x1e000000,Ps2MemSize::Rom1);
vtlb_MapBlock(eeMem->ROM2, 0x1e400000,Ps2MemSize::Rom2);
vtlb_MapBlock(eeMem->EROM, 0x1e040000,Ps2MemSize::ERom);
// IOP memory
// (used by the EE Bios Kernel during initial hardware initialization, Apps/Games
@ -621,29 +604,16 @@ protected:
mmap_PageFaultHandler mmap_faultHandler;
static const uint m_allMemSize =
Ps2MemSize::Rom + Ps2MemSize::Rom1 + Ps2MemSize::Rom2 + Ps2MemSize::ERom +
Ps2MemSize::Base + Ps2MemSize::Hardware + Ps2MemSize::Scratch;
static u8* m_psAllMem = NULL;
EEVM_MemoryAllocMess* eeMem = NULL;
void memAlloc()
{
if( m_psAllMem == NULL )
m_psAllMem = vtlb_malloc( m_allMemSize, 4096 );
if( eeMem == NULL )
eeMem = (EEVM_MemoryAllocMess*)vtlb_malloc( sizeof(*eeMem), 4096 );
if( m_psAllMem == NULL)
if( eeMem == NULL)
throw Exception::OutOfMemory( L"memAlloc > failed to allocate PS2's base ram/rom/scratchpad." );
u8* curpos = m_psAllMem;
psM = curpos; curpos += Ps2MemSize::Base;
psR = curpos; curpos += Ps2MemSize::Rom;
psR1 = curpos; curpos += Ps2MemSize::Rom1;
psR2 = curpos; curpos += Ps2MemSize::Rom2;
psER = curpos; curpos += Ps2MemSize::ERom;
psH = curpos; curpos += Ps2MemSize::Hardware;
psS = curpos; //curpos += Ps2MemSize::Scratch;
Source_PageFault.Add( mmap_faultHandler );
}
@ -651,9 +621,8 @@ void memShutdown()
{
Source_PageFault.Remove( mmap_faultHandler );
vtlb_free( m_psAllMem, m_allMemSize );
m_psAllMem = NULL;
psM = psR = psR1 = psR2 = psER = psS = psH = NULL;
vtlb_free( eeMem, sizeof(*eeMem) );
eeMem = NULL;
vtlb_Term();
}
@ -681,7 +650,7 @@ void memReset()
// rest of the emu is not really set up to support a "soft" reset of that sort
// we opt for the hard/safe version.
memzero_ptr<m_allMemSize>( m_psAllMem );
memzero( *eeMem );
#ifdef ENABLECACHE
memset(pCache,0,sizeof(_cacheS)*64);
#endif
@ -890,7 +859,7 @@ int mmap_GetRamPageInfo( u32 paddr )
paddr &= ~0xfff;
uptr ptr = (uptr)PSM( paddr );
uptr rampage = ptr - (uptr)psM;
uptr rampage = ptr - (uptr)eeMem->Main;
if (rampage >= Ps2MemSize::Base)
return -1; //not in ram, no tracking done ...
@ -905,7 +874,7 @@ void mmap_MarkCountedRamPage( u32 paddr )
paddr &= ~0xfff;
uptr ptr = (uptr)PSM( paddr );
int rampage = (ptr - (uptr)psM) >> 12;
int rampage = (ptr - (uptr)eeMem->Main) >> 12;
// Important: reassign paddr here, since TLB changes could alter the paddr->psM mapping
// (and clear blocks accordingly), but don't necessarily clear the protection status.
@ -920,7 +889,7 @@ void mmap_MarkCountedRamPage( u32 paddr )
);
m_PageProtectInfo[rampage].Mode = ProtMode_Write;
HostSys::MemProtect( &psM[rampage<<12], __pagesize, Protect_ReadOnly );
HostSys::MemProtect( &eeMem->Main[rampage<<12], __pagesize, Protect_ReadOnly );
}
// offset - offset of address relative to psM.
@ -935,7 +904,7 @@ static __fi void mmap_ClearCpuBlock( uint offset )
pxAssertMsg( m_PageProtectInfo[rampage].Mode != ProtMode_Manual,
"Attempted to clear a block that is already under manual protection." );
HostSys::MemProtect( &psM[rampage<<12], __pagesize, Protect_ReadWrite );
HostSys::MemProtect( &eeMem->Main[rampage<<12], __pagesize, Protect_ReadWrite );
m_PageProtectInfo[rampage].Mode = ProtMode_Manual;
Cpu->Clear( m_PageProtectInfo[rampage].ReverseRamMap, 0x400 );
}
@ -943,7 +912,7 @@ static __fi void mmap_ClearCpuBlock( uint offset )
void mmap_PageFaultHandler::OnPageFaultEvent( const PageFaultInfo& info, bool& handled )
{
// get bad virtual address
uptr offset = info.addr - (uptr)psM;
uptr offset = info.addr - (uptr)eeMem->Main;
if( offset >= Ps2MemSize::Base ) return;
mmap_ClearCpuBlock( offset );
@ -958,5 +927,5 @@ void mmap_ResetBlockTracking()
{
//DbgCon.WriteLn( "vtlb/mmap: Block Tracking reset..." );
memzero( m_PageProtectInfo );
HostSys::MemProtect( psM, Ps2MemSize::Base, Protect_ReadWrite );
HostSys::MemProtect( eeMem->Main, Ps2MemSize::Base, Protect_ReadWrite );
}

View File

@ -20,7 +20,6 @@
#endif
//#define ENABLECACHE
#include "MemoryTypes.h"
#include "vtlb.h"
#include <xmmintrin.h>
@ -35,106 +34,88 @@ static __fi void ZeroQWC( void* dest )
_mm_store_ps( (float*)dest, _mm_setzero_ps() );
}
extern u8 *psM; //32mb Main Ram
extern u8 *psR; //4mb rom area
extern u8 *psR1; //256kb rom1 area (actually 196kb, but can't mask this)
extern u8 *psR2; // 0x00080000
extern u8 *psER; // 0x001C0000
extern u8 *psS; //0.015 mb, scratch pad
// separate buffers implementing write only high memory for DMA
extern u8 *psMHR;
extern u8 *psMHW;
#define PS2MEM_BASE psM
#define PS2MEM_HW psH
#define PS2MEM_ROM psR
#define PS2MEM_ROM1 psR1
#define PS2MEM_ROM2 psR2
#define PS2MEM_EROM psER
#define PS2MEM_SCRATCH psS
// Various useful locations
#define spr0 ((DMACh*)&PS2MEM_HW[0xD000])
#define spr1 ((DMACh*)&PS2MEM_HW[0xD400])
#define spr0 ((DMACh*)&eeMem->HW[0xD000])
#define spr1 ((DMACh*)&eeMem->HW[0xD400])
#define gif ((DMACh*)&PS2MEM_HW[0xA000])
#define gif ((DMACh*)&eeMem->HW[0xA000])
#define vif0ch ((DMACh*)&PS2MEM_HW[0x8000])
#define vif1ch ((DMACh*)&PS2MEM_HW[0x9000])
#define vif0ch ((DMACh*)&eeMem->HW[0x8000])
#define vif1ch ((DMACh*)&eeMem->HW[0x9000])
#define sif0dma ((DMACh*)&PS2MEM_HW[0xc000])
#define sif1dma ((DMACh*)&PS2MEM_HW[0xc400])
#define sif2dma ((DMACh*)&PS2MEM_HW[0xc800])
#define sif0dma ((DMACh*)&eeMem->HW[0xc000])
#define sif1dma ((DMACh*)&eeMem->HW[0xc400])
#define sif2dma ((DMACh*)&eeMem->HW[0xc800])
#define ipu0dma ((DMACh *)&PS2MEM_HW[0xb000])
#define ipu1dma ((DMACh *)&PS2MEM_HW[0xb400])
#define ipu0dma ((DMACh *)&eeMem->HW[0xb000])
#define ipu1dma ((DMACh *)&eeMem->HW[0xb400])
#define PSM(mem) (vtlb_GetPhyPtr((mem)&0x1fffffff)) //pcsx2 is a competition.The one with most hacks wins :D
#define psHs8(mem) (*(s8 *)&PS2MEM_HW[(mem) & 0xffff])
#define psHs16(mem) (*(s16*)&PS2MEM_HW[(mem) & 0xffff])
#define psHs32(mem) (*(s32*)&PS2MEM_HW[(mem) & 0xffff])
#define psHs64(mem) (*(s64*)&PS2MEM_HW[(mem) & 0xffff])
#define psHu8(mem) (*(u8 *)&PS2MEM_HW[(mem) & 0xffff])
#define psHu16(mem) (*(u16*)&PS2MEM_HW[(mem) & 0xffff])
#define psHu32(mem) (*(u32*)&PS2MEM_HW[(mem) & 0xffff])
#define psHu64(mem) (*(u64*)&PS2MEM_HW[(mem) & 0xffff])
#define psHu128(mem)(*(u128*)&PS2MEM_HW[(mem) & 0xffff])
#define psHs8(mem) (*(s8 *)&eeMem->HW[(mem) & 0xffff])
#define psHs16(mem) (*(s16*)&eeMem->HW[(mem) & 0xffff])
#define psHs32(mem) (*(s32*)&eeMem->HW[(mem) & 0xffff])
#define psHs64(mem) (*(s64*)&eeMem->HW[(mem) & 0xffff])
#define psHu8(mem) (*(u8 *)&eeMem->HW[(mem) & 0xffff])
#define psHu16(mem) (*(u16*)&eeMem->HW[(mem) & 0xffff])
#define psHu32(mem) (*(u32*)&eeMem->HW[(mem) & 0xffff])
#define psHu64(mem) (*(u64*)&eeMem->HW[(mem) & 0xffff])
#define psHu128(mem)(*(u128*)&eeMem->HW[(mem) & 0xffff])
#define psMs8(mem) (*(s8 *)&PS2MEM_BASE[(mem) & 0x1ffffff])
#define psMs16(mem) (*(s16*)&PS2MEM_BASE[(mem) & 0x1ffffff])
#define psMs32(mem) (*(s32*)&PS2MEM_BASE[(mem) & 0x1ffffff])
#define psMs64(mem) (*(s64*)&PS2MEM_BASE[(mem) & 0x1ffffff])
#define psMu8(mem) (*(u8 *)&PS2MEM_BASE[(mem) & 0x1ffffff])
#define psMu16(mem) (*(u16*)&PS2MEM_BASE[(mem) & 0x1ffffff])
#define psMu32(mem) (*(u32*)&PS2MEM_BASE[(mem) & 0x1ffffff])
#define psMu64(mem) (*(u64*)&PS2MEM_BASE[(mem) & 0x1ffffff])
#define psMs8(mem) (*(s8 *)&eeMem->Main[(mem) & 0x1ffffff])
#define psMs16(mem) (*(s16*)&eeMem->Main[(mem) & 0x1ffffff])
#define psMs32(mem) (*(s32*)&eeMem->Main[(mem) & 0x1ffffff])
#define psMs64(mem) (*(s64*)&eeMem->Main[(mem) & 0x1ffffff])
#define psMu8(mem) (*(u8 *)&eeMem->Main[(mem) & 0x1ffffff])
#define psMu16(mem) (*(u16*)&eeMem->Main[(mem) & 0x1ffffff])
#define psMu32(mem) (*(u32*)&eeMem->Main[(mem) & 0x1ffffff])
#define psMu64(mem) (*(u64*)&eeMem->Main[(mem) & 0x1ffffff])
#define psRs8(mem) (*(s8 *)&PS2MEM_ROM[(mem) & 0x3fffff])
#define psRs16(mem) (*(s16*)&PS2MEM_ROM[(mem) & 0x3fffff])
#define psRs32(mem) (*(s32*)&PS2MEM_ROM[(mem) & 0x3fffff])
#define psRs64(mem) (*(s64*)&PS2MEM_ROM[(mem) & 0x3fffff])
#define psRu8(mem) (*(u8 *)&PS2MEM_ROM[(mem) & 0x3fffff])
#define psRu16(mem) (*(u16*)&PS2MEM_ROM[(mem) & 0x3fffff])
#define psRu32(mem) (*(u32*)&PS2MEM_ROM[(mem) & 0x3fffff])
#define psRu64(mem) (*(u64*)&PS2MEM_ROM[(mem) & 0x3fffff])
#define psRs8(mem) (*(s8 *)&eeMem->ROM[(mem) & 0x3fffff])
#define psRs16(mem) (*(s16*)&eeMem->ROM[(mem) & 0x3fffff])
#define psRs32(mem) (*(s32*)&eeMem->ROM[(mem) & 0x3fffff])
#define psRs64(mem) (*(s64*)&eeMem->ROM[(mem) & 0x3fffff])
#define psRu8(mem) (*(u8 *)&eeMem->ROM[(mem) & 0x3fffff])
#define psRu16(mem) (*(u16*)&eeMem->ROM[(mem) & 0x3fffff])
#define psRu32(mem) (*(u32*)&eeMem->ROM[(mem) & 0x3fffff])
#define psRu64(mem) (*(u64*)&eeMem->ROM[(mem) & 0x3fffff])
#define psR1s8(mem) (*(s8 *)&PS2MEM_ROM1[(mem) & 0x3ffff])
#define psR1s16(mem) (*(s16*)&PS2MEM_ROM1[(mem) & 0x3ffff])
#define psR1s32(mem) (*(s32*)&PS2MEM_ROM1[(mem) & 0x3ffff])
#define psR1s64(mem) (*(s64*)&PS2MEM_ROM1[(mem) & 0x3ffff])
#define psR1u8(mem) (*(u8 *)&PS2MEM_ROM1[(mem) & 0x3ffff])
#define psR1u16(mem) (*(u16*)&PS2MEM_ROM1[(mem) & 0x3ffff])
#define psR1u32(mem) (*(u32*)&PS2MEM_ROM1[(mem) & 0x3ffff])
#define psR1u64(mem) (*(u64*)&PS2MEM_ROM1[(mem) & 0x3ffff])
#define psR1s8(mem) (*(s8 *)&eeMem->ROM1[(mem) & 0x3ffff])
#define psR1s16(mem) (*(s16*)&eeMem->ROM1[(mem) & 0x3ffff])
#define psR1s32(mem) (*(s32*)&eeMem->ROM1[(mem) & 0x3ffff])
#define psR1s64(mem) (*(s64*)&eeMem->ROM1[(mem) & 0x3ffff])
#define psR1u8(mem) (*(u8 *)&eeMem->ROM1[(mem) & 0x3ffff])
#define psR1u16(mem) (*(u16*)&eeMem->ROM1[(mem) & 0x3ffff])
#define psR1u32(mem) (*(u32*)&eeMem->ROM1[(mem) & 0x3ffff])
#define psR1u64(mem) (*(u64*)&eeMem->ROM1[(mem) & 0x3ffff])
#define psR2s8(mem) (*(s8 *)&PS2MEM_ROM2[(mem) & 0x3ffff])
#define psR2s16(mem) (*(s16*)&PS2MEM_ROM2[(mem) & 0x3ffff])
#define psR2s32(mem) (*(s32*)&PS2MEM_ROM2[(mem) & 0x3ffff])
#define psR2s64(mem) (*(s64*)&PS2MEM_ROM2[(mem) & 0x3ffff])
#define psR2u8(mem) (*(u8 *)&PS2MEM_ROM2[(mem) & 0x3ffff])
#define psR2u16(mem) (*(u16*)&PS2MEM_ROM2[(mem) & 0x3ffff])
#define psR2u32(mem) (*(u32*)&PS2MEM_ROM2[(mem) & 0x3ffff])
#define psR2u64(mem) (*(u64*)&PS2MEM_ROM2[(mem) & 0x3ffff])
#define psR2s8(mem) (*(s8 *)&eeMem->ROM2[(mem) & 0x3ffff])
#define psR2s16(mem) (*(s16*)&eeMem->ROM2[(mem) & 0x3ffff])
#define psR2s32(mem) (*(s32*)&eeMem->ROM2[(mem) & 0x3ffff])
#define psR2s64(mem) (*(s64*)&eeMem->ROM2[(mem) & 0x3ffff])
#define psR2u8(mem) (*(u8 *)&eeMem->ROM2[(mem) & 0x3ffff])
#define psR2u16(mem) (*(u16*)&eeMem->ROM2[(mem) & 0x3ffff])
#define psR2u32(mem) (*(u32*)&eeMem->ROM2[(mem) & 0x3ffff])
#define psR2u64(mem) (*(u64*)&eeMem->ROM2[(mem) & 0x3ffff])
#define psERs8(mem) (*(s8 *)&PS2MEM_EROM[(mem) & 0x3ffff])
#define psERs16(mem) (*(s16*)&PS2MEM_EROM[(mem) & 0x3ffff])
#define psERs32(mem) (*(s32*)&PS2MEM_EROM[(mem) & 0x3ffff])
#define psERs64(mem) (*(s64*)&PS2MEM_EROM[(mem) & 0x3ffff])
#define psERu8(mem) (*(u8 *)&PS2MEM_EROM[(mem) & 0x3ffff])
#define psERu16(mem) (*(u16*)&PS2MEM_EROM[(mem) & 0x3ffff])
#define psERu32(mem) (*(u32*)&PS2MEM_EROM[(mem) & 0x3ffff])
#define psERu64(mem) (*(u64*)&PS2MEM_EROM[(mem) & 0x3ffff])
#define psERs8(mem) (*(s8 *)&eeMem->EROM[(mem) & 0x3ffff])
#define psERs16(mem) (*(s16*)&eeMem->EROM[(mem) & 0x3ffff])
#define psERs32(mem) (*(s32*)&eeMem->EROM[(mem) & 0x3ffff])
#define psERs64(mem) (*(s64*)&eeMem->EROM[(mem) & 0x3ffff])
#define psERu8(mem) (*(u8 *)&eeMem->EROM[(mem) & 0x3ffff])
#define psERu16(mem) (*(u16*)&eeMem->EROM[(mem) & 0x3ffff])
#define psERu32(mem) (*(u32*)&eeMem->EROM[(mem) & 0x3ffff])
#define psERu64(mem) (*(u64*)&eeMem->EROM[(mem) & 0x3ffff])
#define psSs32(mem) (*(s32 *)&PS2MEM_SCRATCH[(mem) & 0x3fff])
#define psSs64(mem) (*(s64 *)&PS2MEM_SCRATCH[(mem) & 0x3fff])
#define psSs128(mem) (*(s128*)&PS2MEM_SCRATCH[(mem) & 0x3fff])
#define psSu32(mem) (*(u32 *)&PS2MEM_SCRATCH[(mem) & 0x3fff])
#define psSu64(mem) (*(u64 *)&PS2MEM_SCRATCH[(mem) & 0x3fff])
#define psSu128(mem) (*(u128*)&PS2MEM_SCRATCH[(mem) & 0x3fff])
#define psSs32(mem) (*(s32 *)&eeMem->Scratch[(mem) & 0x3fff])
#define psSs64(mem) (*(s64 *)&eeMem->Scratch[(mem) & 0x3fff])
#define psSs128(mem) (*(s128*)&eeMem->Scratch[(mem) & 0x3fff])
#define psSu32(mem) (*(u32 *)&eeMem->Scratch[(mem) & 0x3fff])
#define psSu64(mem) (*(u64 *)&eeMem->Scratch[(mem) & 0x3fff])
#define psSu128(mem) (*(u128*)&eeMem->Scratch[(mem) & 0x3fff])
#define psH_DMACh(mem) (*(DMACh*)&eeMem->HW[(mem) & 0xffff])
#define psH_DMACh(mem) (*(DMACh*)&PS2MEM_HW[(mem) & 0xffff])
extern void memAlloc();
extern void memReset(); // clears PS2 ram and loads the bios. Throws Exception::FileNotFound on error.
extern void memShutdown();
@ -151,15 +132,15 @@ extern int mmap_GetRamPageInfo( u32 paddr );
extern void mmap_MarkCountedRamPage( u32 paddr );
extern void mmap_ResetBlockTracking();
#define memRead8 vtlb_memRead8
#define memRead16 vtlb_memRead16
#define memRead32 vtlb_memRead32
#define memRead8 vtlb_memRead<mem8_t>
#define memRead16 vtlb_memRead<mem16_t>
#define memRead32 vtlb_memRead<mem32_t>
#define memRead64 vtlb_memRead64
#define memRead128 vtlb_memRead128
#define memWrite8 vtlb_memWrite8
#define memWrite16 vtlb_memWrite16
#define memWrite32 vtlb_memWrite32
#define memWrite8 vtlb_memWrite<mem8_t>
#define memWrite16 vtlb_memWrite<mem16_t>
#define memWrite32 vtlb_memWrite<mem32_t>
#define memWrite64 vtlb_memWrite64
#define memWrite128 vtlb_memWrite128

View File

@ -36,3 +36,24 @@ typedef u16 mem16_t;
typedef u32 mem32_t;
typedef u64 mem64_t;
typedef u128 mem128_t;
struct EEVM_MemoryAllocMess
{
u8 Scratch[Ps2MemSize::Scratch]; // Scratchpad!
u8 Main[Ps2MemSize::Base]; // Main memory (hard-wired to 32MB)
u8 HW[Ps2MemSize::Hardware]; // Hardware registers
u8 ROM[Ps2MemSize::Rom]; // Boot rom (4MB)
u8 ROM1[Ps2MemSize::Rom1]; // DVD player
u8 ROM2[Ps2MemSize::Rom2]; // Chinese extensions (?)
u8 EROM[Ps2MemSize::ERom]; // DVD player extensions (?)
// Two 1 megabyte (max DMA) buffers for reading and writing to high memory (>32MB).
// Such accesses are not documented as causing bus errors but as the memory does
// not exist, reads should continue to return 0 and writes should be discarded.
// Probably.
u8 ZeroRead[_1mb];
u8 ZeroWrite[_1mb];
};
extern EEVM_MemoryAllocMess* eeMem;

View File

@ -87,6 +87,12 @@ void cpuReset()
ElfCRC = 0;
DiscSerial = L"";
ElfEntry = -1;
// FIXME: LastELF should be reset on media changes as well as on CPU resets, in
// the very unlikely case that a user swaps to another media source that "looks"
// the same (identical ELF names) but is actually different (devs actually could
// run into this while testing minor binary hacked changes to ISO images, which
// is why I found out about this) --air
LastELF = L"";
}

View File

@ -152,9 +152,9 @@ void SaveStateBase::FreezeMainMemory()
// First Block - Memory Dumps
// ---------------------------
FreezeMem(PS2MEM_BASE, Ps2MemSize::Base); // 32 MB main memory
FreezeMem(PS2MEM_SCRATCH, Ps2MemSize::Scratch); // scratch pad
FreezeMem(PS2MEM_HW, Ps2MemSize::Hardware); // hardware memory
FreezeMem(eeMem->Main, Ps2MemSize::Base); // 32 MB main memory
FreezeMem(eeMem->Scratch, Ps2MemSize::Scratch); // scratch pad
FreezeMem(eeMem->HW, Ps2MemSize::Hardware); // hardware memory
FreezeMem(psxM, Ps2MemSize::IopRam); // 2 MB main memory
FreezeMem(psxH, Ps2MemSize::IopHardware); // hardware memory

View File

@ -243,11 +243,14 @@ static wxString GetMemoryErrorVM()
);
}
SysCoreAllocations::SysCoreAllocations()
// --------------------------------------------------------------------------------------
// SysAllocVM (implementations)
// --------------------------------------------------------------------------------------
SysAllocVM::SysAllocVM()
{
InstallSignalHandler();
Console.WriteLn( "Initializing PS2 virtual machine..." );
Console.WriteLn( "Allocating memory for the PS2 virtual machine..." );
try
{
@ -277,7 +280,30 @@ SysCoreAllocations::SysCoreAllocations()
)
.SetUserMsg(GetMemoryErrorVM()); // translated
}
}
void SysAllocVM::CleanupMess() throw()
{
try
{
vuMicroMemShutdown();
psxMemShutdown();
memShutdown();
vtlb_Core_Shutdown();
}
DESTRUCTOR_CATCHALL
}
SysAllocVM::~SysAllocVM() throw()
{
CleanupMess();
}
// --------------------------------------------------------------------------------------
// SysCpuProviderPack (implementations)
// --------------------------------------------------------------------------------------
SysCpuProviderPack::SysCpuProviderPack()
{
Console.WriteLn( "Allocating memory for recompilers..." );
CpuProviders = new CpuInitializerSet();
@ -310,18 +336,18 @@ SysCoreAllocations::SysCoreAllocations()
SuperVUDestroy( -1 );
}
bool SysCoreAllocations::IsRecAvailable_MicroVU0() const { return CpuProviders->microVU0.IsAvailable(); }
bool SysCoreAllocations::IsRecAvailable_MicroVU1() const { return CpuProviders->microVU1.IsAvailable(); }
BaseException* SysCoreAllocations::GetException_MicroVU0() const { return CpuProviders->microVU0.ExThrown; }
BaseException* SysCoreAllocations::GetException_MicroVU1() const { return CpuProviders->microVU1.ExThrown; }
bool SysCpuProviderPack::IsRecAvailable_MicroVU0() const { return CpuProviders->microVU0.IsAvailable(); }
bool SysCpuProviderPack::IsRecAvailable_MicroVU1() const { return CpuProviders->microVU1.IsAvailable(); }
BaseException* SysCpuProviderPack::GetException_MicroVU0() const { return CpuProviders->microVU0.ExThrown; }
BaseException* SysCpuProviderPack::GetException_MicroVU1() const { return CpuProviders->microVU1.ExThrown; }
bool SysCoreAllocations::IsRecAvailable_SuperVU0() const { return CpuProviders->superVU0.IsAvailable(); }
bool SysCoreAllocations::IsRecAvailable_SuperVU1() const { return CpuProviders->superVU1.IsAvailable(); }
BaseException* SysCoreAllocations::GetException_SuperVU0() const { return CpuProviders->superVU0.ExThrown; }
BaseException* SysCoreAllocations::GetException_SuperVU1() const { return CpuProviders->superVU1.ExThrown; }
bool SysCpuProviderPack::IsRecAvailable_SuperVU0() const { return CpuProviders->superVU0.IsAvailable(); }
bool SysCpuProviderPack::IsRecAvailable_SuperVU1() const { return CpuProviders->superVU1.IsAvailable(); }
BaseException* SysCpuProviderPack::GetException_SuperVU0() const { return CpuProviders->superVU0.ExThrown; }
BaseException* SysCpuProviderPack::GetException_SuperVU1() const { return CpuProviders->superVU1.ExThrown; }
void SysCoreAllocations::CleanupMess() throw()
void SysCpuProviderPack::CleanupMess() throw()
{
try
{
@ -333,21 +359,16 @@ void SysCoreAllocations::CleanupMess() throw()
psxRec.Shutdown();
recCpu.Shutdown();
vuMicroMemShutdown();
psxMemShutdown();
memShutdown();
vtlb_Core_Shutdown();
}
DESTRUCTOR_CATCHALL
}
SysCoreAllocations::~SysCoreAllocations() throw()
SysCpuProviderPack::~SysCpuProviderPack() throw()
{
CleanupMess();
}
bool SysCoreAllocations::HadSomeFailures( const Pcsx2Config::RecompilerOptions& recOpts ) const
bool SysCpuProviderPack::HadSomeFailures( const Pcsx2Config::RecompilerOptions& recOpts ) const
{
return (recOpts.EnableEE && !IsRecAvailable_EE()) ||
(recOpts.EnableIOP && !IsRecAvailable_IOP()) ||
@ -361,7 +382,7 @@ bool SysCoreAllocations::HadSomeFailures( const Pcsx2Config::RecompilerOptions&
BaseVUmicroCPU* CpuVU0 = NULL;
BaseVUmicroCPU* CpuVU1 = NULL;
void SysCoreAllocations::SelectCpuProviders() const
void SysCpuProviderPack::ApplyConfig() const
{
Cpu = CHECK_EEREC ? &recCpu : &intCpu;
psxCpu = CHECK_IOPREC ? &psxRec : &psxInt;
@ -377,7 +398,7 @@ void SysCoreAllocations::SelectCpuProviders() const
}
// This is a semi-hacky function for convenience
BaseVUmicroCPU* SysCoreAllocations::getVUprovider(int whichProvider, int vuIndex) const {
BaseVUmicroCPU* SysCpuProviderPack::getVUprovider(int whichProvider, int vuIndex) const {
switch (whichProvider) {
case 0: return vuIndex ? (BaseVUmicroCPU*)CpuProviders->interpVU1 : (BaseVUmicroCPU*)CpuProviders->interpVU0;
case 1: return vuIndex ? (BaseVUmicroCPU*)CpuProviders->superVU1 : (BaseVUmicroCPU*)CpuProviders->superVU0;
@ -393,7 +414,7 @@ BaseVUmicroCPU* SysCoreAllocations::getVUprovider(int whichProvider, int vuIndex
// Use this method to reset the recs when important global pointers like the MTGS are re-assigned.
void SysClearExecutionCache()
{
GetSysCoreAlloc().SelectCpuProviders();
GetCpuProviders().ApplyConfig();
// SuperVUreset will do nothing is none of the recs are initialized.
// But it's needed if one or the other is initialized.

View File

@ -25,9 +25,22 @@ typedef SafeArray<u8> VmStateBuffer;
class BaseVUmicroCPU;
// --------------------------------------------------------------------------------------
// SysCoreAllocations class
// SysAllocVM
// --------------------------------------------------------------------------------------
class SysCoreAllocations
class SysAllocVM
{
public:
SysAllocVM();
virtual ~SysAllocVM() throw();
protected:
void CleanupMess() throw();
};
// --------------------------------------------------------------------------------------
// SysCpuProviderPack
// --------------------------------------------------------------------------------------
class SysCpuProviderPack
{
protected:
ScopedPtr<CpuInitializerSet> CpuProviders;
@ -36,10 +49,10 @@ protected:
ScopedPtr<BaseException> m_RecExceptionIOP;
public:
SysCoreAllocations();
virtual ~SysCoreAllocations() throw();
SysCpuProviderPack();
virtual ~SysCpuProviderPack() throw();
void SelectCpuProviders() const;
void ApplyConfig() const;
BaseVUmicroCPU* getVUprovider(int whichProvider, int vuIndex) const;
bool HadSomeFailures( const Pcsx2Config::RecompilerOptions& recOpts ) const;
@ -64,9 +77,9 @@ protected:
void CleanupMess() throw();
};
// GetSysCoreAlloc - this function is not implemented by PCSX2 core -- it must be
// GetCpuProviders - this function is not implemented by PCSX2 core -- it must be
// implemented by the provisioning interface.
extern SysCoreAllocations& GetSysCoreAlloc();
extern SysCpuProviderPack& GetCpuProviders();
extern void SysLogMachineCaps(); // Detects cpu type and fills cpuInfo structs.
extern void SysClearExecutionCache(); // clears recompiled execution caches!

View File

@ -214,8 +214,8 @@ struct VIFregisters {
extern VIFregisters *vifRegs;
#define vif0RegsRef ((VIFregisters&)PS2MEM_HW[0x3800])
#define vif1RegsRef ((VIFregisters&)PS2MEM_HW[0x3c00])
#define vif0RegsRef ((VIFregisters&)eeMem->HW[0x3800])
#define vif1RegsRef ((VIFregisters&)eeMem->HW[0x3c00])
#define vif0Regs (&vif0RegsRef)
#define vif1Regs (&vif1RegsRef)

View File

@ -183,7 +183,7 @@ bool _VIF1chain()
__fi void vif1SetupTransfer()
{
tDMA_TAG *ptag;
DMACh& vif1c = (DMACh&)PS2MEM_HW[0x9000];
DMACh& vif1c = (DMACh&)eeMem->HW[0x9000];
switch (vif1.dmamode)
{

View File

@ -474,7 +474,8 @@ public:
// in parallel to the main message pump, to allow the main pump to run without fear of
// blocked threads stalling the GUI.
ExecutorThread SysExecutorThread;
ScopedPtr<SysCoreAllocations> m_CoreAllocs;
ScopedPtr<SysCpuProviderPack> m_CpuProviders;
ScopedPtr<SysAllocVM> m_VmAllocs;
protected:
wxWindowID m_id_MainFrame;
@ -524,6 +525,8 @@ public:
void StartPendingSave();
void ClearPendingSave();
void AllocateVM();
// --------------------------------------------------------------------------
// App-wide Resources

View File

@ -183,6 +183,7 @@ void Pcsx2App::SysApplySettings()
void AppCoreThread::OnResumeReady()
{
wxGetApp().SysApplySettings();
wxGetApp().AllocateVM();
wxGetApp().PostMethod( AppSaveSettings );
_parent::OnResumeReady();
}

View File

@ -238,6 +238,12 @@ void Pcsx2App::OpenProgramLog()
if( m_current_focus ) m_current_focus->SetFocus();
}
void Pcsx2App::AllocateVM()
{
if (m_VmAllocs) return;
m_VmAllocs = new SysAllocVM();
}
void Pcsx2App::AllocateCoreStuffs()
{
if( AppRpc_TryInvokeAsync( &Pcsx2App::AllocateCoreStuffs ) ) return;
@ -246,14 +252,14 @@ void Pcsx2App::AllocateCoreStuffs()
SysLogMachineCaps();
AppApplySettings();
if( !m_CoreAllocs )
if( !m_CpuProviders )
{
// FIXME : Some or all of SysCoreAllocations should be run from the SysExecutor thread,
// FIXME : Some or all of SysCpuProviderPack should be run from the SysExecutor thread,
// so that the thread is safely blocked from being able to start emulation.
m_CoreAllocs = new SysCoreAllocations();
m_CpuProviders = new SysCpuProviderPack();
if( m_CoreAllocs->HadSomeFailures( g_Conf->EmuOptions.Cpu.Recompiler ) )
if( m_CpuProviders->HadSomeFailures( g_Conf->EmuOptions.Cpu.Recompiler ) )
{
// HadSomeFailures only returns 'true' if an *enabled* cpu type fails to init. If
// the user already has all interps configured, for example, then no point in
@ -274,43 +280,43 @@ void Pcsx2App::AllocateCoreStuffs()
exconf += 6;
exconf += scrollableTextArea | pxExpand.Border(wxALL, 16);
if( BaseException* ex = m_CoreAllocs->GetException_EE() )
if( BaseException* ex = m_CpuProviders->GetException_EE() )
{
scrollableTextArea->AppendText( L"* R5900 (EE)\n\t" + ex->FormatDiagnosticMessage() + L"\n\n" );
g_Conf->EmuOptions.Recompiler.EnableEE = false;
}
if( BaseException* ex = m_CoreAllocs->GetException_IOP() )
if( BaseException* ex = m_CpuProviders->GetException_IOP() )
{
scrollableTextArea->AppendText( L"* R3000A (IOP)\n\t" + ex->FormatDiagnosticMessage() + L"\n\n" );
g_Conf->EmuOptions.Recompiler.EnableIOP = false;
}
if( BaseException* ex = m_CoreAllocs->GetException_MicroVU0() )
if( BaseException* ex = m_CpuProviders->GetException_MicroVU0() )
{
scrollableTextArea->AppendText( L"* microVU0\n\t" + ex->FormatDiagnosticMessage() + L"\n\n" );
g_Conf->EmuOptions.Recompiler.UseMicroVU0 = false;
g_Conf->EmuOptions.Recompiler.EnableVU0 = g_Conf->EmuOptions.Recompiler.EnableVU0 && m_CoreAllocs->IsRecAvailable_SuperVU0();
g_Conf->EmuOptions.Recompiler.EnableVU0 = g_Conf->EmuOptions.Recompiler.EnableVU0 && m_CpuProviders->IsRecAvailable_SuperVU0();
}
if( BaseException* ex = m_CoreAllocs->GetException_MicroVU1() )
if( BaseException* ex = m_CpuProviders->GetException_MicroVU1() )
{
scrollableTextArea->AppendText( L"* microVU1\n\t" + ex->FormatDiagnosticMessage() + L"\n\n" );
g_Conf->EmuOptions.Recompiler.UseMicroVU1 = false;
g_Conf->EmuOptions.Recompiler.EnableVU1 = g_Conf->EmuOptions.Recompiler.EnableVU1 && m_CoreAllocs->IsRecAvailable_SuperVU1();
g_Conf->EmuOptions.Recompiler.EnableVU1 = g_Conf->EmuOptions.Recompiler.EnableVU1 && m_CpuProviders->IsRecAvailable_SuperVU1();
}
if( BaseException* ex = m_CoreAllocs->GetException_SuperVU0() )
if( BaseException* ex = m_CpuProviders->GetException_SuperVU0() )
{
scrollableTextArea->AppendText( L"* SuperVU0\n\t" + ex->FormatDiagnosticMessage() + L"\n\n" );
g_Conf->EmuOptions.Recompiler.UseMicroVU0 = m_CoreAllocs->IsRecAvailable_MicroVU0();
g_Conf->EmuOptions.Recompiler.UseMicroVU0 = m_CpuProviders->IsRecAvailable_MicroVU0();
g_Conf->EmuOptions.Recompiler.EnableVU0 = g_Conf->EmuOptions.Recompiler.EnableVU0 && g_Conf->EmuOptions.Recompiler.UseMicroVU0;
}
if( BaseException* ex = m_CoreAllocs->GetException_SuperVU1() )
if( BaseException* ex = m_CpuProviders->GetException_SuperVU1() )
{
scrollableTextArea->AppendText( L"* SuperVU1\n\t" + ex->FormatDiagnosticMessage() + L"\n\n" );
g_Conf->EmuOptions.Recompiler.UseMicroVU1 = m_CoreAllocs->IsRecAvailable_MicroVU1();
g_Conf->EmuOptions.Recompiler.UseMicroVU1 = m_CpuProviders->IsRecAvailable_MicroVU1();
g_Conf->EmuOptions.Recompiler.EnableVU1 = g_Conf->EmuOptions.Recompiler.EnableVU1 && g_Conf->EmuOptions.Recompiler.UseMicroVU1;
}

View File

@ -940,7 +940,7 @@ SysMtgsThread& GetMTGS()
return mtgsThread;
}
SysCoreAllocations& GetSysCoreAlloc()
SysCpuProviderPack& GetCpuProviders()
{
return *wxGetApp().m_CoreAllocs;
return *wxGetApp().m_CpuProviders;
}

View File

@ -144,7 +144,7 @@ static void loadBiosRom( const wxChar *ext, u8 *dest, s64 maxSize )
//
void LoadBIOS()
{
pxAssertDev( PS2MEM_ROM != NULL, "PS2 system memory has not been initialized yet." );
pxAssertDev( eeMem->ROM != NULL, "PS2 system memory has not been initialized yet." );
wxString Bios( g_Conf->FullpathToBios() );
if( !g_Conf->BaseFilenames.Bios.IsOk() || g_Conf->BaseFilenames.Bios.IsDir() )
@ -159,7 +159,7 @@ void LoadBIOS()
}
wxFile fp( Bios );
fp.Read( PS2MEM_ROM, min( (s64)Ps2MemSize::Rom, filesize ) );
fp.Read( eeMem->ROM, min( (s64)Ps2MemSize::Rom, filesize ) );
BiosVersion = GetBiosVersion();
if( BiosVersion == -1 )
@ -173,9 +173,9 @@ void LoadBIOS()
//injectIRX("host.irx"); //not fully tested; still buggy
loadBiosRom( L"rom1", PS2MEM_ROM1, Ps2MemSize::Rom1 );
loadBiosRom( L"rom2", PS2MEM_ROM2, Ps2MemSize::Rom2 );
loadBiosRom( L"erom", PS2MEM_EROM, Ps2MemSize::ERom );
loadBiosRom( L"rom1", eeMem->ROM1, Ps2MemSize::Rom1 );
loadBiosRom( L"rom2", eeMem->ROM2, Ps2MemSize::Rom2 );
loadBiosRom( L"erom", eeMem->EROM, Ps2MemSize::ERom );
}
bool IsBIOS(const wxString& filename, wxString& description)

View File

@ -39,34 +39,31 @@
using namespace R5900;
using namespace vtlb_private;
#ifdef PCSX2_DEVBUILD
#define verify(x) {if (!(x)) { (*(u8*)0)=3; }}
#else
#define verify pxAssume
#endif
namespace vtlb_private
{
__aligned(64) MapData vtlbdata;
}
vtlbHandler vtlbHandlerCount=0;
static vtlbHandler vtlbHandlerCount=0;
vtlbHandler DefaultPhyHandler;
vtlbHandler UnmappedVirtHandler0;
vtlbHandler UnmappedVirtHandler1;
vtlbHandler UnmappedPhyHandler0;
vtlbHandler UnmappedPhyHandler1;
static vtlbHandler DefaultPhyHandler;
static vtlbHandler UnmappedVirtHandler0;
static vtlbHandler UnmappedVirtHandler1;
static vtlbHandler UnmappedPhyHandler0;
static vtlbHandler UnmappedPhyHandler1;
//////////////////////////////////////////////////////////////////////////////////////////
// --------------------------------------------------------------------------------------
// Interpreter Implementations of VTLB Memory Operations.
// --------------------------------------------------------------------------------------
// See recVTLB.cpp for the dynarec versions.
// Interpreted VTLB lookup for 8, 16, and 32 bit accesses
template<int DataSize,typename DataType>
__fi DataType __fastcall MemOp_r0(u32 addr)
template< typename DataType >
DataType __fastcall vtlb_memRead(u32 addr)
{
static const uint DataSize = sizeof(DataType);
u32 vmv=vtlbdata.vmap[addr>>VTLB_PAGE_BITS];
s32 ppf=addr+vmv;
@ -81,9 +78,9 @@ __fi DataType __fastcall MemOp_r0(u32 addr)
switch( DataSize )
{
case 8: return ((vtlbMemR8FP*)vtlbdata.RWFT[0][0][hand])(paddr);
case 16: return ((vtlbMemR16FP*)vtlbdata.RWFT[1][0][hand])(paddr);
case 32: return ((vtlbMemR32FP*)vtlbdata.RWFT[2][0][hand])(paddr);
case 8: return ((vtlbMemR8FP*)vtlbdata.RWFT[0][0][hand])(paddr);
case 16: return ((vtlbMemR16FP*)vtlbdata.RWFT[1][0][hand])(paddr);
case 32: return ((vtlbMemR32FP*)vtlbdata.RWFT[2][0][hand])(paddr);
jNO_DEFAULT;
}
@ -91,46 +88,6 @@ __fi DataType __fastcall MemOp_r0(u32 addr)
return 0; // technically unreachable, but suppresses warnings.
}
// ------------------------------------------------------------------------
template<int DataSize,typename DataType>
__fi void MemOp_w0(u32 addr, DataType data)
{
u32 vmv=vtlbdata.vmap[addr>>VTLB_PAGE_BITS];
s32 ppf=addr+vmv;
if (!(ppf<0))
{
*reinterpret_cast<DataType*>(ppf)=data;
}
else
{
//has to: translate, find function, call function
u32 hand=(u8)vmv;
u32 paddr=ppf-hand+0x80000000;
//Console.WriteLn("Translated 0x%08X to 0x%08X", addr,paddr);
switch( DataSize )
{
case 8: return ((vtlbMemW8FP*)vtlbdata.RWFT[0][1][hand])(paddr, (u8)data);
case 16: return ((vtlbMemW16FP*)vtlbdata.RWFT[1][1][hand])(paddr, (u16)data);
case 32: return ((vtlbMemW32FP*)vtlbdata.RWFT[2][1][hand])(paddr, (u32)data);
jNO_DEFAULT;
}
}
}
mem8_t __fastcall vtlb_memRead8(u32 mem)
{
return MemOp_r0<8,mem8_t>(mem);
}
mem16_t __fastcall vtlb_memRead16(u32 mem)
{
return MemOp_r0<16,mem16_t>(mem);
}
mem32_t __fastcall vtlb_memRead32(u32 mem)
{
return MemOp_r0<32,mem32_t>(mem);
}
void __fastcall vtlb_memRead64(u32 mem, mem64_t *out)
{
u32 vmv=vtlbdata.vmap[mem>>VTLB_PAGE_BITS];
@ -174,17 +131,33 @@ void __fastcall vtlb_memRead128(u32 mem, u64 (&out)[2])
vtlb_memRead128(mem, (mem128_t*)out);
}
void __fastcall vtlb_memWrite8 (u32 mem, mem8_t value)
template< typename DataType >
void __fastcall vtlb_memWrite(u32 addr, DataType data)
{
MemOp_w0<8,mem8_t>(mem,value);
}
void __fastcall vtlb_memWrite16(u32 mem, mem16_t value)
{
MemOp_w0<16,mem16_t>(mem,value);
}
void __fastcall vtlb_memWrite32(u32 mem, mem32_t value)
{
MemOp_w0<32,mem32_t>(mem,value);
static const uint DataSize = sizeof(DataType);
u32 vmv=vtlbdata.vmap[addr>>VTLB_PAGE_BITS];
s32 ppf=addr+vmv;
if (!(ppf<0))
{
*reinterpret_cast<DataType*>(ppf)=data;
}
else
{
//has to: translate, find function, call function
u32 hand=(u8)vmv;
u32 paddr=ppf-hand+0x80000000;
//Console.WriteLn("Translated 0x%08X to 0x%08X", addr,paddr);
switch( DataSize )
{
case 8: return ((vtlbMemW8FP*)vtlbdata.RWFT[0][1][hand])(paddr, (u8)data);
case 16: return ((vtlbMemW16FP*)vtlbdata.RWFT[1][1][hand])(paddr, (u16)data);
case 32: return ((vtlbMemW32FP*)vtlbdata.RWFT[2][1][hand])(paddr, (u32)data);
jNO_DEFAULT;
}
}
}
void __fastcall vtlb_memWrite64(u32 mem, const mem64_t* value)
{
@ -229,13 +202,23 @@ void __fastcall vtlb_memWrite128(u32 mem, const u64 (&out)[2])
vtlb_memWrite128(mem, (const mem128_t*)out);
}
// ===========================================================================================
// Error / TLB Miss Handlers
// ===========================================================================================
// Important: Throwing exceptions isn't reliable *yet* because memory ops don't flush
// the PC prior to invoking the indirect handlers. That feature will likely be added to
// debug and dev builds soon, and later on to release builds as well.
template mem8_t vtlb_memRead<mem8_t>(u32 mem);
template mem16_t vtlb_memRead<mem16_t>(u32 mem);
template mem32_t vtlb_memRead<mem32_t>(u32 mem);
template void vtlb_memWrite<mem8_t>(u32 mem, mem8_t data);
template void vtlb_memWrite<mem16_t>(u32 mem, mem16_t data);
template void vtlb_memWrite<mem32_t>(u32 mem, mem32_t data);
// --------------------------------------------------------------------------------------
// TLB Miss / BusError Handlers
// --------------------------------------------------------------------------------------
// These are valid VM memory errors that should typically be handled by the VM itself via
// its own cpu exception system.
//
// [TODO] Add first-chance debugging hooks to these exceptions!
//
// Important recompiler note: Mid-block Exception handling isn't reliable *yet* because
// memory ops don't flush the PC prior to invoking the indirect handlers.
// Generates a tlbMiss Exception
static __ri void vtlb_Miss(u32 addr,u32 mode)
@ -251,72 +234,59 @@ static __ri void vtlb_Miss(u32 addr,u32 mode)
// time of the exception.
static __ri void vtlb_BusError(u32 addr,u32 mode)
{
// Throwing exceptions isn't reliable *yet* because memory ops don't flush
// the PC prior to invoking the indirect handlers.
if( IsDevBuild )
Cpu->ThrowCpuException( R5900Exception::BusError( addr, !!mode ) );
else
Console.Error( R5900Exception::TLBMiss( addr, !!mode ).FormatMessage() );
}
///// Virtual Mapping Errors (TLB Miss)
template<u32 saddr>
mem8_t __fastcall vtlbUnmappedVRead8(u32 addr) { vtlb_Miss(addr|saddr,0); return 0; }
template<u32 saddr>
mem16_t __fastcall vtlbUnmappedVRead16(u32 addr) { vtlb_Miss(addr|saddr,0); return 0; }
template<u32 saddr>
mem32_t __fastcall vtlbUnmappedVRead32(u32 addr) { vtlb_Miss(addr|saddr,0); return 0; }
template<u32 saddr>
void __fastcall vtlbUnmappedVRead64(u32 addr,mem64_t* data) { vtlb_Miss(addr|saddr,0); }
template<u32 saddr>
void __fastcall vtlbUnmappedVRead128(u32 addr,mem128_t* data) { vtlb_Miss(addr|saddr,0); }
template<u32 saddr>
void __fastcall vtlbUnmappedVWrite8(u32 addr,mem8_t data) { vtlb_Miss(addr|saddr,1); }
template<u32 saddr>
void __fastcall vtlbUnmappedVWrite16(u32 addr,mem16_t data) { vtlb_Miss(addr|saddr,1); }
template<u32 saddr>
void __fastcall vtlbUnmappedVWrite32(u32 addr,mem32_t data) { vtlb_Miss(addr|saddr,1); }
template<u32 saddr>
void __fastcall vtlbUnmappedVWrite64(u32 addr,const mem64_t* data) { vtlb_Miss(addr|saddr,1); }
template<u32 saddr>
void __fastcall vtlbUnmappedVWrite128(u32 addr,const mem128_t* data) { vtlb_Miss(addr|saddr,1); }
#define _tmpl(ret) template<typename OperandType, u32 saddr> ret __fastcall
///// Physical Mapping Errors (Bus Error)
template<u32 saddr>
mem8_t __fastcall vtlbUnmappedPRead8(u32 addr) { vtlb_BusError(addr|saddr,0); return 0; }
template<u32 saddr>
mem16_t __fastcall vtlbUnmappedPRead16(u32 addr) { vtlb_BusError(addr|saddr,0); return 0; }
template<u32 saddr>
mem32_t __fastcall vtlbUnmappedPRead32(u32 addr) { vtlb_BusError(addr|saddr,0); return 0; }
template<u32 saddr>
void __fastcall vtlbUnmappedPRead64(u32 addr,mem64_t* data) { vtlb_BusError(addr|saddr,0); }
template<u32 saddr>
void __fastcall vtlbUnmappedPRead128(u32 addr,mem128_t* data) { vtlb_BusError(addr|saddr,0); }
template<u32 saddr>
void __fastcall vtlbUnmappedPWrite8(u32 addr,mem8_t data) { vtlb_BusError(addr|saddr,1); }
template<u32 saddr>
void __fastcall vtlbUnmappedPWrite16(u32 addr,mem16_t data) { vtlb_BusError(addr|saddr,1); }
template<u32 saddr>
void __fastcall vtlbUnmappedPWrite32(u32 addr,mem32_t data) { vtlb_BusError(addr|saddr,1); }
template<u32 saddr>
void __fastcall vtlbUnmappedPWrite64(u32 addr,const mem64_t* data) { vtlb_BusError(addr|saddr,1); }
template<u32 saddr>
void __fastcall vtlbUnmappedPWrite128(u32 addr,const mem128_t* data) { vtlb_BusError(addr|saddr,1); }
_tmpl(OperandType) vtlbUnmappedVReadSm(u32 addr) { vtlb_Miss(addr|saddr,0); return 0; }
_tmpl(void) vtlbUnmappedVReadLg(u32 addr,OperandType* data) { vtlb_Miss(addr|saddr,0); }
_tmpl(void) vtlbUnmappedVWriteSm(u32 addr,OperandType data) { vtlb_Miss(addr|saddr,1); }
_tmpl(void) vtlbUnmappedVWriteLg(u32 addr,const OperandType* data) { vtlb_Miss(addr|saddr,1); }
///// VTLB mapping errors (unmapped address spaces)
static mem8_t __fastcall vtlbDefaultPhyRead8(u32 addr) { Console.Error("vtlbDefaultPhyRead8: 0x%X",addr); verify(false); return -1; }
static mem16_t __fastcall vtlbDefaultPhyRead16(u32 addr) { Console.Error("vtlbDefaultPhyRead16: 0x%X",addr); verify(false); return -1; }
static mem32_t __fastcall vtlbDefaultPhyRead32(u32 addr) { Console.Error("vtlbDefaultPhyRead32: 0x%X",addr); verify(false); return -1; }
static void __fastcall vtlbDefaultPhyRead64(u32 addr,mem64_t* data) { Console.Error("vtlbDefaultPhyRead64: 0x%X",addr); verify(false); }
static void __fastcall vtlbDefaultPhyRead128(u32 addr,mem128_t* data) { Console.Error("vtlbDefaultPhyRead128: 0x%X",addr); verify(false); }
_tmpl(OperandType) vtlbUnmappedPReadSm(u32 addr) { vtlb_BusError(addr|saddr,0); return 0; }
_tmpl(void) vtlbUnmappedPReadLg(u32 addr,OperandType* data) { vtlb_BusError(addr|saddr,0); }
_tmpl(void) vtlbUnmappedPWriteSm(u32 addr,OperandType data) { vtlb_BusError(addr|saddr,1); }
_tmpl(void) vtlbUnmappedPWriteLg(u32 addr,const OperandType* data) { vtlb_BusError(addr|saddr,1); }
static void __fastcall vtlbDefaultPhyWrite8(u32 addr,mem8_t data) { Console.Error("vtlbDefaultPhyWrite8: 0x%X",addr); verify(false); }
static void __fastcall vtlbDefaultPhyWrite16(u32 addr,mem16_t data) { Console.Error("vtlbDefaultPhyWrite16: 0x%X",addr); verify(false); }
static void __fastcall vtlbDefaultPhyWrite32(u32 addr,mem32_t data) { Console.Error("vtlbDefaultPhyWrite32: 0x%X",addr); verify(false); }
static void __fastcall vtlbDefaultPhyWrite64(u32 addr,const mem64_t* data) { Console.Error("vtlbDefaultPhyWrite64: 0x%X",addr); verify(false); }
static void __fastcall vtlbDefaultPhyWrite128(u32 addr,const mem128_t* data) { Console.Error("vtlbDefaultPhyWrite128: 0x%X",addr); verify(false); }
#undef _tmpl
// --------------------------------------------------------------------------------------
// VTLB mapping errors
// --------------------------------------------------------------------------------------
// These errors are assertion/logic errors that should never occur if PCSX2 has been initialized
// properly. All addressable physical memory should be configured as TLBMiss or Bus Error.
//
#define _tmpl(ret) template<typename OperandType> ret __fastcall
_tmpl(OperandType) vtlbDefaultPhyReadSm(u32 addr)
{
Console.Error("vtlbDefaultPhyRead%u: 0x%08X", sizeof(OperandType)*8, addr);
pxFailDev("(VTLB) Attempted read from an unmapped physical address.");
return 0;
}
_tmpl(void) vtlbDefaultPhyReadLg(u32 addr,OperandType* data)
{
Console.Error("vtlbDefaultPhyRead%u: 0x%08X", sizeof(OperandType)*8, addr);
pxFailDev("(VTLB) Attempted read from an unmapped physical address.");
}
_tmpl(void) vtlbDefaultPhyWriteSm(u32 addr,OperandType data)
{
Console.Error("vtlbDefaultPhyWrite%u: 0x%08X",sizeof(OperandType)*8,addr);
pxFailDev("(VTLB) Attempted write to an unmapped physical address.");
}
_tmpl(void) vtlbDefaultPhyWriteLg(u32 addr,const OperandType* data)
{
Console.Error("vtlbDefaultPhyWrite%u: 0x%08X",sizeof(OperandType)*8,addr);
pxFailDev("(VTLB) Attempted write to an unmapped physical address.");
}
#undef _tmpl
// ===========================================================================================
// VTLB Public API -- Init/Term/RegisterHandler stuff
@ -330,27 +300,21 @@ static void __fastcall vtlbDefaultPhyWrite128(u32 addr,const mem128_t* data) { C
//
// Note: All handlers persist across calls to vtlb_Reset(), but are wiped/invalidated by calls to vtlb_Init()
//
void vtlb_ReassignHandler( vtlbHandler rv,
vtlbMemR8FP* r8,vtlbMemR16FP* r16,vtlbMemR32FP* r32,vtlbMemR64FP* r64,vtlbMemR128FP* r128,
vtlbMemW8FP* w8,vtlbMemW16FP* w16,vtlbMemW32FP* w32,vtlbMemW64FP* w64,vtlbMemW128FP* w128 )
__ri void vtlb_ReassignHandler( vtlbHandler rv,
vtlbMemR8FP* r8,vtlbMemR16FP* r16,vtlbMemR32FP* r32,vtlbMemR64FP* r64,vtlbMemR128FP* r128,
vtlbMemW8FP* w8,vtlbMemW16FP* w16,vtlbMemW32FP* w32,vtlbMemW64FP* w64,vtlbMemW128FP* w128 )
{
vtlbdata.RWFT[0][0][rv] = (r8!=0) ? (void*)(r8): (void*)vtlbDefaultPhyRead8;
vtlbdata.RWFT[1][0][rv] = (r16!=0) ? (void*)r16: (void*)vtlbDefaultPhyRead16;
vtlbdata.RWFT[2][0][rv] = (r32!=0) ? (void*)r32: (void*)vtlbDefaultPhyRead32;
vtlbdata.RWFT[3][0][rv] = (r64!=0) ? (void*)r64: (void*)vtlbDefaultPhyRead64;
vtlbdata.RWFT[4][0][rv] = (r128!=0) ? (void*)r128: (void*)vtlbDefaultPhyRead128;
vtlbdata.RWFT[0][0][rv] = (void*)((r8!=0) ? r8 : vtlbDefaultPhyReadSm<mem8_t>);
vtlbdata.RWFT[1][0][rv] = (void*)((r16!=0) ? r16 : vtlbDefaultPhyReadSm<mem16_t>);
vtlbdata.RWFT[2][0][rv] = (void*)((r32!=0) ? r32 : vtlbDefaultPhyReadSm<mem32_t>);
vtlbdata.RWFT[3][0][rv] = (void*)((r64!=0) ? r64 : vtlbDefaultPhyReadLg<mem64_t>);
vtlbdata.RWFT[4][0][rv] = (void*)((r128!=0) ? r128 : vtlbDefaultPhyReadLg<mem128_t>);
vtlbdata.RWFT[0][0][rv] = (r8!=0) ? (void*)r8:(void*)vtlbDefaultPhyRead8;
vtlbdata.RWFT[1][0][rv] = (r16!=0) ? (void*)r16:(void*)vtlbDefaultPhyRead16;
vtlbdata.RWFT[2][0][rv] = (r32!=0) ? (void*)r32:(void*)vtlbDefaultPhyRead32;
vtlbdata.RWFT[3][0][rv] = (r64!=0) ? (void*)r64:(void*)vtlbDefaultPhyRead64;
vtlbdata.RWFT[4][0][rv] = (r128!=0) ? (void*)r128:(void*)vtlbDefaultPhyRead128;
vtlbdata.RWFT[0][1][rv] = (void*)((w8!=0) ? w8:vtlbDefaultPhyWrite8);
vtlbdata.RWFT[1][1][rv] = (void*)((w16!=0) ? w16:vtlbDefaultPhyWrite16);
vtlbdata.RWFT[2][1][rv] = (void*)((w32!=0) ? w32:vtlbDefaultPhyWrite32);
vtlbdata.RWFT[3][1][rv] = (void*)((w64!=0) ? w64:vtlbDefaultPhyWrite64);
vtlbdata.RWFT[4][1][rv] = (void*)((w128!=0) ? w128:vtlbDefaultPhyWrite128);
vtlbdata.RWFT[0][1][rv] = (void*)((w8!=0) ? w8 : vtlbDefaultPhyWriteSm<mem8_t>);
vtlbdata.RWFT[1][1][rv] = (void*)((w16!=0) ? w16 : vtlbDefaultPhyWriteSm<mem16_t>);
vtlbdata.RWFT[2][1][rv] = (void*)((w32!=0) ? w32 : vtlbDefaultPhyWriteSm<mem32_t>);
vtlbdata.RWFT[3][1][rv] = (void*)((w64!=0) ? w64 : vtlbDefaultPhyWriteLg<mem64_t>);
vtlbdata.RWFT[4][1][rv] = (void*)((w128!=0) ? w128 : vtlbDefaultPhyWriteLg<mem128_t>);
}
vtlbHandler vtlb_NewHandler()
@ -368,7 +332,7 @@ vtlbHandler vtlb_NewHandler()
//
// Returns a handle for the newly created handler See vtlb_MapHandler for use of the return value.
//
vtlbHandler vtlb_RegisterHandler( vtlbMemR8FP* r8,vtlbMemR16FP* r16,vtlbMemR32FP* r32,vtlbMemR64FP* r64,vtlbMemR128FP* r128,
__ri vtlbHandler vtlb_RegisterHandler( vtlbMemR8FP* r8,vtlbMemR16FP* r16,vtlbMemR32FP* r32,vtlbMemR64FP* r64,vtlbMemR128FP* r128,
vtlbMemW8FP* w8,vtlbMemW16FP* w16,vtlbMemW32FP* w32,vtlbMemW64FP* w64,vtlbMemW128FP* w128)
{
vtlbHandler rv = vtlb_NewHandler();
@ -377,7 +341,6 @@ vtlbHandler vtlb_RegisterHandler( vtlbMemR8FP* r8,vtlbMemR16FP* r16,vtlbMemR32FP
}
//////////////////////////////////////////////////////////////////////////////////////////
// Maps the given hander (created with vtlb_RegisterHandler) to the specified memory region.
// New mappings always assume priority over previous mappings, so place "generic" mappings for
// large areas of memory first, and then specialize specific small regions of memory afterward.
@ -517,38 +480,29 @@ void vtlb_VMapUnmap(u32 vaddr,u32 sz)
}
}
//////////////////////////////////////////////////////////////////////////////////////////
// vtlb_init -- Clears vtlb handlers and memory mappings.
// vtlb_Init -- Clears vtlb handlers and memory mappings.
void vtlb_Init()
{
vtlbHandlerCount=0;
memzero(vtlbdata.RWFT);
#define VTLB_BuildUnmappedHandler(baseName, highBit) \
baseName##ReadSm<mem8_t,0>, baseName##ReadSm<mem16_t,0>, baseName##ReadSm<mem32_t,0>, \
baseName##ReadLg<mem64_t,0>, baseName##ReadLg<mem128_t,0>, \
baseName##WriteSm<mem8_t,0>, baseName##WriteSm<mem16_t,0>, baseName##WriteSm<mem32_t,0>, \
baseName##WriteLg<mem64_t,0>, baseName##WriteLg<mem128_t,0>
//Register default handlers
//Unmapped Virt handlers _MUST_ be registered first.
//On address translation the top bit cannot be preserved.This is not normaly a problem since
//the physical address space can be 'compressed' to just 29 bits.However, to properly handle exceptions
//there must be a way to get the full address back.Thats why i use these 2 functions and encode the hi bit directly into em :)
UnmappedVirtHandler0 = vtlb_RegisterHandler(
vtlbUnmappedVRead8<0>,vtlbUnmappedVRead16<0>,vtlbUnmappedVRead32<0>,vtlbUnmappedVRead64<0>,vtlbUnmappedVRead128<0>,
vtlbUnmappedVWrite8<0>,vtlbUnmappedVWrite16<0>,vtlbUnmappedVWrite32<0>,vtlbUnmappedVWrite64<0>,vtlbUnmappedVWrite128<0>
);
UnmappedVirtHandler0 = vtlb_RegisterHandler( VTLB_BuildUnmappedHandler(vtlbUnmappedV, 0) );
UnmappedVirtHandler1 = vtlb_RegisterHandler( VTLB_BuildUnmappedHandler(vtlbUnmappedV, 0x80000000) );
UnmappedVirtHandler1 = vtlb_RegisterHandler(
vtlbUnmappedVRead8<0x80000000>,vtlbUnmappedVRead16<0x80000000>,vtlbUnmappedVRead32<0x80000000>, vtlbUnmappedVRead64<0x80000000>,vtlbUnmappedVRead128<0x80000000>,
vtlbUnmappedVWrite8<0x80000000>,vtlbUnmappedVWrite16<0x80000000>,vtlbUnmappedVWrite32<0x80000000>, vtlbUnmappedVWrite64<0x80000000>,vtlbUnmappedVWrite128<0x80000000>
);
UnmappedPhyHandler0 = vtlb_RegisterHandler(
vtlbUnmappedPRead8<0>,vtlbUnmappedPRead16<0>,vtlbUnmappedPRead32<0>,vtlbUnmappedPRead64<0>,vtlbUnmappedPRead128<0>,
vtlbUnmappedPWrite8<0>,vtlbUnmappedPWrite16<0>,vtlbUnmappedPWrite32<0>,vtlbUnmappedPWrite64<0>,vtlbUnmappedPWrite128<0>
);
UnmappedPhyHandler1 = vtlb_RegisterHandler(
vtlbUnmappedPRead8<0x80000000>,vtlbUnmappedPRead16<0x80000000>,vtlbUnmappedPRead32<0x80000000>, vtlbUnmappedPRead64<0x80000000>,vtlbUnmappedPRead128<0x80000000>,
vtlbUnmappedPWrite8<0x80000000>,vtlbUnmappedPWrite16<0x80000000>,vtlbUnmappedPWrite32<0x80000000>, vtlbUnmappedPWrite64<0x80000000>,vtlbUnmappedPWrite128<0x80000000>
);
UnmappedPhyHandler0 = vtlb_RegisterHandler( VTLB_BuildUnmappedHandler(vtlbUnmappedP, 0) );
UnmappedPhyHandler1 = vtlb_RegisterHandler( VTLB_BuildUnmappedHandler(vtlbUnmappedP, 0x80000000) );
DefaultPhyHandler = vtlb_RegisterHandler(0,0,0,0,0,0,0,0,0,0);
@ -566,7 +520,6 @@ void vtlb_Init()
vtlb_dynarec_init();
}
//////////////////////////////////////////////////////////////////////////////////////////
// vtlb_Reset -- Performs a COP0-level reset of the PS2's TLB.
// This function should probably be part of the COP0 rather than here in VTLB.
void vtlb_Reset()
@ -579,7 +532,6 @@ void vtlb_Term()
//nothing to do for now
}
//////////////////////////////////////////////////////////////////////////////////////////
// Reserves the vtlb core allocation used by various emulation components!
//
void vtlb_Core_Alloc()
@ -594,12 +546,10 @@ void vtlb_Core_Alloc()
// Win32 just needs this, since malloc always maps below 2GB.
vtlbdata.alloc_base = (u8*)_aligned_malloc( VTLB_ALLOC_SIZE, 4096 );
if( vtlbdata.alloc_base == NULL )
throw Exception::OutOfMemory( L"PS2 mappable system ram (42 megs)" );
throw Exception::OutOfMemory( pxsFmt(L"PS2 mappable system ram (%u megs)", VTLB_ALLOC_SIZE / _1mb) );
#endif
}
//////////////////////////////////////////////////////////////////////////////////////////
//
void vtlb_Core_Shutdown()
{
if( vtlbdata.alloc_base == NULL ) return;
@ -614,7 +564,6 @@ void vtlb_Core_Shutdown()
}
//////////////////////////////////////////////////////////////////////////////////////////
// This function allocates memory block with are compatible with the Vtlb's requirements
// for memory locations. The Vtlb requires the topmost bit (Sign bit) of the memory
// pointer to be cleared. Some operating systems and/or implementations of malloc do that,
@ -628,16 +577,16 @@ u8* vtlb_malloc( uint size, uint align )
int rv = vtlbdata.alloc_current;
vtlbdata.alloc_current += size;
pxAssertDev( vtlbdata.alloc_current < VTLB_ALLOC_SIZE, "(vtlb_malloc) memory overflow! Please increase the size of VTLB_ALLOC_SIZE!" );
return &vtlbdata.alloc_base[rv];
}
//////////////////////////////////////////////////////////////////////////////////////////
//
void vtlb_free( void* pmem, uint size )
{
// Does nothing anymore! Alloc/dealloc is now handled by vtlb_Core_Alloc /
// vtlb_Core_Shutdown. Placebo is left in place in case it becomes useful again
// at a later date.
vtlbdata.alloc_current -= size;
pxAssertDev( vtlbdata.alloc_current >= 0, "(vtlb_free) mismatched calls to vtlb_malloc and free detected via memory underflow." );
return;
}

View File

@ -15,6 +15,8 @@
#pragma once
#include "MemoryTypes.h"
// Specialized function pointers for each read type
typedef mem8_t __fastcall vtlbMemR8FP(u32 addr);
typedef mem16_t __fastcall vtlbMemR16FP(u32 addr);
@ -65,16 +67,14 @@ extern void vtlb_VMapUnmap(u32 vaddr,u32 sz);
//Memory functions
extern mem8_t __fastcall vtlb_memRead8(u32 mem);
extern mem16_t __fastcall vtlb_memRead16(u32 mem);
extern u32 __fastcall vtlb_memRead32(u32 mem);
template< typename DataType >
extern DataType __fastcall vtlb_memRead(u32 mem);
extern void __fastcall vtlb_memRead64(u32 mem, mem64_t *out);
extern void __fastcall vtlb_memRead128(u32 mem, mem128_t *out);
extern void __fastcall vtlb_memRead128(u32 mem, u64 (&out)[2]);
extern void __fastcall vtlb_memWrite8 (u32 mem, mem8_t value);
extern void __fastcall vtlb_memWrite16(u32 mem, mem16_t value);
extern void __fastcall vtlb_memWrite32(u32 mem, u32 value);
template< typename DataType >
extern void __fastcall vtlb_memWrite(u32 mem, DataType value);
extern void __fastcall vtlb_memWrite64(u32 mem, const mem64_t* value);
extern void __fastcall vtlb_memWrite128(u32 mem, const mem128_t* value);
extern void __fastcall vtlb_memWrite128(u32 mem, const u64 (&value)[2]);
@ -89,7 +89,9 @@ extern void vtlb_DynGenRead32_Const( u32 bits, bool sign, u32 addr_const );
namespace vtlb_private
{
static const uint VTLB_ALLOC_SIZE = 0x2900000; //this is a bit more than required
// Allocate enough memory for both EE and IOP memory space (IOP is roughly 2.5mb,
// so we alloc 4mb for now -- a little more than is needed).
static const uint VTLB_ALLOC_SIZE = sizeof(*eeMem) + (_1mb*4);
static const uint VTLB_PAGE_BITS = 12;
static const uint VTLB_PAGE_MASK = 4095;

View File

@ -1082,7 +1082,7 @@ BOOL CALLBACK BrowserProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam)
case IDC_SKIPMPEG:
{
u8 *p = PS2MEM_BASE;
u8 *p = eeMem->Main;
u8 *d = p + Ps2MemSize::Base;
d -= 16;
u32 *u;
@ -1093,7 +1093,7 @@ BOOL CALLBACK BrowserProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam)
//if( (u[0] == 0x4000838c) && (u[1] == 0x0800e003) && (u[2] == 0x0000628c) )
if( (u[0] == 0x8c830040) && (u[1] == 0x03e00008) && (u[2] == 0x8c620000) )
{
AddPatch(1,1, (int)(p+8-PS2MEM_BASE), 3, 0x24020001);
AddPatch(1,1, (int)(p+8-eeMem->Main), 3, 0x24020001);
MessageBox(hWnd, "Patch Found.", "Patch", 0);
RefreshListBox(hWnd);
return FALSE;

View File

@ -431,7 +431,7 @@ BOOL CALLBACK FinderProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam)
return FALSE;
case WM_INITDIALOG:
mptr[0]=psM;
mptr[0]=eeMem->Main;
mptr[1]=psxM;
hWndFinder=hWnd;

View File

@ -1322,12 +1322,12 @@ bool skipMPEG_By_Pattern(u32 sPC) {
if (!CHECK_SKIPMPEGHACK) return 0;
// sceMpegIsEnd: lw reg, 0x40(a0); jr ra; lw v0, 0(reg)
if ((s_nEndBlock == sPC + 12) && (vtlb_memRead32(sPC + 4) == 0x03e00008)) {
u32 code = vtlb_memRead32(sPC);
if ((s_nEndBlock == sPC + 12) && (memRead32(sPC + 4) == 0x03e00008)) {
u32 code = memRead32(sPC);
u32 p1 = 0x8c800040;
u32 p2 = 0x8c020000 | (code & 0x1f0000) << 5;
if ((code & 0xffe0ffff) != p1) return 0;
if (vtlb_memRead32(sPC+8) != p2) return 0;
if (memRead32(sPC+8) != p2) return 0;
xMOV(ptr32[&cpuRegs.GPR.n.v0.UL[0]], 1);
xMOV(ptr32[&cpuRegs.GPR.n.v0.UL[1]], 0);
xMOV(eax, ptr32[&cpuRegs.GPR.n.ra.UL[0]]);

View File

@ -277,12 +277,15 @@ static void DynGen_IndirectDispatch( int mode, int bits )
xJS( GetIndirectDispatcherPtr( mode, szidx ) );
}
//////////////////////////////////////////////////////////////////////////////////////////
// One-time initialization procedure. Calling it multiple times shouldn't
// hurt anything tho.
// One-time initialization procedure. Multiple subsequent calls during the lifespan of the
// process will be ignored.
//
void vtlb_dynarec_init()
{
static bool hasBeenCalled = false;
if (hasBeenCalled) return;
hasBeenCalled = true;
// In case init gets called multiple times:
HostSys::MemProtectStatic( m_IndirectDispatchers, Protect_ReadWrite, false );

View File

@ -63,32 +63,32 @@ const __aligned(32) mVU_Globals mVUglob = {
// Micro VU - Main Functions
//------------------------------------------------------------------
__fi void mVUthrowHardwareDeficiency(const wxChar* extFail, int vuIndex) {
static __fi void mVUthrowHardwareDeficiency(const wxChar* extFail, int vuIndex) {
throw Exception::HardwareDeficiency()
.SetDiagMsg(wxsFormat(L"microVU%d recompiler init failed: %s is not available.", vuIndex, extFail))
.SetUserMsg(wxsFormat(_("%s Extensions not found. microVU requires a host CPU with MMX, SSE, and SSE2 extensions."), extFail ));
}
// Only run this once per VU! ;)
__fi void mVUinit(VURegs* vuRegsPtr, int vuIndex) {
static __ri void mVUinit(int vuIndex) {
if(!x86caps.hasMultimediaExtensions) mVUthrowHardwareDeficiency( L"MMX", vuIndex );
if(!x86caps.hasStreamingSIMDExtensions) mVUthrowHardwareDeficiency( L"SSE", vuIndex );
if(!x86caps.hasStreamingSIMD2Extensions) mVUthrowHardwareDeficiency( L"SSE2", vuIndex );
microVU* mVU = mVUx;
memset(&mVU->prog, 0, sizeof(mVU->prog));
memzero(mVU->prog);
mVU->regs = vuRegsPtr;
mVU->index = vuIndex;
mVU->cop2 = 0;
mVU->vuMemSize = (vuIndex ? 0x4000 : 0x1000);
mVU->microMemSize = (vuIndex ? 0x4000 : 0x1000);
mVU->progSize = (vuIndex ? 0x4000 : 0x1000) / 4;
mVU->progMemMask = mVU->progSize-1;
mVU->dispCache = NULL;
mVU->cache = NULL;
mVU->cacheSize = mVUcacheSize;
mVU->regAlloc = new microRegAlloc(mVU->regs);
mVU->regAlloc = new microRegAlloc();
for (u32 i = 0; i < (mVU->progSize / 2); i++) {
mVU->prog.prog[i] = new deque<microProgram*>();
@ -98,19 +98,31 @@ __fi void mVUinit(VURegs* vuRegsPtr, int vuIndex) {
if (!mVU->dispCache) throw Exception::OutOfMemory( mVU->index ? L"Micro VU1 Dispatcher" : L"Micro VU0 Dispatcher" );
memset(mVU->dispCache, 0xcc, mVUdispCacheSize);
// Setup Entrance/Exit Points
x86SetPtr(mVU->dispCache);
mVUdispatcherA(mVU);
mVUdispatcherB(mVU);
mVUemitSearch();
// Allocates rec-cache and calls mVUreset()
mVUresizeCache(mVU, mVU->cacheSize + mVUcacheSafeZone);
//if (vuIndex) gen_memcpy_vibes();
}
// Resets Rec Data
__fi void mVUreset(mV) {
// If vuRegsPtr is NUL, the current regs pointer assigned to the VU compiler is assumed.
static __fi void mVUreset(mV, VURegs* vuRegsPtr) {
static bool dispatchersGenerated = false;
if (!vuRegsPtr) vuRegsPtr = mVU->regs;
if (!dispatchersGenerated || (mVU->regs != vuRegsPtr))
{
// Setup Entrance/Exit Points
// These must be rebuilt whenever the vuRegsPtr has changed.
dispatchersGenerated = true;
mVU->regs = vuRegsPtr;
x86SetPtr(mVU->dispCache);
mVUdispatcherA(mVU);
mVUdispatcherB(mVU);
mVUemitSearch();
}
// Clear All Program Data
//memset(&mVU->prog, 0, sizeof(mVU->prog));
@ -146,7 +158,7 @@ __fi void mVUreset(mV) {
}
// Free Allocated Resources
__fi void mVUclose(mV) {
static __fi void mVUclose(mV) {
if (mVU->dispCache) { HostSys::Munmap(mVU->dispCache, mVUdispCacheSize); mVU->dispCache = NULL; }
if (mVU->cache) { HostSys::Munmap(mVU->cache, mVU->cacheSize); mVU->cache = NULL; }
@ -160,11 +172,9 @@ __fi void mVUclose(mV) {
}
safe_delete(mVU->prog.prog[i]);
}
safe_delete(mVU->regAlloc);
}
void mVUresizeCache(mV, u32 size) {
static void mVUresizeCache(mV, u32 size) {
if (size >= (u32)mVUcacheMaxSize) {
if (mVU->cacheSize==mVUcacheMaxSize) {
@ -194,7 +204,7 @@ void mVUresizeCache(mV, u32 size) {
}
// Clears Block Data in specified range
__fi void mVUclear(mV, u32 addr, u32 size) {
static __fi void mVUclear(mV, u32 addr, u32 size) {
if (!mVU->prog.cleared) {
memzero(mVU->prog.lpState); // Clear pipeline state
mVU->prog.cleared = 1; // Next execution searches/creates a new microprogram
@ -210,7 +220,7 @@ __fi void mVUclear(mV, u32 addr, u32 size) {
//------------------------------------------------------------------
// Finds and Ages/Kills Programs if they haven't been used in a while.
__fi void mVUvsyncUpdate(mV) {
static __fi void mVUvsyncUpdate(mV) {
//mVU->prog.curFrame++;
}
@ -324,14 +334,14 @@ void recMicroVU0::Allocate() {
if(!m_AllocCount) {
m_AllocCount++;
if (AtomicExchange(mvu0_allocated, 1) == 0)
mVUinit(&VU0, 0);
mVUinit(0);
}
}
void recMicroVU1::Allocate() {
if(!m_AllocCount) {
m_AllocCount++;
if (AtomicExchange(mvu1_allocated, 1) == 0)
mVUinit(&VU1, 1);
mVUinit(1);
}
}
@ -352,11 +362,11 @@ void recMicroVU1::Shutdown() throw() {
void recMicroVU0::Reset() {
if(!pxAssertDev(m_AllocCount, "MicroVU0 CPU Provider has not been allocated prior to reset!")) return;
mVUreset(&microVU0);
mVUreset(&microVU0, &VU0);
}
void recMicroVU1::Reset() {
if(!pxAssertDev(m_AllocCount, "MicroVU1 CPU Provider has not been allocated prior to reset!")) return;
mVUreset(&microVU1);
mVUreset(&microVU1, &VU1);
}
void recMicroVU0::Execute(u32 cycles) {

View File

@ -172,6 +172,7 @@ struct microVU {
u32 vuMemSize; // VU Main Memory Size (in bytes)
u32 microMemSize; // VU Micro Memory Size (in bytes)
u32 progSize; // VU Micro Memory Size (in u32's)
u32 progMemMask; // VU Micro Memory Size (in u32's)
u32 cacheSize; // VU Cache Size
microProgManager prog; // Micro Program Data
@ -204,12 +205,12 @@ extern __aligned16 microVU microVU1;
int mVUdebugNow = 0;
// Main Functions
extern void mVUinit(VURegs*, int);
extern void mVUreset(mV);
extern void mVUclose(mV);
extern void mVUclear(mV, u32, u32);
extern void mVUresizeCache(mV, u32);
extern void* mVUblockFetch(microVU* mVU, u32 startPC, uptr pState);
static void mVUinit(int);
static void mVUreset(mV, VURegs* vuRegsPtr = NULL);
static void mVUclose(mV);
static void mVUclear(mV, u32, u32);
static void mVUresizeCache(mV, u32);
static void* mVUblockFetch(microVU* mVU, u32 startPC, uptr pState);
_mVUt extern void* __fastcall mVUcompileJIT(u32 startPC, uptr pState);
// Prototypes for Linux

View File

@ -393,8 +393,8 @@ void* mVUcompile(microVU* mVU, u32 startPC, uptr pState) {
// First Pass
iPC = startPC / 4;
mVUsetupRange(mVU, startPC, 1); // Setup Program Bounds/Range
mVU->regAlloc->reset(); // Reset regAlloc
mVUsetupRange(mVU, startPC, 1); // Setup Program Bounds/Range
mVU->regAlloc->reset(mVU->regs); // Reset regAlloc
mVUinitFirstPass(mVU, pState, thisPtr);
for (int branch = 0; mVUcount < endCount; mVUcount++) {
incPC(1);
@ -466,14 +466,14 @@ void* mVUcompile(microVU* mVU, u32 startPC, uptr pState) {
}
// Returns the entry point of the block (compiles it if not found)
__fi void* mVUentryGet(microVU* mVU, microBlockManager* block, u32 startPC, uptr pState) {
static __fi void* mVUentryGet(microVU* mVU, microBlockManager* block, u32 startPC, uptr pState) {
microBlock* pBlock = block->search((microRegInfo*)pState);
if (pBlock) return pBlock->x86ptrStart;
else return mVUcompile(mVU, startPC, pState);
}
// Search for Existing Compiled Block (if found, return x86ptr; else, compile and return x86ptr)
__fi void* mVUblockFetch(microVU* mVU, u32 startPC, uptr pState) {
static __fi void* mVUblockFetch(microVU* mVU, u32 startPC, uptr pState) {
if (startPC > mVU->microMemSize-8) { DevCon.Error("microVU%d: invalid startPC [%04x]", mVU->index, startPC); }
startPC &= mVU->microMemSize-8;

View File

@ -198,11 +198,10 @@ private:
}
public:
microRegAlloc(VURegs* vuRegsPtr) {
microRegAlloc() { }
void reset(VURegs* vuRegsPtr) {
vuRegs = vuRegsPtr;
reset();
}
void reset() {
for (int i = 0; i < xmmTotal; i++) {
clearReg(i);
}

View File

@ -36,7 +36,7 @@ void setupMacroOp(int mode, const char* opName) {
microVU0.code = cpuRegs.code;
memset(&microVU0.prog.IRinfo.info[0], 0, sizeof(microVU0.prog.IRinfo.info[0]));
iFlushCall(FLUSH_EVERYTHING);
microVU0.regAlloc->reset();
microVU0.regAlloc->reset(microVU0.regs);
if (mode & 0x01) { // Q-Reg will be Read
xMOVSSZX(xmmPQ, ptr32[&microVU0.regs->VI[REG_Q].UL]);
}

View File

@ -1,246 +1,245 @@
/* PCSX2 - PS2 Emulator for PCs
* Copyright (C) 2002-2010 PCSX2 Dev Team
*
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
* of the GNU Lesser General Public License as published by the Free Software Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* PCSX2 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 PCSX2.
* If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
extern BaseVUmicroCPU* getVUprovider(int whichProvider, int vuIndex);
SysCoreAllocations& GetSysCoreAlloc();
void runSVU1(u32 cycles) {
do { // while loop needed since not always will return finished
SuperVUExecuteProgram(VU1.VI[REG_TPC].UL & 0x3ff8, 1);
} while( VU0.VI[REG_VPU_STAT].UL&0x100 );
}
void runMVU1(u32 cycles) {
GetSysCoreAlloc().getVUprovider(2, 1)->Execute(cycles);
}
void clearSVU1(u32 Addr, u32 Size) {
SuperVUClear(Addr, Size, 1);
}
void clearMVU1(u32 Addr, u32 Size) {
GetSysCoreAlloc().getVUprovider(2, 1)->Clear(Addr, Size);
}
void recSuperVU1::Clear(u32 Addr, u32 Size) {
clearSVU1(Addr, Size);
clearMVU1(Addr, Size);
}
void resetSVU1() {
GetSysCoreAlloc().getVUprovider(1, 1)->Reset();
}
void resetMVU1() {
GetSysCoreAlloc().getVUprovider(2, 1)->Reset();
}
extern int mVUdebugNow;
static u32 runCount = 0;
__aligned16 u8 backVUregs[sizeof(VURegs)];
__aligned16 u8 cmpVUregs [sizeof(VURegs)];
__aligned16 u8 backVUmem [0x4000];
__aligned16 u8 cmpVUmem [0x4000];
#define VU3 (*(VURegs*)cmpVUregs)
#define fABS(aInt) (aInt & 0x7fffffff)
//#define cmpU(uA, uB) (fABS(uA) != fABS(uB))
#define cmpU(uA, uB) (uA != uB)
#define cmpA Console.Error
#define cmpB Console.WriteLn
#define cmpPrint(cond) { \
if (cond) { \
cmpA("%s", str1); \
cmpA("%s", str2); \
/*mVUdebugNow = 1;*/\
} \
else { \
cmpB("%s", str1); \
cmpB("%s", str2); \
} \
}
//#define DEBUG_COMPARE // Run sVU or mVU and print results
//#define DEBUG_COMPARE2 // Runs both VU recs and breaks when results differ
#ifdef DEBUG_COMPARE
static int runAmount = 0;
void VUtestPause() {
runAmount++;
if (runAmount < 654) return;
if (useMVU1) SysPrintf("Micro VU - Pass %d\n", runAmount);
else SysPrintf("Super VU - Pass %d\n", runAmount);
for (int i = 0; i < 32; i++) {
SysPrintf("VF%02d = {%f, %f, %f, %f}\n", i, VU1.VF[i].F[0], VU1.VF[i].F[1], VU1.VF[i].F[2], VU1.VF[i].F[3]);
}
SysPrintf("ACC = {%f, %f, %f, %f}\n", VU1.ACC.F[0], VU1.ACC.F[1], VU1.ACC.F[2], VU1.ACC.F[3]);
for (int i = 0; i < 16; i++) {
SysPrintf("VI%02d = % 8d ($%08x)\n", i, (s16)VU1.VI[i].UL, (s16)VU1.VI[i].UL);
}
SysPrintf("Stat = % 8d ($%08x)\n", (s16)VU1.VI[REG_STATUS_FLAG].UL, (s16)VU1.VI[REG_STATUS_FLAG].UL);
SysPrintf("MAC = % 8d ($%08x)\n", (s16)VU1.VI[REG_MAC_FLAG].UL, (s16)VU1.VI[REG_MAC_FLAG].UL);
SysPrintf("CLIP = % 8d ($%08x)\n", (s16)VU1.VI[REG_CLIP_FLAG].UL, (s16)VU1.VI[REG_CLIP_FLAG].UL);
SysPrintf("Q-reg = %f ($%08x)\n", VU1.VI[REG_Q].F, (s32)VU1.VI[REG_Q].UL);
SysPrintf("P-reg = %f ($%08x)\n", VU1.VI[REG_P].F, (s32)VU1.VI[REG_P].UL);
SysPrintf("I-reg = %f ($%08x)\n", VU1.VI[REG_I].F, (s32)VU1.VI[REG_I].UL);
SysPrintf("_Stat = % 8d ($%08x)\n", (s16)VU1.statusflag, (s16)VU1.statusflag);
SysPrintf("_MAC = % 8d ($%08x)\n", (s16)VU1.macflag, (s16)VU1.macflag);
SysPrintf("_CLIP = % 8d ($%08x)\n", (s16)VU1.clipflag, (s16)VU1.clipflag);
u32 j = 0;
for (int i = 0; i < (0x4000 / 4); i++) {
j ^= ((u32*)(VU1.Mem))[i];
}
SysPrintf("VU Mem CRC = 0x%08x\n", j);
SysPrintf("EndPC = 0x%04x\n", VU1.VI[REG_TPC].UL);
// ... wtf?? --air
for (int i = 0; i < 10000000; i++) {
Threading::Sleep(1000);
}
}
#else
void VUtestPause() {}
#endif
void recSuperVU1::Execute(u32 cycles) {
cycles = 0x7fffffff;
if((VU0.VI[REG_VPU_STAT].UL & 0x100) == 0) return;
if (VU1.VI[REG_TPC].UL >= VU1.maxmicro) { Console.Error("VU1 memory overflow!!: %x", VU1.VI[REG_TPC].UL); }
#ifdef DEBUG_COMPARE
SysPrintf("(%08d) StartPC = 0x%04x\n", runAmount, VU1.VI[REG_TPC].UL);
#endif
runCount++;
memcpy_const((u8*)backVUregs, (u8*)&VU1, sizeof(VURegs));
memcpy_const((u8*)backVUmem, (u8*) VU1.Mem, 0x4000);
runMVU1(cycles);
memcpy_const((u8*)cmpVUregs,(u8*)&VU1, sizeof(VURegs));
memcpy_const((u8*)cmpVUmem, (u8*)VU1.Mem, 0x4000);
memcpy_const((u8*)&VU1, (u8*)backVUregs, sizeof(VURegs));
memcpy_const((u8*)VU1.Mem, (u8*)backVUmem, 0x4000);
runSVU1(cycles);
if ((memcmp((u8*)cmpVUregs, (u8*)&VU1, (16*32) + (16*16))) || (memcmp((u8*)cmpVUmem, (u8*)VU1.Mem, 0x4000))) {
static char str1[1000];
static char str2[1000];
Console.WriteLn("\n\n");
Console.WriteLn("-----------------------------------------------\n");
Console.Warning("Problem Occurred!");
Console.WriteLn("-----------------------------------------------\n");
Console.WriteLn("runCount = %d\n", runCount);
Console.WriteLn("StartPC [%04x]\n", ((VURegs*)backVUregs)->VI[REG_TPC].UL);
Console.WriteLn("-----------------------------------------------\n\n");
Console.WriteLn("-----------------------------------------------\n");
Console.Warning("Micro VU / Super VU");
Console.WriteLn("-----------------------------------------------\n");
for (int i = 0; i < 32; i++) {
sprintf(str1, "VF%02d = {%f, %f, %f, %f}", i, VU3.VF[i].F[0], VU3.VF[i].F[1], VU3.VF[i].F[2], VU3.VF[i].F[3]);
sprintf(str2, "VF%02d = {%f, %f, %f, %f}", i, VU1.VF[i].F[0], VU1.VF[i].F[1], VU1.VF[i].F[2], VU1.VF[i].F[3]);
cmpPrint((cmpU(VU1.VF[i].UL[0], VU3.VF[i].UL[0]) || cmpU(VU1.VF[i].UL[1], VU3.VF[i].UL[1]) || cmpU(VU1.VF[i].UL[2], VU3.VF[i].UL[2]) || cmpU(VU1.VF[i].UL[3], VU3.VF[i].UL[3])));
}
sprintf(str1, "ACC = {%f, %f, %f, %f}", VU3.ACC.F[0], VU3.ACC.F[1], VU3.ACC.F[2], VU3.ACC.F[3]);
sprintf(str2, "ACC = {%f, %f, %f, %f}", VU1.ACC.F[0], VU1.ACC.F[1], VU1.ACC.F[2], VU1.ACC.F[3]);
cmpPrint((cmpU(VU1.ACC.UL[0], VU3.ACC.UL[0]) || cmpU(VU1.ACC.UL[1], VU3.ACC.UL[1]) || cmpU(VU1.ACC.UL[2], VU3.ACC.UL[2]) || cmpU(VU1.ACC.UL[3], VU3.ACC.UL[3])));
for (int i = 0; i < 16; i++) {
sprintf(str1, "VI%02d = % 8d ($%08x)", i, (s16)VU3.VI[i].UL, VU3.VI[i].UL);
sprintf(str2, "VI%02d = % 8d ($%08x)", i, (s16)VU1.VI[i].UL, VU1.VI[i].UL);
cmpPrint((VU1.VI[i].UL != VU3.VI[i].UL));
}
sprintf(str1, "Stat = % 8d ($%08x)", (s16)VU3.VI[REG_STATUS_FLAG].UL, VU3.VI[REG_STATUS_FLAG].UL);
sprintf(str2, "Stat = % 8d ($%08x)", (s16)VU1.VI[REG_STATUS_FLAG].UL, VU1.VI[REG_STATUS_FLAG].UL);
cmpPrint((VU1.VI[REG_STATUS_FLAG].UL != VU3.VI[REG_STATUS_FLAG].UL));
sprintf(str1, "MAC = % 8d ($%08x)", (s16)VU3.VI[REG_MAC_FLAG].UL, VU3.VI[REG_MAC_FLAG].UL);
sprintf(str2, "MAC = % 8d ($%08x)", (s16)VU1.VI[REG_MAC_FLAG].UL, VU1.VI[REG_MAC_FLAG].UL);
cmpPrint((VU1.VI[REG_MAC_FLAG].UL != VU3.VI[REG_MAC_FLAG].UL));
sprintf(str1, "CLIP = % 8d ($%08x)", (s16)VU3.VI[REG_CLIP_FLAG].UL, VU3.VI[REG_CLIP_FLAG].UL);
sprintf(str2, "CLIP = % 8d ($%08x)", (s16)VU1.VI[REG_CLIP_FLAG].UL, VU1.VI[REG_CLIP_FLAG].UL);
cmpPrint((VU1.VI[REG_CLIP_FLAG].UL != VU3.VI[REG_CLIP_FLAG].UL));
sprintf(str1, "Q-reg = %f ($%08x)", VU3.VI[REG_Q].F, VU3.VI[REG_Q].UL);
sprintf(str2, "Q-reg = %f ($%08x)", VU1.VI[REG_Q].F, VU1.VI[REG_Q].UL);
cmpPrint((VU1.VI[REG_Q].UL != VU3.VI[REG_Q].UL));
sprintf(str1, "P-reg = %f ($%08x)", VU3.VI[REG_P].F, VU3.VI[REG_P].UL);
sprintf(str2, "P-reg = %f ($%08x)", VU1.VI[REG_P].F, VU1.VI[REG_P].UL);
cmpPrint((VU1.VI[REG_P].UL != VU3.VI[REG_P].UL));
sprintf(str1, "I-reg = %f ($%08x)", VU3.VI[REG_I].F, VU3.VI[REG_I].UL);
sprintf(str2, "I-reg = %f ($%08x)", VU1.VI[REG_I].F, VU1.VI[REG_I].UL);
cmpPrint((VU1.VI[REG_I].UL != VU3.VI[REG_I].UL));
sprintf(str1, "_Stat = % 8d ($%08x)", (s16)VU3.statusflag, VU3.statusflag);
sprintf(str2, "_Stat = % 8d ($%08x)", (s16)VU1.statusflag, VU1.statusflag);
cmpPrint((VU1.statusflag != VU3.statusflag));
sprintf(str1, "_MAC = % 8d ($%08x)", (s16)VU3.macflag, VU3.macflag);
sprintf(str2, "_MAC = % 8d ($%08x)", (s16)VU1.macflag, VU1.macflag);
cmpPrint((VU1.macflag != VU3.macflag));
sprintf(str1, "_CLIP = % 8d ($%08x)", (s16)VU3.clipflag, VU3.clipflag);
sprintf(str2, "_CLIP = % 8d ($%08x)", (s16)VU1.clipflag, VU1.clipflag);
cmpPrint((VU1.clipflag != VU3.clipflag));
u32 j = 0;
u32 z = 0;
for (int i = 0; i < (0x4000 / 4); i++) {
j ^= ((u32*)(cmpVUmem))[i];
z ^= ((u32*)(VU1.Mem)) [i];
}
sprintf(str1, "VU Mem CRC = 0x%08x", j);
sprintf(str2, "VU Mem CRC = 0x%08x", z);
cmpPrint((j != z));
sprintf(str1, "EndPC = 0x%04x", VU3.VI[REG_TPC].UL);
sprintf(str2, "EndPC = 0x%04x", VU1.VI[REG_TPC].UL);
cmpPrint((VU1.VI[REG_TPC].UL != VU3.VI[REG_TPC].UL));
Console.WriteLn("-----------------------------------------------\n\n");
/*
if (mVUdebugNow) {
resetMVU1();
memcpy_const((u8*)&VU1, (u8*)backVUregs, sizeof(VURegs));
memcpy_const((u8*)VU1.Mem, (u8*)backVUmem, 0x4000);
runMVU1(cycles);
for (int i = 0; i < 10000000; i++) {
Sleep(1000);
}
}*/
}
//VUtestPause();
}
/* PCSX2 - PS2 Emulator for PCs
* Copyright (C) 2002-2010 PCSX2 Dev Team
*
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
* of the GNU Lesser General Public License as published by the Free Software Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* PCSX2 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 PCSX2.
* If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
SysCpuProviderPack& GetCpuProviders();
void runSVU1(u32 cycles) {
do { // while loop needed since not always will return finished
SuperVUExecuteProgram(VU1.VI[REG_TPC].UL & 0x3ff8, 1);
} while( VU0.VI[REG_VPU_STAT].UL&0x100 );
}
void runMVU1(u32 cycles) {
GetCpuProviders().getVUprovider(2, 1)->Execute(cycles);
}
void clearSVU1(u32 Addr, u32 Size) {
SuperVUClear(Addr, Size, 1);
}
void clearMVU1(u32 Addr, u32 Size) {
GetCpuProviders().getVUprovider(2, 1)->Clear(Addr, Size);
}
void recSuperVU1::Clear(u32 Addr, u32 Size) {
clearSVU1(Addr, Size);
clearMVU1(Addr, Size);
}
void resetSVU1() {
GetCpuProviders().getVUprovider(1, 1)->Reset();
}
void resetMVU1() {
GetCpuProviders().getVUprovider(2, 1)->Reset();
}
extern int mVUdebugNow;
static u32 runCount = 0;
__aligned16 u8 backVUregs[sizeof(VURegs)];
__aligned16 u8 cmpVUregs [sizeof(VURegs)];
__aligned16 u8 backVUmem [0x4000];
__aligned16 u8 cmpVUmem [0x4000];
#define VU3 (*(VURegs*)cmpVUregs)
#define fABS(aInt) (aInt & 0x7fffffff)
//#define cmpU(uA, uB) (fABS(uA) != fABS(uB))
#define cmpU(uA, uB) (uA != uB)
#define cmpA Console.Error
#define cmpB Console.WriteLn
#define cmpPrint(cond) { \
if (cond) { \
cmpA("%s", str1); \
cmpA("%s", str2); \
/*mVUdebugNow = 1;*/\
} \
else { \
cmpB("%s", str1); \
cmpB("%s", str2); \
} \
}
//#define DEBUG_COMPARE // Run sVU or mVU and print results
//#define DEBUG_COMPARE2 // Runs both VU recs and breaks when results differ
#ifdef DEBUG_COMPARE
static int runAmount = 0;
void VUtestPause() {
runAmount++;
if (runAmount < 654) return;
if (useMVU1) SysPrintf("Micro VU - Pass %d\n", runAmount);
else SysPrintf("Super VU - Pass %d\n", runAmount);
for (int i = 0; i < 32; i++) {
SysPrintf("VF%02d = {%f, %f, %f, %f}\n", i, VU1.VF[i].F[0], VU1.VF[i].F[1], VU1.VF[i].F[2], VU1.VF[i].F[3]);
}
SysPrintf("ACC = {%f, %f, %f, %f}\n", VU1.ACC.F[0], VU1.ACC.F[1], VU1.ACC.F[2], VU1.ACC.F[3]);
for (int i = 0; i < 16; i++) {
SysPrintf("VI%02d = % 8d ($%08x)\n", i, (s16)VU1.VI[i].UL, (s16)VU1.VI[i].UL);
}
SysPrintf("Stat = % 8d ($%08x)\n", (s16)VU1.VI[REG_STATUS_FLAG].UL, (s16)VU1.VI[REG_STATUS_FLAG].UL);
SysPrintf("MAC = % 8d ($%08x)\n", (s16)VU1.VI[REG_MAC_FLAG].UL, (s16)VU1.VI[REG_MAC_FLAG].UL);
SysPrintf("CLIP = % 8d ($%08x)\n", (s16)VU1.VI[REG_CLIP_FLAG].UL, (s16)VU1.VI[REG_CLIP_FLAG].UL);
SysPrintf("Q-reg = %f ($%08x)\n", VU1.VI[REG_Q].F, (s32)VU1.VI[REG_Q].UL);
SysPrintf("P-reg = %f ($%08x)\n", VU1.VI[REG_P].F, (s32)VU1.VI[REG_P].UL);
SysPrintf("I-reg = %f ($%08x)\n", VU1.VI[REG_I].F, (s32)VU1.VI[REG_I].UL);
SysPrintf("_Stat = % 8d ($%08x)\n", (s16)VU1.statusflag, (s16)VU1.statusflag);
SysPrintf("_MAC = % 8d ($%08x)\n", (s16)VU1.macflag, (s16)VU1.macflag);
SysPrintf("_CLIP = % 8d ($%08x)\n", (s16)VU1.clipflag, (s16)VU1.clipflag);
u32 j = 0;
for (int i = 0; i < (0x4000 / 4); i++) {
j ^= ((u32*)(VU1.Mem))[i];
}
SysPrintf("VU Mem CRC = 0x%08x\n", j);
SysPrintf("EndPC = 0x%04x\n", VU1.VI[REG_TPC].UL);
// ... wtf?? --air
for (int i = 0; i < 10000000; i++) {
Threading::Sleep(1000);
}
}
#else
void VUtestPause() {}
#endif
void recSuperVU1::Execute(u32 cycles) {
cycles = 0x7fffffff;
if((VU0.VI[REG_VPU_STAT].UL & 0x100) == 0) return;
if (VU1.VI[REG_TPC].UL >= VU1.maxmicro) { Console.Error("VU1 memory overflow!!: %x", VU1.VI[REG_TPC].UL); }
#ifdef DEBUG_COMPARE
SysPrintf("(%08d) StartPC = 0x%04x\n", runAmount, VU1.VI[REG_TPC].UL);
#endif
runCount++;
memcpy_const((u8*)backVUregs, (u8*)&VU1, sizeof(VURegs));
memcpy_const((u8*)backVUmem, (u8*) VU1.Mem, 0x4000);
runMVU1(cycles);
memcpy_const((u8*)cmpVUregs,(u8*)&VU1, sizeof(VURegs));
memcpy_const((u8*)cmpVUmem, (u8*)VU1.Mem, 0x4000);
memcpy_const((u8*)&VU1, (u8*)backVUregs, sizeof(VURegs));
memcpy_const((u8*)VU1.Mem, (u8*)backVUmem, 0x4000);
runSVU1(cycles);
if ((memcmp((u8*)cmpVUregs, (u8*)&VU1, (16*32) + (16*16))) || (memcmp((u8*)cmpVUmem, (u8*)VU1.Mem, 0x4000))) {
static char str1[1000];
static char str2[1000];
Console.WriteLn("\n\n");
Console.WriteLn("-----------------------------------------------\n");
Console.Warning("Problem Occurred!");
Console.WriteLn("-----------------------------------------------\n");
Console.WriteLn("runCount = %d\n", runCount);
Console.WriteLn("StartPC [%04x]\n", ((VURegs*)backVUregs)->VI[REG_TPC].UL);
Console.WriteLn("-----------------------------------------------\n\n");
Console.WriteLn("-----------------------------------------------\n");
Console.Warning("Micro VU / Super VU");
Console.WriteLn("-----------------------------------------------\n");
for (int i = 0; i < 32; i++) {
sprintf(str1, "VF%02d = {%f, %f, %f, %f}", i, VU3.VF[i].F[0], VU3.VF[i].F[1], VU3.VF[i].F[2], VU3.VF[i].F[3]);
sprintf(str2, "VF%02d = {%f, %f, %f, %f}", i, VU1.VF[i].F[0], VU1.VF[i].F[1], VU1.VF[i].F[2], VU1.VF[i].F[3]);
cmpPrint((cmpU(VU1.VF[i].UL[0], VU3.VF[i].UL[0]) || cmpU(VU1.VF[i].UL[1], VU3.VF[i].UL[1]) || cmpU(VU1.VF[i].UL[2], VU3.VF[i].UL[2]) || cmpU(VU1.VF[i].UL[3], VU3.VF[i].UL[3])));
}
sprintf(str1, "ACC = {%f, %f, %f, %f}", VU3.ACC.F[0], VU3.ACC.F[1], VU3.ACC.F[2], VU3.ACC.F[3]);
sprintf(str2, "ACC = {%f, %f, %f, %f}", VU1.ACC.F[0], VU1.ACC.F[1], VU1.ACC.F[2], VU1.ACC.F[3]);
cmpPrint((cmpU(VU1.ACC.UL[0], VU3.ACC.UL[0]) || cmpU(VU1.ACC.UL[1], VU3.ACC.UL[1]) || cmpU(VU1.ACC.UL[2], VU3.ACC.UL[2]) || cmpU(VU1.ACC.UL[3], VU3.ACC.UL[3])));
for (int i = 0; i < 16; i++) {
sprintf(str1, "VI%02d = % 8d ($%08x)", i, (s16)VU3.VI[i].UL, VU3.VI[i].UL);
sprintf(str2, "VI%02d = % 8d ($%08x)", i, (s16)VU1.VI[i].UL, VU1.VI[i].UL);
cmpPrint((VU1.VI[i].UL != VU3.VI[i].UL));
}
sprintf(str1, "Stat = % 8d ($%08x)", (s16)VU3.VI[REG_STATUS_FLAG].UL, VU3.VI[REG_STATUS_FLAG].UL);
sprintf(str2, "Stat = % 8d ($%08x)", (s16)VU1.VI[REG_STATUS_FLAG].UL, VU1.VI[REG_STATUS_FLAG].UL);
cmpPrint((VU1.VI[REG_STATUS_FLAG].UL != VU3.VI[REG_STATUS_FLAG].UL));
sprintf(str1, "MAC = % 8d ($%08x)", (s16)VU3.VI[REG_MAC_FLAG].UL, VU3.VI[REG_MAC_FLAG].UL);
sprintf(str2, "MAC = % 8d ($%08x)", (s16)VU1.VI[REG_MAC_FLAG].UL, VU1.VI[REG_MAC_FLAG].UL);
cmpPrint((VU1.VI[REG_MAC_FLAG].UL != VU3.VI[REG_MAC_FLAG].UL));
sprintf(str1, "CLIP = % 8d ($%08x)", (s16)VU3.VI[REG_CLIP_FLAG].UL, VU3.VI[REG_CLIP_FLAG].UL);
sprintf(str2, "CLIP = % 8d ($%08x)", (s16)VU1.VI[REG_CLIP_FLAG].UL, VU1.VI[REG_CLIP_FLAG].UL);
cmpPrint((VU1.VI[REG_CLIP_FLAG].UL != VU3.VI[REG_CLIP_FLAG].UL));
sprintf(str1, "Q-reg = %f ($%08x)", VU3.VI[REG_Q].F, VU3.VI[REG_Q].UL);
sprintf(str2, "Q-reg = %f ($%08x)", VU1.VI[REG_Q].F, VU1.VI[REG_Q].UL);
cmpPrint((VU1.VI[REG_Q].UL != VU3.VI[REG_Q].UL));
sprintf(str1, "P-reg = %f ($%08x)", VU3.VI[REG_P].F, VU3.VI[REG_P].UL);
sprintf(str2, "P-reg = %f ($%08x)", VU1.VI[REG_P].F, VU1.VI[REG_P].UL);
cmpPrint((VU1.VI[REG_P].UL != VU3.VI[REG_P].UL));
sprintf(str1, "I-reg = %f ($%08x)", VU3.VI[REG_I].F, VU3.VI[REG_I].UL);
sprintf(str2, "I-reg = %f ($%08x)", VU1.VI[REG_I].F, VU1.VI[REG_I].UL);
cmpPrint((VU1.VI[REG_I].UL != VU3.VI[REG_I].UL));
sprintf(str1, "_Stat = % 8d ($%08x)", (s16)VU3.statusflag, VU3.statusflag);
sprintf(str2, "_Stat = % 8d ($%08x)", (s16)VU1.statusflag, VU1.statusflag);
cmpPrint((VU1.statusflag != VU3.statusflag));
sprintf(str1, "_MAC = % 8d ($%08x)", (s16)VU3.macflag, VU3.macflag);
sprintf(str2, "_MAC = % 8d ($%08x)", (s16)VU1.macflag, VU1.macflag);
cmpPrint((VU1.macflag != VU3.macflag));
sprintf(str1, "_CLIP = % 8d ($%08x)", (s16)VU3.clipflag, VU3.clipflag);
sprintf(str2, "_CLIP = % 8d ($%08x)", (s16)VU1.clipflag, VU1.clipflag);
cmpPrint((VU1.clipflag != VU3.clipflag));
u32 j = 0;
u32 z = 0;
for (int i = 0; i < (0x4000 / 4); i++) {
j ^= ((u32*)(cmpVUmem))[i];
z ^= ((u32*)(VU1.Mem)) [i];
}
sprintf(str1, "VU Mem CRC = 0x%08x", j);
sprintf(str2, "VU Mem CRC = 0x%08x", z);
cmpPrint((j != z));
sprintf(str1, "EndPC = 0x%04x", VU3.VI[REG_TPC].UL);
sprintf(str2, "EndPC = 0x%04x", VU1.VI[REG_TPC].UL);
cmpPrint((VU1.VI[REG_TPC].UL != VU3.VI[REG_TPC].UL));
Console.WriteLn("-----------------------------------------------\n\n");
/*
if (mVUdebugNow) {
resetMVU1();
memcpy_const((u8*)&VU1, (u8*)backVUregs, sizeof(VURegs));
memcpy_const((u8*)VU1.Mem, (u8*)backVUmem, 0x4000);
runMVU1(cycles);
for (int i = 0; i < 10000000; i++) {
Sleep(1000);
}
}*/
}
//VUtestPause();
}