DSPLLE: Move a bunch of helper functions from DSPJitMisc.cpp to DSPJitUtil.cpp
This commit is contained in:
parent
b91930a2d4
commit
54f3828555
|
@ -23,309 +23,6 @@
|
||||||
#include "x64ABI.h"
|
#include "x64ABI.h"
|
||||||
using namespace Gen;
|
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
|
// MRR $D, $S
|
||||||
// 0001 11dd ddds ssss
|
// 0001 11dd ddds ssss
|
||||||
// Move value from register $S to register $D.
|
// Move value from register $S to register $D.
|
||||||
|
|
|
@ -24,6 +24,309 @@
|
||||||
|
|
||||||
using namespace Gen;
|
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
|
// addr math
|
||||||
//
|
//
|
||||||
// These functions detect overflow by checking if
|
// These functions detect overflow by checking if
|
||||||
|
|
Loading…
Reference in New Issue