From ebac492716620999d00cd4d4f624e6c9ece43ca1 Mon Sep 17 00:00:00 2001 From: nakeee Date: Fri, 16 Apr 2010 10:50:52 +0000 Subject: [PATCH] DSP Jit some code cleanup git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@5376 8ced0084-cf51-0410-be5f-012b33b47a6e --- Source/Core/DSPCore/Src/DSPCore.cpp | 2 +- Source/Core/DSPCore/Src/DSPEmitter.cpp | 41 ++-- Source/Core/DSPCore/Src/DSPEmitter.h | 3 +- Source/Core/DSPCore/Src/Jit/DSPJitUtil.cpp | 253 ++++++++++++--------- 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)); - 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); }