summaryrefslogtreecommitdiff
path: root/Source/Core/DSPCore
diff options
context:
space:
mode:
authornakeee <nakeee@gmail.com>2010-04-16 10:50:52 +0000
committernakeee <nakeee@gmail.com>2010-04-16 10:50:52 +0000
commitebac492716620999d00cd4d4f624e6c9ece43ca1 (patch)
tree960d58f557b7c37593f4befa46fced7767c9fdaa /Source/Core/DSPCore
parent4b232e50c5e8f0de95c9c9a1b8025ff42308f422 (diff)
DSP Jit some code cleanup
git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@5376 8ced0084-cf51-0410-be5f-012b33b47a6e
Diffstat (limited to 'Source/Core/DSPCore')
-rw-r--r--Source/Core/DSPCore/Src/DSPCore.cpp2
-rw-r--r--Source/Core/DSPCore/Src/DSPEmitter.cpp41
-rw-r--r--Source/Core/DSPCore/Src/DSPEmitter.h3
-rw-r--r--Source/Core/DSPCore/Src/Jit/DSPJitUtil.cpp253
4 files changed, 166 insertions, 133 deletions
diff --git a/Source/Core/DSPCore/Src/DSPCore.cpp b/Source/Core/DSPCore/Src/DSPCore.cpp
index 358a147e60..c293651c89 100644
--- a/Source/Core/DSPCore/Src/DSPCore.cpp
+++ b/Source/Core/DSPCore/Src/DSPCore.cpp
@@ -193,7 +193,7 @@ void DSPCore_CheckExceptions()
if (g_dsp.exceptions == 0)
return;
- // it's unclear what to do when there are two exceptions are the same time
+ // it's unclear what to do when there are two exceptions at the same time
// but for sure they should not be called together therefore the
// g_dsp.exception_in_progress
if (g_dsp.exception_in_progress != -1) {
diff --git a/Source/Core/DSPCore/Src/DSPEmitter.cpp b/Source/Core/DSPCore/Src/DSPEmitter.cpp
index 96722cef6d..1782714eb1 100644
--- a/Source/Core/DSPCore/Src/DSPEmitter.cpp
+++ b/Source/Core/DSPCore/Src/DSPEmitter.cpp
@@ -66,6 +66,27 @@ void DSPEmitter::ClearIRAM() {
}
}
+// Must go out of block if exception is detected
+void DSPEmitter::checkExceptions() {
+ ABI_CallFunction((void *)&DSPCore_CheckExternalInterrupt);
+ // Check for interrupts and exceptions
+ TEST(8, M(&g_dsp.exceptions), Imm8(0xff));
+ FixupBranch skipCheck = J_CC(CC_Z);
+
+ ABI_CallFunction((void *)&DSPCore_CheckExceptions);
+
+ MOV(32, R(EAX), M(&g_dsp.exception_in_progress));
+ CMP(32, R(EAX), Imm32(0));
+ FixupBranch noExceptionOccurred = J_CC(CC_L);
+
+ // ABI_CallFunction((void *)DSPInterpreter::HandleLoop);
+ ABI_RestoreStack(0);
+ RET();
+
+ SetJumpTarget(skipCheck);
+ SetJumpTarget(noExceptionOccurred);
+}
+
void DSPEmitter::WriteCallInterpreter(UDSPInstruction inst)
{
const DSPOPCTemplate *tinst = GetOpTemplate(inst);
@@ -116,28 +137,12 @@ const u8 *DSPEmitter::Compile(int start_addr) {
ABI_AlignStack(0);
int addr = start_addr;
-
+ checkExceptions();
while (addr < start_addr + BLOCK_SIZE)
{
UDSPInstruction inst = dsp_imem_read(addr);
const DSPOPCTemplate *opcode = GetOpTemplate(inst);
- // Check for interrupts and exceptions
- TEST(8, M(&g_dsp.exceptions), Imm8(0xff));
- FixupBranch skipCheck = J_CC(CC_Z);
-
- ABI_CallFunction((void *)&DSPCore_CheckExceptions);
-
- MOV(32, R(EAX), M(&g_dsp.exception_in_progress));
- CMP(32, R(EAX), Imm32(0));
- FixupBranch noExceptionOccurred = J_CC(CC_L);
-
- // ABI_CallFunction((void *)DSPInterpreter::HandleLoop);
- ABI_RestoreStack(0);
- RET();
-
- SetJumpTarget(skipCheck);
- SetJumpTarget(noExceptionOccurred);
// Increment PC
ADD(16, M(&(g_dsp.pc)), Imm16(1));
@@ -198,8 +203,6 @@ void STACKALIGN DSPEmitter::RunBlock(int cycles)
{
if (block_cycles > 500)
{
- if(g_dsp.cr & CR_EXTERNAL_INT)
- DSPCore_CheckExternalInterrupt();
block_cycles = 0;
}
diff --git a/Source/Core/DSPCore/Src/DSPEmitter.h b/Source/Core/DSPCore/Src/DSPEmitter.h
index 18e341e8f9..a6baabb5a0 100644
--- a/Source/Core/DSPCore/Src/DSPEmitter.h
+++ b/Source/Core/DSPCore/Src/DSPEmitter.h
@@ -52,7 +52,8 @@ public:
// Register helpers
void setCompileSR(u16 bit);
void clrCompileSR(u16 bit);
-
+ void checkExceptions();
+
// Memory helper functions
void increment_addr_reg(int reg);
void decrement_addr_reg(int reg);
diff --git a/Source/Core/DSPCore/Src/Jit/DSPJitUtil.cpp b/Source/Core/DSPCore/Src/Jit/DSPJitUtil.cpp
index dd362e28e7..549434cdf6 100644
--- a/Source/Core/DSPCore/Src/Jit/DSPJitUtil.cpp
+++ b/Source/Core/DSPCore/Src/Jit/DSPJitUtil.cpp
@@ -29,69 +29,66 @@ using namespace Gen;
// HORRIBLE UGLINESS, someone please fix.
// See http://code.google.com/p/dolphin-emu/source/detail?r=3125
+// EAX = g_dsp.r[reg]
+// EDX = g_dsp.r[DSP_REG_WR0 + reg]
void DSPEmitter::increment_addr_reg(int reg)
{
- // u16 tmb = g_dsp.r[DSP_REG_WR0 + reg];
- MOVZX(32, 16, EAX, M(&g_dsp.r[DSP_REG_WR0 + reg]));
-
- // tmb = tmb | (tmb >> 8);
- MOV(16, R(ECX), R(EAX));
- SHR(16, R(ECX), Imm8(8));
- OR(16, R(EAX), R(ECX));
-
- // tmb = tmb | (tmb >> 4);
- MOV(16, R(ECX), R(EAX));
- SHR(16, R(ECX), Imm8(4));
- OR(16, R(EAX), R(ECX));
-
- // tmb = tmb | (tmb >> 2);
- MOV(16, R(ECX), R(EAX));
- SHR(16, R(ECX), Imm8(2));
- OR(16, R(EAX), R(ECX));
-
- // tmb = tmb | (tmb >> 1);
- MOV(16, R(ECX), R(EAX));
- SHR(16, R(ECX), Imm8(1));
- OR(16, R(EAX), R(ECX));
-
// s16 tmp = g_dsp.r[reg];
- MOVZX(32, 16, ECX, M(&g_dsp.r[reg]));
+ MOV(16, R(EAX), M(&g_dsp.r[reg]));
+ MOV(16, R(EDX), M(&g_dsp.r[DSP_REG_WR0 + reg]));
+
+ //ToMask(WR0), calculating it into EDI
+ MOV(16, R(EDI), R(EDX));
+
+ MOV(16, R(ESI), R(EDI));
+ SHR(16, R(ESI), Imm8(8));
+ OR(16, R(EDI), R(ESI));
+ MOV(16, R(ESI), R(EDI));
+ SHR(16, R(ESI), Imm8(4));
+ OR(16, R(EDI), R(ESI));
+ MOV(16, R(ESI), R(EDI));
+ SHR(16, R(ESI), Imm8(2));
+ OR(16, R(EDI), R(ESI));
+ MOV(16, R(ESI), R(EDI));
+ SHR(16, R(ESI), Imm8(1));
+ OR(16, R(EDI), R(ESI));
// if ((tmp & tmb) == tmb)
- AND(16, R(ECX), R(EAX));
- CMP(16, R(EAX), R(ECX));
+ MOV(16, R(ESI), R(EAX));
+ AND(16, R(ESI), R(EDI));
+ CMP(16, R(ESI), R(EDI));
FixupBranch not_equal = J_CC(CC_NE);
- // tmp ^= g_dsp.r[DSP_REG_WR0 + reg];
- MOVZX(32, 16, ECX, M(&g_dsp.r[reg]));
- XOR(16, R(ECX), M(&g_dsp.r[DSP_REG_WR0 + reg]));
+ // tmp ^= wr_reg
+ XOR(16, R(EAX), R(EDX));
FixupBranch end = J();
SetJumpTarget(not_equal);
- // tmp++;
- MOVZX(32, 16, ECX, M(&g_dsp.r[reg]));
- ADD(16, R(ECX), Imm16(1));
-
+ // else tmp++
+ ADD(16, R(EAX), Imm16(1));
SetJumpTarget(end);
// g_dsp.r[reg] = tmp;
- MOV(16, M(&g_dsp.r[reg]), R(ECX));
+ MOV(16, M(&g_dsp.r[reg]), R(EAX));
}
// See http://code.google.com/p/dolphin-emu/source/detail?r=3125
+// EAX = g_dsp.r[reg]
+// EDX = g_dsp.r[DSP_REG_WR0 + reg]
void DSPEmitter::decrement_addr_reg(int reg)
{
// s16 tmp = g_dsp.r[reg];
MOV(16, R(EAX), M(&g_dsp.r[reg]));
+ MOV(16, R(EDX), M(&g_dsp.r[DSP_REG_WR0 + reg]));
// if ((tmp & g_dsp.r[DSP_REG_WR0 + reg]) == 0)
- TEST(16, R(EAX), M(&g_dsp.r[DSP_REG_WR0 + reg]));
+ TEST(16, R(EAX), R(EDX));
FixupBranch not_equal = J_CC(CC_NZ);
// tmp |= g_dsp.r[DSP_REG_WR0 + reg];
- OR(16, R(EAX), M(&g_dsp.r[DSP_REG_WR0 + reg]));
+ OR(16, R(EAX), R(EDX));
FixupBranch end = J();
SetJumpTarget(not_equal);
@@ -105,6 +102,10 @@ void DSPEmitter::decrement_addr_reg(int reg)
}
// Increase addr register according to the correspond ix register
+// EAX = g_dsp.r[reg]
+// ECX = g_dsp.r[DSP_REG_IX0 + reg]
+// EDX = g_dsp.r[DSP_REG_WR0 + reg]
+// EDI = tomask(EDX)
void DSPEmitter::increase_addr_reg(int reg)
{
MOV(16, R(ECX), M(&g_dsp.r[DSP_REG_IX0 + reg]));
@@ -117,123 +118,151 @@ void DSPEmitter::increase_addr_reg(int reg)
//IX0 > 0
FixupBranch neg = J_CC(CC_L);
- //ToMask(WR0), calculating it once is enough
- MOV(16, R(EBX), R(EDX));
- SHR(16, R(EBX), Imm8(8));
- OR(16, R(EDX), R(EBX));
- MOV(16, R(EBX), R(EDX));
- SHR(16, R(EBX), Imm8(4));
- OR(16, R(EDX), R(EBX));
- MOV(16, R(EBX), R(EDX));
- SHR(16, R(EBX), Imm8(2));
- OR(16, R(EDX), R(EBX));
- MOV(16, R(EBX), R(EDX));
- SHR(16, R(EBX), Imm8(1));
- OR(16, R(EDX), R(EBX));
+ //ToMask(WR0), calculating it into EDI
+ MOV(16, R(EDI), R(EDX));
+
+ MOV(16, R(ESI), R(EDI));
+ SHR(16, R(ESI), Imm8(8));
+ OR(16, R(EDI), R(ESI));
+ MOV(16, R(ESI), R(EDI));
+ SHR(16, R(ESI), Imm8(4));
+ OR(16, R(EDI), R(ESI));
+ MOV(16, R(ESI), R(EDI));
+ SHR(16, R(ESI), Imm8(2));
+ OR(16, R(EDI), R(ESI));
+ MOV(16, R(ESI), R(EDI));
+ SHR(16, R(ESI), Imm8(1));
+ OR(16, R(EDI), R(ESI));
- JumpTarget loop_pos = GetCodePtr();
//dsp_increment
- MOV(16, R(EBX), R(EAX));
- AND(16, R(EBX), R(EDX));
- CMP(16, R(EBX), R(EDX));
+ JumpTarget loop_pos = GetCodePtr();
+ // if ((tmp & tmb) == tmb)
+ MOV(16, R(ESI), R(EAX));
+ AND(16, R(ESI), R(EDI));
+ CMP(16, R(ESI), R(EDI));
FixupBranch pos_neq = J_CC(CC_NE);
- //TODO: WR0 is in EDX already, until ToMask at least.
- // currently, J_CC end jumps exactly 0x80 bytes,
- // just too much for a simple 5bytes = false one...
- // see if we can use some other reg instead.
- XOR(16, R(EAX), M(&g_dsp.r[DSP_REG_WR0 + reg]));
+
+ // tmp ^= wr_reg
+ XOR(16, R(EAX), R(EDX));
FixupBranch pos_eq = J();
SetJumpTarget(pos_neq);
+ // else tmp++
ADD(16, R(EAX), Imm16(1));
SetJumpTarget(pos_eq);
- SUB(16, R(ECX), Imm16(1));
- CMP(16, R(ECX), Imm16(0));
- J_CC(CC_G, loop_pos);
+ SUB(16, R(ECX), Imm16(1)); // value --
+ CMP(16, R(ECX), Imm16(0)); // value > 0
+ J_CC(CC_G, loop_pos);
FixupBranch end_pos = J();
//else, IX0 < 0
SetJumpTarget(neg);
JumpTarget loop_neg = GetCodePtr();
//dsp_decrement
+ // if ((tmp & wr_reg) == 0)
TEST(16, R(EAX), R(EDX));
+
FixupBranch neg_nz = J_CC(CC_NZ);
+ // tmp |= wr_reg;
OR(16, R(EAX), R(EDX));
FixupBranch neg_z = J();
SetJumpTarget(neg_nz);
+ // else tmp--
SUB(16, R(EAX), Imm16(1));
SetJumpTarget(neg_z);
- ADD(16, R(ECX), Imm16(1));
- CMP(16, R(ECX), Imm16(0));
+ ADD(16, R(ECX), Imm16(1)); // value++
+ CMP(16, R(ECX), Imm16(0)); // value < 0
J_CC(CC_L, loop_neg);
+
SetJumpTarget(end_pos);
+
+ // g_dsp.r[reg] = tmp;
MOV(16, M(&g_dsp.r[reg]), R(EAX));
SetJumpTarget(end);
-
- //s16 value = g_dsp.r[DSP_REG_IX0 + reg];
- //if (value != 0)
- //{
- // u16 tmp = g_dsp.r[reg];
- // u16 wr_reg = g_dsp.r[DSP_REG_WR0 + reg];
- // if (value > 0)
- // {
- // u16 tmb = ToMask(wr_reg);
- // while (value-- > 0)
- // {
- // if ((tmp & tmb) == tmb)
- // tmp ^= wr_reg;
- // else
- // tmp++;
- // }
- // }
- // else
- // {
- // while (value++ < 0)
- // {
- // if ((tmp & wr_reg) == 0)
- // tmp |= wr_reg;
- // else
- // tmp--;
- // }
- // }
- // g_dsp.r[reg] = tmp;
- //}
}
// Decrease addr register according to the correspond ix register
+// EAX = g_dsp.r[reg]
+// ECX = g_dsp.r[DSP_REG_IX0 + reg]
+// EDX = g_dsp.r[DSP_REG_WR0 + reg]
+// EDI = tomask(EDX)
void DSPEmitter::decrease_addr_reg(int reg)
{
- // s16 value = (s16)g_dsp.r[DSP_REG_IX0 + reg];
- MOVSX(32, 16, EDX, M(&g_dsp.r[DSP_REG_IX0 + reg]));
-
- // if (value > 0)
- CMP(32, R(EDX), Imm32(0));
- //end is further away than 0x7f, needs a 6-byte jz
+ MOV(16, R(ECX), M(&g_dsp.r[DSP_REG_IX0 + reg]));
+ //IX0 == 0, bail out
+ TEST(16, R(ECX), R(ECX));
FixupBranch end = J_CC(CC_Z, true);
- FixupBranch negValue = J_CC(CC_L);
- // for (; value == 0; value--)
+ MOV(16, R(EAX), M(&g_dsp.r[reg]));
+ MOV(16, R(EDX), M(&g_dsp.r[DSP_REG_WR0 + reg]));
+ //IX0 > 0
+ FixupBranch neg = J_CC(CC_L);
+ //dsp_increment
JumpTarget loop_pos = GetCodePtr();
- decrement_addr_reg(reg);
- SUB(32, R(EDX), Imm32(1)); // value--
- CMP(32, R(EDX), Imm32(0)); // value == 0
- J_CC(CC_NE, loop_pos);
- FixupBranch posValue = J();
+ //dsp_decrement
+ // if ((tmp & wr_reg) == 0)
+ TEST(16, R(EAX), R(EDX));
+
+ FixupBranch neg_nz = J_CC(CC_NZ);
+ // tmp |= wr_reg;
+ OR(16, R(EAX), R(EDX));
+ FixupBranch neg_z = J();
+ SetJumpTarget(neg_nz);
+ // else tmp--
+ SUB(16, R(EAX), Imm16(1));
+ SetJumpTarget(neg_z);
+
+ SUB(16, R(ECX), Imm16(1)); // value --
+ CMP(16, R(ECX), Imm16(0)); // value > 0
+ J_CC(CC_G, loop_pos);
+ FixupBranch end_pos = J();
+
+ //else, IX0 < 0
+ SetJumpTarget(neg);
- SetJumpTarget(negValue);
+ //ToMask(WR0), calculating it into EDI
+ MOV(16, R(EDI), R(EDX));
+
+ MOV(16, R(ESI), R(EDI));
+ SHR(16, R(ESI), Imm8(8));
+ OR(16, R(EDI), R(ESI));
+ MOV(16, R(ESI), R(EDI));
+ SHR(16, R(ESI), Imm8(4));
+ OR(16, R(EDI), R(ESI));
+ MOV(16, R(ESI), R(EDI));
+ SHR(16, R(ESI), Imm8(2));
+ OR(16, R(EDI), R(ESI));
+ MOV(16, R(ESI), R(EDI));
+ SHR(16, R(ESI), Imm8(1));
+ OR(16, R(EDI), R(ESI));
- // for (; value == 0; value++)
JumpTarget loop_neg = GetCodePtr();
- increment_addr_reg(reg);
+ // if ((tmp & tmb) == tmb)
+ MOV(16, R(ESI), R(EAX));
+ AND(16, R(ESI), R(EDI));
+ CMP(16, R(ESI), R(EDI));
+ FixupBranch pos_neq = J_CC(CC_NE);
+
+ // tmp ^= wr_reg
+ XOR(16, R(EAX), R(EDX));
+ FixupBranch pos_eq = J();
+ SetJumpTarget(pos_neq);
+ // else tmp++
+ ADD(16, R(EAX), Imm16(1));
+ SetJumpTarget(pos_eq);
+
+ ADD(16, R(ECX), Imm16(1)); // value++
+ CMP(16, R(ECX), Imm16(0)); // value < 0
+ J_CC(CC_L, loop_neg);
- ADD(32, R(EDX), Imm32(1)); // value++
- CMP(32, R(EDX), Imm32(0)); // value == 0
- J_CC(CC_NE, loop_neg);
+ SetJumpTarget(end_pos);
+
+ // g_dsp.r[reg] = tmp;
+ MOV(16, M(&g_dsp.r[reg]), R(EAX));
- SetJumpTarget(posValue);
SetJumpTarget(end);
}