summaryrefslogtreecommitdiff
path: root/Source/Core/DSPCore
diff options
context:
space:
mode:
authorj4ck.fr0st <j4ck.fr0st@gmail.com>2010-06-30 16:17:20 +0000
committerj4ck.fr0st <j4ck.fr0st@gmail.com>2010-06-30 16:17:20 +0000
commit89c4068663ca961cd9cec40c94eac4bf0f2d6583 (patch)
tree8d90ce8b6ca6afe0548012389bcffc8963c46240 /Source/Core/DSPCore
parent599a4c974d949ef5fc587f3084f5c88ac23539e5 (diff)
Fix a bug in DSP Jit where branches had a blockSize of zero.
Add some useful checking to J_CC/SetJumpTarget. Refactor increment/decrement and reuse code with increase/decrease. git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@5816 8ced0084-cf51-0410-be5f-012b33b47a6e
Diffstat (limited to 'Source/Core/DSPCore')
-rw-r--r--Source/Core/DSPCore/Src/DSPEmitter.cpp11
-rw-r--r--Source/Core/DSPCore/Src/DSPEmitter.h2
-rw-r--r--Source/Core/DSPCore/Src/Jit/DSPJitUtil.cpp186
3 files changed, 98 insertions, 101 deletions
diff --git a/Source/Core/DSPCore/Src/DSPEmitter.cpp b/Source/Core/DSPCore/Src/DSPEmitter.cpp
index 3184e340d8..4b908847fe 100644
--- a/Source/Core/DSPCore/Src/DSPEmitter.cpp
+++ b/Source/Core/DSPCore/Src/DSPEmitter.cpp
@@ -194,6 +194,8 @@ const u8 *DSPEmitter::Compile(int start_addr) {
SetJumpTarget(rLoopCounterExit);
}
+ blockSize[start_addr]++;
+
// End the block if we're at a loop end.
if (opcode->branch ||
(DSPAnalyzer::code_flags[addr] & DSPAnalyzer::CODE_LOOP_END) ||
@@ -201,8 +203,6 @@ const u8 *DSPEmitter::Compile(int start_addr) {
break;
}
addr += opcode->size;
-
- blockSize[start_addr]++;
}
// ABI_RestoreStack(0);
@@ -210,6 +210,13 @@ const u8 *DSPEmitter::Compile(int start_addr) {
RET();
blocks[start_addr] = (CompiledCode)entryPoint;
+ if (blockSize[start_addr] == 0)
+ {
+ // just a safeguard, should never happen anymore.
+ // if it does we might get stuck over in RunForCycles.
+ ERROR_LOG(DSPLLE, "Block at 0x%04x has zero size", start_addr);
+ blockSize[start_addr] = 1;
+ }
return entryPoint;
}
diff --git a/Source/Core/DSPCore/Src/DSPEmitter.h b/Source/Core/DSPCore/Src/DSPEmitter.h
index e09e072bae..2a9cc80c46 100644
--- a/Source/Core/DSPCore/Src/DSPEmitter.h
+++ b/Source/Core/DSPCore/Src/DSPEmitter.h
@@ -117,6 +117,8 @@ private:
DISALLOW_COPY_AND_ASSIGN(DSPEmitter);
void ToMask(Gen::X64Reg value_reg = Gen::EDI, Gen::X64Reg temp_reg = Gen::ESI);
+ void dsp_increment_one(Gen::X64Reg ar = Gen::EAX, Gen::X64Reg wr = Gen::EDX, Gen::X64Reg wr_pow = Gen::EDI, Gen::X64Reg temp_reg = Gen::ESI);
+ void dsp_decrement_one(Gen::X64Reg ar = Gen::EAX, Gen::X64Reg wr = Gen::EDX, Gen::X64Reg wr_pow = Gen::EDI, Gen::X64Reg temp_reg = Gen::ESI);
};
diff --git a/Source/Core/DSPCore/Src/Jit/DSPJitUtil.cpp b/Source/Core/DSPCore/Src/Jit/DSPJitUtil.cpp
index b8ea950f1d..fd49d12672 100644
--- a/Source/Core/DSPCore/Src/Jit/DSPJitUtil.cpp
+++ b/Source/Core/DSPCore/Src/Jit/DSPJitUtil.cpp
@@ -45,44 +45,30 @@ void DSPEmitter::ToMask(X64Reg value_reg, X64Reg temp_reg)
// 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)
+void DSPEmitter::dsp_increment_one(X64Reg ar, X64Reg wr, X64Reg wr_pow, X64Reg temp_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]));
-
- // ToMask(WR0), calculating it into EDI
- MOV(16, R(EDI), R(EDX));
- ToMask(EDI);
-
// if ((tmp & tmb) == tmb)
- MOV(16, R(ESI), R(EAX));
- AND(16, R(ESI), R(EDI));
- CMP(16, R(ESI), R(EDI));
+ MOV(16, R(temp_reg), R(ar));
+ AND(16, R(temp_reg), R(wr_pow));
+ CMP(16, R(temp_reg), R(wr_pow));
FixupBranch not_equal = J_CC(CC_NE);
// tmp -= wr_reg
- SUB(16, R(EAX), R(EDX));
+ SUB(16, R(ar), R(wr));
FixupBranch end = J();
SetJumpTarget(not_equal);
// else tmp++
- ADD(16, R(EAX), Imm16(1));
+ ADD(16, R(ar), Imm16(1));
SetJumpTarget(end);
-
- // g_dsp.r[reg] = tmp;
- 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)
+void DSPEmitter::increment_addr_reg(int reg)
{
- // s16 ar = g_dsp.r[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]));
@@ -90,29 +76,53 @@ void DSPEmitter::decrement_addr_reg(int reg)
MOV(16, R(EDI), R(EDX));
ToMask(EDI);
- //compute min from EDI and EAX
+ dsp_increment_one(EAX, EDX, EDI);
+
+ // g_dsp.r[reg] = tmp;
+ MOV(16, M(&g_dsp.r[reg]), R(EAX));
+}
+
+// See http://code.google.com/p/dolphin-emu/source/detail?r=3125
+void DSPEmitter::dsp_decrement_one(X64Reg ar, X64Reg wr, X64Reg wr_pow, X64Reg temp_reg)
+{
+ // compute min from wr_pow and ar
// min = (tmb+1-ar)&tmb;
- LEA(16, ESI, MDisp(EDI, 1));
- SUB(16, R(ESI), R(EAX));
- AND(16, R(ESI), R(EDI));
+ LEA(16, temp_reg, MDisp(wr_pow, 1));
+ SUB(16, R(temp_reg), R(ar));
+ AND(16, R(temp_reg), R(wr_pow));
// wr < min
- CMP(16, R(EDX), R(ESI));
+ CMP(16, R(wr), R(temp_reg));
FixupBranch wr_lt_min = J_CC(CC_B);
// !min
- TEST(16, R(ESI), R(ESI));
+ TEST(16, R(temp_reg), R(temp_reg));
FixupBranch min_zero = J_CC(CC_Z);
// ar--;
- SUB(16, R(EAX), Imm16(1));
+ SUB(16, R(ar), Imm16(1));
FixupBranch end = J();
// ar += wr;
SetJumpTarget(wr_lt_min);
SetJumpTarget(min_zero);
- ADD(16, R(EAX), R(EDX));
+ ADD(16, R(ar), R(wr));
SetJumpTarget(end);
+}
+
+// EAX = g_dsp.r[reg]
+// EDX = g_dsp.r[DSP_REG_WR0 + reg]
+void DSPEmitter::decrement_addr_reg(int reg)
+{
+ // s16 ar = 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));
+ ToMask(EDI);
+
+ dsp_decrement_one(EAX, EDX, EDI);
// g_dsp.r[reg] = tmp;
MOV(16, M(&g_dsp.r[reg]), R(EAX));
@@ -125,56 +135,50 @@ void DSPEmitter::decrement_addr_reg(int reg)
// EDI = tomask(EDX)
void DSPEmitter::increase_addr_reg(int reg)
{
- MOV(16, R(ECX), M(&g_dsp.r[DSP_REG_IX0 + reg]));
- //IX0 == 0, bail out
+ MOVZX(32, 16, 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);
+ // code too long for a 5-byte jump
+ // TODO: optimize a bit, maybe merge loops?
+ FixupBranch end = J_CC(CC_Z, true);
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 into EDI
+ // ToMask(WR0), calculating it into EDI
MOV(16, R(EDI), R(EDX));
ToMask(EDI);
- //dsp_increment
+ // IX0 > 0
+ // TODO: ToMask flushes flags set by TEST,
+ // needs another CMP here.
+ CMP(16, R(ECX), Imm16(0));
+ FixupBranch neg = J_CC(CC_L);
+
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);
-
- // 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);
+
+ // dsp_increment
+ dsp_increment_one(EAX, EDX, EDI);
SUB(16, R(ECX), Imm16(1)); // value--
+ CMP(16, M(&g_dsp.r[DSP_REG_IX0 + reg]), Imm16(127));
+ FixupBranch dbg = J_CC(CC_NE);
+ CMP(16, R(ECX), Imm16(1));
+ FixupBranch dbg2 = J_CC(CC_NE);
+ INT3();
+ SetJumpTarget(dbg2);
+ SetJumpTarget(dbg);
CMP(16, R(ECX), Imm16(0)); // value > 0
J_CC(CC_G, loop_pos);
FixupBranch end_pos = J();
- //else, IX0 < 0
+ // 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);
+
+ // dsp_decrement
+ dsp_decrement_one(EAX, EDX, EDI);
ADD(16, R(ECX), Imm16(1)); // value++
CMP(16, R(ECX), Imm16(0)); // value < 0
@@ -196,57 +200,41 @@ void DSPEmitter::increase_addr_reg(int reg)
void DSPEmitter::decrease_addr_reg(int reg)
{
MOV(16, R(ECX), M(&g_dsp.r[DSP_REG_IX0 + reg]));
- //IX0 == 0, bail out
+ // IX0 == 0, bail out
TEST(16, R(ECX), R(ECX));
- FixupBranch end = J_CC(CC_Z);
+ // code too long for a 5-byte jump
+ // TODO: optimize a bit, maybe merge loops?
+ FixupBranch end = J_CC(CC_Z, true);
MOV(16, R(EAX), M(&g_dsp.r[reg]));
MOV(16, R(EDX), M(&g_dsp.r[DSP_REG_WR0 + reg]));
- //IX0 > 0
+
+ // ToMask(WR0), calculating it into EDI
+ MOV(16, R(EDI), R(EDX));
+ ToMask(EDI);
+
+ // IX0 > 0
+ // TODO: ToMask flushes flags set by TEST,
+ // needs another CMP here.
+ CMP(16, R(ECX), Imm16(0));
FixupBranch neg = J_CC(CC_L);
- JumpTarget loop_pos = GetCodePtr();
- //dsp_decrement
- // if ((tmp & wr_reg) == 0)
- TEST(16, R(EAX), R(EDX));
+ JumpTarget loop_pos = GetCodePtr();
- 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);
+ // dsp_decrement
+ dsp_decrement_one(EAX, EDX, EDI);
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
+ // else, IX0 < 0
SetJumpTarget(neg);
-
- //ToMask(WR0), calculating it into EDI
- MOV(16, R(EDI), R(EDX));
- ToMask(EDI);
-
JumpTarget loop_neg = GetCodePtr();
- //dsp_increment
- // 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);
+
+ // dsp_increment
+ dsp_increment_one(EAX, EDX, EDI);
ADD(16, R(ECX), Imm16(1)); // value++
CMP(16, R(ECX), Imm16(0)); // value < 0