mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-07-24 14:49:42 -06:00
LLE JIT:
* Completed the JIT versions of the DSP arithmetic instructions (28 instructions added). * Added JIT versions of maddx and msubx (thanks to LM1234). x64 only git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@6652 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@ -150,38 +150,6 @@ void DSPEmitter::Update_SR_Register64_Carry2(Gen::X64Reg val)
|
||||
|
||||
//void DSPEmitter::Update_SR_Register16(s16 _Value, bool carry, bool overflow, bool overS32)
|
||||
//{
|
||||
// g_dsp.r[DSP_REG_SR] &= ~SR_CMP_MASK;
|
||||
|
||||
// // 0x01
|
||||
// if (carry)
|
||||
// {
|
||||
// g_dsp.r[DSP_REG_SR] |= SR_CARRY;
|
||||
// }
|
||||
|
||||
// // 0x02 and 0x80
|
||||
// if (overflow)
|
||||
// {
|
||||
// g_dsp.r[DSP_REG_SR] |= SR_OVERFLOW;
|
||||
// g_dsp.r[DSP_REG_SR] |= SR_OVERFLOW_STICKY;
|
||||
// }
|
||||
|
||||
// // 0x04
|
||||
// if (_Value == 0)
|
||||
// {
|
||||
// g_dsp.r[DSP_REG_SR] |= SR_ARITH_ZERO;
|
||||
// }
|
||||
|
||||
// // 0x08
|
||||
// if (_Value < 0)
|
||||
// {
|
||||
// g_dsp.r[DSP_REG_SR] |= SR_SIGN;
|
||||
// }
|
||||
|
||||
// // 0x10
|
||||
// if (overS32)
|
||||
// {
|
||||
// g_dsp.r[DSP_REG_SR] |= SR_OVER_S32;
|
||||
// }
|
||||
|
||||
// // 0x20 - Checks if top bits of m are equal
|
||||
// if ((((u16)_Value >> 14) == 0) || (((u16)_Value >> 14) == 3))
|
||||
@ -190,6 +158,69 @@ void DSPEmitter::Update_SR_Register64_Carry2(Gen::X64Reg val)
|
||||
// }
|
||||
//}
|
||||
|
||||
// In: RAX: s64 _Value
|
||||
// In: RCX: 1 = carry, 2 = overflow
|
||||
// Clobbers RDX
|
||||
void DSPEmitter::Update_SR_Register16(Gen::X64Reg val)
|
||||
{
|
||||
#ifdef _M_X64
|
||||
AND(16, MDisp(R11, DSP_REG_SR * 2), Imm16(~SR_CMP_MASK));
|
||||
|
||||
// // 0x04
|
||||
// if (_Value == 0) g_dsp.r[DSP_REG_SR] |= SR_ARITH_ZERO;
|
||||
CMP(64, R(val), Imm8(0));
|
||||
FixupBranch notZero = J_CC(CC_NZ);
|
||||
OR(16, MDisp(R11, DSP_REG_SR * 2), Imm16(SR_ARITH_ZERO));
|
||||
SetJumpTarget(notZero);
|
||||
|
||||
// // 0x08
|
||||
// if (_Value < 0) g_dsp.r[DSP_REG_SR] |= SR_SIGN;
|
||||
CMP(64, R(val), Imm8(0));
|
||||
FixupBranch greaterThanEqual = J_CC(CC_GE);
|
||||
OR(16, MDisp(R11, DSP_REG_SR * 2), Imm16(SR_SIGN));
|
||||
SetJumpTarget(greaterThanEqual);
|
||||
|
||||
// // 0x20 - Checks if top bits of m are equal
|
||||
// if ((((u16)_Value >> 14) == 0) || (((u16)_Value >> 14) == 3))
|
||||
//AND(32, R(val), Imm32(0xc0000000));
|
||||
SHR(16, R(val), Imm8(14));
|
||||
CMP(16, R(val), Imm16(0));
|
||||
FixupBranch nZero = J_CC(CC_NE);
|
||||
OR(16, MDisp(R11, DSP_REG_SR * 2), Imm16(SR_TOP2BITS));
|
||||
FixupBranch cC = J();
|
||||
SetJumpTarget(nZero);
|
||||
CMP(16, R(val), Imm16(3));
|
||||
FixupBranch notThree = J_CC(CC_NE);
|
||||
// g_dsp.r[DSP_REG_SR] |= SR_TOP2BITS;
|
||||
OR(16, MDisp(R11, DSP_REG_SR * 2), Imm16(SR_TOP2BITS));
|
||||
SetJumpTarget(notThree);
|
||||
SetJumpTarget(cC);
|
||||
#endif
|
||||
}
|
||||
|
||||
// In: RAX: s64 _Value
|
||||
// In: RCX: 1 = carry, 2 = overflow
|
||||
// Clobbers RDX
|
||||
void DSPEmitter::Update_SR_Register16_OverS32(Gen::X64Reg val)
|
||||
{
|
||||
#ifdef _M_X64
|
||||
AND(16, MDisp(R11, DSP_REG_SR * 2), Imm16(~SR_CMP_MASK));
|
||||
|
||||
// // 0x10
|
||||
// if (_Value != (s32)_Value) g_dsp.r[DSP_REG_SR] |= SR_OVER_S32;
|
||||
MOVSX(64, 32, RSI, R(val));
|
||||
CMP(64, R(RSI), R(val));
|
||||
FixupBranch noOverS32 = J_CC(CC_E);
|
||||
OR(16, MDisp(R11, DSP_REG_SR * 2), Imm16(SR_OVER_S32));
|
||||
SetJumpTarget(noOverS32);
|
||||
|
||||
// // 0x20 - Checks if top bits of m are equal
|
||||
// if ((((u16)_Value >> 14) == 0) || (((u16)_Value >> 14) == 3))
|
||||
//AND(32, R(val), Imm32(0xc0000000));
|
||||
Update_SR_Register16(val);
|
||||
#endif
|
||||
}
|
||||
|
||||
//void DSPEmitter::Update_SR_LZ(bool value) {
|
||||
|
||||
// if (value == true)
|
||||
|
@ -407,16 +407,14 @@ void DSPEmitter::mulmvz(const UDSPInstruction opc)
|
||||
u8 rreg = (opc >> 8) & 0x1;
|
||||
|
||||
// s64 acc = dsp_get_long_prod_round_prodl();
|
||||
get_long_prod_round_prodl();
|
||||
PUSH(64, R(RAX));
|
||||
mul(opc);
|
||||
get_long_prod_round_prodl(RDX);
|
||||
// dsp_set_long_acc(rreg, acc);
|
||||
POP(64, R(RAX));
|
||||
set_long_acc(rreg);
|
||||
set_long_acc(rreg, RDX);
|
||||
mul(opc);
|
||||
// Update_SR_Register64(dsp_get_long_acc(rreg));
|
||||
if (!(DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_START_OF_INST) || (DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_UPDATE_SR))
|
||||
{
|
||||
Update_SR_Register64();
|
||||
Update_SR_Register64(RDX);
|
||||
}
|
||||
#else
|
||||
Default(opc);
|
||||
@ -673,38 +671,50 @@ void DSPEmitter::mulcmvz(const UDSPInstruction opc)
|
||||
// Multiply one part of secondary accumulator $ax0 (selected by S) by
|
||||
// one part of secondary accumulator $ax1 (selected by T) (treat them both as
|
||||
// signed) and add result to product register.
|
||||
//void DSPEmitter::maddx(const UDSPInstruction opc)
|
||||
//{
|
||||
// u8 treg = (opc >> 8) & 0x1;
|
||||
// u8 sreg = (opc >> 9) & 0x1;
|
||||
void DSPEmitter::maddx(const UDSPInstruction opc)
|
||||
{
|
||||
#ifdef _M_X64
|
||||
u8 treg = (opc >> 8) & 0x1;
|
||||
u8 sreg = (opc >> 9) & 0x1;
|
||||
|
||||
// u16 val1 = (sreg == 0) ? dsp_get_ax_l(0) : dsp_get_ax_h(0);
|
||||
// u16 val2 = (treg == 0) ? dsp_get_ax_l(1) : dsp_get_ax_h(1);
|
||||
// s64 prod = dsp_multiply_add(val1, val2);
|
||||
//
|
||||
// zeroWriteBackLog();
|
||||
|
||||
// dsp_set_long_prod(prod);
|
||||
//}
|
||||
MOV(64, R(R11), ImmPtr(&g_dsp.r));
|
||||
// u16 val1 = (sreg == 0) ? dsp_get_ax_l(0) : dsp_get_ax_h(0);
|
||||
MOVSX(64, 16, RSI, MDisp(R11, (DSP_REG_AXL0 + sreg*2) * 2));
|
||||
// u16 val2 = (treg == 0) ? dsp_get_ax_l(1) : dsp_get_ax_h(1);
|
||||
MOVSX(64, 16, RDI, MDisp(R11, (DSP_REG_AXL1 + treg*2) * 2));
|
||||
// s64 prod = dsp_multiply_add(val1, val2);
|
||||
multiply_add();
|
||||
// dsp_set_long_prod(prod);
|
||||
set_long_prod();
|
||||
#else
|
||||
Default(opc);
|
||||
#endif
|
||||
}
|
||||
|
||||
// MSUBX $(0x18+S*2), $(0x19+T*2)
|
||||
// 1110 01st xxxx xxxx
|
||||
// Multiply one part of secondary accumulator $ax0 (selected by S) by
|
||||
// one part of secondary accumulator $ax1 (selected by T) (treat them both as
|
||||
// signed) and subtract result from product register.
|
||||
//void DSPEmitter::msubx(const UDSPInstruction opc)
|
||||
//{
|
||||
// u8 treg = (opc >> 8) & 0x1;
|
||||
// u8 sreg = (opc >> 9) & 0x1;
|
||||
void DSPEmitter::msubx(const UDSPInstruction opc)
|
||||
{
|
||||
#ifdef _M_X64
|
||||
u8 treg = (opc >> 8) & 0x1;
|
||||
u8 sreg = (opc >> 9) & 0x1;
|
||||
|
||||
// u16 val1 = (sreg == 0) ? dsp_get_ax_l(0) : dsp_get_ax_h(0);
|
||||
// u16 val2 = (treg == 0) ? dsp_get_ax_l(1) : dsp_get_ax_h(1);
|
||||
// s64 prod = dsp_multiply_sub(val1, val2);
|
||||
|
||||
// zeroWriteBackLog();
|
||||
|
||||
// dsp_set_long_prod(prod);
|
||||
//}
|
||||
MOV(64, R(R11), ImmPtr(&g_dsp.r));
|
||||
// u16 val1 = (sreg == 0) ? dsp_get_ax_l(0) : dsp_get_ax_h(0);
|
||||
MOVSX(64, 16, RSI, MDisp(R11, (DSP_REG_AXL0 + sreg*2) * 2));
|
||||
// u16 val2 = (treg == 0) ? dsp_get_ax_l(1) : dsp_get_ax_h(1);
|
||||
MOVSX(64, 16, RDI, MDisp(R11, (DSP_REG_AXL1 + treg*2) * 2));
|
||||
// s64 prod = dsp_multiply_sub(val1, val2);
|
||||
multiply_sub();
|
||||
// dsp_set_long_prod(prod);
|
||||
set_long_prod();
|
||||
#else
|
||||
Default(opc);
|
||||
#endif
|
||||
}
|
||||
|
||||
// MADDC $acS.m, $axT.h
|
||||
// 1110 10st xxxx xxxx
|
||||
|
@ -186,7 +186,7 @@ void DSPEmitter::increase_addr_reg(int reg)
|
||||
// TODO: ToMask flushes flags set by TEST,
|
||||
// needs another CMP here.
|
||||
CMP(16, R(ECX), Imm16(0));
|
||||
FixupBranch neg = J_CC(CC_L);
|
||||
FixupBranch negative = J_CC(CC_L);
|
||||
|
||||
JumpTarget loop_pos = GetCodePtr();
|
||||
|
||||
@ -211,7 +211,7 @@ void DSPEmitter::increase_addr_reg(int reg)
|
||||
FixupBranch end_pos = J();
|
||||
|
||||
// else, IX0 < 0
|
||||
SetJumpTarget(neg);
|
||||
SetJumpTarget(negative);
|
||||
JumpTarget loop_neg = GetCodePtr();
|
||||
|
||||
// dsp_decrement
|
||||
@ -269,7 +269,7 @@ void DSPEmitter::decrease_addr_reg(int reg)
|
||||
// TODO: ToMask flushes flags set by TEST,
|
||||
// needs another CMP here.
|
||||
CMP(16, R(ECX), Imm16(0));
|
||||
FixupBranch neg = J_CC(CC_L);
|
||||
FixupBranch negative = J_CC(CC_L);
|
||||
|
||||
JumpTarget loop_pos = GetCodePtr();
|
||||
|
||||
@ -282,7 +282,7 @@ void DSPEmitter::decrease_addr_reg(int reg)
|
||||
FixupBranch end_pos = J();
|
||||
|
||||
// else, IX0 < 0
|
||||
SetJumpTarget(neg);
|
||||
SetJumpTarget(negative);
|
||||
JumpTarget loop_neg = GetCodePtr();
|
||||
|
||||
// dsp_increment
|
||||
@ -512,7 +512,7 @@ void DSPEmitter::get_long_prod_round_prodl(X64Reg long_prod)
|
||||
{
|
||||
#ifdef _M_X64
|
||||
//s64 prod = dsp_get_long_prod();
|
||||
get_long_prod();
|
||||
get_long_prod(long_prod);
|
||||
|
||||
//if (prod & 0x10000) prod = (prod + 0x8000) & ~0xffff;
|
||||
TEST(32, R(long_prod), Imm32(0x10000));
|
||||
@ -554,6 +554,28 @@ void DSPEmitter::set_long_prod()
|
||||
#endif
|
||||
}
|
||||
|
||||
// Returns s64 in RAX
|
||||
// Clobbers RSI
|
||||
void DSPEmitter::round_long_acc(X64Reg long_acc)
|
||||
{
|
||||
#ifdef _M_X64
|
||||
//if (prod & 0x10000) prod = (prod + 0x8000) & ~0xffff;
|
||||
TEST(32, R(long_acc), Imm32(0x10000));
|
||||
FixupBranch jump = J_CC(CC_Z);
|
||||
ADD(64, R(long_acc), Imm32(0x8000));
|
||||
MOV(64, R(ESI), Imm64(~0xffff));
|
||||
AND(64, R(long_acc), R(RSI));
|
||||
FixupBranch ret = J();
|
||||
//else prod = (prod + 0x7fff) & ~0xffff;
|
||||
SetJumpTarget(jump);
|
||||
ADD(64, R(long_acc), Imm32(0x7fff));
|
||||
MOV(64, R(RSI), Imm64(~0xffff));
|
||||
AND(64, R(long_acc), R(RSI));
|
||||
SetJumpTarget(ret);
|
||||
//return prod;
|
||||
#endif
|
||||
}
|
||||
|
||||
// Returns s64 in RAX
|
||||
void DSPEmitter::get_long_acc(int _reg, X64Reg acc)
|
||||
{
|
||||
@ -591,12 +613,22 @@ void DSPEmitter::set_long_acc(int _reg, X64Reg acc)
|
||||
}
|
||||
|
||||
// Returns s16 in AX
|
||||
void DSPEmitter::get_acc_m(int _reg)
|
||||
void DSPEmitter::get_acc_m(int _reg, X64Reg acm)
|
||||
{
|
||||
// return g_dsp.r[DSP_REG_ACM0 + _reg];
|
||||
#ifdef _M_X64
|
||||
MOV(64, R(R11), ImmPtr(&g_dsp.r));
|
||||
MOVSX(64, 16, RAX, MDisp(R11, (DSP_REG_ACM0 + _reg) * 2));
|
||||
MOVSX(64, 16, acm, MDisp(R11, (DSP_REG_ACM0 + _reg) * 2));
|
||||
#endif
|
||||
}
|
||||
|
||||
// Returns s16 in AX
|
||||
void DSPEmitter::set_acc_m(int _reg)
|
||||
{
|
||||
// return g_dsp.r[DSP_REG_ACM0 + _reg];
|
||||
#ifdef _M_X64
|
||||
MOV(64, R(R11), ImmPtr(&g_dsp.r));
|
||||
MOV(16, MDisp(R11, (DSP_REG_ACM0 + _reg) * 2), R(RAX));
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -613,22 +645,22 @@ void DSPEmitter::get_long_acx(int _reg, X64Reg acx)
|
||||
}
|
||||
|
||||
// Returns s16 in EAX
|
||||
void DSPEmitter::get_ax_l(int _reg)
|
||||
void DSPEmitter::get_ax_l(int _reg, X64Reg axl)
|
||||
{
|
||||
// return (s16)g_dsp.r[DSP_REG_AXL0 + _reg];
|
||||
#ifdef _M_X64
|
||||
MOV(64, R(R11), ImmPtr(&g_dsp.r));
|
||||
MOVSX(64, 16, RAX, MDisp(R11, (DSP_REG_AXL0 + _reg) * 2));
|
||||
MOVSX(64, 16, axl, MDisp(R11, (DSP_REG_AXL0 + _reg) * 2));
|
||||
#endif
|
||||
}
|
||||
|
||||
// Returns s16 in EAX
|
||||
void DSPEmitter::get_ax_h(int _reg)
|
||||
void DSPEmitter::get_ax_h(int _reg, X64Reg axh)
|
||||
{
|
||||
// return (s16)g_dsp.r[DSP_REG_AXH0 + _reg];
|
||||
#ifdef _M_X64
|
||||
MOV(64, R(R11), ImmPtr(&g_dsp.r));
|
||||
MOVSX(64, 16, RAX, MDisp(R11, (DSP_REG_AXH0 + _reg) * 2));
|
||||
MOVSX(64, 16, axh, MDisp(R11, (DSP_REG_AXH0 + _reg) * 2));
|
||||
#endif
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user