mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-02-05 18:40:22 +00:00
Core/DSP/Jit: Implement Saturation/Limiting when reading ACM* in 40 bit mode
git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@7336 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
parent
26b6a9af61
commit
ca67d025e2
@ -116,6 +116,7 @@ public:
|
|||||||
void dsp_conditional_extend_accum(int reg);
|
void dsp_conditional_extend_accum(int reg);
|
||||||
void dsp_conditional_extend_accum_imm(int reg, u16 val);
|
void dsp_conditional_extend_accum_imm(int reg, u16 val);
|
||||||
void dsp_op_read_reg(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
|
// Commands
|
||||||
void dar(const UDSPInstruction opc);
|
void dar(const UDSPInstruction opc);
|
||||||
|
@ -68,7 +68,11 @@ void DSPEmitter::mv(const UDSPInstruction opc)
|
|||||||
{
|
{
|
||||||
u8 sreg = (opc & 0x3) + DSP_REG_ACL0;
|
u8 sreg = (opc & 0x3) + DSP_REG_ACL0;
|
||||||
u8 dreg = ((opc >> 2) & 0x3);
|
u8 dreg = ((opc >> 2) & 0x3);
|
||||||
pushExtValueFromReg(dreg + DSP_REG_AXL0, sreg);
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
// S @$arD, $acS.S
|
// S @$arD, $acS.S
|
||||||
@ -85,7 +89,10 @@ void DSPEmitter::s(const UDSPInstruction opc)
|
|||||||
X64Reg tmp1;
|
X64Reg tmp1;
|
||||||
gpr.getFreeXReg(tmp1);
|
gpr.getFreeXReg(tmp1);
|
||||||
|
|
||||||
dsp_op_read_reg(sreg, tmp1, ZERO);
|
if (sreg >= DSP_REG_ACM0)
|
||||||
|
dsp_op_read_reg_and_saturate(sreg, tmp1, ZERO);
|
||||||
|
else
|
||||||
|
dsp_op_read_reg(sreg, tmp1, ZERO);
|
||||||
// u16 val = g_dsp.r[src];
|
// u16 val = g_dsp.r[src];
|
||||||
dmem_write(tmp1);
|
dmem_write(tmp1);
|
||||||
|
|
||||||
@ -107,7 +114,10 @@ void DSPEmitter::sn(const UDSPInstruction opc)
|
|||||||
X64Reg tmp1;
|
X64Reg tmp1;
|
||||||
gpr.getFreeXReg(tmp1);
|
gpr.getFreeXReg(tmp1);
|
||||||
|
|
||||||
dsp_op_read_reg(sreg, tmp1, ZERO);
|
if (sreg >= DSP_REG_ACM0)
|
||||||
|
dsp_op_read_reg_and_saturate(sreg, tmp1, ZERO);
|
||||||
|
else
|
||||||
|
dsp_op_read_reg(sreg, tmp1, ZERO);
|
||||||
dmem_write(tmp1);
|
dmem_write(tmp1);
|
||||||
|
|
||||||
gpr.putXReg(tmp1);
|
gpr.putXReg(tmp1);
|
||||||
@ -177,7 +187,10 @@ void DSPEmitter::ls(const UDSPInstruction opc)
|
|||||||
X64Reg tmp1;
|
X64Reg tmp1;
|
||||||
gpr.getFreeXReg(tmp1);
|
gpr.getFreeXReg(tmp1);
|
||||||
|
|
||||||
get_acc_m(sreg, tmp1, false);
|
if (sreg >= DSP_REG_ACM0)
|
||||||
|
dsp_op_read_reg_and_saturate(sreg + DSP_REG_ACM0, tmp1, ZERO);
|
||||||
|
else
|
||||||
|
dsp_op_read_reg(sreg + DSP_REG_ACM0, tmp1, ZERO);
|
||||||
dmem_write(tmp1);
|
dmem_write(tmp1);
|
||||||
|
|
||||||
gpr.putXReg(tmp1);
|
gpr.putXReg(tmp1);
|
||||||
@ -204,7 +217,10 @@ void DSPEmitter::lsn(const UDSPInstruction opc)
|
|||||||
X64Reg tmp1;
|
X64Reg tmp1;
|
||||||
gpr.getFreeXReg(tmp1);
|
gpr.getFreeXReg(tmp1);
|
||||||
|
|
||||||
get_acc_m(sreg, tmp1, false);
|
if (sreg >= DSP_REG_ACM0)
|
||||||
|
dsp_op_read_reg_and_saturate(sreg + DSP_REG_ACM0, tmp1, ZERO);
|
||||||
|
else
|
||||||
|
dsp_op_read_reg(sreg + DSP_REG_ACM0, tmp1, ZERO);
|
||||||
dmem_write(tmp1);
|
dmem_write(tmp1);
|
||||||
|
|
||||||
gpr.putXReg(tmp1);
|
gpr.putXReg(tmp1);
|
||||||
@ -230,7 +246,10 @@ void DSPEmitter::lsm(const UDSPInstruction opc)
|
|||||||
X64Reg tmp1;
|
X64Reg tmp1;
|
||||||
gpr.getFreeXReg(tmp1);
|
gpr.getFreeXReg(tmp1);
|
||||||
|
|
||||||
get_acc_m(sreg, tmp1, false);
|
if (sreg >= DSP_REG_ACM0)
|
||||||
|
dsp_op_read_reg_and_saturate(sreg + DSP_REG_ACM0, tmp1, ZERO);
|
||||||
|
else
|
||||||
|
dsp_op_read_reg(sreg + DSP_REG_ACM0, tmp1, ZERO);
|
||||||
dmem_write(tmp1);
|
dmem_write(tmp1);
|
||||||
|
|
||||||
gpr.putXReg(tmp1);
|
gpr.putXReg(tmp1);
|
||||||
@ -257,7 +276,10 @@ void DSPEmitter::lsnm(const UDSPInstruction opc)
|
|||||||
X64Reg tmp1;
|
X64Reg tmp1;
|
||||||
gpr.getFreeXReg(tmp1);
|
gpr.getFreeXReg(tmp1);
|
||||||
|
|
||||||
get_acc_m(sreg, tmp1, false);
|
if (sreg >= DSP_REG_ACM0)
|
||||||
|
dsp_op_read_reg_and_saturate(sreg + DSP_REG_ACM0, tmp1, ZERO);
|
||||||
|
else
|
||||||
|
dsp_op_read_reg(sreg + DSP_REG_ACM0, tmp1, ZERO);
|
||||||
dmem_write(tmp1);
|
dmem_write(tmp1);
|
||||||
|
|
||||||
gpr.putXReg(tmp1);
|
gpr.putXReg(tmp1);
|
||||||
@ -282,7 +304,10 @@ void DSPEmitter::sl(const UDSPInstruction opc)
|
|||||||
X64Reg tmp1;
|
X64Reg tmp1;
|
||||||
gpr.getFreeXReg(tmp1);
|
gpr.getFreeXReg(tmp1);
|
||||||
|
|
||||||
get_acc_m(sreg, tmp1, false);
|
if (sreg >= DSP_REG_ACM0)
|
||||||
|
dsp_op_read_reg_and_saturate(sreg + DSP_REG_ACM0, tmp1, ZERO);
|
||||||
|
else
|
||||||
|
dsp_op_read_reg(sreg + DSP_REG_ACM0, tmp1, ZERO);
|
||||||
dmem_write(tmp1);
|
dmem_write(tmp1);
|
||||||
|
|
||||||
gpr.putXReg(tmp1);
|
gpr.putXReg(tmp1);
|
||||||
@ -308,7 +333,10 @@ void DSPEmitter::sln(const UDSPInstruction opc)
|
|||||||
X64Reg tmp1;
|
X64Reg tmp1;
|
||||||
gpr.getFreeXReg(tmp1);
|
gpr.getFreeXReg(tmp1);
|
||||||
|
|
||||||
get_acc_m(sreg, tmp1, false);
|
if (sreg >= DSP_REG_ACM0)
|
||||||
|
dsp_op_read_reg_and_saturate(sreg + DSP_REG_ACM0, tmp1, ZERO);
|
||||||
|
else
|
||||||
|
dsp_op_read_reg(sreg + DSP_REG_ACM0, tmp1, ZERO);
|
||||||
dmem_write(tmp1);
|
dmem_write(tmp1);
|
||||||
|
|
||||||
gpr.putXReg(tmp1);
|
gpr.putXReg(tmp1);
|
||||||
@ -334,7 +362,10 @@ void DSPEmitter::slm(const UDSPInstruction opc)
|
|||||||
X64Reg tmp1;
|
X64Reg tmp1;
|
||||||
gpr.getFreeXReg(tmp1);
|
gpr.getFreeXReg(tmp1);
|
||||||
|
|
||||||
get_acc_m(sreg, tmp1, false);
|
if (sreg >= DSP_REG_ACM0)
|
||||||
|
dsp_op_read_reg_and_saturate(sreg + DSP_REG_ACM0, tmp1, ZERO);
|
||||||
|
else
|
||||||
|
dsp_op_read_reg(sreg + DSP_REG_ACM0, tmp1, ZERO);
|
||||||
dmem_write(tmp1);
|
dmem_write(tmp1);
|
||||||
|
|
||||||
gpr.putXReg(tmp1);
|
gpr.putXReg(tmp1);
|
||||||
@ -360,7 +391,10 @@ void DSPEmitter::slnm(const UDSPInstruction opc)
|
|||||||
X64Reg tmp1;
|
X64Reg tmp1;
|
||||||
gpr.getFreeXReg(tmp1);
|
gpr.getFreeXReg(tmp1);
|
||||||
|
|
||||||
get_acc_m(sreg, tmp1, false);
|
if (sreg >= DSP_REG_ACM0)
|
||||||
|
dsp_op_read_reg_and_saturate(sreg + DSP_REG_ACM0, tmp1, ZERO);
|
||||||
|
else
|
||||||
|
dsp_op_read_reg(sreg + DSP_REG_ACM0, tmp1, ZERO);
|
||||||
dmem_write(tmp1);
|
dmem_write(tmp1);
|
||||||
|
|
||||||
gpr.putXReg(tmp1);
|
gpr.putXReg(tmp1);
|
||||||
|
@ -39,7 +39,10 @@ void DSPEmitter::srs(const UDSPInstruction opc)
|
|||||||
X64Reg tmp1;
|
X64Reg tmp1;
|
||||||
gpr.getFreeXReg(tmp1);
|
gpr.getFreeXReg(tmp1);
|
||||||
|
|
||||||
dsp_op_read_reg(reg, tmp1, ZERO);
|
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(DSP_REG_CR, RAX, ZERO);
|
dsp_op_read_reg(DSP_REG_CR, RAX, ZERO);
|
||||||
SHL(16, R(EAX), Imm8(8));
|
SHL(16, R(EAX), Imm8(8));
|
||||||
OR(16, R(EAX), Imm16(opc & 0xFF));
|
OR(16, R(EAX), Imm16(opc & 0xFF));
|
||||||
@ -77,7 +80,6 @@ void DSPEmitter::lrs(const UDSPInstruction opc)
|
|||||||
// 0000 0000 110d dddd
|
// 0000 0000 110d dddd
|
||||||
// mmmm mmmm mmmm mmmm
|
// mmmm mmmm mmmm mmmm
|
||||||
// Move value from data memory pointed by address M to register $D.
|
// Move value from data memory pointed by address M to register $D.
|
||||||
// FIXME: Perform additional operation depending on destination register.
|
|
||||||
void DSPEmitter::lr(const UDSPInstruction opc)
|
void DSPEmitter::lr(const UDSPInstruction opc)
|
||||||
{
|
{
|
||||||
int reg = opc & DSP_REG_MASK;
|
int reg = opc & DSP_REG_MASK;
|
||||||
@ -91,7 +93,6 @@ void DSPEmitter::lr(const UDSPInstruction opc)
|
|||||||
// 0000 0000 111s ssss
|
// 0000 0000 111s ssss
|
||||||
// mmmm mmmm mmmm mmmm
|
// mmmm mmmm mmmm mmmm
|
||||||
// Store value from register $S to a memory pointed by address M.
|
// Store value from register $S to a memory pointed by address M.
|
||||||
// FIXME: Perform additional operation depending on destination register.
|
|
||||||
void DSPEmitter::sr(const UDSPInstruction opc)
|
void DSPEmitter::sr(const UDSPInstruction opc)
|
||||||
{
|
{
|
||||||
u8 reg = opc & DSP_REG_MASK;
|
u8 reg = opc & DSP_REG_MASK;
|
||||||
@ -100,7 +101,10 @@ void DSPEmitter::sr(const UDSPInstruction opc)
|
|||||||
X64Reg tmp1;
|
X64Reg tmp1;
|
||||||
gpr.getFreeXReg(tmp1);
|
gpr.getFreeXReg(tmp1);
|
||||||
|
|
||||||
dsp_op_read_reg(reg, tmp1);
|
if (reg >= DSP_REG_ACM0)
|
||||||
|
dsp_op_read_reg_and_saturate(reg, tmp1);
|
||||||
|
else
|
||||||
|
dsp_op_read_reg(reg, tmp1);
|
||||||
dmem_write_imm(address, tmp1);
|
dmem_write_imm(address, tmp1);
|
||||||
|
|
||||||
gpr.putXReg(tmp1);
|
gpr.putXReg(tmp1);
|
||||||
@ -128,7 +132,6 @@ void DSPEmitter::si(const UDSPInstruction opc)
|
|||||||
// LRR $D, @$S
|
// LRR $D, @$S
|
||||||
// 0001 1000 0ssd dddd
|
// 0001 1000 0ssd dddd
|
||||||
// Move value from data memory pointed by addressing register $S to register $D.
|
// Move value from data memory pointed by addressing register $S to register $D.
|
||||||
// FIXME: Perform additional operation depending on destination register.
|
|
||||||
void DSPEmitter::lrr(const UDSPInstruction opc)
|
void DSPEmitter::lrr(const UDSPInstruction opc)
|
||||||
{
|
{
|
||||||
u8 sreg = (opc >> 5) & 0x3;
|
u8 sreg = (opc >> 5) & 0x3;
|
||||||
@ -150,7 +153,6 @@ void DSPEmitter::lrr(const UDSPInstruction opc)
|
|||||||
// 0001 1000 1ssd dddd
|
// 0001 1000 1ssd dddd
|
||||||
// Move value from data memory pointed by addressing register $S toregister $D.
|
// Move value from data memory pointed by addressing register $S toregister $D.
|
||||||
// Decrement register $S.
|
// Decrement register $S.
|
||||||
// FIXME: Perform additional operation depending on destination register.
|
|
||||||
void DSPEmitter::lrrd(const UDSPInstruction opc)
|
void DSPEmitter::lrrd(const UDSPInstruction opc)
|
||||||
{
|
{
|
||||||
u8 sreg = (opc >> 5) & 0x3;
|
u8 sreg = (opc >> 5) & 0x3;
|
||||||
@ -173,7 +175,6 @@ void DSPEmitter::lrrd(const UDSPInstruction opc)
|
|||||||
// 0001 1001 0ssd dddd
|
// 0001 1001 0ssd dddd
|
||||||
// Move value from data memory pointed by addressing register $S to register $D.
|
// Move value from data memory pointed by addressing register $S to register $D.
|
||||||
// Increment register $S.
|
// Increment register $S.
|
||||||
// FIXME: Perform additional operation depending on destination register.
|
|
||||||
void DSPEmitter::lrri(const UDSPInstruction opc)
|
void DSPEmitter::lrri(const UDSPInstruction opc)
|
||||||
{
|
{
|
||||||
u8 sreg = (opc >> 5) & 0x3;
|
u8 sreg = (opc >> 5) & 0x3;
|
||||||
@ -196,7 +197,6 @@ void DSPEmitter::lrri(const UDSPInstruction opc)
|
|||||||
// 0001 1001 1ssd dddd
|
// 0001 1001 1ssd dddd
|
||||||
// Move value from data memory pointed by addressing register $S to register $D.
|
// Move value from data memory pointed by addressing register $S to register $D.
|
||||||
// Add indexing register $(0x4+S) to register $S.
|
// Add indexing register $(0x4+S) to register $S.
|
||||||
// FIXME: Perform additional operation depending on destination register.
|
|
||||||
void DSPEmitter::lrrn(const UDSPInstruction opc)
|
void DSPEmitter::lrrn(const UDSPInstruction opc)
|
||||||
{
|
{
|
||||||
u8 sreg = (opc >> 5) & 0x3;
|
u8 sreg = (opc >> 5) & 0x3;
|
||||||
@ -219,7 +219,6 @@ void DSPEmitter::lrrn(const UDSPInstruction opc)
|
|||||||
// 0001 1010 0dds ssss
|
// 0001 1010 0dds ssss
|
||||||
// Store value from source register $S to a memory location pointed by
|
// Store value from source register $S to a memory location pointed by
|
||||||
// addressing register $D.
|
// addressing register $D.
|
||||||
// FIXME: Perform additional operation depending on source register.
|
|
||||||
void DSPEmitter::srr(const UDSPInstruction opc)
|
void DSPEmitter::srr(const UDSPInstruction opc)
|
||||||
{
|
{
|
||||||
u8 dreg = (opc >> 5) & 0x3;
|
u8 dreg = (opc >> 5) & 0x3;
|
||||||
@ -228,7 +227,10 @@ void DSPEmitter::srr(const UDSPInstruction opc)
|
|||||||
X64Reg tmp1;
|
X64Reg tmp1;
|
||||||
gpr.getFreeXReg(tmp1);
|
gpr.getFreeXReg(tmp1);
|
||||||
|
|
||||||
dsp_op_read_reg(sreg, 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(dreg, RAX, ZERO);
|
dsp_op_read_reg(dreg, RAX, ZERO);
|
||||||
dmem_write(tmp1);
|
dmem_write(tmp1);
|
||||||
|
|
||||||
@ -239,7 +241,6 @@ void DSPEmitter::srr(const UDSPInstruction opc)
|
|||||||
// 0001 1010 1dds ssss
|
// 0001 1010 1dds ssss
|
||||||
// Store value from source register $S to a memory location pointed by
|
// Store value from source register $S to a memory location pointed by
|
||||||
// addressing register $D. Decrement register $D.
|
// addressing register $D. Decrement register $D.
|
||||||
// FIXME: Perform additional operation depending on source register.
|
|
||||||
void DSPEmitter::srrd(const UDSPInstruction opc)
|
void DSPEmitter::srrd(const UDSPInstruction opc)
|
||||||
{
|
{
|
||||||
u8 dreg = (opc >> 5) & 0x3;
|
u8 dreg = (opc >> 5) & 0x3;
|
||||||
@ -248,7 +249,10 @@ void DSPEmitter::srrd(const UDSPInstruction opc)
|
|||||||
X64Reg tmp1;
|
X64Reg tmp1;
|
||||||
gpr.getFreeXReg(tmp1);
|
gpr.getFreeXReg(tmp1);
|
||||||
|
|
||||||
dsp_op_read_reg(sreg, 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(dreg, RAX, ZERO);
|
dsp_op_read_reg(dreg, RAX, ZERO);
|
||||||
dmem_write(tmp1);
|
dmem_write(tmp1);
|
||||||
|
|
||||||
@ -261,7 +265,6 @@ void DSPEmitter::srrd(const UDSPInstruction opc)
|
|||||||
// 0001 1011 0dds ssss
|
// 0001 1011 0dds ssss
|
||||||
// Store value from source register $S to a memory location pointed by
|
// Store value from source register $S to a memory location pointed by
|
||||||
// addressing register $D. Increment register $D.
|
// addressing register $D. Increment register $D.
|
||||||
// FIXME: Perform additional operation depending on source register.
|
|
||||||
void DSPEmitter::srri(const UDSPInstruction opc)
|
void DSPEmitter::srri(const UDSPInstruction opc)
|
||||||
{
|
{
|
||||||
u8 dreg = (opc >> 5) & 0x3;
|
u8 dreg = (opc >> 5) & 0x3;
|
||||||
@ -270,7 +273,10 @@ void DSPEmitter::srri(const UDSPInstruction opc)
|
|||||||
X64Reg tmp1;
|
X64Reg tmp1;
|
||||||
gpr.getFreeXReg(tmp1);
|
gpr.getFreeXReg(tmp1);
|
||||||
|
|
||||||
dsp_op_read_reg(sreg, 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(dreg, RAX, ZERO);
|
dsp_op_read_reg(dreg, RAX, ZERO);
|
||||||
dmem_write(tmp1);
|
dmem_write(tmp1);
|
||||||
|
|
||||||
@ -283,7 +289,6 @@ void DSPEmitter::srri(const UDSPInstruction opc)
|
|||||||
// 0001 1011 1dds ssss
|
// 0001 1011 1dds ssss
|
||||||
// Store value from source register $S to a memory location pointed by
|
// Store value from source register $S to a memory location pointed by
|
||||||
// addressing register $D. Add DSP_REG_IX0 register to register $D.
|
// addressing register $D. Add DSP_REG_IX0 register to register $D.
|
||||||
// FIXME: Perform additional operation depending on source register.
|
|
||||||
void DSPEmitter::srrn(const UDSPInstruction opc)
|
void DSPEmitter::srrn(const UDSPInstruction opc)
|
||||||
{
|
{
|
||||||
u8 dreg = (opc >> 5) & 0x3;
|
u8 dreg = (opc >> 5) & 0x3;
|
||||||
@ -292,7 +297,10 @@ void DSPEmitter::srrn(const UDSPInstruction opc)
|
|||||||
X64Reg tmp1;
|
X64Reg tmp1;
|
||||||
gpr.getFreeXReg(tmp1);
|
gpr.getFreeXReg(tmp1);
|
||||||
|
|
||||||
dsp_op_read_reg(sreg, 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(dreg, RAX, ZERO);
|
dsp_op_read_reg(dreg, RAX, ZERO);
|
||||||
dmem_write(tmp1);
|
dmem_write(tmp1);
|
||||||
|
|
||||||
@ -319,7 +327,7 @@ void DSPEmitter::ilrr(const UDSPInstruction opc)
|
|||||||
gpr.putXReg(tmp1);
|
gpr.putXReg(tmp1);
|
||||||
|
|
||||||
set_acc_m(dreg, R(RAX));
|
set_acc_m(dreg, R(RAX));
|
||||||
dsp_conditional_extend_accum(dreg);
|
dsp_conditional_extend_accum(dreg + DSP_REG_ACM0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ILRRD $acD.m, @$arS
|
// ILRRD $acD.m, @$arS
|
||||||
@ -340,7 +348,7 @@ void DSPEmitter::ilrrd(const UDSPInstruction opc)
|
|||||||
gpr.putXReg(tmp1);
|
gpr.putXReg(tmp1);
|
||||||
|
|
||||||
set_acc_m(dreg, R(RAX));
|
set_acc_m(dreg, R(RAX));
|
||||||
dsp_conditional_extend_accum(dreg);
|
dsp_conditional_extend_accum(dreg + DSP_REG_ACM0);
|
||||||
decrement_addr_reg(reg);
|
decrement_addr_reg(reg);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -362,7 +370,7 @@ void DSPEmitter::ilrri(const UDSPInstruction opc)
|
|||||||
gpr.putXReg(tmp1);
|
gpr.putXReg(tmp1);
|
||||||
|
|
||||||
set_acc_m(dreg, R(RAX));
|
set_acc_m(dreg, R(RAX));
|
||||||
dsp_conditional_extend_accum(dreg);
|
dsp_conditional_extend_accum(dreg + DSP_REG_ACM0);
|
||||||
increment_addr_reg(reg);
|
increment_addr_reg(reg);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -385,7 +393,7 @@ void DSPEmitter::ilrrn(const UDSPInstruction opc)
|
|||||||
gpr.putXReg(tmp1);
|
gpr.putXReg(tmp1);
|
||||||
|
|
||||||
set_acc_m(dreg, R(RAX));
|
set_acc_m(dreg, R(RAX));
|
||||||
dsp_conditional_extend_accum(dreg);
|
dsp_conditional_extend_accum(dreg + DSP_REG_ACM0);
|
||||||
increase_addr_reg(reg, reg);
|
increase_addr_reg(reg, reg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -239,16 +239,105 @@ 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)
|
||||||
|
{
|
||||||
|
//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.
|
||||||
// FIXME: Perform additional operation depending on destination register.
|
|
||||||
void DSPEmitter::mrr(const UDSPInstruction opc)
|
void DSPEmitter::mrr(const UDSPInstruction opc)
|
||||||
{
|
{
|
||||||
u8 sreg = opc & 0x1f;
|
u8 sreg = opc & 0x1f;
|
||||||
u8 dreg = (opc >> 5) & 0x1f;
|
u8 dreg = (opc >> 5) & 0x1f;
|
||||||
|
|
||||||
dsp_op_read_reg(sreg, EDX);
|
if (sreg >= DSP_REG_ACM0)
|
||||||
|
dsp_op_read_reg_and_saturate(sreg, EDX);
|
||||||
|
else
|
||||||
|
dsp_op_read_reg(sreg, EDX);
|
||||||
dsp_op_write_reg(dreg, EDX);
|
dsp_op_write_reg(dreg, EDX);
|
||||||
dsp_conditional_extend_accum(dreg);
|
dsp_conditional_extend_accum(dreg);
|
||||||
}
|
}
|
||||||
@ -273,7 +362,6 @@ void DSPEmitter::lri(const UDSPInstruction opc)
|
|||||||
// LRIS $(0x18+D), #I
|
// LRIS $(0x18+D), #I
|
||||||
// 0000 1ddd iiii iiii
|
// 0000 1ddd iiii iiii
|
||||||
// Load immediate value I (8-bit sign extended) to accumulator register.
|
// Load immediate value I (8-bit sign extended) to accumulator register.
|
||||||
// FIXME: Perform additional operation depending on destination register.
|
|
||||||
void DSPEmitter::lris(const UDSPInstruction opc)
|
void DSPEmitter::lris(const UDSPInstruction opc)
|
||||||
{
|
{
|
||||||
u8 reg = ((opc >> 8) & 0x7) + DSP_REG_AXL0;
|
u8 reg = ((opc >> 8) & 0x7) + DSP_REG_AXL0;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user