Merge pull request #5097 from MerryMage/pic

PIE support for the DSP JIT
This commit is contained in:
Markus Wick 2017-03-17 22:24:03 +01:00 committed by GitHub
commit b7f605e88e
7 changed files with 123 additions and 105 deletions

View File

@ -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

View File

@ -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);

View File

@ -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();
}
}

View File

@ -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

View File

@ -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)
{

View File

@ -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;

View File

@ -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)