summaryrefslogtreecommitdiff
path: root/Source
diff options
context:
space:
mode:
authorpierre <pierre@pirsoft.de>2010-10-31 23:26:18 +0000
committerpierre <pierre@pirsoft.de>2010-10-31 23:26:18 +0000
commit4b9831cdce7ffa1fcb0fc5eda5e5686130096eb2 (patch)
tree31c40b514d03bf3134e0cf87c3b5518836ef957b /Source
parent2f2a76b28a0f612c2b2550d25cdae775de0614f5 (diff)
Core/DSPCore: Extended opcode handling fixes
* Make writeToBackLog private to DSPIntExtOps.cpp (JIT variants of 'l and 'ln are disabled and broken as is) * Make zeroing of the backlog conditional on doing an interpreter fallback and do it at a few more places * Fix selection of cleanup for extended opcodes. * Fix the DSP unit tests to correctly emit the function prolog/epilog (else EBX wouldn't be saved) * Add a few more DSP unit tests git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@6325 8ced0084-cf51-0410-be5f-012b33b47a6e
Diffstat (limited to 'Source')
-rw-r--r--Source/Core/DSPCore/Src/DSPEmitter.cpp11
-rw-r--r--Source/Core/DSPCore/Src/DSPEmitter.h1
-rw-r--r--Source/Core/DSPCore/Src/DSPIntExtOps.cpp7
-rw-r--r--Source/Core/DSPCore/Src/DSPIntExtOps.h7
-rw-r--r--Source/Core/DSPCore/Src/Jit/DSPJitExtOps.cpp33
-rw-r--r--Source/Core/DSPCore/Src/Jit/DSPJitMisc.cpp6
-rw-r--r--Source/UnitTests/AudioJitTests.cpp217
-rw-r--r--Source/UnitTests/DSPJitTester.cpp2
8 files changed, 269 insertions, 15 deletions
diff --git a/Source/Core/DSPCore/Src/DSPEmitter.cpp b/Source/Core/DSPCore/Src/DSPEmitter.cpp
index 7b0a27c362..0976d88d5a 100644
--- a/Source/Core/DSPCore/Src/DSPEmitter.cpp
+++ b/Source/Core/DSPCore/Src/DSPEmitter.cpp
@@ -93,6 +93,7 @@ void DSPEmitter::checkExceptions(u32 retval) {
void DSPEmitter::EmitInstruction(UDSPInstruction inst)
{
const DSPOPCTemplate *tinst = GetOpTemplate(inst);
+ bool ext_is_jit = false;
// Call extended
if (tinst->extended) {
@@ -100,15 +101,19 @@ void DSPEmitter::EmitInstruction(UDSPInstruction inst)
if (! extOpTable[inst & 0x7F]->jitFunc) {
// Fall back to interpreter
ABI_CallFunctionC16((void*)extOpTable[inst & 0x7F]->intFunc, inst);
+ ext_is_jit = false;
} else {
(this->*extOpTable[inst & 0x7F]->jitFunc)(inst);
+ ext_is_jit = true;
}
} else {
if (!extOpTable[inst & 0xFF]->jitFunc) {
// Fall back to interpreter
ABI_CallFunctionC16((void*)extOpTable[inst & 0xFF]->intFunc, inst);
+ ext_is_jit = false;
} else {
(this->*extOpTable[inst & 0xFF]->jitFunc)(inst);
+ ext_is_jit = true;
}
}
}
@@ -125,8 +130,10 @@ void DSPEmitter::EmitInstruction(UDSPInstruction inst)
// Backlog
if (tinst->extended) {
- if (! extOpTable[inst & 0x7F]->jitFunc) {
- ABI_CallFunction((void*)applyWriteBackLog);
+ if (!ext_is_jit) {
+ //need to call the online cleanup function because
+ //the writeBackLog gets populated at runtime
+ ABI_CallFunction((void*)::applyWriteBackLog);
} else {
popExtValueToReg();
}
diff --git a/Source/Core/DSPCore/Src/DSPEmitter.h b/Source/Core/DSPCore/Src/DSPEmitter.h
index 8ddd9aa368..95836de01c 100644
--- a/Source/Core/DSPCore/Src/DSPEmitter.h
+++ b/Source/Core/DSPCore/Src/DSPEmitter.h
@@ -64,6 +64,7 @@ public:
void popExtValueToReg();
void pushExtValueFromMem(u16 dreg, u16 sreg);
+ void zeroWriteBackLog(const UDSPInstruction opc);
// Ext commands
void l(const UDSPInstruction opc);
void ln(const UDSPInstruction opc);
diff --git a/Source/Core/DSPCore/Src/DSPIntExtOps.cpp b/Source/Core/DSPCore/Src/DSPIntExtOps.cpp
index 0486d2a238..ce4f29585e 100644
--- a/Source/Core/DSPCore/Src/DSPIntExtOps.cpp
+++ b/Source/Core/DSPCore/Src/DSPIntExtOps.cpp
@@ -28,6 +28,13 @@
// registers will wrap in odd ways, dictated by the corresponding wrapping
// register, WR0-3.
+// Needs comments.
+inline static void writeToBackLog(int i, int idx, u16 value)
+{
+ writeBackLog[i] = value;
+ writeBackLogIdx[i] = idx;
+}
+
namespace DSPInterpreter
{
diff --git a/Source/Core/DSPCore/Src/DSPIntExtOps.h b/Source/Core/DSPCore/Src/DSPIntExtOps.h
index c154af24ee..46b809ca14 100644
--- a/Source/Core/DSPCore/Src/DSPIntExtOps.h
+++ b/Source/Core/DSPCore/Src/DSPIntExtOps.h
@@ -61,11 +61,4 @@ void nop(const UDSPInstruction opc);
} // end namespace Ext
} // end namespace DSPinterpeter
-// Needs comments.
-inline void writeToBackLog(int i, int idx, u16 value)
-{
- writeBackLog[i] = value;
- writeBackLogIdx[i] = idx;
-}
-
#endif
diff --git a/Source/Core/DSPCore/Src/Jit/DSPJitExtOps.cpp b/Source/Core/DSPCore/Src/Jit/DSPJitExtOps.cpp
index fa5e1743cd..d151bf1194 100644
--- a/Source/Core/DSPCore/Src/Jit/DSPJitExtOps.cpp
+++ b/Source/Core/DSPCore/Src/Jit/DSPJitExtOps.cpp
@@ -19,8 +19,6 @@
#include "x64Emitter.h"
#include "ABI.h"
-#include "../DSPIntExtOps.h" // remove when getting rid of writebacklog
-// See docs in the interpeter
using namespace Gen;
// DR $arR
@@ -94,6 +92,7 @@ void DSPEmitter::l(const UDSPInstruction opc)
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));
@@ -102,6 +101,7 @@ void DSPEmitter::l(const UDSPInstruction opc)
writeToBackLog(1, dreg, val);
writeToBackLog(2, dreg - DSP_REG_ACM0 + DSP_REG_ACL0, 0);
increment_addr_reg(sreg);
+*/
}
else
{
@@ -127,6 +127,7 @@ void DSPEmitter::ln(const UDSPInstruction opc)
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));
@@ -134,6 +135,7 @@ void DSPEmitter::ln(const UDSPInstruction opc)
writeToBackLog(1, dreg, val);
writeToBackLog(2, dreg - DSP_REG_ACM0 + DSP_REG_ACL0, 0);
increase_addr_reg(sreg);
+*/
}
else
{
@@ -700,8 +702,8 @@ void DSPEmitter::pushExtValueFromReg(u16 dreg, u16 sreg) {
void DSPEmitter::pushExtValueFromMem(u16 dreg, u16 sreg) {
ext_dmem_read(sreg);
- MOV(16, R(EBX), R(EAX));
-
+ MOVZX(32, 16, EBX, R(EAX));
+
storeIndex = dreg;
}
@@ -726,3 +728,26 @@ void DSPEmitter::popExtValueToReg() {
// TODO handle commands such as 'l
}
+// This function is being called in the main op after all input regs were read
+// and before it writes into any regs. This way we can always use bitwise or to
+// apply the ext command output, because if the main op didn't change the value
+// then 0 | ext output = ext output and if it did then bitwise or is still the
+// right thing to do
+//this is only needed as long as we do fallback for ext ops
+void DSPEmitter::zeroWriteBackLog(const UDSPInstruction opc)
+{
+ const DSPOPCTemplate *tinst = GetOpTemplate(opc);
+
+ // Call extended
+ if (!tinst->extended)
+ return;
+
+ if ((opc >> 12) == 0x3) {
+ if (! extOpTable[opc & 0x7F]->jitFunc)
+ ABI_CallFunction((void*)::zeroWriteBackLog);
+ } else {
+ if (! extOpTable[opc & 0xFF]->jitFunc)
+ ABI_CallFunction((void*)::zeroWriteBackLog);
+ }
+ return;
+}
diff --git a/Source/Core/DSPCore/Src/Jit/DSPJitMisc.cpp b/Source/Core/DSPCore/Src/Jit/DSPJitMisc.cpp
index dafa3bea8f..4a2e3c6540 100644
--- a/Source/Core/DSPCore/Src/Jit/DSPJitMisc.cpp
+++ b/Source/Core/DSPCore/Src/Jit/DSPJitMisc.cpp
@@ -88,6 +88,7 @@ void DSPEmitter::nx(const UDSPInstruction opc)
void DSPEmitter::dar(const UDSPInstruction opc)
{
// g_dsp.r[opc & 0x3] = dsp_decrement_addr_reg(opc & 0x3);
+ zeroWriteBackLog(opc);
decrement_addr_reg(opc & 0x3);
}
@@ -98,6 +99,7 @@ void DSPEmitter::dar(const UDSPInstruction opc)
void DSPEmitter::iar(const UDSPInstruction opc)
{
// g_dsp.r[opc & 0x3] = dsp_increment_addr_reg(opc & 0x3);
+ zeroWriteBackLog(opc);
increment_addr_reg(opc & 0x3);
}
@@ -109,6 +111,7 @@ void DSPEmitter::subarn(const UDSPInstruction opc)
{
// u8 dreg = opc & 0x3;
// g_dsp.r[dreg] = dsp_decrease_addr_reg(dreg, (s16)g_dsp.r[DSP_REG_IX0 + dreg]);
+ zeroWriteBackLog(opc);
decrease_addr_reg(opc & 0x3);
}
@@ -123,6 +126,7 @@ void DSPEmitter::addarn(const UDSPInstruction opc)
// g_dsp.r[dreg] = dsp_increase_addr_reg(dreg, (s16)g_dsp.r[DSP_REG_IX0 + sreg]);
// From looking around it is always called with the matching index register
+ zeroWriteBackLog(opc);
increase_addr_reg(opc & 0x3);
}
@@ -180,7 +184,7 @@ void DSPEmitter::sbset(const UDSPInstruction opc)
// but it's harder to know exactly what effect they have.
void DSPEmitter::srbith(const UDSPInstruction opc)
{
- ABI_CallFunction((void *)zeroWriteBackLog);
+ zeroWriteBackLog(opc);
switch ((opc >> 8) & 0xf)
{
// M0/M2 change the multiplier mode (it can multiply by 2 for free).
diff --git a/Source/UnitTests/AudioJitTests.cpp b/Source/UnitTests/AudioJitTests.cpp
index cfabaeeb6c..4cef5931fa 100644
--- a/Source/UnitTests/AudioJitTests.cpp
+++ b/Source/UnitTests/AudioJitTests.cpp
@@ -28,6 +28,15 @@ void nx_nr()
tester.Report();
}
+void nx_mv()
+{
+ DSPJitTester tester(0x8000, 0x0010);
+ tester.AddTestData(DSP_REG_ACL0);
+ tester.AddTestData(DSP_REG_AXL0);
+ tester.TestAll(true);
+ tester.Report();
+}
+
void dar()
{
DSPJitTester tester(0x0004);
@@ -81,14 +90,205 @@ void nx_s()
{
DSPJitTester tester(0x8000, 0x0020);
tester.AddTestData(DSP_REG_AR0);
+ tester.AddTestData(DSP_REG_WR0);
tester.AddTestData(DSP_REG_ACL0);
tester.TestAll(true);
tester.Report();
}
+
+void nx_sn()
+{
+ DSPJitTester tester(0x8000, 0x0024);
+ tester.AddTestData(DSP_REG_AR0);
+ tester.AddTestData(DSP_REG_WR0);
+ tester.AddTestData(DSP_REG_IX0);
+ tester.AddTestData(DSP_REG_ACL0);
+ tester.TestAll(true);
+ tester.Report();
+}
+
+void nx_l()
+{
+
+ DSPJitTester tester(0x8000, 0x0040);
+ tester.AddTestData(DSP_REG_AR0);
+ tester.AddTestData(DSP_REG_WR0);
+ tester.AddTestData(DSP_REG_AXL0);
+ tester.TestAll(true);
+ tester.Report();
+}
+
+void set16_l()
+{
+
+ DSPJitTester tester(0x8e00, 0x0070);
+ tester.AddTestData(DSP_REG_SR, 0);
+ tester.AddTestData(DSP_REG_SR, SR_40_MODE_BIT);
+ tester.AddTestData(DSP_REG_AR0);
+ tester.AddTestData(DSP_REG_WR0);
+ tester.AddTestData(DSP_REG_ACM0);
+ tester.TestAll(true);
+ tester.Report();
+}
+
+void nx_ln()
+{
+ DSPJitTester tester(0x8000, 0x0044);
+ tester.AddTestData(DSP_REG_AR0);
+ tester.AddTestData(DSP_REG_WR0);
+ tester.AddTestData(DSP_REG_IX0);
+ tester.AddTestData(DSP_REG_AXL0);
+ tester.TestAll(true);
+ tester.Report();
+}
+
+void nx_ls()
+{
+ DSPJitTester tester1(0x8000, 0x0080);
+ tester1.AddTestData(DSP_REG_ACM0);
+ tester1.AddTestData(DSP_REG_AR0);
+ tester1.AddTestData(DSP_REG_WR0);
+ tester1.TestAll(true);
+ tester1.Report();
+
+ DSPJitTester tester2(0x8000, 0x0080);
+ tester2.AddTestData(DSP_REG_ACM0);
+ tester2.AddTestData(DSP_REG_AR3);
+ tester2.AddTestData(DSP_REG_WR3);
+ tester2.TestAll(true);
+ tester2.Report();
+}
+
+void nx_lsn()
+{
+ DSPJitTester tester1(0x8000, 0x0084);
+ tester1.AddTestData(DSP_REG_ACM0);
+ tester1.AddTestData(DSP_REG_AR0);
+ tester1.AddTestData(DSP_REG_WR0);
+ tester1.AddTestData(DSP_REG_IX0);
+ tester1.TestAll(true);
+ tester1.Report();
+
+ DSPJitTester tester2(0x8000, 0x0084);
+ tester2.AddTestData(DSP_REG_ACM0);
+ tester2.AddTestData(DSP_REG_AR3);
+ tester2.AddTestData(DSP_REG_WR3);
+ tester2.TestAll(true);
+ tester2.Report();
+}
+
+void nx_lsm()
+{
+ DSPJitTester tester1(0x8000, 0x0088);
+ tester1.AddTestData(DSP_REG_ACM0);
+ tester1.AddTestData(DSP_REG_AR0);
+ tester1.AddTestData(DSP_REG_WR0);
+ tester1.TestAll(true);
+ tester1.Report();
+
+ DSPJitTester tester2(0x8000, 0x0088);
+ tester2.AddTestData(DSP_REG_ACM0);
+ tester2.AddTestData(DSP_REG_AR3);
+ tester2.AddTestData(DSP_REG_WR3);
+ tester2.AddTestData(DSP_REG_IX3);
+ tester2.TestAll(true);
+ tester2.Report();
+}
+
+void nx_lsnm()
+{
+ DSPJitTester tester1(0x8000, 0x008c);
+ tester1.AddTestData(DSP_REG_ACM0);
+ tester1.AddTestData(DSP_REG_AR0);
+ tester1.AddTestData(DSP_REG_WR0);
+ tester1.AddTestData(DSP_REG_IX0);
+ tester1.TestAll(true);
+ tester1.Report();
+
+ DSPJitTester tester2(0x8000, 0x008c);
+ tester2.AddTestData(DSP_REG_ACM0);
+ tester2.AddTestData(DSP_REG_AR3);
+ tester2.AddTestData(DSP_REG_WR3);
+ tester2.AddTestData(DSP_REG_IX3);
+ tester2.TestAll(true);
+ tester2.Report();
+}
+
+void nx_sl()
+{
+ DSPJitTester tester1(0x8000, 0x0082);
+ tester1.AddTestData(DSP_REG_ACM0);
+ tester1.AddTestData(DSP_REG_AR0);
+ tester1.AddTestData(DSP_REG_WR0);
+ tester1.TestAll(true);
+ tester1.Report();
+
+ DSPJitTester tester2(0x8000, 0x0082);
+ tester2.AddTestData(DSP_REG_ACM0);
+ tester2.AddTestData(DSP_REG_AR3);
+ tester2.AddTestData(DSP_REG_WR3);
+ tester2.TestAll(true);
+ tester2.Report();
+}
+
+void nx_sln()
+{
+ DSPJitTester tester1(0x8000, 0x0086);
+ tester1.AddTestData(DSP_REG_ACM0);
+ tester1.AddTestData(DSP_REG_AR0);
+ tester1.AddTestData(DSP_REG_WR0);
+ tester1.AddTestData(DSP_REG_IX0);
+ tester1.TestAll(true);
+ tester1.Report();
+
+ DSPJitTester tester2(0x8000, 0x0086);
+ tester2.AddTestData(DSP_REG_ACM0);
+ tester2.AddTestData(DSP_REG_AR3);
+ tester2.AddTestData(DSP_REG_WR3);
+ tester2.TestAll(true);
+ tester2.Report();
+}
+
+void nx_slm()
+{
+ DSPJitTester tester1(0x8000, 0x008a);
+ tester1.AddTestData(DSP_REG_ACM0);
+ tester1.AddTestData(DSP_REG_AR0);
+ tester1.AddTestData(DSP_REG_WR0);
+ tester1.TestAll(true);
+ tester1.Report();
+
+ DSPJitTester tester2(0x8000, 0x008a);
+ tester2.AddTestData(DSP_REG_ACM0);
+ tester2.AddTestData(DSP_REG_AR3);
+ tester2.AddTestData(DSP_REG_WR3);
+ tester2.AddTestData(DSP_REG_IX3);
+ tester2.TestAll(true);
+ tester2.Report();
+}
+
+void nx_slnm()
+{
+ DSPJitTester tester1(0x8000, 0x008e);
+ tester1.AddTestData(DSP_REG_ACM0);
+ tester1.AddTestData(DSP_REG_AR0);
+ tester1.AddTestData(DSP_REG_WR0);
+ tester1.AddTestData(DSP_REG_IX0);
+ tester1.TestAll(true);
+ tester1.Report();
+
+ DSPJitTester tester2(0x8000, 0x008e);
+ tester2.AddTestData(DSP_REG_ACM0);
+ tester2.AddTestData(DSP_REG_AR3);
+ tester2.AddTestData(DSP_REG_WR3);
+ tester2.AddTestData(DSP_REG_IX3);
+ tester2.TestAll(true);
+ tester2.Report();
+}
+
void AudioJitTests()
{
DSPJitTester::Initialize();
-
dar();
iar();
subarn();
@@ -99,7 +299,22 @@ void AudioJitTests()
nx_ir();
nx_dr();
nx_nr();
+ nx_mv();
+
+ set16_l();
+
nx_s();
+ nx_sn();
+ nx_l();
+ nx_ln();
+ nx_ls();
+ nx_lsn();
+ nx_lsm();
+ nx_lsnm();
+ nx_sl();
+ nx_sln();
+ nx_slm();
+ nx_slnm();
}
//required to be able to link against DSPCore
diff --git a/Source/UnitTests/DSPJitTester.cpp b/Source/UnitTests/DSPJitTester.cpp
index 2012ee09b8..c0b95ca35e 100644
--- a/Source/UnitTests/DSPJitTester.cpp
+++ b/Source/UnitTests/DSPJitTester.cpp
@@ -41,7 +41,9 @@ SDSP DSPJitTester::RunJit(SDSP dsp_settings)
ResetJit();
memcpy(&g_dsp, &dsp_settings, sizeof(SDSP));
const u8* code = jit.GetCodePtr();
+ jit.ABI_PushAllCalleeSavedRegsAndAdjustStack();
jit.EmitInstruction(instruction);
+ jit.ABI_PopAllCalleeSavedRegsAndAdjustStack();
jit.RET();
((void(*)())code)();