2013-04-17 22:43:11 -04:00
|
|
|
// Copyright 2013 Dolphin Emulator Project
|
|
|
|
// Licensed under GPLv2
|
|
|
|
// Refer to the license.txt file included.
|
2008-12-08 05:30:24 +00:00
|
|
|
|
2014-02-17 05:18:15 -05:00
|
|
|
#include "Common/ChunkFile.h"
|
2014-09-07 20:06:58 -05:00
|
|
|
#include "Common/CommonTypes.h"
|
2014-02-17 05:18:15 -05:00
|
|
|
|
|
|
|
#include "Core/HW/GPFifo.h"
|
|
|
|
#include "Core/HW/Memmap.h"
|
|
|
|
#include "Core/HW/ProcessorInterface.h"
|
|
|
|
#include "Core/PowerPC/PowerPC.h"
|
2014-02-19 13:09:14 -05:00
|
|
|
#include "Core/PowerPC/JitCommon/JitBase.h"
|
2014-02-17 05:18:15 -05:00
|
|
|
|
|
|
|
#include "VideoCommon/VideoBackendBase.h"
|
2008-12-08 05:30:24 +00:00
|
|
|
|
|
|
|
namespace GPFifo
|
|
|
|
{
|
|
|
|
|
|
|
|
// 32 Byte gather pipe with extra space
|
2013-10-29 01:23:17 -04:00
|
|
|
// Overfilling is no problem (up to the real limit), CheckGatherPipe will blast the
|
2008-12-08 05:30:24 +00:00
|
|
|
// contents in nicely sized chunks
|
|
|
|
|
|
|
|
// Other optimizations to think about:
|
|
|
|
|
|
|
|
// If the gp is NOT linked to the fifo, just blast to memory byte by word
|
|
|
|
// If the gp IS linked to the fifo, use a fast wrapping buffer and skip writing to memory
|
|
|
|
|
2013-10-29 01:23:17 -04:00
|
|
|
// Both of these should actually work! Only problem is that we have to decide at run time,
|
2008-12-08 05:30:24 +00:00
|
|
|
// the same function could use both methods. Compile 2 different versions of each such block?
|
|
|
|
|
|
|
|
u8 GC_ALIGNED32(m_gatherPipe[GATHER_PIPE_SIZE*16]); //more room, for the fastmodes
|
|
|
|
|
|
|
|
// pipe counter
|
2011-01-31 01:28:32 +00:00
|
|
|
u32 m_gatherPipeCount = 0;
|
2008-12-08 05:30:24 +00:00
|
|
|
|
|
|
|
void DoState(PointerWrap &p)
|
|
|
|
{
|
|
|
|
p.Do(m_gatherPipe);
|
|
|
|
p.Do(m_gatherPipeCount);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Init()
|
|
|
|
{
|
|
|
|
ResetGatherPipe();
|
2012-01-02 02:20:22 -08:00
|
|
|
memset(m_gatherPipe, 0, sizeof(m_gatherPipe));
|
2008-12-08 05:30:24 +00:00
|
|
|
}
|
|
|
|
|
2010-06-14 16:32:40 +00:00
|
|
|
bool IsEmpty()
|
|
|
|
{
|
2008-12-08 05:30:24 +00:00
|
|
|
return m_gatherPipeCount == 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void ResetGatherPipe()
|
|
|
|
{
|
|
|
|
m_gatherPipeCount = 0;
|
|
|
|
}
|
|
|
|
|
2008-12-25 02:53:56 +00:00
|
|
|
void STACKALIGN CheckGatherPipe()
|
2008-12-08 05:30:24 +00:00
|
|
|
{
|
2010-06-14 16:32:40 +00:00
|
|
|
if (m_gatherPipeCount >= GATHER_PIPE_SIZE)
|
|
|
|
{
|
|
|
|
u32 cnt;
|
|
|
|
u8* curMem = Memory::GetPointer(ProcessorInterface::Fifo_CPUWritePointer);
|
|
|
|
for (cnt = 0; m_gatherPipeCount >= GATHER_PIPE_SIZE; cnt += GATHER_PIPE_SIZE)
|
2013-04-16 23:14:36 -04:00
|
|
|
{
|
2010-06-14 16:32:40 +00:00
|
|
|
// copy the GatherPipe
|
|
|
|
memcpy(curMem, m_gatherPipe + cnt, GATHER_PIPE_SIZE);
|
|
|
|
m_gatherPipeCount -= GATHER_PIPE_SIZE;
|
|
|
|
|
|
|
|
// increase the CPUWritePointer
|
2010-10-16 10:16:05 +00:00
|
|
|
if (ProcessorInterface::Fifo_CPUWritePointer == ProcessorInterface::Fifo_CPUEnd)
|
2013-04-16 23:14:36 -04:00
|
|
|
{
|
2010-06-14 16:32:40 +00:00
|
|
|
ProcessorInterface::Fifo_CPUWritePointer = ProcessorInterface::Fifo_CPUBase;
|
2010-12-13 23:04:13 +00:00
|
|
|
curMem = Memory::GetPointer(ProcessorInterface::Fifo_CPUWritePointer);
|
2010-06-14 16:32:40 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
curMem += GATHER_PIPE_SIZE;
|
|
|
|
ProcessorInterface::Fifo_CPUWritePointer += GATHER_PIPE_SIZE;
|
|
|
|
}
|
|
|
|
|
2011-01-31 01:28:32 +00:00
|
|
|
g_video_backend->Video_GatherPipeBursted();
|
2010-06-14 16:32:40 +00:00
|
|
|
}
|
2013-10-29 01:23:17 -04:00
|
|
|
|
2010-06-14 16:32:40 +00:00
|
|
|
// move back the spill bytes
|
|
|
|
memmove(m_gatherPipe, m_gatherPipe + cnt, m_gatherPipeCount);
|
2013-10-29 01:23:17 -04:00
|
|
|
|
2013-03-28 19:36:37 +11:00
|
|
|
// Profile where the FIFO writes are occurring.
|
|
|
|
if (jit && PC != 0 && (jit->js.fifoWriteAddresses.find(PC)) == (jit->js.fifoWriteAddresses.end()))
|
|
|
|
{
|
|
|
|
// Log only stores, fp stores and ps stores, filtering out other instructions arrived via optimizeGatherPipe
|
|
|
|
int type = GetOpInfo(Memory::ReadUnchecked_U32(PC))->type;
|
|
|
|
if (type == OPTYPE_STORE || type == OPTYPE_STOREFP || (type == OPTYPE_PS && !strcmp(GetOpInfo(Memory::ReadUnchecked_U32(PC))->opname, "psq_st")))
|
|
|
|
{
|
|
|
|
jit->js.fifoWriteAddresses.insert(PC);
|
|
|
|
|
|
|
|
// Invalidate the JIT block so that it gets recompiled with the external exception check included.
|
|
|
|
jit->GetBlockCache()->InvalidateICache(PC, 4);
|
|
|
|
}
|
|
|
|
}
|
2008-12-08 05:30:24 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Write8(const u8 _iValue, const u32 _iAddress)
|
|
|
|
{
|
2009-10-06 15:49:20 +00:00
|
|
|
// LOG(GPFIFO, "GPFIFO #%x: 0x%02x",ProcessorInterface::Fifo_CPUWritePointer+m_gatherPipeCount, _iValue);
|
2011-03-15 23:09:12 +00:00
|
|
|
FastWrite8(_iValue);
|
2008-12-08 05:30:24 +00:00
|
|
|
CheckGatherPipe();
|
|
|
|
}
|
|
|
|
|
|
|
|
void Write16(const u16 _iValue, const u32 _iAddress)
|
|
|
|
{
|
2009-10-06 15:49:20 +00:00
|
|
|
// LOG(GPFIFO, "GPFIFO #%x: 0x%04x",ProcessorInterface::Fifo_CPUWritePointer+m_gatherPipeCount, _iValue);
|
2011-03-15 23:09:12 +00:00
|
|
|
FastWrite16(_iValue);
|
2008-12-08 05:30:24 +00:00
|
|
|
CheckGatherPipe();
|
|
|
|
}
|
|
|
|
|
|
|
|
void Write32(const u32 _iValue, const u32 _iAddress)
|
|
|
|
{
|
2010-04-11 11:16:57 +00:00
|
|
|
//#ifdef _DEBUG
|
|
|
|
// float floatvalue = *(float*)&_iValue;
|
2009-10-06 15:49:20 +00:00
|
|
|
// LOG(GPFIFO, "GPFIFO #%x: 0x%08x / %f",ProcessorInterface::Fifo_CPUWritePointer+m_gatherPipeCount, _iValue, floatvalue);
|
2010-04-11 11:16:57 +00:00
|
|
|
//#endif
|
2011-03-15 23:09:12 +00:00
|
|
|
FastWrite32(_iValue);
|
2008-12-08 05:30:24 +00:00
|
|
|
CheckGatherPipe();
|
|
|
|
}
|
|
|
|
|
2009-02-23 19:45:40 +00:00
|
|
|
void Write64(const u64 _iValue, const u32 _iAddress)
|
|
|
|
{
|
2011-03-15 23:09:12 +00:00
|
|
|
FastWrite64(_iValue);
|
2009-02-23 19:45:40 +00:00
|
|
|
CheckGatherPipe();
|
|
|
|
}
|
|
|
|
|
2008-12-08 05:30:24 +00:00
|
|
|
void FastWrite8(const u8 _iValue)
|
|
|
|
{
|
|
|
|
m_gatherPipe[m_gatherPipeCount] = _iValue;
|
2011-03-15 23:09:12 +00:00
|
|
|
++m_gatherPipeCount;
|
2008-12-08 05:30:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void FastWrite16(const u16 _iValue)
|
|
|
|
{
|
|
|
|
*(u16*)(&m_gatherPipe[m_gatherPipeCount]) = Common::swap16(_iValue);
|
|
|
|
m_gatherPipeCount += 2;
|
|
|
|
}
|
|
|
|
|
|
|
|
void FastWrite32(const u32 _iValue)
|
|
|
|
{
|
|
|
|
*(u32*)(&m_gatherPipe[m_gatherPipeCount]) = Common::swap32(_iValue);
|
|
|
|
m_gatherPipeCount += 4;
|
|
|
|
}
|
|
|
|
|
2009-02-23 19:45:40 +00:00
|
|
|
void FastWrite64(const u64 _iValue)
|
|
|
|
{
|
|
|
|
*(u64*)(&m_gatherPipe[m_gatherPipeCount]) = Common::swap64(_iValue);
|
|
|
|
m_gatherPipeCount += 8;
|
|
|
|
}
|
|
|
|
|
2008-12-08 05:30:24 +00:00
|
|
|
} // end of namespace GPFifo
|