Core/DSPCore: Implement Jit emitters for all extended operations.
May break things, although my testing didn't reveal any regressions. git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@6357 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
parent
874dab37f8
commit
2e0274dd1f
|
@ -29,7 +29,7 @@
|
|||
|
||||
using namespace Gen;
|
||||
|
||||
DSPEmitter::DSPEmitter() : storeIndex(-1)
|
||||
DSPEmitter::DSPEmitter() : storeIndex(-1), storeIndex2(-1)
|
||||
{
|
||||
m_compiledCode = NULL;
|
||||
|
||||
|
|
|
@ -63,8 +63,9 @@ public:
|
|||
void pushExtValueFromReg(u16 dreg, u16 sreg);
|
||||
void popExtValueToReg();
|
||||
void pushExtValueFromMem(u16 dreg, u16 sreg);
|
||||
|
||||
void pushExtValueFromMem2(u16 dreg, u16 sreg);
|
||||
void zeroWriteBackLog(const UDSPInstruction opc);
|
||||
|
||||
// Ext commands
|
||||
void l(const UDSPInstruction opc);
|
||||
void ln(const UDSPInstruction opc);
|
||||
|
@ -111,6 +112,7 @@ private:
|
|||
|
||||
// The index of the last stored ext value (compile time).
|
||||
int storeIndex;
|
||||
int storeIndex2;
|
||||
|
||||
// Counts down.
|
||||
// int cycles;
|
||||
|
|
|
@ -306,32 +306,32 @@ const DSPOPCTemplate cw =
|
|||
|
||||
const DSPOPCTemplate opcodes_ext[] =
|
||||
{
|
||||
{"XXX", 0x0000, 0x00fc, DSPInterpreter::Ext::nop, &DSPEmitter::nop, 1, 1, {{P_VAL, 1, 0, 0, 0x00ff}}, false, false},
|
||||
|
||||
{"DR", 0x0004, 0x00fc, DSPInterpreter::Ext::dr, &DSPEmitter::dr, 1, 1, {{P_REG, 1, 0, 0, 0x0003}}, false, false},
|
||||
{"IR", 0x0008, 0x00fc, DSPInterpreter::Ext::ir, &DSPEmitter::ir, 1, 1, {{P_REG, 1, 0, 0, 0x0003}}, false, false},
|
||||
{"NR", 0x000c, 0x00fc, DSPInterpreter::Ext::nr, &DSPEmitter::nr, 1, 1, {{P_REG, 1, 0, 0, 0x0003}}, false, false},
|
||||
{"MV", 0x0010, 0x00f0, DSPInterpreter::Ext::mv, &DSPEmitter::mv, 1, 2, {{P_REG18, 1, 0, 2, 0x000c}, {P_REG1C, 1, 0, 0, 0x0003}}, false, false},
|
||||
{"XXX", 0x0000, 0x00fc, DSPInterpreter::Ext::nop, &DSPEmitter::nop, 1, 1, {{P_VAL, 1, 0, 0, 0x00ff}}, false, false},
|
||||
|
||||
{"S", 0x0020, 0x00e4, DSPInterpreter::Ext::s, &DSPEmitter::s, 1, 2, {{P_PRG, 1, 0, 0, 0x0003}, {P_REG1C, 1, 0, 3, 0x0018}}, false, false},
|
||||
{"SN", 0x0024, 0x00e4, DSPInterpreter::Ext::sn, &DSPEmitter::sn, 1, 2, {{P_PRG, 1, 0, 0, 0x0003}, {P_REG1C, 1, 0, 3, 0x0018}}, false, false},
|
||||
{"DR", 0x0004, 0x00fc, DSPInterpreter::Ext::dr, &DSPEmitter::dr, 1, 1, {{P_REG, 1, 0, 0, 0x0003}}, false, false},
|
||||
{"IR", 0x0008, 0x00fc, DSPInterpreter::Ext::ir, &DSPEmitter::ir, 1, 1, {{P_REG, 1, 0, 0, 0x0003}}, false, false},
|
||||
{"NR", 0x000c, 0x00fc, DSPInterpreter::Ext::nr, &DSPEmitter::nr, 1, 1, {{P_REG, 1, 0, 0, 0x0003}}, false, false},
|
||||
{"MV", 0x0010, 0x00f0, DSPInterpreter::Ext::mv, &DSPEmitter::mv, 1, 2, {{P_REG18, 1, 0, 2, 0x000c}, {P_REG1C, 1, 0, 0, 0x0003}}, false, false},
|
||||
|
||||
{"L", 0x0040, 0x00c4, DSPInterpreter::Ext::l, NULL /*&DSPEmitter::l*/, 1, 2, {{P_REG18, 1, 0, 3, 0x0038}, {P_PRG, 1, 0, 0, 0x0003}}, false, false},
|
||||
{"LN", 0x0044, 0x00c4, DSPInterpreter::Ext::ln, NULL /*&DSPEmitter::ln*/, 1, 2, {{P_REG18, 1, 0, 3, 0x0038}, {P_PRG, 1, 0, 0, 0x0003}}, false, false},
|
||||
{"S", 0x0020, 0x00e4, DSPInterpreter::Ext::s, &DSPEmitter::s, 1, 2, {{P_PRG, 1, 0, 0, 0x0003}, {P_REG1C, 1, 0, 3, 0x0018}}, false, false},
|
||||
{"SN", 0x0024, 0x00e4, DSPInterpreter::Ext::sn, &DSPEmitter::sn, 1, 2, {{P_PRG, 1, 0, 0, 0x0003}, {P_REG1C, 1, 0, 3, 0x0018}}, false, false},
|
||||
|
||||
{"LS", 0x0080, 0x00ce, DSPInterpreter::Ext::ls, &DSPEmitter::ls, 1, 2, {{P_REG18, 1, 0, 4, 0x0030}, {P_ACCM, 1, 0, 0, 0x0001}}, false, false},
|
||||
{"SL", 0x0082, 0x00ce, DSPInterpreter::Ext::sl, &DSPEmitter::sl, 1, 2, {{P_ACCM, 1, 0, 0, 0x0001}, {P_REG18, 1, 0, 4, 0x0030}}, false, false},
|
||||
{"LSN", 0x0084, 0x00ce, DSPInterpreter::Ext::lsn, &DSPEmitter::lsn, 1, 2, {{P_REG18, 1, 0, 4, 0x0030}, {P_ACCM, 1, 0, 0, 0x0001}}, false, false},
|
||||
{"SLN", 0x0086, 0x00ce, DSPInterpreter::Ext::sln, &DSPEmitter::sln, 1, 2, {{P_ACCM, 1, 0, 0, 0x0001}, {P_REG18, 1, 0, 4, 0x0030}}, false, false},
|
||||
{"LSM", 0x0088, 0x00ce, DSPInterpreter::Ext::lsm, &DSPEmitter::lsm, 1, 2, {{P_REG18, 1, 0, 4, 0x0030}, {P_ACCM, 1, 0, 0, 0x0001}}, false, false},
|
||||
{"SLM", 0x008a, 0x00ce, DSPInterpreter::Ext::slm, &DSPEmitter::slm, 1, 2, {{P_ACCM, 1, 0, 0, 0x0001}, {P_REG18, 1, 0, 4, 0x0030}}, false, false},
|
||||
{"LSNM", 0x008c, 0x00ce, DSPInterpreter::Ext::lsnm, &DSPEmitter::lsnm, 1, 2, {{P_REG18, 1, 0, 4, 0x0030}, {P_ACCM, 1, 0, 0, 0x0001}}, false, false},
|
||||
{"SLNM", 0x008e, 0x00ce, DSPInterpreter::Ext::slnm, &DSPEmitter::slnm, 1, 2, {{P_ACCM, 1, 0, 0, 0x0001}, {P_REG18, 1, 0, 4, 0x0030}}, false, false},
|
||||
{"L", 0x0040, 0x00c4, DSPInterpreter::Ext::l, &DSPEmitter::l, 1, 2, {{P_REG18, 1, 0, 3, 0x0038}, {P_PRG, 1, 0, 0, 0x0003}}, false, false},
|
||||
{"LN", 0x0044, 0x00c4, DSPInterpreter::Ext::ln, &DSPEmitter::ln, 1, 2, {{P_REG18, 1, 0, 3, 0x0038}, {P_PRG, 1, 0, 0, 0x0003}}, false, false},
|
||||
|
||||
{"LD", 0x00c0, 0x00cc, DSPInterpreter::Ext::ld, NULL /*&DSPEmitter::ld*/, 1, 3, {{P_REGM18, 1, 0, 4, 0x0020}, {P_REGM19, 1, 0, 3, 0x0010}, {P_PRG, 1, 0, 0, 0x0003}}, false, false},
|
||||
{"LDN", 0x00c4, 0x00cc, DSPInterpreter::Ext::ldn, NULL /*&DSPEmitter::ldn*/, 1, 3, {{P_REGM18, 1, 0, 4, 0x0020}, {P_REGM19, 1, 0, 3, 0x0010}, {P_PRG, 1, 0, 0, 0x0003}}, false, false},
|
||||
{"LDM", 0x00c8, 0x00cc, DSPInterpreter::Ext::ldm, NULL /*&DSPEmitter::ldm*/, 1, 3, {{P_REGM18, 1, 0, 4, 0x0020}, {P_REGM19, 1, 0, 3, 0x0010}, {P_PRG, 1, 0, 0, 0x0003}}, false, false},
|
||||
{"LDNM", 0x00cc, 0x00cc, DSPInterpreter::Ext::ldnm, NULL /*&DSPEmitter::ldnm*/, 1, 3, {{P_REGM18, 1, 0, 4, 0x0020}, {P_REGM19, 1, 0, 3, 0x0010}, {P_PRG, 1, 0, 0, 0x0003}}, false, false},
|
||||
{"LS", 0x0080, 0x00ce, DSPInterpreter::Ext::ls, &DSPEmitter::ls, 1, 2, {{P_REG18, 1, 0, 4, 0x0030}, {P_ACCM, 1, 0, 0, 0x0001}}, false, false},
|
||||
{"SL", 0x0082, 0x00ce, DSPInterpreter::Ext::sl, &DSPEmitter::sl, 1, 2, {{P_ACCM, 1, 0, 0, 0x0001}, {P_REG18, 1, 0, 4, 0x0030}}, false, false},
|
||||
{"LSN", 0x0084, 0x00ce, DSPInterpreter::Ext::lsn, &DSPEmitter::lsn, 1, 2, {{P_REG18, 1, 0, 4, 0x0030}, {P_ACCM, 1, 0, 0, 0x0001}}, false, false},
|
||||
{"SLN", 0x0086, 0x00ce, DSPInterpreter::Ext::sln, &DSPEmitter::sln, 1, 2, {{P_ACCM, 1, 0, 0, 0x0001}, {P_REG18, 1, 0, 4, 0x0030}}, false, false},
|
||||
{"LSM", 0x0088, 0x00ce, DSPInterpreter::Ext::lsm, &DSPEmitter::lsm, 1, 2, {{P_REG18, 1, 0, 4, 0x0030}, {P_ACCM, 1, 0, 0, 0x0001}}, false, false},
|
||||
{"SLM", 0x008a, 0x00ce, DSPInterpreter::Ext::slm, &DSPEmitter::slm, 1, 2, {{P_ACCM, 1, 0, 0, 0x0001}, {P_REG18, 1, 0, 4, 0x0030}}, false, false},
|
||||
{"LSNM", 0x008c, 0x00ce, DSPInterpreter::Ext::lsnm, &DSPEmitter::lsnm, 1, 2, {{P_REG18, 1, 0, 4, 0x0030}, {P_ACCM, 1, 0, 0, 0x0001}}, false, false},
|
||||
{"SLNM", 0x008e, 0x00ce, DSPInterpreter::Ext::slnm, &DSPEmitter::slnm, 1, 2, {{P_ACCM, 1, 0, 0, 0x0001}, {P_REG18, 1, 0, 4, 0x0030}}, false, false},
|
||||
|
||||
{"LD", 0x00c0, 0x00cc, DSPInterpreter::Ext::ld, &DSPEmitter::ld, 1, 3, {{P_REGM18, 1, 0, 4, 0x0020}, {P_REGM19, 1, 0, 3, 0x0010}, {P_PRG, 1, 0, 0, 0x0003}}, false, false},
|
||||
{"LDN", 0x00c4, 0x00cc, DSPInterpreter::Ext::ldn, &DSPEmitter::ldn, 1, 3, {{P_REGM18, 1, 0, 4, 0x0020}, {P_REGM19, 1, 0, 3, 0x0010}, {P_PRG, 1, 0, 0, 0x0003}}, false, false},
|
||||
{"LDM", 0x00c8, 0x00cc, DSPInterpreter::Ext::ldm, &DSPEmitter::ldm, 1, 3, {{P_REGM18, 1, 0, 4, 0x0020}, {P_REGM19, 1, 0, 3, 0x0010}, {P_PRG, 1, 0, 0, 0x0003}}, false, false},
|
||||
{"LDNM", 0x00cc, 0x00cc, DSPInterpreter::Ext::ldnm, &DSPEmitter::ldnm, 1, 3, {{P_REGM18, 1, 0, 4, 0x0020}, {P_REGM19, 1, 0, 3, 0x0010}, {P_PRG, 1, 0, 0, 0x0003}}, false, false},
|
||||
};
|
||||
|
||||
const int opcodes_size = sizeof(opcodes) / sizeof(DSPOPCTemplate);
|
||||
|
|
|
@ -21,6 +21,22 @@
|
|||
|
||||
using namespace Gen;
|
||||
|
||||
/* It is safe to directly write to the address registers as they are
|
||||
neither read not written by any extendable opcode. The same is true
|
||||
for memory accesses.
|
||||
It probably even is safe to write to all registers except for
|
||||
SR, ACx.x, AXx.x and PROD, which may be modified by the main op.
|
||||
|
||||
This code uses EBX to keep the values of the registers written by
|
||||
the extended op so the main op can still access the old values.
|
||||
storeIndex and storeIndex2 control where the lower and upper 16bits
|
||||
of EBX are written to. Additionally, the upper 16bits can contain the
|
||||
original SR so we can do sign extension in 40bit mode. There is only
|
||||
the 'ld family of opcodes writing to two registers at the same time,
|
||||
and those always are AXx.x, thus no need to leave space for SR for
|
||||
sign extension.
|
||||
*/
|
||||
|
||||
// DR $arR
|
||||
// xxxx xxxx 0000 01rr
|
||||
// Decrement addressing register $arR.
|
||||
|
@ -88,32 +104,26 @@ void DSPEmitter::sn(const UDSPInstruction opc)
|
|||
void DSPEmitter::l(const UDSPInstruction opc)
|
||||
{
|
||||
u8 sreg = opc & 0x3;
|
||||
u8 dreg = ((opc >> 3) & 0x7) + DSP_REG_AXL0;
|
||||
|
||||
if ((dreg >= DSP_REG_ACM0) && (g_dsp.r[DSP_REG_SR] & SR_40_MODE_BIT))
|
||||
{
|
||||
/*
|
||||
u16 val;
|
||||
ext_dmem_read(sreg);
|
||||
MOV(16, M(&val), R(EAX));
|
||||
|
||||
writeToBackLog(0, dreg - DSP_REG_ACM0 + DSP_REG_ACH0, (val & 0x8000) ? 0xFFFF : 0x0000);
|
||||
writeToBackLog(1, dreg, val);
|
||||
writeToBackLog(2, dreg - DSP_REG_ACM0 + DSP_REG_ACL0, 0);
|
||||
increment_addr_reg(sreg);
|
||||
*/
|
||||
}
|
||||
else
|
||||
{
|
||||
ext_dmem_read(sreg);
|
||||
u8 dreg = ((opc >> 3) & 0x7) + DSP_REG_AXL0; //AX?.?, AC?.[LM]
|
||||
|
||||
pushExtValueFromMem(dreg, sreg);
|
||||
|
||||
if (dreg >= DSP_REG_ACM0) {
|
||||
//save SR too, so we can decide later.
|
||||
//even if only for one bit, can only
|
||||
//store (up to) two registers in EBX,
|
||||
//so store all of SR
|
||||
#ifdef _M_IX86 // All32
|
||||
MOV(16, M(&g_dsp.r[dreg]), R(EAX));
|
||||
MOV(16, R(EAX), M(&g_dsp.r[DSP_REG_SR]));
|
||||
#else
|
||||
MOV(64, R(R11), ImmPtr(&g_dsp.r));
|
||||
MOV(16, MDisp(R11,dreg*2), R(EAX));
|
||||
MOV(16, R(EAX), MDisp(R11,DSP_REG_SR*2));
|
||||
#endif
|
||||
increment_addr_reg(sreg);
|
||||
SHL(32, R(EAX), Imm8(16));
|
||||
OR(32, R(EBX), R(EAX));
|
||||
}
|
||||
|
||||
increment_addr_reg(sreg);
|
||||
}
|
||||
|
||||
// LN $axD.D, @$arS
|
||||
|
@ -125,29 +135,24 @@ void DSPEmitter::ln(const UDSPInstruction opc)
|
|||
u8 sreg = opc & 0x3;
|
||||
u8 dreg = ((opc >> 3) & 0x7) + DSP_REG_AXL0;
|
||||
|
||||
if ((dreg >= DSP_REG_ACM0) && (g_dsp.r[DSP_REG_SR] & SR_40_MODE_BIT))
|
||||
{
|
||||
/*
|
||||
u16 val;
|
||||
ext_dmem_read(sreg);
|
||||
MOV(16, M(&val), R(EAX));
|
||||
writeToBackLog(0, dreg - DSP_REG_ACM0 + DSP_REG_ACH0, (val & 0x8000) ? 0xFFFF : 0x0000);
|
||||
writeToBackLog(1, dreg, val);
|
||||
writeToBackLog(2, dreg - DSP_REG_ACM0 + DSP_REG_ACL0, 0);
|
||||
increase_addr_reg(sreg);
|
||||
*/
|
||||
}
|
||||
else
|
||||
{
|
||||
ext_dmem_read(sreg);
|
||||
pushExtValueFromMem(dreg, sreg);
|
||||
|
||||
if (dreg >= DSP_REG_ACM0) {
|
||||
//save SR too, so we can decide later.
|
||||
//even if only for one bit, can only
|
||||
//store (up to) two registers in EBX,
|
||||
//so store all of SR
|
||||
#ifdef _M_IX86 // All32
|
||||
MOV(16, M(&g_dsp.r[dreg]), R(EAX));
|
||||
MOV(16, R(EAX), M(&g_dsp.r[DSP_REG_SR]));
|
||||
#else
|
||||
MOV(64, R(R11), ImmPtr(&g_dsp.r));
|
||||
MOV(16, MDisp(R11,dreg*2), R(EAX));
|
||||
MOV(16, R(EAX), MDisp(R11,DSP_REG_SR*2));
|
||||
#endif
|
||||
increase_addr_reg(sreg);
|
||||
SHL(32, R(EAX), Imm8(16));
|
||||
OR(32, R(EBX), R(EAX));
|
||||
}
|
||||
|
||||
increase_addr_reg(sreg);
|
||||
}
|
||||
|
||||
// LS $axD.D, $acS.m
|
||||
|
@ -317,22 +322,16 @@ void DSPEmitter::ld(const UDSPInstruction opc)
|
|||
u8 dreg = (opc >> 5) & 0x1;
|
||||
u8 rreg = (opc >> 4) & 0x1;
|
||||
u8 sreg = opc & 0x3;
|
||||
|
||||
|
||||
if (sreg != DSP_REG_AR3) {
|
||||
|
||||
ext_dmem_read(sreg);
|
||||
#ifdef _M_IX86 // All32
|
||||
MOV(16, M(&g_dsp.r[(dreg << 1) + DSP_REG_AXL0]), R(EAX));
|
||||
#else
|
||||
MOV(64, R(R11), ImmPtr(&g_dsp.r));
|
||||
MOV(16, MDisp(R11,((dreg << 1) + DSP_REG_AXL0)*2), R(EAX));
|
||||
#endif
|
||||
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[sreg]));
|
||||
MOV(16, R(EDI), M(&g_dsp.r[DSP_REG_AR3]));
|
||||
#else
|
||||
MOV(64, R(R11), ImmPtr(&g_dsp.r));
|
||||
MOV(16, R(ESI), MDisp(R11,sreg*2));
|
||||
MOV(16, R(EDI), MDisp(R11,DSP_REG_AR3*2));
|
||||
#endif
|
||||
|
@ -340,69 +339,39 @@ void DSPEmitter::ld(const UDSPInstruction opc)
|
|||
SHR(16, R(EDI), Imm8(10));
|
||||
CMP(16, R(ESI), R(EDI));
|
||||
FixupBranch not_equal = J_CC(CC_NE);
|
||||
ext_dmem_read(sreg);
|
||||
#ifdef _M_IX86 // All32
|
||||
MOV(16, M(&g_dsp.r[(rreg << 1) + DSP_REG_AXL1]), R(EAX));
|
||||
#else
|
||||
MOV(64, R(R11), ImmPtr(&g_dsp.r));
|
||||
MOV(16, MDisp(R11,((rreg << 1) + DSP_REG_AXL1)*2), R(EAX));
|
||||
#endif
|
||||
pushExtValueFromMem2((rreg << 1) + DSP_REG_AXL1, sreg);
|
||||
FixupBranch after = J();
|
||||
SetJumpTarget(not_equal); // else
|
||||
ext_dmem_read(DSP_REG_AR3);
|
||||
#ifdef _M_IX86 // All32
|
||||
MOV(16, M(&g_dsp.r[(rreg << 1) + DSP_REG_AXL1]), R(EAX));
|
||||
#else
|
||||
MOV(64, R(R11), ImmPtr(&g_dsp.r));
|
||||
MOV(16, MDisp(R11,((rreg << 1) + DSP_REG_AXL1)*2), R(EAX));
|
||||
#endif
|
||||
pushExtValueFromMem2((rreg << 1) + DSP_REG_AXL1, DSP_REG_AR3);
|
||||
SetJumpTarget(after);
|
||||
|
||||
|
||||
increment_addr_reg(sreg);
|
||||
|
||||
|
||||
} else {
|
||||
|
||||
ext_dmem_read(dreg);
|
||||
#ifdef _M_IX86 // All32
|
||||
MOV(16, M(&g_dsp.r[rreg + DSP_REG_AXH0]), R(EAX));
|
||||
#else
|
||||
MOV(64, R(R11), ImmPtr(g_dsp.r));
|
||||
MOV(16, MDisp(R11,(rreg + DSP_REG_AXH0)*2), R(EAX));
|
||||
#endif
|
||||
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[dreg]));
|
||||
MOV(16, R(EDI), M(&g_dsp.r[DSP_REG_AR3]));
|
||||
#else
|
||||
MOV(64, R(R11), ImmPtr(&g_dsp.r));
|
||||
MOV(16, R(ESI), MDisp(R11,dreg*2));
|
||||
MOV(16, R(EDI), MDisp(R11,DSP_REG_AR3*2));
|
||||
#endif
|
||||
SHR(16, R(ESI), Imm8(10));
|
||||
SHR(16, R(EDI), Imm8(10));
|
||||
CMP(16, R(ESI), R(EDI));
|
||||
FixupBranch not_equal = J_CC(CC_NE);
|
||||
ext_dmem_read(dreg);
|
||||
#ifdef _M_IX86 // All32
|
||||
MOV(16, M(&g_dsp.r[rreg + DSP_REG_AXL0]), R(EAX));
|
||||
#else
|
||||
MOV(64, R(R11), ImmPtr(&g_dsp.r));
|
||||
MOV(16, MDisp(R11,(rreg + DSP_REG_AXL0)*2), R(EAX));
|
||||
#endif
|
||||
FixupBranch not_equal = J_CC(CC_NE);
|
||||
pushExtValueFromMem2(rreg + DSP_REG_AXL0, dreg);
|
||||
FixupBranch after = J(); // else
|
||||
SetJumpTarget(not_equal);
|
||||
ext_dmem_read(DSP_REG_AR3);
|
||||
#ifdef _M_IX86 // All32
|
||||
MOV(16, M(&g_dsp.r[rreg + DSP_REG_AXL0]), R(EAX));
|
||||
#else
|
||||
MOV(64, R(R11), ImmPtr(&g_dsp.r));
|
||||
MOV(16, MDisp(R11,(rreg + DSP_REG_AXL0)*2), R(EAX));
|
||||
#endif
|
||||
pushExtValueFromMem2(rreg + DSP_REG_AXL0, DSP_REG_AR3);
|
||||
SetJumpTarget(after);
|
||||
|
||||
|
||||
increment_addr_reg(dreg);
|
||||
}
|
||||
|
||||
|
||||
increment_addr_reg(DSP_REG_AR3);
|
||||
}
|
||||
|
||||
|
@ -414,21 +383,15 @@ void DSPEmitter::ldn(const UDSPInstruction opc)
|
|||
u8 rreg = (opc >> 4) & 0x1;
|
||||
u8 sreg = opc & 0x3;
|
||||
|
||||
|
||||
if (sreg != DSP_REG_AR3) {
|
||||
ext_dmem_read(sreg);
|
||||
#ifdef _M_IX86 // All32
|
||||
MOV(16, M(&g_dsp.r[(dreg << 1) + DSP_REG_AXL0]), R(EAX));
|
||||
#else
|
||||
MOV(64, R(R11), ImmPtr(g_dsp.r));
|
||||
MOV(16, MDisp(R11,((dreg << 1) + DSP_REG_AXL0)*2), R(EAX));
|
||||
#endif
|
||||
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[sreg]));
|
||||
MOV(16, R(EDI), M(&g_dsp.r[DSP_REG_AR3]));
|
||||
#else
|
||||
MOV(64, R(R11), ImmPtr(&g_dsp.r));
|
||||
MOV(16, R(ESI), MDisp(R11,sreg*2));
|
||||
MOV(16, R(EDI), MDisp(R11,DSP_REG_AR3*2));
|
||||
#endif
|
||||
|
@ -436,64 +399,35 @@ void DSPEmitter::ldn(const UDSPInstruction opc)
|
|||
SHR(16, R(EDI), Imm8(10));
|
||||
CMP(16, R(ESI), R(EDI));
|
||||
FixupBranch not_equal = J_CC(CC_NE);
|
||||
ext_dmem_read(sreg);
|
||||
#ifdef _M_IX86 // All32
|
||||
MOV(16, M(&g_dsp.r[(rreg << 1) + DSP_REG_AXL1]), R(EAX));
|
||||
#else
|
||||
MOV(64, R(R11), ImmPtr(&g_dsp.r));
|
||||
MOV(16, MDisp(R11,((rreg << 1) + DSP_REG_AXL1)*2), R(EAX));
|
||||
#endif
|
||||
pushExtValueFromMem2((rreg << 1) + DSP_REG_AXL1, sreg);
|
||||
FixupBranch after = J();
|
||||
SetJumpTarget(not_equal); // else
|
||||
ext_dmem_read(DSP_REG_AR3);
|
||||
#ifdef _M_IX86 // All32
|
||||
MOV(16, M(&g_dsp.r[(rreg << 1) + DSP_REG_AXL1]), R(EAX));
|
||||
#else
|
||||
MOV(64, R(R11), ImmPtr(&g_dsp.r));
|
||||
MOV(16, MDisp(R11,((rreg << 1) + DSP_REG_AXL1)*2), R(EAX));
|
||||
#endif
|
||||
pushExtValueFromMem2((rreg << 1) + DSP_REG_AXL1, DSP_REG_AR3);
|
||||
SetJumpTarget(after);
|
||||
|
||||
|
||||
increase_addr_reg(sreg);
|
||||
} else {
|
||||
ext_dmem_read(dreg);
|
||||
#ifdef _M_IX86 // All32
|
||||
MOV(16, M(&g_dsp.r[rreg + DSP_REG_AXH0]), R(EAX));
|
||||
#else
|
||||
MOV(64, R(R11), ImmPtr(g_dsp.r));
|
||||
MOV(16, MDisp(R11,(rreg + DSP_REG_AXH0)*2), R(EAX));
|
||||
#endif
|
||||
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[dreg]));
|
||||
MOV(16, R(EDI), M(&g_dsp.r[DSP_REG_AR3]));
|
||||
#else
|
||||
MOV(64, R(R11), ImmPtr(&g_dsp.r));
|
||||
MOV(16, R(ESI), MDisp(R11,dreg*2));
|
||||
MOV(16, R(EDI), MDisp(R11,DSP_REG_AR3*2));
|
||||
#endif
|
||||
SHR(16, R(ESI), Imm8(10));
|
||||
SHR(16, R(EDI), Imm8(10));
|
||||
CMP(16, R(ESI), R(EDI));
|
||||
FixupBranch not_equal = J_CC(CC_NE);
|
||||
ext_dmem_read(dreg);
|
||||
#ifdef _M_IX86 // All32
|
||||
MOV(16, M(&g_dsp.r[rreg + DSP_REG_AXL0]), R(EAX));
|
||||
#else
|
||||
MOV(64, R(R11), ImmPtr(&g_dsp.r));
|
||||
MOV(16, MDisp(R11,(rreg + DSP_REG_AXL0)*2), R(EAX));
|
||||
#endif
|
||||
FixupBranch not_equal = J_CC(CC_NE);
|
||||
pushExtValueFromMem2(rreg + DSP_REG_AXL0, dreg);
|
||||
FixupBranch after = J(); // else
|
||||
SetJumpTarget(not_equal);
|
||||
ext_dmem_read(DSP_REG_AR3);
|
||||
#ifdef _M_IX86 // All32
|
||||
MOV(16, M(&g_dsp.r[rreg + DSP_REG_AXL0]), R(EAX));
|
||||
#else
|
||||
MOV(64, R(R11), ImmPtr(&g_dsp.r));
|
||||
MOV(16, MDisp(R11,(rreg + DSP_REG_AXL0)*2), R(EAX));
|
||||
#endif
|
||||
pushExtValueFromMem2(rreg + DSP_REG_AXL0, DSP_REG_AR3);
|
||||
SetJumpTarget(after);
|
||||
|
||||
|
||||
increase_addr_reg(dreg);
|
||||
}
|
||||
|
||||
|
@ -507,21 +441,16 @@ void DSPEmitter::ldm(const UDSPInstruction opc)
|
|||
u8 dreg = (opc >> 5) & 0x1;
|
||||
u8 rreg = (opc >> 4) & 0x1;
|
||||
u8 sreg = opc & 0x3;
|
||||
|
||||
|
||||
if (sreg != DSP_REG_AR3) {
|
||||
ext_dmem_read(sreg);
|
||||
#ifdef _M_IX86 // All32
|
||||
MOV(16, M(&g_dsp.r[(dreg << 1) + DSP_REG_AXL0]), R(EAX));
|
||||
#else
|
||||
MOV(64, R(R11), ImmPtr(g_dsp.r));
|
||||
MOV(16, MDisp(R11,((dreg << 1) + DSP_REG_AXL0)*2), R(EAX));
|
||||
#endif
|
||||
|
||||
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[sreg]));
|
||||
MOV(16, R(EDI), M(&g_dsp.r[DSP_REG_AR3]));
|
||||
#else
|
||||
MOV(64, R(R11), ImmPtr(&g_dsp.r));
|
||||
MOV(16, R(ESI), MDisp(R11,sreg*2));
|
||||
MOV(16, R(EDI), MDisp(R11,DSP_REG_AR3*2));
|
||||
#endif
|
||||
|
@ -529,63 +458,33 @@ void DSPEmitter::ldm(const UDSPInstruction opc)
|
|||
SHR(16, R(EDI), Imm8(10));
|
||||
CMP(16, R(ESI), R(EDI));
|
||||
FixupBranch not_equal = J_CC(CC_NE);
|
||||
ext_dmem_read(sreg);
|
||||
#ifdef _M_IX86 // All32
|
||||
MOV(16, M(&g_dsp.r[(rreg << 1) + DSP_REG_AXL1]), R(EAX));
|
||||
#else
|
||||
MOV(64, R(R11), ImmPtr(&g_dsp.r));
|
||||
MOV(16, MDisp(R11,((rreg << 1) + DSP_REG_AXL1)*2), R(EAX));
|
||||
#endif
|
||||
FixupBranch after = J();
|
||||
pushExtValueFromMem2((rreg << 1) + DSP_REG_AXL1, sreg);
|
||||
FixupBranch after = J();
|
||||
SetJumpTarget(not_equal); // else
|
||||
ext_dmem_read(DSP_REG_AR3);
|
||||
#ifdef _M_IX86 // All32
|
||||
MOV(16, M(&g_dsp.r[(rreg << 1) + DSP_REG_AXL1]), R(EAX));
|
||||
#else
|
||||
MOV(64, R(R11), ImmPtr(&g_dsp.r));
|
||||
MOV(16, MDisp(R11,((rreg << 1) + DSP_REG_AXL1)*2), R(EAX));
|
||||
#endif
|
||||
pushExtValueFromMem2((rreg << 1) + DSP_REG_AXL1, DSP_REG_AR3);
|
||||
SetJumpTarget(after);
|
||||
|
||||
|
||||
increment_addr_reg(sreg);
|
||||
} else {
|
||||
ext_dmem_read(dreg);
|
||||
#ifdef _M_IX86 // All32
|
||||
MOV(16, M(&g_dsp.r[rreg + DSP_REG_AXH0]), R(EAX));
|
||||
#else
|
||||
MOV(64, R(R11), ImmPtr(g_dsp.r));
|
||||
MOV(16, MDisp(R11,(rreg + DSP_REG_AXH0)*2), R(EAX));
|
||||
#endif
|
||||
|
||||
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[dreg]));
|
||||
MOV(16, R(EDI), M(&g_dsp.r[DSP_REG_AR3]));
|
||||
#else
|
||||
MOV(64, R(R11), ImmPtr(&g_dsp.r));
|
||||
MOV(16, R(ESI), MDisp(R11,dreg*2));
|
||||
MOV(16, R(EDI), MDisp(R11,DSP_REG_AR3*2));
|
||||
#endif
|
||||
SHR(16, R(ESI), Imm8(10));
|
||||
SHR(16, R(EDI), Imm8(10));
|
||||
CMP(16, R(ESI), R(EDI));
|
||||
FixupBranch not_equal = J_CC(CC_NE);
|
||||
ext_dmem_read(dreg);
|
||||
#ifdef _M_IX86 // All32
|
||||
MOV(16, M(&g_dsp.r[rreg + DSP_REG_AXL0]), R(EAX));
|
||||
#else
|
||||
MOV(64, R(R11), ImmPtr(&g_dsp.r));
|
||||
MOV(16, MDisp(R11,(rreg + DSP_REG_AXL0)*2), R(EAX));
|
||||
#endif
|
||||
FixupBranch not_equal = J_CC(CC_NE);
|
||||
pushExtValueFromMem2(rreg + DSP_REG_AXL0, dreg);
|
||||
FixupBranch after = J(); // else
|
||||
SetJumpTarget(not_equal);
|
||||
ext_dmem_read(DSP_REG_AR3);
|
||||
#ifdef _M_IX86 // All32
|
||||
MOV(16, M(&g_dsp.r[rreg + DSP_REG_AXL0]), R(EAX));
|
||||
#else
|
||||
MOV(64, R(R11), ImmPtr(&g_dsp.r));
|
||||
MOV(16, MDisp(R11,(rreg + DSP_REG_AXL0)*2), R(EAX));
|
||||
#endif
|
||||
pushExtValueFromMem2(rreg + DSP_REG_AXL0, DSP_REG_AR3);
|
||||
SetJumpTarget(after);
|
||||
|
||||
increment_addr_reg(dreg);
|
||||
|
@ -603,19 +502,14 @@ void DSPEmitter::ldnm(const UDSPInstruction opc)
|
|||
u8 sreg = opc & 0x3;
|
||||
|
||||
if (sreg != DSP_REG_AR3) {
|
||||
ext_dmem_read(sreg);
|
||||
#ifdef _M_IX86 // All32
|
||||
MOV(16, M(&g_dsp.r[(dreg << 1) + DSP_REG_AXL0]), R(EAX));
|
||||
#else
|
||||
MOV(64, R(R11), ImmPtr(&g_dsp.r));
|
||||
MOV(16, MDisp(R11,((dreg << 1) + DSP_REG_AXL0)*2), R(EAX));
|
||||
#endif
|
||||
|
||||
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[sreg]));
|
||||
MOV(16, R(EDI), M(&g_dsp.r[DSP_REG_AR3]));
|
||||
#else
|
||||
MOV(64, R(R11), ImmPtr(&g_dsp.r));
|
||||
MOV(16, R(ESI), MDisp(R11,sreg*2));
|
||||
MOV(16, R(EDI), MDisp(R11,DSP_REG_AR3*2));
|
||||
#endif
|
||||
|
@ -623,64 +517,35 @@ void DSPEmitter::ldnm(const UDSPInstruction opc)
|
|||
SHR(16, R(EDI), Imm8(10));
|
||||
CMP(16, R(ESI), R(EDI));
|
||||
FixupBranch not_equal = J_CC(CC_NE);
|
||||
ext_dmem_read(sreg);
|
||||
#ifdef _M_IX86 // All32
|
||||
MOV(16, M(&g_dsp.r[(rreg << 1) + DSP_REG_AXL1]), R(EAX));
|
||||
#else
|
||||
MOV(64, R(R11), ImmPtr(&g_dsp.r));
|
||||
MOV(16, MDisp(R11,((rreg << 1) + DSP_REG_AXL1)*2), R(EAX));
|
||||
#endif
|
||||
FixupBranch after = J();
|
||||
pushExtValueFromMem2((rreg << 1) + DSP_REG_AXL1, sreg);
|
||||
FixupBranch after = J();
|
||||
SetJumpTarget(not_equal); // else
|
||||
ext_dmem_read(DSP_REG_AR3);
|
||||
#ifdef _M_IX86 // All32
|
||||
MOV(16, M(&g_dsp.r[(rreg << 1) + DSP_REG_AXL1]), R(EAX));
|
||||
#else
|
||||
MOV(64, R(R11), ImmPtr(&g_dsp.r));
|
||||
MOV(16, MDisp(R11,((rreg << 1) + DSP_REG_AXL1)*2), R(EAX));
|
||||
#endif
|
||||
pushExtValueFromMem2((rreg << 1) + DSP_REG_AXL1, DSP_REG_AR3);
|
||||
SetJumpTarget(after);
|
||||
|
||||
|
||||
increase_addr_reg(sreg);
|
||||
} else {
|
||||
ext_dmem_read(dreg);
|
||||
#ifdef _M_IX86 // All32
|
||||
MOV(16, M(&g_dsp.r[rreg + DSP_REG_AXH0]), R(EAX));
|
||||
#else
|
||||
MOV(64, R(R11), ImmPtr(g_dsp.r));
|
||||
MOV(16, MDisp(R11,(rreg + DSP_REG_AXH0)*2), R(EAX));
|
||||
#endif
|
||||
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[dreg]));
|
||||
MOV(16, R(EDI), M(&g_dsp.r[DSP_REG_AR3]));
|
||||
#else
|
||||
MOV(64, R(R11), ImmPtr(&g_dsp.r));
|
||||
MOV(16, R(ESI), MDisp(R11,dreg*2));
|
||||
MOV(16, R(EDI), MDisp(R11,DSP_REG_AR3*2));
|
||||
#endif
|
||||
SHR(16, R(ESI), Imm8(10));
|
||||
SHR(16, R(EDI), Imm8(10));
|
||||
CMP(16, R(ESI), R(EDI));
|
||||
FixupBranch not_equal = J_CC(CC_NE);
|
||||
ext_dmem_read(dreg);
|
||||
#ifdef _M_IX86 // All32
|
||||
MOV(16, M(&g_dsp.r[rreg + DSP_REG_AXL0]), R(EAX));
|
||||
#else
|
||||
MOV(64, R(R11), ImmPtr(&g_dsp.r));
|
||||
MOV(16, MDisp(R11,(rreg + DSP_REG_AXL0)*2), R(EAX));
|
||||
#endif
|
||||
FixupBranch not_equal = J_CC(CC_NE);
|
||||
pushExtValueFromMem2(rreg + DSP_REG_AXL0, dreg);
|
||||
FixupBranch after = J(); // else
|
||||
SetJumpTarget(not_equal);
|
||||
ext_dmem_read(DSP_REG_AR3);
|
||||
#ifdef _M_IX86 // All32
|
||||
MOV(16, M(&g_dsp.r[rreg + DSP_REG_AXL0]), R(EAX));
|
||||
#else
|
||||
MOV(64, R(R11), ImmPtr(&g_dsp.r));
|
||||
MOV(16, MDisp(R11,(rreg + DSP_REG_AXL0)*2), R(EAX));
|
||||
#endif
|
||||
pushExtValueFromMem2(rreg + DSP_REG_AXL0, DSP_REG_AR3);
|
||||
SetJumpTarget(after);
|
||||
|
||||
|
||||
increase_addr_reg(dreg);
|
||||
}
|
||||
|
||||
|
@ -707,6 +572,14 @@ void DSPEmitter::pushExtValueFromMem(u16 dreg, u16 sreg) {
|
|||
storeIndex = dreg;
|
||||
}
|
||||
|
||||
void DSPEmitter::pushExtValueFromMem2(u16 dreg, u16 sreg) {
|
||||
ext_dmem_read(sreg);
|
||||
SHL(32,R(EAX),Imm8(16));
|
||||
OR(32, R(EBX), R(EAX));
|
||||
|
||||
storeIndex2 = dreg;
|
||||
}
|
||||
|
||||
void DSPEmitter::popExtValueToReg() {
|
||||
// in practise, we rarely ever have a non-NX main op
|
||||
// with an extended op, so the OR here is either
|
||||
|
@ -722,10 +595,43 @@ void DSPEmitter::popExtValueToReg() {
|
|||
MOV(64, R(R11), ImmPtr(&g_dsp.r));
|
||||
MOV(16, MDisp(R11,storeIndex*2), R(EBX));
|
||||
#endif
|
||||
if (storeIndex >= DSP_REG_ACM0 && storeIndex2 == -1) {
|
||||
TEST(32, R(EBX), Imm32(SR_40_MODE_BIT << 16));
|
||||
FixupBranch not_40bit = J_CC(CC_Z);
|
||||
//if (g_dsp.r[DSP_REG_SR] & SR_40_MODE_BIT)
|
||||
//{
|
||||
// Sign extend into whole accum.
|
||||
//u16 val = g_dsp.r[reg];
|
||||
MOVSX(32, 16, EAX, R(EBX));
|
||||
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[storeIndex - DSP_REG_ACM0 + DSP_REG_ACH0]),
|
||||
R(EAX));
|
||||
MOV(16,M(&g_dsp.r[storeIndex - DSP_REG_ACM0 + DSP_REG_ACL0]),
|
||||
Imm16(0));
|
||||
#else
|
||||
MOV(16, MDisp(R11,(storeIndex - DSP_REG_ACM0 + DSP_REG_ACH0)*2), R(EAX));
|
||||
MOV(16, MDisp(R11,(storeIndex - DSP_REG_ACM0 + DSP_REG_ACL0)*2), Imm16(0));
|
||||
#endif
|
||||
//}
|
||||
SetJumpTarget(not_40bit);
|
||||
}
|
||||
}
|
||||
|
||||
storeIndex = -1;
|
||||
// TODO handle commands such as 'l
|
||||
|
||||
if (storeIndex2 != -1) {
|
||||
SHR(32,R(EBX),Imm8(16));
|
||||
#ifdef _M_IX86 // All32
|
||||
MOV(16, M(&g_dsp.r[storeIndex2]), R(EBX));
|
||||
#else
|
||||
MOV(64, R(R11), ImmPtr(&g_dsp.r));
|
||||
MOV(16, MDisp(R11,storeIndex2*2), R(EBX));
|
||||
#endif
|
||||
}
|
||||
storeIndex2 = -1;
|
||||
}
|
||||
|
||||
// This function is being called in the main op after all input regs were read
|
||||
|
|
Loading…
Reference in New Issue