Core/Core/Src/DSP: Drop the indirect addressing hackery from DSP Jit
Was made possible by the move of Core/DSPCommon to Core/Core. This should not give a significant speed difference, but frees another register for register allocator use on x64 and generally simplifies the code. git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@7252 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
parent
565ab76e63
commit
8351177738
|
@ -81,20 +81,10 @@ void DSPEmitter::ClearIRAM() {
|
||||||
void DSPEmitter::checkExceptions(u32 retval)
|
void DSPEmitter::checkExceptions(u32 retval)
|
||||||
{
|
{
|
||||||
// Check for interrupts and exceptions
|
// Check for interrupts and exceptions
|
||||||
#ifdef _M_IX86 // All32
|
|
||||||
TEST(8, M(&g_dsp.exceptions), Imm8(0xff));
|
TEST(8, M(&g_dsp.exceptions), Imm8(0xff));
|
||||||
#else
|
FixupBranch skipCheck = J_CC(CC_Z, true);
|
||||||
MOV(64, R(RAX), ImmPtr(&g_dsp.exceptions));
|
|
||||||
TEST(8, MatR(RAX), Imm8(0xff));
|
|
||||||
#endif
|
|
||||||
FixupBranch skipCheck = J_CC(CC_Z);
|
|
||||||
|
|
||||||
#ifdef _M_IX86 // All32
|
|
||||||
MOV(16, M(&(g_dsp.pc)), Imm16(compilePC));
|
MOV(16, M(&(g_dsp.pc)), Imm16(compilePC));
|
||||||
#else
|
|
||||||
MOV(64, R(RAX), ImmPtr(&(g_dsp.pc)));
|
|
||||||
MOV(16, MatR(RAX), Imm16(compilePC));
|
|
||||||
#endif
|
|
||||||
|
|
||||||
DSPJitRegCache c(gpr);
|
DSPJitRegCache c(gpr);
|
||||||
SaveDSPRegs();
|
SaveDSPRegs();
|
||||||
|
@ -113,12 +103,7 @@ void DSPEmitter::Default(UDSPInstruction inst)
|
||||||
// Increment PC - we shouldn't need to do this for every instruction. only for branches and end of block.
|
// Increment PC - we shouldn't need to do this for every instruction. only for branches and end of block.
|
||||||
// Fallbacks to interpreter need this for fetching immediate values
|
// Fallbacks to interpreter need this for fetching immediate values
|
||||||
|
|
||||||
#ifdef _M_IX86 // All32
|
|
||||||
MOV(16, M(&(g_dsp.pc)), Imm16(compilePC + 1));
|
MOV(16, M(&(g_dsp.pc)), Imm16(compilePC + 1));
|
||||||
#else
|
|
||||||
MOV(64, R(RAX), ImmPtr(&(g_dsp.pc)));
|
|
||||||
MOV(16, MatR(RAX), Imm16(compilePC + 1));
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fall back to interpreter
|
// Fall back to interpreter
|
||||||
|
@ -237,32 +222,18 @@ void DSPEmitter::Compile(u16 start_addr)
|
||||||
// by the analyzer.
|
// by the analyzer.
|
||||||
if (DSPAnalyzer::code_flags[compilePC-1] & DSPAnalyzer::CODE_LOOP_END)
|
if (DSPAnalyzer::code_flags[compilePC-1] & DSPAnalyzer::CODE_LOOP_END)
|
||||||
{
|
{
|
||||||
#ifdef _M_IX86 // All32
|
|
||||||
MOVZX(32, 16, EAX, M(&(g_dsp.r.st[2])));
|
MOVZX(32, 16, EAX, M(&(g_dsp.r.st[2])));
|
||||||
#else
|
|
||||||
MOV(64, R(R11), ImmPtr(&g_dsp.r));
|
|
||||||
MOVZX(32, 16, EAX, MDisp(R11, STRUCT_OFFSET(g_dsp.r, st[2])));
|
|
||||||
#endif
|
|
||||||
CMP(32, R(EAX), Imm32(0));
|
CMP(32, R(EAX), Imm32(0));
|
||||||
FixupBranch rLoopAddressExit = J_CC(CC_LE, true);
|
FixupBranch rLoopAddressExit = J_CC(CC_LE, true);
|
||||||
|
|
||||||
#ifdef _M_IX86 // All32
|
|
||||||
MOVZX(32, 16, EAX, M(&g_dsp.r.st[3]));
|
MOVZX(32, 16, EAX, M(&g_dsp.r.st[3]));
|
||||||
#else
|
|
||||||
MOVZX(32, 16, EAX, MDisp(R11, STRUCT_OFFSET(g_dsp.r, st[3])));
|
|
||||||
#endif
|
|
||||||
CMP(32, R(EAX), Imm32(0));
|
CMP(32, R(EAX), Imm32(0));
|
||||||
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
|
||||||
#ifdef _M_IX86 // All32
|
|
||||||
MOV(16, M(&(g_dsp.pc)), Imm16(compilePC));
|
MOV(16, M(&(g_dsp.pc)), Imm16(compilePC));
|
||||||
#else
|
|
||||||
MOV(64, R(RAX), ImmPtr(&(g_dsp.pc)));
|
|
||||||
MOV(16, MatR(RAX), Imm16(compilePC));
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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,14 +267,9 @@ 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
|
||||||
#ifdef _M_IX86 // All32
|
|
||||||
MOV(16, R(AX), M(&g_dsp.pc));
|
MOV(16, R(AX), M(&g_dsp.pc));
|
||||||
#else
|
|
||||||
MOV(64, R(RAX), ImmPtr(&(g_dsp.pc)));
|
|
||||||
MOV(16, R(AX), MatR(RAX));
|
|
||||||
#endif
|
|
||||||
CMP(16, R(AX), Imm16(compilePC));
|
CMP(16, R(AX), Imm16(compilePC));
|
||||||
FixupBranch rNoBranch = J_CC(CC_Z);
|
FixupBranch rNoBranch = J_CC(CC_Z, true);
|
||||||
|
|
||||||
DSPJitRegCache c(gpr);
|
DSPJitRegCache c(gpr);
|
||||||
//don't update g_dsp.pc -- the branch insn already did
|
//don't update g_dsp.pc -- the branch insn already did
|
||||||
|
@ -331,12 +297,7 @@ void DSPEmitter::Compile(u16 start_addr)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fixup_pc) {
|
if (fixup_pc) {
|
||||||
#ifdef _M_IX86 // All32
|
|
||||||
MOV(16, M(&(g_dsp.pc)), Imm16(compilePC));
|
MOV(16, M(&(g_dsp.pc)), Imm16(compilePC));
|
||||||
#else
|
|
||||||
MOV(64, R(RAX), ImmPtr(&(g_dsp.pc)));
|
|
||||||
MOV(16, MatR(RAX), Imm16(compilePC));
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
blocks[start_addr] = (DSPCompiledCode)entryPoint;
|
blocks[start_addr] = (DSPCompiledCode)entryPoint;
|
||||||
|
@ -389,7 +350,6 @@ const u8 *DSPEmitter::CompileStub()
|
||||||
{
|
{
|
||||||
const u8 *entryPoint = AlignCode16();
|
const u8 *entryPoint = AlignCode16();
|
||||||
ABI_CallFunction((void *)&CompileCurrent);
|
ABI_CallFunction((void *)&CompileCurrent);
|
||||||
//MOVZX(32, 16, ECX, M(&g_dsp.pc));
|
|
||||||
XOR(32, R(EAX), R(EAX)); // Return 0 cycles executed
|
XOR(32, R(EAX), R(EAX)); // Return 0 cycles executed
|
||||||
JMP(returnDispatcher);
|
JMP(returnDispatcher);
|
||||||
return entryPoint;
|
return entryPoint;
|
||||||
|
@ -410,26 +370,17 @@ void DSPEmitter::CompileDispatcher()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check for DSP halt
|
// Check for DSP halt
|
||||||
#ifdef _M_IX86
|
|
||||||
TEST(8, M(&g_dsp.cr), Imm8(CR_HALT));
|
TEST(8, M(&g_dsp.cr), Imm8(CR_HALT));
|
||||||
#else
|
|
||||||
MOV(64, R(RAX), ImmPtr(&g_dsp.cr));
|
|
||||||
TEST(8, MatR(RAX), Imm8(CR_HALT));
|
|
||||||
#endif
|
|
||||||
FixupBranch _halt = J_CC(CC_NE);
|
FixupBranch _halt = J_CC(CC_NE);
|
||||||
|
|
||||||
#ifdef _M_IX86
|
|
||||||
MOVZX(32, 16, ECX, M(&g_dsp.pc));
|
|
||||||
#else
|
|
||||||
MOV(64, R(RCX), ImmPtr(&g_dsp.pc));
|
|
||||||
MOVZX(64, 16, RCX, MatR(RCX));
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Execute block. Cycles executed returned in EAX.
|
// Execute block. Cycles executed returned in EAX.
|
||||||
#ifdef _M_IX86
|
#ifdef _M_IX86
|
||||||
|
MOVZX(32, 16, ECX, M(&g_dsp.pc));
|
||||||
MOV(32, R(EBX), ImmPtr(blocks));
|
MOV(32, R(EBX), ImmPtr(blocks));
|
||||||
JMPptr(MComplex(EBX, ECX, SCALE_4, 0));
|
JMPptr(MComplex(EBX, ECX, SCALE_4, 0));
|
||||||
#else
|
#else
|
||||||
|
MOVZX(64, 16, ECX, M(&g_dsp.pc));//for clarity, use 64 here.
|
||||||
MOV(64, R(RBX), ImmPtr(blocks));
|
MOV(64, R(RBX), ImmPtr(blocks));
|
||||||
JMPptr(MComplex(RBX, RCX, SCALE_8, 0));
|
JMPptr(MComplex(RBX, RCX, SCALE_8, 0));
|
||||||
#endif
|
#endif
|
||||||
|
@ -437,15 +388,10 @@ void DSPEmitter::CompileDispatcher()
|
||||||
returnDispatcher = GetCodePtr();
|
returnDispatcher = GetCodePtr();
|
||||||
|
|
||||||
// Decrement cyclesLeft
|
// Decrement cyclesLeft
|
||||||
#ifdef _M_IX86
|
|
||||||
SUB(16, M(&cyclesLeft), R(EAX));
|
SUB(16, M(&cyclesLeft), R(EAX));
|
||||||
#else
|
|
||||||
MOV(64, R(R12), ImmPtr(&cyclesLeft));
|
|
||||||
SUB(16, MatR(R12), R(EAX));
|
|
||||||
#endif
|
|
||||||
|
|
||||||
J_CC(CC_A, dispatcherLoop);
|
J_CC(CC_A, dispatcherLoop);
|
||||||
|
|
||||||
// DSP gave up the remaining cycles.
|
// DSP gave up the remaining cycles.
|
||||||
SetJumpTarget(_halt);
|
SetJumpTarget(_halt);
|
||||||
if (DSPHost_OnThread())
|
if (DSPHost_OnThread())
|
||||||
|
|
|
@ -102,7 +102,6 @@ void DSPEmitter::andcf(const UDSPInstruction opc)
|
||||||
gpr.getReg(DSP_REG_SR,sr_reg);
|
gpr.getReg(DSP_REG_SR,sr_reg);
|
||||||
AND(16, R(RAX), Imm16(imm));
|
AND(16, R(RAX), Imm16(imm));
|
||||||
CMP(16, R(RAX), Imm16(imm));
|
CMP(16, R(RAX), Imm16(imm));
|
||||||
// MOV(64, R(R11), ImmPtr(&g_dsp.r));
|
|
||||||
FixupBranch notLogicZero = J_CC(CC_NE);
|
FixupBranch notLogicZero = J_CC(CC_NE);
|
||||||
OR(16, sr_reg, Imm16(SR_LOGIC_ZERO));
|
OR(16, sr_reg, Imm16(SR_LOGIC_ZERO));
|
||||||
FixupBranch exit = J();
|
FixupBranch exit = J();
|
||||||
|
@ -142,7 +141,6 @@ void DSPEmitter::andf(const UDSPInstruction opc)
|
||||||
OpArg sr_reg;
|
OpArg sr_reg;
|
||||||
gpr.getReg(DSP_REG_SR,sr_reg);
|
gpr.getReg(DSP_REG_SR,sr_reg);
|
||||||
TEST(16, R(RAX), Imm16(imm));
|
TEST(16, R(RAX), Imm16(imm));
|
||||||
// MOV(64, R(R11), ImmPtr(&g_dsp.r));
|
|
||||||
FixupBranch notLogicZero = J_CC(CC_NE);
|
FixupBranch notLogicZero = J_CC(CC_NE);
|
||||||
OR(16, sr_reg, Imm16(SR_LOGIC_ZERO));
|
OR(16, sr_reg, Imm16(SR_LOGIC_ZERO));
|
||||||
FixupBranch exit = J();
|
FixupBranch exit = J();
|
||||||
|
@ -613,7 +611,6 @@ void DSPEmitter::addr(const UDSPInstruction opc)
|
||||||
u8 dreg = (opc >> 8) & 0x1;
|
u8 dreg = (opc >> 8) & 0x1;
|
||||||
u8 sreg = ((opc >> 9) & 0x3) + DSP_REG_AXL0;
|
u8 sreg = ((opc >> 9) & 0x3) + DSP_REG_AXL0;
|
||||||
|
|
||||||
// MOV(64, R(R11), ImmPtr(&g_dsp.r));
|
|
||||||
// s64 acc = dsp_get_long_acc(dreg);
|
// s64 acc = dsp_get_long_acc(dreg);
|
||||||
get_long_acc(dreg, RCX);
|
get_long_acc(dreg, RCX);
|
||||||
MOV(64, R(RAX), R(RCX));
|
MOV(64, R(RAX), R(RCX));
|
||||||
|
@ -947,7 +944,6 @@ void DSPEmitter::subr(const UDSPInstruction opc)
|
||||||
get_long_acc(dreg, RCX);
|
get_long_acc(dreg, RCX);
|
||||||
MOV(64, R(RAX), R(RCX));
|
MOV(64, R(RAX), R(RCX));
|
||||||
// s64 ax = (s16)g_dsp.r[sreg];
|
// s64 ax = (s16)g_dsp.r[sreg];
|
||||||
// MOV(64, R(R11), ImmPtr(&g_dsp.r));
|
|
||||||
dsp_op_read_reg(sreg, RDX, SIGN);
|
dsp_op_read_reg(sreg, RDX, SIGN);
|
||||||
// ax <<= 16;
|
// ax <<= 16;
|
||||||
SHL(64, R(RDX), Imm8(16));
|
SHL(64, R(RDX), Imm8(16));
|
||||||
|
@ -1218,7 +1214,6 @@ void DSPEmitter::movr(const UDSPInstruction opc)
|
||||||
u8 sreg = ((opc >> 9) & 0x3) + DSP_REG_AXL0;
|
u8 sreg = ((opc >> 9) & 0x3) + DSP_REG_AXL0;
|
||||||
|
|
||||||
// s64 acc = (s16)g_dsp.r[sreg];
|
// s64 acc = (s16)g_dsp.r[sreg];
|
||||||
// MOV(64, R(R11), ImmPtr(&g_dsp.r));
|
|
||||||
dsp_op_read_reg(sreg, RAX, SIGN);
|
dsp_op_read_reg(sreg, RAX, SIGN);
|
||||||
// acc <<= 16;
|
// acc <<= 16;
|
||||||
SHL(64, R(RAX), Imm8(16));
|
SHL(64, R(RAX), Imm8(16));
|
||||||
|
|
|
@ -141,7 +141,6 @@ static void WriteBlockLink(DSPEmitter& emitter, u16 dest)
|
||||||
if (emitter.blockLinks[dest] != 0 )
|
if (emitter.blockLinks[dest] != 0 )
|
||||||
{
|
{
|
||||||
emitter.gpr.flushRegs();
|
emitter.gpr.flushRegs();
|
||||||
#ifdef _M_IX86 // All32
|
|
||||||
// Check if we have enough cycles to execute the next block
|
// Check if we have enough cycles to execute the next block
|
||||||
emitter.MOV(16, R(ESI), M(&cyclesLeft));
|
emitter.MOV(16, R(ESI), M(&cyclesLeft));
|
||||||
emitter.CMP(16, R(ESI), Imm16(emitter.blockSize[emitter.startAddr] + emitter.blockSize[dest]));
|
emitter.CMP(16, R(ESI), Imm16(emitter.blockSize[emitter.startAddr] + emitter.blockSize[dest]));
|
||||||
|
@ -149,14 +148,6 @@ static void WriteBlockLink(DSPEmitter& emitter, u16 dest)
|
||||||
|
|
||||||
emitter.SUB(16, R(ESI), Imm16(emitter.blockSize[emitter.startAddr]));
|
emitter.SUB(16, R(ESI), Imm16(emitter.blockSize[emitter.startAddr]));
|
||||||
emitter.MOV(16, M(&cyclesLeft), R(ESI));
|
emitter.MOV(16, M(&cyclesLeft), R(ESI));
|
||||||
#else
|
|
||||||
// Check if we have enough cycles to execute the next block
|
|
||||||
emitter.MOV(64, R(R12), ImmPtr(&cyclesLeft));
|
|
||||||
emitter.CMP(16, MatR(R12), Imm16(emitter.blockSize[emitter.startAddr] + emitter.blockSize[dest]));
|
|
||||||
FixupBranch notEnoughCycles = emitter.J_CC(CC_BE);
|
|
||||||
|
|
||||||
emitter.SUB(16, MatR(R12), Imm16(emitter.blockSize[emitter.startAddr]));
|
|
||||||
#endif
|
|
||||||
emitter.JMP(emitter.blockLinks[dest], true);
|
emitter.JMP(emitter.blockLinks[dest], true);
|
||||||
emitter.SetJumpTarget(notEnoughCycles);
|
emitter.SetJumpTarget(notEnoughCycles);
|
||||||
}
|
}
|
||||||
|
@ -177,12 +168,7 @@ void r_jcc(const UDSPInstruction opc, DSPEmitter& emitter)
|
||||||
// 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(emitter, dest);
|
WriteBlockLink(emitter, dest);
|
||||||
#ifdef _M_IX86 // All32
|
|
||||||
emitter.MOV(16, M(&(g_dsp.pc)), Imm16(dest));
|
emitter.MOV(16, M(&(g_dsp.pc)), Imm16(dest));
|
||||||
#else
|
|
||||||
emitter.MOV(64, R(RAX), ImmPtr(&(g_dsp.pc)));
|
|
||||||
emitter.MOV(16, MatR(RAX), Imm16(dest));
|
|
||||||
#endif
|
|
||||||
WriteBranchExit(emitter);
|
WriteBranchExit(emitter);
|
||||||
}
|
}
|
||||||
// Generic jmp implementation
|
// Generic jmp implementation
|
||||||
|
@ -194,12 +180,7 @@ void r_jcc(const UDSPInstruction opc, DSPEmitter& emitter)
|
||||||
// NOTE: Cannot use Default(opc) here because of the need to write branch exit
|
// NOTE: Cannot use Default(opc) here because of the need to write branch exit
|
||||||
void DSPEmitter::jcc(const UDSPInstruction opc)
|
void DSPEmitter::jcc(const UDSPInstruction opc)
|
||||||
{
|
{
|
||||||
#ifdef _M_IX86 // All32
|
|
||||||
MOV(16, M(&(g_dsp.pc)), Imm16(compilePC + 2));
|
MOV(16, M(&(g_dsp.pc)), Imm16(compilePC + 2));
|
||||||
#else
|
|
||||||
MOV(64, R(RAX), ImmPtr(&(g_dsp.pc)));
|
|
||||||
MOV(16, MatR(RAX), Imm16(compilePC + 2));
|
|
||||||
#endif
|
|
||||||
ReJitConditional<r_jcc>(opc, *this);
|
ReJitConditional<r_jcc>(opc, *this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -209,12 +190,7 @@ void r_jmprcc(const UDSPInstruction opc, DSPEmitter& emitter)
|
||||||
//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.
|
||||||
emitter.dsp_op_read_reg(reg, RAX, NONE);
|
emitter.dsp_op_read_reg(reg, RAX, NONE);
|
||||||
#ifdef _M_IX86 // All32
|
|
||||||
emitter.MOV(16, M(&g_dsp.pc), R(EAX));
|
emitter.MOV(16, M(&g_dsp.pc), R(EAX));
|
||||||
#else
|
|
||||||
emitter.MOV(64, R(RSI), ImmPtr(&(g_dsp.pc)));
|
|
||||||
emitter.MOV(16, MatR(RSI), R(RAX));
|
|
||||||
#endif
|
|
||||||
WriteBranchExit(emitter);
|
WriteBranchExit(emitter);
|
||||||
}
|
}
|
||||||
// Generic jmpr implementation
|
// Generic jmpr implementation
|
||||||
|
@ -224,12 +200,7 @@ void r_jmprcc(const UDSPInstruction opc, DSPEmitter& emitter)
|
||||||
// NOTE: Cannot use Default(opc) here because of the need to write branch exit
|
// NOTE: Cannot use Default(opc) here because of the need to write branch exit
|
||||||
void DSPEmitter::jmprcc(const UDSPInstruction opc)
|
void DSPEmitter::jmprcc(const UDSPInstruction opc)
|
||||||
{
|
{
|
||||||
#ifdef _M_IX86 // All32
|
|
||||||
MOV(16, M(&g_dsp.pc), Imm16(compilePC + 1));
|
MOV(16, M(&g_dsp.pc), Imm16(compilePC + 1));
|
||||||
#else
|
|
||||||
MOV(64, R(RAX), ImmPtr(&(g_dsp.pc)));
|
|
||||||
MOV(16, MatR(RAX), Imm16(compilePC + 1));
|
|
||||||
#endif
|
|
||||||
ReJitConditional<r_jmprcc>(opc, *this);
|
ReJitConditional<r_jmprcc>(opc, *this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -243,12 +214,7 @@ void r_call(const UDSPInstruction opc, DSPEmitter& emitter)
|
||||||
// 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(emitter, dest);
|
WriteBlockLink(emitter, dest);
|
||||||
#ifdef _M_IX86 // All32
|
|
||||||
emitter.MOV(16, M(&(g_dsp.pc)), Imm16(dest));
|
emitter.MOV(16, M(&(g_dsp.pc)), Imm16(dest));
|
||||||
#else
|
|
||||||
emitter.MOV(64, R(RAX), ImmPtr(&(g_dsp.pc)));
|
|
||||||
emitter.MOV(16, MatR(RAX), Imm16(dest));
|
|
||||||
#endif
|
|
||||||
WriteBranchExit(emitter);
|
WriteBranchExit(emitter);
|
||||||
}
|
}
|
||||||
// Generic call implementation
|
// Generic call implementation
|
||||||
|
@ -261,12 +227,7 @@ void r_call(const UDSPInstruction opc, DSPEmitter& emitter)
|
||||||
// NOTE: Cannot use Default(opc) here because of the need to write branch exit
|
// NOTE: Cannot use Default(opc) here because of the need to write branch exit
|
||||||
void DSPEmitter::call(const UDSPInstruction opc)
|
void DSPEmitter::call(const UDSPInstruction opc)
|
||||||
{
|
{
|
||||||
#ifdef _M_IX86 // All32
|
|
||||||
MOV(16, M(&(g_dsp.pc)), Imm16(compilePC + 2));
|
MOV(16, M(&(g_dsp.pc)), Imm16(compilePC + 2));
|
||||||
#else
|
|
||||||
MOV(64, R(RAX), ImmPtr(&(g_dsp.pc)));
|
|
||||||
MOV(16, MatR(RAX), Imm16(compilePC + 2));
|
|
||||||
#endif
|
|
||||||
ReJitConditional<r_call>(opc, *this);
|
ReJitConditional<r_call>(opc, *this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -276,12 +237,7 @@ void r_callr(const UDSPInstruction opc, DSPEmitter& emitter)
|
||||||
emitter.MOV(16, R(DX), Imm16(emitter.compilePC + 1));
|
emitter.MOV(16, R(DX), Imm16(emitter.compilePC + 1));
|
||||||
emitter.dsp_reg_store_stack(DSP_STACK_C);
|
emitter.dsp_reg_store_stack(DSP_STACK_C);
|
||||||
emitter.dsp_op_read_reg(reg, RAX, NONE);
|
emitter.dsp_op_read_reg(reg, RAX, NONE);
|
||||||
#ifdef _M_IX86 // All32
|
|
||||||
emitter.MOV(16, M(&g_dsp.pc), R(EAX));
|
emitter.MOV(16, M(&g_dsp.pc), R(EAX));
|
||||||
#else
|
|
||||||
emitter.MOV(64, R(RSI), ImmPtr(&(g_dsp.pc)));
|
|
||||||
emitter.MOV(16, MatR(RSI), R(RAX));
|
|
||||||
#endif
|
|
||||||
WriteBranchExit(emitter);
|
WriteBranchExit(emitter);
|
||||||
}
|
}
|
||||||
// Generic callr implementation
|
// Generic callr implementation
|
||||||
|
@ -293,23 +249,13 @@ void r_callr(const UDSPInstruction opc, DSPEmitter& emitter)
|
||||||
// NOTE: Cannot use Default(opc) here because of the need to write branch exit
|
// NOTE: Cannot use Default(opc) here because of the need to write branch exit
|
||||||
void DSPEmitter::callr(const UDSPInstruction opc)
|
void DSPEmitter::callr(const UDSPInstruction opc)
|
||||||
{
|
{
|
||||||
#ifdef _M_IX86 // All32
|
|
||||||
MOV(16, M(&g_dsp.pc), Imm16(compilePC + 1));
|
MOV(16, M(&g_dsp.pc), Imm16(compilePC + 1));
|
||||||
#else
|
|
||||||
MOV(64, R(RAX), ImmPtr(&(g_dsp.pc)));
|
|
||||||
MOV(16, MatR(RAX), Imm16(compilePC + 1));
|
|
||||||
#endif
|
|
||||||
ReJitConditional<r_callr>(opc, *this);
|
ReJitConditional<r_callr>(opc, *this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void r_ifcc(const UDSPInstruction opc, DSPEmitter& emitter)
|
void r_ifcc(const UDSPInstruction opc, DSPEmitter& emitter)
|
||||||
{
|
{
|
||||||
#ifdef _M_IX86 // All32
|
|
||||||
emitter.MOV(16, M(&g_dsp.pc), Imm16(emitter.compilePC + 1));
|
emitter.MOV(16, M(&g_dsp.pc), Imm16(emitter.compilePC + 1));
|
||||||
#else
|
|
||||||
emitter.MOV(64, R(RAX), ImmPtr(&(g_dsp.pc)));
|
|
||||||
emitter.MOV(16, MatR(RAX), Imm16(emitter.compilePC + 1));
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
// Generic if implementation
|
// Generic if implementation
|
||||||
// IFcc
|
// IFcc
|
||||||
|
@ -318,12 +264,7 @@ void r_ifcc(const UDSPInstruction opc, DSPEmitter& emitter)
|
||||||
// NOTE: Cannot use Default(opc) here because of the need to write branch exit
|
// NOTE: Cannot use Default(opc) here because of the need to write branch exit
|
||||||
void DSPEmitter::ifcc(const UDSPInstruction opc)
|
void DSPEmitter::ifcc(const UDSPInstruction opc)
|
||||||
{
|
{
|
||||||
#ifdef _M_IX86 // All32
|
|
||||||
MOV(16, M(&g_dsp.pc), Imm16((compilePC + 1) + opTable[compilePC + 1]->size));
|
MOV(16, M(&g_dsp.pc), Imm16((compilePC + 1) + opTable[compilePC + 1]->size));
|
||||||
#else
|
|
||||||
MOV(64, R(RAX), ImmPtr(&(g_dsp.pc)));
|
|
||||||
MOV(16, MatR(RAX), Imm16((compilePC + 1) + opTable[compilePC + 1]->size));
|
|
||||||
#endif
|
|
||||||
ReJitConditional<r_ifcc>(opc, *this);
|
ReJitConditional<r_ifcc>(opc, *this);
|
||||||
WriteBranchExit(*this);
|
WriteBranchExit(*this);
|
||||||
}
|
}
|
||||||
|
@ -331,12 +272,7 @@ void DSPEmitter::ifcc(const UDSPInstruction opc)
|
||||||
void r_ret(const UDSPInstruction opc, DSPEmitter& emitter)
|
void r_ret(const UDSPInstruction opc, DSPEmitter& emitter)
|
||||||
{
|
{
|
||||||
emitter.dsp_reg_load_stack(DSP_STACK_C);
|
emitter.dsp_reg_load_stack(DSP_STACK_C);
|
||||||
#ifdef _M_IX86 // All32
|
|
||||||
emitter.MOV(16, M(&g_dsp.pc), R(DX));
|
emitter.MOV(16, M(&g_dsp.pc), R(DX));
|
||||||
#else
|
|
||||||
emitter.MOV(64, R(RAX), ImmPtr(&(g_dsp.pc)));
|
|
||||||
emitter.MOV(16, MatR(RAX), R(DX));
|
|
||||||
#endif
|
|
||||||
WriteBranchExit(emitter);
|
WriteBranchExit(emitter);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -348,12 +284,7 @@ void r_ret(const UDSPInstruction opc, DSPEmitter& emitter)
|
||||||
// NOTE: Cannot use Default(opc) here because of the need to write branch exit
|
// NOTE: Cannot use Default(opc) here because of the need to write branch exit
|
||||||
void DSPEmitter::ret(const UDSPInstruction opc)
|
void DSPEmitter::ret(const UDSPInstruction opc)
|
||||||
{
|
{
|
||||||
#ifdef _M_IX86 // All32
|
|
||||||
MOV(16, M(&g_dsp.pc), Imm16(compilePC + 1));
|
MOV(16, M(&g_dsp.pc), Imm16(compilePC + 1));
|
||||||
#else
|
|
||||||
MOV(64, R(RAX), ImmPtr(&(g_dsp.pc)));
|
|
||||||
MOV(16, MatR(RAX), Imm16(compilePC + 1));
|
|
||||||
#endif
|
|
||||||
ReJitConditional<r_ret>(opc, *this);
|
ReJitConditional<r_ret>(opc, *this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -369,12 +300,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(DSP_STACK_C);
|
// g_dsp.pc = dsp_reg_load_stack(DSP_STACK_C);
|
||||||
dsp_reg_load_stack(DSP_STACK_C);
|
dsp_reg_load_stack(DSP_STACK_C);
|
||||||
#ifdef _M_IX86 // All32
|
|
||||||
MOV(16, M(&g_dsp.pc), R(DX));
|
MOV(16, M(&g_dsp.pc), R(DX));
|
||||||
#else
|
|
||||||
MOV(64, R(RAX), ImmPtr(&(g_dsp.pc)));
|
|
||||||
MOV(16, MatR(RAX), R(DX));
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// HALT
|
// HALT
|
||||||
|
@ -382,20 +308,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)
|
||||||
{
|
{
|
||||||
#ifdef _M_IX86 // All32
|
|
||||||
OR(16, M(&g_dsp.cr), Imm16(4));
|
OR(16, M(&g_dsp.cr), Imm16(4));
|
||||||
#else
|
|
||||||
MOV(64, R(RAX), ImmPtr(&g_dsp.cr));
|
|
||||||
OR(16, MatR(RAX), Imm16(4));
|
|
||||||
#endif
|
|
||||||
// g_dsp.pc = dsp_reg_load_stack(DSP_STACK_C);
|
// g_dsp.pc = dsp_reg_load_stack(DSP_STACK_C);
|
||||||
dsp_reg_load_stack(DSP_STACK_C);
|
dsp_reg_load_stack(DSP_STACK_C);
|
||||||
#ifdef _M_IX86 // All32
|
|
||||||
MOV(16, M(&g_dsp.pc), R(DX));
|
MOV(16, M(&g_dsp.pc), R(DX));
|
||||||
#else
|
|
||||||
MOV(64, R(RAX), ImmPtr(&(g_dsp.pc)));
|
|
||||||
MOV(16, MatR(RAX), R(DX));
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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
|
||||||
|
@ -406,37 +322,20 @@ void DSPEmitter::halt(const UDSPInstruction opc)
|
||||||
// continues at next opcode.
|
// continues at next opcode.
|
||||||
void DSPEmitter::HandleLoop()
|
void DSPEmitter::HandleLoop()
|
||||||
{
|
{
|
||||||
#ifdef _M_IX86 // All32
|
|
||||||
MOVZX(32, 16, EAX, M(&g_dsp.r.st[2]));
|
MOVZX(32, 16, EAX, M(&g_dsp.r.st[2]));
|
||||||
MOVZX(32, 16, ECX, M(&g_dsp.r.st[3]));
|
MOVZX(32, 16, ECX, M(&g_dsp.r.st[3]));
|
||||||
#else
|
|
||||||
// MOV(64, R(R11), ImmPtr(&g_dsp.r));
|
|
||||||
MOVZX(32, 16, EAX, MDisp(R11, STRUCT_OFFSET(g_dsp.r, st[2])));
|
|
||||||
MOVZX(32, 16, ECX, MDisp(R11, STRUCT_OFFSET(g_dsp.r, st[3])));
|
|
||||||
#endif
|
|
||||||
|
|
||||||
CMP(32, R(RCX), Imm32(0));
|
CMP(32, R(RCX), Imm32(0));
|
||||||
FixupBranch rLoopCntG = J_CC(CC_LE, true);
|
FixupBranch rLoopCntG = J_CC(CC_LE, true);
|
||||||
CMP(16, R(RAX), Imm16(compilePC - 1));
|
CMP(16, R(RAX), Imm16(compilePC - 1));
|
||||||
FixupBranch rLoopAddrG = J_CC(CC_NE, true);
|
FixupBranch rLoopAddrG = J_CC(CC_NE, true);
|
||||||
|
|
||||||
#ifdef _M_IX86 // All32
|
|
||||||
SUB(16, M(&(g_dsp.r.st[3])), Imm16(1));
|
SUB(16, M(&(g_dsp.r.st[3])), Imm16(1));
|
||||||
CMP(16, M(&(g_dsp.r.st[3])), Imm16(0));
|
CMP(16, M(&(g_dsp.r.st[3])), Imm16(0));
|
||||||
#else
|
|
||||||
SUB(16, MDisp(R11, STRUCT_OFFSET(g_dsp.r, st[3])), Imm16(1));
|
|
||||||
CMP(16, MDisp(R11, STRUCT_OFFSET(g_dsp.r, st[3])), Imm16(0));
|
|
||||||
#endif
|
|
||||||
|
|
||||||
FixupBranch loadStack = J_CC(CC_LE, true);
|
FixupBranch loadStack = J_CC(CC_LE, true);
|
||||||
#ifdef _M_IX86 // All32
|
|
||||||
MOVZX(32, 16, ECX, M(&(g_dsp.r.st[0])));
|
MOVZX(32, 16, ECX, M(&(g_dsp.r.st[0])));
|
||||||
MOV(16, M(&g_dsp.pc), R(RCX));
|
MOV(16, M(&g_dsp.pc), R(RCX));
|
||||||
#else
|
|
||||||
MOVZX(32, 16, RCX, MDisp(R11, STRUCT_OFFSET(g_dsp.r, st[0])));
|
|
||||||
MOV(64, R(RAX), ImmPtr(&(g_dsp.pc)));
|
|
||||||
MOV(16, MatR(RAX), R(RCX));
|
|
||||||
#endif
|
|
||||||
FixupBranch loopUpdated = J(true);
|
FixupBranch loopUpdated = J(true);
|
||||||
|
|
||||||
SetJumpTarget(loadStack);
|
SetJumpTarget(loadStack);
|
||||||
|
@ -447,7 +346,6 @@ void DSPEmitter::HandleLoop()
|
||||||
SetJumpTarget(loopUpdated);
|
SetJumpTarget(loopUpdated);
|
||||||
SetJumpTarget(rLoopAddrG);
|
SetJumpTarget(rLoopAddrG);
|
||||||
SetJumpTarget(rLoopCntG);
|
SetJumpTarget(rLoopCntG);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// LOOP $R
|
// LOOP $R
|
||||||
|
@ -474,12 +372,7 @@ void DSPEmitter::loop(const UDSPInstruction opc)
|
||||||
dsp_reg_store_stack(2);
|
dsp_reg_store_stack(2);
|
||||||
|
|
||||||
SetJumpTarget(cnt);
|
SetJumpTarget(cnt);
|
||||||
#ifdef _M_IX86 // All32
|
|
||||||
MOV(16, M(&(g_dsp.pc)), Imm16(compilePC + 1));
|
MOV(16, M(&(g_dsp.pc)), Imm16(compilePC + 1));
|
||||||
#else
|
|
||||||
MOV(64, R(RAX), ImmPtr(&(g_dsp.pc)));
|
|
||||||
MOV(16, MatR(RAX), Imm16(compilePC + 1));
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// LOOPI #I
|
// LOOPI #I
|
||||||
|
@ -504,12 +397,7 @@ void DSPEmitter::loopi(const UDSPInstruction opc)
|
||||||
MOV(16, R(RDX), Imm16(cnt));
|
MOV(16, R(RDX), Imm16(cnt));
|
||||||
dsp_reg_store_stack(3);
|
dsp_reg_store_stack(3);
|
||||||
|
|
||||||
#ifdef _M_IX86 // All32
|
|
||||||
MOV(16, M(&(g_dsp.pc)), Imm16(compilePC + 1));
|
MOV(16, M(&(g_dsp.pc)), Imm16(compilePC + 1));
|
||||||
#else
|
|
||||||
MOV(64, R(RAX), ImmPtr(&(g_dsp.pc)));
|
|
||||||
MOV(16, MatR(RAX), Imm16(compilePC + 1));
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -537,23 +425,13 @@ void DSPEmitter::bloop(const UDSPInstruction opc)
|
||||||
dsp_reg_store_stack(0);
|
dsp_reg_store_stack(0);
|
||||||
MOV(16, R(RDX), Imm16(loop_pc));
|
MOV(16, R(RDX), Imm16(loop_pc));
|
||||||
dsp_reg_store_stack(2);
|
dsp_reg_store_stack(2);
|
||||||
#ifdef _M_IX86 // All32
|
|
||||||
MOV(16, M(&(g_dsp.pc)), Imm16(compilePC + 2));
|
MOV(16, M(&(g_dsp.pc)), Imm16(compilePC + 2));
|
||||||
#else
|
FixupBranch exit = J(true);
|
||||||
MOV(64, R(RAX), ImmPtr(&(g_dsp.pc)));
|
|
||||||
MOV(16, MatR(RAX), Imm16(compilePC + 2));
|
|
||||||
#endif
|
|
||||||
FixupBranch exit = J();
|
|
||||||
|
|
||||||
SetJumpTarget(cnt);
|
SetJumpTarget(cnt);
|
||||||
// g_dsp.pc = loop_pc;
|
// g_dsp.pc = loop_pc;
|
||||||
// dsp_skip_inst();
|
// dsp_skip_inst();
|
||||||
#ifdef _M_IX86 // All32
|
|
||||||
MOV(16, M(&g_dsp.pc), Imm16(loop_pc + opTable[loop_pc]->size));
|
MOV(16, M(&g_dsp.pc), Imm16(loop_pc + opTable[loop_pc]->size));
|
||||||
#else
|
|
||||||
MOV(64, R(RAX), ImmPtr(&(g_dsp.pc)));
|
|
||||||
MOV(16, MatR(RAX), Imm16(loop_pc + opTable[loop_pc]->size));
|
|
||||||
#endif
|
|
||||||
DSPJitRegCache c(gpr);
|
DSPJitRegCache c(gpr);
|
||||||
WriteBranchExit(*this);
|
WriteBranchExit(*this);
|
||||||
gpr.flushRegs(c,false);
|
gpr.flushRegs(c,false);
|
||||||
|
@ -584,23 +462,13 @@ void DSPEmitter::bloopi(const UDSPInstruction opc)
|
||||||
MOV(16, R(RDX), Imm16(cnt));
|
MOV(16, R(RDX), Imm16(cnt));
|
||||||
dsp_reg_store_stack(3);
|
dsp_reg_store_stack(3);
|
||||||
|
|
||||||
#ifdef _M_IX86 // All32
|
|
||||||
MOV(16, M(&(g_dsp.pc)), Imm16(compilePC + 2));
|
MOV(16, M(&(g_dsp.pc)), Imm16(compilePC + 2));
|
||||||
#else
|
|
||||||
MOV(64, R(RAX), ImmPtr(&(g_dsp.pc)));
|
|
||||||
MOV(16, MatR(RAX), Imm16(compilePC + 2));
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// g_dsp.pc = loop_pc;
|
// g_dsp.pc = loop_pc;
|
||||||
// dsp_skip_inst();
|
// dsp_skip_inst();
|
||||||
#ifdef _M_IX86 // All32
|
|
||||||
MOV(16, M(&g_dsp.pc), Imm16(loop_pc + opTable[loop_pc]->size));
|
MOV(16, M(&g_dsp.pc), Imm16(loop_pc + opTable[loop_pc]->size));
|
||||||
#else
|
|
||||||
MOV(64, R(RAX), ImmPtr(&(g_dsp.pc)));
|
|
||||||
MOV(16, MatR(RAX), Imm16(loop_pc + opTable[loop_pc]->size));
|
|
||||||
#endif
|
|
||||||
WriteBranchExit(*this);
|
WriteBranchExit(*this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -117,12 +117,7 @@ void DSPEmitter::l(const UDSPInstruction opc)
|
||||||
//even if only for one bit, can only
|
//even if only for one bit, can only
|
||||||
//store (up to) two registers in EBX,
|
//store (up to) two registers in EBX,
|
||||||
//so store all of SR
|
//so store all of SR
|
||||||
#ifdef _M_IX86 // All32
|
|
||||||
MOV(16, R(EAX), M(&g_dsp.r.sr));
|
MOV(16, R(EAX), M(&g_dsp.r.sr));
|
||||||
#else
|
|
||||||
MOV(64, R(RAX), ImmPtr(&g_dsp.r.sr));
|
|
||||||
MOV(16, R(RAX), MatR(RAX));
|
|
||||||
#endif
|
|
||||||
SHL(32, R(EAX), Imm8(16));
|
SHL(32, R(EAX), Imm8(16));
|
||||||
OR(32, R(EBX), R(EAX));
|
OR(32, R(EBX), R(EAX));
|
||||||
}
|
}
|
||||||
|
@ -146,12 +141,7 @@ void DSPEmitter::ln(const UDSPInstruction opc)
|
||||||
//even if only for one bit, can only
|
//even if only for one bit, can only
|
||||||
//store (up to) two registers in EBX,
|
//store (up to) two registers in EBX,
|
||||||
//so store all of SR
|
//so store all of SR
|
||||||
#ifdef _M_IX86 // All32
|
|
||||||
MOV(16, R(EAX), M(&g_dsp.r.sr));
|
MOV(16, R(EAX), M(&g_dsp.r.sr));
|
||||||
#else
|
|
||||||
MOV(64, R(RAX), ImmPtr(&g_dsp.r.sr));
|
|
||||||
MOV(16, R(RAX), MatR(RAX));
|
|
||||||
#endif
|
|
||||||
SHL(32, R(EAX), Imm8(16));
|
SHL(32, R(EAX), Imm8(16));
|
||||||
OR(32, R(EBX), R(EAX));
|
OR(32, R(EBX), R(EAX));
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,78 +26,45 @@ using namespace Gen;
|
||||||
//clobbers:
|
//clobbers:
|
||||||
//EAX = (s8)g_dsp.reg_stack_ptr[stack_reg]
|
//EAX = (s8)g_dsp.reg_stack_ptr[stack_reg]
|
||||||
//CX = g_dsp.reg_stack[stack_reg][g_dsp.reg_stack_ptr[stack_reg]]
|
//CX = g_dsp.reg_stack[stack_reg][g_dsp.reg_stack_ptr[stack_reg]]
|
||||||
//expects:
|
|
||||||
//R11 = &g_dsp.r
|
|
||||||
void DSPEmitter::dsp_reg_stack_push(int stack_reg)
|
void DSPEmitter::dsp_reg_stack_push(int stack_reg)
|
||||||
{
|
{
|
||||||
//g_dsp.reg_stack_ptr[stack_reg]++;
|
//g_dsp.reg_stack_ptr[stack_reg]++;
|
||||||
//g_dsp.reg_stack_ptr[stack_reg] &= DSP_STACK_MASK;
|
//g_dsp.reg_stack_ptr[stack_reg] &= DSP_STACK_MASK;
|
||||||
#ifdef _M_IX86 // All32
|
|
||||||
MOV(8, R(AL), M(&g_dsp.reg_stack_ptr[stack_reg]));
|
MOV(8, R(AL), M(&g_dsp.reg_stack_ptr[stack_reg]));
|
||||||
#else
|
|
||||||
MOV(8, R(AL), MDisp(R11, PtrOffset(&g_dsp.reg_stack_ptr[stack_reg],
|
|
||||||
&g_dsp.r)));
|
|
||||||
#endif
|
|
||||||
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));
|
||||||
#ifdef _M_IX86 // All32
|
|
||||||
MOV(8, M(&g_dsp.reg_stack_ptr[stack_reg]), R(AL));
|
MOV(8, M(&g_dsp.reg_stack_ptr[stack_reg]), R(AL));
|
||||||
#else
|
|
||||||
MOV(8, MDisp(R11, PtrOffset(&g_dsp.reg_stack_ptr[stack_reg],
|
|
||||||
&g_dsp.r)), R(AL));
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//g_dsp.reg_stack[stack_reg][g_dsp.reg_stack_ptr[stack_reg]] = g_dsp.r[DSP_REG_ST0 + stack_reg];
|
//g_dsp.reg_stack[stack_reg][g_dsp.reg_stack_ptr[stack_reg]] = g_dsp.r[DSP_REG_ST0 + stack_reg];
|
||||||
#ifdef _M_IX86 // All32
|
|
||||||
MOV(16, R(CX), M(&g_dsp.r.st[stack_reg]));
|
MOV(16, R(CX), M(&g_dsp.r.st[stack_reg]));
|
||||||
|
#ifdef _M_IX86 // All32
|
||||||
MOVZX(32, 8, EAX, R(AL));
|
MOVZX(32, 8, EAX, R(AL));
|
||||||
MOV(16, MComplex(EAX, EAX, 1, (u32)&g_dsp.reg_stack[stack_reg][0]), R(CX));
|
|
||||||
#else
|
#else
|
||||||
// MOV(64, R(R11), ImmPtr(&g_dsp.r));
|
|
||||||
MOV(16, R(CX), MDisp(R11, STRUCT_OFFSET(g_dsp.r, st[stack_reg])));
|
|
||||||
MOVZX(64, 8, RAX, R(AL));
|
MOVZX(64, 8, RAX, R(AL));
|
||||||
MOV(16, MComplex(R11, RAX, 2,
|
|
||||||
PtrOffset(&g_dsp.reg_stack[stack_reg][0],&g_dsp.r)),
|
|
||||||
R(CX));
|
|
||||||
#endif
|
#endif
|
||||||
|
MOV(16, MComplex(EAX, EAX, 1, (u64)&g_dsp.reg_stack[stack_reg][0]), R(CX));
|
||||||
}
|
}
|
||||||
|
|
||||||
//clobbers:
|
//clobbers:
|
||||||
//EAX = (s8)g_dsp.reg_stack_ptr[stack_reg]
|
//EAX = (s8)g_dsp.reg_stack_ptr[stack_reg]
|
||||||
//CX = g_dsp.reg_stack[stack_reg][g_dsp.reg_stack_ptr[stack_reg]]
|
//CX = g_dsp.reg_stack[stack_reg][g_dsp.reg_stack_ptr[stack_reg]]
|
||||||
//expects:
|
|
||||||
//R11 = &g_dsp.r
|
|
||||||
void DSPEmitter::dsp_reg_stack_pop(int stack_reg)
|
void DSPEmitter::dsp_reg_stack_pop(int stack_reg)
|
||||||
{
|
{
|
||||||
//g_dsp.r[DSP_REG_ST0 + stack_reg] = g_dsp.reg_stack[stack_reg][g_dsp.reg_stack_ptr[stack_reg]];
|
//g_dsp.r[DSP_REG_ST0 + stack_reg] = g_dsp.reg_stack[stack_reg][g_dsp.reg_stack_ptr[stack_reg]];
|
||||||
#ifdef _M_IX86 // All32
|
|
||||||
MOV(8, R(AL), M(&g_dsp.reg_stack_ptr[stack_reg]));
|
MOV(8, R(AL), M(&g_dsp.reg_stack_ptr[stack_reg]));
|
||||||
#else
|
|
||||||
MOV(8, R(AL),
|
|
||||||
MDisp(R11, PtrOffset(&g_dsp.reg_stack_ptr[stack_reg],&g_dsp.r)));
|
|
||||||
#endif
|
|
||||||
#ifdef _M_IX86 // All32
|
#ifdef _M_IX86 // All32
|
||||||
MOVZX(32, 8, EAX, R(AL));
|
MOVZX(32, 8, EAX, R(AL));
|
||||||
MOV(16, R(CX), MComplex(EAX, EAX, 1, (u32)&g_dsp.reg_stack[stack_reg][0]));
|
|
||||||
MOV(16, M(&g_dsp.r.st[stack_reg]), R(CX));
|
|
||||||
#else
|
#else
|
||||||
MOVZX(64, 8, RAX, R(AL));
|
MOVZX(64, 8, RAX, R(AL));
|
||||||
MOV(16, R(CX), MComplex(R11, RAX, 2,
|
|
||||||
PtrOffset(&g_dsp.reg_stack[stack_reg][0],
|
|
||||||
&g_dsp.r)));
|
|
||||||
MOV(16, MDisp(R11, STRUCT_OFFSET(g_dsp.r, st[stack_reg])), R(CX));
|
|
||||||
#endif
|
#endif
|
||||||
|
MOV(16, R(CX), MComplex(EAX, EAX, 1, (u64)&g_dsp.reg_stack[stack_reg][0]));
|
||||||
|
MOV(16, M(&g_dsp.r.st[stack_reg]), R(CX));
|
||||||
|
|
||||||
//g_dsp.reg_stack_ptr[stack_reg]--;
|
//g_dsp.reg_stack_ptr[stack_reg]--;
|
||||||
//g_dsp.reg_stack_ptr[stack_reg] &= DSP_STACK_MASK;
|
//g_dsp.reg_stack_ptr[stack_reg] &= 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));
|
||||||
#ifdef _M_IX86 // All32
|
|
||||||
MOV(8, M(&g_dsp.reg_stack_ptr[stack_reg]), R(AL));
|
MOV(8, M(&g_dsp.reg_stack_ptr[stack_reg]), R(AL));
|
||||||
#else
|
|
||||||
MOV(8, MDisp(R11, PtrOffset(&g_dsp.reg_stack_ptr[stack_reg],&g_dsp.r)),
|
|
||||||
R(AL));
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -108,23 +75,13 @@ void DSPEmitter::dsp_reg_store_stack(int stack_reg, Gen::X64Reg host_sreg)
|
||||||
}
|
}
|
||||||
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;
|
||||||
#ifdef _M_IX86 // All32
|
|
||||||
MOV(16, M(&g_dsp.r.st[stack_reg]), R(EDX));
|
MOV(16, M(&g_dsp.r.st[stack_reg]), R(EDX));
|
||||||
#else
|
|
||||||
// MOV(64, R(R11), ImmPtr(&g_dsp.r));
|
|
||||||
MOV(16, MDisp(R11, STRUCT_OFFSET(g_dsp.r, st[stack_reg])), R(EDX));
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DSPEmitter::dsp_reg_load_stack(int stack_reg, Gen::X64Reg host_dreg)
|
void DSPEmitter::dsp_reg_load_stack(int 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];
|
||||||
#ifdef _M_IX86 // All32
|
|
||||||
MOV(16, R(EDX), M(&g_dsp.r.st[stack_reg]));
|
MOV(16, R(EDX), M(&g_dsp.r.st[stack_reg]));
|
||||||
#else
|
|
||||||
// MOV(64, R(R11), ImmPtr(&g_dsp.r));
|
|
||||||
MOV(16, R(EDX), MDisp(R11, STRUCT_OFFSET(g_dsp.r, st[stack_reg])));
|
|
||||||
#endif
|
|
||||||
dsp_reg_stack_pop(stack_reg);
|
dsp_reg_stack_pop(stack_reg);
|
||||||
if (host_dreg != EDX) {
|
if (host_dreg != EDX) {
|
||||||
MOV(16, R(host_dreg), R(EDX));
|
MOV(16, R(host_dreg), R(EDX));
|
||||||
|
@ -135,12 +92,7 @@ void DSPEmitter::dsp_reg_store_stack_imm(int 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;
|
||||||
#ifdef _M_IX86 // All32
|
|
||||||
MOV(16, M(&g_dsp.r.st[stack_reg]), Imm16(val));
|
MOV(16, M(&g_dsp.r.st[stack_reg]), Imm16(val));
|
||||||
#else
|
|
||||||
// MOV(64, R(R11), ImmPtr(&g_dsp.r));
|
|
||||||
MOV(16, MDisp(R11, STRUCT_OFFSET(g_dsp.r, st[stack_reg])), Imm16(val));
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DSPEmitter::dsp_op_write_reg(int reg, Gen::X64Reg host_sreg)
|
void DSPEmitter::dsp_op_write_reg(int reg, Gen::X64Reg host_sreg)
|
||||||
|
|
|
@ -168,8 +168,8 @@ void DSPEmitter::clrp(const UDSPInstruction opc)
|
||||||
// g_dsp.r[DSP_REG_PRODH] = 0x00ff;
|
// g_dsp.r[DSP_REG_PRODH] = 0x00ff;
|
||||||
// g_dsp.r[DSP_REG_PRODM2] = 0x0010;
|
// g_dsp.r[DSP_REG_PRODM2] = 0x0010;
|
||||||
//64bit move to memory does not work. use 2 32bits
|
//64bit move to memory does not work. use 2 32bits
|
||||||
MOV(32, MDisp(R11, STRUCT_OFFSET(g_dsp.r, prod.val)+0), Imm32(0xfff00000U));
|
MOV(32, M(&g_dsp.r.prod.val), Imm32(0xfff00000U));
|
||||||
MOV(32, MDisp(R11, STRUCT_OFFSET(g_dsp.r, prod.val)+4), Imm32(0x001000ffU));
|
MOV(32, M((u8*)(&g_dsp.r.prod.val)+4), Imm32(0x001000ffU));
|
||||||
#else
|
#else
|
||||||
Default(opc);
|
Default(opc);
|
||||||
#endif
|
#endif
|
||||||
|
@ -466,7 +466,6 @@ void DSPEmitter::mulx(const UDSPInstruction opc)
|
||||||
u8 treg = ((opc >> 11) & 0x1);
|
u8 treg = ((opc >> 11) & 0x1);
|
||||||
u8 sreg = ((opc >> 12) & 0x1);
|
u8 sreg = ((opc >> 12) & 0x1);
|
||||||
|
|
||||||
// MOV(64, R(R11), ImmPtr(&g_dsp.r));
|
|
||||||
// u16 val1 = (sreg == 0) ? dsp_get_ax_l(0) : dsp_get_ax_h(0);
|
// u16 val1 = (sreg == 0) ? dsp_get_ax_l(0) : dsp_get_ax_h(0);
|
||||||
dsp_op_read_reg(DSP_REG_AXL0 + sreg*2, RSI, SIGN);
|
dsp_op_read_reg(DSP_REG_AXL0 + sreg*2, RSI, SIGN);
|
||||||
// u16 val2 = (treg == 0) ? dsp_get_ax_l(1) : dsp_get_ax_h(1);
|
// u16 val2 = (treg == 0) ? dsp_get_ax_l(1) : dsp_get_ax_h(1);
|
||||||
|
@ -715,7 +714,6 @@ void DSPEmitter::mulcmvz(const UDSPInstruction opc)
|
||||||
u8 treg = (opc >> 11) & 0x1;
|
u8 treg = (opc >> 11) & 0x1;
|
||||||
u8 sreg = (opc >> 12) & 0x1;
|
u8 sreg = (opc >> 12) & 0x1;
|
||||||
|
|
||||||
// MOV(64, R(R11), ImmPtr(&g_dsp.r));
|
|
||||||
// s64 acc = dsp_get_long_prod_round_prodl();
|
// s64 acc = dsp_get_long_prod_round_prodl();
|
||||||
get_long_prod_round_prodl();
|
get_long_prod_round_prodl();
|
||||||
PUSH(64, R(RAX));
|
PUSH(64, R(RAX));
|
||||||
|
|
|
@ -126,11 +126,7 @@ DSPJitRegCache::DSPJitRegCache(DSPEmitter &_emitter)
|
||||||
regs[DSP_REG_AX1_32].size = 4;
|
regs[DSP_REG_AX1_32].size = 4;
|
||||||
for(unsigned int i = 0; i < DSP_REG_MAX_MEM_BACKED+1; i++) {
|
for(unsigned int i = 0; i < DSP_REG_MAX_MEM_BACKED+1; i++) {
|
||||||
regs[i].dirty = false;
|
regs[i].dirty = false;
|
||||||
#ifdef _M_IX86 // All32
|
|
||||||
regs[i].loc = M(regs[i].mem);
|
regs[i].loc = M(regs[i].mem);
|
||||||
#else
|
|
||||||
regs[i].loc = MDisp(R11, PtrOffset(regs[i].mem, &g_dsp.r));
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -218,10 +214,10 @@ void DSPJitRegCache::loadStaticRegs()
|
||||||
{
|
{
|
||||||
#ifdef _M_X64
|
#ifdef _M_X64
|
||||||
#ifdef ROTATED_REG_ACCS
|
#ifdef ROTATED_REG_ACCS
|
||||||
emitter.MOV(64, R(R8), MDisp(R11, STRUCT_OFFSET(g_dsp.r, ac[0].val)));
|
emitter.MOV(64, R(R8), M(&g_dsp.r.ac[0].val));
|
||||||
emitter.MOV(64, R(R9), MDisp(R11, STRUCT_OFFSET(g_dsp.r, ac[1].val)));
|
emitter.MOV(64, R(R9), M(&g_dsp.r.ac[1].val));
|
||||||
#endif
|
#endif
|
||||||
emitter.MOV(64, MDisp(R11, PtrOffset(&ebp_store, &g_dsp.r)), R(RBP));
|
emitter.MOV(64, M(&ebp_store), R(RBP));
|
||||||
#else
|
#else
|
||||||
emitter.MOV(32, M(&ebp_store), R(EBP));
|
emitter.MOV(32, M(&ebp_store), R(EBP));
|
||||||
#endif
|
#endif
|
||||||
|
@ -232,10 +228,10 @@ void DSPJitRegCache::saveStaticRegs()
|
||||||
flushRegs();
|
flushRegs();
|
||||||
#ifdef _M_X64
|
#ifdef _M_X64
|
||||||
#ifdef ROTATED_REG_ACCS
|
#ifdef ROTATED_REG_ACCS
|
||||||
emitter.MOV(64, MDisp(R11, STRUCT_OFFSET(g_dsp.r, ac[0].val)), R(R8));
|
emitter.MOV(64, M(&g_dsp.r.ac[0].val), R(R8));
|
||||||
emitter.MOV(64, MDisp(R11, STRUCT_OFFSET(g_dsp.r, ac[1].val)), R(R9));
|
emitter.MOV(64, M(&g_dsp.r.ac[1].val), R(R9));
|
||||||
#endif
|
#endif
|
||||||
emitter.MOV(64, R(RBP), MDisp(R11, PtrOffset(&ebp_store, &g_dsp.r)));
|
emitter.MOV(64, R(RBP), M(&ebp_store));
|
||||||
#else
|
#else
|
||||||
emitter.MOV(32, R(EBP), M(&ebp_store));
|
emitter.MOV(32, R(EBP), M(&ebp_store));
|
||||||
#endif
|
#endif
|
||||||
|
@ -327,11 +323,7 @@ void DSPJitRegCache::getReg(int reg, OpArg &oparg, bool load)
|
||||||
|
|
||||||
if (load) {
|
if (load) {
|
||||||
u16 *regp = reg_ptr(reg);
|
u16 *regp = reg_ptr(reg);
|
||||||
#ifdef _M_IX86 // All32
|
|
||||||
emitter.MOV(16, oparg, M(regp));
|
emitter.MOV(16, oparg, M(regp));
|
||||||
#else
|
|
||||||
emitter.MOV(16, oparg, MDisp(R11, PtrOffset(regp, &g_dsp.r)));
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
oparg = regs[reg].loc; //when loading/storing from/to mem, need to consider regs[reg].size
|
oparg = regs[reg].loc; //when loading/storing from/to mem, need to consider regs[reg].size
|
||||||
|
@ -390,7 +382,7 @@ void DSPJitRegCache::putReg(int reg, bool dirty)
|
||||||
//need to fix in memory for now.
|
//need to fix in memory for now.
|
||||||
u16 *regp = reg_ptr(reg);
|
u16 *regp = reg_ptr(reg);
|
||||||
OpArg mem;
|
OpArg mem;
|
||||||
mem = MDisp(R11,PtrOffset(regp,&g_dsp.r));
|
mem = M(regp);
|
||||||
X64Reg tmp;
|
X64Reg tmp;
|
||||||
getFreeXReg(tmp);
|
getFreeXReg(tmp);
|
||||||
// sign extend from the bottom 8 bits.
|
// sign extend from the bottom 8 bits.
|
||||||
|
@ -424,11 +416,7 @@ void DSPJitRegCache::putReg(int reg, bool dirty)
|
||||||
|
|
||||||
if(dirty) {
|
if(dirty) {
|
||||||
u16 *regp = reg_ptr(reg);
|
u16 *regp = reg_ptr(reg);
|
||||||
#ifdef _M_IX86 // All32
|
|
||||||
emitter.MOV(16, M(dregp), R(tmp));
|
emitter.MOV(16, M(dregp), R(tmp));
|
||||||
#else
|
|
||||||
emitter.MOV(16, MDisp(R11, PtrOffset(dregp, &g_dsp.r)), R(tmp));
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
|
|
|
@ -324,7 +324,6 @@ void DSPEmitter::imem_read()
|
||||||
// In: ECX - the address to read
|
// In: ECX - the address to read
|
||||||
// Out: EAX - the result of the read (used by caller)
|
// Out: EAX - the result of the read (used by caller)
|
||||||
// ESI - Base
|
// ESI - Base
|
||||||
// Trashes R11 on gdsp_ifx_read
|
|
||||||
void DSPEmitter::dmem_read()
|
void DSPEmitter::dmem_read()
|
||||||
{
|
{
|
||||||
// if (saddr == 0)
|
// if (saddr == 0)
|
||||||
|
@ -408,7 +407,6 @@ void DSPEmitter::dmem_read_imm(u16 address)
|
||||||
void DSPEmitter::get_long_prod(X64Reg long_prod)
|
void DSPEmitter::get_long_prod(X64Reg long_prod)
|
||||||
{
|
{
|
||||||
#ifdef _M_X64
|
#ifdef _M_X64
|
||||||
// MOV(64, R(R11), ImmPtr(&g_dsp.r));
|
|
||||||
//s64 val = (s8)(u8)g_dsp.r[DSP_REG_PRODH];
|
//s64 val = (s8)(u8)g_dsp.r[DSP_REG_PRODH];
|
||||||
OpArg reg;
|
OpArg reg;
|
||||||
gpr.getReg(DSP_REG_PROD_64, reg);
|
gpr.getReg(DSP_REG_PROD_64, reg);
|
||||||
|
@ -581,9 +579,6 @@ void DSPEmitter::get_ax_h(int _reg, X64Reg axh)
|
||||||
|
|
||||||
void DSPEmitter::LoadDSPRegs()
|
void DSPEmitter::LoadDSPRegs()
|
||||||
{
|
{
|
||||||
#ifdef _M_X64
|
|
||||||
MOV(64, R(R11), ImmPtr(&g_dsp.r));
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Load DSP register state here...
|
// Load DSP register state here...
|
||||||
gpr.loadStaticRegs();
|
gpr.loadStaticRegs();
|
||||||
|
|
Loading…
Reference in New Issue