summaryrefslogtreecommitdiff
path: root/Source/Core/DSPCore
diff options
context:
space:
mode:
authornakeee <nakeee@gmail.com>2010-04-11 18:06:29 +0000
committernakeee <nakeee@gmail.com>2010-04-11 18:06:29 +0000
commitd9507260418d233faea32b2c07acc254455a4089 (patch)
tree9b2d5750b7088b8b123f59e5957941299a673173 /Source/Core/DSPCore
parent524a6dd2bba21b87fad612a01b578c46615b34cc (diff)
DSP Jit: Jit some more AR action and added compile SR which suppose to hold the status for
flags such as S40 which we can use to optimize compile. git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@5331 8ced0084-cf51-0410-be5f-012b33b47a6e
Diffstat (limited to 'Source/Core/DSPCore')
-rw-r--r--Source/Core/DSPCore/DSPCore.vcproj4
-rw-r--r--Source/Core/DSPCore/Src/DSPCore.cpp2
-rw-r--r--Source/Core/DSPCore/Src/DSPEmitter.cpp3
-rw-r--r--Source/Core/DSPCore/Src/DSPEmitter.h14
-rw-r--r--Source/Core/DSPCore/Src/DSPTables.cpp24
-rw-r--r--Source/Core/DSPCore/Src/Jit/DSPJitMisc.cpp217
-rw-r--r--Source/Core/DSPCore/Src/SConscript2
7 files changed, 252 insertions, 14 deletions
diff --git a/Source/Core/DSPCore/DSPCore.vcproj b/Source/Core/DSPCore/DSPCore.vcproj
index 16157c4d3d..05917ca096 100644
--- a/Source/Core/DSPCore/DSPCore.vcproj
+++ b/Source/Core/DSPCore/DSPCore.vcproj
@@ -457,6 +457,10 @@
RelativePath=".\Src\Jit\DSPJitUtil.cpp"
>
</File>
+ <File
+ RelativePath=".\Src\Jit\DSPJitMisc.cpp"
+ >
+ </File>
</Filter>
<File
RelativePath=".\Src\assemble.cpp"
diff --git a/Source/Core/DSPCore/Src/DSPCore.cpp b/Source/Core/DSPCore/Src/DSPCore.cpp
index 44ea934b5e..358a147e60 100644
--- a/Source/Core/DSPCore/Src/DSPCore.cpp
+++ b/Source/Core/DSPCore/Src/DSPCore.cpp
@@ -130,7 +130,7 @@ bool DSPCore_Init(const char *irom_filename, const char *coef_filename,
WriteProtectMemory(g_dsp.iram, DSP_IRAM_BYTE_SIZE, false);
// Initialize JIT, if necessary
- if(bUsingJIT)
+ if(bUsingJIT)
jit = new DSPEmitter();
DSPAnalyzer::Analyze();
diff --git a/Source/Core/DSPCore/Src/DSPEmitter.cpp b/Source/Core/DSPCore/Src/DSPEmitter.cpp
index d6d0142170..9598962285 100644
--- a/Source/Core/DSPCore/Src/DSPEmitter.cpp
+++ b/Source/Core/DSPCore/Src/DSPEmitter.cpp
@@ -44,6 +44,9 @@ DSPEmitter::DSPEmitter()
blockSize[i] = 0;
endBlock[i] = false;
}
+ compileSR = 0;
+ compileSR |= SR_INT_ENABLE;
+ compileSR |= SR_EXT_INT_ENABLE;
}
DSPEmitter::~DSPEmitter()
diff --git a/Source/Core/DSPCore/Src/DSPEmitter.h b/Source/Core/DSPCore/Src/DSPEmitter.h
index b778323684..5c10a299b7 100644
--- a/Source/Core/DSPCore/Src/DSPEmitter.h
+++ b/Source/Core/DSPCore/Src/DSPEmitter.h
@@ -32,6 +32,7 @@ class DSPEmitter : public Gen::XCodeBlock
CompiledCode *blocks;
u16 blockSize[0x10000];
bool *endBlock;
+ u16 compileSR;
DISALLOW_COPY_AND_ASSIGN(DSPEmitter);
public:
@@ -48,6 +49,10 @@ public:
void STACKALIGN RunBlock(int cycles);
+ // Register helpers
+ void setSR(u16 bit);
+ void clrSR(u16 bit);
+
// Memory helper functions
void increment_addr_reg(int reg);
void decrement_addr_reg(int reg);
@@ -79,6 +84,15 @@ public:
void ir(const UDSPInstruction opc);
void nr(const UDSPInstruction opc);
void nop(const UDSPInstruction opc) {}
+
+ // Commands
+ void dar(const UDSPInstruction opc);
+ void iar(const UDSPInstruction opc);
+ void subarn(const UDSPInstruction opc);
+ void addarn(const UDSPInstruction opc);
+ void sbclr(const UDSPInstruction opc);
+ void sbset(const UDSPInstruction opc);
+ void srbith(const UDSPInstruction opc);
};
diff --git a/Source/Core/DSPCore/Src/DSPTables.cpp b/Source/Core/DSPCore/Src/DSPTables.cpp
index 681ebf640d..6b5a0e2bf0 100644
--- a/Source/Core/DSPCore/Src/DSPTables.cpp
+++ b/Source/Core/DSPCore/Src/DSPTables.cpp
@@ -35,10 +35,10 @@ const DSPOPCTemplate opcodes[] =
{
{"NOP", 0x0000, 0xfffc, nop, &DSPEmitter::nop, 1, 0, {}, false, false},
- {"DAR", 0x0004, 0xfffc, DSPInterpreter::dar, NULL, 1, 1, {{P_REG, 1, 0, 0, 0x0003}}, false, false},
- {"IAR", 0x0008, 0xfffc, DSPInterpreter::iar, NULL, 1, 1, {{P_REG, 1, 0, 0, 0x0003}}, false, false},
- {"SUBARN", 0x000c, 0xfffc, DSPInterpreter::subarn, NULL, 1, 1, {{P_REG, 1, 0, 0, 0x0003}}, false, false},
- {"ADDARN", 0x0010, 0xfff0, DSPInterpreter::addarn, NULL, 1, 2, {{P_REG, 1, 0, 0, 0x0003}, {P_REG04, 1, 0, 2, 0x000c}}, false, false},
+ {"DAR", 0x0004, 0xfffc, DSPInterpreter::dar, &DSPEmitter::dar, 1, 1, {{P_REG, 1, 0, 0, 0x0003}}, false, false},
+ {"IAR", 0x0008, 0xfffc, DSPInterpreter::iar, &DSPEmitter::iar, 1, 1, {{P_REG, 1, 0, 0, 0x0003}}, false, false},
+ {"SUBARN", 0x000c, 0xfffc, DSPInterpreter::subarn, &DSPEmitter::subarn, 1, 1, {{P_REG, 1, 0, 0, 0x0003}}, false, false},
+ {"ADDARN", 0x0010, 0xfff0, DSPInterpreter::addarn, &DSPEmitter::addarn, 1, 2, {{P_REG, 1, 0, 0, 0x0003}, {P_REG04, 1, 0, 2, 0x000c}}, false, false},
{"HALT", 0x0021, 0xffff, DSPInterpreter::halt, NULL, 1, 0, {}, false, true},
@@ -146,8 +146,8 @@ const DSPOPCTemplate opcodes[] =
{"CALLRO", 0x171e, 0xff1f, DSPInterpreter::callr, NULL, 1, 1, {{P_REG, 1, 0, 5, 0x00e0}}, false, true},
{"CALLR", 0x171f, 0xff1f, DSPInterpreter::callr, NULL, 1, 1, {{P_REG, 1, 0, 5, 0x00e0}}, false, true},
- {"SBCLR", 0x1200, 0xff00, DSPInterpreter::sbclr, NULL, 1, 1, {{P_IMM, 1, 0, 0, 0x0007}}, false, false},
- {"SBSET", 0x1300, 0xff00, DSPInterpreter::sbset, NULL, 1, 1, {{P_IMM, 1, 0, 0, 0x0007}}, false, false},
+ {"SBCLR", 0x1200, 0xff00, DSPInterpreter::sbclr, &DSPEmitter::sbclr, 1, 1, {{P_IMM, 1, 0, 0, 0x0007}}, false, false},
+ {"SBSET", 0x1300, 0xff00, DSPInterpreter::sbset, &DSPEmitter::sbset, 1, 1, {{P_IMM, 1, 0, 0, 0x0007}}, false, false},
{"LSL", 0x1400, 0xfec0, DSPInterpreter::lsl, NULL, 1, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_IMM, 1, 0, 0, 0x003f}}, false, false},
{"LSR", 0x1440, 0xfec0, DSPInterpreter::lsr, NULL, 1, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_IMM, 1, 0, 0, 0x003f}}, false, false},
@@ -255,12 +255,12 @@ const DSPOPCTemplate opcodes[] =
{"CLRP", 0x8400, 0xff00, DSPInterpreter::clrp, NULL, 1 , 0, {}, true, false},
{"TSTPROD", 0x8500, 0xff00, DSPInterpreter::tstprod, NULL, 1 , 0, {}, true, false},
{"TSTAXH", 0x8600, 0xfe00, DSPInterpreter::tstaxh, NULL, 1 , 1, {{P_REG1A, 1, 0, 8, 0x0100}}, true, false},
- {"M2", 0x8a00, 0xff00, DSPInterpreter::srbith, NULL, 1 , 0, {}, true, false},
- {"M0", 0x8b00, 0xff00, DSPInterpreter::srbith, NULL, 1 , 0, {}, true, false},
- {"CLR15", 0x8c00, 0xff00, DSPInterpreter::srbith, NULL, 1 , 0, {}, true, false},
- {"SET15", 0x8d00, 0xff00, DSPInterpreter::srbith, NULL, 1 , 0, {}, true, false},
- {"SET16", 0x8e00, 0xff00, DSPInterpreter::srbith, NULL, 1 , 0, {}, true, false},
- {"SET40", 0x8f00, 0xff00, DSPInterpreter::srbith, NULL, 1 , 0, {}, true, false},
+ {"M2", 0x8a00, 0xff00, DSPInterpreter::srbith, &DSPEmitter::srbith, 1 , 0, {}, true, false},
+ {"M0", 0x8b00, 0xff00, DSPInterpreter::srbith, &DSPEmitter::srbith, 1 , 0, {}, true, false},
+ {"CLR15", 0x8c00, 0xff00, DSPInterpreter::srbith, &DSPEmitter::srbith, 1 , 0, {}, true, false},
+ {"SET15", 0x8d00, 0xff00, DSPInterpreter::srbith, &DSPEmitter::srbith, 1 , 0, {}, true, false},
+ {"SET16", 0x8e00, 0xff00, DSPInterpreter::srbith, &DSPEmitter::srbith, 1 , 0, {}, true, false},
+ {"SET40", 0x8f00, 0xff00, DSPInterpreter::srbith, &DSPEmitter::srbith, 1 , 0, {}, true, false},
//9
{"MUL", 0x9000, 0xf700, DSPInterpreter::mul, NULL, 1 , 2, {{P_REG18, 1, 0, 11, 0x0800}, {P_REG1A, 1, 0, 11, 0x0800}}, true, false},
diff --git a/Source/Core/DSPCore/Src/Jit/DSPJitMisc.cpp b/Source/Core/DSPCore/Src/Jit/DSPJitMisc.cpp
new file mode 100644
index 0000000000..7bafbb72f7
--- /dev/null
+++ b/Source/Core/DSPCore/Src/Jit/DSPJitMisc.cpp
@@ -0,0 +1,217 @@
+// Copyright (C) 2010 Dolphin Project.
+
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, version 2.0.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License 2.0 for more details.
+
+// A copy of the GPL 2.0 should have been included with the program.
+// If not, see http://www.gnu.org/licenses/
+
+// Official SVN repository and contact information can be found at
+// http://code.google.com/p/dolphin-emu/
+
+
+#include "DSPIntUtil.h"
+#include "../DSPEmitter.h"
+#include "x64Emitter.h"
+#include "ABI.h"
+using namespace Gen;
+
+// MRR $D, $S
+// 0001 11dd ddds ssss
+// Move value from register $S to register $D.
+// FIXME: Perform additional operation depending on destination register.
+/*void DSPEmitter::mrr(const UDSPInstruction opc)
+{
+ u8 sreg = opc & 0x1f;
+ u8 dreg = (opc >> 5) & 0x1f;
+
+ u16 val = dsp_op_read_reg(sreg);
+ dsp_op_write_reg(dreg, val);
+ dsp_conditional_extend_accum(dreg);
+}
+*/
+
+// LRI $D, #I
+// 0000 0000 100d dddd
+// iiii iiii iiii iiii
+// Load immediate value I to register $D.
+// FIXME: Perform additional operation depending on destination register.
+//
+// DSPSpy discovery: This, and possibly other instructions that load a
+// register, has a different behaviour in S40 mode if loaded to AC0.M: The
+// value gets sign extended to the whole accumulator! This does not happen in
+// S16 mode.
+/*void DSPEmitter::lri(const UDSPInstruction opc)
+{
+ u8 reg = opc & DSP_REG_MASK;
+ u16 imm = dsp_fetch_code();
+ dsp_op_write_reg(reg, imm);
+ dsp_conditional_extend_accum(reg);
+}
+
+
+// LRIS $(0x18+D), #I
+// 0000 1ddd iiii iiii
+// Load immediate value I (8-bit sign extended) to accumulator register.
+// FIXME: Perform additional operation depending on destination register.
+void DSPEmitter::lris(const UDSPInstruction opc)
+{
+ u8 reg = ((opc >> 8) & 0x7) + DSP_REG_AXL0;
+ u16 imm = (s8)opc;
+ dsp_op_write_reg(reg, imm);
+ dsp_conditional_extend_accum(reg);
+}
+
+//----
+
+// NX
+// 1000 -000 xxxx xxxx
+// No operation, but can be extended with extended opcode.
+// This opcode is supposed to do nothing - it's used if you want to use
+// an opcode extension but not do anything. At least according to duddie.
+void DSPEmitter::nx(const UDSPInstruction opc)
+{
+ zeroWriteBackLog();
+}
+*/
+//----
+
+// DAR $arD
+// 0000 0000 0000 01dd
+// Decrement address register $arD.
+void DSPEmitter::dar(const UDSPInstruction opc)
+{
+ // g_dsp.r[opc & 0x3] = dsp_decrement_addr_reg(opc & 0x3);
+ decrement_addr_reg(opc & 0x3);
+
+}
+
+// IAR $arD
+// 0000 0000 0000 10dd
+// Increment address register $arD.
+void DSPEmitter::iar(const UDSPInstruction opc)
+{
+ // g_dsp.r[opc & 0x3] = dsp_increment_addr_reg(opc & 0x3);
+ increment_addr_reg(opc & 0x3);
+}
+
+// SUBARN $arD
+// 0000 0000 0000 11dd
+// Subtract indexing register $ixD from an addressing register $arD.
+// used only in IPL-NTSC ucode
+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]);
+ decrease_addr_reg(opc & 0x3);
+}
+
+// ADDARN $arD, $ixS
+// 0000 0000 0001 ssdd
+// Adds indexing register $ixS to an addressing register $arD.
+// It is critical for the Zelda ucode that this one wraps correctly.
+void DSPEmitter::addarn(const UDSPInstruction opc)
+{
+ // u8 dreg = opc & 0x3;
+ // u8 sreg = (opc >> 2) & 0x3;
+ // 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
+ increase_addr_reg(opc & 0x3);
+}
+
+//----
+
+
+void DSPEmitter::setSR(u16 bit) {
+
+ // (1 << bit)
+ MOV(32, R(EAX), Imm32(1));
+ SHR(32, R(EAX), Imm32(bit));
+
+ // g_dsp.r[DSP_REG_SR] |= EAX
+ MOV(16, R(ECX), M(&g_dsp.r[DSP_REG_SR]));
+ OR(32, R(ECX), R(EAX));
+
+ compileSR |= (1 << bit);
+}
+
+void DSPEmitter::clrSR(u16 bit) {
+ // ~(1 << bit)
+ MOV(32, R(EAX), Imm32(1));
+ SHR(32, R(EAX), Imm32(bit));
+ NOT(32, R(EAX));
+
+ // g_dsp.r[DSP_REG_SR] &= EAX
+ MOV(16, R(ECX), M(&g_dsp.r[DSP_REG_SR]));
+ AND(32, R(ECX), R(EAX));
+
+ compileSR &= ~(1 << bit);
+}
+// SBCLR #I
+// 0001 0011 aaaa aiii
+// bit of status register $sr. Bit number is calculated by adding 6 to
+// immediate value I.
+void DSPEmitter::sbclr(const UDSPInstruction opc)
+{
+ u16 bit = (opc & 0x7) + 6;
+
+ clrSR(bit);
+}
+
+// SBSET #I
+// 0001 0010 aaaa aiii
+// Set bit of status register $sr. Bit number is calculated by adding 6 to
+// immediate value I.
+void DSPEmitter::sbset(const UDSPInstruction opc)
+{
+ u8 bit = (opc & 0x7) + 6;
+ setSR(bit);
+}
+
+// This is a bunch of flag setters, flipping bits in SR. So far so good,
+// but it's harder to know exactly what effect they have.
+void DSPEmitter::srbith(const UDSPInstruction opc)
+{
+ ABI_CallFunction((void *)zeroWriteBackLog);
+ switch ((opc >> 8) & 0xf)
+ {
+ // M0/M2 change the multiplier mode (it can multiply by 2 for free).
+ case 0xa: // M2
+ clrSR(SR_MUL_MODIFY);
+ break;
+ case 0xb: // M0
+ setSR(SR_MUL_MODIFY);
+ break;
+
+ // If set, treat multiplicands as unsigned.
+ // If clear, treat them as signed.
+ case 0xc: // CLR15
+ clrSR(SR_MUL_UNSIGNED);
+ break;
+ case 0xd: // SET15
+ setSR(SR_MUL_UNSIGNED);
+ break;
+
+ // Automatic 40-bit sign extension when loading ACx.M.
+ // SET40 changes something very important: see the LRI instruction above.
+ case 0xe: // SET16 (CLR40)
+ clrSR(SR_40_MODE_BIT);
+ break;
+
+ case 0xf: // SET40
+ setSR(SR_40_MODE_BIT);
+ g_dsp.r[DSP_REG_SR] |= SR_40_MODE_BIT;
+ break;
+
+ default:
+ break;
+ }
+}
+
diff --git a/Source/Core/DSPCore/Src/SConscript b/Source/Core/DSPCore/Src/SConscript
index 8433d084a1..61b7016bb7 100644
--- a/Source/Core/DSPCore/Src/SConscript
+++ b/Source/Core/DSPCore/Src/SConscript
@@ -26,7 +26,7 @@ files = [
"DSPTables.cpp",
"Jit/DSPJitExtOps.cpp",
"Jit/DSPJitUtil.cpp",
-
+ "Jit/DSPJitMisc.cpp",
]
acenv = env.Clone()