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:
nakeee 2010-04-16 10:50:52 +00:00
parent 4b232e50c5
commit ebac492716
4 changed files with 166 additions and 133 deletions

View File

@ -193,7 +193,7 @@ void DSPCore_CheckExceptions()
if (g_dsp.exceptions == 0) if (g_dsp.exceptions == 0)
return; 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 // but for sure they should not be called together therefore the
// g_dsp.exception_in_progress // g_dsp.exception_in_progress
if (g_dsp.exception_in_progress != -1) { if (g_dsp.exception_in_progress != -1) {

View File

@ -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) void DSPEmitter::WriteCallInterpreter(UDSPInstruction inst)
{ {
const DSPOPCTemplate *tinst = GetOpTemplate(inst); const DSPOPCTemplate *tinst = GetOpTemplate(inst);
@ -116,28 +137,12 @@ const u8 *DSPEmitter::Compile(int start_addr) {
ABI_AlignStack(0); ABI_AlignStack(0);
int addr = start_addr; int addr = start_addr;
checkExceptions();
while (addr < start_addr + BLOCK_SIZE) while (addr < start_addr + BLOCK_SIZE)
{ {
UDSPInstruction inst = dsp_imem_read(addr); UDSPInstruction inst = dsp_imem_read(addr);
const DSPOPCTemplate *opcode = GetOpTemplate(inst); 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 // Increment PC
ADD(16, M(&(g_dsp.pc)), Imm16(1)); ADD(16, M(&(g_dsp.pc)), Imm16(1));
@ -198,8 +203,6 @@ void STACKALIGN DSPEmitter::RunBlock(int cycles)
{ {
if (block_cycles > 500) if (block_cycles > 500)
{ {
if(g_dsp.cr & CR_EXTERNAL_INT)
DSPCore_CheckExternalInterrupt();
block_cycles = 0; block_cycles = 0;
} }

View File

@ -52,7 +52,8 @@ public:
// Register helpers // Register helpers
void setCompileSR(u16 bit); void setCompileSR(u16 bit);
void clrCompileSR(u16 bit); void clrCompileSR(u16 bit);
void checkExceptions();
// Memory helper functions // Memory helper functions
void increment_addr_reg(int reg); void increment_addr_reg(int reg);
void decrement_addr_reg(int reg); void decrement_addr_reg(int reg);

View File

@ -29,69 +29,66 @@ using namespace Gen;
// HORRIBLE UGLINESS, someone please fix. // HORRIBLE UGLINESS, someone please fix.
// See http://code.google.com/p/dolphin-emu/source/detail?r=3125 // 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::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]; // 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) // if ((tmp & tmb) == tmb)
AND(16, R(ECX), R(EAX)); MOV(16, R(ESI), R(EAX));
CMP(16, R(EAX), R(ECX)); AND(16, R(ESI), R(EDI));
CMP(16, R(ESI), R(EDI));
FixupBranch not_equal = J_CC(CC_NE); FixupBranch not_equal = J_CC(CC_NE);
// tmp ^= g_dsp.r[DSP_REG_WR0 + reg]; // tmp ^= wr_reg
MOVZX(32, 16, ECX, M(&g_dsp.r[reg])); XOR(16, R(EAX), R(EDX));
XOR(16, R(ECX), M(&g_dsp.r[DSP_REG_WR0 + reg]));
FixupBranch end = J(); FixupBranch end = J();
SetJumpTarget(not_equal); SetJumpTarget(not_equal);
// tmp++; // else tmp++
MOVZX(32, 16, ECX, M(&g_dsp.r[reg])); ADD(16, R(EAX), Imm16(1));
ADD(16, R(ECX), Imm16(1));
SetJumpTarget(end); SetJumpTarget(end);
// g_dsp.r[reg] = tmp; // 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 // 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::decrement_addr_reg(int reg)
{ {
// s16 tmp = g_dsp.r[reg]; // s16 tmp = g_dsp.r[reg];
MOV(16, R(EAX), 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]));
// if ((tmp & g_dsp.r[DSP_REG_WR0 + reg]) == 0) // 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); FixupBranch not_equal = J_CC(CC_NZ);
// tmp |= g_dsp.r[DSP_REG_WR0 + reg]; // 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(); FixupBranch end = J();
SetJumpTarget(not_equal); SetJumpTarget(not_equal);
@ -105,6 +102,10 @@ 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
// 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) void DSPEmitter::increase_addr_reg(int reg)
{ {
MOV(16, R(ECX), M(&g_dsp.r[DSP_REG_IX0 + 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 //IX0 > 0
FixupBranch neg = J_CC(CC_L); FixupBranch neg = J_CC(CC_L);
//ToMask(WR0), calculating it once is enough //ToMask(WR0), calculating it into EDI
MOV(16, R(EBX), R(EDX)); MOV(16, R(EDI), R(EDX));
SHR(16, R(EBX), Imm8(8));
OR(16, R(EDX), R(EBX)); MOV(16, R(ESI), R(EDI));
MOV(16, R(EBX), R(EDX)); SHR(16, R(ESI), Imm8(8));
SHR(16, R(EBX), Imm8(4)); OR(16, R(EDI), R(ESI));
OR(16, R(EDX), R(EBX)); MOV(16, R(ESI), R(EDI));
MOV(16, R(EBX), R(EDX)); SHR(16, R(ESI), Imm8(4));
SHR(16, R(EBX), Imm8(2)); OR(16, R(EDI), R(ESI));
OR(16, R(EDX), R(EBX)); MOV(16, R(ESI), R(EDI));
MOV(16, R(EBX), R(EDX)); SHR(16, R(ESI), Imm8(2));
SHR(16, R(EBX), Imm8(1)); OR(16, R(EDI), R(ESI));
OR(16, R(EDX), R(EBX)); MOV(16, R(ESI), R(EDI));
SHR(16, R(ESI), Imm8(1));
OR(16, R(EDI), R(ESI));
JumpTarget loop_pos = GetCodePtr();
//dsp_increment //dsp_increment
MOV(16, R(EBX), R(EAX)); JumpTarget loop_pos = GetCodePtr();
AND(16, R(EBX), R(EDX)); // if ((tmp & tmb) == tmb)
CMP(16, R(EBX), R(EDX)); 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); 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, // tmp ^= wr_reg
// just too much for a simple 5bytes = false one... XOR(16, R(EAX), R(EDX));
// 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(); FixupBranch pos_eq = J();
SetJumpTarget(pos_neq); SetJumpTarget(pos_neq);
// else tmp++
ADD(16, R(EAX), Imm16(1)); ADD(16, R(EAX), Imm16(1));
SetJumpTarget(pos_eq); SetJumpTarget(pos_eq);
SUB(16, R(ECX), Imm16(1)); SUB(16, R(ECX), Imm16(1)); // value --
CMP(16, R(ECX), Imm16(0)); CMP(16, R(ECX), Imm16(0)); // value > 0
J_CC(CC_G, loop_pos); J_CC(CC_G, loop_pos);
FixupBranch end_pos = J(); FixupBranch end_pos = J();
//else, IX0 < 0 //else, IX0 < 0
SetJumpTarget(neg); SetJumpTarget(neg);
JumpTarget loop_neg = GetCodePtr(); JumpTarget loop_neg = GetCodePtr();
//dsp_decrement //dsp_decrement
// if ((tmp & wr_reg) == 0)
TEST(16, R(EAX), R(EDX)); TEST(16, R(EAX), R(EDX));
FixupBranch neg_nz = J_CC(CC_NZ); FixupBranch neg_nz = J_CC(CC_NZ);
// tmp |= wr_reg;
OR(16, R(EAX), R(EDX)); OR(16, R(EAX), R(EDX));
FixupBranch neg_z = J(); FixupBranch neg_z = J();
SetJumpTarget(neg_nz); SetJumpTarget(neg_nz);
// else tmp--
SUB(16, R(EAX), Imm16(1)); SUB(16, R(EAX), Imm16(1));
SetJumpTarget(neg_z); SetJumpTarget(neg_z);
ADD(16, R(ECX), Imm16(1)); ADD(16, R(ECX), Imm16(1)); // value++
CMP(16, R(ECX), Imm16(0)); CMP(16, R(ECX), Imm16(0)); // value < 0
J_CC(CC_L, loop_neg); J_CC(CC_L, loop_neg);
SetJumpTarget(end_pos); SetJumpTarget(end_pos);
// g_dsp.r[reg] = tmp;
MOV(16, M(&g_dsp.r[reg]), R(EAX)); MOV(16, M(&g_dsp.r[reg]), R(EAX));
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
// 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) void DSPEmitter::decrease_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 end = J_CC(CC_Z, true); 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(); JumpTarget loop_pos = GetCodePtr();
decrement_addr_reg(reg);
SUB(32, R(EDX), Imm32(1)); // value-- //dsp_decrement
CMP(32, R(EDX), Imm32(0)); // value == 0 // if ((tmp & wr_reg) == 0)
J_CC(CC_NE, loop_pos); TEST(16, R(EAX), R(EDX));
FixupBranch posValue = J();
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(); 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++ // tmp ^= wr_reg
CMP(32, R(EDX), Imm32(0)); // value == 0 XOR(16, R(EAX), R(EDX));
J_CC(CC_NE, loop_neg); 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); SetJumpTarget(end);
} }