diff --git a/Source/Core/DSPCore/Src/DSPInterpreter.h b/Source/Core/DSPCore/Src/DSPInterpreter.h index 4e3ba86f50..81020ef6bb 100644 --- a/Source/Core/DSPCore/Src/DSPInterpreter.h +++ b/Source/Core/DSPCore/Src/DSPInterpreter.h @@ -98,6 +98,8 @@ void lsl(const UDSPInstruction& opc); void lsr(const UDSPInstruction& opc); void asl(const UDSPInstruction& opc); void asr(const UDSPInstruction& opc); +void lsrn(const UDSPInstruction& opc); +void asrn(const UDSPInstruction& opc); void dar(const UDSPInstruction& opc); void iar(const UDSPInstruction& opc); void sbclr(const UDSPInstruction& opc); diff --git a/Source/Core/DSPCore/Src/DSPTables.cpp b/Source/Core/DSPCore/Src/DSPTables.cpp index 371af34dac..39d1d109ef 100644 --- a/Source/Core/DSPCore/Src/DSPTables.cpp +++ b/Source/Core/DSPCore/Src/DSPTables.cpp @@ -159,6 +159,10 @@ const DSPOPCTemplate opcodes[] = {"ASL", 0x1480, 0xfec0, DSPInterpreter::asl, nop, 1, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_IMM, 1, 0, 0, 0x003f}}, NULL, NULL}, {"ASR", 0x14c0, 0xfec0, DSPInterpreter::asr, nop, 1, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_IMM, 1, 0, 0, 0x003f}}, NULL, NULL}, + // discovered by ector! + {"LSRN", 0x02ca, 0xffff, DSPInterpreter::lsrn, nop, 1, 0, {}, NULL, NULL}, + {"ASRN", 0x02cb, 0xffff, DSPInterpreter::asrn, nop, 1, 0, {}, NULL, NULL}, + {"LRI", 0x0080, 0xffe0, DSPInterpreter::lri, nop, 2, 2, {{P_REG, 1, 0, 0, 0x001f}, {P_IMM, 2, 1, 0, 0xffff}}, NULL, NULL}, {"LR", 0x00c0, 0xffe0, DSPInterpreter::lr, nop, 2, 2, {{P_REG, 1, 0, 0, 0x001f}, {P_MEM, 2, 1, 0, 0xffff}}, NULL, NULL}, {"SR", 0x00e0, 0xffe0, DSPInterpreter::sr, nop, 2, 2, {{P_MEM, 2, 1, 0, 0xffff}, {P_REG, 1, 0, 0, 0x001f}}, NULL, NULL}, diff --git a/Source/Core/DSPCore/Src/DspIntArithmetic.cpp b/Source/Core/DSPCore/Src/DspIntArithmetic.cpp index 4fb0ef1236..3be4cbba17 100644 --- a/Source/Core/DSPCore/Src/DspIntArithmetic.cpp +++ b/Source/Core/DSPCore/Src/DspIntArithmetic.cpp @@ -652,6 +652,46 @@ void asr(const UDSPInstruction& opc) Update_SR_Register64(acc); } + +// (NEW) +// LSRN (fixed parameters) +// 0000 0010 1100 1010 +// Logically shifts right accumulator $ACC0 by signed 16-bit value $AC1.M +// (if value negative, becomes left shift). +void lsrn(const UDSPInstruction& opc) +{ + s16 shift = (s16)g_dsp.r[DSP_REG_ACM1]; + u64 acc = dsp_get_long_acc(0); + // Lop off the extraneous sign extension our 64-bit fake accum causes + acc &= 0x000000FFFFFFFFFFULL; + if (shift > 0) { + acc >>= shift; + } else if (shift < 0) { + acc <<= -shift; + } + dsp_set_long_acc(0, (s64)acc); + Update_SR_Register64(acc); +} + +// (NEW) +// ASRN (fixed parameters) +// 0000 0010 1100 1010 +// Arithmetically shifts right accumulator $ACC0 by signed 16-bit value $AC1.M +// (if value negative, becomes left shift). +void asrn(const UDSPInstruction& opc) +{ + s16 shift = (s16)g_dsp.r[DSP_REG_ACM1]; + s64 acc = dsp_get_long_acc(0); + if (shift > 0) { + acc >>= shift; + } else if (shift < 0) { + acc <<= -shift; + } + dsp_set_long_acc(0, acc); + Update_SR_Register64(acc); +} + + // CMPAR $acS axR.h // 1100 0001 xxxx xxxx // Compares accumulator $acS with accumulator axR.h. diff --git a/Source/Core/DSPCore/Src/gdsp_aram.cpp b/Source/Core/DSPCore/Src/gdsp_aram.cpp index 22fd6f7813..11aa749a04 100644 --- a/Source/Core/DSPCore/Src/gdsp_aram.cpp +++ b/Source/Core/DSPCore/Src/gdsp_aram.cpp @@ -64,19 +64,42 @@ s16 ADPCM_Step(u32& _rSamplePos) return val; } +u16 dsp_read_aram_d3() +{ + // Zelda ucode reads ARAM through 0xffd3. + + u32 Address = (gdsp_ifx_regs[DSP_ACCAH] << 16) | gdsp_ifx_regs[DSP_ACCAL]; + u8 value = 0; + switch (gdsp_ifx_regs[DSP_FORMAT]) { + case 0x5: // unsigned 8-bit reads .. I think. + value = DSPHost_ReadHostMemory(Address); + break; + default: + ERROR_LOG(DSPLLE, "dsp_write_aram_d3: Unseen Format %i", gdsp_ifx_regs[DSP_FORMAT]); + break; + } + return value; +} + void dsp_write_aram_d3(u16 value) { - // Not sure about this one but it sure looks like Zelda is writing to ARAM - // through 0xFFd3... + // Zelda ucode writes a bunch of zeros to ARAM through d3 during initialization. + // Don't know if it ever does it later, too. const u32 EndAddress = (gdsp_ifx_regs[DSP_ACEAH] << 16) | gdsp_ifx_regs[DSP_ACEAL]; u32 Address = (gdsp_ifx_regs[DSP_ACCAH] << 16) | gdsp_ifx_regs[DSP_ACCAL]; - - DSPHost_WriteHostMemory(value >> 8, Address); - DSPHost_WriteHostMemory(value & 0xFF, Address + 1); + switch (gdsp_ifx_regs[DSP_FORMAT]) { + case 0xA: // 16-bit writes + DSPHost_WriteHostMemory(value >> 8, Address); + DSPHost_WriteHostMemory(value & 0xFF, Address + 1); + break; + default: + ERROR_LOG(DSPLLE, "dsp_write_aram_d3: Unseen Format %i", gdsp_ifx_regs[DSP_FORMAT]); + break; + } } -u16 dsp_read_aram() +u16 dsp_read_accelerator() { const u32 EndAddress = (gdsp_ifx_regs[DSP_ACEAH] << 16) | gdsp_ifx_regs[DSP_ACEAL]; u32 Address = (gdsp_ifx_regs[DSP_ACCAH] << 16) | gdsp_ifx_regs[DSP_ACCAL]; diff --git a/Source/Core/DSPCore/Src/gdsp_aram.h b/Source/Core/DSPCore/Src/gdsp_aram.h index e310b9858e..b291406d9c 100644 --- a/Source/Core/DSPCore/Src/gdsp_aram.h +++ b/Source/Core/DSPCore/Src/gdsp_aram.h @@ -18,7 +18,9 @@ #ifndef _GDSP_ARAM_H #define _GDSP_ARAM_H -u16 dsp_read_aram(); +u16 dsp_read_accelerator(); + +u16 dsp_read_aram_d3(); void dsp_write_aram_d3(u16 value); #endif diff --git a/Source/Core/DSPCore/Src/gdsp_interface.cpp b/Source/Core/DSPCore/Src/gdsp_interface.cpp index 9a7fb823a0..8693b2ef36 100644 --- a/Source/Core/DSPCore/Src/gdsp_interface.cpp +++ b/Source/Core/DSPCore/Src/gdsp_interface.cpp @@ -173,26 +173,28 @@ void gdsp_ifx_write(u16 addr, u16 val) } } - u16 gdsp_ifx_read(u16 addr) { switch (addr & 0xff) { - case 0xfc: // DMBH + case 0xfc: // DMBH return gdsp_mbox_read_h(GDSP_MBOX_DSP); - case 0xfe: // CMBH + case 0xfe: // CMBH return gdsp_mbox_read_h(GDSP_MBOX_CPU); - case 0xff: // CMBL + case 0xff: // CMBL return gdsp_mbox_read_l(GDSP_MBOX_CPU); case 0xc9: return gdsp_ifx_regs[addr & 0xFF]; - case 0xdd: - // ERROR_LOG(DSPLLE, "Accelerator"); - return dsp_read_aram(); + case 0xdd: // ADPCM Accelerator reads + return dsp_read_accelerator(); + + case 0xd3: + ERROR_LOG(DSPLLE, "DSP read aram D3"); + return dsp_read_aram_d3(); default: if ((addr & 0xff) >= 0xa0) { @@ -210,7 +212,6 @@ u16 gdsp_ifx_read(u16 addr) } } - void gdsp_idma_in(u16 dsp_addr, u32 addr, u32 size) { UnWriteProtectMemory(g_dsp.iram, DSP_IRAM_BYTE_SIZE, false); @@ -235,6 +236,7 @@ void gdsp_idma_out(u16 dsp_addr, u32 addr, u32 size) } +// TODO: These should eat clock cycles. void gdsp_ddma_in(u16 dsp_addr, u32 addr, u32 size) { if ((addr & 0x7FFFFFFF) > 0x01FFFFFF)