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