summaryrefslogtreecommitdiff
path: root/Source/Core
diff options
context:
space:
mode:
authorj4ck.fr0st <j4ck.fr0st@gmail.com>2010-04-15 20:01:44 +0000
committerj4ck.fr0st <j4ck.fr0st@gmail.com>2010-04-15 20:01:44 +0000
commit01fc261c2f48b806bae65ec675da609cec324b00 (patch)
tree298a3ed182e5066529dec58de721e9229f32e14f /Source/Core
parent6cc0ddadd49f1577739a61126ca69770fc7c5195 (diff)
DSP Jit: rewrite dsp_increase_addr_reg a couple of times, only to find that int was wrong - credits to LordMark for finding that.
git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@5374 8ced0084-cf51-0410-be5f-012b33b47a6e
Diffstat (limited to 'Source/Core')
-rw-r--r--Source/Core/DSPCore/Src/DSPIntUtil.h49
-rw-r--r--Source/Core/DSPCore/Src/Jit/DSPJitUtil.cpp109
2 files changed, 108 insertions, 50 deletions
diff --git a/Source/Core/DSPCore/Src/DSPIntUtil.h b/Source/Core/DSPCore/Src/DSPIntUtil.h
index 5aa81b2d13..c126d76153 100644
--- a/Source/Core/DSPCore/Src/DSPIntUtil.h
+++ b/Source/Core/DSPCore/Src/DSPIntUtil.h
@@ -63,44 +63,41 @@ inline u16 ToMask(u16 a)
return a | (a >> 1);
}
-inline s16 dsp_increment_addr_reg(int reg, s32 value = -1)
+inline s16 dsp_increment_addr_reg(int reg, s16 value)
{
u16 tmb = ToMask(g_dsp.r[DSP_REG_WR0 + reg]);
- s16 tmp;
- if (value == -1)
- tmp = g_dsp.r[reg];
- else
- tmp = value;
- if ((tmp & tmb) == tmb)
- tmp ^= g_dsp.r[DSP_REG_WR0 + reg];
+ if ((value & tmb) == tmb)
+ value ^= g_dsp.r[DSP_REG_WR0 + reg];
else
- tmp++;
+ value++;
- return tmp;
+ return value;
+}
+inline s16 dsp_increment_addr_reg(int reg)
+{
+ return dsp_increment_addr_reg(reg, g_dsp.r[reg]);
}
// See http://code.google.com/p/dolphin-emu/source/detail?r=3125
-inline s16 dsp_decrement_addr_reg(int reg, s32 value = -1)
+inline s16 dsp_decrement_addr_reg(int reg, s16 value)
{
- s16 tmp;
- if (value == -1)
- tmp = g_dsp.r[reg];
- else
- tmp = value;
-
// This one is easy. Looks like a hw implementation. Increment is worse...
- if ((tmp & g_dsp.r[DSP_REG_WR0 + reg]) == 0)
- tmp |= g_dsp.r[DSP_REG_WR0 + reg];
+ if ((value & g_dsp.r[DSP_REG_WR0 + reg]) == 0)
+ value |= g_dsp.r[DSP_REG_WR0 + reg];
else
- tmp--;
+ value--;
- return tmp;
+ return value;
+}
+inline s16 dsp_decrement_addr_reg(int reg)
+{
+ return dsp_decrement_addr_reg(reg, g_dsp.r[reg]);
}
inline s16 dsp_increase_addr_reg(int reg, s16 value)
{
- s16 tmp = - 1;
+ s16 tmp = g_dsp.r[reg];
// TODO: DO RIGHT!
if (value > 0) {
@@ -111,15 +108,14 @@ inline s16 dsp_increase_addr_reg(int reg, s16 value)
for (int i = 0; i < (int)(-value); i++) {
tmp = dsp_decrement_addr_reg(reg, tmp);
}
- } else
- tmp = g_dsp.r[reg];
+ }
return tmp;
}
inline s16 dsp_decrease_addr_reg(int reg, s16 value)
{
- s16 tmp = - 1;
+ s16 tmp = g_dsp.r[reg];
// TODO: DO RIGHT!
if (value > 0) {
@@ -130,8 +126,7 @@ inline s16 dsp_decrease_addr_reg(int reg, s16 value)
for (int i = 0; i < (int)(-value); i++) {
tmp = dsp_increment_addr_reg(reg, tmp);
}
- } else
- tmp = g_dsp.r[reg];
+ }
return tmp;
}
diff --git a/Source/Core/DSPCore/Src/Jit/DSPJitUtil.cpp b/Source/Core/DSPCore/Src/Jit/DSPJitUtil.cpp
index a25ee383a0..dd362e28e7 100644
--- a/Source/Core/DSPCore/Src/Jit/DSPJitUtil.cpp
+++ b/Source/Core/DSPCore/Src/Jit/DSPJitUtil.cpp
@@ -107,36 +107,99 @@ void DSPEmitter::decrement_addr_reg(int reg)
// Increase addr register according to the correspond ix register
void DSPEmitter::increase_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
- FixupBranch negValue = J_CC(CC_L);
+ 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);
- // for (; value == 0; value--)
- JumpTarget loop_pos = GetCodePtr();
- increment_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();
-
- SetJumpTarget(negValue);
+ 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);
+
+ //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));
- // for (; value == 0; value++)
+ JumpTarget loop_pos = GetCodePtr();
+ //dsp_increment
+ MOV(16, R(EBX), R(EAX));
+ AND(16, R(EBX), R(EDX));
+ CMP(16, R(EBX), R(EDX));
+ 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]));
+ FixupBranch pos_eq = J();
+ SetJumpTarget(pos_neq);
+ 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);
+ FixupBranch end_pos = J();
+
+ //else, IX0 < 0
+ SetJumpTarget(neg);
JumpTarget loop_neg = GetCodePtr();
- decrement_addr_reg(reg);
+ //dsp_decrement
+ TEST(16, R(EAX), R(EDX));
+ FixupBranch neg_nz = J_CC(CC_NZ);
+ OR(16, R(EAX), R(EDX));
+ FixupBranch neg_z = J();
+ SetJumpTarget(neg_nz);
+ SUB(16, R(EAX), Imm16(1));
+ SetJumpTarget(neg_z);
- ADD(32, R(EDX), Imm32(1)); // value++
- CMP(32, R(EDX), Imm32(0)); // value == 0
- J_CC(CC_NE, loop_neg);
+ ADD(16, R(ECX), Imm16(1));
+ CMP(16, R(ECX), Imm16(0));
+ J_CC(CC_L, loop_neg);
+ SetJumpTarget(end_pos);
+ MOV(16, M(&g_dsp.r[reg]), R(EAX));
- SetJumpTarget(posValue);
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