mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-02-15 16:59:18 +01:00
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 "Core/DSP/Jit/DSPEmitter.h"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <cstddef>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
|
||||||
#include "Common/Assert.h"
|
#include "Common/Assert.h"
|
||||||
@ -105,10 +106,10 @@ void DSPEmitter::ClearIRAMandDSPJITCodespaceReset()
|
|||||||
void DSPEmitter::checkExceptions(u32 retval)
|
void DSPEmitter::checkExceptions(u32 retval)
|
||||||
{
|
{
|
||||||
// Check for interrupts and exceptions
|
// 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);
|
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);
|
DSPJitRegCache c(m_gpr);
|
||||||
m_gpr.SaveRegs();
|
m_gpr.SaveRegs();
|
||||||
@ -138,7 +139,7 @@ void DSPEmitter::FallBackToInterpreter(UDSPInstruction inst)
|
|||||||
// of block.
|
// of block.
|
||||||
// Fallbacks to interpreter need this for fetching immediate values
|
// 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
|
// Fall back to interpreter
|
||||||
@ -250,18 +251,18 @@ void DSPEmitter::Compile(u16 start_addr)
|
|||||||
// by the analyzer.
|
// by the analyzer.
|
||||||
if (Analyzer::GetCodeFlags(static_cast<u16>(m_compile_pc - 1u)) & Analyzer::CODE_LOOP_END)
|
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));
|
TEST(32, R(EAX), R(EAX));
|
||||||
FixupBranch rLoopAddressExit = J_CC(CC_LE, true);
|
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));
|
TEST(32, R(EAX), R(EAX));
|
||||||
FixupBranch rLoopCounterExit = J_CC(CC_LE, true);
|
FixupBranch rLoopCounterExit = J_CC(CC_LE, true);
|
||||||
|
|
||||||
if (!opcode->branch)
|
if (!opcode->branch)
|
||||||
{
|
{
|
||||||
// branch insns update the g_dsp.pc
|
// 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
|
// 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)
|
else if (!opcode->jitFunc)
|
||||||
{
|
{
|
||||||
// look at g_dsp.pc if we actually branched
|
// 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));
|
CMP(16, R(AX), Imm16(m_compile_pc));
|
||||||
FixupBranch rNoBranch = J_CC(CC_Z, true);
|
FixupBranch rNoBranch = J_CC(CC_Z, true);
|
||||||
|
|
||||||
@ -328,7 +329,7 @@ void DSPEmitter::Compile(u16 start_addr)
|
|||||||
|
|
||||||
if (fixup_pc)
|
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;
|
m_blocks[start_addr] = (DSPCompiledCode)entryPoint;
|
||||||
@ -415,21 +416,23 @@ void DSPEmitter::CompileDispatcher()
|
|||||||
BitSet32 registers_used = ABI_ALL_CALLEE_SAVED & BitSet32(0xffff);
|
BitSet32 registers_used = ABI_ALL_CALLEE_SAVED & BitSet32(0xffff);
|
||||||
ABI_PushRegistersAndAdjustStack(registers_used, 8);
|
ABI_PushRegistersAndAdjustStack(registers_used, 8);
|
||||||
|
|
||||||
|
MOV(64, R(R15), ImmPtr(&g_dsp));
|
||||||
|
|
||||||
const u8* dispatcherLoop = GetCodePtr();
|
const u8* dispatcherLoop = GetCodePtr();
|
||||||
|
|
||||||
FixupBranch exceptionExit;
|
FixupBranch exceptionExit;
|
||||||
if (Host::OnThread())
|
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);
|
exceptionExit = J_CC(CC_NE);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check for DSP halt
|
// 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);
|
FixupBranch _halt = J_CC(CC_NE);
|
||||||
|
|
||||||
// Execute block. Cycles executed returned in EAX.
|
// 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()));
|
MOV(64, R(RBX), ImmPtr(m_blocks.data()));
|
||||||
JMPptr(MComplex(RBX, RCX, SCALE_8, 0));
|
JMPptr(MComplex(RBX, RCX, SCALE_8, 0));
|
||||||
|
|
||||||
@ -452,6 +455,36 @@ void DSPEmitter::CompileDispatcher()
|
|||||||
RET();
|
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 x86
|
||||||
} // namespace JIT
|
} // namespace JIT
|
||||||
} // namespace DSP
|
} // namespace DSP
|
||||||
|
@ -279,6 +279,14 @@ private:
|
|||||||
void dsp_op_read_reg(int reg, Gen::X64Reg host_dreg,
|
void dsp_op_read_reg(int reg, Gen::X64Reg host_dreg,
|
||||||
RegisterExtension extend = RegisterExtension::None);
|
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
|
// Ext command helpers
|
||||||
void popExtValueToReg();
|
void popExtValueToReg();
|
||||||
void pushExtValueFromMem(u16 dreg, u16 sreg);
|
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 the block is unconditional, attempt to link block
|
||||||
if (opcode->uncond_branch)
|
if (opcode->uncond_branch)
|
||||||
WriteBlockLink(dest);
|
WriteBlockLink(dest);
|
||||||
MOV(16, M(&g_dsp.pc), Imm16(dest));
|
MOV(16, M_SDSP_pc(), Imm16(dest));
|
||||||
WriteBranchExit();
|
WriteBranchExit();
|
||||||
}
|
}
|
||||||
// Generic jmp implementation
|
// 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
|
// NOTE: Cannot use FallBackToInterpreter(opc) here because of the need to write branch exit
|
||||||
void DSPEmitter::jcc(const UDSPInstruction opc)
|
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);
|
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,
|
// reg can only be DSP_REG_ARx and DSP_REG_IXx now,
|
||||||
// no need to handle DSP_REG_STx.
|
// no need to handle DSP_REG_STx.
|
||||||
dsp_op_read_reg(reg, RAX);
|
dsp_op_read_reg(reg, RAX);
|
||||||
MOV(16, M(&g_dsp.pc), R(EAX));
|
MOV(16, M_SDSP_pc(), R(EAX));
|
||||||
WriteBranchExit();
|
WriteBranchExit();
|
||||||
}
|
}
|
||||||
// Generic jmpr implementation
|
// 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
|
// NOTE: Cannot use FallBackToInterpreter(opc) here because of the need to write branch exit
|
||||||
void DSPEmitter::jmprcc(const UDSPInstruction opc)
|
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);
|
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 the block is unconditional, attempt to link block
|
||||||
if (opcode->uncond_branch)
|
if (opcode->uncond_branch)
|
||||||
WriteBlockLink(dest);
|
WriteBlockLink(dest);
|
||||||
MOV(16, M(&g_dsp.pc), Imm16(dest));
|
MOV(16, M_SDSP_pc(), Imm16(dest));
|
||||||
WriteBranchExit();
|
WriteBranchExit();
|
||||||
}
|
}
|
||||||
// Generic call implementation
|
// 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
|
// NOTE: Cannot use FallBackToInterpreter(opc) here because of the need to write branch exit
|
||||||
void DSPEmitter::call(const UDSPInstruction opc)
|
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);
|
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));
|
MOV(16, R(DX), Imm16(m_compile_pc + 1));
|
||||||
dsp_reg_store_stack(StackRegister::Call);
|
dsp_reg_store_stack(StackRegister::Call);
|
||||||
dsp_op_read_reg(reg, RAX);
|
dsp_op_read_reg(reg, RAX);
|
||||||
MOV(16, M(&g_dsp.pc), R(EAX));
|
MOV(16, M_SDSP_pc(), R(EAX));
|
||||||
WriteBranchExit();
|
WriteBranchExit();
|
||||||
}
|
}
|
||||||
// Generic callr implementation
|
// 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
|
// NOTE: Cannot use FallBackToInterpreter(opc) here because of the need to write branch exit
|
||||||
void DSPEmitter::callr(const UDSPInstruction opc)
|
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);
|
ReJitConditional(opc, &DSPEmitter::r_callr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DSPEmitter::r_ifcc(const UDSPInstruction opc)
|
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
|
// Generic if implementation
|
||||||
// IFcc
|
// IFcc
|
||||||
@ -235,7 +235,7 @@ void DSPEmitter::ifcc(const UDSPInstruction opc)
|
|||||||
const u16 address = m_compile_pc + 1;
|
const u16 address = m_compile_pc + 1;
|
||||||
const DSPOPCTemplate* const op_template = GetOpTemplate(dsp_imem_read(address));
|
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);
|
ReJitConditional(opc, &DSPEmitter::r_ifcc);
|
||||||
WriteBranchExit();
|
WriteBranchExit();
|
||||||
}
|
}
|
||||||
@ -243,7 +243,7 @@ void DSPEmitter::ifcc(const UDSPInstruction opc)
|
|||||||
void DSPEmitter::r_ret(const UDSPInstruction opc)
|
void DSPEmitter::r_ret(const UDSPInstruction opc)
|
||||||
{
|
{
|
||||||
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));
|
||||||
WriteBranchExit();
|
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
|
// NOTE: Cannot use FallBackToInterpreter(opc) here because of the need to write branch exit
|
||||||
void DSPEmitter::ret(const UDSPInstruction opc)
|
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);
|
ReJitConditional(opc, &DSPEmitter::r_ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -271,7 +271,7 @@ void DSPEmitter::rti(const UDSPInstruction opc)
|
|||||||
dsp_op_write_reg(DSP_REG_SR, RDX);
|
dsp_op_write_reg(DSP_REG_SR, RDX);
|
||||||
// g_dsp.pc = dsp_reg_load_stack(StackRegister::Call);
|
// g_dsp.pc = dsp_reg_load_stack(StackRegister::Call);
|
||||||
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
|
// 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.
|
// Stops execution of DSP code. Sets bit DSP_CR_HALT in register DREG_CR.
|
||||||
void DSPEmitter::halt(const UDSPInstruction opc)
|
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);
|
// g_dsp.pc = dsp_reg_load_stack(StackRegister::Call);
|
||||||
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
|
// 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.
|
// continues at next opcode.
|
||||||
void DSPEmitter::HandleLoop()
|
void DSPEmitter::HandleLoop()
|
||||||
{
|
{
|
||||||
MOVZX(32, 16, EAX, M(&g_dsp.r.st[2]));
|
MOVZX(32, 16, EAX, M_SDSP_r_st(2));
|
||||||
MOVZX(32, 16, ECX, M(&g_dsp.r.st[3]));
|
MOVZX(32, 16, ECX, M_SDSP_r_st(3));
|
||||||
|
|
||||||
TEST(32, R(RCX), R(RCX));
|
TEST(32, R(RCX), R(RCX));
|
||||||
FixupBranch rLoopCntG = J_CC(CC_LE, true);
|
FixupBranch rLoopCntG = J_CC(CC_LE, true);
|
||||||
CMP(16, R(RAX), Imm16(m_compile_pc - 1));
|
CMP(16, R(RAX), Imm16(m_compile_pc - 1));
|
||||||
FixupBranch rLoopAddrG = J_CC(CC_NE, true);
|
FixupBranch rLoopAddrG = J_CC(CC_NE, true);
|
||||||
|
|
||||||
SUB(16, M(&(g_dsp.r.st[3])), Imm16(1));
|
SUB(16, M_SDSP_r_st(3), Imm16(1));
|
||||||
CMP(16, M(&(g_dsp.r.st[3])), Imm16(0));
|
CMP(16, M_SDSP_r_st(3), Imm16(0));
|
||||||
|
|
||||||
FixupBranch loadStack = J_CC(CC_LE, true);
|
FixupBranch loadStack = J_CC(CC_LE, true);
|
||||||
MOVZX(32, 16, ECX, M(&(g_dsp.r.st[0])));
|
MOVZX(32, 16, ECX, M_SDSP_r_st(0));
|
||||||
MOV(16, M(&g_dsp.pc), R(RCX));
|
MOV(16, M_SDSP_pc(), R(RCX));
|
||||||
FixupBranch loopUpdated = J(true);
|
FixupBranch loopUpdated = J(true);
|
||||||
|
|
||||||
SetJumpTarget(loadStack);
|
SetJumpTarget(loadStack);
|
||||||
@ -346,12 +346,12 @@ void DSPEmitter::loop(const UDSPInstruction opc)
|
|||||||
MOV(16, R(RDX), Imm16(loop_pc));
|
MOV(16, R(RDX), Imm16(loop_pc));
|
||||||
dsp_reg_store_stack(StackRegister::LoopAddress);
|
dsp_reg_store_stack(StackRegister::LoopAddress);
|
||||||
m_gpr.FlushRegs(c);
|
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);
|
FixupBranch exit = J(true);
|
||||||
|
|
||||||
SetJumpTarget(cnt);
|
SetJumpTarget(cnt);
|
||||||
// dsp_skip_inst();
|
// 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();
|
WriteBranchExit();
|
||||||
m_gpr.FlushRegs(c, false);
|
m_gpr.FlushRegs(c, false);
|
||||||
SetJumpTarget(exit);
|
SetJumpTarget(exit);
|
||||||
@ -379,12 +379,12 @@ void DSPEmitter::loopi(const UDSPInstruction opc)
|
|||||||
MOV(16, R(RDX), Imm16(cnt));
|
MOV(16, R(RDX), Imm16(cnt));
|
||||||
dsp_reg_store_stack(StackRegister::LoopCounter);
|
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
|
else
|
||||||
{
|
{
|
||||||
// dsp_skip_inst();
|
// 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();
|
WriteBranchExit();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -414,14 +414,14 @@ void DSPEmitter::bloop(const UDSPInstruction opc)
|
|||||||
dsp_reg_store_stack(StackRegister::Call);
|
dsp_reg_store_stack(StackRegister::Call);
|
||||||
MOV(16, R(RDX), Imm16(loop_pc));
|
MOV(16, R(RDX), Imm16(loop_pc));
|
||||||
dsp_reg_store_stack(StackRegister::LoopAddress);
|
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);
|
m_gpr.FlushRegs(c, true);
|
||||||
FixupBranch exit = J(true);
|
FixupBranch exit = J(true);
|
||||||
|
|
||||||
SetJumpTarget(cnt);
|
SetJumpTarget(cnt);
|
||||||
// g_dsp.pc = loop_pc;
|
// g_dsp.pc = loop_pc;
|
||||||
// dsp_skip_inst();
|
// 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();
|
WriteBranchExit();
|
||||||
m_gpr.FlushRegs(c, false);
|
m_gpr.FlushRegs(c, false);
|
||||||
SetJumpTarget(exit);
|
SetJumpTarget(exit);
|
||||||
@ -451,13 +451,13 @@ void DSPEmitter::bloopi(const UDSPInstruction opc)
|
|||||||
MOV(16, R(RDX), Imm16(cnt));
|
MOV(16, R(RDX), Imm16(cnt));
|
||||||
dsp_reg_store_stack(StackRegister::LoopCounter);
|
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
|
else
|
||||||
{
|
{
|
||||||
// g_dsp.pc = loop_pc;
|
// g_dsp.pc = loop_pc;
|
||||||
// dsp_skip_inst();
|
// 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();
|
WriteBranchExit();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,8 @@
|
|||||||
|
|
||||||
// Multiplier and product register control
|
// Multiplier and product register control
|
||||||
|
|
||||||
|
#include <cstddef>
|
||||||
|
|
||||||
#include "Common/CommonTypes.h"
|
#include "Common/CommonTypes.h"
|
||||||
|
|
||||||
#include "Core/DSP/DSPCore.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).
|
// direct use of prod regs by AX/AXWII (look @that part of ucode).
|
||||||
void DSPEmitter::clrp(const UDSPInstruction opc)
|
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
|
// 64bit move to memory does not work. use 2 32bits
|
||||||
MOV(32, M(((u32*)&g_dsp.r.prod.val) + 0), Imm32(0xfff00000U));
|
MOV(32, MDisp(R15, offset + 0 * sizeof(u32)), Imm32(0xfff00000U));
|
||||||
MOV(32, M(((u32*)&g_dsp.r.prod.val) + 1), Imm32(0x001000ffU));
|
MOV(32, MDisp(R15, offset + 1 * sizeof(u32)), Imm32(0x001000ffU));
|
||||||
}
|
}
|
||||||
|
|
||||||
// TSTPROD
|
// TSTPROD
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
#include "Core/DSP/Jit/DSPJitRegCache.h"
|
#include "Core/DSP/Jit/DSPJitRegCache.h"
|
||||||
|
|
||||||
#include <cinttypes>
|
#include <cinttypes>
|
||||||
|
#include <cstddef>
|
||||||
|
|
||||||
#include "Common/Assert.h"
|
#include "Common/Assert.h"
|
||||||
#include "Common/Logging/Log.h"
|
#include "Common/Logging/Log.h"
|
||||||
@ -26,7 +27,7 @@ namespace x86
|
|||||||
constexpr std::array<X64Reg, 15> s_allocation_order = {
|
constexpr std::array<X64Reg, 15> s_allocation_order = {
|
||||||
{R8, R9, R10, R11, R12, R13, R14, R15, RSI, RDI, RBX, RCX, RDX, RAX, RBP}};
|
{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)
|
switch (reg)
|
||||||
{
|
{
|
||||||
@ -34,60 +35,60 @@ static void* GetRegisterPointer(size_t reg)
|
|||||||
case DSP_REG_AR1:
|
case DSP_REG_AR1:
|
||||||
case DSP_REG_AR2:
|
case DSP_REG_AR2:
|
||||||
case DSP_REG_AR3:
|
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_IX0:
|
||||||
case DSP_REG_IX1:
|
case DSP_REG_IX1:
|
||||||
case DSP_REG_IX2:
|
case DSP_REG_IX2:
|
||||||
case DSP_REG_IX3:
|
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_WR0:
|
||||||
case DSP_REG_WR1:
|
case DSP_REG_WR1:
|
||||||
case DSP_REG_WR2:
|
case DSP_REG_WR2:
|
||||||
case DSP_REG_WR3:
|
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_ST0:
|
||||||
case DSP_REG_ST1:
|
case DSP_REG_ST1:
|
||||||
case DSP_REG_ST2:
|
case DSP_REG_ST2:
|
||||||
case DSP_REG_ST3:
|
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_ACH0:
|
||||||
case DSP_REG_ACH1:
|
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:
|
case DSP_REG_CR:
|
||||||
return &g_dsp.r.cr;
|
return MDisp(R15, static_cast<int>(offsetof(SDSP, r.cr)));
|
||||||
case DSP_REG_SR:
|
case DSP_REG_SR:
|
||||||
return &g_dsp.r.sr;
|
return MDisp(R15, static_cast<int>(offsetof(SDSP, r.sr)));
|
||||||
case DSP_REG_PRODL:
|
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:
|
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:
|
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:
|
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_AXL0:
|
||||||
case DSP_REG_AXL1:
|
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_AXH0:
|
||||||
case DSP_REG_AXH1:
|
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_ACL0:
|
||||||
case DSP_REG_ACL1:
|
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_ACM0:
|
||||||
case DSP_REG_ACM1:
|
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_AX0_32:
|
||||||
case DSP_REG_AX1_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_ACC0_64:
|
||||||
case DSP_REG_ACC1_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:
|
case DSP_REG_PROD_64:
|
||||||
return &g_dsp.r.prod.val;
|
return MDisp(R15, static_cast<int>(offsetof(SDSP, r.prod.val)));
|
||||||
default:
|
default:
|
||||||
_assert_msg_(DSPLLE, 0, "cannot happen");
|
_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[R12].guest_reg = DSP_REG_NONE;
|
||||||
m_xregs[R13].guest_reg = DSP_REG_NONE;
|
m_xregs[R13].guest_reg = DSP_REG_NONE;
|
||||||
m_xregs[R14].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++)
|
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].parentReg = DSP_REG_NONE;
|
||||||
m_regs[i].shift = 0;
|
m_regs[i].shift = 0;
|
||||||
m_regs[i].host_reg = INVALID_REG;
|
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++)
|
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[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[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[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;
|
m_use_ctr = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static u64 ebp_store;
|
|
||||||
|
|
||||||
void DSPJitRegCache::LoadRegs(bool emit)
|
void DSPJitRegCache::LoadRegs(bool emit)
|
||||||
{
|
{
|
||||||
for (size_t i = 0; i < m_regs.size(); i++)
|
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);
|
MovToHostReg(i, m_regs[i].host_reg, emit);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (emit)
|
|
||||||
{
|
|
||||||
m_emitter.MOV(64, M(&ebp_store), R(RBP));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DSPJitRegCache::SaveRegs()
|
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);
|
_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()
|
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,
|
m_xregs[i].guest_reg == DSP_REG_NONE || m_xregs[i].guest_reg == DSP_REG_STATIC,
|
||||||
"register %zu is still used", i);
|
"register %zu is still used", i);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_emitter.MOV(64, R(RBP), M(&ebp_store));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DSPJitRegCache::PopRegs()
|
void DSPJitRegCache::PopRegs()
|
||||||
{
|
{
|
||||||
m_emitter.MOV(64, M(&ebp_store), R(RBP));
|
|
||||||
|
|
||||||
int push_count = 0;
|
int push_count = 0;
|
||||||
for (int i = static_cast<int>(m_xregs.size() - 1); i >= 0; i--)
|
for (int i = static_cast<int>(m_xregs.size() - 1); i >= 0; i--)
|
||||||
{
|
{
|
||||||
@ -492,22 +480,7 @@ void DSPJitRegCache::PopRegs()
|
|||||||
|
|
||||||
X64Reg DSPJitRegCache::MakeABICallSafe(X64Reg reg)
|
X64Reg DSPJitRegCache::MakeABICallSafe(X64Reg reg)
|
||||||
{
|
{
|
||||||
if (reg != RBP)
|
return reg;
|
||||||
{
|
|
||||||
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)
|
void DSPJitRegCache::MovToHostReg(size_t reg, X64Reg host_reg, bool load)
|
||||||
@ -654,7 +627,7 @@ void DSPJitRegCache::MovToMemory(size_t reg)
|
|||||||
_assert_msg_(DSPLLE, m_regs[reg].shift == 0, "still shifted??");
|
_assert_msg_(DSPLLE, m_regs[reg].shift == 0, "still shifted??");
|
||||||
|
|
||||||
// move to mem
|
// move to mem
|
||||||
OpArg tmp = M(m_regs[reg].mem);
|
OpArg tmp = m_regs[reg].mem;
|
||||||
|
|
||||||
if (m_regs[reg].dirty)
|
if (m_regs[reg].dirty)
|
||||||
{
|
{
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
|
|
||||||
#include "Common/x64Emitter.h"
|
#include "Common/x64Emitter.h"
|
||||||
|
|
||||||
namespace DSP
|
namespace DSP
|
||||||
@ -143,7 +144,7 @@ private:
|
|||||||
struct DynamicReg
|
struct DynamicReg
|
||||||
{
|
{
|
||||||
Gen::OpArg loc;
|
Gen::OpArg loc;
|
||||||
void* mem;
|
Gen::OpArg mem;
|
||||||
size_t size;
|
size_t size;
|
||||||
bool dirty;
|
bool dirty;
|
||||||
bool used;
|
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]++;
|
||||||
// g_dsp.reg_stack_ptr[reg_index] &= DSP_STACK_MASK;
|
// 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));
|
ADD(8, R(AL), Imm8(1));
|
||||||
AND(8, R(AL), Imm8(DSP_STACK_MASK));
|
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 tmp1 = m_gpr.GetFreeXReg();
|
||||||
X64Reg tmp2 = 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];
|
// 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));
|
MOVZX(64, 8, RAX, R(AL));
|
||||||
MOV(64, R(tmp2), ImmPtr(g_dsp.reg_stack[reg_index]));
|
MOV(64, R(tmp2), ImmPtr(g_dsp.reg_stack[reg_index]));
|
||||||
MOV(16, MComplex(tmp2, EAX, SCALE_2, 0), R(tmp1));
|
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);
|
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]];
|
// 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 tmp1 = m_gpr.GetFreeXReg();
|
||||||
X64Reg tmp2 = m_gpr.GetFreeXReg();
|
X64Reg tmp2 = m_gpr.GetFreeXReg();
|
||||||
MOVZX(64, 8, RAX, R(AL));
|
MOVZX(64, 8, RAX, R(AL));
|
||||||
MOV(64, R(tmp2), ImmPtr(g_dsp.reg_stack[reg_index]));
|
MOV(64, R(tmp2), ImmPtr(g_dsp.reg_stack[reg_index]));
|
||||||
MOV(16, R(tmp1), MComplex(tmp2, EAX, SCALE_2, 0));
|
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(tmp1);
|
||||||
m_gpr.PutXReg(tmp2);
|
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;
|
// g_dsp.reg_stack_ptr[reg_index] &= DSP_STACK_MASK;
|
||||||
SUB(8, R(AL), Imm8(1));
|
SUB(8, R(AL), Imm8(1));
|
||||||
AND(8, R(AL), Imm8(DSP_STACK_MASK));
|
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)
|
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);
|
dsp_reg_stack_push(stack_reg);
|
||||||
|
|
||||||
// g_dsp.r[DSP_REG_ST0 + stack_reg] = val;
|
// 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)
|
void DSPEmitter::dsp_reg_load_stack(StackRegister stack_reg, Gen::X64Reg host_dreg)
|
||||||
{
|
{
|
||||||
// u16 val = g_dsp.r[DSP_REG_ST0 + stack_reg];
|
// 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);
|
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);
|
dsp_reg_stack_push(stack_reg);
|
||||||
|
|
||||||
// g_dsp.r[DSP_REG_ST0 + stack_reg] = val;
|
// 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)
|
void DSPEmitter::dsp_op_write_reg(int reg, Gen::X64Reg host_sreg)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user