mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-01-25 15:31:17 +01:00
Implement the newly discovered DSP opcodes that I named LSRN and ASRN. Also (attempt to) implement reading ARAM through 0xFFD3, like the zelda ucode does.
git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@3523 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
parent
1ca874365b
commit
37375c7115
@ -98,6 +98,8 @@ void lsl(const UDSPInstruction& opc);
|
|||||||
void lsr(const UDSPInstruction& opc);
|
void lsr(const UDSPInstruction& opc);
|
||||||
void asl(const UDSPInstruction& opc);
|
void asl(const UDSPInstruction& opc);
|
||||||
void asr(const UDSPInstruction& opc);
|
void asr(const UDSPInstruction& opc);
|
||||||
|
void lsrn(const UDSPInstruction& opc);
|
||||||
|
void asrn(const UDSPInstruction& opc);
|
||||||
void dar(const UDSPInstruction& opc);
|
void dar(const UDSPInstruction& opc);
|
||||||
void iar(const UDSPInstruction& opc);
|
void iar(const UDSPInstruction& opc);
|
||||||
void sbclr(const UDSPInstruction& opc);
|
void sbclr(const UDSPInstruction& opc);
|
||||||
|
@ -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},
|
{"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},
|
{"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},
|
{"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},
|
{"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},
|
{"SR", 0x00e0, 0xffe0, DSPInterpreter::sr, nop, 2, 2, {{P_MEM, 2, 1, 0, 0xffff}, {P_REG, 1, 0, 0, 0x001f}}, NULL, NULL},
|
||||||
|
@ -652,6 +652,46 @@ void asr(const UDSPInstruction& opc)
|
|||||||
Update_SR_Register64(acc);
|
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
|
// CMPAR $acS axR.h
|
||||||
// 1100 0001 xxxx xxxx
|
// 1100 0001 xxxx xxxx
|
||||||
// Compares accumulator $acS with accumulator axR.h.
|
// Compares accumulator $acS with accumulator axR.h.
|
||||||
|
@ -64,19 +64,42 @@ s16 ADPCM_Step(u32& _rSamplePos)
|
|||||||
return val;
|
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)
|
void dsp_write_aram_d3(u16 value)
|
||||||
{
|
{
|
||||||
// Not sure about this one but it sure looks like Zelda is writing to ARAM
|
// Zelda ucode writes a bunch of zeros to ARAM through d3 during initialization.
|
||||||
// through 0xFFd3...
|
// Don't know if it ever does it later, too.
|
||||||
|
|
||||||
const u32 EndAddress = (gdsp_ifx_regs[DSP_ACEAH] << 16) | gdsp_ifx_regs[DSP_ACEAL];
|
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];
|
u32 Address = (gdsp_ifx_regs[DSP_ACCAH] << 16) | gdsp_ifx_regs[DSP_ACCAL];
|
||||||
|
switch (gdsp_ifx_regs[DSP_FORMAT]) {
|
||||||
DSPHost_WriteHostMemory(value >> 8, Address);
|
case 0xA: // 16-bit writes
|
||||||
DSPHost_WriteHostMemory(value & 0xFF, Address + 1);
|
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];
|
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];
|
u32 Address = (gdsp_ifx_regs[DSP_ACCAH] << 16) | gdsp_ifx_regs[DSP_ACCAL];
|
||||||
|
@ -18,7 +18,9 @@
|
|||||||
#ifndef _GDSP_ARAM_H
|
#ifndef _GDSP_ARAM_H
|
||||||
#define _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);
|
void dsp_write_aram_d3(u16 value);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -173,26 +173,28 @@ void gdsp_ifx_write(u16 addr, u16 val)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
u16 gdsp_ifx_read(u16 addr)
|
u16 gdsp_ifx_read(u16 addr)
|
||||||
{
|
{
|
||||||
switch (addr & 0xff)
|
switch (addr & 0xff)
|
||||||
{
|
{
|
||||||
case 0xfc: // DMBH
|
case 0xfc: // DMBH
|
||||||
return gdsp_mbox_read_h(GDSP_MBOX_DSP);
|
return gdsp_mbox_read_h(GDSP_MBOX_DSP);
|
||||||
|
|
||||||
case 0xfe: // CMBH
|
case 0xfe: // CMBH
|
||||||
return gdsp_mbox_read_h(GDSP_MBOX_CPU);
|
return gdsp_mbox_read_h(GDSP_MBOX_CPU);
|
||||||
|
|
||||||
case 0xff: // CMBL
|
case 0xff: // CMBL
|
||||||
return gdsp_mbox_read_l(GDSP_MBOX_CPU);
|
return gdsp_mbox_read_l(GDSP_MBOX_CPU);
|
||||||
|
|
||||||
case 0xc9:
|
case 0xc9:
|
||||||
return gdsp_ifx_regs[addr & 0xFF];
|
return gdsp_ifx_regs[addr & 0xFF];
|
||||||
|
|
||||||
case 0xdd:
|
case 0xdd: // ADPCM Accelerator reads
|
||||||
// ERROR_LOG(DSPLLE, "Accelerator");
|
return dsp_read_accelerator();
|
||||||
return dsp_read_aram();
|
|
||||||
|
case 0xd3:
|
||||||
|
ERROR_LOG(DSPLLE, "DSP read aram D3");
|
||||||
|
return dsp_read_aram_d3();
|
||||||
|
|
||||||
default:
|
default:
|
||||||
if ((addr & 0xff) >= 0xa0) {
|
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)
|
void gdsp_idma_in(u16 dsp_addr, u32 addr, u32 size)
|
||||||
{
|
{
|
||||||
UnWriteProtectMemory(g_dsp.iram, DSP_IRAM_BYTE_SIZE, false);
|
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)
|
void gdsp_ddma_in(u16 dsp_addr, u32 addr, u32 size)
|
||||||
{
|
{
|
||||||
if ((addr & 0x7FFFFFFF) > 0x01FFFFFF)
|
if ((addr & 0x7FFFFFFF) > 0x01FFFFFF)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user