DSP Jit some code cleanup
git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@5376 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
parent
4b232e50c5
commit
ebac492716
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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));
|
||||
|
||||
SetJumpTarget(negValue);
|
||||
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);
|
||||
|
||||
//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);
|
||||
|
||||
ADD(32, R(EDX), Imm32(1)); // value++
|
||||
CMP(32, R(EDX), Imm32(0)); // value == 0
|
||||
J_CC(CC_NE, loop_neg);
|
||||
// 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);
|
||||
|
||||
SetJumpTarget(end_pos);
|
||||
|
||||
// g_dsp.r[reg] = tmp;
|
||||
MOV(16, M(&g_dsp.r[reg]), R(EAX));
|
||||
|
||||
SetJumpTarget(posValue);
|
||||
SetJumpTarget(end);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue