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).
This commit is contained in:
Andrew Gardner 2013-01-15 05:35:38 +00:00
parent 7ba4947440
commit f6e01f41e4
4 changed files with 133 additions and 32 deletions

View File

@ -57,7 +57,10 @@ dsp16_device::dsp16_device(const machine_config &mconfig, const char *tag, devic
m_c2(0), m_c2(0),
m_sioc(0), m_sioc(0),
m_srta(0), m_srta(0),
m_sdx(0),
m_pioc(0), m_pioc(0),
m_pdx0(0),
m_pdx1(0),
m_ppc(0), m_ppc(0),
m_cacheStart(CACHE_INVALID), m_cacheStart(CACHE_INVALID),
m_cacheEnd(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_C2, "C2", m_c2);
state_add(DSP16_SIOC, "SIOC", m_sioc).formatstr("%16s"); state_add(DSP16_SIOC, "SIOC", m_sioc).formatstr("%16s");
state_add(DSP16_SRTA, "SRTA", m_srta); 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 // register our state for saving
save_item(NAME(m_i)); save_item(NAME(m_i));
@ -136,7 +142,10 @@ void dsp16_device::device_start()
save_item(NAME(m_c2)); save_item(NAME(m_c2));
save_item(NAME(m_sioc)); save_item(NAME(m_sioc));
save_item(NAME(m_srta)); save_item(NAME(m_srta));
save_item(NAME(m_sdx));
save_item(NAME(m_pioc)); save_item(NAME(m_pioc));
save_item(NAME(m_pdx0));
save_item(NAME(m_pdx1));
save_item(NAME(m_ppc)); save_item(NAME(m_ppc));
save_item(NAME(m_cacheStart)); save_item(NAME(m_cacheStart));
save_item(NAME(m_cacheEnd)); save_item(NAME(m_cacheEnd));

View File

@ -83,7 +83,10 @@ protected:
// Serial and parallel interfaces // Serial and parallel interfaces
UINT16 m_sioc; UINT16 m_sioc;
UINT16 m_srta; UINT16 m_srta;
UINT16 m_sdx;
UINT16 m_pioc; 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 // internal stuff
UINT16 m_ppc; UINT16 m_ppc;
@ -120,6 +123,8 @@ protected:
// execution // execution
void executeF1Field(const UINT8& F1, const UINT8& D, const UINT8& S); void executeF1Field(const UINT8& F1, const UINT8& D, const UINT8& S);
void executeYFieldPost(const UINT8& Y); void executeYFieldPost(const UINT8& Y);
void executeZFieldPartOne(const UINT8& Z, UINT16* rN);
void executeZFieldPartTwo(const UINT8& Z, UINT16* rN);
// helpers // helpers
void* addressYL(); void* addressYL();
@ -163,7 +168,10 @@ enum
DSP16_C2, DSP16_C2,
DSP16_SIOC, DSP16_SIOC,
DSP16_SRTA, DSP16_SRTA,
DSP16_PIOC DSP16_SDX,
DSP16_PIOC,
DSP16_PDX0,
DSP16_PDX1
}; };

View File

@ -505,6 +505,7 @@ CPU_DISASSEMBLE( dsp16a )
const UINT8 R = (op & 0x03f0) >> 4; const UINT8 R = (op & 0x03f0) >> 4;
astring yString = disasmYField(Y); astring yString = disasmYField(Y);
astring rString = disasmRField(R); astring rString = disasmRField(R);
// TODO: page 3-31 "special function encoding"
sprintf(buffer, "%s = %s", yString.cstr(), rString.cstr()); sprintf(buffer, "%s = %s", yString.cstr(), rString.cstr());
break; break;
} }

View File

@ -112,18 +112,18 @@ void* dsp16_device::registerFromRTable(const UINT8 &R)
case 0x10: return (void*)&m_x; case 0x10: return (void*)&m_x;
case 0x11: return (void*)&m_y; case 0x11: return (void*)&m_y;
case 0x12: return (void*)addressYL(); 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 0x14: return (void*)&m_psw;
case 0x15: return (void*)&m_c0; case 0x15: return (void*)&m_c0; // sign extended
case 0x16: return (void*)&m_c1; case 0x16: return (void*)&m_c1; // sign extended
case 0x17: return (void*)&m_c2; case 0x17: return (void*)&m_c2; // sign extended
case 0x18: return (void*)&m_sioc; case 0x18: return (void*)&m_sioc;
case 0x19: return (void*)&m_srta; 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 0x1b: return (void*)&m_tdms;
case 0x1c: return (void*)&m_pioc; case 0x1c: return (void*)&m_pioc;
//case 0x1d: return (void*)&m_pdx0; case 0x1d: return (void*)&m_pdx0;
//case 0x1e: return (void*)&m_pdx1; case 0x1e: return (void*)&m_pdx1;
default: return NULL; 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) void dsp16_device::execute_one(const UINT16& op, UINT8& cycles, UINT8& pcAdvance)
{ {
cycles = 1; cycles = 1;
@ -262,11 +288,17 @@ void dsp16_device::execute_one(const UINT16& op, UINT8& cycles, UINT8& pcAdvance
} }
case 0x16: case 0x16:
{ {
// F1, x = Y // F1, x = Y : (page 3-42)
//const UINT8 Y = (op & 0x000f); const UINT8 Y = (op & 0x000f);
//const UINT8 S = (op & 0x0200) >> 9; const UINT8 S = (op & 0x0200) >> 9;
//const UINT8 D = (op & 0x0400) >> 10; const UINT8 D = (op & 0x0400) >> 10;
//const UINT8 F1 = (op & 0x01e0) >> 5; 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; break;
} }
case 0x17: case 0x17:
@ -293,12 +325,24 @@ void dsp16_device::execute_one(const UINT16& op, UINT8& cycles, UINT8& pcAdvance
} }
case 0x1f: case 0x1f:
{ {
// F1, y = Y, x = *pt++[i] // F1, y = Y, x = *pt++[i] : (page 3-46)
//const UINT8 Y = (op & 0x000f); const UINT8 Y = (op & 0x000f);
//const UINT8 X = (op & 0x0010) >> 4; const UINT8 X = (op & 0x0010) >> 4;
//const UINT8 S = (op & 0x0200) >> 9; const UINT8 S = (op & 0x0200) >> 9;
//const UINT8 D = (op & 0x0400) >> 10; const UINT8 D = (op & 0x0400) >> 10;
//const UINT8 F1 = (op & 0x01e0) >> 5; 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; break;
} }
case 0x19: case 0x1b: 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); 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)? 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); 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) switch (X)
{ {
case 0x00: m_pt++; break; 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 // Format 2: Multiply/ALU Read/Write Group
case 0x15: case 0x15:
{ {
// F1, Z : y[1] // F1, Z : y[1] : (page 3-54)
//const UINT8 Z = (op & 0x000f); const UINT8 Z = (op & 0x000f);
//const UINT8 X = (op & 0x0010) >> 4; const UINT8 X = (op & 0x0010) >> 4;
//const UINT8 S = (op & 0x0200) >> 9; const UINT8 S = (op & 0x0200) >> 9;
//const UINT8 D = (op & 0x0400) >> 10; const UINT8 D = (op & 0x0400) >> 10;
//const UINT8 F1 = (op & 0x01e0) >> 5; 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; break;
} }
case 0x1d: case 0x1d:
@ -497,9 +565,24 @@ void dsp16_device::execute_one(const UINT16& op, UINT8& cycles, UINT8& pcAdvance
} }
case 0x08: case 0x08:
{ {
// aT = R // aT = R : (page 3-30)
//const UINT8 R = (op & 0x03f0) >> 4; const UINT8 R = (op & 0x03f0) >> 4;
//const UINT8 aT = (op & 0x0400) >> 10; 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; break;
} }
case 0x0f: case 0x0f:
@ -573,14 +656,14 @@ void dsp16_device::execute_one(const UINT16& op, UINT8& cycles, UINT8& pcAdvance
// Do // Do
m_cacheStart = m_pc + 1; m_cacheStart = m_pc + 1;
m_cacheEnd = m_pc + NI + 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; cycles = 1;
pcAdvance = 1; pcAdvance = 1;
} }
else else
{ {
// Redo // 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_cacheRedoNextPC = m_pc + 1;
m_pc = m_cacheStart; m_pc = m_cacheStart;
pcAdvance = 0; pcAdvance = 0;