Expand Up
@@ -9,310 +9,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.
Expand All
@@ -321,10 +17,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);
}
Expand Down