Core/DSPCore: Consolidation of register accesses(except for the four hw
stacks), addition of a register cache(currently accumulators on 64bit only). It feels a bit slower, but the numbers are about the same. Caching accumulators doesn't change speed either. git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@6848 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
parent
c99f0d03a4
commit
fb1ebd8022
|
@ -195,16 +195,16 @@ inline u32 PtrOffset(void* ptr, void* base) {
|
|||
_assert_msg_(DYNA_REC, 0, "pointer offset out of range");
|
||||
return 0;
|
||||
}
|
||||
return distance;
|
||||
return (u32)distance;
|
||||
#else
|
||||
return (u32)ptr-(u32)base;
|
||||
#endif
|
||||
}
|
||||
|
||||
//usage: int a[]; ARRAY_OFFSET(a,10)
|
||||
#define ARRAY_OFFSET(array,index) ((u64)&(array)[index]-(u64)&(array)[0])
|
||||
#define ARRAY_OFFSET(array,index) ((u32)((u64)&(array)[index]-(u64)&(array)[0]))
|
||||
//usage: struct {int e;} s; STRUCT_OFFSET(s,e)
|
||||
#define STRUCT_OFFSET(str,elem) ((u64)&(str).elem-(u64)&(str))
|
||||
#define STRUCT_OFFSET(str,elem) ((u32)((u64)&(str).elem-(u64)&(str)))
|
||||
|
||||
struct FixupBranch
|
||||
{
|
||||
|
|
|
@ -18,6 +18,7 @@ set(SRCS Src/assemble.cpp
|
|||
Src/DSPInterpreter.cpp
|
||||
Src/DSPCore.cpp
|
||||
Src/DSPTables.cpp
|
||||
Src/Jit/DSPJitRegCache.cpp
|
||||
Src/Jit/DSPJitExtOps.cpp
|
||||
Src/Jit/DSPJitBranch.cpp
|
||||
Src/Jit/DSPJitCCUtil.cpp
|
||||
|
|
|
@ -486,6 +486,14 @@
|
|||
RelativePath=".\Src\Jit\DSPJitMultiplier.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Src\Jit\DSPJitRegCache.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Src\Jit\DSPJitRegCache.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Src\Jit\DSPJitUtil.cpp"
|
||||
>
|
||||
|
@ -493,7 +501,7 @@
|
|||
<File
|
||||
RelativePath=".\Src\Jit\DSPJitUtil.h"
|
||||
>
|
||||
</File>
|
||||
</File>
|
||||
</Filter>
|
||||
<File
|
||||
RelativePath=".\Src\assemble.cpp"
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include "DSPCore.h"
|
||||
#include "DSPInterpreter.h"
|
||||
#include "DSPAnalyzer.h"
|
||||
#include "Jit/DSPJitUtil.h"
|
||||
#include "x64Emitter.h"
|
||||
#include "ABI.h"
|
||||
|
||||
|
@ -30,15 +31,16 @@
|
|||
|
||||
using namespace Gen;
|
||||
|
||||
DSPEmitter::DSPEmitter() : storeIndex(-1), storeIndex2(-1)
|
||||
DSPEmitter::DSPEmitter() : gpr(*this), storeIndex(-1), storeIndex2(-1)
|
||||
{
|
||||
m_compiledCode = NULL;
|
||||
|
||||
AllocCodeSpace(COMPILED_CODE_SIZE);
|
||||
|
||||
blocks = new CompiledCode[MAX_BLOCKS];
|
||||
blockLinks = new CompiledCode[MAX_BLOCKS];
|
||||
blockSize = new u16[0x10000];
|
||||
blockLinks = new Block[MAX_BLOCKS];
|
||||
blockSize = new u16[MAX_BLOCKS];
|
||||
unresolvedJumps = new std::list<u16>[MAX_BLOCKS];
|
||||
|
||||
compileSR = 0;
|
||||
compileSR |= SR_INT_ENABLE;
|
||||
|
@ -93,6 +95,9 @@ void DSPEmitter::checkExceptions(u32 retval)
|
|||
MOV(16, MatR(RAX), Imm16(compilePC));
|
||||
#endif
|
||||
|
||||
DSPJitRegCache c(gpr);
|
||||
|
||||
SaveDSPRegs();
|
||||
ABI_CallFunction((void *)&DSPCore_CheckExceptions);
|
||||
|
||||
// ABI_RestoreStack(0);
|
||||
|
@ -100,6 +105,8 @@ void DSPEmitter::checkExceptions(u32 retval)
|
|||
MOV(32, R(EAX), Imm32(retval));
|
||||
RET();
|
||||
|
||||
gpr.flushRegs(c,false);
|
||||
|
||||
SetJumpTarget(skipCheck);
|
||||
}
|
||||
|
||||
|
@ -206,14 +213,14 @@ void DSPEmitter::Compile(u16 start_addr)
|
|||
return;
|
||||
*/
|
||||
|
||||
LoadDSPRegs();
|
||||
|
||||
blockLinkEntry = GetCodePtr();
|
||||
|
||||
compilePC = start_addr;
|
||||
bool fixup_pc = false;
|
||||
blockSize[start_addr] = 0;
|
||||
|
||||
LoadDSPRegs();
|
||||
|
||||
while (compilePC < start_addr + MAX_BLOCK_SIZE)
|
||||
{
|
||||
if (DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_CHECK_INT)
|
||||
|
@ -266,8 +273,9 @@ void DSPEmitter::Compile(u16 start_addr)
|
|||
|
||||
// These functions branch and therefore only need to be called in the
|
||||
// end of each block and in this order
|
||||
DSPJitRegCache c(gpr);
|
||||
HandleLoop();
|
||||
// ABI_RestoreStack(0);
|
||||
SaveDSPRegs();
|
||||
ABI_PopAllCalleeSavedRegsAndAdjustStack();
|
||||
if (DSPAnalyzer::code_flags[start_addr] & DSPAnalyzer::CODE_IDLE_SKIP)
|
||||
{
|
||||
|
@ -276,8 +284,9 @@ void DSPEmitter::Compile(u16 start_addr)
|
|||
else
|
||||
{
|
||||
MOV(16, R(EAX), Imm16(blockSize[start_addr]));
|
||||
}
|
||||
}
|
||||
RET();
|
||||
gpr.flushRegs(c,false);
|
||||
|
||||
SetJumpTarget(rLoopAddressExit);
|
||||
SetJumpTarget(rLoopCounterExit);
|
||||
|
@ -303,8 +312,9 @@ void DSPEmitter::Compile(u16 start_addr)
|
|||
CMP(16, R(AX), Imm16(compilePC));
|
||||
FixupBranch rNoBranch = J_CC(CC_Z);
|
||||
|
||||
DSPJitRegCache c(gpr);
|
||||
//don't update g_dsp.pc -- the branch insn already did
|
||||
// ABI_RestoreStack(0);
|
||||
SaveDSPRegs();
|
||||
ABI_PopAllCalleeSavedRegsAndAdjustStack();
|
||||
if (DSPAnalyzer::code_flags[start_addr] & DSPAnalyzer::CODE_IDLE_SKIP)
|
||||
{
|
||||
|
@ -313,8 +323,9 @@ void DSPEmitter::Compile(u16 start_addr)
|
|||
else
|
||||
{
|
||||
MOV(16, R(EAX), Imm16(blockSize[start_addr]));
|
||||
}
|
||||
}
|
||||
RET();
|
||||
gpr.flushRegs(c,false);
|
||||
|
||||
SetJumpTarget(rNoBranch);
|
||||
}
|
||||
|
@ -342,7 +353,7 @@ void DSPEmitter::Compile(u16 start_addr)
|
|||
// any unresolved CALL's
|
||||
if (unresolvedJumps[start_addr].empty())
|
||||
{
|
||||
blockLinks[start_addr] = (CompiledCode)blockLinkEntry;
|
||||
blockLinks[start_addr] = blockLinkEntry;
|
||||
|
||||
for(u16 i = 0x0000; i < 0xffff; ++i)
|
||||
{
|
||||
|
@ -372,7 +383,6 @@ void DSPEmitter::Compile(u16 start_addr)
|
|||
|
||||
SaveDSPRegs();
|
||||
|
||||
// ABI_RestoreStack(0);
|
||||
ABI_PopAllCalleeSavedRegsAndAdjustStack();
|
||||
if (DSPAnalyzer::code_flags[start_addr] & DSPAnalyzer::CODE_IDLE_SKIP)
|
||||
{
|
||||
|
@ -389,9 +399,7 @@ const u8 *DSPEmitter::CompileStub()
|
|||
{
|
||||
const u8 *entryPoint = AlignCode16();
|
||||
ABI_PushAllCalleeSavedRegsAndAdjustStack();
|
||||
// ABI_AlignStack(0);
|
||||
ABI_CallFunction((void *)&CompileCurrent);
|
||||
// ABI_RestoreStack(0);
|
||||
ABI_PopAllCalleeSavedRegsAndAdjustStack();
|
||||
//MOVZX(32, 16, ECX, M(&g_dsp.pc));
|
||||
XOR(32, R(EAX), R(EAX)); // Return 0 cycles executed
|
||||
|
|
|
@ -22,12 +22,14 @@
|
|||
|
||||
#include "DSPCommon.h"
|
||||
#include "x64Emitter.h"
|
||||
#include "Jit/DSPJitRegCache.h"
|
||||
|
||||
#define COMPILED_CODE_SIZE sizeof(void *) * 0x200000
|
||||
|
||||
#define MAX_BLOCKS 0x10000
|
||||
|
||||
typedef u32 (*CompiledCode)();
|
||||
typedef const u8 *Block;
|
||||
|
||||
class DSPEmitter : public Gen::XCodeBlock, NonCopyable
|
||||
{
|
||||
|
@ -35,14 +37,14 @@ public:
|
|||
DSPEmitter();
|
||||
~DSPEmitter();
|
||||
|
||||
const u8 *m_compiledCode;
|
||||
Block m_compiledCode;
|
||||
|
||||
void EmitInstruction(UDSPInstruction inst);
|
||||
void unknown_instruction(UDSPInstruction inst);
|
||||
void ClearIRAM();
|
||||
|
||||
void CompileDispatcher();
|
||||
const u8 *CompileStub();
|
||||
Block CompileStub();
|
||||
void Compile(u16 start_addr);
|
||||
void ClearCallFlag();
|
||||
|
||||
|
@ -113,7 +115,7 @@ public:
|
|||
void dsp_op_write_reg_imm(int reg, u16 val);
|
||||
void dsp_conditional_extend_accum(int reg);
|
||||
void dsp_conditional_extend_accum_imm(int reg, u16 val);
|
||||
void dsp_op_read_reg(int reg, Gen::X64Reg host_dreg);
|
||||
void dsp_op_read_reg(int reg, Gen::X64Reg host_dreg, DSPJitSignExtend extend = NONE);
|
||||
|
||||
// Commands
|
||||
void dar(const UDSPInstruction opc);
|
||||
|
@ -253,13 +255,18 @@ public:
|
|||
const u8 *stubEntryPoint;
|
||||
u16 compilePC;
|
||||
u16 startAddr;
|
||||
CompiledCode *blockLinks;
|
||||
Block *blockLinks;
|
||||
u16 *blockSize;
|
||||
std::list<u16> unresolvedJumps[0x10000];
|
||||
std::list<u16> *unresolvedJumps;
|
||||
|
||||
DSPJitRegCache gpr;
|
||||
|
||||
void LoadDSPRegs();
|
||||
void SaveDSPRegs();
|
||||
|
||||
private:
|
||||
CompiledCode *blocks;
|
||||
const u8 *blockLinkEntry;
|
||||
Block blockLinkEntry;
|
||||
u16 compileSR;
|
||||
|
||||
// The index of the last stored ext value (compile time).
|
||||
|
@ -269,8 +276,6 @@ private:
|
|||
// Counts down.
|
||||
// int cycles;
|
||||
|
||||
void LoadDSPRegs();
|
||||
void SaveDSPRegs();
|
||||
|
||||
void Update_SR_Register(Gen::X64Reg val = Gen::EAX);
|
||||
|
||||
|
@ -282,8 +287,12 @@ private:
|
|||
void set_long_prod();
|
||||
void round_long_acc(Gen::X64Reg long_acc = Gen::EAX);
|
||||
void set_long_acc(int _reg, Gen::X64Reg acc = Gen::EAX);
|
||||
void get_acc_m(int _reg, Gen::X64Reg acc = Gen::EAX);
|
||||
void set_acc_m(int _reg);
|
||||
void get_acc_h(int _reg, Gen::X64Reg acc = Gen::EAX, bool sign = true);
|
||||
void set_acc_h(int _reg, Gen::OpArg arg = R(Gen::EAX));
|
||||
void get_acc_m(int _reg, Gen::X64Reg acc = Gen::EAX, bool sign = true);
|
||||
void set_acc_m(int _reg, Gen::OpArg arg = R(Gen::EAX));
|
||||
void get_acc_l(int _reg, Gen::X64Reg acc = Gen::EAX, bool sign = true);
|
||||
void set_acc_l(int _reg, Gen::OpArg arg = R(Gen::EAX));
|
||||
void get_long_acx(int _reg, Gen::X64Reg acx = Gen::EAX);
|
||||
void get_ax_l(int _reg, Gen::X64Reg acx = Gen::EAX);
|
||||
void get_ax_h(int _reg, Gen::X64Reg acc = Gen::EAX);
|
||||
|
|
|
@ -98,15 +98,18 @@ void DSPEmitter::andcf(const UDSPInstruction opc)
|
|||
// g_dsp.r.sr |= SR_LOGIC_ZERO;
|
||||
// else
|
||||
// g_dsp.r.sr &= ~SR_LOGIC_ZERO;
|
||||
OpArg sr_reg;
|
||||
gpr.getReg(DSP_REG_SR,sr_reg);
|
||||
AND(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);
|
||||
OR(16, MDisp(R11, STRUCT_OFFSET(g_dsp.r, sr)), Imm16(SR_LOGIC_ZERO));
|
||||
OR(16, sr_reg, Imm16(SR_LOGIC_ZERO));
|
||||
FixupBranch exit = J();
|
||||
SetJumpTarget(notLogicZero);
|
||||
AND(16, MDisp(R11, STRUCT_OFFSET(g_dsp.r, sr)), Imm16(~SR_LOGIC_ZERO));
|
||||
AND(16, sr_reg, Imm16(~SR_LOGIC_ZERO));
|
||||
SetJumpTarget(exit);
|
||||
gpr.putReg(DSP_REG_SR);
|
||||
}
|
||||
#else
|
||||
Default(opc);
|
||||
|
@ -136,14 +139,17 @@ void DSPEmitter::andf(const UDSPInstruction opc)
|
|||
// g_dsp.r.sr |= SR_LOGIC_ZERO;
|
||||
// else
|
||||
// g_dsp.r.sr &= ~SR_LOGIC_ZERO;
|
||||
OpArg sr_reg;
|
||||
gpr.getReg(DSP_REG_SR,sr_reg);
|
||||
TEST(16, R(RAX), Imm16(imm));
|
||||
// MOV(64, R(R11), ImmPtr(&g_dsp.r));
|
||||
FixupBranch notLogicZero = J_CC(CC_NE);
|
||||
OR(16, MDisp(R11, STRUCT_OFFSET(g_dsp.r, sr)), Imm16(SR_LOGIC_ZERO));
|
||||
OR(16, sr_reg, Imm16(SR_LOGIC_ZERO));
|
||||
FixupBranch exit = J();
|
||||
SetJumpTarget(notLogicZero);
|
||||
AND(16, MDisp(R11, STRUCT_OFFSET(g_dsp.r, sr)), Imm16(~SR_LOGIC_ZERO));
|
||||
AND(16, sr_reg, Imm16(~SR_LOGIC_ZERO));
|
||||
SetJumpTarget(exit);
|
||||
gpr.putReg(DSP_REG_SR);
|
||||
}
|
||||
#else
|
||||
Default(opc);
|
||||
|
@ -606,14 +612,13 @@ void DSPEmitter::addr(const UDSPInstruction opc)
|
|||
#ifdef _M_X64
|
||||
u8 dreg = (opc >> 8) & 0x1;
|
||||
u8 sreg = ((opc >> 9) & 0x3) + DSP_REG_AXL0;
|
||||
u16 *sregp = reg_ptr(sreg);
|
||||
|
||||
// MOV(64, R(R11), ImmPtr(&g_dsp.r));
|
||||
// s64 acc = dsp_get_long_acc(dreg);
|
||||
get_long_acc(dreg, RCX);
|
||||
MOV(64, R(RAX), R(RCX));
|
||||
// s64 ax = (s16)g_dsp.r[sreg];
|
||||
MOVSX(64, 16, RDX, MDisp(R11, PtrOffset(sregp, &g_dsp.r)));
|
||||
dsp_op_read_reg(sreg, RDX, SIGN);
|
||||
// ax <<= 16;
|
||||
SHL(64, R(RDX), Imm8(16));
|
||||
// s64 res = acc + ax;
|
||||
|
@ -937,14 +942,13 @@ void DSPEmitter::subr(const UDSPInstruction opc)
|
|||
#ifdef _M_X64
|
||||
u8 dreg = (opc >> 8) & 0x1;
|
||||
u8 sreg = ((opc >> 9) & 0x3) + DSP_REG_AXL0;
|
||||
u16 *sregp = reg_ptr(sreg);
|
||||
|
||||
// s64 acc = dsp_get_long_acc(dreg);
|
||||
get_long_acc(dreg, RCX);
|
||||
MOV(64, R(RAX), R(RCX));
|
||||
// s64 ax = (s16)g_dsp.r[sreg];
|
||||
// MOV(64, R(R11), ImmPtr(&g_dsp.r));
|
||||
MOVSX(64, 16, RDX, MDisp(R11, PtrOffset(sregp, &g_dsp.r)));
|
||||
dsp_op_read_reg(sreg, RDX, SIGN);
|
||||
// ax <<= 16;
|
||||
SHL(64, R(RDX), Imm8(16));
|
||||
// s64 res = acc - ax;
|
||||
|
@ -1212,11 +1216,10 @@ void DSPEmitter::movr(const UDSPInstruction opc)
|
|||
#ifdef _M_X64
|
||||
u8 areg = (opc >> 8) & 0x1;
|
||||
u8 sreg = ((opc >> 9) & 0x3) + DSP_REG_AXL0;
|
||||
u16 *sregp = reg_ptr(sreg);
|
||||
|
||||
// s64 acc = (s16)g_dsp.r[sreg];
|
||||
// MOV(64, R(R11), ImmPtr(&g_dsp.r));
|
||||
MOVSX(64, 16, RAX, MDisp(R11, PtrOffset(sregp, &g_dsp.r)));
|
||||
dsp_op_read_reg(sreg, RAX, SIGN);
|
||||
// acc <<= 16;
|
||||
SHL(64, R(RAX), Imm8(16));
|
||||
// acc &= ~0xffff;
|
||||
|
|
|
@ -25,30 +25,17 @@
|
|||
|
||||
using namespace Gen;
|
||||
|
||||
const int GetCodeSize(void(*jitCode)(const UDSPInstruction, DSPEmitter&), const UDSPInstruction opc, DSPEmitter &emitter)
|
||||
template <void(*jitCode)(const UDSPInstruction, DSPEmitter&)>
|
||||
static void ReJitConditional(const UDSPInstruction opc, DSPEmitter& emitter)
|
||||
{
|
||||
u16 pc = g_dsp.pc;
|
||||
const u8* ptr = emitter.GetCodePtr();
|
||||
jitCode(opc, emitter);
|
||||
//emitter.JMP(emitter.GetCodePtr());
|
||||
int size = (int)(emitter.GetCodePtr() - ptr);
|
||||
emitter.SetCodePtr((u8*)ptr);
|
||||
g_dsp.pc = pc;
|
||||
return size;
|
||||
}
|
||||
|
||||
const u8* CheckCondition(DSPEmitter& emitter, u8 cond, u8 skipCodeSize)
|
||||
{
|
||||
if (cond == 0xf) // Always true.
|
||||
return NULL;
|
||||
//emitter.INT3();
|
||||
u8 cond = opc & 0xf;
|
||||
if (cond == 0xf) {// Always true.
|
||||
jitCode(opc,emitter);
|
||||
return;
|
||||
}
|
||||
FixupBranch skipCode2;
|
||||
#ifdef _M_IX86 // All32
|
||||
emitter.MOV(16, R(EAX), M(&g_dsp.r.sr));
|
||||
#else
|
||||
emitter.MOV(64, R(RAX), ImmPtr(&g_dsp.r.sr));
|
||||
emitter.MOV(16, R(EAX), MatR(RAX));
|
||||
#endif
|
||||
emitter.dsp_op_read_reg(DSP_REG_SR, RAX);
|
||||
DSPJitRegCache c2(emitter.gpr);
|
||||
switch(cond)
|
||||
{
|
||||
case 0x0: // GE - Greater Equal
|
||||
|
@ -61,19 +48,17 @@ const u8* CheckCondition(DSPEmitter& emitter, u8 cond, u8 skipCodeSize)
|
|||
emitter.SHR(16, R(EAX), Imm8(1)); //SR_OVERFLOW flag
|
||||
emitter.NOT(16, R(EAX));
|
||||
emitter.XOR(16, R(EAX), R(EDX));
|
||||
emitter.TEST(16, R(EAX), Imm16(1));
|
||||
if (cond < 0x2)
|
||||
if (cond < 0x2) {
|
||||
emitter.TEST(16, R(EAX), Imm16(1));
|
||||
break;
|
||||
|
||||
}
|
||||
c2 = emitter.gpr;
|
||||
emitter.TEST(16, R(EAX), Imm16(1));
|
||||
|
||||
//LE: problem in here, half the tests fail
|
||||
skipCode2 = emitter.J_CC(CC_NE);
|
||||
//skipCode2 = emitter.J_CC((CCFlags)(CC_NE - (cond & 1)));
|
||||
#ifdef _M_IX86 // All32
|
||||
emitter.MOV(16, R(EAX), M(&g_dsp.r.sr));
|
||||
#else
|
||||
emitter.MOV(64, R(RAX), ImmPtr(&g_dsp.r.sr));
|
||||
emitter.MOV(16, R(EAX), MatR(RAX));
|
||||
#endif
|
||||
emitter.dsp_op_read_reg(DSP_REG_SR, RAX);
|
||||
emitter.TEST(16, R(EAX), Imm16(SR_ARITH_ZERO));
|
||||
break;
|
||||
case 0x4: // NZ - Not Zero
|
||||
|
@ -107,6 +92,7 @@ const u8* CheckCondition(DSPEmitter& emitter, u8 cond, u8 skipCodeSize)
|
|||
emitter.SETcc(CC_E, R(EAX));
|
||||
emitter.TEST(8, R(EAX), R(EAX));
|
||||
break;
|
||||
//c2 = emitter.gpr;
|
||||
//emitter.TEST(16, R(EAX), Imm16(SR_OVER_S32 | SR_TOP2BITS));
|
||||
//skipCode2 = emitter.J_CC((CCFlags)(CC_E + (cond & 1)));
|
||||
//emitter.TEST(16, R(EAX), Imm16(SR_ARITH_ZERO));
|
||||
|
@ -120,36 +106,22 @@ const u8* CheckCondition(DSPEmitter& emitter, u8 cond, u8 skipCodeSize)
|
|||
emitter.TEST(16, R(EAX), Imm16(SR_OVERFLOW));
|
||||
break;
|
||||
}
|
||||
DSPJitRegCache c1(emitter.gpr);
|
||||
FixupBranch skipCode = cond == 0xe ? emitter.J_CC(CC_E) : emitter.J_CC((CCFlags)(CC_NE - (cond & 1)));
|
||||
const u8* res = emitter.GetCodePtr();
|
||||
emitter.NOP(skipCodeSize);
|
||||
jitCode(opc,emitter);
|
||||
emitter.gpr.flushRegs(c1);
|
||||
emitter.SetJumpTarget(skipCode);
|
||||
if ((cond | 1) == 0x3) // || (cond | 1) == 0xb)
|
||||
if ((cond | 1) == 0x3) {// || (cond | 1) == 0xb)
|
||||
emitter.gpr.flushRegs(c2);
|
||||
emitter.SetJumpTarget(skipCode2);
|
||||
return res;
|
||||
} else {
|
||||
c2.drop();
|
||||
}
|
||||
}
|
||||
|
||||
template <void(*jitCode)(const UDSPInstruction, DSPEmitter&)>
|
||||
void ReJitConditional(const UDSPInstruction opc, DSPEmitter& emitter)
|
||||
static void WriteBranchExit(DSPEmitter& emitter)
|
||||
{
|
||||
static const int codeSize = GetCodeSize(jitCode, opc, emitter);
|
||||
//emitter.INT3();
|
||||
const u8* codePtr = CheckCondition(emitter, opc & 0xf, codeSize);
|
||||
//const u8* afterSkip = emitter.GetCodePtr();
|
||||
if (codePtr != NULL)
|
||||
emitter.SetCodePtr((u8*)codePtr);
|
||||
jitCode(opc, emitter);
|
||||
//if (codePtr != NULL)
|
||||
//{
|
||||
// emitter.JMP(afterSkip + 4 + sizeof(void*));
|
||||
// emitter.SetCodePtr((u8*)afterSkip);
|
||||
// emitter.ADD(16, M(&g_dsp.pc), Imm8(1)); //4 bytes + pointer
|
||||
//}
|
||||
}
|
||||
|
||||
void WriteBranchExit(DSPEmitter& emitter)
|
||||
{
|
||||
// ABI_RestoreStack(0);
|
||||
emitter.SaveDSPRegs();
|
||||
emitter.ABI_PopAllCalleeSavedRegsAndAdjustStack();
|
||||
if (DSPAnalyzer::code_flags[emitter.startAddr] & DSPAnalyzer::CODE_IDLE_SKIP)
|
||||
{
|
||||
|
@ -162,13 +134,14 @@ void WriteBranchExit(DSPEmitter& emitter)
|
|||
emitter.RET();
|
||||
}
|
||||
|
||||
void WriteBlockLink(DSPEmitter& emitter, u16 dest)
|
||||
static void WriteBlockLink(DSPEmitter& emitter, u16 dest)
|
||||
{
|
||||
// Jump directly to the called block if it has already been compiled.
|
||||
if (!(dest >= emitter.startAddr && dest <= emitter.compilePC))
|
||||
{
|
||||
if (emitter.blockLinks[dest] != 0 )
|
||||
{
|
||||
emitter.gpr.flushRegs();
|
||||
#ifdef _M_IX86 // All32
|
||||
// Check if we have enough cycles to execute the next block
|
||||
emitter.MOV(16, R(ESI), M(&cyclesLeft));
|
||||
|
@ -177,20 +150,15 @@ void WriteBlockLink(DSPEmitter& emitter, u16 dest)
|
|||
|
||||
emitter.SUB(16, R(ESI), Imm16(emitter.blockSize[emitter.startAddr]));
|
||||
emitter.MOV(16, M(&cyclesLeft), R(ESI));
|
||||
emitter.JMPptr(M(&emitter.blockLinks[dest]));
|
||||
|
||||
emitter.SetJumpTarget(notEnoughCycles);
|
||||
#else
|
||||
// Check if we have enough cycles to execute the next block
|
||||
emitter.CMP(16, R(R12), Imm16(emitter.blockSize[emitter.startAddr] + emitter.blockSize[dest]));
|
||||
FixupBranch notEnoughCycles = emitter.J_CC(CC_BE);
|
||||
|
||||
emitter.SUB(16, R(R12), Imm16(emitter.blockSize[emitter.startAddr]));
|
||||
emitter.MOV(64, R(RAX), ImmPtr((void *)emitter.blockLinks[dest]));
|
||||
emitter.JMPptr(R(RAX));
|
||||
|
||||
emitter.SetJumpTarget(notEnoughCycles);
|
||||
#endif
|
||||
emitter.JMP(emitter.blockLinks[dest], true);
|
||||
emitter.SetJumpTarget(notEnoughCycles);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -238,17 +206,14 @@ void DSPEmitter::jcc(const UDSPInstruction opc)
|
|||
void r_jmprcc(const UDSPInstruction opc, DSPEmitter& emitter)
|
||||
{
|
||||
u8 reg = (opc >> 5) & 0x7;
|
||||
u16 *regp = reg_ptr(reg);
|
||||
//reg can only be DSP_REG_ARx and DSP_REG_IXx now,
|
||||
//no need to handle DSP_REG_STx.
|
||||
emitter.dsp_op_read_reg(reg, RAX, NONE);
|
||||
#ifdef _M_IX86 // All32
|
||||
emitter.MOV(16, R(EAX), M(regp));
|
||||
emitter.MOV(16, M(&g_dsp.pc), R(EAX));
|
||||
#else
|
||||
emitter.MOV(64, R(RSI), ImmPtr(regp));
|
||||
emitter.MOV(16, R(RSI), MatR(RSI));
|
||||
emitter.MOV(64, R(RAX), ImmPtr(&(g_dsp.pc)));
|
||||
emitter.MOV(16, MatR(RAX), R(RSI));
|
||||
emitter.MOV(64, R(RSI), ImmPtr(&(g_dsp.pc)));
|
||||
emitter.MOV(16, MatR(RSI), R(RAX));
|
||||
#endif
|
||||
WriteBranchExit(emitter);
|
||||
}
|
||||
|
@ -308,17 +273,14 @@ void DSPEmitter::call(const UDSPInstruction opc)
|
|||
void r_callr(const UDSPInstruction opc, DSPEmitter& emitter)
|
||||
{
|
||||
u8 reg = (opc >> 5) & 0x7;
|
||||
u16 *regp = reg_ptr(reg);
|
||||
emitter.MOV(16, R(DX), Imm16(emitter.compilePC + 1));
|
||||
emitter.dsp_reg_store_stack(DSP_STACK_C);
|
||||
emitter.dsp_op_read_reg(reg, RAX, NONE);
|
||||
#ifdef _M_IX86 // All32
|
||||
emitter.MOV(16, R(EAX), M(regp));
|
||||
emitter.MOV(16, M(&g_dsp.pc), R(EAX));
|
||||
#else
|
||||
emitter.MOV(64, R(RSI), ImmPtr(regp));
|
||||
emitter.MOV(16, R(RSI), MatR(RSI));
|
||||
emitter.MOV(64, R(RAX), ImmPtr(&(g_dsp.pc)));
|
||||
emitter.MOV(16, MatR(RAX), R(RSI));
|
||||
emitter.MOV(64, R(RSI), ImmPtr(&(g_dsp.pc)));
|
||||
emitter.MOV(16, MatR(RSI), R(RAX));
|
||||
#endif
|
||||
WriteBranchExit(emitter);
|
||||
}
|
||||
|
@ -404,12 +366,7 @@ void DSPEmitter::rti(const UDSPInstruction opc)
|
|||
{
|
||||
// g_dsp.r[DSP_REG_SR] = dsp_reg_load_stack(DSP_STACK_D);
|
||||
dsp_reg_load_stack(DSP_STACK_D);
|
||||
#ifdef _M_IX86 // All32
|
||||
MOV(16, M(&g_dsp.r.sr), R(DX));
|
||||
#else
|
||||
// MOV(64, R(R11), ImmPtr(&g_dsp.r));
|
||||
MOV(16, MDisp(R11, STRUCT_OFFSET(g_dsp.r, sr)), R(DX));
|
||||
#endif
|
||||
dsp_op_write_reg(DSP_REG_SR, RDX);
|
||||
// g_dsp.pc = dsp_reg_load_stack(DSP_STACK_C);
|
||||
dsp_reg_load_stack(DSP_STACK_C);
|
||||
#ifdef _M_IX86 // All32
|
||||
|
@ -504,14 +461,8 @@ void DSPEmitter::HandleLoop()
|
|||
void DSPEmitter::loop(const UDSPInstruction opc)
|
||||
{
|
||||
u16 reg = opc & 0x1f;
|
||||
u16 *regp = reg_ptr(reg);
|
||||
// u16 cnt = g_dsp.r[reg];
|
||||
#ifdef _M_IX86 // All32
|
||||
MOVZX(32, 16, EDX, M(regp));
|
||||
#else
|
||||
// MOV(64, R(R11), ImmPtr(&g_dsp.r));
|
||||
MOVZX(32, 16, EDX, MDisp(R11, PtrOffset(regp, &g_dsp.r)));
|
||||
#endif
|
||||
dsp_op_read_reg(reg, RDX, ZERO);
|
||||
u16 loop_pc = compilePC + 1;
|
||||
|
||||
CMP(16, R(EDX), Imm16(0));
|
||||
|
@ -575,14 +526,8 @@ void DSPEmitter::loopi(const UDSPInstruction opc)
|
|||
void DSPEmitter::bloop(const UDSPInstruction opc)
|
||||
{
|
||||
u16 reg = opc & 0x1f;
|
||||
u16* regp = reg_ptr(reg);
|
||||
// u16 cnt = g_dsp.r[reg];
|
||||
#ifdef _M_IX86 // All32
|
||||
MOVZX(32, 16, EDX, M(regp));
|
||||
#else
|
||||
// MOV(64, R(R11), ImmPtr(&g_dsp.r));
|
||||
MOVZX(32, 16, EDX, MDisp(R11, PtrOffset(regp, &g_dsp.r)));
|
||||
#endif
|
||||
dsp_op_read_reg(reg, RDX, ZERO);
|
||||
u16 loop_pc = dsp_imem_read(compilePC + 1);
|
||||
|
||||
CMP(16, R(EDX), Imm16(0));
|
||||
|
@ -609,7 +554,9 @@ void DSPEmitter::bloop(const UDSPInstruction opc)
|
|||
MOV(64, R(RAX), ImmPtr(&(g_dsp.pc)));
|
||||
MOV(16, MatR(RAX), Imm16(loop_pc + opTable[loop_pc]->size));
|
||||
#endif
|
||||
DSPJitRegCache c(gpr);
|
||||
WriteBranchExit(*this);
|
||||
gpr.flushRegs(c,false);
|
||||
SetJumpTarget(exit);
|
||||
}
|
||||
|
||||
|
|
|
@ -32,18 +32,20 @@ using namespace Gen;
|
|||
void DSPEmitter::Update_SR_Register(Gen::X64Reg val)
|
||||
{
|
||||
#ifdef _M_X64
|
||||
OpArg sr_reg;
|
||||
gpr.getReg(DSP_REG_SR,sr_reg);
|
||||
// // 0x04
|
||||
// if (_Value == 0) g_dsp.r[DSP_REG_SR] |= SR_ARITH_ZERO;
|
||||
CMP(64, R(val), Imm8(0));
|
||||
FixupBranch notZero = J_CC(CC_NZ);
|
||||
OR(16, MDisp(R11, STRUCT_OFFSET(g_dsp.r, sr)), Imm16(SR_ARITH_ZERO));
|
||||
OR(16, sr_reg, Imm16(SR_ARITH_ZERO));
|
||||
SetJumpTarget(notZero);
|
||||
|
||||
// // 0x08
|
||||
// if (_Value < 0) g_dsp.r[DSP_REG_SR] |= SR_SIGN;
|
||||
CMP(64, R(val), Imm8(0));
|
||||
FixupBranch greaterThanEqual = J_CC(CC_GE);
|
||||
OR(16, MDisp(R11, STRUCT_OFFSET(g_dsp.r, sr)), Imm16(SR_SIGN));
|
||||
OR(16, sr_reg, Imm16(SR_SIGN));
|
||||
SetJumpTarget(greaterThanEqual);
|
||||
|
||||
// // 0x10
|
||||
|
@ -51,7 +53,7 @@ void DSPEmitter::Update_SR_Register(Gen::X64Reg val)
|
|||
MOVSX(64, 32, RDX, R(val));
|
||||
CMP(64, R(RDX), R(val));
|
||||
FixupBranch noOverS32 = J_CC(CC_E);
|
||||
OR(16, MDisp(R11, STRUCT_OFFSET(g_dsp.r, sr)), Imm16(SR_OVER_S32));
|
||||
OR(16, sr_reg, Imm16(SR_OVER_S32));
|
||||
SetJumpTarget(noOverS32);
|
||||
|
||||
// // 0x20 - Checks if top bits of m are equal
|
||||
|
@ -63,8 +65,9 @@ void DSPEmitter::Update_SR_Register(Gen::X64Reg val)
|
|||
FixupBranch cC = J_CC(CC_NE);
|
||||
SetJumpTarget(zeroC);
|
||||
// g_dsp.r[DSP_REG_SR] |= SR_TOP2BITS;
|
||||
OR(16, MDisp(R11, STRUCT_OFFSET(g_dsp.r, sr)), Imm16(SR_TOP2BITS));
|
||||
OR(16, sr_reg, Imm16(SR_TOP2BITS));
|
||||
SetJumpTarget(cC);
|
||||
gpr.putReg(DSP_REG_SR);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -75,7 +78,10 @@ void DSPEmitter::Update_SR_Register64(Gen::X64Reg val)
|
|||
{
|
||||
#ifdef _M_X64
|
||||
// g_dsp.r[DSP_REG_SR] &= ~SR_CMP_MASK;
|
||||
AND(16, MDisp(R11, STRUCT_OFFSET(g_dsp.r, sr)), Imm16(~SR_CMP_MASK));
|
||||
OpArg sr_reg;
|
||||
gpr.getReg(DSP_REG_SR,sr_reg);
|
||||
AND(16, sr_reg, Imm16(~SR_CMP_MASK));
|
||||
gpr.putReg(DSP_REG_SR);
|
||||
Update_SR_Register(val);
|
||||
#endif
|
||||
}
|
||||
|
@ -86,8 +92,10 @@ void DSPEmitter::Update_SR_Register64(Gen::X64Reg val)
|
|||
void DSPEmitter::Update_SR_Register64_Carry(Gen::X64Reg val)
|
||||
{
|
||||
#ifdef _M_X64
|
||||
OpArg sr_reg;
|
||||
gpr.getReg(DSP_REG_SR,sr_reg);
|
||||
// g_dsp.r[DSP_REG_SR] &= ~SR_CMP_MASK;
|
||||
AND(16, MDisp(R11, STRUCT_OFFSET(g_dsp.r, sr)), Imm16(~SR_CMP_MASK));
|
||||
AND(16, sr_reg, Imm16(~SR_CMP_MASK));
|
||||
|
||||
CMP(64, R(RCX), R(val));
|
||||
|
||||
|
@ -95,7 +103,7 @@ void DSPEmitter::Update_SR_Register64_Carry(Gen::X64Reg val)
|
|||
// g_dsp.r[DSP_REG_SR] |= SR_CARRY;
|
||||
// Carry = (acc>res)
|
||||
FixupBranch noCarry = J_CC(CC_BE);
|
||||
OR(16, MDisp(R11, STRUCT_OFFSET(g_dsp.r, sr)), Imm16(SR_CARRY));
|
||||
OR(16, sr_reg, Imm16(SR_CARRY));
|
||||
SetJumpTarget(noCarry);
|
||||
|
||||
// 0x02 and 0x80
|
||||
|
@ -107,9 +115,10 @@ void DSPEmitter::Update_SR_Register64_Carry(Gen::X64Reg val)
|
|||
AND(64, R(RCX), R(RDX));
|
||||
CMP(64, R(RCX), Imm8(0));
|
||||
FixupBranch noOverflow = J_CC(CC_GE);
|
||||
OR(16, MDisp(R11, STRUCT_OFFSET(g_dsp.r, sr)), Imm16(SR_OVERFLOW | SR_OVERFLOW_STICKY));
|
||||
OR(16, sr_reg, Imm16(SR_OVERFLOW | SR_OVERFLOW_STICKY));
|
||||
SetJumpTarget(noOverflow);
|
||||
|
||||
gpr.putReg(DSP_REG_SR);
|
||||
Update_SR_Register(val);
|
||||
#endif
|
||||
}
|
||||
|
@ -120,8 +129,10 @@ void DSPEmitter::Update_SR_Register64_Carry(Gen::X64Reg val)
|
|||
void DSPEmitter::Update_SR_Register64_Carry2(Gen::X64Reg val)
|
||||
{
|
||||
#ifdef _M_X64
|
||||
OpArg sr_reg;
|
||||
gpr.getReg(DSP_REG_SR,sr_reg);
|
||||
// g_dsp.r[DSP_REG_SR] &= ~SR_CMP_MASK;
|
||||
AND(16, MDisp(R11, STRUCT_OFFSET(g_dsp.r, sr)), Imm16(~SR_CMP_MASK));
|
||||
AND(16, sr_reg, Imm16(~SR_CMP_MASK));
|
||||
|
||||
CMP(64, R(RCX), R(val));
|
||||
|
||||
|
@ -129,7 +140,7 @@ void DSPEmitter::Update_SR_Register64_Carry2(Gen::X64Reg val)
|
|||
// g_dsp.r[DSP_REG_SR] |= SR_CARRY;
|
||||
// Carry2 = (acc>=res)
|
||||
FixupBranch noCarry2 = J_CC(CC_B);
|
||||
OR(16, MDisp(R11, STRUCT_OFFSET(g_dsp.r, sr)), Imm16(SR_CARRY));
|
||||
OR(16, sr_reg, Imm16(SR_CARRY));
|
||||
SetJumpTarget(noCarry2);
|
||||
|
||||
// 0x02 and 0x80
|
||||
|
@ -141,8 +152,9 @@ void DSPEmitter::Update_SR_Register64_Carry2(Gen::X64Reg val)
|
|||
AND(64, R(RCX), R(RDX));
|
||||
CMP(64, R(RCX), Imm8(0));
|
||||
FixupBranch noOverflow = J_CC(CC_GE);
|
||||
OR(16, MDisp(R11, STRUCT_OFFSET(g_dsp.r, sr)), Imm16(SR_OVERFLOW | SR_OVERFLOW_STICKY));
|
||||
OR(16, sr_reg, Imm16(SR_OVERFLOW | SR_OVERFLOW_STICKY));
|
||||
SetJumpTarget(noOverflow);
|
||||
gpr.putReg(DSP_REG_SR);
|
||||
|
||||
Update_SR_Register();
|
||||
#endif
|
||||
|
@ -164,20 +176,22 @@ void DSPEmitter::Update_SR_Register64_Carry2(Gen::X64Reg val)
|
|||
void DSPEmitter::Update_SR_Register16(Gen::X64Reg val)
|
||||
{
|
||||
#ifdef _M_X64
|
||||
AND(16, MDisp(R11, STRUCT_OFFSET(g_dsp.r, sr)), Imm16(~SR_CMP_MASK));
|
||||
OpArg sr_reg;
|
||||
gpr.getReg(DSP_REG_SR,sr_reg);
|
||||
AND(16, sr_reg, Imm16(~SR_CMP_MASK));
|
||||
|
||||
// // 0x04
|
||||
// if (_Value == 0) g_dsp.r[DSP_REG_SR] |= SR_ARITH_ZERO;
|
||||
CMP(64, R(val), Imm8(0));
|
||||
FixupBranch notZero = J_CC(CC_NZ);
|
||||
OR(16, MDisp(R11, STRUCT_OFFSET(g_dsp.r, sr)), Imm16(SR_ARITH_ZERO));
|
||||
OR(16, sr_reg, Imm16(SR_ARITH_ZERO));
|
||||
SetJumpTarget(notZero);
|
||||
|
||||
// // 0x08
|
||||
// if (_Value < 0) g_dsp.r[DSP_REG_SR] |= SR_SIGN;
|
||||
CMP(64, R(val), Imm8(0));
|
||||
FixupBranch greaterThanEqual = J_CC(CC_GE);
|
||||
OR(16, MDisp(R11, STRUCT_OFFSET(g_dsp.r, sr)), Imm16(SR_SIGN));
|
||||
OR(16, sr_reg, Imm16(SR_SIGN));
|
||||
SetJumpTarget(greaterThanEqual);
|
||||
|
||||
// // 0x20 - Checks if top bits of m are equal
|
||||
|
@ -186,15 +200,16 @@ void DSPEmitter::Update_SR_Register16(Gen::X64Reg val)
|
|||
SHR(16, R(val), Imm8(14));
|
||||
CMP(16, R(val), Imm16(0));
|
||||
FixupBranch nZero = J_CC(CC_NE);
|
||||
OR(16, MDisp(R11, STRUCT_OFFSET(g_dsp.r, sr)), Imm16(SR_TOP2BITS));
|
||||
OR(16, sr_reg, Imm16(SR_TOP2BITS));
|
||||
FixupBranch cC = J();
|
||||
SetJumpTarget(nZero);
|
||||
CMP(16, R(val), Imm16(3));
|
||||
FixupBranch notThree = J_CC(CC_NE);
|
||||
// g_dsp.r[DSP_REG_SR] |= SR_TOP2BITS;
|
||||
OR(16, MDisp(R11, STRUCT_OFFSET(g_dsp.r, sr)), Imm16(SR_TOP2BITS));
|
||||
OR(16, sr_reg, Imm16(SR_TOP2BITS));
|
||||
SetJumpTarget(notThree);
|
||||
SetJumpTarget(cC);
|
||||
gpr.putReg(DSP_REG_SR);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -204,16 +219,19 @@ void DSPEmitter::Update_SR_Register16(Gen::X64Reg val)
|
|||
void DSPEmitter::Update_SR_Register16_OverS32(Gen::X64Reg val)
|
||||
{
|
||||
#ifdef _M_X64
|
||||
AND(16, MDisp(R11, STRUCT_OFFSET(g_dsp.r, sr)), Imm16(~SR_CMP_MASK));
|
||||
OpArg sr_reg;
|
||||
gpr.getReg(DSP_REG_SR,sr_reg);
|
||||
AND(16, sr_reg, Imm16(~SR_CMP_MASK));
|
||||
|
||||
// // 0x10
|
||||
// if (_Value != (s32)_Value) g_dsp.r[DSP_REG_SR] |= SR_OVER_S32;
|
||||
MOVSX(64, 32, RSI, R(val));
|
||||
CMP(64, R(RSI), R(val));
|
||||
FixupBranch noOverS32 = J_CC(CC_E);
|
||||
OR(16, MDisp(R11, STRUCT_OFFSET(g_dsp.r, sr)), Imm16(SR_OVER_S32));
|
||||
OR(16, sr_reg, Imm16(SR_OVER_S32));
|
||||
SetJumpTarget(noOverS32);
|
||||
|
||||
gpr.putReg(DSP_REG_SR);
|
||||
// // 0x20 - Checks if top bits of m are equal
|
||||
// if ((((u16)_Value >> 14) == 0) || (((u16)_Value >> 14) == 3))
|
||||
//AND(32, R(val), Imm32(0xc0000000));
|
||||
|
|
|
@ -79,29 +79,9 @@ void DSPEmitter::s(const UDSPInstruction opc)
|
|||
{
|
||||
u8 dreg = opc & 0x3;
|
||||
u8 sreg = ((opc >> 3) & 0x3) + DSP_REG_ACL0;
|
||||
u16 *sregp = 0;
|
||||
switch(sreg) {
|
||||
case DSP_REG_ACL0:
|
||||
case DSP_REG_ACL1:
|
||||
sregp = &(g_dsp.r.ac[sreg-DSP_REG_ACL0].l);
|
||||
break;
|
||||
case DSP_REG_ACM0:
|
||||
case DSP_REG_ACM1:
|
||||
sregp = &(g_dsp.r.ac[sreg-DSP_REG_ACM0].m);
|
||||
break;
|
||||
default:
|
||||
sregp = NULL;
|
||||
break;
|
||||
}
|
||||
// u16 addr = g_dsp.r[dest];
|
||||
#ifdef _M_IX86 // All32
|
||||
MOVZX(32, 16, EAX, M(&g_dsp.r.ar[dreg]));
|
||||
MOVZX(32, 16, ECX, M(sregp));
|
||||
#else
|
||||
// MOV(64, R(R11), ImmPtr(&g_dsp.r));
|
||||
MOVZX(64, 16, EAX, MDisp(R11, STRUCT_OFFSET(g_dsp.r, ar[dreg])));
|
||||
MOVZX(64, 16, ECX, MDisp(R11, PtrOffset(sregp, &g_dsp.r)));
|
||||
#endif
|
||||
dsp_op_read_reg(dreg, RAX, ZERO);
|
||||
dsp_op_read_reg(sreg, RCX, ZERO);
|
||||
// u16 val = g_dsp.r[src];
|
||||
dmem_write();
|
||||
increment_addr_reg(dreg);
|
||||
|
@ -115,28 +95,8 @@ void DSPEmitter::sn(const UDSPInstruction opc)
|
|||
{
|
||||
u8 dreg = opc & 0x3;
|
||||
u8 sreg = ((opc >> 3) & 0x3) + DSP_REG_ACL0;
|
||||
u16 *sregp = 0;
|
||||
switch(sreg) {
|
||||
case DSP_REG_ACL0:
|
||||
case DSP_REG_ACL1:
|
||||
sregp = &(g_dsp.r.ac[sreg-DSP_REG_ACL0].l);
|
||||
break;
|
||||
case DSP_REG_ACM0:
|
||||
case DSP_REG_ACM1:
|
||||
sregp = &(g_dsp.r.ac[sreg-DSP_REG_ACM0].m);
|
||||
break;
|
||||
default:
|
||||
sregp = NULL;
|
||||
break;
|
||||
}
|
||||
#ifdef _M_IX86 // All32
|
||||
MOVZX(32, 16, EAX, M(&g_dsp.r.ar[dreg]));
|
||||
MOVZX(32, 16, ECX, M(sregp));
|
||||
#else
|
||||
// MOV(64, R(R11), ImmPtr(&g_dsp.r));
|
||||
MOVZX(64, 16, EAX, MDisp(R11, STRUCT_OFFSET(g_dsp.r, ar[dreg])));
|
||||
MOVZX(64, 16, ECX, MDisp(R11, PtrOffset(sregp, &g_dsp.r)));
|
||||
#endif
|
||||
dsp_op_read_reg(dreg, RAX, ZERO);
|
||||
dsp_op_read_reg(sreg, RCX, ZERO);
|
||||
dmem_write();
|
||||
increase_addr_reg(dreg);
|
||||
}
|
||||
|
@ -208,14 +168,8 @@ void DSPEmitter::ls(const UDSPInstruction opc)
|
|||
{
|
||||
u8 sreg = opc & 0x1;
|
||||
u8 dreg = ((opc >> 4) & 0x3) + DSP_REG_AXL0;
|
||||
#ifdef _M_IX86 // All32
|
||||
MOVZX(32, 16, EAX, M(&g_dsp.r.ar[3]));
|
||||
MOVZX(32, 16, ECX, M(&g_dsp.r.ac[sreg].m));
|
||||
#else
|
||||
// MOV(64, R(R11), ImmPtr(&g_dsp.r));
|
||||
MOVZX(64, 16, EAX, MDisp(R11, STRUCT_OFFSET(g_dsp.r, ar[3])));
|
||||
MOVZX(64, 16, ECX, MDisp(R11, STRUCT_OFFSET(g_dsp.r, ac[sreg].m)));
|
||||
#endif
|
||||
dsp_op_read_reg(DSP_REG_AR3, RAX, ZERO);
|
||||
get_acc_m(sreg, ECX, false);
|
||||
dmem_write();
|
||||
|
||||
pushExtValueFromMem(dreg, DSP_REG_AR0);
|
||||
|
@ -235,14 +189,8 @@ void DSPEmitter::lsn(const UDSPInstruction opc)
|
|||
{
|
||||
u8 sreg = opc & 0x1;
|
||||
u8 dreg = ((opc >> 4) & 0x3) + DSP_REG_AXL0;
|
||||
#ifdef _M_IX86 // All32
|
||||
MOVZX(32, 16, EAX, M(&g_dsp.r.ar[3]));
|
||||
MOVZX(32, 16, ECX, M(&g_dsp.r.ac[sreg].m));
|
||||
#else
|
||||
// MOV(64, R(R11), ImmPtr(&g_dsp.r));
|
||||
MOVZX(64, 16, EAX, MDisp(R11, STRUCT_OFFSET(g_dsp.r, ar[3])));
|
||||
MOVZX(64, 16, ECX, MDisp(R11, STRUCT_OFFSET(g_dsp.r, ac[sreg].m)));
|
||||
#endif
|
||||
dsp_op_read_reg(DSP_REG_AR3, RAX, ZERO);
|
||||
get_acc_m(sreg, ECX, false);
|
||||
dmem_write();
|
||||
|
||||
pushExtValueFromMem(dreg, DSP_REG_AR0);
|
||||
|
@ -261,14 +209,8 @@ void DSPEmitter::lsm(const UDSPInstruction opc)
|
|||
{
|
||||
u8 sreg = opc & 0x1;
|
||||
u8 dreg = ((opc >> 4) & 0x3) + DSP_REG_AXL0;
|
||||
#ifdef _M_IX86 // All32
|
||||
MOVZX(32, 16, EAX, M(&g_dsp.r.ar[3]));
|
||||
MOVZX(32, 16, ECX, M(&g_dsp.r.ac[sreg].m));
|
||||
#else
|
||||
// MOV(64, R(R11), ImmPtr(&g_dsp.r));
|
||||
MOVZX(64, 16, EAX, MDisp(R11, STRUCT_OFFSET(g_dsp.r, ar[3])));
|
||||
MOVZX(64, 16, ECX, MDisp(R11, STRUCT_OFFSET(g_dsp.r, ac[sreg].m)));
|
||||
#endif
|
||||
dsp_op_read_reg(DSP_REG_AR3, RAX, ZERO);
|
||||
get_acc_m(sreg, ECX, false);
|
||||
dmem_write();
|
||||
|
||||
pushExtValueFromMem(dreg, DSP_REG_AR0);
|
||||
|
@ -288,14 +230,8 @@ void DSPEmitter::lsnm(const UDSPInstruction opc)
|
|||
{
|
||||
u8 sreg = opc & 0x1;
|
||||
u8 dreg = ((opc >> 4) & 0x3) + DSP_REG_AXL0;
|
||||
#ifdef _M_IX86 // All32
|
||||
MOVZX(32, 16, EAX, M(&g_dsp.r.ar[3]));
|
||||
MOVZX(32, 16, ECX, M(&g_dsp.r.ac[sreg].m));
|
||||
#else
|
||||
// MOV(64, R(R11), ImmPtr(&g_dsp.r));
|
||||
MOVZX(64, 16, EAX, MDisp(R11, STRUCT_OFFSET(g_dsp.r, ar[3])));
|
||||
MOVZX(64, 16, ECX, MDisp(R11, STRUCT_OFFSET(g_dsp.r, ac[sreg].m)));
|
||||
#endif
|
||||
dsp_op_read_reg(DSP_REG_AR3, RAX, ZERO);
|
||||
get_acc_m(sreg, ECX, false);
|
||||
dmem_write();
|
||||
|
||||
pushExtValueFromMem(dreg, DSP_REG_AR0);
|
||||
|
@ -313,14 +249,8 @@ void DSPEmitter::sl(const UDSPInstruction opc)
|
|||
{
|
||||
u8 sreg = opc & 0x1;
|
||||
u8 dreg = ((opc >> 4) & 0x3) + DSP_REG_AXL0;
|
||||
#ifdef _M_IX86 // All32
|
||||
MOVZX(32, 16, EAX, M(&g_dsp.r.ar[0]));
|
||||
MOVZX(32, 16, ECX, M(&g_dsp.r.ac[sreg].m));
|
||||
#else
|
||||
// MOV(64, R(R11), ImmPtr(&g_dsp.r));
|
||||
MOVZX(64, 16, EAX, MDisp(R11, STRUCT_OFFSET(g_dsp.r, ar[0])));
|
||||
MOVZX(64, 16, ECX, MDisp(R11, STRUCT_OFFSET(g_dsp.r, ac[sreg].m)));
|
||||
#endif
|
||||
dsp_op_read_reg(DSP_REG_AR0, RAX, ZERO);
|
||||
get_acc_m(sreg, ECX, false);
|
||||
dmem_write();
|
||||
|
||||
pushExtValueFromMem(dreg, DSP_REG_AR3);
|
||||
|
@ -339,14 +269,8 @@ void DSPEmitter::sln(const UDSPInstruction opc)
|
|||
{
|
||||
u8 sreg = opc & 0x1;
|
||||
u8 dreg = ((opc >> 4) & 0x3) + DSP_REG_AXL0;
|
||||
#ifdef _M_IX86 // All32
|
||||
MOVZX(32, 16, EAX, M(&g_dsp.r.ar[0]));
|
||||
MOVZX(32, 16, ECX, M(&g_dsp.r.ac[sreg].m));
|
||||
#else
|
||||
// MOV(64, R(R11), ImmPtr(&g_dsp.r));
|
||||
MOVZX(64, 16, EAX, MDisp(R11, STRUCT_OFFSET(g_dsp.r, ar[0])));
|
||||
MOVZX(64, 16, ECX, MDisp(R11, STRUCT_OFFSET(g_dsp.r, ac[sreg].m)));
|
||||
#endif
|
||||
dsp_op_read_reg(DSP_REG_AR0, RAX, ZERO);
|
||||
get_acc_m(sreg, ECX, false);
|
||||
dmem_write();
|
||||
|
||||
pushExtValueFromMem(dreg, DSP_REG_AR3);
|
||||
|
@ -365,14 +289,8 @@ void DSPEmitter::slm(const UDSPInstruction opc)
|
|||
{
|
||||
u8 sreg = opc & 0x1;
|
||||
u8 dreg = ((opc >> 4) & 0x3) + DSP_REG_AXL0;
|
||||
#ifdef _M_IX86 // All32
|
||||
MOVZX(32, 16, EAX, M(&g_dsp.r.ar[0]));
|
||||
MOVZX(32, 16, ECX, M(&g_dsp.r.ac[sreg].m));
|
||||
#else
|
||||
// MOV(64, R(R11), ImmPtr(&g_dsp.r));
|
||||
MOVZX(64, 16, EAX, MDisp(R11, STRUCT_OFFSET(g_dsp.r, ar[0])));
|
||||
MOVZX(64, 16, ECX, MDisp(R11, STRUCT_OFFSET(g_dsp.r, ac[sreg].m)));
|
||||
#endif
|
||||
dsp_op_read_reg(DSP_REG_AR0, RAX, ZERO);
|
||||
get_acc_m(sreg, ECX, false);
|
||||
dmem_write();
|
||||
|
||||
pushExtValueFromMem(dreg, DSP_REG_AR3);
|
||||
|
@ -391,14 +309,8 @@ void DSPEmitter::slnm(const UDSPInstruction opc)
|
|||
{
|
||||
u8 sreg = opc & 0x1;
|
||||
u8 dreg = ((opc >> 4) & 0x3) + DSP_REG_AXL0;
|
||||
#ifdef _M_IX86 // All32
|
||||
MOVZX(32, 16, EAX, M(&g_dsp.r.ar[0]));
|
||||
MOVZX(32, 16, ECX, M(&g_dsp.r.ac[sreg].m));
|
||||
#else
|
||||
// MOV(64, R(R11), ImmPtr(&g_dsp.r));
|
||||
MOVZX(64, 16, EAX, MDisp(R11, STRUCT_OFFSET(g_dsp.r, ar[0])));
|
||||
MOVZX(64, 16, ECX, MDisp(R11, STRUCT_OFFSET(g_dsp.r, ac[sreg].m)));
|
||||
#endif
|
||||
dsp_op_read_reg(DSP_REG_AR0, RAX, ZERO);
|
||||
get_acc_m(sreg, ECX, false);
|
||||
dmem_write();
|
||||
|
||||
pushExtValueFromMem(dreg, DSP_REG_AR3);
|
||||
|
@ -427,22 +339,19 @@ void DSPEmitter::ld(const UDSPInstruction opc)
|
|||
pushExtValueFromMem((dreg << 1) + DSP_REG_AXL0, sreg);
|
||||
|
||||
// if (IsSameMemArea(g_dsp.r[sreg], g_dsp.r[DSP_REG_AR3])) {
|
||||
#ifdef _M_IX86 // All32
|
||||
MOV(16, R(ESI), M(&g_dsp.r.ar[sreg]));
|
||||
MOV(16, R(EDI), M(&g_dsp.r.ar[3]));
|
||||
#else
|
||||
// MOV(64, R(R11), ImmPtr(&g_dsp.r));
|
||||
MOV(16, R(ESI), MDisp(R11, STRUCT_OFFSET(g_dsp.r, ar[sreg])));
|
||||
MOV(16, R(EDI), MDisp(R11, STRUCT_OFFSET(g_dsp.r, ar[3])));
|
||||
#endif
|
||||
dsp_op_read_reg(sreg, RSI, NONE);
|
||||
dsp_op_read_reg(DSP_REG_AR3, RDI, NONE);
|
||||
SHR(16, R(ESI), Imm8(10));
|
||||
SHR(16, R(EDI), Imm8(10));
|
||||
DSPJitRegCache c(gpr);
|
||||
CMP(16, R(ESI), R(EDI));
|
||||
FixupBranch not_equal = J_CC(CC_NE);
|
||||
FixupBranch not_equal = J_CC(CC_NE,true);
|
||||
pushExtValueFromMem2((rreg << 1) + DSP_REG_AXL1, sreg);
|
||||
FixupBranch after = J();
|
||||
gpr.flushRegs(c);
|
||||
FixupBranch after = J(true);
|
||||
SetJumpTarget(not_equal); // else
|
||||
pushExtValueFromMem2((rreg << 1) + DSP_REG_AXL1, DSP_REG_AR3);
|
||||
gpr.flushRegs(c);
|
||||
SetJumpTarget(after);
|
||||
|
||||
increment_addr_reg(sreg);
|
||||
|
@ -451,22 +360,19 @@ void DSPEmitter::ld(const UDSPInstruction opc)
|
|||
pushExtValueFromMem(rreg + DSP_REG_AXH0, dreg);
|
||||
|
||||
//if (IsSameMemArea(g_dsp.r[dreg], g_dsp.r[DSP_REG_AR3])) {
|
||||
#ifdef _M_IX86 // All32
|
||||
MOV(16, R(ESI), M(&g_dsp.r.ar[dreg]));
|
||||
MOV(16, R(EDI), M(&g_dsp.r.ar[3]));
|
||||
#else
|
||||
// MOV(64, R(R11), ImmPtr(&g_dsp.r));
|
||||
MOV(16, R(ESI), MDisp(R11, STRUCT_OFFSET(g_dsp.r, ar[dreg])));
|
||||
MOV(16, R(EDI), MDisp(R11, STRUCT_OFFSET(g_dsp.r, ar[3])));
|
||||
#endif
|
||||
dsp_op_read_reg(dreg, RSI, NONE);
|
||||
dsp_op_read_reg(DSP_REG_AR3, RDI, NONE);
|
||||
SHR(16, R(ESI), Imm8(10));
|
||||
SHR(16, R(EDI), Imm8(10));
|
||||
DSPJitRegCache c(gpr);
|
||||
CMP(16, R(ESI), R(EDI));
|
||||
FixupBranch not_equal = J_CC(CC_NE, true);
|
||||
pushExtValueFromMem2(rreg + DSP_REG_AXL0, dreg);
|
||||
gpr.flushRegs(c);
|
||||
FixupBranch after = J(true); // else
|
||||
SetJumpTarget(not_equal);
|
||||
pushExtValueFromMem2(rreg + DSP_REG_AXL0, DSP_REG_AR3);
|
||||
gpr.flushRegs(c);
|
||||
SetJumpTarget(after);
|
||||
|
||||
increment_addr_reg(dreg);
|
||||
|
@ -486,23 +392,20 @@ void DSPEmitter::ldn(const UDSPInstruction opc)
|
|||
if (sreg != DSP_REG_AR3) {
|
||||
pushExtValueFromMem((dreg << 1) + DSP_REG_AXL0, sreg);
|
||||
|
||||
// if (IsSameMemArea(g_dsp.r[sreg], g_dsp.r[DSP_REG_AR3])) {
|
||||
#ifdef _M_IX86 // All32
|
||||
MOV(16, R(ESI), M(&g_dsp.r.ar[sreg]));
|
||||
MOV(16, R(EDI), M(&g_dsp.r.ar[3]));
|
||||
#else
|
||||
// MOV(64, R(R11), ImmPtr(&g_dsp.r));
|
||||
MOV(16, R(ESI), MDisp(R11, STRUCT_OFFSET(g_dsp.r, ar[sreg])));
|
||||
MOV(16, R(EDI), MDisp(R11, STRUCT_OFFSET(g_dsp.r, ar[3])));
|
||||
#endif
|
||||
//if (IsSameMemArea(g_dsp.r[sreg], g_dsp.r[DSP_REG_AR3])) {
|
||||
dsp_op_read_reg(sreg, RSI, NONE);
|
||||
dsp_op_read_reg(DSP_REG_AR3, RDI, NONE);
|
||||
SHR(16, R(ESI), Imm8(10));
|
||||
SHR(16, R(EDI), Imm8(10));
|
||||
DSPJitRegCache c(gpr);
|
||||
CMP(16, R(ESI), R(EDI));
|
||||
FixupBranch not_equal = J_CC(CC_NE);
|
||||
FixupBranch not_equal = J_CC(CC_NE,true);
|
||||
pushExtValueFromMem2((rreg << 1) + DSP_REG_AXL1, sreg);
|
||||
FixupBranch after = J();
|
||||
gpr.flushRegs(c);
|
||||
FixupBranch after = J(true);
|
||||
SetJumpTarget(not_equal); // else
|
||||
pushExtValueFromMem2((rreg << 1) + DSP_REG_AXL1, DSP_REG_AR3);
|
||||
gpr.flushRegs(c);
|
||||
SetJumpTarget(after);
|
||||
|
||||
increase_addr_reg(sreg);
|
||||
|
@ -510,22 +413,19 @@ void DSPEmitter::ldn(const UDSPInstruction opc)
|
|||
pushExtValueFromMem(rreg + DSP_REG_AXH0, dreg);
|
||||
|
||||
//if (IsSameMemArea(g_dsp.r[dreg], g_dsp.r[DSP_REG_AR3])) {
|
||||
#ifdef _M_IX86 // All32
|
||||
MOV(16, R(ESI), M(&g_dsp.r.ar[dreg]));
|
||||
MOV(16, R(EDI), M(&g_dsp.r.ar[3]));
|
||||
#else
|
||||
// MOV(64, R(R11), ImmPtr(&g_dsp.r));
|
||||
MOV(16, R(ESI), MDisp(R11, STRUCT_OFFSET(g_dsp.r, ar[dreg])));
|
||||
MOV(16, R(EDI), MDisp(R11, STRUCT_OFFSET(g_dsp.r, ar[3])));
|
||||
#endif
|
||||
dsp_op_read_reg(dreg, RSI, NONE);
|
||||
dsp_op_read_reg(DSP_REG_AR3, RDI, NONE);
|
||||
SHR(16, R(ESI), Imm8(10));
|
||||
SHR(16, R(EDI), Imm8(10));
|
||||
DSPJitRegCache c(gpr);
|
||||
CMP(16, R(ESI), R(EDI));
|
||||
FixupBranch not_equal = J_CC(CC_NE);
|
||||
FixupBranch not_equal = J_CC(CC_NE,true);
|
||||
pushExtValueFromMem2(rreg + DSP_REG_AXL0, dreg);
|
||||
FixupBranch after = J(); // else
|
||||
gpr.flushRegs(c);
|
||||
FixupBranch after = J(true); // else
|
||||
SetJumpTarget(not_equal);
|
||||
pushExtValueFromMem2(rreg + DSP_REG_AXL0, DSP_REG_AR3);
|
||||
gpr.flushRegs(c);
|
||||
SetJumpTarget(after);
|
||||
|
||||
increase_addr_reg(dreg);
|
||||
|
@ -545,23 +445,20 @@ void DSPEmitter::ldm(const UDSPInstruction opc)
|
|||
if (sreg != DSP_REG_AR3) {
|
||||
pushExtValueFromMem((dreg << 1) + DSP_REG_AXL0, sreg);
|
||||
|
||||
// if (IsSameMemArea(g_dsp.r[sreg], g_dsp.r[DSP_REG_AR3])) {
|
||||
#ifdef _M_IX86 // All32
|
||||
MOV(16, R(ESI), M(&g_dsp.r.ar[sreg]));
|
||||
MOV(16, R(EDI), M(&g_dsp.r.ar[3]));
|
||||
#else
|
||||
// MOV(64, R(R11), ImmPtr(&g_dsp.r));
|
||||
MOV(16, R(ESI), MDisp(R11, STRUCT_OFFSET(g_dsp.r, ar[sreg])));
|
||||
MOV(16, R(EDI), MDisp(R11, STRUCT_OFFSET(g_dsp.r, ar[3])));
|
||||
#endif
|
||||
//if (IsSameMemArea(g_dsp.r[sreg], g_dsp.r[DSP_REG_AR3])) {
|
||||
dsp_op_read_reg(sreg, RSI, NONE);
|
||||
dsp_op_read_reg(DSP_REG_AR3, RDI, NONE);
|
||||
SHR(16, R(ESI), Imm8(10));
|
||||
SHR(16, R(EDI), Imm8(10));
|
||||
DSPJitRegCache c(gpr);
|
||||
CMP(16, R(ESI), R(EDI));
|
||||
FixupBranch not_equal = J_CC(CC_NE);
|
||||
FixupBranch not_equal = J_CC(CC_NE,true);
|
||||
pushExtValueFromMem2((rreg << 1) + DSP_REG_AXL1, sreg);
|
||||
FixupBranch after = J();
|
||||
gpr.flushRegs(c);
|
||||
FixupBranch after = J(true);
|
||||
SetJumpTarget(not_equal); // else
|
||||
pushExtValueFromMem2((rreg << 1) + DSP_REG_AXL1, DSP_REG_AR3);
|
||||
gpr.flushRegs(c);
|
||||
SetJumpTarget(after);
|
||||
|
||||
increment_addr_reg(sreg);
|
||||
|
@ -569,22 +466,19 @@ void DSPEmitter::ldm(const UDSPInstruction opc)
|
|||
pushExtValueFromMem(rreg + DSP_REG_AXH0, dreg);
|
||||
|
||||
//if (IsSameMemArea(g_dsp.r[dreg], g_dsp.r[DSP_REG_AR3])) {
|
||||
#ifdef _M_IX86 // All32
|
||||
MOV(16, R(ESI), M(&g_dsp.r.ar[dreg]));
|
||||
MOV(16, R(EDI), M(&g_dsp.r.ar[3]));
|
||||
#else
|
||||
// MOV(64, R(R11), ImmPtr(&g_dsp.r));
|
||||
MOV(16, R(ESI), MDisp(R11, STRUCT_OFFSET(g_dsp.r, ar[dreg])));
|
||||
MOV(16, R(EDI), MDisp(R11, STRUCT_OFFSET(g_dsp.r, ar[3])));
|
||||
#endif
|
||||
dsp_op_read_reg(dreg, RSI, NONE);
|
||||
dsp_op_read_reg(DSP_REG_AR3, RDI, NONE);
|
||||
SHR(16, R(ESI), Imm8(10));
|
||||
SHR(16, R(EDI), Imm8(10));
|
||||
DSPJitRegCache c(gpr);
|
||||
CMP(16, R(ESI), R(EDI));
|
||||
FixupBranch not_equal = J_CC(CC_NE);
|
||||
FixupBranch not_equal = J_CC(CC_NE,true);
|
||||
pushExtValueFromMem2(rreg + DSP_REG_AXL0, dreg);
|
||||
FixupBranch after = J(); // else
|
||||
gpr.flushRegs(c);
|
||||
FixupBranch after = J(true); // else
|
||||
SetJumpTarget(not_equal);
|
||||
pushExtValueFromMem2(rreg + DSP_REG_AXL0, DSP_REG_AR3);
|
||||
gpr.flushRegs(c);
|
||||
SetJumpTarget(after);
|
||||
|
||||
increment_addr_reg(dreg);
|
||||
|
@ -604,23 +498,20 @@ void DSPEmitter::ldnm(const UDSPInstruction opc)
|
|||
if (sreg != DSP_REG_AR3) {
|
||||
pushExtValueFromMem((dreg << 1) + DSP_REG_AXL0, sreg);
|
||||
|
||||
// if (IsSameMemArea(g_dsp.r[sreg], g_dsp.r[DSP_REG_AR3])) {
|
||||
#ifdef _M_IX86 // All32
|
||||
MOV(16, R(ESI), M(&g_dsp.r.ar[sreg]));
|
||||
MOV(16, R(EDI), M(&g_dsp.r.ar[3]));
|
||||
#else
|
||||
// MOV(64, R(R11), ImmPtr(&g_dsp.r));
|
||||
MOV(16, R(ESI), MDisp(R11, STRUCT_OFFSET(g_dsp.r, ar[sreg])));
|
||||
MOV(16, R(EDI), MDisp(R11, STRUCT_OFFSET(g_dsp.r, ar[3])));
|
||||
#endif
|
||||
//if (IsSameMemArea(g_dsp.r[sreg], g_dsp.r[DSP_REG_AR3])) {
|
||||
dsp_op_read_reg(sreg, RSI, NONE);
|
||||
dsp_op_read_reg(DSP_REG_AR3, RDI, NONE);
|
||||
SHR(16, R(ESI), Imm8(10));
|
||||
SHR(16, R(EDI), Imm8(10));
|
||||
DSPJitRegCache c(gpr);
|
||||
CMP(16, R(ESI), R(EDI));
|
||||
FixupBranch not_equal = J_CC(CC_NE);
|
||||
FixupBranch not_equal = J_CC(CC_NE,true);
|
||||
pushExtValueFromMem2((rreg << 1) + DSP_REG_AXL1, sreg);
|
||||
FixupBranch after = J();
|
||||
gpr.flushRegs(c);
|
||||
FixupBranch after = J(true);
|
||||
SetJumpTarget(not_equal); // else
|
||||
pushExtValueFromMem2((rreg << 1) + DSP_REG_AXL1, DSP_REG_AR3);
|
||||
gpr.flushRegs(c);
|
||||
SetJumpTarget(after);
|
||||
|
||||
increase_addr_reg(sreg);
|
||||
|
@ -628,22 +519,19 @@ void DSPEmitter::ldnm(const UDSPInstruction opc)
|
|||
pushExtValueFromMem(rreg + DSP_REG_AXH0, dreg);
|
||||
|
||||
//if (IsSameMemArea(g_dsp.r[dreg], g_dsp.r[DSP_REG_AR3])) {
|
||||
#ifdef _M_IX86 // All32
|
||||
MOV(16, R(ESI), M(&g_dsp.r.ar[dreg]));
|
||||
MOV(16, R(EDI), M(&g_dsp.r.ar[3]));
|
||||
#else
|
||||
// MOV(64, R(R11), ImmPtr(&g_dsp.r));
|
||||
MOV(16, R(ESI), MDisp(R11, STRUCT_OFFSET(g_dsp.r, ar[dreg])));
|
||||
MOV(16, R(EDI), MDisp(R11, STRUCT_OFFSET(g_dsp.r, ar[3])));
|
||||
#endif
|
||||
dsp_op_read_reg(dreg, RSI, NONE);
|
||||
dsp_op_read_reg(DSP_REG_AR3, RDI, NONE);
|
||||
SHR(16, R(ESI), Imm8(10));
|
||||
SHR(16, R(EDI), Imm8(10));
|
||||
DSPJitRegCache c(gpr);
|
||||
CMP(16, R(ESI), R(EDI));
|
||||
FixupBranch not_equal = J_CC(CC_NE);
|
||||
FixupBranch not_equal = J_CC(CC_NE,true);
|
||||
pushExtValueFromMem2(rreg + DSP_REG_AXL0, dreg);
|
||||
FixupBranch after = J(); // else
|
||||
gpr.flushRegs(c);
|
||||
FixupBranch after = J(true); // else
|
||||
SetJumpTarget(not_equal);
|
||||
pushExtValueFromMem2(rreg + DSP_REG_AXL0, DSP_REG_AR3);
|
||||
gpr.flushRegs(c);
|
||||
SetJumpTarget(after);
|
||||
|
||||
increase_addr_reg(dreg);
|
||||
|
@ -656,24 +544,13 @@ void DSPEmitter::ldnm(const UDSPInstruction opc)
|
|||
// Push value from g_dsp.r[sreg] into EBX and stores the destinationindex in
|
||||
// storeIndex
|
||||
void DSPEmitter::pushExtValueFromReg(u16 dreg, u16 sreg) {
|
||||
u16 *sregp = reg_ptr(sreg);
|
||||
#ifdef _M_IX86 // All32
|
||||
MOVZX(32, 16, EBX, M(sregp));
|
||||
#else
|
||||
MOV(64, R(RBX), ImmPtr(&g_dsp.r));
|
||||
MOVZX(32, 16, EBX, MDisp(RBX, PtrOffset(sregp, &g_dsp.r)));
|
||||
#endif
|
||||
dsp_op_read_reg(sreg, RBX, ZERO);
|
||||
storeIndex = dreg;
|
||||
}
|
||||
|
||||
void DSPEmitter::pushExtValueFromMem(u16 dreg, u16 sreg) {
|
||||
// u16 addr = g_dsp.r[addr];
|
||||
#ifdef _M_IX86 // All32
|
||||
MOVZX(32, 16, ECX, M(&g_dsp.r.ar[sreg]));
|
||||
#else
|
||||
// MOV(64, R(R11), ImmPtr(&g_dsp.r));
|
||||
MOVZX(64, 16, ECX, MDisp(R11, STRUCT_OFFSET(g_dsp.r, ar[sreg])));
|
||||
#endif
|
||||
dsp_op_read_reg(sreg, RCX, ZERO);
|
||||
dmem_read();
|
||||
MOVZX(32, 16, EBX, R(EAX));
|
||||
|
||||
|
@ -682,12 +559,7 @@ void DSPEmitter::pushExtValueFromMem(u16 dreg, u16 sreg) {
|
|||
|
||||
void DSPEmitter::pushExtValueFromMem2(u16 dreg, u16 sreg) {
|
||||
// u16 addr = g_dsp.r[addr];
|
||||
#ifdef _M_IX86 // All32
|
||||
MOVZX(32, 16, ECX, M(&g_dsp.r.ar[sreg]));
|
||||
#else
|
||||
// MOV(64, R(R11), ImmPtr(&g_dsp.r));
|
||||
MOVZX(64, 16, ECX, MDisp(R11, STRUCT_OFFSET(g_dsp.r, ar[sreg])));
|
||||
#endif
|
||||
dsp_op_read_reg(sreg, RCX, ZERO);
|
||||
dmem_read();
|
||||
SHL(32, R(EAX), Imm8(16));
|
||||
OR(32, R(EBX), R(EAX));
|
||||
|
@ -704,16 +576,11 @@ void DSPEmitter::popExtValueToReg() {
|
|||
// [nakeee] the or case never happens in real
|
||||
// [nakeee] it's just how the hardware works so we added it
|
||||
if (storeIndex != -1) {
|
||||
u16 *dregp = reg_ptr(storeIndex);
|
||||
#ifdef _M_IX86 // All32
|
||||
MOV(16, M(dregp), R(EBX));
|
||||
#else
|
||||
// MOV(64, R(R11), ImmPtr(&g_dsp.r));
|
||||
MOV(16, MDisp(R11, PtrOffset(dregp, &g_dsp.r)), R(EBX));
|
||||
#endif
|
||||
dsp_op_write_reg(storeIndex, RBX);
|
||||
if (storeIndex >= DSP_REG_ACM0 && storeIndex2 == -1) {
|
||||
TEST(32, R(EBX), Imm32(SR_40_MODE_BIT << 16));
|
||||
FixupBranch not_40bit = J_CC(CC_Z);
|
||||
DSPJitRegCache c(gpr);
|
||||
//if (g_dsp.r[DSP_REG_SR] & SR_40_MODE_BIT)
|
||||
//{
|
||||
// Sign extend into whole accum.
|
||||
|
@ -722,16 +589,10 @@ void DSPEmitter::popExtValueToReg() {
|
|||
SHR(32, R(EAX), Imm8(16));
|
||||
//g_dsp.r[reg - DSP_REG_ACM0 + DSP_REG_ACH0] = (val & 0x8000) ? 0xFFFF : 0x0000;
|
||||
//g_dsp.r[reg - DSP_REG_ACM0 + DSP_REG_ACL0] = 0;
|
||||
#ifdef _M_IX86 // All32
|
||||
MOV(16, M(&g_dsp.r.ac[storeIndex - DSP_REG_ACM0].h),
|
||||
R(EAX));
|
||||
MOV(16, M(&g_dsp.r.ac[storeIndex - DSP_REG_ACM0].l),
|
||||
Imm16(0));
|
||||
#else
|
||||
MOV(16, MDisp(R11, STRUCT_OFFSET(g_dsp.r, ac[storeIndex - DSP_REG_ACM0].h)), R(EAX));
|
||||
MOV(16, MDisp(R11, STRUCT_OFFSET(g_dsp.r, ac[storeIndex - DSP_REG_ACM0].l)), Imm16(0));
|
||||
#endif
|
||||
set_acc_h(storeIndex - DSP_REG_ACM0, R(RAX));
|
||||
set_acc_l(storeIndex - DSP_REG_ACM0, Imm16(0));
|
||||
//}
|
||||
gpr.flushRegs(c);
|
||||
SetJumpTarget(not_40bit);
|
||||
}
|
||||
}
|
||||
|
@ -740,13 +601,7 @@ void DSPEmitter::popExtValueToReg() {
|
|||
|
||||
if (storeIndex2 != -1) {
|
||||
SHR(32, R(EBX), Imm8(16));
|
||||
u16 *dregp = reg_ptr(storeIndex2);
|
||||
#ifdef _M_IX86 // All32
|
||||
MOV(16, M(dregp), R(EBX));
|
||||
#else
|
||||
// MOV(64, R(R11), ImmPtr(&g_dsp.r));
|
||||
MOV(16, MDisp(R11, PtrOffset(dregp, &g_dsp.r)), R(EBX));
|
||||
#endif
|
||||
dsp_op_write_reg(storeIndex2, RBX);
|
||||
}
|
||||
storeIndex2 = -1;
|
||||
}
|
||||
|
|
|
@ -34,16 +34,9 @@ using namespace Gen;
|
|||
void DSPEmitter::srs(const UDSPInstruction opc)
|
||||
{
|
||||
u8 reg = ((opc >> 8) & 0x7) + 0x18;
|
||||
u16 *regp = reg_ptr(reg);
|
||||
//u16 addr = (g_dsp.r.cr << 8) | (opc & 0xFF);
|
||||
#ifdef _M_IX86 // All32
|
||||
MOVZX(32, 16, ECX, M(regp));
|
||||
MOVZX(32, 8, EAX, M(&g_dsp.r.cr));
|
||||
#else
|
||||
// MOV(64, R(R11), ImmPtr(&g_dsp.r));
|
||||
MOVZX(64, 16, RCX, MDisp(R11, PtrOffset(regp, &g_dsp.r)));
|
||||
MOVZX(64, 8, RAX, MDisp(R11, STRUCT_OFFSET(g_dsp.r, cr)));
|
||||
#endif
|
||||
dsp_op_read_reg(reg, RCX, ZERO);
|
||||
dsp_op_read_reg(DSP_REG_CR, RAX, ZERO);
|
||||
SHL(16, R(EAX), Imm8(8));
|
||||
OR(8, R(EAX), Imm8(opc & 0xFF));
|
||||
dmem_write();
|
||||
|
@ -57,23 +50,12 @@ void DSPEmitter::srs(const UDSPInstruction opc)
|
|||
void DSPEmitter::lrs(const UDSPInstruction opc)
|
||||
{
|
||||
u8 reg = ((opc >> 8) & 0x7) + 0x18;
|
||||
u16 *regp = reg_ptr(reg);
|
||||
//u16 addr = (g_dsp.r[DSP_REG_CR] << 8) | (opc & 0xFF);
|
||||
#ifdef _M_IX86 // All32
|
||||
MOVZX(32, 8, ECX, M(&g_dsp.r.cr));
|
||||
dsp_op_read_reg(DSP_REG_CR, RCX, ZERO);
|
||||
SHL(16, R(ECX), Imm8(8));
|
||||
OR(8, R(ECX), Imm8(opc & 0xFF));
|
||||
dmem_read();
|
||||
MOV(16, M(regp), R(EAX));
|
||||
#else
|
||||
// MOV(64, R(R11), ImmPtr(&g_dsp.r));
|
||||
MOVZX(64, 8, RCX, MDisp(R11, STRUCT_OFFSET(g_dsp.r, cr)));
|
||||
SHL(16, R(ECX), Imm8(8));
|
||||
OR(8, R(ECX), Imm8(opc & 0xFF));
|
||||
dmem_read();
|
||||
// MOV(64, R(R11), ImmPtr(&g_dsp.r));
|
||||
MOV(16, MDisp(R11, PtrOffset(regp, &g_dsp.r)), R(RAX));
|
||||
#endif
|
||||
dsp_op_write_reg(reg, RAX);
|
||||
dsp_conditional_extend_accum(reg);
|
||||
}
|
||||
|
||||
|
@ -194,12 +176,7 @@ void DSPEmitter::srr(const UDSPInstruction opc)
|
|||
u8 sreg = opc & 0x1f;
|
||||
|
||||
dsp_op_read_reg(sreg, ECX);
|
||||
#ifdef _M_IX86 // All32
|
||||
MOVZX(32, 16, EAX, M(&g_dsp.r.ar[dreg]));
|
||||
#else
|
||||
// MOV(64, R(R11), ImmPtr(&g_dsp.r));
|
||||
MOVZX(64, 16, RAX, MDisp(R11, STRUCT_OFFSET(g_dsp.r, ar[dreg])));
|
||||
#endif
|
||||
dsp_op_read_reg(dreg, RAX, ZERO);
|
||||
dmem_write();
|
||||
}
|
||||
|
||||
|
@ -214,12 +191,7 @@ void DSPEmitter::srrd(const UDSPInstruction opc)
|
|||
u8 sreg = opc & 0x1f;
|
||||
|
||||
dsp_op_read_reg(sreg, ECX);
|
||||
#ifdef _M_IX86 // All32
|
||||
MOVZX(32, 16, EAX, M(&g_dsp.r.ar[dreg]));
|
||||
#else
|
||||
// MOV(64, R(R11), ImmPtr(&g_dsp.r));
|
||||
MOVZX(64, 16, RAX, MDisp(R11, STRUCT_OFFSET(g_dsp.r, ar[dreg])));
|
||||
#endif
|
||||
dsp_op_read_reg(dreg, RAX, ZERO);
|
||||
dmem_write();
|
||||
decrement_addr_reg(dreg);
|
||||
}
|
||||
|
@ -235,12 +207,7 @@ void DSPEmitter::srri(const UDSPInstruction opc)
|
|||
u8 sreg = opc & 0x1f;
|
||||
|
||||
dsp_op_read_reg(sreg, ECX);
|
||||
#ifdef _M_IX86 // All32
|
||||
MOVZX(32, 16, EAX, M(&g_dsp.r.ar[dreg]));
|
||||
#else
|
||||
// MOV(64, R(R11), ImmPtr(&g_dsp.r));
|
||||
MOVZX(64, 16, RAX, MDisp(R11, STRUCT_OFFSET(g_dsp.r, ar[dreg])));
|
||||
#endif
|
||||
dsp_op_read_reg(dreg, RAX, ZERO);
|
||||
dmem_write();
|
||||
increment_addr_reg(dreg);
|
||||
}
|
||||
|
@ -256,12 +223,7 @@ void DSPEmitter::srrn(const UDSPInstruction opc)
|
|||
u8 sreg = opc & 0x1f;
|
||||
|
||||
dsp_op_read_reg(sreg, ECX);
|
||||
#ifdef _M_IX86 // All32
|
||||
MOVZX(32, 16, EAX, M(&g_dsp.r.ar[dreg]));
|
||||
#else
|
||||
// MOV(64, R(R11), ImmPtr(&g_dsp.r));
|
||||
MOVZX(64, 16, RAX, MDisp(R11, STRUCT_OFFSET(g_dsp.r, ar[dreg])));
|
||||
#endif
|
||||
dsp_op_read_reg(dreg, RAX, ZERO);
|
||||
dmem_write();
|
||||
increase_addr_reg(dreg);
|
||||
}
|
||||
|
@ -275,19 +237,9 @@ void DSPEmitter::ilrr(const UDSPInstruction opc)
|
|||
u16 reg = opc & 0x3;
|
||||
u16 dreg = (opc >> 8) & 1;
|
||||
|
||||
#ifdef _M_IX86 // All32
|
||||
MOVZX(32, 16, ECX, M(&g_dsp.r.ar[reg]));
|
||||
#else
|
||||
// MOV(64, R(R11), ImmPtr(&g_dsp.r));
|
||||
MOVZX(64, 16, RCX, MDisp(R11, STRUCT_OFFSET(g_dsp.r, ar[reg])));
|
||||
#endif
|
||||
dsp_op_read_reg(reg, RCX, ZERO);
|
||||
imem_read();
|
||||
#ifdef _M_IX86 // All32
|
||||
MOV(16, M(&g_dsp.r.ac[dreg].m), R(EAX));
|
||||
#else
|
||||
// MOV(64, R(R11), ImmPtr(&g_dsp.r));
|
||||
MOV(16, MDisp(R11, STRUCT_OFFSET(g_dsp.r, ac[dreg].m)), R(RAX));
|
||||
#endif
|
||||
set_acc_m(dreg, R(RAX));
|
||||
dsp_conditional_extend_accum(dreg);
|
||||
}
|
||||
|
||||
|
@ -300,19 +252,9 @@ void DSPEmitter::ilrrd(const UDSPInstruction opc)
|
|||
u16 reg = opc & 0x3;
|
||||
u16 dreg = (opc >> 8) & 1;
|
||||
|
||||
#ifdef _M_IX86 // All32
|
||||
MOVZX(32, 16, ECX, M(&g_dsp.r.ar[reg]));
|
||||
#else
|
||||
// MOV(64, R(R11), ImmPtr(&g_dsp.r));
|
||||
MOVZX(64, 16, RCX, MDisp(R11, STRUCT_OFFSET(g_dsp.r, ar[reg])));
|
||||
#endif
|
||||
dsp_op_read_reg(reg, RCX, ZERO);
|
||||
imem_read();
|
||||
#ifdef _M_IX86 // All32
|
||||
MOV(16, M(&g_dsp.r.ac[dreg].m), R(EAX));
|
||||
#else
|
||||
// MOV(64, R(R11), ImmPtr(&g_dsp.r));
|
||||
MOV(16, MDisp(R11, STRUCT_OFFSET(g_dsp.r, ac[dreg].m)), R(RAX));
|
||||
#endif
|
||||
set_acc_m(dreg, R(RAX));
|
||||
dsp_conditional_extend_accum(dreg);
|
||||
decrement_addr_reg(reg);
|
||||
}
|
||||
|
@ -326,19 +268,9 @@ void DSPEmitter::ilrri(const UDSPInstruction opc)
|
|||
u16 reg = opc & 0x3;
|
||||
u16 dreg = (opc >> 8) & 1;
|
||||
|
||||
#ifdef _M_IX86 // All32
|
||||
MOVZX(32, 16, ECX, M(&g_dsp.r.ar[reg]));
|
||||
#else
|
||||
// MOV(64, R(R11), ImmPtr(&g_dsp.r));
|
||||
MOVZX(64, 16, RCX, MDisp(R11, STRUCT_OFFSET(g_dsp.r, ar[reg])));
|
||||
#endif
|
||||
dsp_op_read_reg(reg, RCX, ZERO);
|
||||
imem_read();
|
||||
#ifdef _M_IX86 // All32
|
||||
MOV(16, M(&g_dsp.r.ac[dreg].m), R(EAX));
|
||||
#else
|
||||
// MOV(64, R(R11), ImmPtr(&g_dsp.r));
|
||||
MOV(16, MDisp(R11, STRUCT_OFFSET(g_dsp.r, ac[dreg].m)), R(RAX));
|
||||
#endif
|
||||
set_acc_m(dreg, R(RAX));
|
||||
dsp_conditional_extend_accum(dreg);
|
||||
increment_addr_reg(reg);
|
||||
}
|
||||
|
@ -353,19 +285,9 @@ void DSPEmitter::ilrrn(const UDSPInstruction opc)
|
|||
u16 reg = opc & 0x3;
|
||||
u16 dreg = (opc >> 8) & 1;
|
||||
|
||||
#ifdef _M_IX86 // All32
|
||||
MOVZX(32, 16, ECX, M(&g_dsp.r.ar[reg]));
|
||||
#else
|
||||
// MOV(64, R(R11), ImmPtr(&g_dsp.r));
|
||||
MOVZX(64, 16, RCX, MDisp(R11, STRUCT_OFFSET(g_dsp.r, ar[reg])));
|
||||
#endif
|
||||
dsp_op_read_reg(reg, RCX, ZERO);
|
||||
imem_read();
|
||||
#ifdef _M_IX86 // All32
|
||||
MOV(16, M(&g_dsp.r.ac[dreg].m), R(EAX));
|
||||
#else
|
||||
// MOV(64, R(R11), ImmPtr(&g_dsp.r));
|
||||
MOV(16, MDisp(R11, STRUCT_OFFSET(g_dsp.r, ac[dreg].m)), R(RAX));
|
||||
#endif
|
||||
set_acc_m(dreg, R(RAX));
|
||||
dsp_conditional_extend_accum(dreg);
|
||||
increase_addr_reg(reg);
|
||||
}
|
||||
|
|
|
@ -25,9 +25,9 @@ using namespace Gen;
|
|||
|
||||
//clobbers:
|
||||
//EAX = (s8)g_dsp.reg_stack_ptr[stack_reg]
|
||||
//R10 = &g_dsp.reg_stack[stack_reg][0]
|
||||
//R11 = &g_dsp.r
|
||||
//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)
|
||||
{
|
||||
//g_dsp.reg_stack_ptr[stack_reg]++;
|
||||
|
@ -35,15 +35,16 @@ void DSPEmitter::dsp_reg_stack_push(int stack_reg)
|
|||
#ifdef _M_IX86 // All32
|
||||
MOV(8, R(AL), M(&g_dsp.reg_stack_ptr[stack_reg]));
|
||||
#else
|
||||
MOV(64, R(R10), ImmPtr(g_dsp.reg_stack_ptr));
|
||||
MOV(8, R(AL), MDisp(R10, stack_reg));
|
||||
MOV(8, R(AL), MDisp(R11, PtrOffset(&g_dsp.reg_stack_ptr[stack_reg],
|
||||
&g_dsp.r)));
|
||||
#endif
|
||||
ADD(8, R(AL), Imm8(1));
|
||||
AND(8, R(AL), Imm8(DSP_STACK_MASK));
|
||||
#ifdef _M_IX86 // All32
|
||||
MOV(8, M(&g_dsp.reg_stack_ptr[stack_reg]), R(AL));
|
||||
#else
|
||||
MOV(8, MDisp(R10, stack_reg), R(AL));
|
||||
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];
|
||||
|
@ -55,24 +56,25 @@ void DSPEmitter::dsp_reg_stack_push(int stack_reg)
|
|||
// 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));
|
||||
MOV(64, R(R10), ImmPtr(&g_dsp.reg_stack[stack_reg][0]));
|
||||
MOV(16, MComplex(R10, RAX, 2, 0), R(CX));
|
||||
MOV(16, MComplex(R11, RAX, 2,
|
||||
PtrOffset(&g_dsp.reg_stack[stack_reg][0],&g_dsp.r)),
|
||||
R(CX));
|
||||
#endif
|
||||
}
|
||||
|
||||
//clobbers:
|
||||
//EAX = (s8)g_dsp.reg_stack_ptr[stack_reg]
|
||||
//R10 = &g_dsp.reg_stack[stack_reg][0]
|
||||
//R11 = &g_dsp.r
|
||||
//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)
|
||||
{
|
||||
//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]));
|
||||
#else
|
||||
MOV(64, R(R10), ImmPtr(g_dsp.reg_stack_ptr));
|
||||
MOV(8, R(AL), MDisp(R10, stack_reg));
|
||||
MOV(8, R(AL),
|
||||
MDisp(R11, PtrOffset(&g_dsp.reg_stack_ptr[stack_reg],&g_dsp.r)));
|
||||
#endif
|
||||
#ifdef _M_IX86 // All32
|
||||
MOVZX(32, 8, EAX, R(AL));
|
||||
|
@ -80,9 +82,9 @@ void DSPEmitter::dsp_reg_stack_pop(int stack_reg)
|
|||
MOV(16, M(&g_dsp.r.st[stack_reg]), R(CX));
|
||||
#else
|
||||
MOVZX(64, 8, RAX, R(AL));
|
||||
MOV(64, R(R10), ImmPtr(&g_dsp.reg_stack[stack_reg][0]));
|
||||
MOV(16, R(CX), MComplex(R10, RAX, 2, 0));
|
||||
// MOV(64, R(R11), ImmPtr(&g_dsp.r));
|
||||
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
|
||||
|
||||
|
@ -93,8 +95,8 @@ void DSPEmitter::dsp_reg_stack_pop(int stack_reg)
|
|||
#ifdef _M_IX86 // All32
|
||||
MOV(8, M(&g_dsp.reg_stack_ptr[stack_reg]), R(AL));
|
||||
#else
|
||||
MOV(64, R(R10), ImmPtr(g_dsp.reg_stack_ptr));
|
||||
MOV(8, MDisp(R10, stack_reg), R(AL));
|
||||
MOV(8, MDisp(R11, PtrOffset(&g_dsp.reg_stack_ptr[stack_reg],&g_dsp.r)),
|
||||
R(AL));
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -144,17 +146,10 @@ void DSPEmitter::dsp_reg_store_stack_imm(int stack_reg, u16 val)
|
|||
void DSPEmitter::dsp_op_write_reg(int reg, Gen::X64Reg host_sreg)
|
||||
{
|
||||
switch (reg & 0x1f) {
|
||||
// 8-bit sign extended registers. Should look at prod.h too...
|
||||
// 8-bit sign extended registers.
|
||||
case DSP_REG_ACH0:
|
||||
case DSP_REG_ACH1:
|
||||
// sign extend from the bottom 8 bits.
|
||||
MOVSX(16, 8, host_sreg, R(host_sreg));
|
||||
#ifdef _M_IX86 // All32
|
||||
MOV(16, M(&g_dsp.r.ac[reg-DSP_REG_ACH0].h), R(host_sreg));
|
||||
#else
|
||||
// MOV(64, R(R11), ImmPtr(&g_dsp.r));
|
||||
MOV(16, MDisp(R11, STRUCT_OFFSET(g_dsp.r, ac[reg-DSP_REG_ACH0].h)), R(host_sreg));
|
||||
#endif
|
||||
gpr.writeReg(reg, R(host_sreg));
|
||||
break;
|
||||
|
||||
// Stack registers.
|
||||
|
@ -166,17 +161,9 @@ void DSPEmitter::dsp_op_write_reg(int reg, Gen::X64Reg host_sreg)
|
|||
break;
|
||||
|
||||
default:
|
||||
{
|
||||
u16 *regp = reg_ptr(reg);
|
||||
#ifdef _M_IX86 // All32
|
||||
MOV(16, M(regp), R(host_sreg));
|
||||
#else
|
||||
// MOV(64, R(R11), ImmPtr(&g_dsp.r));
|
||||
MOV(16, MDisp(R11, PtrOffset(regp, &g_dsp.r)), R(host_sreg));
|
||||
#endif
|
||||
gpr.writeReg(reg, R(host_sreg));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DSPEmitter::dsp_op_write_reg_imm(int reg, u16 val)
|
||||
|
@ -185,15 +172,8 @@ void DSPEmitter::dsp_op_write_reg_imm(int reg, u16 val)
|
|||
// 8-bit sign extended registers. Should look at prod.h too...
|
||||
case DSP_REG_ACH0:
|
||||
case DSP_REG_ACH1:
|
||||
// sign extend from the bottom 8 bits.
|
||||
#ifdef _M_IX86 // All32
|
||||
MOV(16, M(&g_dsp.r.ac[reg-DSP_REG_ACH0].h), Imm16((u16)(s16)(s8)(u8)val));
|
||||
#else
|
||||
// MOV(64, R(R11), ImmPtr(&g_dsp.r));
|
||||
MOV(16, MDisp(R11, STRUCT_OFFSET(g_dsp.r, ac[reg-DSP_REG_ACH0].h)), Imm16((u16)(s16)(s8)(u8)val));
|
||||
#endif
|
||||
gpr.writeReg(reg, Imm16((u16)(s16)(s8)(u8)val));
|
||||
break;
|
||||
|
||||
// Stack registers.
|
||||
case DSP_REG_ST0:
|
||||
case DSP_REG_ST1:
|
||||
|
@ -203,17 +183,9 @@ void DSPEmitter::dsp_op_write_reg_imm(int reg, u16 val)
|
|||
break;
|
||||
|
||||
default:
|
||||
{
|
||||
u16 *regp = reg_ptr(reg);
|
||||
#ifdef _M_IX86 // All32
|
||||
MOV(16, M(regp), Imm16(val));
|
||||
#else
|
||||
// MOV(64, R(R11), ImmPtr(&g_dsp.r));
|
||||
MOV(16, MDisp(R11, PtrOffset(regp, &g_dsp.r)), Imm16(val));
|
||||
#endif
|
||||
gpr.writeReg(reg, Imm16(val));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DSPEmitter::dsp_conditional_extend_accum(int reg)
|
||||
|
@ -223,37 +195,25 @@ void DSPEmitter::dsp_conditional_extend_accum(int reg)
|
|||
case DSP_REG_ACM0:
|
||||
case DSP_REG_ACM1:
|
||||
{
|
||||
#ifdef _M_IX86 // All32
|
||||
MOV(16, R(EAX), M(&g_dsp.r.sr));
|
||||
#else
|
||||
// MOV(64, R(R11), ImmPtr(&g_dsp.r));
|
||||
MOV(16, R(EAX), MDisp(R11, STRUCT_OFFSET(g_dsp.r, sr)));
|
||||
#endif
|
||||
TEST(16, R(EAX), Imm16(SR_40_MODE_BIT));
|
||||
FixupBranch not_40bit = J_CC(CC_Z);
|
||||
OpArg sr_reg;
|
||||
gpr.getReg(DSP_REG_SR,sr_reg);
|
||||
DSPJitRegCache c(gpr);
|
||||
TEST(16, sr_reg, Imm16(SR_40_MODE_BIT));
|
||||
FixupBranch not_40bit = J_CC(CC_Z,true);
|
||||
//if (g_dsp.r[DSP_REG_SR] & SR_40_MODE_BIT)
|
||||
//{
|
||||
// Sign extend into whole accum.
|
||||
//u16 val = g_dsp.r[reg];
|
||||
#ifdef _M_IX86 // All32
|
||||
MOVSX(32, 16, EAX, M(&g_dsp.r.ac[reg-DSP_REG_ACM0].m));
|
||||
#else
|
||||
MOVSX(64, 16, EAX, MDisp(R11, STRUCT_OFFSET(g_dsp.r, ac[reg-DSP_REG_ACM0].m)));
|
||||
#endif
|
||||
get_acc_m(reg - DSP_REG_ACM0, EAX);
|
||||
SHR(32, R(EAX), Imm8(16));
|
||||
//g_dsp.r[reg - DSP_REG_ACM0 + DSP_REG_ACH0] = (val & 0x8000) ? 0xFFFF : 0x0000;
|
||||
//g_dsp.r[reg - DSP_REG_ACM0 + DSP_REG_ACL0] = 0;
|
||||
#ifdef _M_IX86 // All32
|
||||
MOV(16, M(&g_dsp.r.ac[reg - DSP_REG_ACM0].h),
|
||||
R(EAX));
|
||||
MOV(16, M(&g_dsp.r.ac[reg - DSP_REG_ACM0].l),
|
||||
Imm16(0));
|
||||
#else
|
||||
MOV(16, MDisp(R11, STRUCT_OFFSET(g_dsp.r, ac[reg-DSP_REG_ACM0].h)), R(EAX));
|
||||
MOV(16, MDisp(R11, STRUCT_OFFSET(g_dsp.r, ac[reg-DSP_REG_ACM0].l)), Imm16(0));
|
||||
#endif
|
||||
set_acc_h(reg - DSP_REG_ACM0, R(RAX));
|
||||
set_acc_l(reg - DSP_REG_ACM0, Imm16(0));
|
||||
//}
|
||||
gpr.flushRegs(c);
|
||||
SetJumpTarget(not_40bit);
|
||||
gpr.putReg(DSP_REG_SR);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -265,55 +225,57 @@ void DSPEmitter::dsp_conditional_extend_accum_imm(int reg, u16 val)
|
|||
case DSP_REG_ACM0:
|
||||
case DSP_REG_ACM1:
|
||||
{
|
||||
#ifdef _M_IX86 // All32
|
||||
MOV(16, R(EAX), M(&g_dsp.r.sr));
|
||||
#else
|
||||
// MOV(64, R(R11), ImmPtr(&g_dsp.r));
|
||||
MOV(16, R(EAX), MDisp(R11, STRUCT_OFFSET(g_dsp.r, sr)));
|
||||
#endif
|
||||
TEST(16, R(EAX), Imm16(SR_40_MODE_BIT));
|
||||
OpArg sr_reg;
|
||||
gpr.getReg(DSP_REG_SR,sr_reg);
|
||||
DSPJitRegCache c(gpr);
|
||||
TEST(16, sr_reg, Imm16(SR_40_MODE_BIT));
|
||||
FixupBranch not_40bit = J_CC(CC_Z);
|
||||
//if (g_dsp.r[DSP_REG_SR] & SR_40_MODE_BIT)
|
||||
//{
|
||||
// Sign extend into whole accum.
|
||||
//g_dsp.r[reg - DSP_REG_ACM0 + DSP_REG_ACH0] = (val & 0x8000) ? 0xFFFF : 0x0000;
|
||||
//g_dsp.r[reg - DSP_REG_ACM0 + DSP_REG_ACL0] = 0;
|
||||
#ifdef _M_IX86 // All32
|
||||
MOV(16, M(&g_dsp.r.ac[reg - DSP_REG_ACM0].h),
|
||||
Imm16((val & 0x8000)?0xffff:0x0000));
|
||||
MOV(16, M(&g_dsp.r.ac[reg - DSP_REG_ACM0].l),
|
||||
Imm16(0));
|
||||
#else
|
||||
MOV(16, MDisp(R11, STRUCT_OFFSET(g_dsp.r, ac[reg-DSP_REG_ACM0].h)),
|
||||
Imm16((val & 0x8000)?0xffff:0x0000));
|
||||
MOV(16, MDisp(R11, STRUCT_OFFSET(g_dsp.r, ac[reg-DSP_REG_ACM0].l)),
|
||||
Imm16(0));
|
||||
#endif
|
||||
set_acc_h(reg - DSP_REG_ACM0, Imm16((val & 0x8000)?0xffff:0x0000));
|
||||
set_acc_l(reg - DSP_REG_ACM0, Imm16(0));
|
||||
//}
|
||||
gpr.flushRegs(c);
|
||||
SetJumpTarget(not_40bit);
|
||||
gpr.putReg(DSP_REG_SR);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DSPEmitter::dsp_op_read_reg(int reg, Gen::X64Reg host_dreg)
|
||||
void DSPEmitter::dsp_op_read_reg(int reg, Gen::X64Reg host_dreg, DSPJitSignExtend extend)
|
||||
{
|
||||
switch (reg & 0x1f) {
|
||||
case DSP_REG_ST0:
|
||||
case DSP_REG_ST1:
|
||||
case DSP_REG_ST2:
|
||||
case DSP_REG_ST3:
|
||||
return dsp_reg_load_stack(reg - DSP_REG_ST0, host_dreg);
|
||||
default:
|
||||
{
|
||||
u16 *regp = reg_ptr(reg);
|
||||
//return g_dsp.r[reg];
|
||||
dsp_reg_load_stack(reg - DSP_REG_ST0, host_dreg);
|
||||
switch(extend) {
|
||||
case SIGN:
|
||||
#ifdef _M_IX86 // All32
|
||||
MOV(16, R(host_dreg), M(regp));
|
||||
MOVSX(32, 16, host_dreg, R(host_dreg));
|
||||
#else
|
||||
// MOV(64, R(R11), ImmPtr(&g_dsp.r));
|
||||
MOV(16, R(host_dreg), MDisp(R11, PtrOffset(regp, &g_dsp.r)));
|
||||
MOVSX(64, 16, host_dreg, R(host_dreg));
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
case ZERO:
|
||||
#ifdef _M_IX86 // All32
|
||||
MOVZX(32, 16, host_dreg, R(host_dreg));
|
||||
#else
|
||||
MOVZX(64, 16, host_dreg, R(host_dreg));
|
||||
#endif
|
||||
break;
|
||||
case NONE:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return;
|
||||
default:
|
||||
gpr.readReg(reg, host_dreg, extend);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -424,12 +386,10 @@ void DSPEmitter::addarn(const UDSPInstruction opc)
|
|||
void DSPEmitter::setCompileSR(u16 bit) {
|
||||
|
||||
// g_dsp.r[DSP_REG_SR] |= bit
|
||||
#ifdef _M_IX86 // All32
|
||||
OR(16, M(&g_dsp.r.sr), Imm16(bit));
|
||||
#else
|
||||
// MOV(64, R(R11), ImmPtr(&g_dsp.r));
|
||||
OR(16, MDisp(R11, STRUCT_OFFSET(g_dsp.r, sr)), Imm16(bit));
|
||||
#endif
|
||||
OpArg sr_reg;
|
||||
gpr.getReg(DSP_REG_SR,sr_reg);
|
||||
OR(16, sr_reg, Imm16(bit));
|
||||
gpr.putReg(DSP_REG_SR);
|
||||
|
||||
compileSR |= bit;
|
||||
}
|
||||
|
@ -437,12 +397,10 @@ void DSPEmitter::setCompileSR(u16 bit) {
|
|||
void DSPEmitter::clrCompileSR(u16 bit) {
|
||||
|
||||
// g_dsp.r[DSP_REG_SR] &= bit
|
||||
#ifdef _M_IX86 // All32
|
||||
AND(16, M(&g_dsp.r.sr), Imm16(~bit));
|
||||
#else
|
||||
// MOV(64, R(R11), ImmPtr(&g_dsp.r));
|
||||
AND(16, MDisp(R11, STRUCT_OFFSET(g_dsp.r, sr)), Imm16(~bit));
|
||||
#endif
|
||||
OpArg sr_reg;
|
||||
gpr.getReg(DSP_REG_SR,sr_reg);
|
||||
AND(16, sr_reg, Imm16(~bit));
|
||||
gpr.putReg(DSP_REG_SR);
|
||||
|
||||
compileSR &= ~bit;
|
||||
}
|
||||
|
|
|
@ -41,11 +41,14 @@ void DSPEmitter::multiply()
|
|||
|
||||
// Conditionally multiply by 2.
|
||||
// if ((g_dsp.r.sr & SR_MUL_MODIFY) == 0)
|
||||
TEST(16, MDisp(R11, STRUCT_OFFSET(g_dsp.r, sr)), Imm16(SR_MUL_MODIFY));
|
||||
OpArg sr_reg;
|
||||
gpr.getReg(DSP_REG_SR,sr_reg);
|
||||
TEST(16, sr_reg, Imm16(SR_MUL_MODIFY));
|
||||
FixupBranch noMult2 = J_CC(CC_NZ);
|
||||
// prod <<= 1;
|
||||
SHL(64, R(EAX), Imm8(1));
|
||||
SetJumpTarget(noMult2);
|
||||
gpr.putReg(DSP_REG_SR);
|
||||
// return prod;
|
||||
#endif
|
||||
}
|
||||
|
@ -93,7 +96,9 @@ void DSPEmitter::multiply_mulx(u8 axh0, u8 axh1)
|
|||
|
||||
|
||||
// if ((sign == 1) && (g_dsp.r.sr & SR_MUL_UNSIGNED)) //unsigned
|
||||
TEST(16, MDisp(R11, STRUCT_OFFSET(g_dsp.r, sr)), Imm16(SR_MUL_UNSIGNED));
|
||||
OpArg sr_reg;
|
||||
gpr.getReg(DSP_REG_SR,sr_reg);
|
||||
TEST(16, sr_reg, Imm16(SR_MUL_UNSIGNED));
|
||||
FixupBranch unsignedMul = J_CC(CC_NZ);
|
||||
// prod = (s16)a * (s16)b; //signed
|
||||
MOVSX(64, 16, RAX, R(RDI));
|
||||
|
@ -135,11 +140,12 @@ void DSPEmitter::multiply_mulx(u8 axh0, u8 axh1)
|
|||
|
||||
// Conditionally multiply by 2.
|
||||
// if ((g_dsp.r.sr & SR_MUL_MODIFY) == 0)
|
||||
TEST(16, MDisp(R11, STRUCT_OFFSET(g_dsp.r, sr)), Imm16(SR_MUL_MODIFY));
|
||||
TEST(16, sr_reg, Imm16(SR_MUL_MODIFY));
|
||||
FixupBranch noMult2 = J_CC(CC_NZ);
|
||||
// prod <<= 1;
|
||||
SHL(64, R(RAX), Imm8(1));
|
||||
SetJumpTarget(noMult2);
|
||||
gpr.putReg(DSP_REG_SR);
|
||||
// return prod;
|
||||
}
|
||||
|
||||
|
@ -158,14 +164,12 @@ void DSPEmitter::clrp(const UDSPInstruction opc)
|
|||
{
|
||||
#ifdef _M_X64
|
||||
// g_dsp.r[DSP_REG_PRODL] = 0x0000;
|
||||
// MOV(64, R(R11), ImmPtr(&g_dsp.r));
|
||||
MOV(16, MDisp(R11, STRUCT_OFFSET(g_dsp.r, prod.l)), Imm16(0x0000));
|
||||
// g_dsp.r[DSP_REG_PRODM] = 0xfff0;
|
||||
MOV(16, MDisp(R11, STRUCT_OFFSET(g_dsp.r, prod.m)), Imm16(0xfff0));
|
||||
// g_dsp.r[DSP_REG_PRODH] = 0x00ff;
|
||||
MOV(16, MDisp(R11, STRUCT_OFFSET(g_dsp.r, prod.h)), Imm16(0x00ff));
|
||||
// g_dsp.r[DSP_REG_PRODM2] = 0x0010;
|
||||
MOV(16, MDisp(R11, STRUCT_OFFSET(g_dsp.r, prod.m2)), Imm16(0x0010));
|
||||
//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, MDisp(R11, STRUCT_OFFSET(g_dsp.r, prod.val)+4), Imm32(0x001000ffU));
|
||||
#else
|
||||
Default(opc);
|
||||
#endif
|
||||
|
@ -319,8 +323,7 @@ void DSPEmitter::mulaxh(const UDSPInstruction opc)
|
|||
{
|
||||
#ifdef _M_X64
|
||||
// s64 prod = dsp_multiply(dsp_get_ax_h(0), dsp_get_ax_h(0));
|
||||
// MOV(64, R(R11), ImmPtr(&g_dsp.r));
|
||||
MOVSX(64, 16, RSI, MDisp(R11, STRUCT_OFFSET(g_dsp.r, ax[0].h)));
|
||||
dsp_op_read_reg(DSP_REG_AXH0, RSI, SIGN);
|
||||
MOV(64, R(RDI), R(RSI));
|
||||
multiply();
|
||||
// dsp_set_long_prod(prod);
|
||||
|
@ -342,10 +345,9 @@ void DSPEmitter::mul(const UDSPInstruction opc)
|
|||
u8 sreg = (opc >> 11) & 0x1;
|
||||
|
||||
// u16 axl = dsp_get_ax_l(sreg);
|
||||
// MOV(64, R(R11), ImmPtr(&g_dsp.r));
|
||||
MOVSX(64, 16, RSI, MDisp(R11, STRUCT_OFFSET(g_dsp.r, ax[sreg].l)));
|
||||
dsp_op_read_reg(DSP_REG_AXL0+sreg, RSI, SIGN);
|
||||
// u16 axh = dsp_get_ax_h(sreg);
|
||||
MOVSX(64, 16, RDI, MDisp(R11, STRUCT_OFFSET(g_dsp.r, ax[sreg].h)));
|
||||
dsp_op_read_reg(DSP_REG_AXH0+sreg, RDI, SIGN);
|
||||
// s64 prod = dsp_multiply(axh, axl);
|
||||
multiply();
|
||||
// dsp_set_long_prod(prod);
|
||||
|
@ -375,9 +377,9 @@ void DSPEmitter::mulac(const UDSPInstruction opc)
|
|||
ADD(64, R(RAX), R(RDX));
|
||||
PUSH(64, R(RAX));
|
||||
// u16 axl = dsp_get_ax_l(sreg);
|
||||
MOVSX(64, 16, RSI, MDisp(R11, STRUCT_OFFSET(g_dsp.r, ax[sreg].l)));
|
||||
dsp_op_read_reg(DSP_REG_AXL0+sreg, RSI, SIGN);
|
||||
// u16 axh = dsp_get_ax_h(sreg);
|
||||
MOVSX(64, 16, RDI, MDisp(R11, STRUCT_OFFSET(g_dsp.r, ax[sreg].h)));
|
||||
dsp_op_read_reg(DSP_REG_AXH0+sreg, RDI, SIGN);
|
||||
// s64 prod = dsp_multiply(axl, axh);
|
||||
multiply();
|
||||
// dsp_set_long_prod(prod);
|
||||
|
@ -463,14 +465,12 @@ void DSPEmitter::mulx(const UDSPInstruction opc)
|
|||
#ifdef _M_X64
|
||||
u8 treg = ((opc >> 11) & 0x1);
|
||||
u8 sreg = ((opc >> 12) & 0x1);
|
||||
u16 *sregp = reg_ptr(DSP_REG_AXL0 + sreg*2);
|
||||
u16 *tregp = reg_ptr(DSP_REG_AXL1 + treg*2);
|
||||
|
||||
// MOV(64, R(R11), ImmPtr(&g_dsp.r));
|
||||
// u16 val1 = (sreg == 0) ? dsp_get_ax_l(0) : dsp_get_ax_h(0);
|
||||
MOVSX(64, 16, RSI, MDisp(R11, PtrOffset(sregp,&g_dsp.r)));
|
||||
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);
|
||||
MOVSX(64, 16, RDI, MDisp(R11, PtrOffset(tregp,&g_dsp.r)));
|
||||
dsp_op_read_reg(DSP_REG_AXL1 + treg*2, RDI, SIGN);
|
||||
// s64 prod = dsp_multiply_mulx(sreg, treg, val1, val2);
|
||||
multiply_mulx(sreg, treg);
|
||||
// dsp_set_long_prod(prod);
|
||||
|
@ -493,17 +493,15 @@ void DSPEmitter::mulxac(const UDSPInstruction opc)
|
|||
u8 rreg = (opc >> 8) & 0x1;
|
||||
u8 treg = (opc >> 11) & 0x1;
|
||||
u8 sreg = (opc >> 12) & 0x1;
|
||||
u16 *sregp = reg_ptr(DSP_REG_AXL0 + sreg*2);
|
||||
u16 *tregp = reg_ptr(DSP_REG_AXL1 + treg*2);
|
||||
|
||||
// s64 acc = dsp_get_long_acc(rreg) + dsp_get_long_prod();
|
||||
get_long_acc(rreg, RCX);
|
||||
get_long_prod();
|
||||
ADD(64, R(RCX), R(RAX));
|
||||
// u16 val1 = (sreg == 0) ? dsp_get_ax_l(0) : dsp_get_ax_h(0);
|
||||
MOVSX(64, 16, RSI, MDisp(R11, PtrOffset(sregp, &g_dsp.r)));
|
||||
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);
|
||||
MOVSX(64, 16, RDI, MDisp(R11, PtrOffset(tregp, &g_dsp.r)));
|
||||
dsp_op_read_reg(DSP_REG_AXL1 + treg*2, RDI, SIGN);
|
||||
// s64 prod = dsp_multiply_mulx(sreg, treg, val1, val2);
|
||||
multiply_mulx(sreg, treg);
|
||||
|
||||
|
@ -534,15 +532,13 @@ void DSPEmitter::mulxmv(const UDSPInstruction opc)
|
|||
u8 rreg = ((opc >> 8) & 0x1);
|
||||
u8 treg = (opc >> 11) & 0x1;
|
||||
u8 sreg = (opc >> 12) & 0x1;
|
||||
u16 *sregp = reg_ptr(DSP_REG_AXL0 + sreg*2);
|
||||
u16 *tregp = reg_ptr(DSP_REG_AXL1 + treg*2);
|
||||
|
||||
// s64 acc = dsp_get_long_prod();
|
||||
get_long_prod(RCX);
|
||||
// u16 val1 = (sreg == 0) ? dsp_get_ax_l(0) : dsp_get_ax_h(0);
|
||||
MOVSX(64, 16, RSI, MDisp(R11, PtrOffset(sregp, &g_dsp.r)));
|
||||
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);
|
||||
MOVSX(64, 16, RDI, MDisp(R11, PtrOffset(tregp, &g_dsp.r)));
|
||||
dsp_op_read_reg(DSP_REG_AXL1 + treg*2, RDI, SIGN);
|
||||
// s64 prod = dsp_multiply_mulx(sreg, treg, val1, val2);
|
||||
multiply_mulx(sreg, treg);
|
||||
|
||||
|
@ -574,15 +570,13 @@ void DSPEmitter::mulxmvz(const UDSPInstruction opc)
|
|||
u8 rreg = (opc >> 8) & 0x1;
|
||||
u8 treg = (opc >> 11) & 0x1;
|
||||
u8 sreg = (opc >> 12) & 0x1;
|
||||
u16 *sregp = reg_ptr(DSP_REG_AXL0 + sreg*2);
|
||||
u16 *tregp = reg_ptr(DSP_REG_AXL1 + treg*2);
|
||||
|
||||
// s64 acc = dsp_get_long_prod_round_prodl();
|
||||
get_long_prod_round_prodl(RCX);
|
||||
// u16 val1 = (sreg == 0) ? dsp_get_ax_l(0) : dsp_get_ax_h(0);
|
||||
MOVSX(64, 16, RSI, MDisp(R11, PtrOffset(sregp, &g_dsp.r)));
|
||||
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);
|
||||
MOVSX(64, 16, RDI, MDisp(R11, PtrOffset(tregp, &g_dsp.r)));
|
||||
dsp_op_read_reg(DSP_REG_AXL1 + treg*2, RDI, SIGN);
|
||||
// s64 prod = dsp_multiply_mulx(sreg, treg, val1, val2);
|
||||
multiply_mulx(sreg, treg);
|
||||
|
||||
|
@ -613,10 +607,9 @@ void DSPEmitter::mulc(const UDSPInstruction opc)
|
|||
u8 sreg = (opc >> 12) & 0x1;
|
||||
|
||||
// u16 accm = dsp_get_acc_m(sreg);
|
||||
// MOV(64, R(R11), ImmPtr(&g_dsp.r));
|
||||
MOVSX(64, 16, ESI, MDisp(R11, STRUCT_OFFSET(g_dsp.r, ac[sreg].m)));
|
||||
get_acc_m(sreg, ESI);
|
||||
// u16 axh = dsp_get_ax_h(treg);
|
||||
MOVSX(64, 16, EDI, MDisp(R11, STRUCT_OFFSET(g_dsp.r, ax[treg].h)));
|
||||
dsp_op_read_reg(DSP_REG_AXH0+treg, RDI, SIGN);
|
||||
// s64 prod = dsp_multiply(accm, axh);
|
||||
multiply();
|
||||
// dsp_set_long_prod(prod);
|
||||
|
@ -647,9 +640,9 @@ void DSPEmitter::mulcac(const UDSPInstruction opc)
|
|||
ADD(64, R(RAX), R(RDX));
|
||||
PUSH(64, R(RAX));
|
||||
// u16 accm = dsp_get_acc_m(sreg);
|
||||
MOVSX(64, 16, RSI, MDisp(R11, STRUCT_OFFSET(g_dsp.r, ac[sreg].m)));
|
||||
get_acc_m(sreg, ESI);
|
||||
// u16 axh = dsp_get_ax_h(treg);
|
||||
MOVSX(64, 16, RDI, MDisp(R11, STRUCT_OFFSET(g_dsp.r, ax[treg].h)));
|
||||
dsp_op_read_reg(DSP_REG_AXH0+treg, RDI, SIGN);
|
||||
// s64 prod = dsp_multiply(accm, axh);
|
||||
multiply();
|
||||
// dsp_set_long_prod(prod);
|
||||
|
@ -686,9 +679,9 @@ void DSPEmitter::mulcmv(const UDSPInstruction opc)
|
|||
get_long_prod();
|
||||
PUSH(64, R(RAX));
|
||||
// u16 accm = dsp_get_acc_m(sreg);
|
||||
MOVSX(64, 16, RSI, MDisp(R11, STRUCT_OFFSET(g_dsp.r, ac[sreg].m)));
|
||||
get_acc_m(sreg, ESI);
|
||||
// u16 axh = dsp_get_ax_h(treg);
|
||||
MOVSX(64, 16, RDI, MDisp(R11, STRUCT_OFFSET(g_dsp.r, ax[treg].h)));
|
||||
dsp_op_read_reg(DSP_REG_AXH0+treg, RDI, SIGN);
|
||||
// s64 prod = dsp_multiply(accm, axh);
|
||||
multiply();
|
||||
// dsp_set_long_prod(prod);
|
||||
|
@ -727,9 +720,9 @@ void DSPEmitter::mulcmvz(const UDSPInstruction opc)
|
|||
get_long_prod_round_prodl();
|
||||
PUSH(64, R(RAX));
|
||||
// u16 accm = dsp_get_acc_m(sreg);
|
||||
MOVSX(64, 16, RSI, MDisp(R11, STRUCT_OFFSET(g_dsp.r, ac[sreg].m)));
|
||||
get_acc_m(sreg, ESI);
|
||||
// u16 axh = dsp_get_ax_h(treg);
|
||||
MOVSX(64, 16, RDI, MDisp(R11, STRUCT_OFFSET(g_dsp.r, ax[treg].h)));
|
||||
dsp_op_read_reg(DSP_REG_AXH0+treg, RDI, SIGN);
|
||||
// s64 prod = dsp_multiply(accm, axh);
|
||||
multiply();
|
||||
// dsp_set_long_prod(prod);
|
||||
|
@ -759,14 +752,11 @@ void DSPEmitter::maddx(const UDSPInstruction opc)
|
|||
#ifdef _M_X64
|
||||
u8 treg = (opc >> 8) & 0x1;
|
||||
u8 sreg = (opc >> 9) & 0x1;
|
||||
u16 *sregp = reg_ptr(DSP_REG_AXL0 + sreg*2);
|
||||
u16 *tregp = reg_ptr(DSP_REG_AXL1 + treg*2);
|
||||
|
||||
// MOV(64, R(R11), ImmPtr(&g_dsp.r));
|
||||
// u16 val1 = (sreg == 0) ? dsp_get_ax_l(0) : dsp_get_ax_h(0);
|
||||
MOVSX(64, 16, RSI, MDisp(R11, PtrOffset(sregp, &g_dsp.r)));
|
||||
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);
|
||||
MOVSX(64, 16, RDI, MDisp(R11, PtrOffset(tregp, &g_dsp.r)));
|
||||
dsp_op_read_reg(DSP_REG_AXL1 + treg*2, RDI, SIGN);
|
||||
// s64 prod = dsp_multiply_add(val1, val2);
|
||||
multiply_add();
|
||||
// dsp_set_long_prod(prod);
|
||||
|
@ -786,14 +776,11 @@ void DSPEmitter::msubx(const UDSPInstruction opc)
|
|||
#ifdef _M_X64
|
||||
u8 treg = (opc >> 8) & 0x1;
|
||||
u8 sreg = (opc >> 9) & 0x1;
|
||||
u16 *sregp = reg_ptr(DSP_REG_AXL0 + sreg*2);
|
||||
u16 *tregp = reg_ptr(DSP_REG_AXL1 + treg*2);
|
||||
|
||||
// MOV(64, R(R11), ImmPtr(&g_dsp.r));
|
||||
// u16 val1 = (sreg == 0) ? dsp_get_ax_l(0) : dsp_get_ax_h(0);
|
||||
MOVSX(64, 16, RSI, MDisp(R11, PtrOffset(sregp, &g_dsp.r)));
|
||||
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);
|
||||
MOVSX(64, 16, RDI, MDisp(R11, PtrOffset(tregp, &g_dsp.r)));
|
||||
dsp_op_read_reg(DSP_REG_AXL1 + treg*2, RDI, SIGN);
|
||||
// s64 prod = dsp_multiply_sub(val1, val2);
|
||||
multiply_sub();
|
||||
// dsp_set_long_prod(prod);
|
||||
|
@ -814,11 +801,10 @@ void DSPEmitter::maddc(const UDSPInstruction opc)
|
|||
u8 treg = (opc >> 8) & 0x1;
|
||||
u8 sreg = (opc >> 9) & 0x1;
|
||||
|
||||
// MOV(64, R(R11), ImmPtr(&g_dsp.r));
|
||||
// u16 accm = dsp_get_acc_m(sreg);
|
||||
MOVSX(64, 16, RSI, MDisp(R11, STRUCT_OFFSET(g_dsp.r, ac[sreg].m)));
|
||||
get_acc_m(sreg, ESI);
|
||||
// u16 axh = dsp_get_ax_h(treg);
|
||||
MOVSX(64, 16, RDI, MDisp(R11, STRUCT_OFFSET(g_dsp.r, ax[treg].h)));
|
||||
dsp_op_read_reg(DSP_REG_AXH0+treg, RDI, SIGN);
|
||||
// s64 prod = dsp_multiply_add(accm, axh);
|
||||
multiply_add();
|
||||
// dsp_set_long_prod(prod);
|
||||
|
@ -840,10 +826,9 @@ void DSPEmitter::msubc(const UDSPInstruction opc)
|
|||
u8 sreg = (opc >> 9) & 0x1;
|
||||
|
||||
// u16 accm = dsp_get_acc_m(sreg);
|
||||
// MOV(64, R(R11), ImmPtr(&g_dsp.r));
|
||||
MOVSX(64, 16, RSI, MDisp(R11, STRUCT_OFFSET(g_dsp.r, ac[sreg].m)));
|
||||
get_acc_m(sreg, ESI);
|
||||
// u16 axh = dsp_get_ax_h(treg);
|
||||
MOVSX(64, 16, RDI, MDisp(R11, STRUCT_OFFSET(g_dsp.r, ax[treg].h)));
|
||||
dsp_op_read_reg(DSP_REG_AXH0+treg, RDI, SIGN);
|
||||
// s64 prod = dsp_multiply_sub(accm, axh);
|
||||
multiply_sub();
|
||||
// dsp_set_long_prod(prod);
|
||||
|
@ -863,11 +848,10 @@ void DSPEmitter::madd(const UDSPInstruction opc)
|
|||
#ifdef _M_X64
|
||||
u8 sreg = (opc >> 8) & 0x1;
|
||||
|
||||
// MOV(64, R(R11), ImmPtr(&g_dsp.r));
|
||||
// u16 axl = dsp_get_ax_l(sreg);
|
||||
MOVSX(64, 16, RSI, MDisp(R11, STRUCT_OFFSET(g_dsp.r, ax[sreg].l)));
|
||||
dsp_op_read_reg(DSP_REG_AXL0+sreg, RSI, SIGN);
|
||||
// u16 axh = dsp_get_ax_h(sreg);
|
||||
MOVSX(64, 16, RDI, MDisp(R11, STRUCT_OFFSET(g_dsp.r, ax[sreg].h)));
|
||||
dsp_op_read_reg(DSP_REG_AXH0+sreg, RDI, SIGN);
|
||||
// s64 prod = dsp_multiply_add(axl, axh);
|
||||
multiply_add();
|
||||
// dsp_set_long_prod(prod);
|
||||
|
@ -886,12 +870,11 @@ void DSPEmitter::msub(const UDSPInstruction opc)
|
|||
{
|
||||
#ifdef _M_X64
|
||||
u8 sreg = (opc >> 8) & 0x1;
|
||||
//
|
||||
|
||||
// u16 axl = dsp_get_ax_l(sreg);
|
||||
// MOV(64, R(R11), ImmPtr(&g_dsp.r));
|
||||
MOVSX(64, 16, RSI, MDisp(R11, STRUCT_OFFSET(g_dsp.r, ax[sreg].l)));
|
||||
dsp_op_read_reg(DSP_REG_AXL0+sreg, RSI, SIGN);
|
||||
// u16 axh = dsp_get_ax_h(sreg);
|
||||
MOVSX(64, 16, RDI, MDisp(R11, STRUCT_OFFSET(g_dsp.r, ax[sreg].h)));
|
||||
dsp_op_read_reg(DSP_REG_AXH0+sreg, RDI, SIGN);
|
||||
// s64 prod = dsp_multiply_sub(axl, axh);
|
||||
multiply_sub();
|
||||
// dsp_set_long_prod(prod);
|
||||
|
|
|
@ -0,0 +1,540 @@
|
|||
// Copyright (C) 2011 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#include "DSPJitRegCache.h"
|
||||
#include "../DSPEmitter.h"
|
||||
#include "../DSPMemoryMap.h"
|
||||
|
||||
using namespace Gen;
|
||||
|
||||
static u16 *reg_ptr(int reg) {
|
||||
switch(reg) {
|
||||
case DSP_REG_AR0:
|
||||
case DSP_REG_AR1:
|
||||
case DSP_REG_AR2:
|
||||
case DSP_REG_AR3:
|
||||
return &g_dsp.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];
|
||||
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];
|
||||
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];
|
||||
case DSP_REG_ACH0:
|
||||
case DSP_REG_ACH1:
|
||||
return &g_dsp.r.ac[reg - DSP_REG_ACH0].h;
|
||||
case DSP_REG_CR: return &g_dsp.r.cr;
|
||||
case DSP_REG_SR: return &g_dsp.r.sr;
|
||||
case DSP_REG_PRODL: return &g_dsp.r.prod.l;
|
||||
case DSP_REG_PRODM: return &g_dsp.r.prod.m;
|
||||
case DSP_REG_PRODH: return &g_dsp.r.prod.h;
|
||||
case DSP_REG_PRODM2: return &g_dsp.r.prod.m2;
|
||||
case DSP_REG_AXL0:
|
||||
case DSP_REG_AXL1:
|
||||
return &g_dsp.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;
|
||||
case DSP_REG_ACL0:
|
||||
case DSP_REG_ACL1:
|
||||
return &g_dsp.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;
|
||||
default:
|
||||
_assert_msg_(DSPLLE, 0, "cannot happen");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
#define ROTATED_REG_ACCS
|
||||
//#undef ROTATED_REG_ACCS
|
||||
|
||||
DSPJitRegCache::DSPJitRegCache(DSPEmitter &_emitter)
|
||||
: emitter(_emitter), temporary(false), merged(false) {
|
||||
for(unsigned int i = 0; i < NUMXREGS; i++) {
|
||||
xregs[i].guest_reg = DSP_REG_STATIC;
|
||||
}
|
||||
xregs[RSP].guest_reg = DSP_REG_STATIC;//stack pointer
|
||||
xregs[RBX].guest_reg = DSP_REG_STATIC;//extended op backing store
|
||||
|
||||
xregs[RBP].guest_reg = DSP_REG_NONE;//definitely usable in dsplle because
|
||||
//all external calls are protected
|
||||
|
||||
#ifdef _M_X64
|
||||
xregs[R8].guest_reg = DSP_REG_STATIC;//acc0
|
||||
xregs[R9].guest_reg = DSP_REG_STATIC;//acc1
|
||||
xregs[R10].guest_reg = DSP_REG_NONE;
|
||||
xregs[R11].guest_reg = DSP_REG_STATIC;//&g_dsp.r
|
||||
xregs[R12].guest_reg = DSP_REG_STATIC;//used for cycle counting
|
||||
xregs[R13].guest_reg = DSP_REG_NONE;
|
||||
xregs[R14].guest_reg = DSP_REG_NONE;
|
||||
xregs[R15].guest_reg = DSP_REG_NONE;
|
||||
#endif
|
||||
|
||||
#ifdef _M_X64
|
||||
acc[0].host_reg = R8;
|
||||
acc[0].shift = 0;
|
||||
acc[0].dirty = false;
|
||||
acc[0].used = false;
|
||||
acc[0].tmp_reg = INVALID_REG;
|
||||
|
||||
acc[1].host_reg = R9;
|
||||
acc[1].shift = 0;
|
||||
acc[1].dirty = false;
|
||||
acc[1].used = false;
|
||||
acc[1].tmp_reg = INVALID_REG;
|
||||
#endif
|
||||
for(unsigned int i = 0; i < 32; i++) {
|
||||
regs[i].mem = reg_ptr(i);
|
||||
regs[i].size = 2;
|
||||
}
|
||||
#ifdef _M_X64
|
||||
regs[DSP_REG_ACC0_64].mem = &g_dsp.r.ac[0].val;
|
||||
regs[DSP_REG_ACC0_64].size = 8;
|
||||
regs[DSP_REG_ACC1_64].mem = &g_dsp.r.ac[1].val;
|
||||
regs[DSP_REG_ACC1_64].size = 8;
|
||||
regs[DSP_REG_PROD_64].mem = &g_dsp.r.prod.val;
|
||||
regs[DSP_REG_PROD_64].size = 8;
|
||||
#endif
|
||||
regs[DSP_REG_AX0_32].mem = &g_dsp.r.ax[0].val;
|
||||
regs[DSP_REG_AX0_32].size = 4;
|
||||
regs[DSP_REG_AX1_32].mem = &g_dsp.r.ax[1].val;
|
||||
regs[DSP_REG_AX1_32].size = 4;
|
||||
for(unsigned int i = 0; i < DSP_REG_MAX_MEM_BACKED+1; i++) {
|
||||
regs[i].dirty = false;
|
||||
#ifdef _M_IX86 // All32
|
||||
regs[i].loc = M(regs[i].mem);
|
||||
#else
|
||||
regs[i].loc = MDisp(R11, PtrOffset(regs[i].mem, &g_dsp.r));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
DSPJitRegCache::DSPJitRegCache(const DSPJitRegCache &cache)
|
||||
: emitter(cache.emitter), temporary(true), merged(false)
|
||||
{
|
||||
memcpy(xregs,cache.xregs,sizeof(xregs));
|
||||
#ifdef _M_X64
|
||||
memcpy(acc,cache.acc,sizeof(acc));
|
||||
#endif
|
||||
memcpy(regs,cache.regs,sizeof(regs));
|
||||
}
|
||||
|
||||
DSPJitRegCache& DSPJitRegCache::operator=(const DSPJitRegCache &cache)
|
||||
{
|
||||
_assert_msg_(DSPLLE, &emitter == &cache.emitter, "emitter does not match");
|
||||
_assert_msg_(DSPLLE, temporary, "register cache not temporary??");
|
||||
merged = false;
|
||||
memcpy(xregs,cache.xregs,sizeof(xregs));
|
||||
#ifdef _M_X64
|
||||
memcpy(acc,cache.acc,sizeof(acc));
|
||||
#endif
|
||||
memcpy(regs,cache.regs,sizeof(regs));
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
DSPJitRegCache::~DSPJitRegCache()
|
||||
{
|
||||
_assert_msg_(DSPLLE, !temporary || merged, "temporary cache not merged");
|
||||
}
|
||||
|
||||
void DSPJitRegCache::flushRegs(DSPJitRegCache &cache, bool emit)
|
||||
{
|
||||
cache.merged = true;
|
||||
|
||||
#ifdef _M_X64
|
||||
for(unsigned int i = 0; i < 2; i++) {
|
||||
if (acc[i].shift > cache.acc[i].shift) {
|
||||
if (emit)
|
||||
emitter.ROL(64, R(acc[i].host_reg),
|
||||
Imm8(acc[i].shift-cache.acc[i].shift));
|
||||
acc[i].shift = cache.acc[i].shift;
|
||||
}
|
||||
if (acc[i].shift < cache.acc[i].shift) {
|
||||
if (emit)
|
||||
emitter.ROR(64, R(acc[i].host_reg),
|
||||
Imm8(cache.acc[i].shift-acc[i].shift));
|
||||
acc[i].shift = cache.acc[i].shift;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void DSPJitRegCache::drop()
|
||||
{
|
||||
merged = true;
|
||||
}
|
||||
|
||||
void DSPJitRegCache::flushRegs()
|
||||
{
|
||||
//also needs to undo any dynamic changes to static allocated regs
|
||||
//this should have the same effect as
|
||||
//merge(DSPJitRegCache(emitter));
|
||||
#ifdef _M_X64
|
||||
#ifdef ROTATED_REG_ACCS
|
||||
for(unsigned int i = 0; i < 2; i++) {
|
||||
if (acc[i].shift > 0) {
|
||||
emitter.ROL(64, R(acc[i].host_reg),
|
||||
Imm8(acc[i].shift));
|
||||
acc[i].shift = 0;
|
||||
}
|
||||
_assert_msg_(DSPLLE, !acc[i].used,
|
||||
"accumulator still in use");
|
||||
if (acc[i].used)
|
||||
emitter.INT3();
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
static u64 ebp_store;
|
||||
|
||||
void DSPJitRegCache::loadStaticRegs()
|
||||
{
|
||||
#ifdef _M_X64
|
||||
#ifdef ROTATED_REG_ACCS
|
||||
emitter.MOV(64, R(R8), MDisp(R11, STRUCT_OFFSET(g_dsp.r, ac[0].val)));
|
||||
emitter.MOV(64, R(R9), MDisp(R11, STRUCT_OFFSET(g_dsp.r, ac[1].val)));
|
||||
#endif
|
||||
emitter.MOV(64, MDisp(R11, PtrOffset(&ebp_store, &g_dsp.r)), R(RBP));
|
||||
#else
|
||||
emitter.MOV(32, M(&ebp_store), R(EBP));
|
||||
#endif
|
||||
}
|
||||
|
||||
void DSPJitRegCache::saveStaticRegs()
|
||||
{
|
||||
flushRegs();
|
||||
#ifdef _M_X64
|
||||
#ifdef ROTATED_REG_ACCS
|
||||
emitter.MOV(64, MDisp(R11, STRUCT_OFFSET(g_dsp.r, ac[0].val)), R(R8));
|
||||
emitter.MOV(64, MDisp(R11, STRUCT_OFFSET(g_dsp.r, ac[1].val)), R(R9));
|
||||
#endif
|
||||
emitter.MOV(64, R(RBP), MDisp(R11, PtrOffset(&ebp_store, &g_dsp.r)));
|
||||
#else
|
||||
emitter.MOV(32, R(EBP), M(&ebp_store));
|
||||
#endif
|
||||
}
|
||||
|
||||
void DSPJitRegCache::getReg(int reg, OpArg &oparg, bool load)
|
||||
{
|
||||
switch(reg) {
|
||||
#ifdef _M_X64
|
||||
#ifdef ROTATED_REG_ACCS
|
||||
case DSP_REG_ACH0:
|
||||
case DSP_REG_ACH1:
|
||||
{
|
||||
_assert_msg_(DSPLLE, !acc[reg-DSP_REG_ACH0].used,
|
||||
"accumulator already in use");
|
||||
if (acc[reg-DSP_REG_ACH0].used)
|
||||
emitter.INT3();
|
||||
oparg = R(acc[reg-DSP_REG_ACH0].host_reg);
|
||||
if (acc[reg-DSP_REG_ACH0].shift < 32) {
|
||||
emitter.ROR(64, oparg, Imm8(32-acc[reg-DSP_REG_ACH0].shift));
|
||||
acc[reg-DSP_REG_ACH0].shift = 32;
|
||||
}
|
||||
|
||||
acc[reg-DSP_REG_ACH0].used = true;
|
||||
}
|
||||
break;
|
||||
case DSP_REG_ACM0:
|
||||
case DSP_REG_ACM1:
|
||||
{
|
||||
_assert_msg_(DSPLLE, !acc[reg-DSP_REG_ACM0].used,
|
||||
"accumulator already in use");
|
||||
if (acc[reg-DSP_REG_ACM0].used)
|
||||
emitter.INT3();
|
||||
oparg = R(acc[reg-DSP_REG_ACM0].host_reg);
|
||||
if (acc[reg-DSP_REG_ACM0].shift < 16) {
|
||||
emitter.ROR(64, oparg, Imm8(16-acc[reg-DSP_REG_ACM0].shift));
|
||||
acc[reg-DSP_REG_ACM0].shift = 16;
|
||||
}
|
||||
if (acc[reg-DSP_REG_ACM0].shift > 16) {
|
||||
emitter.ROL(64, oparg, Imm8(acc[reg-DSP_REG_ACM0].shift-16));
|
||||
acc[reg-DSP_REG_ACM0].shift = 16;
|
||||
}
|
||||
acc[reg-DSP_REG_ACM0].used = true;
|
||||
}
|
||||
break;
|
||||
case DSP_REG_ACL0:
|
||||
case DSP_REG_ACL1:
|
||||
{
|
||||
_assert_msg_(DSPLLE, !acc[reg-DSP_REG_ACL0].used,
|
||||
"accumulator already in use");
|
||||
if (acc[reg-DSP_REG_ACL0].used)
|
||||
emitter.INT3();
|
||||
oparg = R(acc[reg-DSP_REG_ACL0].host_reg);
|
||||
if (acc[reg-DSP_REG_ACL0].shift > 0) {
|
||||
emitter.ROL(64, oparg, Imm8(acc[reg-DSP_REG_ACL0].shift));
|
||||
acc[reg-DSP_REG_ACL0].shift = 0;
|
||||
}
|
||||
acc[reg-DSP_REG_ACL0].used = true;
|
||||
}
|
||||
break;
|
||||
case DSP_REG_ACC0_64:
|
||||
case DSP_REG_ACC1_64:
|
||||
{
|
||||
if (acc[reg-DSP_REG_ACC0_64].used)
|
||||
emitter.INT3();
|
||||
_assert_msg_(DSPLLE, !acc[reg-DSP_REG_ACC0_64].used,
|
||||
"accumulator already in use");
|
||||
oparg = R(acc[reg-DSP_REG_ACC0_64].host_reg);
|
||||
if (load) {
|
||||
if (acc[reg-DSP_REG_ACC0_64].shift > 0) {
|
||||
emitter.ROL(64, oparg, Imm8(acc[reg-DSP_REG_ACC0_64].shift));
|
||||
}
|
||||
emitter.SHL(64, oparg, Imm8(64-40));//sign extend
|
||||
emitter.SAR(64, oparg, Imm8(64-40));
|
||||
}
|
||||
//don't bother to rotate if caller replaces all data
|
||||
acc[reg-DSP_REG_ACC0_64].shift = 0;
|
||||
acc[reg-DSP_REG_ACC0_64].used = true;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
#endif
|
||||
default:
|
||||
{
|
||||
/*
|
||||
getFreeXReg(reg[reg].host_reg);
|
||||
X64Reg tmp = reg[reg].host_reg;
|
||||
oparg = R(tmp);
|
||||
|
||||
if (load) {
|
||||
u16 *regp = reg_ptr(reg);
|
||||
#ifdef _M_IX86 // All32
|
||||
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
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void DSPJitRegCache::putReg(int reg, bool dirty)
|
||||
{
|
||||
switch(reg) {
|
||||
#ifdef _M_X64
|
||||
#ifdef ROTATED_REG_ACCS
|
||||
case DSP_REG_ACH0:
|
||||
case DSP_REG_ACH1:
|
||||
{
|
||||
|
||||
if (dirty) {
|
||||
if (acc[reg-DSP_REG_ACH0].shift > 0) {
|
||||
emitter.ROL(64, R(acc[reg-DSP_REG_ACH0].host_reg),
|
||||
Imm8(acc[reg-DSP_REG_ACH0].shift));
|
||||
acc[reg-DSP_REG_ACH0].shift = 0;
|
||||
}
|
||||
emitter.SHL(64, R(acc[reg-DSP_REG_ACH0].host_reg), Imm8(64-40));//sign extend
|
||||
emitter.SAR(64, R(acc[reg-DSP_REG_ACH0].host_reg), Imm8(64-40));
|
||||
}
|
||||
acc[reg-DSP_REG_ACH0].used = false;
|
||||
}
|
||||
break;
|
||||
case DSP_REG_ACM0:
|
||||
case DSP_REG_ACM1:
|
||||
{
|
||||
acc[reg-DSP_REG_ACM0].used = false;
|
||||
}
|
||||
break;
|
||||
case DSP_REG_ACL0:
|
||||
case DSP_REG_ACL1:
|
||||
acc[reg-DSP_REG_ACL0].used = false;
|
||||
break;
|
||||
case DSP_REG_ACC0_64:
|
||||
case DSP_REG_ACC1_64:
|
||||
{
|
||||
if (dirty) {
|
||||
OpArg _reg = R(acc[reg-DSP_REG_ACC0_64].host_reg);
|
||||
|
||||
emitter.SHL(64, _reg, Imm8(64-40));//sign extend
|
||||
emitter.SAR(64, _reg, Imm8(64-40));
|
||||
}
|
||||
acc[reg-DSP_REG_ACC0_64].used = false;
|
||||
}
|
||||
break;
|
||||
#else
|
||||
case DSP_REG_ACH0:
|
||||
case DSP_REG_ACH1:
|
||||
{
|
||||
//need to fix in memory for now.
|
||||
u16 *regp = reg_ptr(reg);
|
||||
OpArg mem;
|
||||
mem = MDisp(R11,PtrOffset(regp,&g_dsp.r));
|
||||
X64Reg tmp;
|
||||
getFreeXReg(tmp);
|
||||
// sign extend from the bottom 8 bits.
|
||||
emitter.MOVSX(16, 8, tmp, mem);
|
||||
emitter.MOV(16, mem, R(tmp));
|
||||
putXReg(tmp);
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
#else
|
||||
case DSP_REG_ACH0:
|
||||
case DSP_REG_ACH1:
|
||||
{
|
||||
//need to fix in memory for now.
|
||||
u16 *regp = reg_ptr(reg);
|
||||
OpArg mem;
|
||||
mem = M(regp);
|
||||
X64Reg tmp;
|
||||
getFreeXReg(tmp);
|
||||
// sign extend from the bottom 8 bits.
|
||||
emitter.MOVSX(16, 8, tmp, mem);
|
||||
emitter.MOV(16, mem, R(tmp));
|
||||
putXReg(tmp);
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
{
|
||||
/*
|
||||
X64Reg tmp = reg[reg].host_reg;
|
||||
|
||||
if(dirty) {
|
||||
u16 *regp = reg_ptr(reg);
|
||||
#ifdef _M_IX86 // All32
|
||||
emitter.MOV(16, M(dregp), R(tmp));
|
||||
#else
|
||||
emitter.MOV(16, MDisp(R11, PtrOffset(dregp, &g_dsp.r)), R(tmp));
|
||||
#endif
|
||||
}
|
||||
*/
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void DSPJitRegCache::readReg(int sreg, X64Reg host_dreg, DSPJitSignExtend extend)
|
||||
{
|
||||
OpArg reg;
|
||||
getReg(sreg, reg);
|
||||
switch(regs[sreg].size) {
|
||||
case 2:
|
||||
switch(extend) {
|
||||
#ifdef _M_X64
|
||||
case SIGN: emitter.MOVSX(64, 16, host_dreg, reg); break;
|
||||
case ZERO: emitter.MOVZX(64, 16, host_dreg, reg); break;
|
||||
#else
|
||||
case SIGN: emitter.MOVSX(32, 16, host_dreg, reg); break;
|
||||
case ZERO: emitter.MOVZX(32, 16, host_dreg, reg); break;
|
||||
#endif
|
||||
case NONE: emitter.MOV(16, R(host_dreg), reg); break;
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
#ifdef _M_X64
|
||||
switch(extend) {
|
||||
case SIGN: emitter.MOVSX(64, 32, host_dreg, reg); break;
|
||||
case ZERO: emitter.MOVZX(64, 32, host_dreg, reg); break;
|
||||
case NONE: emitter.MOV(32, R(host_dreg), reg); break;
|
||||
}
|
||||
#else
|
||||
emitter.MOV(32, R(host_dreg), reg); break;
|
||||
#endif
|
||||
break;
|
||||
#ifdef _M_X64
|
||||
case 8:
|
||||
emitter.MOV(64, R(host_dreg), reg); break;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
_assert_msg_(DSPLLE, 0, "unsupported memory size");
|
||||
break;
|
||||
}
|
||||
putReg(sreg, false);
|
||||
}
|
||||
|
||||
void DSPJitRegCache::writeReg(int dreg, OpArg arg)
|
||||
{
|
||||
OpArg reg;
|
||||
getReg(dreg, reg, false);
|
||||
switch(regs[dreg].size) {
|
||||
case 2: emitter.MOV(16, reg, arg); break;
|
||||
case 4: emitter.MOV(32, reg, arg); break;
|
||||
#ifdef _M_X64
|
||||
case 8: emitter.MOV(64, reg, arg); break;
|
||||
#endif
|
||||
default:
|
||||
_assert_msg_(DSPLLE, 0, "unsupported memory size");
|
||||
break;
|
||||
}
|
||||
putReg(dreg, true);
|
||||
}
|
||||
|
||||
X64Reg DSPJitRegCache::spillXReg()
|
||||
{
|
||||
//todo: implement
|
||||
return INVALID_REG;
|
||||
}
|
||||
|
||||
void DSPJitRegCache::spillXReg(X64Reg reg)
|
||||
{
|
||||
//todo: implement
|
||||
}
|
||||
|
||||
X64Reg DSPJitRegCache::findFreeXReg()
|
||||
{
|
||||
int i;
|
||||
for(i = 0; i < NUMXREGS; i++) {
|
||||
if (xregs[i].guest_reg == DSP_REG_NONE) {
|
||||
return (X64Reg)i;
|
||||
}
|
||||
}
|
||||
return INVALID_REG;
|
||||
}
|
||||
|
||||
void DSPJitRegCache::getFreeXReg(X64Reg ®)
|
||||
{
|
||||
reg = findFreeXReg();
|
||||
if (reg == INVALID_REG)
|
||||
reg = spillXReg();
|
||||
_assert_msg_(DSPLLE, reg != INVALID_REG, "could not find register");
|
||||
xregs[reg].guest_reg = DSP_REG_USED;
|
||||
}
|
||||
|
||||
void DSPJitRegCache::getXReg(X64Reg reg)
|
||||
{
|
||||
if (xregs[reg].guest_reg != DSP_REG_NONE)
|
||||
spillXReg(reg);
|
||||
_assert_msg_(DSPLLE, xregs[reg].guest_reg != DSP_REG_NONE, "register already in use");
|
||||
xregs[reg].guest_reg = DSP_REG_USED;
|
||||
}
|
||||
|
||||
void DSPJitRegCache::putXReg(X64Reg reg)
|
||||
{
|
||||
_assert_msg_(DSPLLE, xregs[reg].guest_reg == DSP_REG_USED,
|
||||
"putXReg without get(Free)XReg");
|
||||
xregs[reg].guest_reg = DSP_REG_NONE;
|
||||
}
|
|
@ -0,0 +1,169 @@
|
|||
// Copyright (C) 2011 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#ifndef _DSPJITREGCACHE_H
|
||||
#define _DSPJITREGCACHE_H
|
||||
|
||||
#include "x64Emitter.h"
|
||||
|
||||
class DSPEmitter;
|
||||
|
||||
enum DSPJitRegSpecial {
|
||||
DSP_REG_ACC0_64 =32,
|
||||
DSP_REG_ACC1_64 =33,
|
||||
DSP_REG_AX0_32 =34,
|
||||
DSP_REG_AX1_32 =35,
|
||||
DSP_REG_PROD_64 =36,
|
||||
DSP_REG_MAX_MEM_BACKED = 36,
|
||||
|
||||
DSP_REG_USED =253,
|
||||
DSP_REG_STATIC =254,
|
||||
DSP_REG_NONE =255
|
||||
};
|
||||
|
||||
enum DSPJitSignExtend {
|
||||
SIGN, ZERO, NONE
|
||||
};
|
||||
|
||||
#ifdef _M_X64
|
||||
#define NUMXREGS 16
|
||||
#elif _M_IX86
|
||||
#define NUMXREGS 8
|
||||
#endif
|
||||
|
||||
class DSPJitRegCache {
|
||||
private:
|
||||
struct X64CachedReg
|
||||
{
|
||||
int guest_reg; //including DSPJitRegSpecial
|
||||
};
|
||||
struct DynamicReg {
|
||||
Gen::OpArg loc;
|
||||
void *mem;
|
||||
size_t size;
|
||||
bool dirty;
|
||||
};
|
||||
|
||||
#ifdef _M_X64
|
||||
//when there is a way to do this efficiently in x86, uncondition
|
||||
struct {
|
||||
Gen::X64Reg host_reg;
|
||||
int shift;
|
||||
bool dirty;
|
||||
bool used;
|
||||
Gen::X64Reg tmp_reg;
|
||||
} acc[2];
|
||||
#endif
|
||||
|
||||
DynamicReg regs[DSP_REG_MAX_MEM_BACKED+1];
|
||||
X64CachedReg xregs[NUMXREGS];
|
||||
|
||||
DSPEmitter &emitter;
|
||||
bool temporary;
|
||||
bool merged;
|
||||
private:
|
||||
//find a free host reg
|
||||
Gen::X64Reg findFreeXReg();
|
||||
Gen::X64Reg spillXReg();
|
||||
void spillXReg(Gen::X64Reg reg);
|
||||
public:
|
||||
DSPJitRegCache(DSPEmitter &_emitter);
|
||||
|
||||
//for branching into multiple control flows
|
||||
DSPJitRegCache(const DSPJitRegCache &cache);
|
||||
DSPJitRegCache& operator=(const DSPJitRegCache &cache);
|
||||
|
||||
~DSPJitRegCache();
|
||||
|
||||
//merge must be done _before_ leaving the code branch, so we can fix
|
||||
//up any differences in state
|
||||
void flushRegs(DSPJitRegCache &cache, bool emit = true);
|
||||
/* since some use cases are non-trivial, some examples:
|
||||
|
||||
//this does not modify the final state of gpr
|
||||
<code using gpr>
|
||||
FixupBranch b = JCC();
|
||||
DSPJitRegCache c = gpr;
|
||||
<code using c>
|
||||
gpr.flushRegs(c);
|
||||
SetBranchTarget(b);
|
||||
<code using gpr>
|
||||
|
||||
//this does not modify the final state of gpr
|
||||
<code using gpr>
|
||||
DSPJitRegCache c = gpr;
|
||||
FixupBranch b1 = JCC();
|
||||
<code using gpr>
|
||||
gpr.flushRegs(c);
|
||||
FixupBranch b2 = JMP();
|
||||
SetBranchTarget(b1);
|
||||
<code using gpr>
|
||||
gpr.flushRegs(c);
|
||||
SetBranchTarget(b2);
|
||||
<code using gpr>
|
||||
|
||||
//this allows gpr to be modified in the second branch
|
||||
//and fixes gpr according to the results form in the first branch
|
||||
<code using gpr>
|
||||
DSPJitRegCache c = gpr;
|
||||
FixupBranch b1 = JCC();
|
||||
<code using c>
|
||||
FixupBranch b2 = JMP();
|
||||
SetBranchTarget(b1);
|
||||
<code using gpr>
|
||||
gpr.flushRegs(c);
|
||||
SetBranchTarget(b2);
|
||||
<code using gpr>
|
||||
|
||||
//this does not modify the final state of gpr
|
||||
<code using gpr>
|
||||
u8* b = GetCodePtr();
|
||||
DSPJitRegCache c = gpr;
|
||||
<code using gpr>
|
||||
gpr.flushRegs(c);
|
||||
JCC(b);
|
||||
<code using gpr>
|
||||
|
||||
this all is not needed when gpr would not be used at all in the
|
||||
conditional branch
|
||||
*/
|
||||
//drop this copy without warning
|
||||
void drop();
|
||||
|
||||
//prepare state so that another flushed DSPJitRegCache can take over
|
||||
void flushRegs();
|
||||
|
||||
void loadStaticRegs();//load statically allocated regs from memory
|
||||
void saveStaticRegs();//save statically allocated regs to memory
|
||||
|
||||
//gives no SCALE_RIP with abs(offset) >= 0x80000000
|
||||
void getReg(int reg, Gen::OpArg &oparg, bool load = true);
|
||||
//done with all usages of OpArg above
|
||||
void putReg(int reg, bool dirty = true);
|
||||
|
||||
void readReg(int sreg, Gen::X64Reg host_dreg, DSPJitSignExtend extend);
|
||||
void writeReg(int dreg, Gen::OpArg arg);
|
||||
|
||||
//find a free host reg, spill if used, reserve
|
||||
void getFreeXReg(Gen::X64Reg ®);
|
||||
//spill a specific host reg if used, reserve
|
||||
void getXReg(Gen::X64Reg reg);
|
||||
//unreserve the given host reg
|
||||
void putXReg(Gen::X64Reg reg);
|
||||
};
|
||||
|
||||
#endif /*_DSPJITREGCACHE_H*/
|
|
@ -18,6 +18,7 @@
|
|||
#include "../DSPMemoryMap.h"
|
||||
#include "../DSPHWInterface.h"
|
||||
#include "../DSPEmitter.h"
|
||||
#include "DSPJitUtil.h"
|
||||
#include "x64Emitter.h"
|
||||
#include "ABI.h"
|
||||
|
||||
|
@ -39,14 +40,13 @@ using namespace Gen;
|
|||
// ECX = temp
|
||||
void DSPEmitter::increment_addr_reg(int reg)
|
||||
{
|
||||
#ifdef _M_IX86 // All32
|
||||
MOVZX(32, 16, EAX, M(&g_dsp.r.ar[reg]));
|
||||
MOVZX(32, 16, EDX, M(&g_dsp.r.wr[reg]));
|
||||
#else
|
||||
// MOV(64, R(R11), ImmPtr(&g_dsp.r));
|
||||
MOVZX(32, 16, EAX, MDisp(R11, STRUCT_OFFSET(g_dsp.r, ar[reg])));
|
||||
MOVZX(32, 16, EDX, MDisp(R11, STRUCT_OFFSET(g_dsp.r, wr[reg])));
|
||||
#endif
|
||||
OpArg ar_reg;
|
||||
OpArg wr_reg;
|
||||
gpr.getReg(DSP_REG_WR0+reg,wr_reg);
|
||||
MOVZX(32, 16, EDX, wr_reg);
|
||||
gpr.putReg(DSP_REG_WR0+reg);
|
||||
gpr.getReg(DSP_REG_AR0+reg,ar_reg);
|
||||
MOVZX(32, 16, EAX, ar_reg);
|
||||
|
||||
//u32 nar = ar + 1;
|
||||
MOV(32, R(EDI), R(EAX));
|
||||
|
@ -64,12 +64,8 @@ void DSPEmitter::increment_addr_reg(int reg)
|
|||
SetJumpTarget(nowrap);
|
||||
// g_dsp.r.ar[reg] = nar;
|
||||
|
||||
#ifdef _M_IX86 // All32
|
||||
MOV(16, M(&g_dsp.r.ar[reg]), R(AX));
|
||||
#else
|
||||
// MOV(64, R(R11), ImmPtr(&g_dsp.r));
|
||||
MOV(16, MDisp(R11, STRUCT_OFFSET(g_dsp.r, ar[reg])), R(AX));
|
||||
#endif
|
||||
MOV(16, ar_reg, R(AX));
|
||||
gpr.putReg(DSP_REG_AR0+reg);
|
||||
}
|
||||
|
||||
// EAX = g_dsp.r.ar[reg]
|
||||
|
@ -78,14 +74,13 @@ void DSPEmitter::increment_addr_reg(int reg)
|
|||
// ECX = temp
|
||||
void DSPEmitter::decrement_addr_reg(int reg)
|
||||
{
|
||||
#ifdef _M_IX86 // All32
|
||||
MOVZX(32, 16, EAX, M(&g_dsp.r.ar[reg]));
|
||||
MOVZX(32, 16, EDX, M(&g_dsp.r.wr[reg]));
|
||||
#else
|
||||
// MOV(64, R(R11), ImmPtr(&g_dsp.r));
|
||||
MOVZX(32, 16, EAX, MDisp(R11, STRUCT_OFFSET(g_dsp.r, ar[reg])));
|
||||
MOVZX(32, 16, EDX, MDisp(R11, STRUCT_OFFSET(g_dsp.r, wr[reg])));
|
||||
#endif
|
||||
OpArg ar_reg;
|
||||
OpArg wr_reg;
|
||||
gpr.getReg(DSP_REG_WR0+reg,wr_reg);
|
||||
MOVZX(32, 16, EDX, wr_reg);
|
||||
gpr.putReg(DSP_REG_WR0+reg);
|
||||
gpr.getReg(DSP_REG_AR0+reg,ar_reg);
|
||||
MOVZX(32, 16, EAX, ar_reg);
|
||||
|
||||
// u32 nar = ar + wr;
|
||||
// edi = nar
|
||||
|
@ -104,12 +99,8 @@ void DSPEmitter::decrement_addr_reg(int reg)
|
|||
SetJumpTarget(nowrap);
|
||||
// g_dsp.r.ar[reg] = nar;
|
||||
|
||||
#ifdef _M_IX86 // All32
|
||||
MOV(16, M(&g_dsp.r.ar[reg]), R(DI));
|
||||
#else
|
||||
// MOV(64, R(R11), ImmPtr(&g_dsp.r));
|
||||
MOV(16, MDisp(R11, STRUCT_OFFSET(g_dsp.r, ar[reg])), R(DI));
|
||||
#endif
|
||||
MOV(16, ar_reg, R(DI));
|
||||
gpr.putReg(DSP_REG_AR0+reg);
|
||||
}
|
||||
|
||||
// Increase addr register according to the correspond ix register
|
||||
|
@ -120,16 +111,17 @@ void DSPEmitter::decrement_addr_reg(int reg)
|
|||
// EDI = temp
|
||||
void DSPEmitter::increase_addr_reg(int reg)
|
||||
{
|
||||
#ifdef _M_IX86 // All32
|
||||
MOVZX(32, 16, EAX, M(&g_dsp.r.ar[reg]));
|
||||
MOVZX(32, 16, EDX, M(&g_dsp.r.wr[reg]));
|
||||
MOVSX(32, 16, ESI, M(&g_dsp.r.ix[reg]));
|
||||
#else
|
||||
// MOV(64, R(R11), ImmPtr(&g_dsp.r));
|
||||
MOVZX(32, 16, EAX, MDisp(R11, STRUCT_OFFSET(g_dsp.r, ar[reg])));
|
||||
MOVZX(32, 16, EDX, MDisp(R11, STRUCT_OFFSET(g_dsp.r, wr[reg])));
|
||||
MOVSX(32, 16, ESI, MDisp(R11, STRUCT_OFFSET(g_dsp.r, ix[reg])));
|
||||
#endif
|
||||
OpArg ar_reg;
|
||||
OpArg wr_reg;
|
||||
OpArg ix_reg;
|
||||
gpr.getReg(DSP_REG_WR0+reg,wr_reg);
|
||||
gpr.getReg(DSP_REG_IX0+reg,ix_reg);
|
||||
MOVZX(32, 16, EDX, wr_reg);
|
||||
MOVSX(32, 16, ESI, ix_reg);
|
||||
gpr.putReg(DSP_REG_WR0+reg);
|
||||
gpr.putReg(DSP_REG_IX0+reg);
|
||||
gpr.getReg(DSP_REG_AR0+reg,ar_reg);
|
||||
MOVZX(32, 16, EAX, ar_reg);
|
||||
|
||||
//u32 nar = ar + ix;
|
||||
//edi = nar
|
||||
|
@ -170,12 +162,8 @@ void DSPEmitter::increase_addr_reg(int reg)
|
|||
SetJumpTarget(done3);
|
||||
// g_dsp.r.ar[reg] = nar;
|
||||
|
||||
#ifdef _M_IX86 // All32
|
||||
MOV(16, M(&g_dsp.r.ar[reg]), R(DI));
|
||||
#else
|
||||
// MOV(64, R(R11), ImmPtr(&g_dsp.r));
|
||||
MOV(16, MDisp(R11, STRUCT_OFFSET(g_dsp.r, ar[reg])), R(DI));
|
||||
#endif
|
||||
MOV(16, ar_reg, R(DI));
|
||||
gpr.putReg(DSP_REG_AR0+reg);
|
||||
}
|
||||
|
||||
// Decrease addr register according to the correspond ix register
|
||||
|
@ -186,16 +174,17 @@ void DSPEmitter::increase_addr_reg(int reg)
|
|||
// EDI = temp
|
||||
void DSPEmitter::decrease_addr_reg(int reg)
|
||||
{
|
||||
#ifdef _M_IX86 // All32
|
||||
MOVZX(32, 16, EAX, M(&g_dsp.r.ar[reg]));
|
||||
MOVZX(32, 16, EDX, M(&g_dsp.r.wr[reg]));
|
||||
MOVSX(32, 16, ESI, M(&g_dsp.r.ix[reg]));
|
||||
#else
|
||||
// MOV(64, R(R11), ImmPtr(&g_dsp.r));
|
||||
MOVZX(32, 16, EAX, MDisp(R11, STRUCT_OFFSET(g_dsp.r, ar[reg])));
|
||||
MOVZX(32, 16, EDX, MDisp(R11, STRUCT_OFFSET(g_dsp.r, wr[reg])));
|
||||
MOVSX(32, 16, ESI, MDisp(R11, STRUCT_OFFSET(g_dsp.r, ix[reg])));
|
||||
#endif
|
||||
OpArg ar_reg;
|
||||
OpArg wr_reg;
|
||||
OpArg ix_reg;
|
||||
gpr.getReg(DSP_REG_WR0+reg,wr_reg);
|
||||
gpr.getReg(DSP_REG_IX0+reg,ix_reg);
|
||||
MOVZX(32, 16, EDX, wr_reg);
|
||||
MOVSX(32, 16, ESI, ix_reg);
|
||||
gpr.putReg(DSP_REG_WR0+reg);
|
||||
gpr.putReg(DSP_REG_IX0+reg);
|
||||
gpr.getReg(DSP_REG_WR0+reg,ar_reg);
|
||||
MOVZX(32, 16, EAX, ar_reg);
|
||||
|
||||
NOT(32, R(ESI)); //esi = ~ix
|
||||
|
||||
|
@ -237,12 +226,8 @@ void DSPEmitter::decrease_addr_reg(int reg)
|
|||
SetJumpTarget(done3);
|
||||
//return nar
|
||||
|
||||
#ifdef _M_IX86 // All32
|
||||
MOV(16, M(&g_dsp.r.ar[reg]), R(DI));
|
||||
#else
|
||||
// MOV(64, R(R11), ImmPtr(&g_dsp.r));
|
||||
MOV(16, MDisp(R11, STRUCT_OFFSET(g_dsp.r, ar[reg])), R(DI));
|
||||
#endif
|
||||
MOV(16, ar_reg, R(DI));
|
||||
gpr.putReg(DSP_REG_WR0+reg);
|
||||
}
|
||||
|
||||
|
||||
|
@ -268,9 +253,11 @@ void DSPEmitter::dmem_write()
|
|||
// else if (saddr == 0xf)
|
||||
SetJumpTarget(ifx);
|
||||
// Does it mean gdsp_ifx_write needs u32 rather than u16?
|
||||
DSPJitRegCache c(gpr);
|
||||
SaveDSPRegs();
|
||||
ABI_CallFunctionRR((void *)gdsp_ifx_write, EAX, ECX);
|
||||
LoadDSPRegs();
|
||||
gpr.flushRegs(c);
|
||||
SetJumpTarget(end);
|
||||
}
|
||||
|
||||
|
@ -374,9 +361,11 @@ void DSPEmitter::dmem_read()
|
|||
SetJumpTarget(ifx);
|
||||
// else if (saddr == 0xf)
|
||||
// return gdsp_ifx_read(addr);
|
||||
DSPJitRegCache c(gpr);
|
||||
SaveDSPRegs();
|
||||
ABI_CallFunctionR((void *)gdsp_ifx_read, ECX);
|
||||
LoadDSPRegs();
|
||||
gpr.flushRegs(c);
|
||||
SetJumpTarget(end);
|
||||
SetJumpTarget(end2);
|
||||
}
|
||||
|
@ -419,34 +408,22 @@ void DSPEmitter::dmem_read_imm(u16 address)
|
|||
void DSPEmitter::get_long_prod(X64Reg long_prod)
|
||||
{
|
||||
#ifdef _M_X64
|
||||
#if 0
|
||||
// MOV(64, R(R11), ImmPtr(&g_dsp.r));
|
||||
//s64 val = (s8)(u8)g_dsp.r[DSP_REG_PRODH];
|
||||
MOVSX(64, 8, long_prod, MDisp(R11, STRUCT_OFFSET(g_dsp.r, prod.h)));
|
||||
//val <<= 32;
|
||||
SHL(64, R(long_prod), Imm8(16));
|
||||
//s64 low_prod = g_dsp.r[DSP_REG_PRODM];
|
||||
OR(16, R(long_prod), MDisp(R11, STRUCT_OFFSET(g_dsp.r, prod.m)));
|
||||
//low_prod += g_dsp.r[DSP_REG_PRODM2];
|
||||
ADD(16, R(long_prod), MDisp(R11, STRUCT_OFFSET(g_dsp.r, prod.m2)));
|
||||
//low_prod <<= 16;
|
||||
SHL(64, R(long_prod), Imm8(16));
|
||||
//low_prod |= g_dsp.r[DSP_REG_PRODL];
|
||||
OR(16, R(long_prod), MDisp(R11, STRUCT_OFFSET(g_dsp.r, prod.l)));
|
||||
//return val;
|
||||
#else
|
||||
// MOV(64, R(R11), ImmPtr(&g_dsp.r));
|
||||
//s64 val = (s8)(u8)g_dsp.r[DSP_REG_PRODH];
|
||||
MOV(64, R(long_prod), MDisp(R11, STRUCT_OFFSET(g_dsp.r, prod.val)));
|
||||
MOV(64, R(R11), R(long_prod));
|
||||
OpArg reg;
|
||||
gpr.getReg(DSP_REG_PROD_64, reg);
|
||||
X64Reg tmp;
|
||||
gpr.getFreeXReg(tmp);
|
||||
MOV(64, R(long_prod), reg);
|
||||
MOV(64, R(tmp), R(long_prod));
|
||||
SHL(64, R(long_prod), Imm8(64-40));//sign extend
|
||||
SAR(64, R(long_prod), Imm8(64-40));
|
||||
SHR(64, R(R11), Imm8(48));
|
||||
SHL(64, R(R11), Imm8(16));
|
||||
ADD(64, R(long_prod), R(R11));
|
||||
MOV(64, R(R11), ImmPtr(&g_dsp.r));
|
||||
SHR(64, R(tmp), Imm8(48));
|
||||
SHL(64, R(tmp), Imm8(16));
|
||||
ADD(64, R(long_prod), R(tmp));
|
||||
gpr.putXReg(tmp);
|
||||
gpr.putReg(DSP_REG_PROD_64, false);
|
||||
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -481,28 +458,18 @@ void DSPEmitter::get_long_prod_round_prodl(X64Reg long_prod)
|
|||
void DSPEmitter::set_long_prod()
|
||||
{
|
||||
#ifdef _M_X64
|
||||
#if 0
|
||||
OpArg reg;
|
||||
gpr.getReg(DSP_REG_PROD_64, reg, false);
|
||||
X64Reg tmp;
|
||||
gpr.getFreeXReg(tmp);
|
||||
|
||||
MOV(64, R(tmp), Imm64(0x000000ffffffffffULL));
|
||||
AND(64, R(RAX), R(tmp));
|
||||
// g_dsp.r[DSP_REG_PRODL] = (u16)val;
|
||||
// MOV(64, R(R11), ImmPtr(&g_dsp.r));
|
||||
MOV(16, MDisp(R11, STRUCT_OFFSET(g_dsp.r, prod.l)), R(AX));
|
||||
// val >>= 16;
|
||||
SAR(64, R(RAX), Imm8(16));
|
||||
// g_dsp.r[DSP_REG_PRODM] = (u16)val;
|
||||
MOV(16, MDisp(R11, STRUCT_OFFSET(g_dsp.r, prod.m)), R(AX));
|
||||
// val >>= 16;
|
||||
SAR(64, R(RAX), Imm8(16));
|
||||
// g_dsp.r[DSP_REG_PRODH] = (u8)val;
|
||||
MOVSX(64, 8, RAX, R(AL));
|
||||
MOV(8, MDisp(R11, STRUCT_OFFSET(g_dsp.r, prod.h)), R(AL));
|
||||
// g_dsp.r[DSP_REG_PRODM2] = 0;
|
||||
MOV(16, MDisp(R11, STRUCT_OFFSET(g_dsp.r, prod.m2)), Imm16(0));
|
||||
#else
|
||||
MOV(64, R(R11), Imm64(0x000000ffffffffffULL));
|
||||
AND(64, R(RAX), R(R11));
|
||||
// g_dsp.r[DSP_REG_PRODL] = (u16)val;
|
||||
MOV(64, R(R11), ImmPtr(&g_dsp.r));
|
||||
MOV(64, MDisp(R11, STRUCT_OFFSET(g_dsp.r, prod.val)), R(RAX));
|
||||
#endif
|
||||
MOV(64, reg, R(RAX));
|
||||
|
||||
gpr.putXReg(tmp);
|
||||
gpr.putReg(DSP_REG_PROD_64, true);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -528,113 +495,88 @@ void DSPEmitter::round_long_acc(X64Reg long_acc)
|
|||
#endif
|
||||
}
|
||||
|
||||
// Returns s64 in RAX
|
||||
// Returns s64 in acc
|
||||
void DSPEmitter::get_long_acc(int _reg, X64Reg acc)
|
||||
{
|
||||
#ifdef _M_X64
|
||||
#if 0
|
||||
// s64 high = (s64)(s8)g_dsp.r[DSP_REG_ACH0 + reg] << 32;
|
||||
// MOV(64, R(R11), ImmPtr(&g_dsp.r));
|
||||
MOVSX(64, 8, acc, MDisp(R11, STRUCT_OFFSET(g_dsp.r, ac[_reg].h)));
|
||||
SHL(64, R(acc), Imm8(16));
|
||||
// u32 mid_low = ((u32)g_dsp.r[DSP_REG_ACM0 + reg] << 16) | g_dsp.r[DSP_REG_ACL0 + reg];
|
||||
OR(16, R(acc), MDisp(R11, STRUCT_OFFSET(g_dsp.r, ac[_reg].m)));
|
||||
SHL(64, R(acc), Imm8(16));
|
||||
OR(16, R(acc), MDisp(R11, STRUCT_OFFSET(g_dsp.r, ac[_reg].l)));
|
||||
// return high | mid_low;
|
||||
#else
|
||||
// s64 high = (s64)(s8)g_dsp.r[DSP_REG_ACH0 + reg] << 32;
|
||||
// MOV(64, R(R11), ImmPtr(&g_dsp.r));
|
||||
MOV(64, R(acc), MDisp(R11, STRUCT_OFFSET(g_dsp.r, ac[_reg].val)));
|
||||
SHL(64, R(acc), Imm8(64-40));//sign extend
|
||||
SAR(64, R(acc), Imm8(64-40));
|
||||
#endif
|
||||
OpArg reg;
|
||||
gpr.getReg(DSP_REG_ACC0_64+_reg, reg);
|
||||
MOV(64, R(acc), reg);
|
||||
gpr.putReg(DSP_REG_ACC0_64+_reg, false);
|
||||
#endif
|
||||
}
|
||||
|
||||
// In: RAX = s64 val
|
||||
// Clobbers the input reg
|
||||
// In: acc = s64 val
|
||||
void DSPEmitter::set_long_acc(int _reg, X64Reg acc)
|
||||
{
|
||||
#ifdef _M_X64
|
||||
#if 0
|
||||
// g_dsp.r[DSP_REG_ACL0 + _reg] = (u16)val;
|
||||
// MOV(64, R(R11), ImmPtr(&g_dsp.r));
|
||||
MOV(16, MDisp(R11, STRUCT_OFFSET(g_dsp.r, ac[_reg].l)), R(acc));
|
||||
// val >>= 16;
|
||||
SHR(64, R(acc), Imm8(16));
|
||||
// g_dsp.r[DSP_REG_ACM0 + _reg] = (u16)val;
|
||||
MOV(16, MDisp(R11, STRUCT_OFFSET(g_dsp.r, ac[_reg].m)), R(acc));
|
||||
// val >>= 16;
|
||||
SHR(64, R(acc), Imm8(16));
|
||||
// g_dsp.r[DSP_REG_ACH0 + _reg] = (u16)(s16)(s8)(u8)val;
|
||||
MOVSX(64, 8, acc, R(acc));
|
||||
MOV(16, MDisp(R11, STRUCT_OFFSET(g_dsp.r, ac[_reg].h)), R(acc));
|
||||
#else
|
||||
SHL(64, R(acc), Imm8(64-40));//sign extend
|
||||
SAR(64, R(acc), Imm8(64-40));
|
||||
// g_dsp.r[DSP_REG_ACL0 + _reg] = (u16)val;
|
||||
// MOV(64, R(R11), ImmPtr(&g_dsp.r));
|
||||
MOV(64, MDisp(R11, STRUCT_OFFSET(g_dsp.r, ac[_reg].val)), R(acc));
|
||||
#endif
|
||||
OpArg reg;
|
||||
gpr.getReg(DSP_REG_ACC0_64+_reg, reg, false);
|
||||
MOV(64, reg, R(acc));
|
||||
gpr.putReg(DSP_REG_ACC0_64+_reg);
|
||||
#endif
|
||||
}
|
||||
|
||||
// Returns s16 in AX
|
||||
void DSPEmitter::get_acc_m(int _reg, X64Reg acm)
|
||||
{
|
||||
// return g_dsp.r[DSP_REG_ACM0 + _reg];
|
||||
#ifdef _M_X64
|
||||
// MOV(64, R(R11), ImmPtr(&g_dsp.r));
|
||||
MOVSX(64, 16, acm, MDisp(R11, STRUCT_OFFSET(g_dsp.r, ac[_reg].m)));
|
||||
#endif
|
||||
}
|
||||
|
||||
// Returns s16 in AX
|
||||
void DSPEmitter::set_acc_m(int _reg)
|
||||
void DSPEmitter::get_acc_l(int _reg, X64Reg acl, bool sign)
|
||||
{
|
||||
// return g_dsp.r[DSP_REG_ACM0 + _reg];
|
||||
#ifdef _M_X64
|
||||
// MOV(64, R(R11), ImmPtr(&g_dsp.r));
|
||||
MOV(16, MDisp(R11, STRUCT_OFFSET(g_dsp.r, ac[_reg].m)), R(RAX));
|
||||
#endif
|
||||
gpr.readReg(_reg+DSP_REG_ACL0, acl, sign?SIGN:ZERO);
|
||||
}
|
||||
|
||||
void DSPEmitter::set_acc_l(int _reg, OpArg arg)
|
||||
{
|
||||
// return g_dsp.r[DSP_REG_ACM0 + _reg];
|
||||
gpr.writeReg(_reg+DSP_REG_ACL0,arg);
|
||||
}
|
||||
|
||||
// Returns s16 in AX
|
||||
void DSPEmitter::get_acc_m(int _reg, X64Reg acm, bool sign)
|
||||
{
|
||||
// return g_dsp.r[DSP_REG_ACM0 + _reg];
|
||||
gpr.readReg(_reg+DSP_REG_ACM0, acm, sign?SIGN:ZERO);
|
||||
}
|
||||
|
||||
// In: s16 in AX
|
||||
void DSPEmitter::set_acc_m(int _reg, OpArg arg)
|
||||
{
|
||||
// return g_dsp.r.ac[_reg].m;
|
||||
gpr.writeReg(_reg+DSP_REG_ACM0,arg);
|
||||
}
|
||||
|
||||
// Returns s16 in AX
|
||||
void DSPEmitter::get_acc_h(int _reg, X64Reg ach, bool sign)
|
||||
{
|
||||
// return g_dsp.r.ac[_reg].h;
|
||||
gpr.readReg(_reg+DSP_REG_ACH0, ach, sign?SIGN:ZERO);
|
||||
}
|
||||
|
||||
// In: s16 in AX
|
||||
void DSPEmitter::set_acc_h(int _reg, OpArg arg)
|
||||
{
|
||||
// return g_dsp.r[DSP_REG_ACM0 + _reg];
|
||||
gpr.writeReg(_reg+DSP_REG_ACH0,arg);
|
||||
}
|
||||
|
||||
// Returns u32 in EAX
|
||||
void DSPEmitter::get_long_acx(int _reg, X64Reg acx)
|
||||
{
|
||||
// return ((u32)g_dsp.r[DSP_REG_AXH0 + _reg] << 16) | g_dsp.r[DSP_REG_AXL0 + _reg];
|
||||
#ifdef _M_X64
|
||||
#if 0
|
||||
// MOV(64, R(R11), ImmPtr(&g_dsp.r));
|
||||
MOVSX(64, 16, acx, MDisp(R11, STRUCT_OFFSET(g_dsp.r, ax[_reg].h)));
|
||||
SHL(64, R(acx), Imm8(16));
|
||||
OR(16, R(acx), MDisp(R11, STRUCT_OFFSET(g_dsp.r, ax[_reg].l)));
|
||||
#else
|
||||
// MOV(64, R(R11), ImmPtr(&g_dsp.r));
|
||||
MOVSX(64, 32, acx, MDisp(R11, STRUCT_OFFSET(g_dsp.r, ax[_reg].val)));
|
||||
#endif
|
||||
#endif
|
||||
gpr.readReg(_reg+DSP_REG_AX0_32, acx, SIGN);
|
||||
}
|
||||
|
||||
// Returns s16 in EAX
|
||||
void DSPEmitter::get_ax_l(int _reg, X64Reg axl)
|
||||
{
|
||||
// return (s16)g_dsp.r[DSP_REG_AXL0 + _reg];
|
||||
#ifdef _M_X64
|
||||
// MOV(64, R(R11), ImmPtr(&g_dsp.r));
|
||||
MOVSX(64, 16, axl, MDisp(R11, STRUCT_OFFSET(g_dsp.r, ax[_reg].l)));
|
||||
#endif
|
||||
gpr.readReg(_reg+DSP_REG_AXL0, axl, SIGN);
|
||||
}
|
||||
|
||||
// Returns s16 in EAX
|
||||
void DSPEmitter::get_ax_h(int _reg, X64Reg axh)
|
||||
{
|
||||
// return (s16)g_dsp.r[DSP_REG_AXH0 + _reg];
|
||||
#ifdef _M_X64
|
||||
// MOV(64, R(R11), ImmPtr(&g_dsp.r));
|
||||
MOVSX(64, 16, axh, MDisp(R11, STRUCT_OFFSET(g_dsp.r, ax[_reg].h)));
|
||||
#endif
|
||||
gpr.readReg(_reg+DSP_REG_AXH0, axh, SIGN);
|
||||
}
|
||||
|
||||
void DSPEmitter::LoadDSPRegs()
|
||||
|
@ -642,10 +584,13 @@ void DSPEmitter::LoadDSPRegs()
|
|||
#ifdef _M_X64
|
||||
MOV(64, R(R11), ImmPtr(&g_dsp.r));
|
||||
#endif
|
||||
|
||||
// Load DSP register state here...
|
||||
gpr.loadStaticRegs();
|
||||
}
|
||||
|
||||
void DSPEmitter::SaveDSPRegs()
|
||||
{
|
||||
// Save DSP register state here...
|
||||
gpr.saveStaticRegs();
|
||||
}
|
||||
|
|
|
@ -18,57 +18,4 @@
|
|||
#ifndef __DSPJITUTIL_H__
|
||||
#define __DSPJITUTIL_H__
|
||||
|
||||
#include "../DSPMemoryMap.h"
|
||||
#include "../DSPHWInterface.h"
|
||||
#include "../DSPEmitter.h"
|
||||
|
||||
static u16 *reg_ptr(int reg) {
|
||||
switch(reg) {
|
||||
case DSP_REG_AR0:
|
||||
case DSP_REG_AR1:
|
||||
case DSP_REG_AR2:
|
||||
case DSP_REG_AR3:
|
||||
return &g_dsp.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];
|
||||
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];
|
||||
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];
|
||||
case DSP_REG_ACH0:
|
||||
case DSP_REG_ACH1:
|
||||
return &g_dsp.r.ac[reg - DSP_REG_ACH0].h;
|
||||
case DSP_REG_CR: return &g_dsp.r.cr;
|
||||
case DSP_REG_SR: return &g_dsp.r.sr;
|
||||
case DSP_REG_PRODL: return &g_dsp.r.prod.l;
|
||||
case DSP_REG_PRODM: return &g_dsp.r.prod.m;
|
||||
case DSP_REG_PRODH: return &g_dsp.r.prod.h;
|
||||
case DSP_REG_PRODM2: return &g_dsp.r.prod.m2;
|
||||
case DSP_REG_AXL0:
|
||||
case DSP_REG_AXL1:
|
||||
return &g_dsp.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;
|
||||
case DSP_REG_ACL0:
|
||||
case DSP_REG_ACL1:
|
||||
return &g_dsp.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;
|
||||
default:
|
||||
_assert_msg_(DSP_JIT, 0, "cannot happen");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /*__DSPJITUTIL_H__*/
|
||||
|
|
|
@ -31,6 +31,7 @@ files = [
|
|||
"Jit/DSPJitLoadStore.cpp",
|
||||
"Jit/DSPJitMultiplier.cpp",
|
||||
"Jit/DSPJitMisc.cpp",
|
||||
"Jit/DSPJitRegCache.cpp",
|
||||
]
|
||||
|
||||
env.StaticLibrary(env['local_libs'] + 'dspcore', files)
|
||||
|
|
Loading…
Reference in New Issue