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:
pierre 2011-01-14 18:00:25 +00:00
parent c99f0d03a4
commit fb1ebd8022
17 changed files with 1196 additions and 882 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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 &reg);
//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*/

View File

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

View File

@ -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__*/

View File

@ -31,6 +31,7 @@ files = [
"Jit/DSPJitLoadStore.cpp",
"Jit/DSPJitMultiplier.cpp",
"Jit/DSPJitMisc.cpp",
"Jit/DSPJitRegCache.cpp",
]
env.StaticLibrary(env['local_libs'] + 'dspcore', files)