diff options
| author | nakeee <nakeee@gmail.com> | 2010-04-11 18:06:29 +0000 |
|---|---|---|
| committer | nakeee <nakeee@gmail.com> | 2010-04-11 18:06:29 +0000 |
| commit | d9507260418d233faea32b2c07acc254455a4089 (patch) | |
| tree | 9b2d5750b7088b8b123f59e5957941299a673173 /Source/Core/DSPCore | |
| parent | 524a6dd2bba21b87fad612a01b578c46615b34cc (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.vcproj | 4 | ||||
| -rw-r--r-- | Source/Core/DSPCore/Src/DSPCore.cpp | 2 | ||||
| -rw-r--r-- | Source/Core/DSPCore/Src/DSPEmitter.cpp | 3 | ||||
| -rw-r--r-- | Source/Core/DSPCore/Src/DSPEmitter.h | 14 | ||||
| -rw-r--r-- | Source/Core/DSPCore/Src/DSPTables.cpp | 24 | ||||
| -rw-r--r-- | Source/Core/DSPCore/Src/Jit/DSPJitMisc.cpp | 217 | ||||
| -rw-r--r-- | Source/Core/DSPCore/Src/SConscript | 2 |
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() |
