mirror of
https://github.com/RetroDECK/Duckstation.git
synced 2024-11-26 15:45:42 +00:00
CPU/NewRec: Fix SR interrupts on non-x64
This commit is contained in:
parent
b8d4669997
commit
ca1dd27d4a
|
@ -1931,21 +1931,22 @@ void CPU::NewRec::AArch32Compiler::Compile_mtc0(CompileFlags cf)
|
||||||
Flush(FLUSH_FOR_C_CALL);
|
Flush(FLUSH_FOR_C_CALL);
|
||||||
|
|
||||||
SwitchToFarCodeIfBitSet(changed_bits, 16);
|
SwitchToFarCodeIfBitSet(changed_bits, 16);
|
||||||
armAsm->push(RegisterList(RARG1, RARG2));
|
armAsm->push(RegisterList(RARG1));
|
||||||
EmitCall(reinterpret_cast<const void*>(&CPU::UpdateMemoryPointers));
|
EmitCall(reinterpret_cast<const void*>(&CPU::UpdateMemoryPointers));
|
||||||
armAsm->pop(RegisterList(RARG1, RARG2));
|
armAsm->pop(RegisterList(RARG1));
|
||||||
if (CodeCache::IsUsingFastmem() && m_block->HasFlag(CodeCache::BlockFlags::ContainsLoadStoreInstructions) &&
|
if (CodeCache::IsUsingFastmem() && m_block->HasFlag(CodeCache::BlockFlags::ContainsLoadStoreInstructions) &&
|
||||||
IsHostRegAllocated(RMEMBASE.GetCode()))
|
IsHostRegAllocated(RMEMBASE.GetCode()))
|
||||||
{
|
{
|
||||||
FreeHostReg(RMEMBASE.GetCode());
|
FreeHostReg(RMEMBASE.GetCode());
|
||||||
}
|
}
|
||||||
SwitchToNearCode(true);
|
SwitchToNearCode(true);
|
||||||
}
|
|
||||||
|
|
||||||
if (reg == Cop0Reg::SR || reg == Cop0Reg::CAUSE)
|
TestInterrupts(RARG1);
|
||||||
|
}
|
||||||
|
else if (reg == Cop0Reg::CAUSE)
|
||||||
{
|
{
|
||||||
const Register sr = (reg == Cop0Reg::SR) ? RARG2 : (armAsm->ldr(RARG1, PTR(&g_state.cop0_regs.sr.bits)), RARG1);
|
armAsm->ldr(RARG1, PTR(&g_state.cop0_regs.sr.bits));
|
||||||
TestInterrupts(sr);
|
TestInterrupts(RARG1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (reg == Cop0Reg::DCIC && g_settings.cpu_recompiler_memory_exceptions)
|
if (reg == Cop0Reg::DCIC && g_settings.cpu_recompiler_memory_exceptions)
|
||||||
|
|
|
@ -1911,18 +1911,19 @@ void CPU::NewRec::AArch64Compiler::Compile_mtc0(CompileFlags cf)
|
||||||
|
|
||||||
SwitchToFarCodeIfBitSet(changed_bits, 16);
|
SwitchToFarCodeIfBitSet(changed_bits, 16);
|
||||||
armAsm->sub(sp, sp, 16);
|
armAsm->sub(sp, sp, 16);
|
||||||
armAsm->stp(RWARG1, RWARG2, MemOperand(sp));
|
armAsm->str(RWARG1, MemOperand(sp));
|
||||||
EmitCall(reinterpret_cast<const void*>(&CPU::UpdateMemoryPointers));
|
EmitCall(reinterpret_cast<const void*>(&CPU::UpdateMemoryPointers));
|
||||||
armAsm->ldp(RWARG1, RWARG2, MemOperand(sp));
|
armAsm->ldr(RWARG1, MemOperand(sp));
|
||||||
armAsm->add(sp, sp, 16);
|
armAsm->add(sp, sp, 16);
|
||||||
armAsm->ldr(RMEMBASE, PTR(&g_state.fastmem_base));
|
armAsm->ldr(RMEMBASE, PTR(&g_state.fastmem_base));
|
||||||
SwitchToNearCode(true);
|
SwitchToNearCode(true);
|
||||||
}
|
|
||||||
|
|
||||||
if (reg == Cop0Reg::SR || reg == Cop0Reg::CAUSE)
|
TestInterrupts(RWARG1);
|
||||||
|
}
|
||||||
|
else if (reg == Cop0Reg::CAUSE)
|
||||||
{
|
{
|
||||||
const WRegister sr = (reg == Cop0Reg::SR) ? RWARG2 : (armAsm->ldr(RWARG1, PTR(&g_state.cop0_regs.sr.bits)), RWARG1);
|
armAsm->ldr(RWARG1, PTR(&g_state.cop0_regs.sr.bits));
|
||||||
TestInterrupts(sr);
|
TestInterrupts(RWARG1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (reg == Cop0Reg::DCIC && g_settings.cpu_recompiler_memory_exceptions)
|
if (reg == Cop0Reg::DCIC && g_settings.cpu_recompiler_memory_exceptions)
|
||||||
|
|
|
@ -2160,19 +2160,18 @@ void CPU::NewRec::RISCV64Compiler::Compile_mtc0(CompileFlags cf)
|
||||||
SwitchToFarCode(true, &Assembler::BEQ, RSCRATCH, zero);
|
SwitchToFarCode(true, &Assembler::BEQ, RSCRATCH, zero);
|
||||||
rvAsm->ADDI(sp, sp, -16);
|
rvAsm->ADDI(sp, sp, -16);
|
||||||
rvAsm->SW(RARG1, 0, sp);
|
rvAsm->SW(RARG1, 0, sp);
|
||||||
rvAsm->SW(RARG2, 8, sp);
|
|
||||||
EmitCall(reinterpret_cast<const void*>(&CPU::UpdateMemoryPointers));
|
EmitCall(reinterpret_cast<const void*>(&CPU::UpdateMemoryPointers));
|
||||||
rvAsm->SW(RARG2, 8, sp);
|
rvAsm->LW(RARG1, 0, sp);
|
||||||
rvAsm->SW(RARG1, 0, sp);
|
|
||||||
rvAsm->ADDI(sp, sp, 16);
|
rvAsm->ADDI(sp, sp, 16);
|
||||||
rvAsm->LD(RMEMBASE, PTR(&g_state.fastmem_base));
|
rvAsm->LD(RMEMBASE, PTR(&g_state.fastmem_base));
|
||||||
SwitchToNearCode(true);
|
SwitchToNearCode(true);
|
||||||
}
|
|
||||||
|
|
||||||
if (reg == Cop0Reg::SR || reg == Cop0Reg::CAUSE)
|
TestInterrupts(RARG1);
|
||||||
|
}
|
||||||
|
else if (reg == Cop0Reg::CAUSE)
|
||||||
{
|
{
|
||||||
const GPR sr = (reg == Cop0Reg::SR) ? RARG2 : (rvAsm->LW(RARG1, PTR(&g_state.cop0_regs.sr.bits)), RARG1);
|
rvAsm->LW(RARG1, PTR(&g_state.cop0_regs.sr.bits));
|
||||||
TestInterrupts(sr);
|
TestInterrupts(RARG1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (reg == Cop0Reg::DCIC && g_settings.cpu_recompiler_memory_exceptions)
|
if (reg == Cop0Reg::DCIC && g_settings.cpu_recompiler_memory_exceptions)
|
||||||
|
|
|
@ -28,6 +28,13 @@ Log_SetChannel(CPU::NewRec);
|
||||||
|
|
||||||
static constexpr u32 BACKPATCH_JMP_SIZE = 5;
|
static constexpr u32 BACKPATCH_JMP_SIZE = 5;
|
||||||
|
|
||||||
|
// on win32, we need to reserve an additional 32 bytes shadow space when calling out to C
|
||||||
|
#ifdef _WIN32
|
||||||
|
static constexpr u32 STACK_SHADOW_SIZE = 32;
|
||||||
|
#else
|
||||||
|
static constexpr u32 STACK_SHADOW_SIZE = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
using namespace Xbyak;
|
using namespace Xbyak;
|
||||||
|
|
||||||
using CPU::Recompiler::IsCallerSavedRegister;
|
using CPU::Recompiler::IsCallerSavedRegister;
|
||||||
|
@ -1881,20 +1888,20 @@ void CPU::NewRec::X64Compiler::Compile_mtc0(CompileFlags cf)
|
||||||
|
|
||||||
cg->test(changed_bits, 1u << 16);
|
cg->test(changed_bits, 1u << 16);
|
||||||
SwitchToFarCode(true, &CodeGenerator::jnz);
|
SwitchToFarCode(true, &CodeGenerator::jnz);
|
||||||
cg->push(RWARG1);
|
cg->mov(cg->dword[cg->rsp], RWARG2);
|
||||||
cg->push(RWARG2);
|
cg->sub(cg->rsp, STACK_SHADOW_SIZE + 8);
|
||||||
cg->call(&CPU::UpdateMemoryPointers);
|
cg->call(&CPU::UpdateMemoryPointers);
|
||||||
cg->pop(RWARG2);
|
cg->add(cg->rsp, STACK_SHADOW_SIZE + 8);
|
||||||
cg->pop(RWARG1);
|
cg->mov(RWARG2, cg->dword[cg->rsp]);
|
||||||
cg->mov(RMEMBASE, cg->qword[PTR(&g_state.fastmem_base)]);
|
cg->mov(RMEMBASE, cg->qword[PTR(&g_state.fastmem_base)]);
|
||||||
SwitchToNearCode(true);
|
SwitchToNearCode(true);
|
||||||
}
|
|
||||||
|
|
||||||
if (reg == Cop0Reg::SR || reg == Cop0Reg::CAUSE)
|
TestInterrupts(RWARG2);
|
||||||
|
}
|
||||||
|
else if (reg == Cop0Reg::CAUSE)
|
||||||
{
|
{
|
||||||
const Reg32 sr =
|
cg->mov(RWARG1, cg->dword[PTR(&g_state.cop0_regs.sr.bits)]);
|
||||||
(reg == Cop0Reg::SR) ? RWARG2 : (cg->mov(RWARG1, cg->dword[PTR(&g_state.cop0_regs.sr.bits)]), RWARG1);
|
TestInterrupts(RWARG1);
|
||||||
TestInterrupts(sr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (reg == Cop0Reg::DCIC && g_settings.cpu_recompiler_memory_exceptions)
|
if (reg == Cop0Reg::DCIC && g_settings.cpu_recompiler_memory_exceptions)
|
||||||
|
@ -2104,13 +2111,6 @@ u32 CPU::NewRec::CompileLoadStoreThunk(void* thunk_code, u32 thunk_space, void*
|
||||||
|
|
||||||
static constexpr u32 GPR_SIZE = 8;
|
static constexpr u32 GPR_SIZE = 8;
|
||||||
|
|
||||||
// on win32, we need to reserve an additional 32 bytes shadow space when calling out to C
|
|
||||||
#ifdef _WIN32
|
|
||||||
static constexpr u32 SHADOW_SIZE = 32;
|
|
||||||
#else
|
|
||||||
static constexpr u32 SHADOW_SIZE = 0;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// save regs
|
// save regs
|
||||||
u32 num_gprs = 0;
|
u32 num_gprs = 0;
|
||||||
|
|
||||||
|
@ -2120,13 +2120,13 @@ u32 CPU::NewRec::CompileLoadStoreThunk(void* thunk_code, u32 thunk_space, void*
|
||||||
num_gprs++;
|
num_gprs++;
|
||||||
}
|
}
|
||||||
|
|
||||||
const u32 stack_size = (((num_gprs + 1) & ~1u) * GPR_SIZE) + SHADOW_SIZE;
|
const u32 stack_size = (((num_gprs + 1) & ~1u) * GPR_SIZE) + STACK_SHADOW_SIZE;
|
||||||
|
|
||||||
if (stack_size > 0)
|
if (stack_size > 0)
|
||||||
{
|
{
|
||||||
cg->sub(cg->rsp, stack_size);
|
cg->sub(cg->rsp, stack_size);
|
||||||
|
|
||||||
u32 stack_offset = SHADOW_SIZE;
|
u32 stack_offset = STACK_SHADOW_SIZE;
|
||||||
for (u32 i = 0; i < NUM_HOST_REGS; i++)
|
for (u32 i = 0; i < NUM_HOST_REGS; i++)
|
||||||
{
|
{
|
||||||
if ((gpr_bitmask & (1u << i)) && IsCallerSavedRegister(i) && (!is_load || data_register != i))
|
if ((gpr_bitmask & (1u << i)) && IsCallerSavedRegister(i) && (!is_load || data_register != i))
|
||||||
|
@ -2201,7 +2201,7 @@ u32 CPU::NewRec::CompileLoadStoreThunk(void* thunk_code, u32 thunk_space, void*
|
||||||
// restore regs
|
// restore regs
|
||||||
if (stack_size > 0)
|
if (stack_size > 0)
|
||||||
{
|
{
|
||||||
u32 stack_offset = SHADOW_SIZE;
|
u32 stack_offset = STACK_SHADOW_SIZE;
|
||||||
for (u32 i = 0; i < NUM_HOST_REGS; i++)
|
for (u32 i = 0; i < NUM_HOST_REGS; i++)
|
||||||
{
|
{
|
||||||
if ((gpr_bitmask & (1u << i)) && IsCallerSavedRegister(i) && (!is_load || data_register != i))
|
if ((gpr_bitmask & (1u << i)) && IsCallerSavedRegister(i) && (!is_load || data_register != i))
|
||||||
|
|
|
@ -1411,17 +1411,7 @@ void CodeGenerator::RestoreStackAfterCall(u32 adjust_size)
|
||||||
|
|
||||||
void CodeGenerator::EmitCall(const void* ptr)
|
void CodeGenerator::EmitCall(const void* ptr)
|
||||||
{
|
{
|
||||||
const s64 displacement = armGetPCDisplacement(GetCurrentCodePointer(), ptr);
|
armEmitCall(m_emit, ptr, false);
|
||||||
const bool use_blr = !vixl::IsInt26(displacement);
|
|
||||||
if (use_blr)
|
|
||||||
{
|
|
||||||
m_emit->Mov(GetHostReg64(RSCRATCH), reinterpret_cast<uintptr_t>(ptr));
|
|
||||||
m_emit->Blr(GetHostReg64(RSCRATCH));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
m_emit->bl(displacement);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CodeGenerator::EmitFunctionCallPtr(Value* return_value, const void* ptr)
|
void CodeGenerator::EmitFunctionCallPtr(Value* return_value, const void* ptr)
|
||||||
|
|
Loading…
Reference in a new issue