From 54f3828555f3dc547a1bf8cfafbeca64bfc700e3 Mon Sep 17 00:00:00 2001 From: Pierre Date: Sun, 4 Sep 2011 15:22:39 +0200 Subject: [PATCH 01/11] DSPLLE: Move a bunch of helper functions from DSPJitMisc.cpp to DSPJitUtil.cpp --- Source/Core/Core/Src/DSP/Jit/DSPJitMisc.cpp | 303 -------------------- Source/Core/Core/Src/DSP/Jit/DSPJitUtil.cpp | 303 ++++++++++++++++++++ 2 files changed, 303 insertions(+), 303 deletions(-) diff --git a/Source/Core/Core/Src/DSP/Jit/DSPJitMisc.cpp b/Source/Core/Core/Src/DSP/Jit/DSPJitMisc.cpp index d0bf7a3822..e26db20ecf 100644 --- a/Source/Core/Core/Src/DSP/Jit/DSPJitMisc.cpp +++ b/Source/Core/Core/Src/DSP/Jit/DSPJitMisc.cpp @@ -23,309 +23,6 @@ #include "x64ABI.h" using namespace Gen; -//clobbers: -//EAX = (s8)g_dsp.reg_stack_ptr[stack_reg] -//expects: -void DSPEmitter::dsp_reg_stack_push(int stack_reg) -{ - //g_dsp.reg_stack_ptr[stack_reg]++; - //g_dsp.reg_stack_ptr[stack_reg] &= DSP_STACK_MASK; - MOV(8, R(AL), M(&g_dsp.reg_stack_ptr[stack_reg])); - ADD(8, R(AL), Imm8(1)); - AND(8, R(AL), Imm8(DSP_STACK_MASK)); - MOV(8, M(&g_dsp.reg_stack_ptr[stack_reg]), R(AL)); - - X64Reg tmp1; - gpr.getFreeXReg(tmp1); - //g_dsp.reg_stack[stack_reg][g_dsp.reg_stack_ptr[stack_reg]] = g_dsp.r[DSP_REG_ST0 + stack_reg]; - MOV(16, R(tmp1), M(&g_dsp.r.st[stack_reg])); -#ifdef _M_IX86 // All32 - MOVZX(32, 8, EAX, R(AL)); -#else - MOVZX(64, 8, RAX, R(AL)); -#endif - MOV(16, MComplex(EAX, EAX, 1, - PtrOffset(&g_dsp.reg_stack[stack_reg][0],0)), R(tmp1)); - gpr.putXReg(tmp1); -} - -//clobbers: -//EAX = (s8)g_dsp.reg_stack_ptr[stack_reg] -//expects: -void DSPEmitter::dsp_reg_stack_pop(int stack_reg) -{ - //g_dsp.r[DSP_REG_ST0 + stack_reg] = g_dsp.reg_stack[stack_reg][g_dsp.reg_stack_ptr[stack_reg]]; - MOV(8, R(AL), M(&g_dsp.reg_stack_ptr[stack_reg])); - X64Reg tmp1; - gpr.getFreeXReg(tmp1); -#ifdef _M_IX86 // All32 - MOVZX(32, 8, EAX, R(AL)); -#else - MOVZX(64, 8, RAX, R(AL)); -#endif - MOV(16, R(tmp1), MComplex(EAX, EAX, 1, - PtrOffset(&g_dsp.reg_stack[stack_reg][0],0))); - MOV(16, M(&g_dsp.r.st[stack_reg]), R(tmp1)); - gpr.putXReg(tmp1); - - //g_dsp.reg_stack_ptr[stack_reg]--; - //g_dsp.reg_stack_ptr[stack_reg] &= DSP_STACK_MASK; - SUB(8, R(AL), Imm8(1)); - AND(8, R(AL), Imm8(DSP_STACK_MASK)); - MOV(8, M(&g_dsp.reg_stack_ptr[stack_reg]), R(AL)); -} - - -void DSPEmitter::dsp_reg_store_stack(int stack_reg, Gen::X64Reg host_sreg) -{ - if (host_sreg != EDX) { - MOV(16, R(EDX), R(host_sreg)); - } - dsp_reg_stack_push(stack_reg); - //g_dsp.r[DSP_REG_ST0 + stack_reg] = val; - MOV(16, M(&g_dsp.r.st[stack_reg]), R(EDX)); -} - -void DSPEmitter::dsp_reg_load_stack(int stack_reg, Gen::X64Reg host_dreg) -{ - //u16 val = g_dsp.r[DSP_REG_ST0 + stack_reg]; - MOV(16, R(EDX), M(&g_dsp.r.st[stack_reg])); - dsp_reg_stack_pop(stack_reg); - if (host_dreg != EDX) { - MOV(16, R(host_dreg), R(EDX)); - } -} - -void DSPEmitter::dsp_reg_store_stack_imm(int stack_reg, u16 val) -{ - dsp_reg_stack_push(stack_reg); - //g_dsp.r[DSP_REG_ST0 + stack_reg] = val; - MOV(16, M(&g_dsp.r.st[stack_reg]), Imm16(val)); -} - -void DSPEmitter::dsp_op_write_reg(int reg, Gen::X64Reg host_sreg) -{ - switch (reg & 0x1f) { - // 8-bit sign extended registers. - case DSP_REG_ACH0: - case DSP_REG_ACH1: - gpr.writeReg(reg, R(host_sreg)); - break; - - // Stack registers. - case DSP_REG_ST0: - case DSP_REG_ST1: - case DSP_REG_ST2: - case DSP_REG_ST3: - dsp_reg_store_stack(reg - DSP_REG_ST0, host_sreg); - break; - - default: - gpr.writeReg(reg, R(host_sreg)); - break; - } -} - -void DSPEmitter::dsp_op_write_reg_imm(int reg, u16 val) -{ - switch (reg & 0x1f) { - // 8-bit sign extended registers. Should look at prod.h too... - case DSP_REG_ACH0: - case DSP_REG_ACH1: - gpr.writeReg(reg, Imm16((u16)(s16)(s8)(u8)val)); - break; - // Stack registers. - case DSP_REG_ST0: - case DSP_REG_ST1: - case DSP_REG_ST2: - case DSP_REG_ST3: - dsp_reg_store_stack_imm(reg - DSP_REG_ST0, val); - break; - - default: - gpr.writeReg(reg, Imm16(val)); - break; - } -} - -void DSPEmitter::dsp_conditional_extend_accum(int reg) -{ - switch (reg) - { - case DSP_REG_ACM0: - case DSP_REG_ACM1: - { - OpArg sr_reg; - gpr.getReg(DSP_REG_SR,sr_reg); - DSPJitRegCache c(gpr); - TEST(16, sr_reg, Imm16(SR_40_MODE_BIT)); - FixupBranch not_40bit = J_CC(CC_Z,true); - //if (g_dsp.r[DSP_REG_SR] & SR_40_MODE_BIT) - //{ - // Sign extend into whole accum. - //u16 val = g_dsp.r[reg]; - get_acc_m(reg - DSP_REG_ACM0, EAX); - SHR(32, R(EAX), Imm8(16)); - //g_dsp.r[reg - DSP_REG_ACM0 + DSP_REG_ACH0] = (val & 0x8000) ? 0xFFFF : 0x0000; - //g_dsp.r[reg - DSP_REG_ACM0 + DSP_REG_ACL0] = 0; - set_acc_h(reg - DSP_REG_ACM0, R(RAX)); - set_acc_l(reg - DSP_REG_ACM0, Imm16(0)); - //} - gpr.flushRegs(c); - SetJumpTarget(not_40bit); - gpr.putReg(DSP_REG_SR, false); - } - } -} - -void DSPEmitter::dsp_conditional_extend_accum_imm(int reg, u16 val) -{ - switch (reg) - { - case DSP_REG_ACM0: - case DSP_REG_ACM1: - { - OpArg sr_reg; - gpr.getReg(DSP_REG_SR,sr_reg); - DSPJitRegCache c(gpr); - TEST(16, sr_reg, Imm16(SR_40_MODE_BIT)); - FixupBranch not_40bit = J_CC(CC_Z, true); - //if (g_dsp.r[DSP_REG_SR] & SR_40_MODE_BIT) - //{ - // Sign extend into whole accum. - //g_dsp.r[reg - DSP_REG_ACM0 + DSP_REG_ACH0] = (val & 0x8000) ? 0xFFFF : 0x0000; - //g_dsp.r[reg - DSP_REG_ACM0 + DSP_REG_ACL0] = 0; - set_acc_h(reg - DSP_REG_ACM0, Imm16((val & 0x8000)?0xffff:0x0000)); - set_acc_l(reg - DSP_REG_ACM0, Imm16(0)); - //} - gpr.flushRegs(c); - SetJumpTarget(not_40bit); - gpr.putReg(DSP_REG_SR, false); - } - } -} - -void DSPEmitter::dsp_op_read_reg(int reg, Gen::X64Reg host_dreg, DSPJitSignExtend extend) -{ - switch (reg & 0x1f) { - case DSP_REG_ST0: - case DSP_REG_ST1: - case DSP_REG_ST2: - case DSP_REG_ST3: - dsp_reg_load_stack(reg - DSP_REG_ST0, host_dreg); - switch(extend) { - case SIGN: -#ifdef _M_IX86 // All32 - MOVSX(32, 16, host_dreg, R(host_dreg)); -#else - MOVSX(64, 16, host_dreg, R(host_dreg)); -#endif - break; - case ZERO: -#ifdef _M_IX86 // All32 - MOVZX(32, 16, host_dreg, R(host_dreg)); -#else - MOVZX(64, 16, host_dreg, R(host_dreg)); -#endif - break; - case NONE: - default: - break; - } - return; - default: - gpr.readReg(reg, host_dreg, extend); - return; - } -} - -void DSPEmitter::dsp_op_read_reg_and_saturate(int reg, Gen::X64Reg host_dreg, DSPJitSignExtend extend) -{ - //we already know this is ACCM0 or ACCM1 -#ifdef _M_IX86 // All32 - gpr.readReg(reg, host_dreg, extend); -#else - OpArg acc_reg; - gpr.getReg(reg-DSP_REG_ACM0+DSP_REG_ACC0_64, acc_reg); -#endif - OpArg sr_reg; - gpr.getReg(DSP_REG_SR,sr_reg); - - DSPJitRegCache c(gpr); - TEST(16, sr_reg, Imm16(SR_40_MODE_BIT)); - FixupBranch not_40bit = J_CC(CC_Z, true); - -#ifdef _M_IX86 // All32 - DSPJitRegCache c2(gpr); - gpr.putReg(DSP_REG_SR, false); - X64Reg tmp1; - gpr.getFreeXReg(tmp1); - gpr.readReg(reg-DSP_REG_ACM0+DSP_REG_ACH0, tmp1, NONE); - MOVSX(32,16,host_dreg,R(host_dreg)); - SHL(32, R(tmp1), Imm8(16)); - MOV(16,R(tmp1),R(host_dreg)); - CMP(32,R(host_dreg), R(tmp1)); - - FixupBranch no_saturate = J_CC(CC_Z); - - CMP(32,R(tmp1),Imm32(0)); - FixupBranch negative = J_CC(CC_LE); - - MOV(32,R(host_dreg),Imm32(0x7fff));//this works for all extend modes - FixupBranch done_positive = J(); - - SetJumpTarget(negative); - if (extend == NONE || extend == ZERO) - MOV(32,R(host_dreg),Imm32(0x00008000)); - else - MOV(32,R(host_dreg),Imm32(0xffff8000)); - FixupBranch done_negative = J(); - - SetJumpTarget(no_saturate); - if (extend == ZERO) - MOVZX(32,16,host_dreg,R(host_dreg)); - SetJumpTarget(done_positive); - SetJumpTarget(done_negative); - gpr.putXReg(tmp1); - gpr.flushRegs(c2); - SetJumpTarget(not_40bit); - gpr.flushRegs(c); -#else - - MOVSX(64,32,host_dreg,acc_reg); - CMP(64,R(host_dreg),acc_reg); - FixupBranch no_saturate = J_CC(CC_Z); - - CMP(64,acc_reg,Imm32(0)); - FixupBranch negative = J_CC(CC_LE); - - MOV(64,R(host_dreg),Imm32(0x7fff));//this works for all extend modes - FixupBranch done_positive = J(); - - SetJumpTarget(negative); - if (extend == NONE || extend == ZERO) - MOV(64,R(host_dreg),Imm32(0x00008000)); - else - MOV(64,R(host_dreg),Imm32(0xffff8000)); - FixupBranch done_negative = J(); - - SetJumpTarget(no_saturate); - SetJumpTarget(not_40bit); - - MOV(64, R(host_dreg), acc_reg); - if (extend == NONE || extend == ZERO) - SHR(64, R(host_dreg), Imm8(16)); - else - SAR(64, R(host_dreg), Imm8(16)); - SetJumpTarget(done_positive); - SetJumpTarget(done_negative); - gpr.flushRegs(c); - gpr.putReg(reg-DSP_REG_ACM0+DSP_REG_ACC0_64, false); -#endif - - gpr.putReg(DSP_REG_SR, false); -} - // MRR $D, $S // 0001 11dd ddds ssss // Move value from register $S to register $D. diff --git a/Source/Core/Core/Src/DSP/Jit/DSPJitUtil.cpp b/Source/Core/Core/Src/DSP/Jit/DSPJitUtil.cpp index 2fb18f83da..38c4dc23ca 100644 --- a/Source/Core/Core/Src/DSP/Jit/DSPJitUtil.cpp +++ b/Source/Core/Core/Src/DSP/Jit/DSPJitUtil.cpp @@ -24,6 +24,309 @@ using namespace Gen; +//clobbers: +//EAX = (s8)g_dsp.reg_stack_ptr[stack_reg] +//expects: +void DSPEmitter::dsp_reg_stack_push(int stack_reg) +{ + //g_dsp.reg_stack_ptr[stack_reg]++; + //g_dsp.reg_stack_ptr[stack_reg] &= DSP_STACK_MASK; + MOV(8, R(AL), M(&g_dsp.reg_stack_ptr[stack_reg])); + ADD(8, R(AL), Imm8(1)); + AND(8, R(AL), Imm8(DSP_STACK_MASK)); + MOV(8, M(&g_dsp.reg_stack_ptr[stack_reg]), R(AL)); + + X64Reg tmp1; + gpr.getFreeXReg(tmp1); + //g_dsp.reg_stack[stack_reg][g_dsp.reg_stack_ptr[stack_reg]] = g_dsp.r[DSP_REG_ST0 + stack_reg]; + MOV(16, R(tmp1), M(&g_dsp.r.st[stack_reg])); +#ifdef _M_IX86 // All32 + MOVZX(32, 8, EAX, R(AL)); +#else + MOVZX(64, 8, RAX, R(AL)); +#endif + MOV(16, MComplex(EAX, EAX, 1, + PtrOffset(&g_dsp.reg_stack[stack_reg][0],0)), R(tmp1)); + gpr.putXReg(tmp1); +} + +//clobbers: +//EAX = (s8)g_dsp.reg_stack_ptr[stack_reg] +//expects: +void DSPEmitter::dsp_reg_stack_pop(int stack_reg) +{ + //g_dsp.r[DSP_REG_ST0 + stack_reg] = g_dsp.reg_stack[stack_reg][g_dsp.reg_stack_ptr[stack_reg]]; + MOV(8, R(AL), M(&g_dsp.reg_stack_ptr[stack_reg])); + X64Reg tmp1; + gpr.getFreeXReg(tmp1); +#ifdef _M_IX86 // All32 + MOVZX(32, 8, EAX, R(AL)); +#else + MOVZX(64, 8, RAX, R(AL)); +#endif + MOV(16, R(tmp1), MComplex(EAX, EAX, 1, + PtrOffset(&g_dsp.reg_stack[stack_reg][0],0))); + MOV(16, M(&g_dsp.r.st[stack_reg]), R(tmp1)); + gpr.putXReg(tmp1); + + //g_dsp.reg_stack_ptr[stack_reg]--; + //g_dsp.reg_stack_ptr[stack_reg] &= DSP_STACK_MASK; + SUB(8, R(AL), Imm8(1)); + AND(8, R(AL), Imm8(DSP_STACK_MASK)); + MOV(8, M(&g_dsp.reg_stack_ptr[stack_reg]), R(AL)); +} + + +void DSPEmitter::dsp_reg_store_stack(int stack_reg, Gen::X64Reg host_sreg) +{ + if (host_sreg != EDX) { + MOV(16, R(EDX), R(host_sreg)); + } + dsp_reg_stack_push(stack_reg); + //g_dsp.r[DSP_REG_ST0 + stack_reg] = val; + MOV(16, M(&g_dsp.r.st[stack_reg]), R(EDX)); +} + +void DSPEmitter::dsp_reg_load_stack(int stack_reg, Gen::X64Reg host_dreg) +{ + //u16 val = g_dsp.r[DSP_REG_ST0 + stack_reg]; + MOV(16, R(EDX), M(&g_dsp.r.st[stack_reg])); + dsp_reg_stack_pop(stack_reg); + if (host_dreg != EDX) { + MOV(16, R(host_dreg), R(EDX)); + } +} + +void DSPEmitter::dsp_reg_store_stack_imm(int stack_reg, u16 val) +{ + dsp_reg_stack_push(stack_reg); + //g_dsp.r[DSP_REG_ST0 + stack_reg] = val; + MOV(16, M(&g_dsp.r.st[stack_reg]), Imm16(val)); +} + +void DSPEmitter::dsp_op_write_reg(int reg, Gen::X64Reg host_sreg) +{ + switch (reg & 0x1f) { + // 8-bit sign extended registers. + case DSP_REG_ACH0: + case DSP_REG_ACH1: + gpr.writeReg(reg, R(host_sreg)); + break; + + // Stack registers. + case DSP_REG_ST0: + case DSP_REG_ST1: + case DSP_REG_ST2: + case DSP_REG_ST3: + dsp_reg_store_stack(reg - DSP_REG_ST0, host_sreg); + break; + + default: + gpr.writeReg(reg, R(host_sreg)); + break; + } +} + +void DSPEmitter::dsp_op_write_reg_imm(int reg, u16 val) +{ + switch (reg & 0x1f) { + // 8-bit sign extended registers. Should look at prod.h too... + case DSP_REG_ACH0: + case DSP_REG_ACH1: + gpr.writeReg(reg, Imm16((u16)(s16)(s8)(u8)val)); + break; + // Stack registers. + case DSP_REG_ST0: + case DSP_REG_ST1: + case DSP_REG_ST2: + case DSP_REG_ST3: + dsp_reg_store_stack_imm(reg - DSP_REG_ST0, val); + break; + + default: + gpr.writeReg(reg, Imm16(val)); + break; + } +} + +void DSPEmitter::dsp_conditional_extend_accum(int reg) +{ + switch (reg) + { + case DSP_REG_ACM0: + case DSP_REG_ACM1: + { + OpArg sr_reg; + gpr.getReg(DSP_REG_SR,sr_reg); + DSPJitRegCache c(gpr); + TEST(16, sr_reg, Imm16(SR_40_MODE_BIT)); + FixupBranch not_40bit = J_CC(CC_Z,true); + //if (g_dsp.r[DSP_REG_SR] & SR_40_MODE_BIT) + //{ + // Sign extend into whole accum. + //u16 val = g_dsp.r[reg]; + get_acc_m(reg - DSP_REG_ACM0, EAX); + SHR(32, R(EAX), Imm8(16)); + //g_dsp.r[reg - DSP_REG_ACM0 + DSP_REG_ACH0] = (val & 0x8000) ? 0xFFFF : 0x0000; + //g_dsp.r[reg - DSP_REG_ACM0 + DSP_REG_ACL0] = 0; + set_acc_h(reg - DSP_REG_ACM0, R(RAX)); + set_acc_l(reg - DSP_REG_ACM0, Imm16(0)); + //} + gpr.flushRegs(c); + SetJumpTarget(not_40bit); + gpr.putReg(DSP_REG_SR, false); + } + } +} + +void DSPEmitter::dsp_conditional_extend_accum_imm(int reg, u16 val) +{ + switch (reg) + { + case DSP_REG_ACM0: + case DSP_REG_ACM1: + { + OpArg sr_reg; + gpr.getReg(DSP_REG_SR,sr_reg); + DSPJitRegCache c(gpr); + TEST(16, sr_reg, Imm16(SR_40_MODE_BIT)); + FixupBranch not_40bit = J_CC(CC_Z, true); + //if (g_dsp.r[DSP_REG_SR] & SR_40_MODE_BIT) + //{ + // Sign extend into whole accum. + //g_dsp.r[reg - DSP_REG_ACM0 + DSP_REG_ACH0] = (val & 0x8000) ? 0xFFFF : 0x0000; + //g_dsp.r[reg - DSP_REG_ACM0 + DSP_REG_ACL0] = 0; + set_acc_h(reg - DSP_REG_ACM0, Imm16((val & 0x8000)?0xffff:0x0000)); + set_acc_l(reg - DSP_REG_ACM0, Imm16(0)); + //} + gpr.flushRegs(c); + SetJumpTarget(not_40bit); + gpr.putReg(DSP_REG_SR, false); + } + } +} + +void DSPEmitter::dsp_op_read_reg(int reg, Gen::X64Reg host_dreg, DSPJitSignExtend extend) +{ + switch (reg & 0x1f) { + case DSP_REG_ST0: + case DSP_REG_ST1: + case DSP_REG_ST2: + case DSP_REG_ST3: + dsp_reg_load_stack(reg - DSP_REG_ST0, host_dreg); + switch(extend) { + case SIGN: +#ifdef _M_IX86 // All32 + MOVSX(32, 16, host_dreg, R(host_dreg)); +#else + MOVSX(64, 16, host_dreg, R(host_dreg)); +#endif + break; + case ZERO: +#ifdef _M_IX86 // All32 + MOVZX(32, 16, host_dreg, R(host_dreg)); +#else + MOVZX(64, 16, host_dreg, R(host_dreg)); +#endif + break; + case NONE: + default: + break; + } + return; + default: + gpr.readReg(reg, host_dreg, extend); + return; + } +} + +void DSPEmitter::dsp_op_read_reg_and_saturate(int reg, Gen::X64Reg host_dreg, DSPJitSignExtend extend) +{ + //we already know this is ACCM0 or ACCM1 +#ifdef _M_IX86 // All32 + gpr.readReg(reg, host_dreg, extend); +#else + OpArg acc_reg; + gpr.getReg(reg-DSP_REG_ACM0+DSP_REG_ACC0_64, acc_reg); +#endif + OpArg sr_reg; + gpr.getReg(DSP_REG_SR,sr_reg); + + DSPJitRegCache c(gpr); + TEST(16, sr_reg, Imm16(SR_40_MODE_BIT)); + FixupBranch not_40bit = J_CC(CC_Z, true); + +#ifdef _M_IX86 // All32 + DSPJitRegCache c2(gpr); + gpr.putReg(DSP_REG_SR, false); + X64Reg tmp1; + gpr.getFreeXReg(tmp1); + gpr.readReg(reg-DSP_REG_ACM0+DSP_REG_ACH0, tmp1, NONE); + MOVSX(32,16,host_dreg,R(host_dreg)); + SHL(32, R(tmp1), Imm8(16)); + MOV(16,R(tmp1),R(host_dreg)); + CMP(32,R(host_dreg), R(tmp1)); + + FixupBranch no_saturate = J_CC(CC_Z); + + CMP(32,R(tmp1),Imm32(0)); + FixupBranch negative = J_CC(CC_LE); + + MOV(32,R(host_dreg),Imm32(0x7fff));//this works for all extend modes + FixupBranch done_positive = J(); + + SetJumpTarget(negative); + if (extend == NONE || extend == ZERO) + MOV(32,R(host_dreg),Imm32(0x00008000)); + else + MOV(32,R(host_dreg),Imm32(0xffff8000)); + FixupBranch done_negative = J(); + + SetJumpTarget(no_saturate); + if (extend == ZERO) + MOVZX(32,16,host_dreg,R(host_dreg)); + SetJumpTarget(done_positive); + SetJumpTarget(done_negative); + gpr.putXReg(tmp1); + gpr.flushRegs(c2); + SetJumpTarget(not_40bit); + gpr.flushRegs(c); +#else + + MOVSX(64,32,host_dreg,acc_reg); + CMP(64,R(host_dreg),acc_reg); + FixupBranch no_saturate = J_CC(CC_Z); + + CMP(64,acc_reg,Imm32(0)); + FixupBranch negative = J_CC(CC_LE); + + MOV(64,R(host_dreg),Imm32(0x7fff));//this works for all extend modes + FixupBranch done_positive = J(); + + SetJumpTarget(negative); + if (extend == NONE || extend == ZERO) + MOV(64,R(host_dreg),Imm32(0x00008000)); + else + MOV(64,R(host_dreg),Imm32(0xffff8000)); + FixupBranch done_negative = J(); + + SetJumpTarget(no_saturate); + SetJumpTarget(not_40bit); + + MOV(64, R(host_dreg), acc_reg); + if (extend == NONE || extend == ZERO) + SHR(64, R(host_dreg), Imm8(16)); + else + SAR(64, R(host_dreg), Imm8(16)); + SetJumpTarget(done_positive); + SetJumpTarget(done_negative); + gpr.flushRegs(c); + gpr.putReg(reg-DSP_REG_ACM0+DSP_REG_ACC0_64, false); +#endif + + gpr.putReg(DSP_REG_SR, false); +} + // addr math // // These functions detect overflow by checking if From a902c720e014732564da426978e7c471e46ed14e Mon Sep 17 00:00:00 2001 From: Pierre Date: Sun, 4 Sep 2011 15:37:53 +0200 Subject: [PATCH 02/11] DSP/Jit: Fold the test for ACMx into dsp_op_read_reg() adds a new dsp_op_read_reg_dont_saturate for the few cases where saturation is not appropriate --- Source/Core/Core/Src/DSP/DSPEmitter.h | 2 +- Source/Core/Core/Src/DSP/Jit/DSPJitBranch.cpp | 6 +- Source/Core/Core/Src/DSP/Jit/DSPJitExtOps.cpp | 43 ++--- .../Core/Core/Src/DSP/Jit/DSPJitLoadStore.cpp | 30 +--- Source/Core/Core/Src/DSP/Jit/DSPJitMisc.cpp | 5 +- Source/Core/Core/Src/DSP/Jit/DSPJitUtil.cpp | 164 +++++++++++------- 6 files changed, 125 insertions(+), 125 deletions(-) diff --git a/Source/Core/Core/Src/DSP/DSPEmitter.h b/Source/Core/Core/Src/DSP/DSPEmitter.h index 7fcb9a74f6..a59dd05ca6 100644 --- a/Source/Core/Core/Src/DSP/DSPEmitter.h +++ b/Source/Core/Core/Src/DSP/DSPEmitter.h @@ -120,8 +120,8 @@ public: void dsp_op_write_reg_imm(int reg, u16 val); void dsp_conditional_extend_accum(int reg); void dsp_conditional_extend_accum_imm(int reg, u16 val); + void dsp_op_read_reg_dont_saturate(int reg, Gen::X64Reg host_dreg, DSPJitSignExtend extend = NONE); void dsp_op_read_reg(int reg, Gen::X64Reg host_dreg, DSPJitSignExtend extend = NONE); - void dsp_op_read_reg_and_saturate(int reg, Gen::X64Reg host_dreg, DSPJitSignExtend extend = NONE); // Commands void dar(const UDSPInstruction opc); diff --git a/Source/Core/Core/Src/DSP/Jit/DSPJitBranch.cpp b/Source/Core/Core/Src/DSP/Jit/DSPJitBranch.cpp index 252550b84c..deeaea28c9 100644 --- a/Source/Core/Core/Src/DSP/Jit/DSPJitBranch.cpp +++ b/Source/Core/Core/Src/DSP/Jit/DSPJitBranch.cpp @@ -334,7 +334,8 @@ void DSPEmitter::loop(const UDSPInstruction opc) { u16 reg = opc & 0x1f; // u16 cnt = g_dsp.r[reg]; - dsp_op_read_reg(reg, RDX, ZERO); +//todo: check if we can use normal variant here + dsp_op_read_reg_dont_saturate(reg, RDX, ZERO); u16 loop_pc = compilePC + 1; CMP(16, R(EDX), Imm16(0)); @@ -403,7 +404,8 @@ void DSPEmitter::bloop(const UDSPInstruction opc) { u16 reg = opc & 0x1f; // u16 cnt = g_dsp.r[reg]; - dsp_op_read_reg(reg, RDX, ZERO); +//todo: check if we can use normal variant here + dsp_op_read_reg_dont_saturate(reg, RDX, ZERO); u16 loop_pc = dsp_imem_read(compilePC + 1); CMP(16, R(EDX), Imm16(0)); diff --git a/Source/Core/Core/Src/DSP/Jit/DSPJitExtOps.cpp b/Source/Core/Core/Src/DSP/Jit/DSPJitExtOps.cpp index 40e39a89e9..91dae79ade 100644 --- a/Source/Core/Core/Src/DSP/Jit/DSPJitExtOps.cpp +++ b/Source/Core/Core/Src/DSP/Jit/DSPJitExtOps.cpp @@ -68,11 +68,8 @@ void DSPEmitter::mv(const UDSPInstruction opc) { u8 sreg = (opc & 0x3) + DSP_REG_ACL0; u8 dreg = ((opc >> 2) & 0x3); - if (sreg >= DSP_REG_ACM0) { - dsp_op_read_reg_and_saturate(sreg, RBX, ZERO); - storeIndex = dreg + DSP_REG_AXL0; - } else - pushExtValueFromReg(dreg + DSP_REG_AXL0, sreg); + dsp_op_read_reg(sreg, RBX, ZERO); + storeIndex = dreg + DSP_REG_AXL0; } // S @$arD, $acS.S @@ -89,10 +86,7 @@ void DSPEmitter::s(const UDSPInstruction opc) X64Reg tmp1; gpr.getFreeXReg(tmp1); - if (sreg >= DSP_REG_ACM0) - dsp_op_read_reg_and_saturate(sreg, tmp1, ZERO); - else - dsp_op_read_reg(sreg, tmp1, ZERO); + dsp_op_read_reg(sreg, tmp1, ZERO); // u16 val = g_dsp.r[src]; dmem_write(tmp1); @@ -114,10 +108,7 @@ void DSPEmitter::sn(const UDSPInstruction opc) X64Reg tmp1; gpr.getFreeXReg(tmp1); - if (sreg >= DSP_REG_ACM0) - dsp_op_read_reg_and_saturate(sreg, tmp1, ZERO); - else - dsp_op_read_reg(sreg, tmp1, ZERO); + dsp_op_read_reg(sreg, tmp1, ZERO); dmem_write(tmp1); gpr.putXReg(tmp1); @@ -187,7 +178,7 @@ void DSPEmitter::ls(const UDSPInstruction opc) X64Reg tmp1; gpr.getFreeXReg(tmp1); - dsp_op_read_reg_and_saturate(sreg + DSP_REG_ACM0, tmp1, ZERO); + dsp_op_read_reg(sreg + DSP_REG_ACM0, tmp1, ZERO); dmem_write(tmp1); gpr.putXReg(tmp1); @@ -214,7 +205,7 @@ void DSPEmitter::lsn(const UDSPInstruction opc) X64Reg tmp1; gpr.getFreeXReg(tmp1); - dsp_op_read_reg_and_saturate(sreg + DSP_REG_ACM0, tmp1, ZERO); + dsp_op_read_reg(sreg + DSP_REG_ACM0, tmp1, ZERO); dmem_write(tmp1); gpr.putXReg(tmp1); @@ -240,7 +231,7 @@ void DSPEmitter::lsm(const UDSPInstruction opc) X64Reg tmp1; gpr.getFreeXReg(tmp1); - dsp_op_read_reg_and_saturate(sreg + DSP_REG_ACM0, tmp1, ZERO); + dsp_op_read_reg(sreg + DSP_REG_ACM0, tmp1, ZERO); dmem_write(tmp1); gpr.putXReg(tmp1); @@ -267,7 +258,7 @@ void DSPEmitter::lsnm(const UDSPInstruction opc) X64Reg tmp1; gpr.getFreeXReg(tmp1); - dsp_op_read_reg_and_saturate(sreg + DSP_REG_ACM0, tmp1, ZERO); + dsp_op_read_reg(sreg + DSP_REG_ACM0, tmp1, ZERO); dmem_write(tmp1); gpr.putXReg(tmp1); @@ -292,7 +283,7 @@ void DSPEmitter::sl(const UDSPInstruction opc) X64Reg tmp1; gpr.getFreeXReg(tmp1); - dsp_op_read_reg_and_saturate(sreg + DSP_REG_ACM0, tmp1, ZERO); + dsp_op_read_reg(sreg + DSP_REG_ACM0, tmp1, ZERO); dmem_write(tmp1); gpr.putXReg(tmp1); @@ -318,7 +309,7 @@ void DSPEmitter::sln(const UDSPInstruction opc) X64Reg tmp1; gpr.getFreeXReg(tmp1); - dsp_op_read_reg_and_saturate(sreg + DSP_REG_ACM0, tmp1, ZERO); + dsp_op_read_reg(sreg + DSP_REG_ACM0, tmp1, ZERO); dmem_write(tmp1); gpr.putXReg(tmp1); @@ -344,7 +335,7 @@ void DSPEmitter::slm(const UDSPInstruction opc) X64Reg tmp1; gpr.getFreeXReg(tmp1); - dsp_op_read_reg_and_saturate(sreg + DSP_REG_ACM0, tmp1, ZERO); + dsp_op_read_reg(sreg + DSP_REG_ACM0, tmp1, ZERO); dmem_write(tmp1); gpr.putXReg(tmp1); @@ -370,7 +361,7 @@ void DSPEmitter::slnm(const UDSPInstruction opc) X64Reg tmp1; gpr.getFreeXReg(tmp1); - dsp_op_read_reg_and_saturate(sreg + DSP_REG_ACM0, tmp1, ZERO); + dsp_op_read_reg(sreg + DSP_REG_ACM0, tmp1, ZERO); dmem_write(tmp1); gpr.putXReg(tmp1); @@ -649,14 +640,8 @@ void DSPEmitter::ldaxnm(const UDSPInstruction opc) increase_addr_reg(DSP_REG_AR3, DSP_REG_AR3); } - -// Push value from g_dsp.r[sreg] into EBX and stores the destinationindex in -// storeIndex -void DSPEmitter::pushExtValueFromReg(u16 dreg, u16 sreg) { - dsp_op_read_reg(sreg, RBX, ZERO); - storeIndex = dreg; -} - +// Push value from address in g_dsp.r[sreg] into EBX and stores the +// destinationindex in storeIndex void DSPEmitter::pushExtValueFromMem(u16 dreg, u16 sreg) { // u16 addr = g_dsp.r[addr]; diff --git a/Source/Core/Core/Src/DSP/Jit/DSPJitLoadStore.cpp b/Source/Core/Core/Src/DSP/Jit/DSPJitLoadStore.cpp index 248ed8f945..38255f0c47 100644 --- a/Source/Core/Core/Src/DSP/Jit/DSPJitLoadStore.cpp +++ b/Source/Core/Core/Src/DSP/Jit/DSPJitLoadStore.cpp @@ -39,10 +39,7 @@ void DSPEmitter::srs(const UDSPInstruction opc) X64Reg tmp1; gpr.getFreeXReg(tmp1); - if (reg >= DSP_REG_ACM0) - dsp_op_read_reg_and_saturate(reg, tmp1, ZERO); - else - dsp_op_read_reg(reg, tmp1, ZERO); + dsp_op_read_reg(reg, tmp1, ZERO); dsp_op_read_reg(DSP_REG_CR, RAX, ZERO); SHL(16, R(EAX), Imm8(8)); OR(16, R(EAX), Imm16(opc & 0xFF)); @@ -101,10 +98,7 @@ void DSPEmitter::sr(const UDSPInstruction opc) X64Reg tmp1; gpr.getFreeXReg(tmp1); - if (reg >= DSP_REG_ACM0) - dsp_op_read_reg_and_saturate(reg, tmp1); - else - dsp_op_read_reg(reg, tmp1); + dsp_op_read_reg(reg, tmp1); dmem_write_imm(address, tmp1); gpr.putXReg(tmp1); @@ -227,10 +221,7 @@ void DSPEmitter::srr(const UDSPInstruction opc) X64Reg tmp1; gpr.getFreeXReg(tmp1); - if (sreg >= DSP_REG_ACM0) - dsp_op_read_reg_and_saturate(sreg, tmp1); - else - dsp_op_read_reg(sreg, tmp1); + dsp_op_read_reg(sreg, tmp1); dsp_op_read_reg(dreg, RAX, ZERO); dmem_write(tmp1); @@ -249,10 +240,7 @@ void DSPEmitter::srrd(const UDSPInstruction opc) X64Reg tmp1; gpr.getFreeXReg(tmp1); - if (sreg >= DSP_REG_ACM0) - dsp_op_read_reg_and_saturate(sreg, tmp1); - else - dsp_op_read_reg(sreg, tmp1); + dsp_op_read_reg(sreg, tmp1); dsp_op_read_reg(dreg, RAX, ZERO); dmem_write(tmp1); @@ -273,10 +261,7 @@ void DSPEmitter::srri(const UDSPInstruction opc) X64Reg tmp1; gpr.getFreeXReg(tmp1); - if (sreg >= DSP_REG_ACM0) - dsp_op_read_reg_and_saturate(sreg, tmp1); - else - dsp_op_read_reg(sreg, tmp1); + dsp_op_read_reg(sreg, tmp1); dsp_op_read_reg(dreg, RAX, ZERO); dmem_write(tmp1); @@ -297,10 +282,7 @@ void DSPEmitter::srrn(const UDSPInstruction opc) X64Reg tmp1; gpr.getFreeXReg(tmp1); - if (sreg >= DSP_REG_ACM0) - dsp_op_read_reg_and_saturate(sreg, tmp1); - else - dsp_op_read_reg(sreg, tmp1); + dsp_op_read_reg(sreg, tmp1); dsp_op_read_reg(dreg, RAX, ZERO); dmem_write(tmp1); diff --git a/Source/Core/Core/Src/DSP/Jit/DSPJitMisc.cpp b/Source/Core/Core/Src/DSP/Jit/DSPJitMisc.cpp index e26db20ecf..6138bc5455 100644 --- a/Source/Core/Core/Src/DSP/Jit/DSPJitMisc.cpp +++ b/Source/Core/Core/Src/DSP/Jit/DSPJitMisc.cpp @@ -31,10 +31,7 @@ void DSPEmitter::mrr(const UDSPInstruction opc) u8 sreg = opc & 0x1f; u8 dreg = (opc >> 5) & 0x1f; - if (sreg >= DSP_REG_ACM0) - dsp_op_read_reg_and_saturate(sreg, EDX); - else - dsp_op_read_reg(sreg, EDX); + dsp_op_read_reg(sreg, EDX); dsp_op_write_reg(dreg, EDX); dsp_conditional_extend_accum(dreg); } diff --git a/Source/Core/Core/Src/DSP/Jit/DSPJitUtil.cpp b/Source/Core/Core/Src/DSP/Jit/DSPJitUtil.cpp index 38c4dc23ca..adf4d33276 100644 --- a/Source/Core/Core/Src/DSP/Jit/DSPJitUtil.cpp +++ b/Source/Core/Core/Src/DSP/Jit/DSPJitUtil.cpp @@ -206,7 +206,7 @@ void DSPEmitter::dsp_conditional_extend_accum_imm(int reg, u16 val) } } -void DSPEmitter::dsp_op_read_reg(int reg, Gen::X64Reg host_dreg, DSPJitSignExtend extend) +void DSPEmitter::dsp_op_read_reg_dont_saturate(int reg, Gen::X64Reg host_dreg, DSPJitSignExtend extend) { switch (reg & 0x1f) { case DSP_REG_ST0: @@ -240,91 +240,125 @@ void DSPEmitter::dsp_op_read_reg(int reg, Gen::X64Reg host_dreg, DSPJitSignExten } } -void DSPEmitter::dsp_op_read_reg_and_saturate(int reg, Gen::X64Reg host_dreg, DSPJitSignExtend extend) +void DSPEmitter::dsp_op_read_reg(int reg, Gen::X64Reg host_dreg, DSPJitSignExtend extend) { - //we already know this is ACCM0 or ACCM1 + switch (reg & 0x1f) { + case DSP_REG_ST0: + case DSP_REG_ST1: + case DSP_REG_ST2: + case DSP_REG_ST3: + dsp_reg_load_stack(reg - DSP_REG_ST0, host_dreg); + switch(extend) { + case SIGN: #ifdef _M_IX86 // All32 - gpr.readReg(reg, host_dreg, extend); + MOVSX(32, 16, host_dreg, R(host_dreg)); #else - OpArg acc_reg; - gpr.getReg(reg-DSP_REG_ACM0+DSP_REG_ACC0_64, acc_reg); + MOVSX(64, 16, host_dreg, R(host_dreg)); #endif - OpArg sr_reg; - gpr.getReg(DSP_REG_SR,sr_reg); + break; + case ZERO: +#ifdef _M_IX86 // All32 + MOVZX(32, 16, host_dreg, R(host_dreg)); +#else + MOVZX(64, 16, host_dreg, R(host_dreg)); +#endif + break; + case NONE: + default: + break; + } + return; + case DSP_REG_ACM0: + case DSP_REG_ACM1: { + //we already know this is ACCM0 or ACCM1 +#ifdef _M_IX86 // All32 + gpr.readReg(reg, host_dreg, extend); +#else + OpArg acc_reg; + gpr.getReg(reg-DSP_REG_ACM0+DSP_REG_ACC0_64, acc_reg); +#endif + OpArg sr_reg; + gpr.getReg(DSP_REG_SR,sr_reg); - DSPJitRegCache c(gpr); - TEST(16, sr_reg, Imm16(SR_40_MODE_BIT)); - FixupBranch not_40bit = J_CC(CC_Z, true); + DSPJitRegCache c(gpr); + TEST(16, sr_reg, Imm16(SR_40_MODE_BIT)); + FixupBranch not_40bit = J_CC(CC_Z, true); #ifdef _M_IX86 // All32 - DSPJitRegCache c2(gpr); - gpr.putReg(DSP_REG_SR, false); - X64Reg tmp1; - gpr.getFreeXReg(tmp1); - gpr.readReg(reg-DSP_REG_ACM0+DSP_REG_ACH0, tmp1, NONE); - MOVSX(32,16,host_dreg,R(host_dreg)); - SHL(32, R(tmp1), Imm8(16)); - MOV(16,R(tmp1),R(host_dreg)); - CMP(32,R(host_dreg), R(tmp1)); + DSPJitRegCache c2(gpr); + gpr.putReg(DSP_REG_SR, false); + X64Reg tmp1; + gpr.getFreeXReg(tmp1); + gpr.readReg(reg-DSP_REG_ACM0+DSP_REG_ACH0, tmp1, NONE); + MOVSX(32,16,host_dreg,R(host_dreg)); + SHL(32, R(tmp1), Imm8(16)); + MOV(16,R(tmp1),R(host_dreg)); + CMP(32,R(host_dreg), R(tmp1)); - FixupBranch no_saturate = J_CC(CC_Z); + FixupBranch no_saturate = J_CC(CC_Z); - CMP(32,R(tmp1),Imm32(0)); - FixupBranch negative = J_CC(CC_LE); + CMP(32,R(tmp1),Imm32(0)); + FixupBranch negative = J_CC(CC_LE); - MOV(32,R(host_dreg),Imm32(0x7fff));//this works for all extend modes - FixupBranch done_positive = J(); + MOV(32,R(host_dreg),Imm32(0x7fff));//this works for all extend modes + FixupBranch done_positive = J(); - SetJumpTarget(negative); - if (extend == NONE || extend == ZERO) - MOV(32,R(host_dreg),Imm32(0x00008000)); - else - MOV(32,R(host_dreg),Imm32(0xffff8000)); - FixupBranch done_negative = J(); + SetJumpTarget(negative); + if (extend == NONE || extend == ZERO) + MOV(32,R(host_dreg),Imm32(0x00008000)); + else + MOV(32,R(host_dreg),Imm32(0xffff8000)); + FixupBranch done_negative = J(); - SetJumpTarget(no_saturate); - if (extend == ZERO) - MOVZX(32,16,host_dreg,R(host_dreg)); - SetJumpTarget(done_positive); - SetJumpTarget(done_negative); - gpr.putXReg(tmp1); - gpr.flushRegs(c2); - SetJumpTarget(not_40bit); - gpr.flushRegs(c); + SetJumpTarget(no_saturate); + if (extend == ZERO) + MOVZX(32,16,host_dreg,R(host_dreg)); + SetJumpTarget(done_positive); + SetJumpTarget(done_negative); + gpr.putXReg(tmp1); + gpr.flushRegs(c2); + SetJumpTarget(not_40bit); + gpr.flushRegs(c); #else - MOVSX(64,32,host_dreg,acc_reg); - CMP(64,R(host_dreg),acc_reg); - FixupBranch no_saturate = J_CC(CC_Z); + MOVSX(64,32,host_dreg,acc_reg); + CMP(64,R(host_dreg),acc_reg); + FixupBranch no_saturate = J_CC(CC_Z); - CMP(64,acc_reg,Imm32(0)); - FixupBranch negative = J_CC(CC_LE); + CMP(64,acc_reg,Imm32(0)); + FixupBranch negative = J_CC(CC_LE); - MOV(64,R(host_dreg),Imm32(0x7fff));//this works for all extend modes - FixupBranch done_positive = J(); + MOV(64,R(host_dreg),Imm32(0x7fff));//this works for all extend modes + FixupBranch done_positive = J(); - SetJumpTarget(negative); - if (extend == NONE || extend == ZERO) - MOV(64,R(host_dreg),Imm32(0x00008000)); - else - MOV(64,R(host_dreg),Imm32(0xffff8000)); - FixupBranch done_negative = J(); + SetJumpTarget(negative); + if (extend == NONE || extend == ZERO) + MOV(64,R(host_dreg),Imm32(0x00008000)); + else + MOV(64,R(host_dreg),Imm32(0xffff8000)); + FixupBranch done_negative = J(); - SetJumpTarget(no_saturate); - SetJumpTarget(not_40bit); + SetJumpTarget(no_saturate); + SetJumpTarget(not_40bit); - MOV(64, R(host_dreg), acc_reg); - if (extend == NONE || extend == ZERO) - SHR(64, R(host_dreg), Imm8(16)); - else - SAR(64, R(host_dreg), Imm8(16)); - SetJumpTarget(done_positive); - SetJumpTarget(done_negative); - gpr.flushRegs(c); - gpr.putReg(reg-DSP_REG_ACM0+DSP_REG_ACC0_64, false); + MOV(64, R(host_dreg), acc_reg); + if (extend == NONE || extend == ZERO) + SHR(64, R(host_dreg), Imm8(16)); + else + SAR(64, R(host_dreg), Imm8(16)); + SetJumpTarget(done_positive); + SetJumpTarget(done_negative); + gpr.flushRegs(c); + gpr.putReg(reg-DSP_REG_ACM0+DSP_REG_ACC0_64, false); #endif - gpr.putReg(DSP_REG_SR, false); + gpr.putReg(DSP_REG_SR, false); + } + return; + default: + gpr.readReg(reg, host_dreg, extend); + return; + } } // addr math From 5440ddde148bf34a32bccf689350a2d1211e1d49 Mon Sep 17 00:00:00 2001 From: Pierre Date: Sun, 22 Jul 2012 22:55:16 +0200 Subject: [PATCH 03/11] DSP: regcache: Synch host regs back to previous state only if we are told to not emit the fixup to get it to that state --- Source/Core/Core/Src/DSP/Jit/DSPJitRegCache.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/Source/Core/Core/Src/DSP/Jit/DSPJitRegCache.cpp b/Source/Core/Core/Src/DSP/Jit/DSPJitRegCache.cpp index 687982cfb9..7a4050afd8 100644 --- a/Source/Core/Core/Src/DSP/Jit/DSPJitRegCache.cpp +++ b/Source/Core/Core/Src/DSP/Jit/DSPJitRegCache.cpp @@ -251,6 +251,18 @@ void DSPJitRegCache::flushRegs(DSPJitRegCache &cache, bool emit) regs[i].last_use_ctr = cache.regs[i].last_use_ctr; } + //sync the freely used xregs + if (!emit) { + for(i = 0; i < NUMXREGS; i++) { + if (cache.xregs[i].guest_reg == DSP_REG_USED && + xregs[i].guest_reg == DSP_REG_NONE) + xregs[i].guest_reg = DSP_REG_USED; + if (cache.xregs[i].guest_reg == DSP_REG_NONE && + xregs[i].guest_reg == DSP_REG_USED) + xregs[i].guest_reg = DSP_REG_NONE; + } + } + //consistency checks for(i = 0; i < NUMXREGS; i++) { _assert_msg_(DSPLLE, From 6873443a9a9015f23dd6aeb59047464883ccca6a Mon Sep 17 00:00:00 2001 From: Pierre Date: Mon, 2 Apr 2012 21:02:46 +0200 Subject: [PATCH 04/11] DSPJIT: RegCache: Fix writing immediates to guest registers --- .../Core/Core/Src/DSP/Jit/DSPJitRegCache.cpp | 32 +++++++++++++++---- 1 file changed, 25 insertions(+), 7 deletions(-) diff --git a/Source/Core/Core/Src/DSP/Jit/DSPJitRegCache.cpp b/Source/Core/Core/Src/DSP/Jit/DSPJitRegCache.cpp index 7a4050afd8..6397172800 100644 --- a/Source/Core/Core/Src/DSP/Jit/DSPJitRegCache.cpp +++ b/Source/Core/Core/Src/DSP/Jit/DSPJitRegCache.cpp @@ -854,15 +854,33 @@ void DSPJitRegCache::writeReg(int dreg, OpArg arg) { OpArg reg; getReg(dreg, reg, false); - switch(regs[dreg].size) { - case 2: emitter.MOV(16, reg, arg); break; - case 4: emitter.MOV(32, reg, arg); break; + if (arg.IsImm()) { + switch(regs[dreg].size) { + case 2: emitter.MOV(16, reg, Imm16(arg.offset)); break; + case 4: emitter.MOV(32, reg, Imm32(arg.offset)); break; #ifdef _M_X64 - case 8: emitter.MOV(64, reg, arg); break; + case 8: + if ((s32)arg.offset == (s64)arg.offset) + emitter.MOV(64, reg, Imm32(arg.offset)); + else + emitter.MOV(64, reg, Imm64(arg.offset)); + break; #endif - default: - _assert_msg_(DSPLLE, 0, "unsupported memory size"); - break; + default: + _assert_msg_(DSPLLE, 0, "unsupported memory size"); + break; + } + } else { + switch(regs[dreg].size) { + case 2: emitter.MOV(16, reg, arg); break; + case 4: emitter.MOV(32, reg, arg); break; +#ifdef _M_X64 + case 8: emitter.MOV(64, reg, arg); break; +#endif + default: + _assert_msg_(DSPLLE, 0, "unsupported memory size"); + break; + } } putReg(dreg, true); } From 9c1d18a14cd010f251c5af4f81c73d630d24444d Mon Sep 17 00:00:00 2001 From: Pierre Date: Sun, 22 Jul 2012 23:53:54 +0200 Subject: [PATCH 05/11] DSP/Jit: Some small optimizations to lsrn emitter --- Source/Core/Core/Src/DSP/Jit/DSPJitArithmetic.cpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/Source/Core/Core/Src/DSP/Jit/DSPJitArithmetic.cpp b/Source/Core/Core/Src/DSP/Jit/DSPJitArithmetic.cpp index 185ada8ba3..85511c1b9d 100644 --- a/Source/Core/Core/Src/DSP/Jit/DSPJitArithmetic.cpp +++ b/Source/Core/Core/Src/DSP/Jit/DSPJitArithmetic.cpp @@ -1570,16 +1570,17 @@ void DSPEmitter::lsrn(const UDSPInstruction opc) // acc <<= -shift; // } - CMP(64, R(RDX), Imm8(0)); + CMP(64, R(RDX), Imm8(0));//is this actually worth the branch cost? FixupBranch zero = J_CC(CC_E); - TEST(16, R(RAX), Imm16(0x3f)); + TEST(16, R(RAX), Imm16(0x3f));//is this actually worth the branch cost? FixupBranch noShift = J_CC(CC_Z); - MOVZX(64, 16, RCX, R(RAX)); - AND(16, R(RCX), Imm16(0x3f)); +//CL gets automatically masked with 0x3f on IA32/AMD64 + //MOVZX(64, 16, RCX, R(RAX)); + //AND(16, R(RCX), Imm16(0x3f)); TEST(16, R(RAX), Imm16(0x40)); FixupBranch shiftLeft = J_CC(CC_Z); NEG(16, R(RCX)); - ADD(16, R(RCX), Imm16(0x40)); + //ADD(16, R(RCX), Imm16(0x40)); SHL(64, R(RDX), R(RCX)); FixupBranch exit = J(); SetJumpTarget(shiftLeft); From 701b5916ababc24ca62910d6874d9d31c037ee93 Mon Sep 17 00:00:00 2001 From: Pierre Date: Sun, 30 Dec 2012 19:38:49 +0100 Subject: [PATCH 06/11] Revert "In memory of calc84." This reverts commit 539bf405f2df07e84ac0d549c4553d0b1435d231. --- Source/Core/Common/Src/x64Emitter.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/Source/Core/Common/Src/x64Emitter.cpp b/Source/Core/Common/Src/x64Emitter.cpp index 1a74eaef80..022115a40a 100644 --- a/Source/Core/Common/Src/x64Emitter.cpp +++ b/Source/Core/Common/Src/x64Emitter.cpp @@ -1068,10 +1068,8 @@ void XEmitter::XOR (int bits, const OpArg &a1, const OpArg &a2) {WriteNormalOp(t void XEmitter::MOV (int bits, const OpArg &a1, const OpArg &a2) { #ifdef _DEBUG -#ifndef _M_X64 _assert_msg_(DYNA_REC, !a1.IsSimpleReg() || !a2.IsSimpleReg() || a1.GetSimpleReg() != a2.GetSimpleReg(), "Redundant MOV @ %p - bug in JIT?", - code); -#endif + code); #endif WriteNormalOp(this, bits, nrmMOV, a1, a2); } From 6b5b8ab5bee7283281e53df40ebc881570dc74fa Mon Sep 17 00:00:00 2001 From: Pierre Date: Sat, 25 Aug 2012 01:00:13 +0200 Subject: [PATCH 07/11] Implement and use MOVZX(64, 32,...) Probably better to keep that same-register-MOV assert useful. Also, explicit type extension documents whats happening. Internally, this boils down to the original MOV, but without the assert. --- Source/Core/Common/Src/x64Emitter.cpp | 4 ++++ Source/Core/Core/Src/PowerPC/Jit64/Jit_Integer.cpp | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/Source/Core/Common/Src/x64Emitter.cpp b/Source/Core/Common/Src/x64Emitter.cpp index 022115a40a..e79f73fcca 100644 --- a/Source/Core/Common/Src/x64Emitter.cpp +++ b/Source/Core/Common/Src/x64Emitter.cpp @@ -768,6 +768,10 @@ void XEmitter::MOVZX(int dbits, int sbits, X64Reg dest, OpArg src) Write8(0x0F); Write8(0xB7); } + else if (sbits == 32 && dbits == 64) + { + Write8(0x8B); + } else { Crash(); diff --git a/Source/Core/Core/Src/PowerPC/Jit64/Jit_Integer.cpp b/Source/Core/Core/Src/PowerPC/Jit64/Jit_Integer.cpp index 3d88d687e0..b444dbd783 100644 --- a/Source/Core/Core/Src/PowerPC/Jit64/Jit_Integer.cpp +++ b/Source/Core/Core/Src/PowerPC/Jit64/Jit_Integer.cpp @@ -1977,7 +1977,7 @@ void Jit64::slwx(UGeckoInstruction inst) } else { - MOV(32, gpr.R(a), gpr.R(a)); + MOVZX(64, 32, gpr.R(a).GetSimpleReg(), gpr.R(a)); } gpr.UnlockAll(); gpr.UnlockAllX(); From d3de29c673b6e138c739ec30ebdb2fe026ccf385 Mon Sep 17 00:00:00 2001 From: Pierre Date: Mon, 27 Aug 2012 22:16:08 +0200 Subject: [PATCH 08/11] DSPJit: fix bug in DSPJitRegCache::getXReg --- Source/Core/Core/Src/DSP/Jit/DSPJitRegCache.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Core/Core/Src/DSP/Jit/DSPJitRegCache.cpp b/Source/Core/Core/Src/DSP/Jit/DSPJitRegCache.cpp index 6397172800..aa12da9d12 100644 --- a/Source/Core/Core/Src/DSP/Jit/DSPJitRegCache.cpp +++ b/Source/Core/Core/Src/DSP/Jit/DSPJitRegCache.cpp @@ -982,7 +982,7 @@ void DSPJitRegCache::getXReg(X64Reg reg) } if (xregs[reg].guest_reg != DSP_REG_NONE) spillXReg(reg); - _assert_msg_(DSPLLE, xregs[reg].guest_reg != DSP_REG_NONE, "register already in use"); + _assert_msg_(DSPLLE, xregs[reg].guest_reg == DSP_REG_NONE, "register already in use"); xregs[reg].guest_reg = DSP_REG_USED; } From 5cbe75b389b819dcdaf140e3eef0be9593311a3c Mon Sep 17 00:00:00 2001 From: Pierre Date: Sun, 7 Oct 2012 22:35:33 +0200 Subject: [PATCH 09/11] DSPJIT: fix increase/decrease_addr_reg to match interpreter again --- Source/Core/Core/Src/DSP/Jit/DSPJitUtil.cpp | 22 +++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/Source/Core/Core/Src/DSP/Jit/DSPJitUtil.cpp b/Source/Core/Core/Src/DSP/Jit/DSPJitUtil.cpp index adf4d33276..4edcb556a8 100644 --- a/Source/Core/Core/Src/DSP/Jit/DSPJitUtil.cpp +++ b/Source/Core/Core/Src/DSP/Jit/DSPJitUtil.cpp @@ -469,13 +469,14 @@ void DSPEmitter::increase_addr_reg(int reg, int _ix_reg) //eax = dar XOR(32, R(EAX), R(ECX)); XOR(32, R(EAX), R(tmp1)); - LEA(32, ECX, MRegSum(EDX, EDX)); - OR(32, R(ECX), Imm8(2)); - AND(32, R(EAX), R(ECX)); //if (ix >= 0) TEST(32, R(ECX), R(ECX)); FixupBranch negative = J_CC(CC_S); + LEA(32, ECX, MRegSum(EDX, EDX)); + OR(32, R(ECX), Imm8(2)); + AND(32, R(EAX), R(ECX)); + //if (dar > wr) CMP(32, R(EAX), R(EDX)); FixupBranch done = J_CC(CC_BE); @@ -486,6 +487,10 @@ void DSPEmitter::increase_addr_reg(int reg, int _ix_reg) //else SetJumpTarget(negative); + LEA(32, ECX, MRegSum(EDX, EDX)); + OR(32, R(ECX), Imm8(2)); + AND(32, R(EAX), R(ECX)); + //if ((((nar + wr + 1) ^ nar) & dar) <= wr) LEA(32, ECX, MComplex(tmp1, EDX, 1, 1)); XOR(32, R(ECX), R(tmp1)); @@ -534,13 +539,14 @@ void DSPEmitter::decrease_addr_reg(int reg) //eax = dar XOR(32, R(EAX), R(ECX)); XOR(32, R(EAX), R(tmp1)); - LEA(32, ECX, MRegSum(EDX, EDX)); - OR(32, R(ECX), Imm8(2)); - AND(32, R(EAX), R(ECX)); //if ((u32)ix > 0xFFFF8000) ==> (~ix < 0x00007FFF) CMP(32, R(ECX), Imm32(0x00007FFF)); FixupBranch positive = J_CC(CC_AE); + LEA(32, ECX, MRegSum(EDX, EDX)); + OR(32, R(ECX), Imm8(2)); + AND(32, R(EAX), R(ECX)); + //if (dar > wr) CMP(32, R(EAX), R(EDX)); FixupBranch done = J_CC(CC_BE); @@ -551,6 +557,10 @@ void DSPEmitter::decrease_addr_reg(int reg) //else SetJumpTarget(positive); + LEA(32, ECX, MRegSum(EDX, EDX)); + OR(32, R(ECX), Imm8(2)); + AND(32, R(EAX), R(ECX)); + //if ((((nar + wr + 1) ^ nar) & dar) <= wr) LEA(32, ECX, MComplex(tmp1, EDX, 1, 1)); XOR(32, R(ECX), R(tmp1)); From 9299026572a45e154ab5c99aa4181eea6e50f0d9 Mon Sep 17 00:00:00 2001 From: Pierre Date: Mon, 5 Nov 2012 00:43:44 +0100 Subject: [PATCH 10/11] DSP: fix for interpreter, jit ADDP should probably use carry, not carry2 --- Source/Core/Core/Src/DSP/DspIntArithmetic.cpp | 2 +- Source/Core/Core/Src/DSP/Jit/DSPJitArithmetic.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Source/Core/Core/Src/DSP/DspIntArithmetic.cpp b/Source/Core/Core/Src/DSP/DspIntArithmetic.cpp index f9627f2176..4dde985f5f 100644 --- a/Source/Core/Core/Src/DSP/DspIntArithmetic.cpp +++ b/Source/Core/Core/Src/DSP/DspIntArithmetic.cpp @@ -464,7 +464,7 @@ void addp(const UDSPInstruction opc) dsp_set_long_acc(dreg, res); res = dsp_get_long_acc(dreg); - Update_SR_Register64(res, isCarry2(acc, res), isOverflow(acc, prod, res)); + Update_SR_Register64(res, isCarry(acc, res), isOverflow(acc, prod, res)); } // ADDAXL $acD, $axS.l diff --git a/Source/Core/Core/Src/DSP/Jit/DSPJitArithmetic.cpp b/Source/Core/Core/Src/DSP/Jit/DSPJitArithmetic.cpp index 85511c1b9d..0fbabf6391 100644 --- a/Source/Core/Core/Src/DSP/Jit/DSPJitArithmetic.cpp +++ b/Source/Core/Core/Src/DSP/Jit/DSPJitArithmetic.cpp @@ -750,12 +750,12 @@ void DSPEmitter::addp(const UDSPInstruction opc) ADD(64, R(RAX), R(RDX)); // dsp_set_long_acc(dreg, res); // res = dsp_get_long_acc(dreg); -// Update_SR_Register64(res, isCarry2(acc, res), isOverflow(acc, prod, res)); +// Update_SR_Register64(res, isCarry(acc, res), isOverflow(acc, prod, res)); if (FlagsNeeded()) { MOV(64, R(RCX), R(RAX)); set_long_acc(dreg, RCX); - Update_SR_Register64_Carry2(EAX, tmp1); + Update_SR_Register64_Carry(EAX, tmp1); } else { From 7768b6f960d6433a05934133cb8dd6bcb8041bd0 Mon Sep 17 00:00:00 2001 From: Pierre Date: Mon, 1 Apr 2013 23:29:45 +0200 Subject: [PATCH 11/11] DSPJIT: Fix movToHostReg usage --- Source/Core/Core/Src/DSP/Jit/DSPJitRegCache.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Source/Core/Core/Src/DSP/Jit/DSPJitRegCache.cpp b/Source/Core/Core/Src/DSP/Jit/DSPJitRegCache.cpp index aa12da9d12..b035e481f7 100644 --- a/Source/Core/Core/Src/DSP/Jit/DSPJitRegCache.cpp +++ b/Source/Core/Core/Src/DSP/Jit/DSPJitRegCache.cpp @@ -387,7 +387,7 @@ void DSPJitRegCache::loadRegs(bool emit) { for(unsigned int i = 0; i <= DSP_REG_MAX_MEM_BACKED; i++) { if (regs[i].host_reg != INVALID_REG) - movToHostReg(i,regs[i].host_reg); + movToHostReg(i,regs[i].host_reg, emit); } if (emit) { @@ -503,7 +503,7 @@ void DSPJitRegCache::popRegs() { for(unsigned int i = 0; i <= DSP_REG_MAX_MEM_BACKED; i++) { if (regs[i].host_reg != INVALID_REG) - movToHostReg(i,regs[i].host_reg); + movToHostReg(i,regs[i].host_reg, true); } }