From 2e0274dd1f42e070d08edfbbf683aa8f4e4dc849 Mon Sep 17 00:00:00 2001 From: pierre Date: Sun, 7 Nov 2010 23:43:26 +0000 Subject: [PATCH] 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 --- Source/Core/DSPCore/Src/DSPEmitter.cpp | 2 +- Source/Core/DSPCore/Src/DSPEmitter.h | 4 +- Source/Core/DSPCore/Src/DSPTables.cpp | 44 +-- Source/Core/DSPCore/Src/Jit/DSPJitExtOps.cpp | 368 +++++++------------ 4 files changed, 163 insertions(+), 255 deletions(-) diff --git a/Source/Core/DSPCore/Src/DSPEmitter.cpp b/Source/Core/DSPCore/Src/DSPEmitter.cpp index 0976d88d5a..d1f4027d10 100644 --- a/Source/Core/DSPCore/Src/DSPEmitter.cpp +++ b/Source/Core/DSPCore/Src/DSPEmitter.cpp @@ -29,7 +29,7 @@ using namespace Gen; -DSPEmitter::DSPEmitter() : storeIndex(-1) +DSPEmitter::DSPEmitter() : storeIndex(-1), storeIndex2(-1) { m_compiledCode = NULL; diff --git a/Source/Core/DSPCore/Src/DSPEmitter.h b/Source/Core/DSPCore/Src/DSPEmitter.h index 95836de01c..c703157c43 100644 --- a/Source/Core/DSPCore/Src/DSPEmitter.h +++ b/Source/Core/DSPCore/Src/DSPEmitter.h @@ -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; diff --git a/Source/Core/DSPCore/Src/DSPTables.cpp b/Source/Core/DSPCore/Src/DSPTables.cpp index e154667006..8c1c8adc01 100644 --- a/Source/Core/DSPCore/Src/DSPTables.cpp +++ b/Source/Core/DSPCore/Src/DSPTables.cpp @@ -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); diff --git a/Source/Core/DSPCore/Src/Jit/DSPJitExtOps.cpp b/Source/Core/DSPCore/Src/Jit/DSPJitExtOps.cpp index d151bf1194..a4229a7557 100644 --- a/Source/Core/DSPCore/Src/Jit/DSPJitExtOps.cpp +++ b/Source/Core/DSPCore/Src/Jit/DSPJitExtOps.cpp @@ -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