mirror of https://github.com/PCSX2/pcsx2.git
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:
parent
912a90a605
commit
a21fb4b984
29
pcsx2/Dmac.h
29
pcsx2/Dmac.h
|
@ -211,7 +211,7 @@ union tDMA_QWC {
|
|||
wxString desc() const { return wxsFormat(L"QWC: 0x%x", _u32); }
|
||||
};
|
||||
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);
|
||||
|
||||
struct DMACh {
|
||||
|
@ -258,9 +258,9 @@ struct DMACh {
|
|||
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)
|
||||
{
|
||||
throwBusError("dmaGetAddr");
|
||||
|
@ -273,7 +273,7 @@ struct DMACh {
|
|||
|
||||
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;
|
||||
|
||||
|
@ -622,18 +622,14 @@ static __forceinline void setDmacStat(u32 num)
|
|||
dmacRegs->stat.set_flags(1 << num);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static __forceinline bool inScratchpad(u32 addr)
|
||||
{
|
||||
return ((addr >=0x70000000) && (addr <= 0x70003fff));
|
||||
}
|
||||
|
||||
// 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 (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];
|
||||
}
|
||||
|
||||
ptr = (tDMA_TAG*)vtlb_GetPhyPtr(addr & 0x1FFFFFF0);
|
||||
if (ptr == NULL)
|
||||
{
|
||||
if (addr > 0x10000000)
|
||||
{
|
||||
Console.Error( "*PCSX2*: DMA error: %8.8x", addr);
|
||||
return NULL;
|
||||
}
|
||||
return ptr;
|
||||
}
|
||||
|
||||
if (addr > Ps2MemSize::Base)
|
||||
{
|
||||
return (tDMA_TAG*)(write ? psMHW : psMHR);
|
||||
}
|
||||
|
||||
return (tDMA_TAG*)&psM[addr];
|
||||
}
|
||||
|
||||
void hwIntcIrq(int n);
|
||||
|
|
|
@ -112,7 +112,7 @@ int _GIFchain()
|
|||
u32 qwc = min( gifsplit, (int)gif->qwc );
|
||||
tDMA_TAG *pMem;
|
||||
|
||||
pMem = dmaGetAddr(gif->madr);
|
||||
pMem = dmaGetAddr(gif->madr, false);
|
||||
if (pMem == NULL)
|
||||
{
|
||||
// reset path3, fixes dark cloud 2
|
||||
|
@ -152,7 +152,7 @@ static __forceinline bool checkTieBit(tDMA_TAG* &ptag)
|
|||
|
||||
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;
|
||||
|
||||
|
@ -165,7 +165,7 @@ static __forceinline tDMA_TAG* ReadTag()
|
|||
|
||||
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->madr = ptag[1]._u32;
|
||||
|
@ -306,7 +306,7 @@ void GIFdma()
|
|||
|
||||
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->madr = ptag[1]._u32;
|
||||
|
||||
|
@ -424,7 +424,7 @@ static __forceinline bool mfifoGIFchain()
|
|||
{
|
||||
int mfifoqwc;
|
||||
|
||||
tDMA_TAG *pMem = dmaGetAddr(gif->madr);
|
||||
tDMA_TAG *pMem = dmaGetAddr(gif->madr, false);
|
||||
if (pMem == NULL) return false;
|
||||
|
||||
mfifoqwc = WRITERING_DMA(pMem, gif->qwc);
|
||||
|
@ -471,7 +471,7 @@ void mfifoGIFtransfer(int qwc)
|
|||
|
||||
gif->tadr = qwctag(gif->tadr);
|
||||
|
||||
ptag = dmaGetAddr(gif->tadr);
|
||||
ptag = dmaGetAddr(gif->tadr, false);
|
||||
gif->unsafeTransfer(ptag);
|
||||
gif->madr = ptag[1]._u32;
|
||||
|
||||
|
|
|
@ -1313,7 +1313,7 @@ static __forceinline int IPU1chain() {
|
|||
int qwc = ipu1dma->qwc;
|
||||
u32 *pMem;
|
||||
|
||||
pMem = (u32*)dmaGetAddr(ipu1dma->madr);
|
||||
pMem = (u32*)dmaGetAddr(ipu1dma->madr, false);
|
||||
|
||||
if (pMem == NULL)
|
||||
{
|
||||
|
@ -1404,7 +1404,7 @@ int IPU1dma()
|
|||
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?
|
||||
{
|
||||
Console.Error("IPU1 BUSERR");
|
||||
|
@ -1509,7 +1509,7 @@ int IPU0dma()
|
|||
|
||||
pxAssert(ipu0dma->chcr.MOD == NORMAL_MODE);
|
||||
|
||||
pMem = dmaGetAddr(ipu0dma->madr);
|
||||
pMem = dmaGetAddr(ipu0dma->madr, true);
|
||||
|
||||
readsize = min(ipu0dma->qwc, (u16)ipuRegs->ctrl.OFC);
|
||||
totalsize+=readsize;
|
||||
|
|
|
@ -85,6 +85,15 @@ 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)
|
||||
|
@ -96,6 +105,8 @@ void MyMemCheck(u32 mem)
|
|||
/////////////////////////////
|
||||
// REGULAR MEM START
|
||||
/////////////////////////////
|
||||
vtlbHandler null_handler;
|
||||
|
||||
vtlbHandler tlb_fallback_0;
|
||||
vtlbHandler tlb_fallback_1;
|
||||
vtlbHandler tlb_fallback_2;
|
||||
|
@ -137,6 +148,8 @@ void memMapPhy()
|
|||
{
|
||||
// Main memory
|
||||
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)
|
||||
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>
|
||||
mem8_t __fastcall _ext_memRead8 (u32 mem)
|
||||
{
|
||||
|
@ -640,6 +694,9 @@ void memReset()
|
|||
|
||||
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_3 = vtlb_RegisterHandlerTempl1(_ext_mem,3);
|
||||
tlb_fallback_4 = vtlb_RegisterHandlerTempl1(_ext_mem,4);
|
||||
|
|
|
@ -30,6 +30,10 @@ 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
|
||||
|
|
|
@ -785,7 +785,8 @@ int __Deci2Call(int call, u32 *addr)
|
|||
// Console.WriteLn("deci2msg: %s", (char*)PSM(deci2addr[4]+0xc));
|
||||
if (deci2addr == NULL) return 1;
|
||||
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 )
|
||||
pdeciaddr = (u8*)PSM(deci2addr[4]+0xc);
|
||||
else
|
||||
|
|
|
@ -52,7 +52,7 @@ int _SPR0chain()
|
|||
tDMA_TAG *pMem;
|
||||
|
||||
if (spr0->qwc == 0) return 0;
|
||||
pMem = dmaGetAddr(spr0->madr);
|
||||
pMem = dmaGetAddr(spr0->madr, true);
|
||||
if (pMem == NULL) return -1;
|
||||
|
||||
switch (dmacRegs->ctrl.MFD)
|
||||
|
@ -106,7 +106,7 @@ void _SPR0interleave()
|
|||
{
|
||||
spr0->qwc = std::min(tqwc, qwc);
|
||||
qwc -= spr0->qwc;
|
||||
pMem = dmaGetAddr(spr0->madr);
|
||||
pMem = dmaGetAddr(spr0->madr, true);
|
||||
|
||||
switch (dmacRegs->ctrl.MFD)
|
||||
{
|
||||
|
@ -290,7 +290,7 @@ int _SPR1chain()
|
|||
|
||||
if (spr1->qwc == 0) return 0;
|
||||
|
||||
pMem = dmaGetAddr(spr1->madr);
|
||||
pMem = dmaGetAddr(spr1->madr, false);
|
||||
if (pMem == NULL) return -1;
|
||||
|
||||
SPR1transfer((u32*)pMem, spr1->qwc << 2);
|
||||
|
@ -320,7 +320,7 @@ void _SPR1interleave()
|
|||
{
|
||||
spr1->qwc = std::min(tqwc, qwc);
|
||||
qwc -= spr1->qwc;
|
||||
pMem = dmaGetAddr(spr1->madr);
|
||||
pMem = dmaGetAddr(spr1->madr, false);
|
||||
memcpy_fast(&psSu8(spr1->sadr), (u8*)pMem, spr1->qwc << 4);
|
||||
spr1->sadr += spr1->qwc * 16;
|
||||
spr1->madr += (sqwc + spr1->qwc) * 16;
|
||||
|
@ -356,7 +356,7 @@ void _dmaSPR1() // toSPR work function
|
|||
}
|
||||
// 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))
|
||||
{
|
||||
|
@ -390,7 +390,7 @@ void _dmaSPR1() // toSPR work function
|
|||
spr1finished = 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);
|
||||
}
|
||||
break;
|
||||
|
@ -414,7 +414,7 @@ void dmaSPR1() // toSPR
|
|||
if ((spr1->chcr.MOD == CHAIN_MODE) && (spr1->qwc == 0))
|
||||
{
|
||||
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 );
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -42,7 +42,7 @@ static __forceinline bool WriteFifoToEE()
|
|||
//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);
|
||||
|
||||
ptag = sif0dma->getAddr(sif0dma->madr, DMAC_SIF0);
|
||||
ptag = sif0dma->getAddr(sif0dma->madr, DMAC_SIF0, true);
|
||||
if (ptag == NULL)
|
||||
{
|
||||
DevCon.Warning("Write Fifo to EE: ptag == NULL");
|
||||
|
|
|
@ -42,7 +42,7 @@ static __forceinline bool WriteEEtoFifo()
|
|||
|
||||
tDMA_TAG *ptag;
|
||||
|
||||
ptag = sif1dma->getAddr(sif1dma->madr, DMAC_SIF1);
|
||||
ptag = sif1dma->getAddr(sif1dma->madr, DMAC_SIF1, false);
|
||||
if (ptag == NULL)
|
||||
{
|
||||
DevCon.Warning("Write EE to Fifo: ptag == NULL");
|
||||
|
|
|
@ -39,7 +39,7 @@ bool _VIF0chain()
|
|||
return true;
|
||||
}
|
||||
|
||||
pMem = (u32*)dmaGetAddr(vif0ch->madr);
|
||||
pMem = (u32*)dmaGetAddr(vif0ch->madr, false);
|
||||
if (pMem == NULL)
|
||||
{
|
||||
vif0.cmd = 0;
|
||||
|
@ -70,7 +70,7 @@ __forceinline void vif0SetupTransfer()
|
|||
break;
|
||||
|
||||
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;
|
||||
|
||||
|
|
|
@ -32,7 +32,7 @@ __forceinline void vif1FLUSH()
|
|||
void vif1TransferToMemory()
|
||||
{
|
||||
int size;
|
||||
u64* pMem = (u64*)dmaGetAddr(vif1ch->madr);
|
||||
u64* pMem = (u64*)dmaGetAddr(vif1ch->madr, false);
|
||||
|
||||
// VIF from gsMemory
|
||||
if (pMem == NULL) //Is vif0ptag empty?
|
||||
|
@ -107,7 +107,7 @@ bool _VIF1chain()
|
|||
return true;
|
||||
}
|
||||
|
||||
pMem = (u32*)dmaGetAddr(vif1ch->madr);
|
||||
pMem = (u32*)dmaGetAddr(vif1ch->madr, !vif1ch->chcr.DIR);
|
||||
if (pMem == NULL)
|
||||
{
|
||||
vif1.cmd = 0;
|
||||
|
@ -139,7 +139,7 @@ __forceinline void vif1SetupTransfer()
|
|||
break;
|
||||
|
||||
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;
|
||||
|
||||
|
|
|
@ -98,7 +98,7 @@ static __forceinline bool mfifo_VIF1chain()
|
|||
}
|
||||
else
|
||||
{
|
||||
tDMA_TAG *pMem = dmaGetAddr(vif1ch->madr);
|
||||
tDMA_TAG *pMem = dmaGetAddr(vif1ch->madr, !vif1ch->chcr.DIR);
|
||||
SPR_LOG("Non-MFIFO Location");
|
||||
|
||||
if (pMem == NULL) return false;
|
||||
|
@ -142,7 +142,7 @@ void mfifoVIF1transfer(int qwc)
|
|||
|
||||
if (vif1ch->qwc == 0 && vifqwc > 0)
|
||||
{
|
||||
ptag = dmaGetAddr(vif1ch->tadr);
|
||||
ptag = dmaGetAddr(vif1ch->tadr, false);
|
||||
|
||||
if (vif1ch->chcr.TTE)
|
||||
{
|
||||
|
|
|
@ -91,7 +91,7 @@ s32 DoSifRead(u32 iopAvailable)
|
|||
|
||||
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)
|
||||
{
|
||||
DevCon.Warning("Write IOP to EE: ptag == NULL");
|
||||
|
|
Loading…
Reference in New Issue