summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author Andrew Gardner <andrew-gardner@users.noreply.github.com>2013-01-15 05:35:38 +0000
committer Andrew Gardner <andrew-gardner@users.noreply.github.com>2013-01-15 05:35:38 +0000
commitf6e01f41e45ca82a9e2cb4c25db0b87155d08464 (patch)
tree0bf7c0cc62ddb7cdd6830166171eb58654db9e9b
parent7ba4947440ade0fb83c8cf8dd9886aaeafd93539 (diff)
DSP16: The PC moves on from potentially all used opcodes now. [Andrew Gardner]
Out of whatsnew.txt: I believe I've roughed in each of the opcodes the QSound program uses (every opcode the dsp16 has except three, apparently). Even without all flags being set and conditions being tested, reasonable memory regions are being accessed. Unfortunately, though, I've found what I believe to be my first bad opcode (at PC=03e6 and will have to do a bit of spelunking to see what I can make of that).
-rw-r--r--src/emu/cpu/dsp16/dsp16.c11
-rw-r--r--src/emu/cpu/dsp16/dsp16.h10
-rw-r--r--src/emu/cpu/dsp16/dsp16dis.c1
-rw-r--r--src/emu/cpu/dsp16/dsp16ops.c143
4 files changed, 133 insertions, 32 deletions
diff --git a/src/emu/cpu/dsp16/dsp16.c b/src/emu/cpu/dsp16/dsp16.c
index ce0b3907388..d8a0ecf6190 100644
--- a/src/emu/cpu/dsp16/dsp16.c
+++ b/src/emu/cpu/dsp16/dsp16.c
@@ -57,7 +57,10 @@ dsp16_device::dsp16_device(const machine_config &mconfig, const char *tag, devic
m_c2(0),
m_sioc(0),
m_srta(0),
+ m_sdx(0),
m_pioc(0),
+ m_pdx0(0),
+ m_pdx1(0),
m_ppc(0),
m_cacheStart(CACHE_INVALID),
m_cacheEnd(CACHE_INVALID),
@@ -108,7 +111,10 @@ void dsp16_device::device_start()
state_add(DSP16_C2, "C2", m_c2);
state_add(DSP16_SIOC, "SIOC", m_sioc).formatstr("%16s");
state_add(DSP16_SRTA, "SRTA", m_srta);
- state_add(DSP16_PIOC, "PIOC", m_pioc); //.formatstr("%16s");
+ state_add(DSP16_SDX, "SDX", m_sdx);
+ state_add(DSP16_PIOC, "PIOC", m_pioc);
+ state_add(DSP16_PDX0, "PDX0", m_pdx0);
+ state_add(DSP16_PDX1, "PDX1", m_pdx1);
// register our state for saving
save_item(NAME(m_i));
@@ -136,7 +142,10 @@ void dsp16_device::device_start()
save_item(NAME(m_c2));
save_item(NAME(m_sioc));
save_item(NAME(m_srta));
+ save_item(NAME(m_sdx));
save_item(NAME(m_pioc));
+ save_item(NAME(m_pdx0));
+ save_item(NAME(m_pdx1));
save_item(NAME(m_ppc));
save_item(NAME(m_cacheStart));
save_item(NAME(m_cacheEnd));
diff --git a/src/emu/cpu/dsp16/dsp16.h b/src/emu/cpu/dsp16/dsp16.h
index 09f27800eb3..b87f775a8e7 100644
--- a/src/emu/cpu/dsp16/dsp16.h
+++ b/src/emu/cpu/dsp16/dsp16.h
@@ -83,7 +83,10 @@ protected:
// Serial and parallel interfaces
UINT16 m_sioc;
UINT16 m_srta;
+ UINT16 m_sdx;
UINT16 m_pioc;
+ UINT16 m_pdx0; // pdx0 & pdx1 refer to the same physical register (page 6-1)
+ UINT16 m_pdx1; // but we keep them seperate for logic's sake.
// internal stuff
UINT16 m_ppc;
@@ -120,6 +123,8 @@ protected:
// execution
void executeF1Field(const UINT8& F1, const UINT8& D, const UINT8& S);
void executeYFieldPost(const UINT8& Y);
+ void executeZFieldPartOne(const UINT8& Z, UINT16* rN);
+ void executeZFieldPartTwo(const UINT8& Z, UINT16* rN);
// helpers
void* addressYL();
@@ -163,7 +168,10 @@ enum
DSP16_C2,
DSP16_SIOC,
DSP16_SRTA,
- DSP16_PIOC
+ DSP16_SDX,
+ DSP16_PIOC,
+ DSP16_PDX0,
+ DSP16_PDX1
};
diff --git a/src/emu/cpu/dsp16/dsp16dis.c b/src/emu/cpu/dsp16/dsp16dis.c
index f8669164430..9b58d190306 100644
--- a/src/emu/cpu/dsp16/dsp16dis.c
+++ b/src/emu/cpu/dsp16/dsp16dis.c
@@ -505,6 +505,7 @@ CPU_DISASSEMBLE( dsp16a )
const UINT8 R = (op & 0x03f0) >> 4;
astring yString = disasmYField(Y);
astring rString = disasmRField(R);
+ // TODO: page 3-31 "special function encoding"
sprintf(buffer, "%s = %s", yString.cstr(), rString.cstr());
break;
}
diff --git a/src/emu/cpu/dsp16/dsp16ops.c b/src/emu/cpu/dsp16/dsp16ops.c
index c0fd6e0261d..872a096a8bf 100644
--- a/src/emu/cpu/dsp16/dsp16ops.c
+++ b/src/emu/cpu/dsp16/dsp16ops.c
@@ -112,18 +112,18 @@ void* dsp16_device::registerFromRTable(const UINT8 &R)
case 0x10: return (void*)&m_x;
case 0x11: return (void*)&m_y;
case 0x12: return (void*)addressYL();
- case 0x13: return (void*)&m_auc;
+ case 0x13: return (void*)&m_auc; // zero extended
case 0x14: return (void*)&m_psw;
- case 0x15: return (void*)&m_c0;
- case 0x16: return (void*)&m_c1;
- case 0x17: return (void*)&m_c2;
+ case 0x15: return (void*)&m_c0; // sign extended
+ case 0x16: return (void*)&m_c1; // sign extended
+ case 0x17: return (void*)&m_c2; // sign extended
case 0x18: return (void*)&m_sioc;
case 0x19: return (void*)&m_srta;
- //case 0x1a: return (void*)&m_sdx;
+ case 0x1a: return (void*)&m_sdx;
//case 0x1b: return (void*)&m_tdms;
case 0x1c: return (void*)&m_pioc;
- //case 0x1d: return (void*)&m_pdx0;
- //case 0x1e: return (void*)&m_pdx1;
+ case 0x1d: return (void*)&m_pdx0;
+ case 0x1e: return (void*)&m_pdx1;
default: return NULL;
}
@@ -213,6 +213,32 @@ void dsp16_device::executeYFieldPost(const UINT8& Y)
}
+void dsp16_device::executeZFieldPartOne(const UINT8& Z, UINT16* rN)
+{
+ const UINT8 lower = Z & 0x03;
+ switch (lower)
+ {
+ case 0x00: /* nop */ break;
+ case 0x01: (*rN)++; break;
+ case 0x02: (*rN)--; break;
+ case 0x03: (*rN) += m_j; break;
+ }
+}
+
+
+void dsp16_device::executeZFieldPartTwo(const UINT8& Z, UINT16* rN)
+{
+ const UINT8 lower = Z & 0x03;
+ switch (lower)
+ {
+ case 0x00: (*rN)++; break;
+ case 0x01: /* nop */ break;
+ case 0x02: (*rN) += 2; break;
+ case 0x03: (*rN) += m_k; break;
+ }
+}
+
+
void dsp16_device::execute_one(const UINT16& op, UINT8& cycles, UINT8& pcAdvance)
{
cycles = 1;
@@ -262,11 +288,17 @@ void dsp16_device::execute_one(const UINT16& op, UINT8& cycles, UINT8& pcAdvance
}
case 0x16:
{
- // F1, x = Y
- //const UINT8 Y = (op & 0x000f);
- //const UINT8 S = (op & 0x0200) >> 9;
- //const UINT8 D = (op & 0x0400) >> 10;
- //const UINT8 F1 = (op & 0x01e0) >> 5;
+ // F1, x = Y : (page 3-42)
+ const UINT8 Y = (op & 0x000f);
+ const UINT8 S = (op & 0x0200) >> 9;
+ const UINT8 D = (op & 0x0400) >> 10;
+ const UINT8 F1 = (op & 0x01e0) >> 5;
+ executeF1Field(F1, D, S);
+ UINT16* sourceReg = (UINT16*)registerFromYFieldUpper(Y);
+ writeRegister(&m_x, data_read(*sourceReg));
+ executeYFieldPost(Y);
+ cycles = 1;
+ pcAdvance = 1;
break;
}
case 0x17:
@@ -293,12 +325,24 @@ void dsp16_device::execute_one(const UINT16& op, UINT8& cycles, UINT8& pcAdvance
}
case 0x1f:
{
- // F1, y = Y, x = *pt++[i]
- //const UINT8 Y = (op & 0x000f);
- //const UINT8 X = (op & 0x0010) >> 4;
- //const UINT8 S = (op & 0x0200) >> 9;
- //const UINT8 D = (op & 0x0400) >> 10;
- //const UINT8 F1 = (op & 0x01e0) >> 5;
+ // F1, y = Y, x = *pt++[i] : (page 3-46)
+ const UINT8 Y = (op & 0x000f);
+ const UINT8 X = (op & 0x0010) >> 4;
+ const UINT8 S = (op & 0x0200) >> 9;
+ const UINT8 D = (op & 0x0400) >> 10;
+ const UINT8 F1 = (op & 0x01e0) >> 5;
+ executeF1Field(F1, D, S);
+ UINT16* sourceRegR = (UINT16*)registerFromYFieldUpper(Y);
+ writeRegister(&m_y, data_read(*sourceRegR));
+ executeYFieldPost(Y);
+ writeRegister(&m_x, data_read(m_pt));
+ switch (X)
+ {
+ case 0x00: m_pt++; break;
+ case 0x01: m_pt += m_i; break;
+ }
+ cycles = 2; // TODO: 1 if cached
+ pcAdvance = 1;
break;
}
case 0x19: case 0x1b:
@@ -313,7 +357,7 @@ void dsp16_device::execute_one(const UINT16& op, UINT8& cycles, UINT8& pcAdvance
if (Y != 0x00) printf("Unknown opcode @ PC=0x%04x", m_pc);
m_y = (useA1) ? (m_a1 & 0xffffffff) : (m_a0 & 0xffffffff); // TODO: What happens to Ax when it goes 32 bit (pc=3f & pc=47)?
executeF1Field(F1, D, S);
- m_x = data_read(m_pt); // TODO: EXM Pin & internal/external ROM? Research.
+ writeRegister(&m_x, data_read(m_pt)); // TODO: EXM Pin & internal/external ROM? Research.
switch (X)
{
case 0x00: m_pt++; break;
@@ -375,12 +419,36 @@ void dsp16_device::execute_one(const UINT16& op, UINT8& cycles, UINT8& pcAdvance
// Format 2: Multiply/ALU Read/Write Group
case 0x15:
{
- // F1, Z : y[1]
- //const UINT8 Z = (op & 0x000f);
- //const UINT8 X = (op & 0x0010) >> 4;
- //const UINT8 S = (op & 0x0200) >> 9;
- //const UINT8 D = (op & 0x0400) >> 10;
- //const UINT8 F1 = (op & 0x01e0) >> 5;
+ // F1, Z : y[1] : (page 3-54)
+ const UINT8 Z = (op & 0x000f);
+ const UINT8 X = (op & 0x0010) >> 4;
+ const UINT8 S = (op & 0x0200) >> 9;
+ const UINT8 D = (op & 0x0400) >> 10;
+ const UINT8 F1 = (op & 0x01e0) >> 5;
+ executeF1Field(F1, D, S);
+ UINT16 temp = 0x0000;
+ UINT16* rN = (UINT16*)registerFromYFieldUpper(Z);
+ switch (X)
+ {
+ case 0x00:
+ temp = m_y & 0x0000ffff;
+ m_y &= 0xffff0000;
+ m_y |= data_read(*rN);
+ executeZFieldPartOne(Z, rN);
+ data_write(*rN, temp);
+ executeZFieldPartTwo(Z, rN);
+ break;
+ case 0x01:
+ temp = (m_y & 0xffff0000) >> 16;
+ m_y &= 0x0000ffff;
+ m_y |= (data_read(*rN) << 16);
+ executeZFieldPartOne(Z, rN);
+ data_write(*rN, temp);
+ executeZFieldPartTwo(Z, rN);
+ break;
+ }
+ cycles = 2;
+ pcAdvance = 1;
break;
}
case 0x1d:
@@ -497,9 +565,24 @@ void dsp16_device::execute_one(const UINT16& op, UINT8& cycles, UINT8& pcAdvance
}
case 0x08:
{
- // aT = R
- //const UINT8 R = (op & 0x03f0) >> 4;
- //const UINT8 aT = (op & 0x0400) >> 10;
+ // aT = R : (page 3-30)
+ const UINT8 R = (op & 0x03f0) >> 4;
+ const UINT8 aT = (op & 0x0400) >> 10;
+ UINT64* destinationReg = NULL;
+ switch(aT)
+ {
+ case 0: destinationReg = &m_a1; break;
+ case 1: destinationReg = &m_a0; break;
+ default: break;
+ }
+ void* sourceReg = registerFromRTable(R);
+ *destinationReg &= U64(0x00000ffff);
+ *destinationReg |= (*(UINT16*)sourceReg) << 16; // TODO: Fix for all registers
+ if (*(UINT16*)sourceReg & 0x8000)
+ *destinationReg |= U64(0xf00000000);
+ // TODO: Special function encoding
+ cycles = 2;
+ pcAdvance = 1;
break;
}
case 0x0f:
@@ -573,14 +656,14 @@ void dsp16_device::execute_one(const UINT16& op, UINT8& cycles, UINT8& pcAdvance
// Do
m_cacheStart = m_pc + 1;
m_cacheEnd = m_pc + NI + 1;
- m_cacheIterations = K-1; // -1 because we check the counter below
+ m_cacheIterations = K-1; // -1 because we check the counter @ the end
cycles = 1;
pcAdvance = 1;
}
else
{
// Redo
- m_cacheIterations = K-1; // -1 because we check the counter below
+ m_cacheIterations = K-1; // -1 because we check the counter @ the end
m_cacheRedoNextPC = m_pc + 1;
m_pc = m_cacheStart;
pcAdvance = 0;