summaryrefslogtreecommitdiff
path: root/Source/Core
diff options
context:
space:
mode:
authorpierre <pierre@pirsoft.de>2010-11-07 23:43:26 +0000
committerpierre <pierre@pirsoft.de>2010-11-07 23:43:26 +0000
commit2e0274dd1f42e070d08edfbbf683aa8f4e4dc849 (patch)
tree40e1761e33ae37297b5d6208044cf0105bd1eb67 /Source/Core
parent874dab37f893ccd6d22b6dcc750e665405c0b755 (diff)
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
Diffstat (limited to 'Source/Core')
-rw-r--r--Source/Core/DSPCore/Src/DSPEmitter.cpp2
-rw-r--r--Source/Core/DSPCore/Src/DSPEmitter.h4
-rw-r--r--Source/Core/DSPCore/Src/DSPTables.cpp52
-rw-r--r--Source/Core/DSPCore/Src/Jit/DSPJitExtOps.cpp368
4 files changed, 167 insertions, 259 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},
-
- {"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},
-
- {"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},
-
- {"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, 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},
+ {"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},
+
+ {"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},
+
+ {"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},
+
+ {"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