summaryrefslogtreecommitdiff
path: root/Source/Core
diff options
context:
space:
mode:
authorhrydgard <hrydgard@gmail.com>2009-06-21 12:09:17 +0000
committerhrydgard <hrydgard@gmail.com>2009-06-21 12:09:17 +0000
commit37375c711571fc515dc6c0b227c3edf3f4eb44c4 (patch)
tree3ba1383689b3f57569a7bf9cf0256b97577769d2 /Source/Core
parent1ca874365b3bfe6d0ab6d8cbfbc1d34fa37abdeb (diff)
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
Diffstat (limited to 'Source/Core')
-rw-r--r--Source/Core/DSPCore/Src/DSPInterpreter.h2
-rw-r--r--Source/Core/DSPCore/Src/DSPTables.cpp4
-rw-r--r--Source/Core/DSPCore/Src/DspIntArithmetic.cpp40
-rw-r--r--Source/Core/DSPCore/Src/gdsp_aram.cpp35
-rw-r--r--Source/Core/DSPCore/Src/gdsp_aram.h4
-rw-r--r--Source/Core/DSPCore/Src/gdsp_interface.cpp18
6 files changed, 88 insertions, 15 deletions
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)