Merge pull request #5097 from MerryMage/pic
PIE support for the DSP JIT
This commit is contained in:
commit
b7f605e88e
|
@ -5,6 +5,7 @@
|
|||
#include "Core/DSP/Jit/DSPEmitter.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstddef>
|
||||
#include <cstring>
|
||||
|
||||
#include "Common/Assert.h"
|
||||
|
@ -105,10 +106,10 @@ void DSPEmitter::ClearIRAMandDSPJITCodespaceReset()
|
|||
void DSPEmitter::checkExceptions(u32 retval)
|
||||
{
|
||||
// Check for interrupts and exceptions
|
||||
TEST(8, M(&g_dsp.exceptions), Imm8(0xff));
|
||||
TEST(8, M_SDSP_exceptions(), Imm8(0xff));
|
||||
FixupBranch skipCheck = J_CC(CC_Z, true);
|
||||
|
||||
MOV(16, M(&(g_dsp.pc)), Imm16(m_compile_pc));
|
||||
MOV(16, M_SDSP_pc(), Imm16(m_compile_pc));
|
||||
|
||||
DSPJitRegCache c(m_gpr);
|
||||
m_gpr.SaveRegs();
|
||||
|
@ -138,7 +139,7 @@ void DSPEmitter::FallBackToInterpreter(UDSPInstruction inst)
|
|||
// of block.
|
||||
// Fallbacks to interpreter need this for fetching immediate values
|
||||
|
||||
MOV(16, M(&(g_dsp.pc)), Imm16(m_compile_pc + 1));
|
||||
MOV(16, M_SDSP_pc(), Imm16(m_compile_pc + 1));
|
||||
}
|
||||
|
||||
// Fall back to interpreter
|
||||
|
@ -250,18 +251,18 @@ void DSPEmitter::Compile(u16 start_addr)
|
|||
// by the analyzer.
|
||||
if (Analyzer::GetCodeFlags(static_cast<u16>(m_compile_pc - 1u)) & Analyzer::CODE_LOOP_END)
|
||||
{
|
||||
MOVZX(32, 16, EAX, M(&(g_dsp.r.st[2])));
|
||||
MOVZX(32, 16, EAX, M_SDSP_r_st(2));
|
||||
TEST(32, R(EAX), R(EAX));
|
||||
FixupBranch rLoopAddressExit = J_CC(CC_LE, true);
|
||||
|
||||
MOVZX(32, 16, EAX, M(&g_dsp.r.st[3]));
|
||||
MOVZX(32, 16, EAX, M_SDSP_r_st(3));
|
||||
TEST(32, R(EAX), R(EAX));
|
||||
FixupBranch rLoopCounterExit = J_CC(CC_LE, true);
|
||||
|
||||
if (!opcode->branch)
|
||||
{
|
||||
// branch insns update the g_dsp.pc
|
||||
MOV(16, M(&(g_dsp.pc)), Imm16(m_compile_pc));
|
||||
MOV(16, M_SDSP_pc(), Imm16(m_compile_pc));
|
||||
}
|
||||
|
||||
// These functions branch and therefore only need to be called in the
|
||||
|
@ -296,7 +297,7 @@ void DSPEmitter::Compile(u16 start_addr)
|
|||
else if (!opcode->jitFunc)
|
||||
{
|
||||
// look at g_dsp.pc if we actually branched
|
||||
MOV(16, R(AX), M(&g_dsp.pc));
|
||||
MOV(16, R(AX), M_SDSP_pc());
|
||||
CMP(16, R(AX), Imm16(m_compile_pc));
|
||||
FixupBranch rNoBranch = J_CC(CC_Z, true);
|
||||
|
||||
|
@ -328,7 +329,7 @@ void DSPEmitter::Compile(u16 start_addr)
|
|||
|
||||
if (fixup_pc)
|
||||
{
|
||||
MOV(16, M(&(g_dsp.pc)), Imm16(m_compile_pc));
|
||||
MOV(16, M_SDSP_pc(), Imm16(m_compile_pc));
|
||||
}
|
||||
|
||||
m_blocks[start_addr] = (DSPCompiledCode)entryPoint;
|
||||
|
@ -415,21 +416,23 @@ void DSPEmitter::CompileDispatcher()
|
|||
BitSet32 registers_used = ABI_ALL_CALLEE_SAVED & BitSet32(0xffff);
|
||||
ABI_PushRegistersAndAdjustStack(registers_used, 8);
|
||||
|
||||
MOV(64, R(R15), ImmPtr(&g_dsp));
|
||||
|
||||
const u8* dispatcherLoop = GetCodePtr();
|
||||
|
||||
FixupBranch exceptionExit;
|
||||
if (Host::OnThread())
|
||||
{
|
||||
CMP(8, M(const_cast<bool*>(&g_dsp.external_interrupt_waiting)), Imm8(0));
|
||||
CMP(8, M_SDSP_external_interrupt_waiting(), Imm8(0));
|
||||
exceptionExit = J_CC(CC_NE);
|
||||
}
|
||||
|
||||
// Check for DSP halt
|
||||
TEST(8, M(&g_dsp.cr), Imm8(CR_HALT));
|
||||
TEST(8, M_SDSP_cr(), Imm8(CR_HALT));
|
||||
FixupBranch _halt = J_CC(CC_NE);
|
||||
|
||||
// Execute block. Cycles executed returned in EAX.
|
||||
MOVZX(64, 16, ECX, M(&g_dsp.pc));
|
||||
MOVZX(64, 16, ECX, M_SDSP_pc());
|
||||
MOV(64, R(RBX), ImmPtr(m_blocks.data()));
|
||||
JMPptr(MComplex(RBX, RCX, SCALE_8, 0));
|
||||
|
||||
|
@ -452,6 +455,36 @@ void DSPEmitter::CompileDispatcher()
|
|||
RET();
|
||||
}
|
||||
|
||||
Gen::OpArg DSPEmitter::M_SDSP_pc()
|
||||
{
|
||||
return MDisp(R15, static_cast<int>(offsetof(SDSP, pc)));
|
||||
}
|
||||
|
||||
Gen::OpArg DSPEmitter::M_SDSP_exceptions()
|
||||
{
|
||||
return MDisp(R15, static_cast<int>(offsetof(SDSP, exceptions)));
|
||||
}
|
||||
|
||||
Gen::OpArg DSPEmitter::M_SDSP_cr()
|
||||
{
|
||||
return MDisp(R15, static_cast<int>(offsetof(SDSP, cr)));
|
||||
}
|
||||
|
||||
Gen::OpArg DSPEmitter::M_SDSP_external_interrupt_waiting()
|
||||
{
|
||||
return MDisp(R15, static_cast<int>(offsetof(SDSP, external_interrupt_waiting)));
|
||||
}
|
||||
|
||||
Gen::OpArg DSPEmitter::M_SDSP_r_st(size_t index)
|
||||
{
|
||||
return MDisp(R15, static_cast<int>(offsetof(SDSP, r.st[index])));
|
||||
}
|
||||
|
||||
Gen::OpArg DSPEmitter::M_SDSP_reg_stack_ptr(size_t index)
|
||||
{
|
||||
return MDisp(R15, static_cast<int>(offsetof(SDSP, reg_stack_ptr[index])));
|
||||
}
|
||||
|
||||
} // namespace x86
|
||||
} // namespace JIT
|
||||
} // namespace DSP
|
||||
|
|
|
@ -279,6 +279,14 @@ private:
|
|||
void dsp_op_read_reg(int reg, Gen::X64Reg host_dreg,
|
||||
RegisterExtension extend = RegisterExtension::None);
|
||||
|
||||
// SDSP memory offset helpers
|
||||
Gen::OpArg M_SDSP_pc();
|
||||
Gen::OpArg M_SDSP_exceptions();
|
||||
Gen::OpArg M_SDSP_cr();
|
||||
Gen::OpArg M_SDSP_external_interrupt_waiting();
|
||||
Gen::OpArg M_SDSP_r_st(size_t index);
|
||||
Gen::OpArg M_SDSP_reg_stack_ptr(size_t index);
|
||||
|
||||
// Ext command helpers
|
||||
void popExtValueToReg();
|
||||
void pushExtValueFromMem(u16 dreg, u16 sreg);
|
||||
|
|
|
@ -136,7 +136,7 @@ void DSPEmitter::r_jcc(const UDSPInstruction opc)
|
|||
// If the block is unconditional, attempt to link block
|
||||
if (opcode->uncond_branch)
|
||||
WriteBlockLink(dest);
|
||||
MOV(16, M(&g_dsp.pc), Imm16(dest));
|
||||
MOV(16, M_SDSP_pc(), Imm16(dest));
|
||||
WriteBranchExit();
|
||||
}
|
||||
// Generic jmp implementation
|
||||
|
@ -148,7 +148,7 @@ void DSPEmitter::r_jcc(const UDSPInstruction opc)
|
|||
// NOTE: Cannot use FallBackToInterpreter(opc) here because of the need to write branch exit
|
||||
void DSPEmitter::jcc(const UDSPInstruction opc)
|
||||
{
|
||||
MOV(16, M(&(g_dsp.pc)), Imm16(m_compile_pc + 2));
|
||||
MOV(16, M_SDSP_pc(), Imm16(m_compile_pc + 2));
|
||||
ReJitConditional(opc, &DSPEmitter::r_jcc);
|
||||
}
|
||||
|
||||
|
@ -158,7 +158,7 @@ void DSPEmitter::r_jmprcc(const UDSPInstruction opc)
|
|||
// reg can only be DSP_REG_ARx and DSP_REG_IXx now,
|
||||
// no need to handle DSP_REG_STx.
|
||||
dsp_op_read_reg(reg, RAX);
|
||||
MOV(16, M(&g_dsp.pc), R(EAX));
|
||||
MOV(16, M_SDSP_pc(), R(EAX));
|
||||
WriteBranchExit();
|
||||
}
|
||||
// Generic jmpr implementation
|
||||
|
@ -168,7 +168,7 @@ void DSPEmitter::r_jmprcc(const UDSPInstruction opc)
|
|||
// NOTE: Cannot use FallBackToInterpreter(opc) here because of the need to write branch exit
|
||||
void DSPEmitter::jmprcc(const UDSPInstruction opc)
|
||||
{
|
||||
MOV(16, M(&g_dsp.pc), Imm16(m_compile_pc + 1));
|
||||
MOV(16, M_SDSP_pc(), Imm16(m_compile_pc + 1));
|
||||
ReJitConditional(opc, &DSPEmitter::r_jmprcc);
|
||||
}
|
||||
|
||||
|
@ -182,7 +182,7 @@ void DSPEmitter::r_call(const UDSPInstruction opc)
|
|||
// If the block is unconditional, attempt to link block
|
||||
if (opcode->uncond_branch)
|
||||
WriteBlockLink(dest);
|
||||
MOV(16, M(&g_dsp.pc), Imm16(dest));
|
||||
MOV(16, M_SDSP_pc(), Imm16(dest));
|
||||
WriteBranchExit();
|
||||
}
|
||||
// Generic call implementation
|
||||
|
@ -195,7 +195,7 @@ void DSPEmitter::r_call(const UDSPInstruction opc)
|
|||
// NOTE: Cannot use FallBackToInterpreter(opc) here because of the need to write branch exit
|
||||
void DSPEmitter::call(const UDSPInstruction opc)
|
||||
{
|
||||
MOV(16, M(&(g_dsp.pc)), Imm16(m_compile_pc + 2));
|
||||
MOV(16, M_SDSP_pc(), Imm16(m_compile_pc + 2));
|
||||
ReJitConditional(opc, &DSPEmitter::r_call);
|
||||
}
|
||||
|
||||
|
@ -205,7 +205,7 @@ void DSPEmitter::r_callr(const UDSPInstruction opc)
|
|||
MOV(16, R(DX), Imm16(m_compile_pc + 1));
|
||||
dsp_reg_store_stack(StackRegister::Call);
|
||||
dsp_op_read_reg(reg, RAX);
|
||||
MOV(16, M(&g_dsp.pc), R(EAX));
|
||||
MOV(16, M_SDSP_pc(), R(EAX));
|
||||
WriteBranchExit();
|
||||
}
|
||||
// Generic callr implementation
|
||||
|
@ -217,13 +217,13 @@ void DSPEmitter::r_callr(const UDSPInstruction opc)
|
|||
// NOTE: Cannot use FallBackToInterpreter(opc) here because of the need to write branch exit
|
||||
void DSPEmitter::callr(const UDSPInstruction opc)
|
||||
{
|
||||
MOV(16, M(&g_dsp.pc), Imm16(m_compile_pc + 1));
|
||||
MOV(16, M_SDSP_pc(), Imm16(m_compile_pc + 1));
|
||||
ReJitConditional(opc, &DSPEmitter::r_callr);
|
||||
}
|
||||
|
||||
void DSPEmitter::r_ifcc(const UDSPInstruction opc)
|
||||
{
|
||||
MOV(16, M(&g_dsp.pc), Imm16(m_compile_pc + 1));
|
||||
MOV(16, M_SDSP_pc(), Imm16(m_compile_pc + 1));
|
||||
}
|
||||
// Generic if implementation
|
||||
// IFcc
|
||||
|
@ -235,7 +235,7 @@ void DSPEmitter::ifcc(const UDSPInstruction opc)
|
|||
const u16 address = m_compile_pc + 1;
|
||||
const DSPOPCTemplate* const op_template = GetOpTemplate(dsp_imem_read(address));
|
||||
|
||||
MOV(16, M(&g_dsp.pc), Imm16(address + op_template->size));
|
||||
MOV(16, M_SDSP_pc(), Imm16(address + op_template->size));
|
||||
ReJitConditional(opc, &DSPEmitter::r_ifcc);
|
||||
WriteBranchExit();
|
||||
}
|
||||
|
@ -243,7 +243,7 @@ void DSPEmitter::ifcc(const UDSPInstruction opc)
|
|||
void DSPEmitter::r_ret(const UDSPInstruction opc)
|
||||
{
|
||||
dsp_reg_load_stack(StackRegister::Call);
|
||||
MOV(16, M(&g_dsp.pc), R(DX));
|
||||
MOV(16, M_SDSP_pc(), R(DX));
|
||||
WriteBranchExit();
|
||||
}
|
||||
|
||||
|
@ -255,7 +255,7 @@ void DSPEmitter::r_ret(const UDSPInstruction opc)
|
|||
// NOTE: Cannot use FallBackToInterpreter(opc) here because of the need to write branch exit
|
||||
void DSPEmitter::ret(const UDSPInstruction opc)
|
||||
{
|
||||
MOV(16, M(&g_dsp.pc), Imm16(m_compile_pc + 1));
|
||||
MOV(16, M_SDSP_pc(), Imm16(m_compile_pc + 1));
|
||||
ReJitConditional(opc, &DSPEmitter::r_ret);
|
||||
}
|
||||
|
||||
|
@ -271,7 +271,7 @@ void DSPEmitter::rti(const UDSPInstruction opc)
|
|||
dsp_op_write_reg(DSP_REG_SR, RDX);
|
||||
// g_dsp.pc = dsp_reg_load_stack(StackRegister::Call);
|
||||
dsp_reg_load_stack(StackRegister::Call);
|
||||
MOV(16, M(&g_dsp.pc), R(DX));
|
||||
MOV(16, M_SDSP_pc(), R(DX));
|
||||
}
|
||||
|
||||
// HALT
|
||||
|
@ -279,10 +279,10 @@ void DSPEmitter::rti(const UDSPInstruction opc)
|
|||
// Stops execution of DSP code. Sets bit DSP_CR_HALT in register DREG_CR.
|
||||
void DSPEmitter::halt(const UDSPInstruction opc)
|
||||
{
|
||||
OR(16, M(&g_dsp.cr), Imm16(4));
|
||||
OR(16, M_SDSP_cr(), Imm16(4));
|
||||
// g_dsp.pc = dsp_reg_load_stack(StackRegister::Call);
|
||||
dsp_reg_load_stack(StackRegister::Call);
|
||||
MOV(16, M(&g_dsp.pc), R(DX));
|
||||
MOV(16, M_SDSP_pc(), R(DX));
|
||||
}
|
||||
|
||||
// LOOP handling: Loop stack is used to control execution of repeated blocks of
|
||||
|
@ -293,20 +293,20 @@ void DSPEmitter::halt(const UDSPInstruction opc)
|
|||
// continues at next opcode.
|
||||
void DSPEmitter::HandleLoop()
|
||||
{
|
||||
MOVZX(32, 16, EAX, M(&g_dsp.r.st[2]));
|
||||
MOVZX(32, 16, ECX, M(&g_dsp.r.st[3]));
|
||||
MOVZX(32, 16, EAX, M_SDSP_r_st(2));
|
||||
MOVZX(32, 16, ECX, M_SDSP_r_st(3));
|
||||
|
||||
TEST(32, R(RCX), R(RCX));
|
||||
FixupBranch rLoopCntG = J_CC(CC_LE, true);
|
||||
CMP(16, R(RAX), Imm16(m_compile_pc - 1));
|
||||
FixupBranch rLoopAddrG = J_CC(CC_NE, true);
|
||||
|
||||
SUB(16, M(&(g_dsp.r.st[3])), Imm16(1));
|
||||
CMP(16, M(&(g_dsp.r.st[3])), Imm16(0));
|
||||
SUB(16, M_SDSP_r_st(3), Imm16(1));
|
||||
CMP(16, M_SDSP_r_st(3), Imm16(0));
|
||||
|
||||
FixupBranch loadStack = J_CC(CC_LE, true);
|
||||
MOVZX(32, 16, ECX, M(&(g_dsp.r.st[0])));
|
||||
MOV(16, M(&g_dsp.pc), R(RCX));
|
||||
MOVZX(32, 16, ECX, M_SDSP_r_st(0));
|
||||
MOV(16, M_SDSP_pc(), R(RCX));
|
||||
FixupBranch loopUpdated = J(true);
|
||||
|
||||
SetJumpTarget(loadStack);
|
||||
|
@ -346,12 +346,12 @@ void DSPEmitter::loop(const UDSPInstruction opc)
|
|||
MOV(16, R(RDX), Imm16(loop_pc));
|
||||
dsp_reg_store_stack(StackRegister::LoopAddress);
|
||||
m_gpr.FlushRegs(c);
|
||||
MOV(16, M(&(g_dsp.pc)), Imm16(m_compile_pc + 1));
|
||||
MOV(16, M_SDSP_pc(), Imm16(m_compile_pc + 1));
|
||||
FixupBranch exit = J(true);
|
||||
|
||||
SetJumpTarget(cnt);
|
||||
// dsp_skip_inst();
|
||||
MOV(16, M(&g_dsp.pc), Imm16(loop_pc + GetOpTemplate(dsp_imem_read(loop_pc))->size));
|
||||
MOV(16, M_SDSP_pc(), Imm16(loop_pc + GetOpTemplate(dsp_imem_read(loop_pc))->size));
|
||||
WriteBranchExit();
|
||||
m_gpr.FlushRegs(c, false);
|
||||
SetJumpTarget(exit);
|
||||
|
@ -379,12 +379,12 @@ void DSPEmitter::loopi(const UDSPInstruction opc)
|
|||
MOV(16, R(RDX), Imm16(cnt));
|
||||
dsp_reg_store_stack(StackRegister::LoopCounter);
|
||||
|
||||
MOV(16, M(&(g_dsp.pc)), Imm16(m_compile_pc + 1));
|
||||
MOV(16, M_SDSP_pc(), Imm16(m_compile_pc + 1));
|
||||
}
|
||||
else
|
||||
{
|
||||
// dsp_skip_inst();
|
||||
MOV(16, M(&g_dsp.pc), Imm16(loop_pc + GetOpTemplate(dsp_imem_read(loop_pc))->size));
|
||||
MOV(16, M_SDSP_pc(), Imm16(loop_pc + GetOpTemplate(dsp_imem_read(loop_pc))->size));
|
||||
WriteBranchExit();
|
||||
}
|
||||
}
|
||||
|
@ -414,14 +414,14 @@ void DSPEmitter::bloop(const UDSPInstruction opc)
|
|||
dsp_reg_store_stack(StackRegister::Call);
|
||||
MOV(16, R(RDX), Imm16(loop_pc));
|
||||
dsp_reg_store_stack(StackRegister::LoopAddress);
|
||||
MOV(16, M(&(g_dsp.pc)), Imm16(m_compile_pc + 2));
|
||||
MOV(16, M_SDSP_pc(), Imm16(m_compile_pc + 2));
|
||||
m_gpr.FlushRegs(c, true);
|
||||
FixupBranch exit = J(true);
|
||||
|
||||
SetJumpTarget(cnt);
|
||||
// g_dsp.pc = loop_pc;
|
||||
// dsp_skip_inst();
|
||||
MOV(16, M(&g_dsp.pc), Imm16(loop_pc + GetOpTemplate(dsp_imem_read(loop_pc))->size));
|
||||
MOV(16, M_SDSP_pc(), Imm16(loop_pc + GetOpTemplate(dsp_imem_read(loop_pc))->size));
|
||||
WriteBranchExit();
|
||||
m_gpr.FlushRegs(c, false);
|
||||
SetJumpTarget(exit);
|
||||
|
@ -451,13 +451,13 @@ void DSPEmitter::bloopi(const UDSPInstruction opc)
|
|||
MOV(16, R(RDX), Imm16(cnt));
|
||||
dsp_reg_store_stack(StackRegister::LoopCounter);
|
||||
|
||||
MOV(16, M(&(g_dsp.pc)), Imm16(m_compile_pc + 2));
|
||||
MOV(16, M_SDSP_pc(), Imm16(m_compile_pc + 2));
|
||||
}
|
||||
else
|
||||
{
|
||||
// g_dsp.pc = loop_pc;
|
||||
// dsp_skip_inst();
|
||||
MOV(16, M(&g_dsp.pc), Imm16(loop_pc + GetOpTemplate(dsp_imem_read(loop_pc))->size));
|
||||
MOV(16, M_SDSP_pc(), Imm16(loop_pc + GetOpTemplate(dsp_imem_read(loop_pc))->size));
|
||||
WriteBranchExit();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,6 +6,8 @@
|
|||
|
||||
// Multiplier and product register control
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
#include "Common/CommonTypes.h"
|
||||
|
||||
#include "Core/DSP/DSPCore.h"
|
||||
|
@ -151,9 +153,10 @@ void DSPEmitter::multiply_mulx(u8 axh0, u8 axh1)
|
|||
// direct use of prod regs by AX/AXWII (look @that part of ucode).
|
||||
void DSPEmitter::clrp(const UDSPInstruction opc)
|
||||
{
|
||||
int offset = static_cast<int>(offsetof(SDSP, r.prod.val));
|
||||
// 64bit move to memory does not work. use 2 32bits
|
||||
MOV(32, M(((u32*)&g_dsp.r.prod.val) + 0), Imm32(0xfff00000U));
|
||||
MOV(32, M(((u32*)&g_dsp.r.prod.val) + 1), Imm32(0x001000ffU));
|
||||
MOV(32, MDisp(R15, offset + 0 * sizeof(u32)), Imm32(0xfff00000U));
|
||||
MOV(32, MDisp(R15, offset + 1 * sizeof(u32)), Imm32(0x001000ffU));
|
||||
}
|
||||
|
||||
// TSTPROD
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#include "Core/DSP/Jit/DSPJitRegCache.h"
|
||||
|
||||
#include <cinttypes>
|
||||
#include <cstddef>
|
||||
|
||||
#include "Common/Assert.h"
|
||||
#include "Common/Logging/Log.h"
|
||||
|
@ -26,7 +27,7 @@ namespace x86
|
|||
constexpr std::array<X64Reg, 15> s_allocation_order = {
|
||||
{R8, R9, R10, R11, R12, R13, R14, R15, RSI, RDI, RBX, RCX, RDX, RAX, RBP}};
|
||||
|
||||
static void* GetRegisterPointer(size_t reg)
|
||||
static Gen::OpArg GetRegisterPointer(size_t reg)
|
||||
{
|
||||
switch (reg)
|
||||
{
|
||||
|
@ -34,60 +35,60 @@ static void* GetRegisterPointer(size_t reg)
|
|||
case DSP_REG_AR1:
|
||||
case DSP_REG_AR2:
|
||||
case DSP_REG_AR3:
|
||||
return &g_dsp.r.ar[reg - DSP_REG_AR0];
|
||||
return MDisp(R15, static_cast<int>(offsetof(SDSP, r.ar[reg - DSP_REG_AR0])));
|
||||
case DSP_REG_IX0:
|
||||
case DSP_REG_IX1:
|
||||
case DSP_REG_IX2:
|
||||
case DSP_REG_IX3:
|
||||
return &g_dsp.r.ix[reg - DSP_REG_IX0];
|
||||
return MDisp(R15, static_cast<int>(offsetof(SDSP, r.ix[reg - DSP_REG_IX0])));
|
||||
case DSP_REG_WR0:
|
||||
case DSP_REG_WR1:
|
||||
case DSP_REG_WR2:
|
||||
case DSP_REG_WR3:
|
||||
return &g_dsp.r.wr[reg - DSP_REG_WR0];
|
||||
return MDisp(R15, static_cast<int>(offsetof(SDSP, r.wr[reg - DSP_REG_WR0])));
|
||||
case DSP_REG_ST0:
|
||||
case DSP_REG_ST1:
|
||||
case DSP_REG_ST2:
|
||||
case DSP_REG_ST3:
|
||||
return &g_dsp.r.st[reg - DSP_REG_ST0];
|
||||
return MDisp(R15, static_cast<int>(offsetof(SDSP, r.st[reg - DSP_REG_ST0])));
|
||||
case DSP_REG_ACH0:
|
||||
case DSP_REG_ACH1:
|
||||
return &g_dsp.r.ac[reg - DSP_REG_ACH0].h;
|
||||
return MDisp(R15, static_cast<int>(offsetof(SDSP, r.ac[reg - DSP_REG_ACH0].h)));
|
||||
case DSP_REG_CR:
|
||||
return &g_dsp.r.cr;
|
||||
return MDisp(R15, static_cast<int>(offsetof(SDSP, r.cr)));
|
||||
case DSP_REG_SR:
|
||||
return &g_dsp.r.sr;
|
||||
return MDisp(R15, static_cast<int>(offsetof(SDSP, r.sr)));
|
||||
case DSP_REG_PRODL:
|
||||
return &g_dsp.r.prod.l;
|
||||
return MDisp(R15, static_cast<int>(offsetof(SDSP, r.prod.l)));
|
||||
case DSP_REG_PRODM:
|
||||
return &g_dsp.r.prod.m;
|
||||
return MDisp(R15, static_cast<int>(offsetof(SDSP, r.prod.m)));
|
||||
case DSP_REG_PRODH:
|
||||
return &g_dsp.r.prod.h;
|
||||
return MDisp(R15, static_cast<int>(offsetof(SDSP, r.prod.h)));
|
||||
case DSP_REG_PRODM2:
|
||||
return &g_dsp.r.prod.m2;
|
||||
return MDisp(R15, static_cast<int>(offsetof(SDSP, r.prod.m2)));
|
||||
case DSP_REG_AXL0:
|
||||
case DSP_REG_AXL1:
|
||||
return &g_dsp.r.ax[reg - DSP_REG_AXL0].l;
|
||||
return MDisp(R15, static_cast<int>(offsetof(SDSP, r.ax[reg - DSP_REG_AXL0].l)));
|
||||
case DSP_REG_AXH0:
|
||||
case DSP_REG_AXH1:
|
||||
return &g_dsp.r.ax[reg - DSP_REG_AXH0].h;
|
||||
return MDisp(R15, static_cast<int>(offsetof(SDSP, r.ax[reg - DSP_REG_AXH0].h)));
|
||||
case DSP_REG_ACL0:
|
||||
case DSP_REG_ACL1:
|
||||
return &g_dsp.r.ac[reg - DSP_REG_ACL0].l;
|
||||
return MDisp(R15, static_cast<int>(offsetof(SDSP, r.ac[reg - DSP_REG_ACL0].l)));
|
||||
case DSP_REG_ACM0:
|
||||
case DSP_REG_ACM1:
|
||||
return &g_dsp.r.ac[reg - DSP_REG_ACM0].m;
|
||||
return MDisp(R15, static_cast<int>(offsetof(SDSP, r.ac[reg - DSP_REG_ACM0].m)));
|
||||
case DSP_REG_AX0_32:
|
||||
case DSP_REG_AX1_32:
|
||||
return &g_dsp.r.ax[reg - DSP_REG_AX0_32].val;
|
||||
return MDisp(R15, static_cast<int>(offsetof(SDSP, r.ax[reg - DSP_REG_AX0_32].val)));
|
||||
case DSP_REG_ACC0_64:
|
||||
case DSP_REG_ACC1_64:
|
||||
return &g_dsp.r.ac[reg - DSP_REG_ACC0_64].val;
|
||||
return MDisp(R15, static_cast<int>(offsetof(SDSP, r.ac[reg - DSP_REG_ACC0_64].val)));
|
||||
case DSP_REG_PROD_64:
|
||||
return &g_dsp.r.prod.val;
|
||||
return MDisp(R15, static_cast<int>(offsetof(SDSP, r.prod.val)));
|
||||
default:
|
||||
_assert_msg_(DSPLLE, 0, "cannot happen");
|
||||
return nullptr;
|
||||
return M(static_cast<void*>(nullptr));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -129,7 +130,7 @@ DSPJitRegCache::DSPJitRegCache(DSPEmitter& emitter)
|
|||
m_xregs[R12].guest_reg = DSP_REG_NONE;
|
||||
m_xregs[R13].guest_reg = DSP_REG_NONE;
|
||||
m_xregs[R14].guest_reg = DSP_REG_NONE;
|
||||
m_xregs[R15].guest_reg = DSP_REG_NONE;
|
||||
m_xregs[R15].guest_reg = DSP_REG_STATIC; // reserved for SDSP pointer
|
||||
|
||||
for (size_t i = 0; i < m_regs.size(); i++)
|
||||
{
|
||||
|
@ -141,7 +142,7 @@ DSPJitRegCache::DSPJitRegCache(DSPEmitter& emitter)
|
|||
m_regs[i].parentReg = DSP_REG_NONE;
|
||||
m_regs[i].shift = 0;
|
||||
m_regs[i].host_reg = INVALID_REG;
|
||||
m_regs[i].loc = M(m_regs[i].mem);
|
||||
m_regs[i].loc = m_regs[i].mem;
|
||||
}
|
||||
|
||||
for (unsigned int i = 0; i < 32; i++)
|
||||
|
@ -374,13 +375,11 @@ void DSPJitRegCache::FlushRegs()
|
|||
_assert_msg_(DSPLLE, m_xregs[R12].guest_reg == DSP_REG_NONE, "wrong xreg state for %d", R12);
|
||||
_assert_msg_(DSPLLE, m_xregs[R13].guest_reg == DSP_REG_NONE, "wrong xreg state for %d", R13);
|
||||
_assert_msg_(DSPLLE, m_xregs[R14].guest_reg == DSP_REG_NONE, "wrong xreg state for %d", R14);
|
||||
_assert_msg_(DSPLLE, m_xregs[R15].guest_reg == DSP_REG_NONE, "wrong xreg state for %d", R15);
|
||||
_assert_msg_(DSPLLE, m_xregs[R15].guest_reg == DSP_REG_STATIC, "wrong xreg state for %d", R15);
|
||||
|
||||
m_use_ctr = 0;
|
||||
}
|
||||
|
||||
static u64 ebp_store;
|
||||
|
||||
void DSPJitRegCache::LoadRegs(bool emit)
|
||||
{
|
||||
for (size_t i = 0; i < m_regs.size(); i++)
|
||||
|
@ -390,11 +389,6 @@ void DSPJitRegCache::LoadRegs(bool emit)
|
|||
MovToHostReg(i, m_regs[i].host_reg, emit);
|
||||
}
|
||||
}
|
||||
|
||||
if (emit)
|
||||
{
|
||||
m_emitter.MOV(64, M(&ebp_store), R(RBP));
|
||||
}
|
||||
}
|
||||
|
||||
void DSPJitRegCache::SaveRegs()
|
||||
|
@ -410,8 +404,6 @@ void DSPJitRegCache::SaveRegs()
|
|||
|
||||
_assert_msg_(DSPLLE, !m_regs[i].loc.IsSimpleReg(), "register %zu is still a simple reg", i);
|
||||
}
|
||||
|
||||
m_emitter.MOV(64, R(RBP), M(&ebp_store));
|
||||
}
|
||||
|
||||
void DSPJitRegCache::PushRegs()
|
||||
|
@ -454,14 +446,10 @@ void DSPJitRegCache::PushRegs()
|
|||
m_xregs[i].guest_reg == DSP_REG_NONE || m_xregs[i].guest_reg == DSP_REG_STATIC,
|
||||
"register %zu is still used", i);
|
||||
}
|
||||
|
||||
m_emitter.MOV(64, R(RBP), M(&ebp_store));
|
||||
}
|
||||
|
||||
void DSPJitRegCache::PopRegs()
|
||||
{
|
||||
m_emitter.MOV(64, M(&ebp_store), R(RBP));
|
||||
|
||||
int push_count = 0;
|
||||
for (int i = static_cast<int>(m_xregs.size() - 1); i >= 0; i--)
|
||||
{
|
||||
|
@ -491,25 +479,10 @@ void DSPJitRegCache::PopRegs()
|
|||
}
|
||||
|
||||
X64Reg DSPJitRegCache::MakeABICallSafe(X64Reg reg)
|
||||
{
|
||||
if (reg != RBP)
|
||||
{
|
||||
return reg;
|
||||
}
|
||||
|
||||
size_t rbp_guest = m_xregs[RBP].guest_reg;
|
||||
m_xregs[RBP].guest_reg = DSP_REG_USED;
|
||||
X64Reg safe = FindSpillFreeXReg();
|
||||
_assert_msg_(DSPLLE, safe != INVALID_REG, "could not find register");
|
||||
if (safe == INVALID_REG)
|
||||
{
|
||||
m_emitter.INT3();
|
||||
}
|
||||
m_xregs[RBP].guest_reg = rbp_guest;
|
||||
m_emitter.MOV(64, R(safe), R(reg));
|
||||
return safe;
|
||||
}
|
||||
|
||||
void DSPJitRegCache::MovToHostReg(size_t reg, X64Reg host_reg, bool load)
|
||||
{
|
||||
_assert_msg_(DSPLLE, reg < m_regs.size(), "bad register name %zu", reg);
|
||||
|
@ -654,7 +627,7 @@ void DSPJitRegCache::MovToMemory(size_t reg)
|
|||
_assert_msg_(DSPLLE, m_regs[reg].shift == 0, "still shifted??");
|
||||
|
||||
// move to mem
|
||||
OpArg tmp = M(m_regs[reg].mem);
|
||||
OpArg tmp = m_regs[reg].mem;
|
||||
|
||||
if (m_regs[reg].dirty)
|
||||
{
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#pragma once
|
||||
|
||||
#include <array>
|
||||
|
||||
#include "Common/x64Emitter.h"
|
||||
|
||||
namespace DSP
|
||||
|
@ -143,7 +144,7 @@ private:
|
|||
struct DynamicReg
|
||||
{
|
||||
Gen::OpArg loc;
|
||||
void* mem;
|
||||
Gen::OpArg mem;
|
||||
size_t size;
|
||||
bool dirty;
|
||||
bool used;
|
||||
|
|
|
@ -25,15 +25,15 @@ void DSPEmitter::dsp_reg_stack_push(StackRegister stack_reg)
|
|||
|
||||
// g_dsp.reg_stack_ptr[reg_index]++;
|
||||
// g_dsp.reg_stack_ptr[reg_index] &= DSP_STACK_MASK;
|
||||
MOV(8, R(AL), M(&g_dsp.reg_stack_ptr[reg_index]));
|
||||
MOV(8, R(AL), M_SDSP_reg_stack_ptr(reg_index));
|
||||
ADD(8, R(AL), Imm8(1));
|
||||
AND(8, R(AL), Imm8(DSP_STACK_MASK));
|
||||
MOV(8, M(&g_dsp.reg_stack_ptr[reg_index]), R(AL));
|
||||
MOV(8, M_SDSP_reg_stack_ptr(reg_index), R(AL));
|
||||
|
||||
X64Reg tmp1 = m_gpr.GetFreeXReg();
|
||||
X64Reg tmp2 = m_gpr.GetFreeXReg();
|
||||
// g_dsp.reg_stack[reg_index][g_dsp.reg_stack_ptr[reg_index]] = g_dsp.r[DSP_REG_ST0 + reg_index];
|
||||
MOV(16, R(tmp1), M(&g_dsp.r.st[reg_index]));
|
||||
MOV(16, R(tmp1), M_SDSP_r_st(reg_index));
|
||||
MOVZX(64, 8, RAX, R(AL));
|
||||
MOV(64, R(tmp2), ImmPtr(g_dsp.reg_stack[reg_index]));
|
||||
MOV(16, MComplex(tmp2, EAX, SCALE_2, 0), R(tmp1));
|
||||
|
@ -49,13 +49,13 @@ void DSPEmitter::dsp_reg_stack_pop(StackRegister stack_reg)
|
|||
const auto reg_index = static_cast<size_t>(stack_reg);
|
||||
|
||||
// g_dsp.r[DSP_REG_ST0 + reg_index] = g_dsp.reg_stack[reg_index][g_dsp.reg_stack_ptr[reg_index]];
|
||||
MOV(8, R(AL), M(&g_dsp.reg_stack_ptr[reg_index]));
|
||||
MOV(8, R(AL), M_SDSP_reg_stack_ptr(reg_index));
|
||||
X64Reg tmp1 = m_gpr.GetFreeXReg();
|
||||
X64Reg tmp2 = m_gpr.GetFreeXReg();
|
||||
MOVZX(64, 8, RAX, R(AL));
|
||||
MOV(64, R(tmp2), ImmPtr(g_dsp.reg_stack[reg_index]));
|
||||
MOV(16, R(tmp1), MComplex(tmp2, EAX, SCALE_2, 0));
|
||||
MOV(16, M(&g_dsp.r.st[reg_index]), R(tmp1));
|
||||
MOV(16, M_SDSP_r_st(reg_index), R(tmp1));
|
||||
m_gpr.PutXReg(tmp1);
|
||||
m_gpr.PutXReg(tmp2);
|
||||
|
||||
|
@ -63,7 +63,7 @@ void DSPEmitter::dsp_reg_stack_pop(StackRegister stack_reg)
|
|||
// g_dsp.reg_stack_ptr[reg_index] &= DSP_STACK_MASK;
|
||||
SUB(8, R(AL), Imm8(1));
|
||||
AND(8, R(AL), Imm8(DSP_STACK_MASK));
|
||||
MOV(8, M(&g_dsp.reg_stack_ptr[reg_index]), R(AL));
|
||||
MOV(8, M_SDSP_reg_stack_ptr(reg_index), R(AL));
|
||||
}
|
||||
|
||||
void DSPEmitter::dsp_reg_store_stack(StackRegister stack_reg, Gen::X64Reg host_sreg)
|
||||
|
@ -76,13 +76,13 @@ void DSPEmitter::dsp_reg_store_stack(StackRegister stack_reg, Gen::X64Reg host_s
|
|||
dsp_reg_stack_push(stack_reg);
|
||||
|
||||
// g_dsp.r[DSP_REG_ST0 + stack_reg] = val;
|
||||
MOV(16, M(&g_dsp.r.st[static_cast<size_t>(stack_reg)]), R(EDX));
|
||||
MOV(16, M_SDSP_r_st(static_cast<size_t>(stack_reg)), R(EDX));
|
||||
}
|
||||
|
||||
void DSPEmitter::dsp_reg_load_stack(StackRegister stack_reg, Gen::X64Reg host_dreg)
|
||||
{
|
||||
// u16 val = g_dsp.r[DSP_REG_ST0 + stack_reg];
|
||||
MOV(16, R(EDX), M(&g_dsp.r.st[static_cast<size_t>(stack_reg)]));
|
||||
MOV(16, R(EDX), M_SDSP_r_st(static_cast<size_t>(stack_reg)));
|
||||
|
||||
dsp_reg_stack_pop(stack_reg);
|
||||
|
||||
|
@ -97,7 +97,7 @@ void DSPEmitter::dsp_reg_store_stack_imm(StackRegister stack_reg, u16 val)
|
|||
dsp_reg_stack_push(stack_reg);
|
||||
|
||||
// g_dsp.r[DSP_REG_ST0 + stack_reg] = val;
|
||||
MOV(16, M(&g_dsp.r.st[static_cast<size_t>(stack_reg)]), Imm16(val));
|
||||
MOV(16, M_SDSP_r_st(static_cast<size_t>(stack_reg)), Imm16(val));
|
||||
}
|
||||
|
||||
void DSPEmitter::dsp_op_write_reg(int reg, Gen::X64Reg host_sreg)
|
||||
|
|
Loading…
Reference in New Issue