mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-07-23 14:19:46 -06:00
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
This commit is contained in:
@ -63,44 +63,41 @@ inline u16 ToMask(u16 a)
|
|||||||
return a | (a >> 1);
|
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]);
|
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)
|
if ((value & tmb) == tmb)
|
||||||
tmp ^= g_dsp.r[DSP_REG_WR0 + reg];
|
value ^= g_dsp.r[DSP_REG_WR0 + reg];
|
||||||
else
|
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
|
// 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...
|
// This one is easy. Looks like a hw implementation. Increment is worse...
|
||||||
if ((tmp & g_dsp.r[DSP_REG_WR0 + reg]) == 0)
|
if ((value & g_dsp.r[DSP_REG_WR0 + reg]) == 0)
|
||||||
tmp |= g_dsp.r[DSP_REG_WR0 + reg];
|
value |= g_dsp.r[DSP_REG_WR0 + reg];
|
||||||
else
|
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)
|
inline s16 dsp_increase_addr_reg(int reg, s16 value)
|
||||||
{
|
{
|
||||||
s16 tmp = - 1;
|
s16 tmp = g_dsp.r[reg];
|
||||||
|
|
||||||
// TODO: DO RIGHT!
|
// TODO: DO RIGHT!
|
||||||
if (value > 0) {
|
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++) {
|
for (int i = 0; i < (int)(-value); i++) {
|
||||||
tmp = dsp_decrement_addr_reg(reg, tmp);
|
tmp = dsp_decrement_addr_reg(reg, tmp);
|
||||||
}
|
}
|
||||||
} else
|
}
|
||||||
tmp = g_dsp.r[reg];
|
|
||||||
|
|
||||||
return tmp;
|
return tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline s16 dsp_decrease_addr_reg(int reg, s16 value)
|
inline s16 dsp_decrease_addr_reg(int reg, s16 value)
|
||||||
{
|
{
|
||||||
s16 tmp = - 1;
|
s16 tmp = g_dsp.r[reg];
|
||||||
|
|
||||||
// TODO: DO RIGHT!
|
// TODO: DO RIGHT!
|
||||||
if (value > 0) {
|
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++) {
|
for (int i = 0; i < (int)(-value); i++) {
|
||||||
tmp = dsp_increment_addr_reg(reg, tmp);
|
tmp = dsp_increment_addr_reg(reg, tmp);
|
||||||
}
|
}
|
||||||
} else
|
}
|
||||||
tmp = g_dsp.r[reg];
|
|
||||||
|
|
||||||
return tmp;
|
return tmp;
|
||||||
}
|
}
|
||||||
|
@ -107,36 +107,99 @@ void DSPEmitter::decrement_addr_reg(int reg)
|
|||||||
// Increase addr register according to the correspond ix register
|
// Increase addr register according to the correspond ix register
|
||||||
void DSPEmitter::increase_addr_reg(int reg)
|
void DSPEmitter::increase_addr_reg(int reg)
|
||||||
{
|
{
|
||||||
// s16 value = (s16)g_dsp.r[DSP_REG_IX0 + reg];
|
MOV(16, R(ECX), M(&g_dsp.r[DSP_REG_IX0 + reg]));
|
||||||
MOVSX(32, 16, EDX, M(&g_dsp.r[DSP_REG_IX0 + reg]));
|
//IX0 == 0, bail out
|
||||||
|
TEST(16, R(ECX), R(ECX));
|
||||||
// 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);
|
|
||||||
FixupBranch end = J_CC(CC_Z, true);
|
FixupBranch end = J_CC(CC_Z, true);
|
||||||
|
|
||||||
// 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);
|
||||||
|
|
||||||
|
//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));
|
||||||
|
|
||||||
JumpTarget loop_pos = GetCodePtr();
|
JumpTarget loop_pos = GetCodePtr();
|
||||||
increment_addr_reg(reg);
|
//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(32, R(EDX), Imm32(1)); // value--
|
SUB(16, R(ECX), Imm16(1));
|
||||||
CMP(32, R(EDX), Imm32(0)); // value == 0
|
CMP(16, R(ECX), Imm16(0));
|
||||||
J_CC(CC_NE, loop_pos);
|
J_CC(CC_G, loop_pos);
|
||||||
FixupBranch posValue = J();
|
FixupBranch end_pos = J();
|
||||||
|
|
||||||
SetJumpTarget(negValue);
|
//else, IX0 < 0
|
||||||
|
SetJumpTarget(neg);
|
||||||
// for (; value == 0; value++)
|
|
||||||
JumpTarget loop_neg = GetCodePtr();
|
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++
|
ADD(16, R(ECX), Imm16(1));
|
||||||
CMP(32, R(EDX), Imm32(0)); // value == 0
|
CMP(16, R(ECX), Imm16(0));
|
||||||
J_CC(CC_NE, loop_neg);
|
J_CC(CC_L, loop_neg);
|
||||||
|
SetJumpTarget(end_pos);
|
||||||
|
MOV(16, M(&g_dsp.r[reg]), R(EAX));
|
||||||
|
|
||||||
SetJumpTarget(posValue);
|
|
||||||
SetJumpTarget(end);
|
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
|
// Decrease addr register according to the correspond ix register
|
||||||
|
Reference in New Issue
Block a user