Map uninstalled main memory (>32MB). I can't see any suggestion in the manuals that accessing these addresses generates a bus error or tlb miss (and they are in the bios default tlb initialisation), so I'm assuming that it acts as write only memory for both DMA and normal accesses. The write-only implementation is a little sketchy for DMA, but it's very unlikely to matter in practice.

Changed dmaGetAddr to not lookup addresses in the TLB.

git-svn-id: http://pcsx2.googlecode.com/svn/trunk@2883 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
sudonim1 2010-04-22 00:11:53 +00:00
parent 912a90a605
commit a21fb4b984
13 changed files with 104 additions and 41 deletions

View File

@ -211,7 +211,7 @@ union tDMA_QWC {
wxString desc() const { return wxsFormat(L"QWC: 0x%x", _u32); } wxString desc() const { return wxsFormat(L"QWC: 0x%x", _u32); }
}; };
static __forceinline void setDmacStat(u32 num); static __forceinline void setDmacStat(u32 num);
static __forceinline tDMA_TAG *dmaGetAddr(u32 addr); static __forceinline tDMA_TAG *dmaGetAddr(u32 addr, bool write);
static __forceinline void throwBusError(const char *s); static __forceinline void throwBusError(const char *s);
struct DMACh { struct DMACh {
@ -258,9 +258,9 @@ struct DMACh {
qwcTransfer(ptag); qwcTransfer(ptag);
} }
tDMA_TAG *getAddr(u32 addr, u32 num) tDMA_TAG *getAddr(u32 addr, u32 num, bool write)
{ {
tDMA_TAG *ptr = dmaGetAddr(addr); tDMA_TAG *ptr = dmaGetAddr(addr, write);
if (ptr == NULL) if (ptr == NULL)
{ {
throwBusError("dmaGetAddr"); throwBusError("dmaGetAddr");
@ -273,7 +273,7 @@ struct DMACh {
tDMA_TAG *DMAtransfer(u32 addr, u32 num) tDMA_TAG *DMAtransfer(u32 addr, u32 num)
{ {
tDMA_TAG *tag = getAddr(addr, num); tDMA_TAG *tag = getAddr(addr, num, false);
if (tag == NULL) return NULL; if (tag == NULL) return NULL;
@ -622,18 +622,14 @@ static __forceinline void setDmacStat(u32 num)
dmacRegs->stat.set_flags(1 << num); dmacRegs->stat.set_flags(1 << num);
} }
static __forceinline bool inScratchpad(u32 addr) static __forceinline bool inScratchpad(u32 addr)
{ {
return ((addr >=0x70000000) && (addr <= 0x70003fff)); return ((addr >=0x70000000) && (addr <= 0x70003fff));
} }
// Note: Dma addresses are guaranteed to be aligned to 16 bytes (128 bits) // Note: Dma addresses are guaranteed to be aligned to 16 bytes (128 bits)
static __forceinline tDMA_TAG *dmaGetAddr(u32 addr) static __forceinline tDMA_TAG *dmaGetAddr(u32 addr, bool write)
{ {
tDMA_TAG *ptr;
// if (addr & 0xf) { DMA_LOG("*PCSX2*: DMA address not 128bit aligned: %8.8x", addr); } // 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*)&psS[addr & 0x3ff0];
@ -645,13 +641,18 @@ static __forceinline tDMA_TAG *dmaGetAddr(u32 addr)
return (tDMA_TAG*)&psS[addr & 0x3ff0]; return (tDMA_TAG*)&psS[addr & 0x3ff0];
} }
ptr = (tDMA_TAG*)vtlb_GetPhyPtr(addr & 0x1FFFFFF0); if (addr > 0x10000000)
if (ptr == NULL)
{ {
Console.Error( "*PCSX2*: DMA error: %8.8x", addr); Console.Error( "*PCSX2*: DMA error: %8.8x", addr);
return NULL; return NULL;
} }
return ptr;
if (addr > Ps2MemSize::Base)
{
return (tDMA_TAG*)(write ? psMHW : psMHR);
}
return (tDMA_TAG*)&psM[addr];
} }
void hwIntcIrq(int n); void hwIntcIrq(int n);

View File

@ -112,7 +112,7 @@ int _GIFchain()
u32 qwc = min( gifsplit, (int)gif->qwc ); u32 qwc = min( gifsplit, (int)gif->qwc );
tDMA_TAG *pMem; tDMA_TAG *pMem;
pMem = dmaGetAddr(gif->madr); pMem = dmaGetAddr(gif->madr, false);
if (pMem == NULL) if (pMem == NULL)
{ {
// reset path3, fixes dark cloud 2 // reset path3, fixes dark cloud 2
@ -152,7 +152,7 @@ static __forceinline bool checkTieBit(tDMA_TAG* &ptag)
static __forceinline tDMA_TAG* ReadTag() static __forceinline tDMA_TAG* ReadTag()
{ {
tDMA_TAG* ptag = dmaGetAddr(gif->tadr); //Set memory pointer to TADR tDMA_TAG* ptag = dmaGetAddr(gif->tadr, false); //Set memory pointer to TADR
if (!(gif->transfer("Gif", ptag))) return NULL; if (!(gif->transfer("Gif", ptag))) return NULL;
@ -165,7 +165,7 @@ static __forceinline tDMA_TAG* ReadTag()
static __forceinline tDMA_TAG* ReadTag2() static __forceinline tDMA_TAG* ReadTag2()
{ {
tDMA_TAG* ptag = dmaGetAddr(gif->tadr); //Set memory pointer to TADR tDMA_TAG* ptag = dmaGetAddr(gif->tadr, false); //Set memory pointer to TADR
gif->unsafeTransfer(ptag); gif->unsafeTransfer(ptag);
gif->madr = ptag[1]._u32; gif->madr = ptag[1]._u32;
@ -306,7 +306,7 @@ void GIFdma()
if ((!gspath3done) && (gif->qwc == 0)) if ((!gspath3done) && (gif->qwc == 0))
{ {
ptag = dmaGetAddr(gif->tadr); //Set memory pointer to TADR ptag = dmaGetAddr(gif->tadr, false); //Set memory pointer to TADR
gif->unsafeTransfer(ptag); gif->unsafeTransfer(ptag);
gif->madr = ptag[1]._u32; gif->madr = ptag[1]._u32;
@ -424,7 +424,7 @@ static __forceinline bool mfifoGIFchain()
{ {
int mfifoqwc; int mfifoqwc;
tDMA_TAG *pMem = dmaGetAddr(gif->madr); tDMA_TAG *pMem = dmaGetAddr(gif->madr, false);
if (pMem == NULL) return false; if (pMem == NULL) return false;
mfifoqwc = WRITERING_DMA(pMem, gif->qwc); mfifoqwc = WRITERING_DMA(pMem, gif->qwc);
@ -471,7 +471,7 @@ void mfifoGIFtransfer(int qwc)
gif->tadr = qwctag(gif->tadr); gif->tadr = qwctag(gif->tadr);
ptag = dmaGetAddr(gif->tadr); ptag = dmaGetAddr(gif->tadr, false);
gif->unsafeTransfer(ptag); gif->unsafeTransfer(ptag);
gif->madr = ptag[1]._u32; gif->madr = ptag[1]._u32;

View File

@ -1313,7 +1313,7 @@ static __forceinline int IPU1chain() {
int qwc = ipu1dma->qwc; int qwc = ipu1dma->qwc;
u32 *pMem; u32 *pMem;
pMem = (u32*)dmaGetAddr(ipu1dma->madr); pMem = (u32*)dmaGetAddr(ipu1dma->madr, false);
if (pMem == NULL) if (pMem == NULL)
{ {
@ -1404,7 +1404,7 @@ int IPU1dma()
u32 *ptag; u32 *ptag;
ptag = (u32*)dmaGetAddr(ipu1dma->tadr); //Set memory pointer to TADR ptag = (u32*)dmaGetAddr(ipu1dma->tadr, false); //Set memory pointer to TADR
if (ptag == NULL) //Is ptag empty? if (ptag == NULL) //Is ptag empty?
{ {
Console.Error("IPU1 BUSERR"); Console.Error("IPU1 BUSERR");
@ -1509,7 +1509,7 @@ int IPU0dma()
pxAssert(ipu0dma->chcr.MOD == NORMAL_MODE); pxAssert(ipu0dma->chcr.MOD == NORMAL_MODE);
pMem = dmaGetAddr(ipu0dma->madr); pMem = dmaGetAddr(ipu0dma->madr, true);
readsize = min(ipu0dma->qwc, (u16)ipuRegs->ctrl.OFC); readsize = min(ipu0dma->qwc, (u16)ipuRegs->ctrl.OFC);
totalsize+=readsize; totalsize+=readsize;

View File

@ -85,6 +85,15 @@ u8 *psR2 = NULL; // 0x00080000
u8 *psER = NULL; // 0x001C0000 u8 *psER = NULL; // 0x001C0000
u8 *psS = NULL; //0.015 mb, scratch pad 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) #define CHECK_MEM(mem) //MyMemCheck(mem)
void MyMemCheck(u32 mem) void MyMemCheck(u32 mem)
@ -96,6 +105,8 @@ void MyMemCheck(u32 mem)
///////////////////////////// /////////////////////////////
// REGULAR MEM START // REGULAR MEM START
///////////////////////////// /////////////////////////////
vtlbHandler null_handler;
vtlbHandler tlb_fallback_0; vtlbHandler tlb_fallback_0;
vtlbHandler tlb_fallback_1; vtlbHandler tlb_fallback_1;
vtlbHandler tlb_fallback_2; vtlbHandler tlb_fallback_2;
@ -137,6 +148,8 @@ void memMapPhy()
{ {
// Main memory // Main memory
vtlb_MapBlock(psM, 0x00000000,Ps2MemSize::Base);//mirrored on first 256 mb ? vtlb_MapBlock(psM, 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) // Various ROMs (all read-only)
vtlb_MapBlock(psR, 0x1fc00000,Ps2MemSize::Rom); vtlb_MapBlock(psR, 0x1fc00000,Ps2MemSize::Rom);
@ -206,6 +219,47 @@ void memMapUserMem()
{ {
} }
static mem8_t __fastcall nullRead8(u32 mem) {
MEM_LOG("Read uninstalled memory at address %08x", mem);
return 0;
}
static mem16_t __fastcall nullRead16(u32 mem) {
MEM_LOG("Read uninstalled memory at address %08x", mem);
return 0;
}
static mem32_t __fastcall nullRead32(u32 mem) {
MEM_LOG("Read uninstalled memory at address %08x", mem);
return 0;
}
static void __fastcall nullRead64(u32 mem, mem64_t *out) {
MEM_LOG("Read uninstalled memory at address %08x", mem);
*out = 0;
}
static void __fastcall nullRead128(u32 mem, mem128_t *out) {
MEM_LOG("Read uninstalled memory at address %08x", mem);
*out = 0;
}
static void __fastcall nullWrite8(u32 mem, mem8_t value)
{
MEM_LOG("Write uninstalled memory at address %08x", mem);
}
static void __fastcall nullWrite16(u32 mem, mem16_t value)
{
MEM_LOG("Write uninstalled memory at address %08x", mem);
}
static void __fastcall nullWrite32(u32 mem, mem32_t value)
{
MEM_LOG("Write uninstalled memory at address %08x", mem);
}
static void __fastcall nullWrite64(u32 mem, const mem64_t *value)
{
MEM_LOG("Write uninstalled memory at address %08x", mem);
}
static void __fastcall nullWrite128(u32 mem, const mem128_t *value)
{
MEM_LOG("Write uninstalled memory at address %08x", mem);
}
template<int p> template<int p>
mem8_t __fastcall _ext_memRead8 (u32 mem) mem8_t __fastcall _ext_memRead8 (u32 mem)
{ {
@ -640,6 +694,9 @@ void memReset()
vtlb_Init(); vtlb_Init();
null_handler = vtlb_RegisterHandler(nullRead8, nullRead16, nullRead32, nullRead64, nullRead128,
nullWrite8, nullWrite16, nullWrite32, nullWrite64, nullWrite128);
tlb_fallback_0 = vtlb_RegisterHandlerTempl1(_ext_mem,0); tlb_fallback_0 = vtlb_RegisterHandlerTempl1(_ext_mem,0);
tlb_fallback_3 = vtlb_RegisterHandlerTempl1(_ext_mem,3); tlb_fallback_3 = vtlb_RegisterHandlerTempl1(_ext_mem,3);
tlb_fallback_4 = vtlb_RegisterHandlerTempl1(_ext_mem,4); tlb_fallback_4 = vtlb_RegisterHandlerTempl1(_ext_mem,4);

View File

@ -30,6 +30,10 @@ extern u8 *psR2; // 0x00080000
extern u8 *psER; // 0x001C0000 extern u8 *psER; // 0x001C0000
extern u8 *psS; //0.015 mb, scratch pad 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_BASE psM
#define PS2MEM_HW psH #define PS2MEM_HW psH
#define PS2MEM_ROM psR #define PS2MEM_ROM psR

View File

@ -785,7 +785,8 @@ int __Deci2Call(int call, u32 *addr)
// Console.WriteLn("deci2msg: %s", (char*)PSM(deci2addr[4]+0xc)); // Console.WriteLn("deci2msg: %s", (char*)PSM(deci2addr[4]+0xc));
if (deci2addr == NULL) return 1; if (deci2addr == NULL) return 1;
if (deci2addr[1]>0xc){ if (deci2addr[1]>0xc){
u8* pdeciaddr = (u8*)dmaGetAddr(deci2addr[4]+0xc); // this looks horribly wrong, justification please?
u8* pdeciaddr = (u8*)dmaGetAddr(deci2addr[4]+0xc, false);
if( pdeciaddr == NULL ) if( pdeciaddr == NULL )
pdeciaddr = (u8*)PSM(deci2addr[4]+0xc); pdeciaddr = (u8*)PSM(deci2addr[4]+0xc);
else else

View File

@ -52,7 +52,7 @@ int _SPR0chain()
tDMA_TAG *pMem; tDMA_TAG *pMem;
if (spr0->qwc == 0) return 0; if (spr0->qwc == 0) return 0;
pMem = dmaGetAddr(spr0->madr); pMem = dmaGetAddr(spr0->madr, true);
if (pMem == NULL) return -1; if (pMem == NULL) return -1;
switch (dmacRegs->ctrl.MFD) switch (dmacRegs->ctrl.MFD)
@ -106,7 +106,7 @@ void _SPR0interleave()
{ {
spr0->qwc = std::min(tqwc, qwc); spr0->qwc = std::min(tqwc, qwc);
qwc -= spr0->qwc; qwc -= spr0->qwc;
pMem = dmaGetAddr(spr0->madr); pMem = dmaGetAddr(spr0->madr, true);
switch (dmacRegs->ctrl.MFD) switch (dmacRegs->ctrl.MFD)
{ {
@ -290,7 +290,7 @@ int _SPR1chain()
if (spr1->qwc == 0) return 0; if (spr1->qwc == 0) return 0;
pMem = dmaGetAddr(spr1->madr); pMem = dmaGetAddr(spr1->madr, false);
if (pMem == NULL) return -1; if (pMem == NULL) return -1;
SPR1transfer((u32*)pMem, spr1->qwc << 2); SPR1transfer((u32*)pMem, spr1->qwc << 2);
@ -320,7 +320,7 @@ void _SPR1interleave()
{ {
spr1->qwc = std::min(tqwc, qwc); spr1->qwc = std::min(tqwc, qwc);
qwc -= spr1->qwc; qwc -= spr1->qwc;
pMem = dmaGetAddr(spr1->madr); pMem = dmaGetAddr(spr1->madr, false);
memcpy_fast(&psSu8(spr1->sadr), (u8*)pMem, spr1->qwc << 4); memcpy_fast(&psSu8(spr1->sadr), (u8*)pMem, spr1->qwc << 4);
spr1->sadr += spr1->qwc * 16; spr1->sadr += spr1->qwc * 16;
spr1->madr += (sqwc + spr1->qwc) * 16; spr1->madr += (sqwc + spr1->qwc) * 16;
@ -356,7 +356,7 @@ void _dmaSPR1() // toSPR work function
} }
// Chain Mode // Chain Mode
ptag = dmaGetAddr(spr1->tadr); //Set memory pointer to TADR ptag = dmaGetAddr(spr1->tadr, false); //Set memory pointer to TADR
if (!spr1->transfer("SPR1 Tag", ptag)) if (!spr1->transfer("SPR1 Tag", ptag))
{ {
@ -390,7 +390,7 @@ void _dmaSPR1() // toSPR work function
spr1finished = done; spr1finished = done;
if (!done) if (!done)
{ {
ptag = dmaGetAddr(spr1->tadr); //Set memory pointer to TADR ptag = dmaGetAddr(spr1->tadr, false); //Set memory pointer to TADR
CPU_INT(DMAC_TO_SPR, /*(ptag[0].QWC / BIAS)*/ 4 );// the lower 16 bits of the tag / BIAS); CPU_INT(DMAC_TO_SPR, /*(ptag[0].QWC / BIAS)*/ 4 );// the lower 16 bits of the tag / BIAS);
} }
break; break;
@ -414,7 +414,7 @@ void dmaSPR1() // toSPR
if ((spr1->chcr.MOD == CHAIN_MODE) && (spr1->qwc == 0)) if ((spr1->chcr.MOD == CHAIN_MODE) && (spr1->qwc == 0))
{ {
tDMA_TAG *ptag; tDMA_TAG *ptag;
ptag = dmaGetAddr(spr1->tadr); //Set memory pointer to TADR ptag = dmaGetAddr(spr1->tadr, false); //Set memory pointer to TADR
CPU_INT(DMAC_TO_SPR, /*ptag[0].QWC / BIAS*/ 4 ); CPU_INT(DMAC_TO_SPR, /*ptag[0].QWC / BIAS*/ 4 );
return; return;
} }

View File

@ -42,7 +42,7 @@ static __forceinline bool WriteFifoToEE()
//SIF_LOG(" EE SIF doing transfer %04Xqw to %08X", readSize, sif0dma->madr); //SIF_LOG(" EE SIF doing transfer %04Xqw to %08X", readSize, sif0dma->madr);
SIF_LOG("Write Fifo to EE: ----------- %lX of %lX", readSize << 2, sif0dma->qwc << 2); SIF_LOG("Write Fifo to EE: ----------- %lX of %lX", readSize << 2, sif0dma->qwc << 2);
ptag = sif0dma->getAddr(sif0dma->madr, DMAC_SIF0); ptag = sif0dma->getAddr(sif0dma->madr, DMAC_SIF0, true);
if (ptag == NULL) if (ptag == NULL)
{ {
DevCon.Warning("Write Fifo to EE: ptag == NULL"); DevCon.Warning("Write Fifo to EE: ptag == NULL");

View File

@ -42,7 +42,7 @@ static __forceinline bool WriteEEtoFifo()
tDMA_TAG *ptag; tDMA_TAG *ptag;
ptag = sif1dma->getAddr(sif1dma->madr, DMAC_SIF1); ptag = sif1dma->getAddr(sif1dma->madr, DMAC_SIF1, false);
if (ptag == NULL) if (ptag == NULL)
{ {
DevCon.Warning("Write EE to Fifo: ptag == NULL"); DevCon.Warning("Write EE to Fifo: ptag == NULL");

View File

@ -39,7 +39,7 @@ bool _VIF0chain()
return true; return true;
} }
pMem = (u32*)dmaGetAddr(vif0ch->madr); pMem = (u32*)dmaGetAddr(vif0ch->madr, false);
if (pMem == NULL) if (pMem == NULL)
{ {
vif0.cmd = 0; vif0.cmd = 0;
@ -70,7 +70,7 @@ __forceinline void vif0SetupTransfer()
break; break;
case VIF_CHAIN_MODE: case VIF_CHAIN_MODE:
ptag = dmaGetAddr(vif0ch->tadr); //Set memory pointer to TADR ptag = dmaGetAddr(vif0ch->tadr, false); //Set memory pointer to TADR
if (!(vif0ch->transfer("vif0 Tag", ptag))) return; if (!(vif0ch->transfer("vif0 Tag", ptag))) return;

View File

@ -32,7 +32,7 @@ __forceinline void vif1FLUSH()
void vif1TransferToMemory() void vif1TransferToMemory()
{ {
int size; int size;
u64* pMem = (u64*)dmaGetAddr(vif1ch->madr); u64* pMem = (u64*)dmaGetAddr(vif1ch->madr, false);
// VIF from gsMemory // VIF from gsMemory
if (pMem == NULL) //Is vif0ptag empty? if (pMem == NULL) //Is vif0ptag empty?
@ -107,7 +107,7 @@ bool _VIF1chain()
return true; return true;
} }
pMem = (u32*)dmaGetAddr(vif1ch->madr); pMem = (u32*)dmaGetAddr(vif1ch->madr, !vif1ch->chcr.DIR);
if (pMem == NULL) if (pMem == NULL)
{ {
vif1.cmd = 0; vif1.cmd = 0;
@ -139,7 +139,7 @@ __forceinline void vif1SetupTransfer()
break; break;
case VIF_CHAIN_MODE: case VIF_CHAIN_MODE:
ptag = dmaGetAddr(vif1ch->tadr); //Set memory pointer to TADR ptag = dmaGetAddr(vif1ch->tadr, false); //Set memory pointer to TADR
if (!(vif1ch->transfer("Vif1 Tag", ptag))) return; if (!(vif1ch->transfer("Vif1 Tag", ptag))) return;

View File

@ -98,7 +98,7 @@ static __forceinline bool mfifo_VIF1chain()
} }
else else
{ {
tDMA_TAG *pMem = dmaGetAddr(vif1ch->madr); tDMA_TAG *pMem = dmaGetAddr(vif1ch->madr, !vif1ch->chcr.DIR);
SPR_LOG("Non-MFIFO Location"); SPR_LOG("Non-MFIFO Location");
if (pMem == NULL) return false; if (pMem == NULL) return false;
@ -142,7 +142,7 @@ void mfifoVIF1transfer(int qwc)
if (vif1ch->qwc == 0 && vifqwc > 0) if (vif1ch->qwc == 0 && vifqwc > 0)
{ {
ptag = dmaGetAddr(vif1ch->tadr); ptag = dmaGetAddr(vif1ch->tadr, false);
if (vif1ch->chcr.TTE) if (vif1ch->chcr.TTE)
{ {

View File

@ -91,7 +91,7 @@ s32 DoSifRead(u32 iopAvailable)
SIF_LOG("Write IOP to EE: +++++++++++ %lX of %lX", transferSizeWords, sif0.iop.counter); SIF_LOG("Write IOP to EE: +++++++++++ %lX of %lX", transferSizeWords, sif0.iop.counter);
tDMA_TAG *ptag = sif0dma->getAddr(sif0dma->madr, DMAC_SIF0); tDMA_TAG *ptag = sif0dma->getAddr(sif0dma->madr, DMAC_SIF0, true);
if (ptag == NULL) if (ptag == NULL)
{ {
DevCon.Warning("Write IOP to EE: ptag == NULL"); DevCon.Warning("Write IOP to EE: ptag == NULL");