mirror of
https://github.com/holub/mame
synced 2025-05-28 08:33:05 +03:00
DSP16 improvements. [Andrew Gardner]
- Fixed R=M disassembly - Added flag formatting - Shadow register is hooked up - Opcode & flag fixes
This commit is contained in:
parent
61ffaec76e
commit
6c9a29c27f
@ -14,7 +14,11 @@
|
||||
// TODO:
|
||||
// * Store the cache in 15 unique memory locations as it is on-chip.
|
||||
// * Modify cycle counts when running from within the cache
|
||||
//
|
||||
// * A write to PI resets the pseudoramdom sequence generator) (page 2-4)
|
||||
// * Handle virtual shift addressing using RB & RE (when RE is enabled) (page 2-6)
|
||||
// * The ALU sign-extends 32-bit operands from y or p to 36 bits and produces a 36-bit output
|
||||
// * Interrupt lines (page 2-15)
|
||||
//
|
||||
|
||||
//**************************************************************************
|
||||
// DEVICE INTERFACE
|
||||
@ -104,15 +108,15 @@ void dsp16_device::device_start()
|
||||
state_add(DSP16_P, "P", m_p);
|
||||
state_add(DSP16_A0, "A0", m_a0).mask(U64(0xfffffffff));
|
||||
state_add(DSP16_A1, "A1", m_a1).mask(U64(0xfffffffff));
|
||||
state_add(DSP16_AUC, "AUC", m_auc); //.formatstr("%6s");
|
||||
state_add(DSP16_PSW, "PSW", m_psw); //.formatstr("%16s");
|
||||
state_add(DSP16_AUC, "AUC", m_auc).formatstr("%8s");
|
||||
state_add(DSP16_PSW, "PSW", m_psw).formatstr("%16s");
|
||||
state_add(DSP16_C0, "C0", m_c0);
|
||||
state_add(DSP16_C1, "C1", m_c1);
|
||||
state_add(DSP16_C2, "C2", m_c2);
|
||||
state_add(DSP16_SIOC, "SIOC", m_sioc).formatstr("%16s");
|
||||
state_add(DSP16_SIOC, "SIOC", m_sioc).formatstr("%10s");
|
||||
state_add(DSP16_SRTA, "SRTA", m_srta);
|
||||
state_add(DSP16_SDX, "SDX", m_sdx);
|
||||
state_add(DSP16_PIOC, "PIOC", m_pioc);
|
||||
state_add(DSP16_PIOC, "PIOC", m_pioc).formatstr("%16s");
|
||||
state_add(DSP16_PDX0, "PDX0", m_pdx0);
|
||||
state_add(DSP16_PDX1, "PDX1", m_pdx1);
|
||||
|
||||
@ -170,12 +174,15 @@ void dsp16_device::device_reset()
|
||||
{
|
||||
// Page 7-5
|
||||
m_pc = 0x0000;
|
||||
m_sioc = 0x0000;
|
||||
m_pi = 0x0000;
|
||||
m_sioc = 0x0000; // (page 5-4)
|
||||
|
||||
// SRTA is unaltered by reset
|
||||
m_pioc = 0x0008;
|
||||
m_rb = 0x0000;
|
||||
m_re = 0x0000;
|
||||
// AUC is not affected by reset
|
||||
|
||||
// AUC is not affected by reset
|
||||
m_ppc = m_pc;
|
||||
|
||||
// Hacky cache emulation.
|
||||
@ -195,8 +202,8 @@ void dsp16_device::device_reset()
|
||||
const address_space_config *dsp16_device::memory_space_config(address_spacenum spacenum) const
|
||||
{
|
||||
return (spacenum == AS_PROGRAM) ? &m_program_config :
|
||||
(spacenum == AS_DATA) ? &m_data_config :
|
||||
NULL;
|
||||
(spacenum == AS_DATA) ? &m_data_config :
|
||||
NULL;
|
||||
}
|
||||
|
||||
|
||||
@ -213,10 +220,101 @@ void dsp16_device::state_string_export(const device_state_entry &entry, astring
|
||||
string.printf("(below)");
|
||||
break;
|
||||
|
||||
case DSP16_AUC:
|
||||
{
|
||||
astring alignString;
|
||||
const UINT8 align = m_auc & 0x03;
|
||||
switch (align)
|
||||
{
|
||||
case 0x00: alignString.printf("xy"); break;
|
||||
case 0x01: alignString.printf("/4"); break;
|
||||
case 0x02: alignString.printf("x4"); break;
|
||||
case 0x03: alignString.printf(",,"); break;
|
||||
}
|
||||
string.printf("%c%c%c%c%c%s",
|
||||
m_auc & 0x40 ? 'Y':'.',
|
||||
m_auc & 0x20 ? '1':'.',
|
||||
m_auc & 0x10 ? '0':'.',
|
||||
m_auc & 0x08 ? '1':'.',
|
||||
m_auc & 0x04 ? '0':'.',
|
||||
alignString.cstr());
|
||||
break;
|
||||
}
|
||||
|
||||
case DSP16_PSW:
|
||||
string.printf("%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c",
|
||||
m_psw & 0x8000 ? 'M':'.',
|
||||
m_psw & 0x4000 ? 'E':'.',
|
||||
m_psw & 0x2000 ? 'L':'.',
|
||||
m_psw & 0x1000 ? 'V':'.',
|
||||
m_psw & 0x0800 ? ',':',',
|
||||
m_psw & 0x0400 ? ',':',',
|
||||
m_psw & 0x0200 ? 'O':'.',
|
||||
m_psw & 0x0100 ? '1':'.',
|
||||
m_psw & 0x0080 ? '1':'.',
|
||||
m_psw & 0x0040 ? '1':'.',
|
||||
m_psw & 0x0020 ? '1':'.',
|
||||
m_psw & 0x0010 ? 'O':'.',
|
||||
m_psw & 0x0008 ? '1':'.',
|
||||
m_psw & 0x0004 ? '1':'.',
|
||||
m_psw & 0x0002 ? '1':'.',
|
||||
m_psw & 0x0001 ? '1':'.');
|
||||
break;
|
||||
|
||||
case DSP16_PIOC:
|
||||
{
|
||||
astring strobeString;
|
||||
const UINT8 strobe = (m_pioc & 0x6000) >> 13;
|
||||
switch (strobe)
|
||||
{
|
||||
case 0x00: strobeString.printf("1T"); break;
|
||||
case 0x01: strobeString.printf("2T"); break;
|
||||
case 0x02: strobeString.printf("3T"); break;
|
||||
case 0x03: strobeString.printf("4T"); break;
|
||||
}
|
||||
string.printf("%c%s%c%c%c%c%c%c%c%c%c%c%c%c%c",
|
||||
m_pioc & 0x8000 ? 'I':'.',
|
||||
strobeString.cstr(),
|
||||
m_pioc & 0x1000 ? 'O':'I',
|
||||
m_pioc & 0x0800 ? 'O':'I',
|
||||
m_pioc & 0x0400 ? 'S':'.',
|
||||
m_pioc & 0x0200 ? 'I':'.',
|
||||
m_pioc & 0x0100 ? 'O':'.',
|
||||
m_pioc & 0x0080 ? 'P':'.',
|
||||
m_pioc & 0x0040 ? 'P':'.',
|
||||
m_pioc & 0x0020 ? 'I':'.',
|
||||
m_pioc & 0x0010 ? 'I':'.',
|
||||
m_pioc & 0x0008 ? 'O':'.',
|
||||
m_pioc & 0x0004 ? 'P':'.',
|
||||
m_pioc & 0x0002 ? 'P':'.',
|
||||
m_pioc & 0x0001 ? 'I':'.');
|
||||
break;
|
||||
}
|
||||
|
||||
// Placeholder for a better view later (TODO)
|
||||
case DSP16_SIOC:
|
||||
string.printf("%04x", *(UINT16*)entry.dataptr());
|
||||
break;
|
||||
{
|
||||
astring clkString;
|
||||
const UINT8 clk = (m_sioc & 0x0180) >> 7;
|
||||
switch (clk)
|
||||
{
|
||||
case 0x00: clkString.printf("/4"); break;
|
||||
case 0x01: clkString.printf("12"); break;
|
||||
case 0x02: clkString.printf("16"); break;
|
||||
case 0x03: clkString.printf("20"); break;
|
||||
}
|
||||
string.printf("%c%s%c%c%c%c%c%c%c",
|
||||
m_sioc & 0x0200 ? 'I':'O',
|
||||
clkString.cstr(),
|
||||
m_sioc & 0x0040 ? 'L':'M',
|
||||
m_sioc & 0x0020 ? 'I':'O',
|
||||
m_sioc & 0x0010 ? 'I':'O',
|
||||
m_sioc & 0x0008 ? 'I':'O',
|
||||
m_sioc & 0x0004 ? 'I':'O',
|
||||
m_sioc & 0x0002 ? '2':'1',
|
||||
m_sioc & 0x0001 ? '2':'1');
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -343,6 +441,10 @@ void dsp16_device::execute_run()
|
||||
m_pc += pcAdvance;
|
||||
m_icount -= cycles;
|
||||
|
||||
// The 16 bit PI "shadow" register gets set to PC on each instruction except
|
||||
// when an interrupt service routine is active (TODO: Interrupt check) (page 2-4)
|
||||
m_pi = m_pc;
|
||||
|
||||
} while (m_icount > 0);
|
||||
}
|
||||
|
||||
|
@ -54,22 +54,24 @@ protected:
|
||||
const address_space_config m_data_config;
|
||||
|
||||
// CPU registers
|
||||
// ROM Address Arithmetic Unit (XAAU)
|
||||
// ROM Address Arithmetic Unit (XAAU) (page 2-4)
|
||||
UINT16 m_i; // 12 bits
|
||||
UINT16 m_pc;
|
||||
UINT16 m_pt;
|
||||
UINT16 m_pr;
|
||||
UINT16 m_pi;
|
||||
// RAM Address Arithmetic Unit (YAAU)
|
||||
UINT16 m_j;
|
||||
UINT16 m_k;
|
||||
|
||||
// RAM Address Arithmetic Unit (YAAU) (page 2-6)
|
||||
UINT16 m_j; // Signed
|
||||
UINT16 m_k; // Signed
|
||||
UINT16 m_rb;
|
||||
UINT16 m_re;
|
||||
UINT16 m_r0;
|
||||
UINT16 m_r1;
|
||||
UINT16 m_r2;
|
||||
UINT16 m_r3;
|
||||
// Data Arithmetic Unit (DAU)
|
||||
|
||||
// Data Arithmetic Unit (DAU) (page 2-6)
|
||||
UINT16 m_x;
|
||||
UINT32 m_y;
|
||||
UINT32 m_p;
|
||||
@ -80,19 +82,20 @@ protected:
|
||||
UINT8 m_c0;
|
||||
UINT8 m_c1;
|
||||
UINT8 m_c2;
|
||||
// Serial and parallel interfaces
|
||||
|
||||
// Serial and parallel interfaces (TODO: More here (page 2-13))
|
||||
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.
|
||||
UINT16 m_pdx1; // but we keep them seperate for logic's sake.
|
||||
|
||||
// internal stuff
|
||||
UINT16 m_ppc;
|
||||
|
||||
// This core handles the cache as more of a loop than 15 seperate memory elements.
|
||||
// It's a bit of a hack, but it's easier this way.
|
||||
// This CPU core handles the cache as more of a loop than 15 seperate memory elements.
|
||||
// It's a bit of a hack, but it's easier this way (for now).
|
||||
UINT16 m_cacheStart;
|
||||
UINT16 m_cacheEnd;
|
||||
UINT16 m_cacheRedoNextPC;
|
||||
@ -118,7 +121,7 @@ protected:
|
||||
// table decoders
|
||||
void* registerFromRImmediateField(const UINT8& R);
|
||||
void* registerFromRTable(const UINT8& R);
|
||||
void* registerFromYFieldUpper(const UINT8& Y);
|
||||
UINT16* registerFromYFieldUpper(const UINT8& Y);
|
||||
|
||||
// execution
|
||||
void executeF1Field(const UINT8& F1, const UINT8& D, const UINT8& S);
|
||||
@ -130,6 +133,12 @@ protected:
|
||||
void* addressYL();
|
||||
void writeRegister(void* reg, const UINT16& value);
|
||||
bool conditionTest(const UINT8& CON);
|
||||
|
||||
// flags
|
||||
bool lmi();
|
||||
bool leq();
|
||||
bool llv();
|
||||
bool lmv();
|
||||
};
|
||||
|
||||
|
||||
|
@ -535,10 +535,10 @@ CPU_DISASSEMBLE( dsp16a )
|
||||
case 0x02: case 0x03:
|
||||
{
|
||||
// R = M
|
||||
const UINT8 M = (op & 0x00ff);
|
||||
const UINT8 R = (op & 0x0e00) >> 9;
|
||||
const UINT16 M = (op & 0x01ff);
|
||||
const UINT8 R = (op & 0x0e00) >> 9;
|
||||
astring rString = disasmRImmediateField(R);
|
||||
sprintf(buffer, "%s = 0x%02x", rString.cstr(), M);
|
||||
sprintf(buffer, "%s = 0x%04x", rString.cstr(), M);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,23 @@
|
||||
#include "dsp16.h"
|
||||
|
||||
#define DSP_LINE(__DSP_DOCLINE__) printf("0x%04x - %d (%s)\n", m_pc, __LINE__, __DSP_DOCLINE__);
|
||||
|
||||
// TODO:
|
||||
// * AUC has a CLR field for writing to A0 & A1 + sign extension + psw + zero lower bits
|
||||
// implement as a clean function (page 2-7)
|
||||
// * Implement saturation overflow (SAT on AUC) (page 2-8)
|
||||
// * Implement p alignment (ALIGN on AUC) (page 2-9)
|
||||
// * When a register is used as a memory pointer. its value is compared with re. If its value is
|
||||
// equal to the contents of re and the postincrement is +1, then the value in rb is copied into
|
||||
// the register after the memory access is complete. See Section 4.2.3.
|
||||
// * CPU flags go to the PSW & conditionTest() works on that (Page 3-4)
|
||||
// * Some instructions are not interruptible.
|
||||
//
|
||||
|
||||
|
||||
// NOTES:
|
||||
// When y is used in an assembly-language instruction, the DSPI6/DSPI6A device will read
|
||||
// or write the high half (bits 16-31) of the y register (page 2-7)
|
||||
|
||||
// The YL register is the lower half of the 32 bit Y register
|
||||
void* dsp16_device::addressYL()
|
||||
@ -8,6 +26,28 @@ void* dsp16_device::addressYL()
|
||||
}
|
||||
|
||||
|
||||
// Flag getters
|
||||
bool dsp16_device::lmi()
|
||||
{
|
||||
return m_psw & 0x8000;
|
||||
}
|
||||
|
||||
bool dsp16_device::leq()
|
||||
{
|
||||
return m_psw & 0x4000;
|
||||
}
|
||||
|
||||
bool dsp16_device::llv()
|
||||
{
|
||||
return m_psw & 0x2000;
|
||||
}
|
||||
|
||||
bool dsp16_device::lmv()
|
||||
{
|
||||
return m_psw & 0x1000;
|
||||
}
|
||||
|
||||
|
||||
void dsp16_device::writeRegister(void* reg, const UINT16 &value)
|
||||
{
|
||||
// Make sure you're not attempting to write somewhere this function doesn't support.
|
||||
@ -22,6 +62,15 @@ void dsp16_device::writeRegister(void* reg, const UINT16 &value)
|
||||
// 8 bit registers
|
||||
*(UINT8*)reg = value & 0x00ff;
|
||||
}
|
||||
else if (reg == &m_psw)
|
||||
{
|
||||
// Writes to the a0 & a1 guard bits too
|
||||
m_a0 &= U64(0x0ffffffff);
|
||||
m_a0 |= U64(m_psw & 0x000f) << 32;
|
||||
m_a1 &= U64(0x0ffffffff);
|
||||
m_a1 |= U64(m_psw & 0x01e0) << 27;
|
||||
m_psw = value;
|
||||
}
|
||||
else if (reg == &m_i)
|
||||
{
|
||||
// 12 bit register
|
||||
@ -29,12 +78,13 @@ void dsp16_device::writeRegister(void* reg, const UINT16 &value)
|
||||
}
|
||||
else if (reg == &m_y)
|
||||
{
|
||||
// Y register [[TODO - check a flag to see if clearing yl is necessary]]
|
||||
// Y register
|
||||
// TODO - Automatic clearing of yl may be selected (according to the CLR field of the auc register) (page 2-7)
|
||||
m_y = (value << 16) | (m_y & 0x0000ffff);
|
||||
}
|
||||
else if (reg == addressYL())
|
||||
{
|
||||
// Yl register
|
||||
// Yl register (Writes to yl do not change the data in the high half of y)
|
||||
m_y = value | (m_y & 0xffff0000);
|
||||
}
|
||||
else
|
||||
@ -49,26 +99,29 @@ bool dsp16_device::conditionTest(const UINT8& CON)
|
||||
{
|
||||
switch (CON)
|
||||
{
|
||||
case 0x00: return (m_psw & 0x8000); // mi (negative result)
|
||||
case 0x01: printf("UNIMPLEMENTED condition check @ PC 0x%04x\n", m_pc); return false; // pl (positive result)
|
||||
case 0x02: printf("UNIMPLEMENTED condition check @ PC 0x%04x\n", m_pc); return false; // eq (result == 0)
|
||||
case 0x03: printf("UNIMPLEMENTED condition check @ PC 0x%04x\n", m_pc); return false; // ne (result != 0)
|
||||
case 0x04: printf("UNIMPLEMENTED condition check @ PC 0x%04x\n", m_pc); return false; // lvs (logical overflow set)
|
||||
case 0x05: printf("UNIMPLEMENTED condition check @ PC 0x%04x\n", m_pc); return false; // lvc (logical overflow clear)
|
||||
case 0x06: printf("UNIMPLEMENTED condition check @ PC 0x%04x\n", m_pc); return false; // mvs (math. overflow set)
|
||||
case 0x07: printf("UNIMPLEMENTED condition check @ PC 0x%04x\n", m_pc); return false; // mvc (math. overflow clear)
|
||||
case 0x00: return lmi(); // mi (negative result)
|
||||
case 0x01: return !lmi(); // pl (positive result)
|
||||
case 0x02: return leq(); // eq (result == 0)
|
||||
case 0x03: return !leq(); // ne (result != 0)
|
||||
case 0x04: return llv(); // lvs (logical overflow set)
|
||||
case 0x05: return !llv(); // lvc (logical overflow clear)
|
||||
case 0x06: return lmv(); // mvs (math. overflow set)
|
||||
case 0x07: return !lmv(); // mvc (math. overflow clear)
|
||||
case 0x08: printf("UNIMPLEMENTED condition check @ PC 0x%04x\n", m_pc); return false; // heads (random bit set)
|
||||
case 0x09: printf("UNIMPLEMENTED condition check @ PC 0x%04x\n", m_pc); return false; // tails (random bit clear)
|
||||
case 0x0a: printf("UNIMPLEMENTED condition check @ PC 0x%04x\n", m_pc); return false; // c0ge (counter0 >= 0)
|
||||
case 0x0b: printf("UNIMPLEMENTED condition check @ PC 0x%04x\n", m_pc); return false; // c0lt (counter0 < 0)
|
||||
case 0x0c: printf("UNIMPLEMENTED condition check @ PC 0x%04x\n", m_pc); return false; // c1ge (counter1 >= 0)
|
||||
case 0x0d: printf("UNIMPLEMENTED condition check @ PC 0x%04x\n", m_pc); return false; // c1lt (counter1 < 0)
|
||||
case 0x0e: printf("UNIMPLEMENTED condition check @ PC 0x%04x\n", m_pc); return false; // true (always)
|
||||
case 0x0f: printf("UNIMPLEMENTED condition check @ PC 0x%04x\n", m_pc); return false; // false (never)
|
||||
case 0x10: printf("UNIMPLEMENTED condition check @ PC 0x%04x\n", m_pc); return false; // gt (result > 0
|
||||
case 0x11: printf("UNIMPLEMENTED condition check @ PC 0x%04x\n", m_pc); return false; // le (result <= 0)
|
||||
case 0x0a: printf("UNIMPLEMENTED condition check @ PC 0x%04x\n", m_pc); return false; // c0ge (counter0 >= 0)*
|
||||
case 0x0b: printf("UNIMPLEMENTED condition check @ PC 0x%04x\n", m_pc); return false; // c0lt (counter0 < 0)*
|
||||
case 0x0c: printf("UNIMPLEMENTED condition check @ PC 0x%04x\n", m_pc); return false; // c1ge (counter1 >= 0)*
|
||||
case 0x0d: printf("UNIMPLEMENTED condition check @ PC 0x%04x\n", m_pc); return false; // c1lt (counter1 < 0)*
|
||||
case 0x0e: return true; // true (always)
|
||||
case 0x0f: return false; // false (never)
|
||||
case 0x10: return (!lmi() && !leq()); // gt (result > 0)
|
||||
case 0x11: return (lmi() || leq()); // le (result <= 0)
|
||||
default: logerror("Unrecognized condition at PC=0x%04x\n", m_pc); break;
|
||||
}
|
||||
|
||||
// Testing each of these conditions (*) increments the respective counter being tested (page 3-5)
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -120,7 +173,7 @@ void* dsp16_device::registerFromRTable(const UINT8 &R)
|
||||
case 0x18: return (void*)&m_sioc;
|
||||
case 0x19: return (void*)&m_srta;
|
||||
case 0x1a: return (void*)&m_sdx;
|
||||
//case 0x1b: return (void*)&m_tdms;
|
||||
case 0x1b: logerror("dsp16::registerFromRTable tdms requested 0x%04x.\n", m_pc); break;
|
||||
case 0x1c: return (void*)&m_pioc;
|
||||
case 0x1d: return (void*)&m_pdx0;
|
||||
case 0x1e: return (void*)&m_pdx1;
|
||||
@ -133,47 +186,194 @@ void* dsp16_device::registerFromRTable(const UINT8 &R)
|
||||
|
||||
void dsp16_device::executeF1Field(const UINT8& F1, const UINT8& D, const UINT8& S)
|
||||
{
|
||||
// Where is the first operation being written?
|
||||
//UINT64* destinationReg = NULL;
|
||||
//switch (D)
|
||||
//{
|
||||
// case 0x00: destinationReg = &m_a0;
|
||||
// case 0x01: destinationReg = &m_a1;
|
||||
// default: break;
|
||||
//}
|
||||
// TODO: I'm pretty sure we need to feed X into these as well - Double check
|
||||
|
||||
// Note these instructions read right-to-left, so act accordingly (page 3-6)
|
||||
// y & p are sign extended (page 3-9)
|
||||
// implementation details (page 3-9)
|
||||
|
||||
// Where is are the results going?
|
||||
UINT64* destinationReg = NULL;
|
||||
switch (D)
|
||||
{
|
||||
case 0x00: destinationReg = &m_a0; break;
|
||||
case 0x01: destinationReg = &m_a1; break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
// Which source is being used?
|
||||
//UINT64* sourceReg = NULL;
|
||||
//switch (S)
|
||||
//{
|
||||
// case 0x00: sourceReg = &m_a0;
|
||||
// case 0x01: sourceReg = &m_a1;
|
||||
// default: break;
|
||||
//}
|
||||
UINT64* sourceReg = NULL;
|
||||
switch (S)
|
||||
{
|
||||
case 0x00: sourceReg = &m_a0; break;
|
||||
case 0x01: sourceReg = &m_a1; break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
|
||||
// We must compute into an intermediate variable to compute flags on
|
||||
UINT64 result = 0;
|
||||
bool justATest = false;
|
||||
|
||||
switch (F1)
|
||||
{
|
||||
case 0x00: printf("UNIMPLEMENTED F1 operation @ PC 0x%04x\n", m_pc); break;
|
||||
case 0x01: printf("UNIMPLEMENTED F1 operation @ PC 0x%04x\n", m_pc); break;
|
||||
case 0x02: m_p = (INT32)((INT16)m_x * (INT16)((m_y & 0xffff0000) >> 16)); break;
|
||||
case 0x03: printf("UNIMPLEMENTED F1 operation @ PC 0x%04x\n", m_pc); break;
|
||||
case 0x04: printf("UNIMPLEMENTED F1 operation @ PC 0x%04x\n", m_pc); break;
|
||||
case 0x05: printf("UNIMPLEMENTED F1 operation @ PC 0x%04x\n", m_pc); break;
|
||||
case 0x06: /* nop */ break;
|
||||
case 0x07: printf("UNIMPLEMENTED F1 operation @ PC 0x%04x\n", m_pc); break;
|
||||
case 0x08: printf("UNIMPLEMENTED F1 operation @ PC 0x%04x\n", m_pc); break;
|
||||
case 0x09: printf("UNIMPLEMENTED F1 operation @ PC 0x%04x\n", m_pc); break;
|
||||
case 0x0a: printf("UNIMPLEMENTED F1 operation @ PC 0x%04x\n", m_pc); break;
|
||||
case 0x0b: printf("UNIMPLEMENTED F1 operation @ PC 0x%04x\n", m_pc); break;
|
||||
case 0x0c: printf("UNIMPLEMENTED F1 operation @ PC 0x%04x\n", m_pc); break;
|
||||
case 0x0d: printf("UNIMPLEMENTED F1 operation @ PC 0x%04x\n", m_pc); break;
|
||||
case 0x0e: printf("UNIMPLEMENTED F1 operation @ PC 0x%04x\n", m_pc); break;
|
||||
case 0x0f: printf("UNIMPLEMENTED F1 operation @ PC 0x%04x\n", m_pc); break;
|
||||
case 0x00:
|
||||
{
|
||||
// Ad = p p = x*y
|
||||
printf("UNIMPLEMENTED F1 operation @ PC 0x%04x (%d)\n", m_pc, __LINE__);
|
||||
break;
|
||||
}
|
||||
case 0x01:
|
||||
{
|
||||
// Ad = aS+p p = x*y
|
||||
printf("UNIMPLEMENTED F1 operation @ PC 0x%04x (%d)\n", m_pc, __LINE__);
|
||||
break;
|
||||
}
|
||||
case 0x02:
|
||||
{
|
||||
// p = x*y
|
||||
// TODO: What happens to the flags in this operation?
|
||||
const INT16 y = (m_y & 0xffff0000) >> 16;
|
||||
m_p = (INT32)((INT16)m_x * y);
|
||||
justATest = true;
|
||||
break;
|
||||
}
|
||||
case 0x03:
|
||||
{
|
||||
// Ad = aS-p p = x*y
|
||||
printf("UNIMPLEMENTED F1 operation @ PC 0x%04x (%d)\n", m_pc, __LINE__);
|
||||
break;
|
||||
}
|
||||
case 0x04:
|
||||
{
|
||||
// Ad = p
|
||||
printf("UNIMPLEMENTED F1 operation @ PC 0x%04x (%d)\n", m_pc, __LINE__);
|
||||
break;
|
||||
}
|
||||
case 0x05:
|
||||
{
|
||||
// Ad = aS+p
|
||||
printf("UNIMPLEMENTED F1 operation @ PC 0x%04x (%d)\n", m_pc, __LINE__);
|
||||
break;
|
||||
}
|
||||
case 0x06:
|
||||
{
|
||||
// nop
|
||||
justATest = true;
|
||||
break;
|
||||
}
|
||||
case 0x07:
|
||||
{
|
||||
// Ad = aS-p
|
||||
printf("UNIMPLEMENTED F1 operation @ PC 0x%04x (%d)\n", m_pc, __LINE__);
|
||||
break;
|
||||
}
|
||||
case 0x08:
|
||||
{
|
||||
// Ad = aS|y
|
||||
printf("UNIMPLEMENTED F1 operation @ PC 0x%04x (%d)\n", m_pc, __LINE__);
|
||||
break;
|
||||
}
|
||||
case 0x09:
|
||||
{
|
||||
// Ad = aS^y
|
||||
printf("UNIMPLEMENTED F1 operation @ PC 0x%04x (%d)\n", m_pc, __LINE__);
|
||||
break;
|
||||
}
|
||||
case 0x0a:
|
||||
{
|
||||
// aS&y
|
||||
printf("UNIMPLEMENTED F1 operation @ PC 0x%04x (%d)\n", m_pc, __LINE__);
|
||||
justATest = true;
|
||||
break;
|
||||
}
|
||||
case 0x0b:
|
||||
{
|
||||
// aS-y
|
||||
INT64 aS = *sourceReg;
|
||||
if (aS & U64(0x800000000))
|
||||
aS |= U64(0xfffffff000000000);
|
||||
|
||||
INT64 y = (m_y & 0xffff0000) >> 16;
|
||||
if (y & 0x8000)
|
||||
y |= U64(0xffffffffffff0000);
|
||||
|
||||
result = aS-y;
|
||||
justATest = true;
|
||||
break;
|
||||
}
|
||||
case 0x0c:
|
||||
{
|
||||
// Ad = y
|
||||
printf("UNIMPLEMENTED F1 operation @ PC 0x%04x (%d)\n", m_pc, __LINE__);
|
||||
break;
|
||||
}
|
||||
case 0x0d:
|
||||
{
|
||||
// Ad = aS+y
|
||||
INT64 aS = *sourceReg;
|
||||
if (aS & U64(0x800000000))
|
||||
aS |= U64(0xfffffff000000000);
|
||||
|
||||
INT64 y = (m_y & 0xffff0000) >> 16;
|
||||
if (y & 0x8000)
|
||||
y |= U64(0xffffffffffff0000);
|
||||
|
||||
result = aS+y;
|
||||
break;
|
||||
}
|
||||
case 0x0e:
|
||||
{
|
||||
// Ad = aS&y
|
||||
printf("UNIMPLEMENTED F1 operation @ PC 0x%04x (%d)\n", m_pc, __LINE__);
|
||||
break;
|
||||
}
|
||||
case 0x0f:
|
||||
{
|
||||
// Ad = aS-y
|
||||
INT64 aS = *sourceReg;
|
||||
if (aS & U64(0x800000000))
|
||||
aS |= U64(0xfffffff000000000);
|
||||
|
||||
INT64 y = (m_y & 0xffff0000) >> 16;
|
||||
if (y & 0x8000)
|
||||
y |= U64(0xffffffffffff0000);
|
||||
|
||||
result = aS-y;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// CPU Flags (page 3-4)
|
||||
// LMI (logical minus)
|
||||
if (result & U64(0x800000000))
|
||||
m_psw |= 0x8000;
|
||||
else
|
||||
m_psw &= (~0x8000);
|
||||
|
||||
// LEQ (logical equal)
|
||||
if (result == U64(0x000000000))
|
||||
m_psw |= 0x4000;
|
||||
else
|
||||
m_psw &= (~0x4000);
|
||||
|
||||
// LLV (logical overflow)
|
||||
// TODO
|
||||
|
||||
// LMV (mathematical overflow)
|
||||
if ((result | U64(0xf00000000)) != U64(0xf00000000) &&
|
||||
(result | U64(0xf00000000)) != U64(0x000000000))
|
||||
m_psw |= 0x1000;
|
||||
else
|
||||
m_psw &= (~0x1000);
|
||||
|
||||
// If it was a real operation, make sure the data goes where it should
|
||||
if (!justATest)
|
||||
*destinationReg = (UINT64)result & U64(0x0000000fffffffff);
|
||||
}
|
||||
|
||||
|
||||
void* dsp16_device::registerFromYFieldUpper(const UINT8& Y)
|
||||
UINT16* dsp16_device::registerFromYFieldUpper(const UINT8& Y)
|
||||
{
|
||||
UINT16* destinationReg = NULL;
|
||||
const UINT8 N = (Y & 0x0c) >> 2;
|
||||
@ -191,16 +391,7 @@ void* dsp16_device::registerFromYFieldUpper(const UINT8& Y)
|
||||
|
||||
void dsp16_device::executeYFieldPost(const UINT8& Y)
|
||||
{
|
||||
UINT16* opReg = NULL;
|
||||
const UINT8 N = (Y & 0x0c) >> 2;
|
||||
switch (N)
|
||||
{
|
||||
case 0x00: opReg = &m_r0; break;
|
||||
case 0x01: opReg = &m_r1; break;
|
||||
case 0x02: opReg = &m_r2; break;
|
||||
case 0x03: opReg = &m_r3; break;
|
||||
default: break;
|
||||
}
|
||||
UINT16* opReg = registerFromYFieldUpper(Y);
|
||||
|
||||
const UINT8 lower = Y & 0x03;
|
||||
switch (lower)
|
||||
@ -208,7 +399,7 @@ void dsp16_device::executeYFieldPost(const UINT8& Y)
|
||||
case 0x00: /* nop */ break;
|
||||
case 0x01: (*opReg)++; break;
|
||||
case 0x02: (*opReg)--; break;
|
||||
case 0x03: (*opReg) += m_j; break;
|
||||
case 0x03: (*opReg) += m_j; break; // TODO: J is signed
|
||||
}
|
||||
}
|
||||
|
||||
@ -221,7 +412,7 @@ void dsp16_device::executeZFieldPartOne(const UINT8& Z, UINT16* rN)
|
||||
case 0x00: /* nop */ break;
|
||||
case 0x01: (*rN)++; break;
|
||||
case 0x02: (*rN)--; break;
|
||||
case 0x03: (*rN) += m_j; break;
|
||||
case 0x03: (*rN) += m_j; break; // TODO: J is signed
|
||||
}
|
||||
}
|
||||
|
||||
@ -234,7 +425,7 @@ void dsp16_device::executeZFieldPartTwo(const UINT8& Z, UINT16* rN)
|
||||
case 0x00: (*rN)++; break;
|
||||
case 0x01: /* nop */ break;
|
||||
case 0x02: (*rN) += 2; break;
|
||||
case 0x03: (*rN) += m_k; break;
|
||||
case 0x03: (*rN) += m_k; break; // TODO: K is signed
|
||||
}
|
||||
}
|
||||
|
||||
@ -244,12 +435,15 @@ void dsp16_device::execute_one(const UINT16& op, UINT8& cycles, UINT8& pcAdvance
|
||||
cycles = 1;
|
||||
pcAdvance = 0;
|
||||
|
||||
// NOTE: pages 3-5 through 3-19 are good english descriptions of what's up
|
||||
|
||||
const UINT8 opcode = (op >> 11) & 0x1f;
|
||||
switch(opcode)
|
||||
{
|
||||
// Format 1: Multiply/ALU Read/Write Group
|
||||
case 0x06:
|
||||
{
|
||||
DSP_LINE("3-38")
|
||||
// F1, Y : (page 3-38)
|
||||
const UINT8 Y = (op & 0x000f);
|
||||
const UINT8 S = (op & 0x0200) >> 9;
|
||||
@ -263,21 +457,23 @@ void dsp16_device::execute_one(const UINT16& op, UINT8& cycles, UINT8& pcAdvance
|
||||
}
|
||||
case 0x04: case 0x1c:
|
||||
{
|
||||
DSP_LINE("3-40")
|
||||
// F1 Y=a0[1] | F1 Y=a1[1] : (page 3-40)
|
||||
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 D = (op & 0x0400) >> 10;
|
||||
const UINT8 F1 = (op & 0x01e0) >> 5;
|
||||
UINT16* destinationReg = (UINT16*)registerFromYFieldUpper(Y);
|
||||
UINT16* destinationReg = registerFromYFieldUpper(Y);
|
||||
// (page 3-18)
|
||||
UINT16 aRegValue = 0x0000;
|
||||
if (op & 0xc000)
|
||||
{
|
||||
aRegValue = (X) ? (m_a0 & 0x0ffff0000) >> 16 : m_a0 & 0x00000ffff;
|
||||
aRegValue = (m_a0 & U64(0x0ffff0000)) >> 16;
|
||||
}
|
||||
else
|
||||
{
|
||||
aRegValue = (X) ? (m_a1 & 0x0ffff0000) >> 16 : m_a1 & 0x00000ffff;
|
||||
aRegValue = (m_a1 & U64(0x0ffff0000)) >> 16;
|
||||
}
|
||||
data_write(*destinationReg, aRegValue);
|
||||
executeYFieldPost(Y);
|
||||
@ -288,13 +484,14 @@ void dsp16_device::execute_one(const UINT16& op, UINT8& cycles, UINT8& pcAdvance
|
||||
}
|
||||
case 0x16:
|
||||
{
|
||||
DSP_LINE("3-42")
|
||||
// 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);
|
||||
UINT16* sourceReg = registerFromYFieldUpper(Y);
|
||||
writeRegister(&m_x, data_read(*sourceReg));
|
||||
executeYFieldPost(Y);
|
||||
cycles = 1;
|
||||
@ -303,6 +500,7 @@ void dsp16_device::execute_one(const UINT16& op, UINT8& cycles, UINT8& pcAdvance
|
||||
}
|
||||
case 0x17:
|
||||
{
|
||||
DSP_LINE("3-44")
|
||||
// F1, y[l] = Y : (page 3-44)
|
||||
const UINT8 Y = (op & 0x000f);
|
||||
const UINT8 X = (op & 0x0010) >> 4;
|
||||
@ -310,7 +508,7 @@ void dsp16_device::execute_one(const UINT16& op, UINT8& cycles, UINT8& pcAdvance
|
||||
const UINT8 D = (op & 0x0400) >> 10;
|
||||
const UINT8 F1 = (op & 0x01e0) >> 5;
|
||||
executeF1Field(F1, D, S);
|
||||
UINT16* sourceReg = (UINT16*)registerFromYFieldUpper(Y);
|
||||
UINT16* sourceReg = registerFromYFieldUpper(Y);
|
||||
UINT16 sourceValue = data_read(*sourceReg);
|
||||
switch (X)
|
||||
{
|
||||
@ -325,6 +523,7 @@ void dsp16_device::execute_one(const UINT16& op, UINT8& cycles, UINT8& pcAdvance
|
||||
}
|
||||
case 0x1f:
|
||||
{
|
||||
DSP_LINE("3-46")
|
||||
// F1, y = Y, x = *pt++[i] : (page 3-46)
|
||||
const UINT8 Y = (op & 0x000f);
|
||||
const UINT8 X = (op & 0x0010) >> 4;
|
||||
@ -332,7 +531,7 @@ void dsp16_device::execute_one(const UINT16& op, UINT8& cycles, UINT8& pcAdvance
|
||||
const UINT8 D = (op & 0x0400) >> 10;
|
||||
const UINT8 F1 = (op & 0x01e0) >> 5;
|
||||
executeF1Field(F1, D, S);
|
||||
UINT16* sourceRegR = (UINT16*)registerFromYFieldUpper(Y);
|
||||
UINT16* sourceRegR = registerFromYFieldUpper(Y);
|
||||
writeRegister(&m_y, data_read(*sourceRegR));
|
||||
executeYFieldPost(Y);
|
||||
writeRegister(&m_x, data_read(m_pt));
|
||||
@ -347,6 +546,7 @@ void dsp16_device::execute_one(const UINT16& op, UINT8& cycles, UINT8& pcAdvance
|
||||
}
|
||||
case 0x19: case 0x1b:
|
||||
{
|
||||
DSP_LINE("3-48")
|
||||
// F1, y = a0|1, x = *pt++[i] : (page 3-48)
|
||||
const UINT8 Y = (op & 0x000f);
|
||||
const UINT8 X = (op & 0x0010) >> 4;
|
||||
@ -369,14 +569,15 @@ void dsp16_device::execute_one(const UINT16& op, UINT8& cycles, UINT8& pcAdvance
|
||||
}
|
||||
case 0x14:
|
||||
{
|
||||
// F1, Y = y[1] : (page 3-53)
|
||||
DSP_LINE("3-53")
|
||||
// F1, Y = y[l] : (page 3-53)
|
||||
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* destinationReg = (UINT16*)registerFromYFieldUpper(Y);
|
||||
UINT16* destinationReg = registerFromYFieldUpper(Y);
|
||||
UINT16 yRegValue = 0x0000;
|
||||
switch (X)
|
||||
{
|
||||
@ -394,7 +595,9 @@ void dsp16_device::execute_one(const UINT16& op, UINT8& cycles, UINT8& pcAdvance
|
||||
// Format 1a: Multiply/ALU Read/Write Group (TODO: Figure out major typo in docs on p3-51)
|
||||
case 0x07:
|
||||
{
|
||||
DSP_LINE("3-50")
|
||||
// F1, At[1] = Y : (page 3-50)
|
||||
// TODO: What does the X field do here, exactly?
|
||||
const UINT8 Y = (op & 0x000f);
|
||||
const UINT8 S = (op & 0x0200) >> 9;
|
||||
const UINT8 aT = (op & 0x0400) >> 10;
|
||||
@ -407,7 +610,7 @@ void dsp16_device::execute_one(const UINT16& op, UINT8& cycles, UINT8& pcAdvance
|
||||
case 1: destinationReg = &m_a0; break;
|
||||
default: break;
|
||||
}
|
||||
UINT16 sourceAddress = *((UINT16*)registerFromYFieldUpper(Y));
|
||||
UINT16 sourceAddress = *(registerFromYFieldUpper(Y));
|
||||
INT64 sourceValueSigned = (INT16)data_read(sourceAddress);
|
||||
*destinationReg = sourceValueSigned & U64(0xffffffffff);
|
||||
executeYFieldPost(Y);
|
||||
@ -419,7 +622,8 @@ 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] : (page 3-54)
|
||||
DSP_LINE("3-54")
|
||||
// F1, Z : y[l] : (page 3-54)
|
||||
const UINT8 Z = (op & 0x000f);
|
||||
const UINT8 X = (op & 0x0010) >> 4;
|
||||
const UINT8 S = (op & 0x0200) >> 9;
|
||||
@ -427,7 +631,7 @@ void dsp16_device::execute_one(const UINT16& op, UINT8& cycles, UINT8& pcAdvance
|
||||
const UINT8 F1 = (op & 0x01e0) >> 5;
|
||||
executeF1Field(F1, D, S);
|
||||
UINT16 temp = 0x0000;
|
||||
UINT16* rN = (UINT16*)registerFromYFieldUpper(Z);
|
||||
UINT16* rN = registerFromYFieldUpper(Z);
|
||||
switch (X)
|
||||
{
|
||||
case 0x00:
|
||||
@ -453,6 +657,7 @@ void dsp16_device::execute_one(const UINT16& op, UINT8& cycles, UINT8& pcAdvance
|
||||
}
|
||||
case 0x1d:
|
||||
{
|
||||
DSP_LINE("?")
|
||||
// F1, Z : y, x=*pt++[i]
|
||||
//const UINT8 Z = (op & 0x000f);
|
||||
//const UINT8 X = (op & 0x0010) >> 4;
|
||||
@ -465,6 +670,7 @@ void dsp16_device::execute_one(const UINT16& op, UINT8& cycles, UINT8& pcAdvance
|
||||
// Format 2a: Multiply/ALU Read/Write Group
|
||||
case 0x05:
|
||||
{
|
||||
DSP_LINE("?")
|
||||
// F1, Z : aT[1]
|
||||
//const UINT8 Z = (op & 0x000f);
|
||||
//const UINT8 X = (op & 0x0010) >> 4;
|
||||
@ -478,7 +684,8 @@ void dsp16_device::execute_one(const UINT16& op, UINT8& cycles, UINT8& pcAdvance
|
||||
case 0x12:
|
||||
case 0x13:
|
||||
{
|
||||
// if|ifc CON F2
|
||||
DSP_LINE("3-36")
|
||||
// if|ifc CON F2 (page 3-36)
|
||||
const UINT8 CON = (op & 0x001f);
|
||||
//const UINT8 S = (op & 0x0200) >> 9;
|
||||
//const UINT8 D = (op & 0x0400) >> 10;
|
||||
@ -486,7 +693,7 @@ void dsp16_device::execute_one(const UINT16& op, UINT8& cycles, UINT8& pcAdvance
|
||||
bool conditionFulfilled = conditionTest(CON);
|
||||
if (conditionFulfilled)
|
||||
{
|
||||
printf("Fulfilled condition not yet implemented @ PC=0x%04x", m_pc);
|
||||
printf("Fulfilled condition not yet implemented @ PC=0x%04x\n", m_pc);
|
||||
}
|
||||
cycles = 1;
|
||||
pcAdvance = 1;
|
||||
@ -496,7 +703,8 @@ void dsp16_device::execute_one(const UINT16& op, UINT8& cycles, UINT8& pcAdvance
|
||||
// Format 4: Branch Direct Group
|
||||
case 0x00: case 0x01:
|
||||
{
|
||||
// goto JA : (page 3-20)
|
||||
DSP_LINE("3-20")
|
||||
// goto JA : (page 3-20) (DONE)
|
||||
const UINT16 JA = (op & 0x0fff) | (m_pc & 0xf000);
|
||||
m_pc = JA;
|
||||
cycles = 2;
|
||||
@ -506,6 +714,7 @@ void dsp16_device::execute_one(const UINT16& op, UINT8& cycles, UINT8& pcAdvance
|
||||
|
||||
case 0x10: case 0x11:
|
||||
{
|
||||
DSP_LINE("3-23")
|
||||
// call JA : (page 3-23)
|
||||
const UINT16 JA = (op & 0x0fff) | (m_pc & 0xf000);
|
||||
m_pr = m_pc + 1;
|
||||
@ -518,6 +727,7 @@ void dsp16_device::execute_one(const UINT16& op, UINT8& cycles, UINT8& pcAdvance
|
||||
// Format 5: Branch Indirect Group
|
||||
case 0x18:
|
||||
{
|
||||
DSP_LINE("3-21")
|
||||
// goto B : (page 3-21)
|
||||
const UINT8 B = (op & 0x0700) >> 8;
|
||||
switch (B)
|
||||
@ -536,6 +746,7 @@ void dsp16_device::execute_one(const UINT16& op, UINT8& cycles, UINT8& pcAdvance
|
||||
// Format 6: Contitional Branch Qualifier/Software Interrupt (icall)
|
||||
case 0x1a:
|
||||
{
|
||||
DSP_LINE("3-22")
|
||||
// if CON [goto/call/return] : (page 3-22)
|
||||
const UINT8 CON = (op & 0x001f);
|
||||
bool conditionFulfilled = conditionTest(CON);
|
||||
@ -551,8 +762,9 @@ void dsp16_device::execute_one(const UINT16& op, UINT8& cycles, UINT8& pcAdvance
|
||||
// Format 7: Data Move Group
|
||||
case 0x09: case 0x0b:
|
||||
{
|
||||
// TODO: Fix register pdxX (pc=338)
|
||||
DSP_LINE("3-29")
|
||||
// R = aS : (page 3-29)
|
||||
// TODO: Fix register pdxX (pc=338)
|
||||
const UINT8 R = (op & 0x03f0) >> 4;
|
||||
const UINT8 S = (op & 0x1000) >> 12;
|
||||
void* destinationReg = registerFromRTable(R);
|
||||
@ -565,6 +777,7 @@ void dsp16_device::execute_one(const UINT16& op, UINT8& cycles, UINT8& pcAdvance
|
||||
}
|
||||
case 0x08:
|
||||
{
|
||||
DSP_LINE("3-30")
|
||||
// aT = R : (page 3-30)
|
||||
const UINT8 R = (op & 0x03f0) >> 4;
|
||||
const UINT8 aT = (op & 0x0400) >> 10;
|
||||
@ -587,10 +800,11 @@ void dsp16_device::execute_one(const UINT16& op, UINT8& cycles, UINT8& pcAdvance
|
||||
}
|
||||
case 0x0f:
|
||||
{
|
||||
DSP_LINE("3-32")
|
||||
// R = Y : (page 3-32)
|
||||
const UINT8 Y = (op & 0x000f);
|
||||
const UINT8 R = (op & 0x03f0) >> 4;
|
||||
UINT16* sourceReg = (UINT16*)registerFromYFieldUpper(Y);
|
||||
UINT16* sourceReg = registerFromYFieldUpper(Y);
|
||||
void* destinationReg = registerFromRTable(R);
|
||||
writeRegister(destinationReg, data_read(*sourceReg));
|
||||
executeYFieldPost(Y);
|
||||
@ -600,12 +814,14 @@ void dsp16_device::execute_one(const UINT16& op, UINT8& cycles, UINT8& pcAdvance
|
||||
}
|
||||
case 0x0c:
|
||||
{
|
||||
DSP_LINE("3-33")
|
||||
// Y = R : (page 3-33)
|
||||
// TODO: Zero & Sign extend i, c0, c1, c2, and auc
|
||||
const UINT8 Y = (op & 0x000f);
|
||||
const UINT8 R = (op & 0x03f0) >> 4;
|
||||
UINT16* destinationReg = (UINT16*)registerFromYFieldUpper(Y);
|
||||
UINT16* sourceReg = (UINT16*)registerFromRTable(R);
|
||||
data_write(*destinationReg, *sourceReg);
|
||||
UINT16* destinationReg = registerFromYFieldUpper(Y);
|
||||
UINT16* sourceReg = (UINT16*)registerFromRTable(R); // TODO: This won't work for certain registers!
|
||||
data_write(*destinationReg, *sourceReg); // Fix in data_write() maybe?
|
||||
executeYFieldPost(Y);
|
||||
cycles = 2;
|
||||
pcAdvance = 1;
|
||||
@ -613,6 +829,7 @@ void dsp16_device::execute_one(const UINT16& op, UINT8& cycles, UINT8& pcAdvance
|
||||
}
|
||||
case 0x0d:
|
||||
{
|
||||
DSP_LINE("?")
|
||||
// Z : R
|
||||
//const UINT8 Z = (op & 0x000f);
|
||||
//const UINT8 R = (op & 0x03f0) >> 4;
|
||||
@ -622,11 +839,14 @@ void dsp16_device::execute_one(const UINT16& op, UINT8& cycles, UINT8& pcAdvance
|
||||
// Format 8: Data Move (immediate operand - 2 words)
|
||||
case 0x0a:
|
||||
{
|
||||
// R = N : (page 3-28)
|
||||
DSP_LINE("3-28")
|
||||
// R = N : (page 3-28) (DONE)
|
||||
// NOTE: The docs speak of register sources & sign extension, but this is a register
|
||||
// destination, so, typo? If so, what does one do with the overflow bits?
|
||||
const UINT8 R = (op & 0x03f0) >> 4;
|
||||
const UINT16 iVal = opcode_read(1);
|
||||
void* reg = registerFromRTable(R);
|
||||
writeRegister(reg, iVal);
|
||||
void* destinationReg = registerFromRTable(R);
|
||||
writeRegister(destinationReg, iVal);
|
||||
cycles = 2;
|
||||
pcAdvance = 2;
|
||||
break;
|
||||
@ -635,11 +855,19 @@ void dsp16_device::execute_one(const UINT16& op, UINT8& cycles, UINT8& pcAdvance
|
||||
// Format 9: Short Immediate Group
|
||||
case 0x02: case 0x03:
|
||||
{
|
||||
DSP_LINE("3-27")
|
||||
// R = M : (page 3-27)
|
||||
const INT8 M = (op & 0x00ff);
|
||||
const UINT8 R = (op & 0x0e00) >> 9;
|
||||
void* reg = registerFromRImmediateField(R);
|
||||
writeRegister(reg, (INT16)M); // Sign extend 8 bit int
|
||||
// TODO: Figure out notes about the DSP16A vs the DSP16. 9 bit is very DSP16...
|
||||
const UINT16 M = (op & 0x01ff);
|
||||
const UINT8 R = (op & 0x0e00) >> 9;
|
||||
void* destinationReg = registerFromRImmediateField(R);
|
||||
// Sign extend if the destination is j or k
|
||||
UINT16 mValue = M;
|
||||
if (destinationReg == &m_j || destinationReg == &m_k)
|
||||
{
|
||||
if (mValue & 0x0100) mValue |= 0xfe00;
|
||||
}
|
||||
writeRegister(destinationReg, mValue);
|
||||
cycles = 1;
|
||||
pcAdvance = 1;
|
||||
break;
|
||||
@ -648,14 +876,16 @@ void dsp16_device::execute_one(const UINT16& op, UINT8& cycles, UINT8& pcAdvance
|
||||
// Format 10: do - redo
|
||||
case 0x0e:
|
||||
{
|
||||
DSP_LINE("3-25/3-26")
|
||||
// do|redo K : (pages 3-25 & 3-26)
|
||||
// TODO: The timings are intricate to say the least...
|
||||
const UINT8 K = (op & 0x007f);
|
||||
const UINT8 NI = (op & 0x0780) >> 7;
|
||||
if (NI != 0)
|
||||
{
|
||||
// Do
|
||||
m_cacheStart = m_pc + 1;
|
||||
m_cacheEnd = m_pc + NI + 1;
|
||||
m_cacheEnd = m_pc + 1 + NI;
|
||||
m_cacheIterations = K-1; // -1 because we check the counter @ the end
|
||||
cycles = 1;
|
||||
pcAdvance = 1;
|
||||
@ -666,9 +896,8 @@ void dsp16_device::execute_one(const UINT16& op, UINT8& cycles, UINT8& pcAdvance
|
||||
m_cacheIterations = K-1; // -1 because we check the counter @ the end
|
||||
m_cacheRedoNextPC = m_pc + 1;
|
||||
m_pc = m_cacheStart;
|
||||
pcAdvance = 0;
|
||||
cycles = 2;
|
||||
pcAdvance = 1;
|
||||
pcAdvance = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -676,12 +905,14 @@ void dsp16_device::execute_one(const UINT16& op, UINT8& cycles, UINT8& pcAdvance
|
||||
// RESERVED
|
||||
case 0x1e:
|
||||
{
|
||||
DSP_LINE("XXX")
|
||||
break;
|
||||
}
|
||||
|
||||
// UNKNOWN
|
||||
default:
|
||||
{
|
||||
DSP_LINE("XXX")
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user