GPFifo: Use a pointer instead of an index

This simplifies code generated by the jits.
x86_64 jit now emits PIC.
This commit is contained in:
MerryMage 2017-04-13 23:31:29 +01:00
parent 722aca0830
commit c45028a708
5 changed files with 62 additions and 83 deletions

View File

@ -28,52 +28,65 @@ namespace GPFifo
// the same function could use both methods. Compile 2 different versions of each such block? // the same function could use both methods. Compile 2 different versions of each such block?
// More room for the fastmodes // More room for the fastmodes
alignas(32) u8 m_gatherPipe[GATHER_PIPE_SIZE * 16]; alignas(32) static u8 s_gather_pipe[GATHER_PIPE_SIZE * 16];
// pipe counter // pipe pointer
u32 m_gatherPipeCount = 0; u8* g_gather_pipe_ptr = s_gather_pipe;
static size_t GetGatherPipeCount()
{
return g_gather_pipe_ptr - s_gather_pipe;
}
static void SetGatherPipeCount(size_t size)
{
g_gather_pipe_ptr = s_gather_pipe + size;
}
void DoState(PointerWrap& p) void DoState(PointerWrap& p)
{ {
p.Do(m_gatherPipe); p.Do(s_gather_pipe);
p.Do(m_gatherPipeCount); u32 pipe_count = static_cast<u32>(GetGatherPipeCount());
p.Do(pipe_count);
SetGatherPipeCount(pipe_count);
} }
void Init() void Init()
{ {
ResetGatherPipe(); ResetGatherPipe();
memset(m_gatherPipe, 0, sizeof(m_gatherPipe)); memset(s_gather_pipe, 0, sizeof(s_gather_pipe));
} }
bool IsEmpty() bool IsEmpty()
{ {
return m_gatherPipeCount == 0; return GetGatherPipeCount() == 0;
} }
void ResetGatherPipe() void ResetGatherPipe()
{ {
m_gatherPipeCount = 0; SetGatherPipeCount(0);
} }
static void UpdateGatherPipe() static void UpdateGatherPipe()
{ {
u32 cnt; size_t pipe_count = GetGatherPipeCount();
u8* curMem = Memory::GetPointer(ProcessorInterface::Fifo_CPUWritePointer); size_t processed;
for (cnt = 0; m_gatherPipeCount >= GATHER_PIPE_SIZE; cnt += GATHER_PIPE_SIZE) u8* cur_mem = Memory::GetPointer(ProcessorInterface::Fifo_CPUWritePointer);
for (processed = 0; pipe_count >= GATHER_PIPE_SIZE; processed += GATHER_PIPE_SIZE)
{ {
// copy the GatherPipe // copy the GatherPipe
memcpy(curMem, m_gatherPipe + cnt, GATHER_PIPE_SIZE); memcpy(cur_mem, s_gather_pipe + processed, GATHER_PIPE_SIZE);
m_gatherPipeCount -= GATHER_PIPE_SIZE; pipe_count -= GATHER_PIPE_SIZE;
// increase the CPUWritePointer // increase the CPUWritePointer
if (ProcessorInterface::Fifo_CPUWritePointer == ProcessorInterface::Fifo_CPUEnd) if (ProcessorInterface::Fifo_CPUWritePointer == ProcessorInterface::Fifo_CPUEnd)
{ {
ProcessorInterface::Fifo_CPUWritePointer = ProcessorInterface::Fifo_CPUBase; ProcessorInterface::Fifo_CPUWritePointer = ProcessorInterface::Fifo_CPUBase;
curMem = Memory::GetPointer(ProcessorInterface::Fifo_CPUWritePointer); cur_mem = Memory::GetPointer(ProcessorInterface::Fifo_CPUWritePointer);
} }
else else
{ {
curMem += GATHER_PIPE_SIZE; cur_mem += GATHER_PIPE_SIZE;
ProcessorInterface::Fifo_CPUWritePointer += GATHER_PIPE_SIZE; ProcessorInterface::Fifo_CPUWritePointer += GATHER_PIPE_SIZE;
} }
@ -81,12 +94,13 @@ static void UpdateGatherPipe()
} }
// move back the spill bytes // move back the spill bytes
memmove(m_gatherPipe, m_gatherPipe + cnt, m_gatherPipeCount); memmove(s_gather_pipe, s_gather_pipe + processed, pipe_count);
SetGatherPipeCount(pipe_count);
} }
void FastCheckGatherPipe() void FastCheckGatherPipe()
{ {
if (m_gatherPipeCount >= GATHER_PIPE_SIZE) if (GetGatherPipeCount() >= GATHER_PIPE_SIZE)
{ {
UpdateGatherPipe(); UpdateGatherPipe();
} }
@ -94,7 +108,7 @@ void FastCheckGatherPipe()
void CheckGatherPipe() void CheckGatherPipe()
{ {
if (m_gatherPipeCount >= GATHER_PIPE_SIZE) if (GetGatherPipeCount() >= GATHER_PIPE_SIZE)
{ {
UpdateGatherPipe(); UpdateGatherPipe();
@ -129,29 +143,29 @@ void Write64(const u64 value)
void FastWrite8(const u8 value) void FastWrite8(const u8 value)
{ {
m_gatherPipe[m_gatherPipeCount] = value; *g_gather_pipe_ptr = value;
++m_gatherPipeCount; g_gather_pipe_ptr += sizeof(u8);
} }
void FastWrite16(u16 value) void FastWrite16(u16 value)
{ {
value = Common::swap16(value); value = Common::swap16(value);
std::memcpy(&m_gatherPipe[m_gatherPipeCount], &value, sizeof(u16)); std::memcpy(g_gather_pipe_ptr, &value, sizeof(u16));
m_gatherPipeCount += sizeof(u16); g_gather_pipe_ptr += sizeof(u16);
} }
void FastWrite32(u32 value) void FastWrite32(u32 value)
{ {
value = Common::swap32(value); value = Common::swap32(value);
std::memcpy(&m_gatherPipe[m_gatherPipeCount], &value, sizeof(u32)); std::memcpy(g_gather_pipe_ptr, &value, sizeof(u32));
m_gatherPipeCount += sizeof(u32); g_gather_pipe_ptr += sizeof(u32);
} }
void FastWrite64(u64 value) void FastWrite64(u64 value)
{ {
value = Common::swap64(value); value = Common::swap64(value);
std::memcpy(&m_gatherPipe[m_gatherPipeCount], &value, sizeof(u64)); std::memcpy(g_gather_pipe_ptr, &value, sizeof(u64));
m_gatherPipeCount += sizeof(u64); g_gather_pipe_ptr += sizeof(u64);
} }
} // end of namespace GPFifo } // end of namespace GPFifo

View File

@ -15,11 +15,8 @@ enum
GATHER_PIPE_SIZE = 32 GATHER_PIPE_SIZE = 32
}; };
// More room for the fastmodes // pipe pointer for JIT access
alignas(32) extern u8 m_gatherPipe[GATHER_PIPE_SIZE * 16]; extern u8* g_gather_pipe_ptr;
// pipe counter
extern u32 m_gatherPipeCount;
// Init // Init
void Init(); void Init();

View File

@ -28,10 +28,12 @@ void CommonAsmRoutines::GenFifoWrite(int size)
const void* start = GetCodePtr(); const void* start = GetCodePtr();
// Assume value in RSCRATCH // Assume value in RSCRATCH
MOV(32, R(RSCRATCH2), M(&GPFifo::m_gatherPipeCount)); MOV(64, R(RSCRATCH2), ImmPtr(&GPFifo::g_gather_pipe_ptr));
SwapAndStore(size, MDisp(RSCRATCH2, PtrOffset(GPFifo::m_gatherPipe)), RSCRATCH); MOV(64, R(RSCRATCH2), MatR(RSCRATCH2));
ADD(32, R(RSCRATCH2), Imm8(size >> 3)); SwapAndStore(size, MatR(RSCRATCH2), RSCRATCH);
MOV(32, M(&GPFifo::m_gatherPipeCount), R(RSCRATCH2)); MOV(64, R(RSCRATCH), ImmPtr(&GPFifo::g_gather_pipe_ptr));
ADD(64, R(RSCRATCH2), Imm8(size >> 3));
MOV(64, MatR(RSCRATCH), R(RSCRATCH2));
RET(); RET();
JitRegister::Register(start, GetCodePtr(), "JIT_FifoWrite_%i", size); JitRegister::Register(start, GetCodePtr(), "JIT_FifoWrite_%i", size);

View File

@ -141,7 +141,7 @@ void JitArm64::SafeLoadToReg(u32 dest, s32 addr, s32 offsetReg, u32 flags, s32 o
void JitArm64::SafeStoreFromReg(s32 dest, u32 value, s32 regOffset, u32 flags, s32 offset) void JitArm64::SafeStoreFromReg(s32 dest, u32 value, s32 regOffset, u32 flags, s32 offset)
{ {
// We want to make sure to not get LR as a temp register // We want to make sure to not get LR as a temp register
gpr.Lock(W0, W1, W30); gpr.Lock(W0, W1);
ARM64Reg RS = gpr.R(value); ARM64Reg RS = gpr.R(value);
@ -242,41 +242,23 @@ void JitArm64::SafeStoreFromReg(s32 dest, u32 value, s32 regOffset, u32 flags, s
if (accessSize != 8) if (accessSize != 8)
WA = gpr.GetReg(); WA = gpr.GetReg();
u64 base_ptr = std::min((u64)&GPFifo::m_gatherPipeCount, (u64)&GPFifo::m_gatherPipe); MOVP2R(X1, &GPFifo::g_gather_pipe_ptr);
u32 count_off = (u64)&GPFifo::m_gatherPipeCount - base_ptr; LDR(INDEX_UNSIGNED, X0, X1, 0);
u32 pipe_off = (u64)&GPFifo::m_gatherPipe - base_ptr;
MOVI2R(X30, base_ptr);
if (pipe_off)
ADD(X1, X30, pipe_off);
LDR(INDEX_UNSIGNED, W0, X30, count_off);
if (accessSize == 32) if (accessSize == 32)
{ {
REV32(WA, RS); REV32(WA, RS);
if (pipe_off) STR(INDEX_POST, WA, X0, 4);
STR(WA, X1, ArithOption(X0));
else
STR(WA, X30, ArithOption(X0));
} }
else if (accessSize == 16) else if (accessSize == 16)
{ {
REV16(WA, RS); REV16(WA, RS);
if (pipe_off) STRH(INDEX_POST, WA, X0, 2);
STRH(WA, X1, ArithOption(X0));
else
STRH(WA, X30, ArithOption(X0));
} }
else else
{ {
if (pipe_off) STRB(INDEX_POST, WA, X0, 1);
STRB(RS, X1, ArithOption(X0));
else
STRB(RS, X30, ArithOption(X0));
} }
ADD(W0, W0, accessSize >> 3); STR(INDEX_UNSIGNED, X0, X1, 0);
STR(INDEX_UNSIGNED, W0, X30, count_off);
js.fifoBytesSinceCheck += accessSize >> 3; js.fifoBytesSinceCheck += accessSize >> 3;
if (accessSize != 8) if (accessSize != 8)
@ -300,7 +282,7 @@ void JitArm64::SafeStoreFromReg(s32 dest, u32 value, s32 regOffset, u32 flags, s
EmitBackpatchRoutine(flags, jo.fastmem, jo.fastmem, RS, XA, regs_in_use, fprs_in_use); EmitBackpatchRoutine(flags, jo.fastmem, jo.fastmem, RS, XA, regs_in_use, fprs_in_use);
} }
gpr.Unlock(W0, W1, W30); gpr.Unlock(W0, W1);
} }
void JitArm64::lXX(UGeckoInstruction inst) void JitArm64::lXX(UGeckoInstruction inst)

View File

@ -241,7 +241,7 @@ void JitArm64::stfXX(UGeckoInstruction inst)
u32 imm_addr = 0; u32 imm_addr = 0;
bool is_immediate = false; bool is_immediate = false;
gpr.Lock(W0, W1, W30); gpr.Lock(W0, W1);
fpr.Lock(Q0); fpr.Lock(Q0);
bool single = (flags & BackPatchInfo::FLAG_SIZE_F32) && fpr.IsSingle(inst.FS, true); bool single = (flags & BackPatchInfo::FLAG_SIZE_F32) && fpr.IsSingle(inst.FS, true);
@ -357,16 +357,8 @@ void JitArm64::stfXX(UGeckoInstruction inst)
else else
accessSize = 32; accessSize = 32;
u64 base_ptr = std::min((u64)&GPFifo::m_gatherPipeCount, (u64)&GPFifo::m_gatherPipe); MOVP2R(X1, &GPFifo::g_gather_pipe_ptr);
u32 count_off = (u64)&GPFifo::m_gatherPipeCount - base_ptr; LDR(INDEX_UNSIGNED, X0, X1, 0);
u32 pipe_off = (u64)&GPFifo::m_gatherPipe - base_ptr;
MOVI2R(X30, base_ptr);
if (pipe_off)
ADD(X1, X30, pipe_off);
LDR(INDEX_UNSIGNED, W0, X30, count_off);
if (flags & BackPatchInfo::FLAG_SIZE_F64) if (flags & BackPatchInfo::FLAG_SIZE_F64)
{ {
m_float_emit.REV64(8, Q0, V0); m_float_emit.REV64(8, Q0, V0);
@ -381,17 +373,9 @@ void JitArm64::stfXX(UGeckoInstruction inst)
m_float_emit.REV32(8, D0, V0); m_float_emit.REV32(8, D0, V0);
} }
if (pipe_off) m_float_emit.STR(accessSize, INDEX_POST, accessSize == 64 ? Q0 : D0, X0, accessSize >> 3);
{
m_float_emit.STR(accessSize, accessSize == 64 ? Q0 : D0, X1, ArithOption(X0));
}
else
{
m_float_emit.STR(accessSize, accessSize == 64 ? Q0 : D0, X30, ArithOption(X0));
}
ADD(W0, W0, accessSize >> 3); STR(INDEX_UNSIGNED, X0, X1, 0);
STR(INDEX_UNSIGNED, W0, X30, count_off);
js.fifoBytesSinceCheck += accessSize >> 3; js.fifoBytesSinceCheck += accessSize >> 3;
if (update) if (update)
@ -414,6 +398,6 @@ void JitArm64::stfXX(UGeckoInstruction inst)
{ {
EmitBackpatchRoutine(flags, jo.fastmem, jo.fastmem, V0, XA, regs_in_use, fprs_in_use); EmitBackpatchRoutine(flags, jo.fastmem, jo.fastmem, V0, XA, regs_in_use, fprs_in_use);
} }
gpr.Unlock(W0, W1, W30); gpr.Unlock(W0, W1);
fpr.Unlock(Q0); fpr.Unlock(Q0);
} }