918 lines
17 KiB
C++
918 lines
17 KiB
C++
// license:BSD-3-Clause
|
|
// copyright-holders:Olivier Galibert
|
|
/***************************************************************************
|
|
|
|
tms57002.c
|
|
|
|
TMS57002 "DASP" emulator.
|
|
|
|
***************************************************************************/
|
|
|
|
|
|
#include "emu.h"
|
|
#include "debugger.h"
|
|
#include "tms57002.h"
|
|
|
|
const device_type TMS57002 = &device_creator<tms57002_device>;
|
|
|
|
// Can't use a DEVICE_ADDRESS_MAP, not yet anyway
|
|
static ADDRESS_MAP_START(internal_pgm, AS_PROGRAM, 32, tms57002_device)
|
|
AM_RANGE(0x00, 0xff) AM_RAM
|
|
ADDRESS_MAP_END
|
|
|
|
tms57002_device::tms57002_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
|
|
: cpu_device(mconfig, TMS57002, "TMS57002", tag, owner, clock, "tms57002", __FILE__),
|
|
device_sound_interface(mconfig, *this), macc(0), st0(0), st1(0), sti(0),
|
|
txrd(0),
|
|
program_config("program", ENDIANNESS_LITTLE, 32, 8, -2, ADDRESS_MAP_NAME(internal_pgm)),
|
|
data_config("data", ENDIANNESS_LITTLE, 8, 20)
|
|
{
|
|
}
|
|
|
|
|
|
WRITE_LINE_MEMBER(tms57002_device::pload_w)
|
|
{
|
|
UINT8 olds = sti;
|
|
if(state)
|
|
sti &= ~IN_PLOAD;
|
|
else
|
|
sti |= IN_PLOAD;
|
|
if(olds ^ sti) {
|
|
if (sti & IN_PLOAD) {
|
|
hidx = 0;
|
|
hpc = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
WRITE_LINE_MEMBER(tms57002_device::cload_w)
|
|
{
|
|
UINT8 olds = sti;
|
|
if(state)
|
|
sti &= ~IN_CLOAD;
|
|
else
|
|
sti |= IN_CLOAD;
|
|
if(olds ^ sti) {
|
|
if (sti & IN_CLOAD) {
|
|
hidx = 0;
|
|
ca = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
void tms57002_device::device_reset()
|
|
{
|
|
sti = (sti & ~(SU_MASK|S_READ|S_WRITE|S_BRANCH|S_HOST)) | (SU_ST0|S_IDLE);
|
|
pc = 0;
|
|
ca = 0;
|
|
hidx = 0;
|
|
id = 0;
|
|
ba0 = 0;
|
|
ba1 = 0;
|
|
st0 &= ~(ST0_INCS | ST0_DIRI | ST0_FI | ST0_SIM | ST0_PLRI |
|
|
ST0_PBCI | ST0_DIRO | ST0_FO | ST0_SOM | ST0_PLRO |
|
|
ST0_PBCO | ST0_CNS);
|
|
st1 &= ~(ST1_AOV | ST1_SFAI | ST1_SFAO | ST1_MOVM | ST1_MOV |
|
|
ST1_SFMA | ST1_SFMO | ST1_RND | ST1_CRM | ST1_DBP);
|
|
|
|
xba = 0;
|
|
xoa = 0;
|
|
cache_flush();
|
|
}
|
|
|
|
WRITE8_MEMBER(tms57002_device::data_w)
|
|
{
|
|
switch(sti & (IN_PLOAD|IN_CLOAD)) {
|
|
case 0:
|
|
hidx = 0;
|
|
sti &= ~SU_CVAL;
|
|
break;
|
|
case IN_PLOAD:
|
|
host[hidx++] = data;
|
|
if(hidx >= 3) {
|
|
UINT32 val = (host[0]<<16) | (host[1]<<8) | host[2];
|
|
hidx = 0;
|
|
|
|
switch(sti & SU_MASK) {
|
|
case SU_ST0:
|
|
st0 = val;
|
|
sti = (sti & ~SU_MASK) | SU_ST1;
|
|
break;
|
|
case SU_ST1:
|
|
st1 = val;
|
|
sti = (sti & ~SU_MASK) | SU_PRG;
|
|
break;
|
|
case SU_PRG:
|
|
program->write_dword(pc++ << 2, val);
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
case IN_CLOAD:
|
|
if(sti & SU_CVAL) {
|
|
host[hidx++] = data;
|
|
if(hidx >= 4) {
|
|
UINT32 val = (host[0]<<24) | (host[1]<<16) | (host[2]<<8) | host[3];
|
|
cmem[sa] = val;
|
|
sti &= ~SU_CVAL;
|
|
allow_update = 0;
|
|
}
|
|
} else {
|
|
sa = data;
|
|
hidx = 0;
|
|
sti |= SU_CVAL;
|
|
}
|
|
|
|
break;
|
|
case IN_PLOAD|IN_CLOAD:
|
|
host[hidx++] = data;
|
|
if(hidx >= 4) {
|
|
UINT32 val = (host[0]<<24) | (host[1]<<16) | (host[2]<<8) | host[3];
|
|
hidx = 0;
|
|
cmem[ca++] = val;
|
|
}
|
|
break;
|
|
};
|
|
}
|
|
|
|
READ8_MEMBER(tms57002_device::data_r)
|
|
{
|
|
UINT8 res;
|
|
if(!(sti & S_HOST))
|
|
return 0xff;
|
|
|
|
res = host[hidx];
|
|
hidx++;
|
|
if(hidx == 4) {
|
|
hidx = 0;
|
|
sti &= ~S_HOST;
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
READ_LINE_MEMBER(tms57002_device::empty_r)
|
|
{
|
|
return 1;
|
|
}
|
|
|
|
READ_LINE_MEMBER(tms57002_device::dready_r)
|
|
{
|
|
return sti & S_HOST ? 0 : 1;
|
|
}
|
|
|
|
READ_LINE_MEMBER(tms57002_device::pc0_r)
|
|
{
|
|
return pc == 0 ? 0 : 1;
|
|
}
|
|
|
|
WRITE_LINE_MEMBER(tms57002_device::sync_w)
|
|
{
|
|
if(sti & (IN_PLOAD | IN_CLOAD))
|
|
return;
|
|
|
|
allow_update = 1;
|
|
pc = 0;
|
|
ca = 0;
|
|
id = 0;
|
|
if(!(st0 & ST0_INCS)) {
|
|
ba0--;
|
|
ba1++;
|
|
}
|
|
xba = (xba-1) & 0x7ffff;
|
|
st1 &= ~(ST1_AOV | ST1_MOV);
|
|
sti &= ~S_IDLE;
|
|
}
|
|
|
|
void tms57002_device::xm_init()
|
|
{
|
|
UINT32 adr = xoa + xba;
|
|
UINT32 mask = 0;
|
|
|
|
switch(st0 & ST0_M) {
|
|
case ST0_M_64K: mask = 0x0ffff; break;
|
|
case ST0_M_256K: mask = 0x3ffff; break;
|
|
case ST0_M_1M: mask = 0xfffff; break;
|
|
}
|
|
if(st0 & ST0_WORD)
|
|
adr <<= 2;
|
|
else
|
|
adr <<= 1;
|
|
|
|
if(!(st0 & ST0_SEL))
|
|
adr <<= 1;
|
|
|
|
xm_adr = adr & mask;
|
|
}
|
|
|
|
inline void tms57002_device::xm_step_read()
|
|
{
|
|
UINT32 adr = xm_adr;
|
|
UINT8 v = data->read_byte(adr);
|
|
int done;
|
|
if(st0 & ST0_WORD) {
|
|
if(st0 & ST0_SEL) {
|
|
int off = 16 - ((adr & 3) << 3);
|
|
txrd = (txrd & ~(0xff << off)) | (v << off);
|
|
done = off == 0;
|
|
} else {
|
|
int off = 20 - ((adr & 7) << 2);
|
|
txrd = (txrd & ~(0xf << off)) | ((v & 0xf) << off);
|
|
done = off == 0;
|
|
}
|
|
} else {
|
|
if(st0 & ST0_SEL) {
|
|
int off = 16 - ((adr & 1) << 3);
|
|
txrd = (txrd & ~(0xff << off)) | (v << off);
|
|
done = off == 8;
|
|
if(done)
|
|
txrd &= 0xffff00;
|
|
} else {
|
|
int off = 20 - ((adr & 3) << 2);
|
|
txrd = (txrd & ~(0xf << off)) | ((v & 0xf) << off);
|
|
done = off == 8;
|
|
if(done)
|
|
txrd &= 0xffff00;
|
|
}
|
|
}
|
|
if(done) {
|
|
xrd = txrd;
|
|
sti &= ~S_READ;
|
|
xm_adr = 0;
|
|
} else
|
|
xm_adr = adr+1;
|
|
}
|
|
|
|
inline void tms57002_device::xm_step_write()
|
|
{
|
|
UINT32 adr = xm_adr;
|
|
UINT8 v;
|
|
int done;
|
|
if(st0 & ST0_WORD) {
|
|
if(st0 & ST0_SEL) {
|
|
int off = 16 - ((adr & 3) << 3);
|
|
v = xwr >> off;
|
|
done = off == 0;
|
|
} else {
|
|
int off = 20 - ((adr & 7) << 2);
|
|
v = (xwr >> off) & 0xf;
|
|
done = off == 0;
|
|
}
|
|
} else {
|
|
if(st0 & ST0_SEL) {
|
|
int off = 16 - ((adr & 1) << 3);
|
|
v = xwr >> off;
|
|
done = off == 8;
|
|
} else {
|
|
int off = 20 - ((adr & 3) << 2);
|
|
v = (xwr >> off) & 0xf;
|
|
done = off == 8;
|
|
}
|
|
}
|
|
data->write_byte(adr, v);
|
|
if(done) {
|
|
sti &= ~S_WRITE;
|
|
xm_adr = 0;
|
|
} else
|
|
xm_adr = adr+1;
|
|
}
|
|
|
|
INT64 tms57002_device::macc_to_output_0(INT64 rounding, UINT64 rmask)
|
|
{
|
|
INT64 m = macc;
|
|
UINT64 m1;
|
|
int over = 0;
|
|
|
|
// Overflow detection and shifting
|
|
m1 = m & 0xf800000000000ULL;
|
|
if(m1 && m1 != 0xf800000000000ULL)
|
|
over = 1;
|
|
|
|
m = (m + rounding) & rmask;
|
|
|
|
// Second overflow detection
|
|
m1 = m & 0xf800000000000ULL;
|
|
if(m1 && m1 != 0xf800000000000ULL)
|
|
over = 1;
|
|
|
|
// Overflow handling
|
|
if(over) {
|
|
st1 |= ST1_MOV;
|
|
}
|
|
return m;
|
|
}
|
|
|
|
INT64 tms57002_device::macc_to_output_1(INT64 rounding, UINT64 rmask)
|
|
{
|
|
INT64 m = macc;
|
|
UINT64 m1;
|
|
int over = 0;
|
|
|
|
// Overflow detection and shifting
|
|
m1 = m & 0xfe00000000000ULL;
|
|
if(m1 && m1 != 0xfe00000000000ULL)
|
|
over = 1;
|
|
m <<= 2;
|
|
|
|
m = (m + rounding) & rmask;
|
|
|
|
// Second overflow detection
|
|
m1 = m & 0xf800000000000ULL;
|
|
if(m1 && m1 != 0xf800000000000ULL)
|
|
over = 1;
|
|
|
|
// Overflow handling
|
|
if(over) {
|
|
st1 |= ST1_MOV;
|
|
}
|
|
return m;
|
|
}
|
|
|
|
INT64 tms57002_device::macc_to_output_2(INT64 rounding, UINT64 rmask)
|
|
{
|
|
INT64 m = macc;
|
|
UINT64 m1;
|
|
int over = 0;
|
|
|
|
// Overflow detection and shifting
|
|
m1 = m & 0xff80000000000ULL;
|
|
if(m1 && m1 != 0xff80000000000ULL)
|
|
over = 1;
|
|
m <<= 4;
|
|
|
|
m = (m + rounding) & rmask;
|
|
|
|
// Second overflow detection
|
|
m1 = m & 0xf800000000000ULL;
|
|
if(m1 && m1 != 0xf800000000000ULL)
|
|
over = 1;
|
|
|
|
// Overflow handling
|
|
if(over) {
|
|
st1 |= ST1_MOV;
|
|
}
|
|
return m;
|
|
}
|
|
|
|
INT64 tms57002_device::macc_to_output_3(INT64 rounding, UINT64 rmask)
|
|
{
|
|
INT64 m = macc;
|
|
UINT64 m1;
|
|
int over = 0;
|
|
|
|
// Overflow detection and shifting
|
|
m >>= 8;
|
|
|
|
m = (m + rounding) & rmask;
|
|
|
|
// Second overflow detection
|
|
m1 = m & 0xf800000000000ULL;
|
|
if(m1 && m1 != 0xf800000000000ULL)
|
|
over = 1;
|
|
|
|
// Overflow handling
|
|
if(over) {
|
|
st1 |= ST1_MOV;
|
|
}
|
|
return m;
|
|
}
|
|
|
|
INT64 tms57002_device::macc_to_output_0s(INT64 rounding, UINT64 rmask)
|
|
{
|
|
INT64 m = macc;
|
|
UINT64 m1;
|
|
int over = 0;
|
|
|
|
// Overflow detection and shifting
|
|
m1 = m & 0xf800000000000ULL;
|
|
if(m1 && m1 != 0xf800000000000ULL)
|
|
over = 1;
|
|
|
|
m = (m + rounding) & rmask;
|
|
|
|
// Second overflow detection
|
|
m1 = m & 0xf800000000000ULL;
|
|
if(m1 && m1 != 0xf800000000000ULL)
|
|
over = 1;
|
|
|
|
// Overflow handling
|
|
if(over) {
|
|
st1 |= ST1_MOV;
|
|
if(m & 0x8000000000000ULL)
|
|
m = 0xffff800000000000ULL;
|
|
else
|
|
m = 0x00007fffffffffffULL;
|
|
}
|
|
return m;
|
|
}
|
|
|
|
INT64 tms57002_device::macc_to_output_1s(INT64 rounding, UINT64 rmask)
|
|
{
|
|
INT64 m = macc;
|
|
UINT64 m1;
|
|
int over = 0;
|
|
|
|
// Overflow detection and shifting
|
|
m1 = m & 0xfe00000000000ULL;
|
|
if(m1 && m1 != 0xfe00000000000ULL)
|
|
over = 1;
|
|
m <<= 2;
|
|
|
|
m = (m + rounding) & rmask;
|
|
|
|
// Second overflow detection
|
|
m1 = m & 0xf800000000000ULL;
|
|
if(m1 && m1 != 0xf800000000000ULL)
|
|
over = 1;
|
|
|
|
// Overflow handling
|
|
if(over) {
|
|
st1 |= ST1_MOV;
|
|
if(m & 0x8000000000000ULL)
|
|
m = 0xffff800000000000ULL;
|
|
else
|
|
m = 0x00007fffffffffffULL;
|
|
}
|
|
return m;
|
|
}
|
|
|
|
INT64 tms57002_device::macc_to_output_2s(INT64 rounding, UINT64 rmask)
|
|
{
|
|
INT64 m = macc;
|
|
UINT64 m1;
|
|
int over = 0;
|
|
|
|
// Overflow detection and shifting
|
|
m1 = m & 0xff80000000000ULL;
|
|
if(m1 && m1 != 0xff80000000000ULL)
|
|
over = 1;
|
|
m <<= 4;
|
|
|
|
m = (m + rounding) & rmask;
|
|
|
|
// Second overflow detection
|
|
m1 = m & 0xf800000000000ULL;
|
|
if(m1 && m1 != 0xf800000000000ULL)
|
|
over = 1;
|
|
|
|
// Overflow handling
|
|
if(over) {
|
|
st1 |= ST1_MOV;
|
|
if(m & 0x8000000000000ULL)
|
|
m = 0xffff800000000000ULL;
|
|
else
|
|
m = 0x00007fffffffffffULL;
|
|
}
|
|
return m;
|
|
}
|
|
|
|
INT64 tms57002_device::macc_to_output_3s(INT64 rounding, UINT64 rmask)
|
|
{
|
|
INT64 m = macc;
|
|
UINT64 m1;
|
|
int over = 0;
|
|
|
|
// Overflow detection and shifting
|
|
m >>= 8;
|
|
|
|
m = (m + rounding) & rmask;
|
|
|
|
// Second overflow detection
|
|
m1 = m & 0xf800000000000ULL;
|
|
if(m1 && m1 != 0xf800000000000ULL)
|
|
over = 1;
|
|
|
|
// Overflow handling
|
|
if(over) {
|
|
st1 |= ST1_MOV;
|
|
if(m & 0x8000000000000ULL)
|
|
m = 0xffff800000000000ULL;
|
|
else
|
|
m = 0x00007fffffffffffULL;
|
|
}
|
|
return m;
|
|
}
|
|
|
|
INT64 tms57002_device::check_macc_overflow_0()
|
|
{
|
|
INT64 m = macc;
|
|
UINT64 m1;
|
|
|
|
// Overflow detection
|
|
m1 = m & 0xf800000000000ULL;
|
|
if(m1 && m1 != 0xf800000000000ULL) {
|
|
st1 |= ST1_MOV;
|
|
}
|
|
return m;
|
|
}
|
|
|
|
INT64 tms57002_device::check_macc_overflow_1()
|
|
{
|
|
INT64 m = macc;
|
|
UINT64 m1;
|
|
|
|
// Overflow detection
|
|
m1 = m & 0xfe00000000000ULL;
|
|
if(m1 && m1 != 0xfe00000000000ULL) {
|
|
st1 |= ST1_MOV;
|
|
}
|
|
return m;
|
|
}
|
|
|
|
INT64 tms57002_device::check_macc_overflow_2()
|
|
{
|
|
INT64 m = macc;
|
|
UINT64 m1;
|
|
|
|
// Overflow detection
|
|
m1 = m & 0xff80000000000ULL;
|
|
if(m1 && m1 != 0xff80000000000ULL) {
|
|
st1 |= ST1_MOV;
|
|
}
|
|
return m;
|
|
}
|
|
|
|
INT64 tms57002_device::check_macc_overflow_3()
|
|
{
|
|
return macc;
|
|
}
|
|
|
|
INT64 tms57002_device::check_macc_overflow_0s()
|
|
{
|
|
INT64 m = macc;
|
|
UINT64 m1;
|
|
|
|
// Overflow detection
|
|
m1 = m & 0xf800000000000ULL;
|
|
if(m1 && m1 != 0xf800000000000ULL) {
|
|
st1 |= ST1_MOV;
|
|
if(m & 0x8000000000000ULL)
|
|
m = 0xffff800000000000ULL;
|
|
else
|
|
m = 0x00007fffffffffffULL;
|
|
}
|
|
return m;
|
|
}
|
|
|
|
INT64 tms57002_device::check_macc_overflow_1s()
|
|
{
|
|
INT64 m = macc;
|
|
UINT64 m1;
|
|
|
|
// Overflow detection
|
|
m1 = m & 0xfe00000000000ULL;
|
|
if(m1 && m1 != 0xfe00000000000ULL) {
|
|
st1 |= ST1_MOV;
|
|
if(m & 0x8000000000000ULL)
|
|
m = 0xffff800000000000ULL;
|
|
else
|
|
m = 0x00007fffffffffffULL;
|
|
}
|
|
return m;
|
|
}
|
|
|
|
INT64 tms57002_device::check_macc_overflow_2s()
|
|
{
|
|
INT64 m = macc;
|
|
UINT64 m1;
|
|
|
|
// Overflow detection
|
|
m1 = m & 0xff80000000000ULL;
|
|
if(m1 && m1 != 0xff80000000000ULL) {
|
|
st1 |= ST1_MOV;
|
|
if(m & 0x8000000000000ULL)
|
|
m = 0xffff800000000000ULL;
|
|
else
|
|
m = 0x00007fffffffffffULL;
|
|
}
|
|
return m;
|
|
}
|
|
|
|
INT64 tms57002_device::check_macc_overflow_3s()
|
|
{
|
|
return macc;
|
|
}
|
|
|
|
void tms57002_device::cache_flush()
|
|
{
|
|
int i;
|
|
cache.hused = cache.iused = 0;
|
|
for(i=0; i != 256; i++)
|
|
cache.hashbase[i] = -1;
|
|
for(i=0; i != HBS; i++) {
|
|
cache.hashnode[i].st1 = 0;
|
|
cache.hashnode[i].ipc = -1;
|
|
cache.hashnode[i].next = -1;
|
|
}
|
|
for(i=0; i != IBS; i++) {
|
|
cache.inst[i].op = 0;
|
|
cache.inst[i].next = -1;
|
|
cache.inst[i].param = 0;
|
|
}
|
|
}
|
|
|
|
void tms57002_device::add_one(cstate *cs, unsigned short op, UINT8 param)
|
|
{
|
|
short ipc = cache.iused++;
|
|
cache.inst[ipc].op = op;
|
|
cache.inst[ipc].param = param;
|
|
cache.inst[ipc].next = -1;
|
|
if(cs->ipc != -1)
|
|
cache.inst[cs->ipc].next = ipc;
|
|
cs->ipc = ipc;
|
|
if(cs->hnode != -1) {
|
|
cache.hashnode[cs->hnode].ipc = ipc;
|
|
cs->hnode = -1;
|
|
}
|
|
}
|
|
|
|
void tms57002_device::decode_one(UINT32 opcode, cstate *cs, void (tms57002_device::*dec)(UINT32 opcode, unsigned short *op, cstate *cs))
|
|
{
|
|
unsigned short op = 0;
|
|
(this->*dec)(opcode, &op, cs);
|
|
if(!op)
|
|
return;
|
|
add_one(cs, op, opcode & 0xff);
|
|
}
|
|
|
|
short tms57002_device::get_hash(unsigned char adr, UINT32 st1, short *pnode)
|
|
{
|
|
short hnode;
|
|
st1 &= ST1_CACHE;
|
|
*pnode = -1;
|
|
hnode = cache.hashbase[adr];
|
|
while(hnode != -1) {
|
|
if(cache.hashnode[hnode].st1 == st1)
|
|
return cache.hashnode[hnode].ipc;
|
|
*pnode = hnode;
|
|
hnode = cache.hashnode[hnode].next;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
short tms57002_device::get_hashnode(unsigned char adr, UINT32 st1, short pnode)
|
|
{
|
|
short hnode = cache.hused++;
|
|
cache.hashnode[hnode].st1 = st1 & ST1_CACHE;
|
|
cache.hashnode[hnode].ipc = -1;
|
|
cache.hashnode[hnode].next = -1;
|
|
if(pnode == -1)
|
|
cache.hashbase[adr] = hnode;
|
|
else
|
|
cache.hashnode[pnode].next = hnode;
|
|
return hnode;
|
|
}
|
|
|
|
int tms57002_device::decode_get_pc()
|
|
{
|
|
short pnode, res;
|
|
cstate cs;
|
|
UINT8 adr = pc;
|
|
|
|
res = get_hash(adr, st1, &pnode);
|
|
if(res != -1)
|
|
return res;
|
|
|
|
if(HBS - cache.hused < 256 || IBS - cache.iused < 256*3) {
|
|
cache_flush();
|
|
pnode = -1;
|
|
}
|
|
|
|
cs.hnode = res = get_hashnode(adr, st1, pnode);
|
|
cs.ipc = -1;
|
|
cs.branch = 0;
|
|
|
|
for(;;) {
|
|
short ipc;
|
|
UINT32 opcode = program->read_dword(adr << 2);
|
|
|
|
cs.inc = 0;
|
|
|
|
if((opcode & 0xfc0000) == 0xfc0000)
|
|
decode_one(opcode, &cs, &tms57002_device::decode_cat3);
|
|
else {
|
|
decode_one(opcode, &cs, &tms57002_device::decode_cat2_pre);
|
|
decode_one(opcode, &cs, &tms57002_device::decode_cat1);
|
|
decode_one(opcode, &cs, &tms57002_device::decode_cat2_post);
|
|
}
|
|
add_one(&cs, cs.inc, 0);
|
|
|
|
if(cs.branch)
|
|
break;
|
|
|
|
adr++;
|
|
ipc = get_hash(adr, st1, &pnode);
|
|
if(ipc != -1) {
|
|
cache.inst[cs.ipc].next = ipc;
|
|
break;
|
|
}
|
|
cs.hnode = get_hashnode(adr, st1, pnode);
|
|
}
|
|
|
|
return cache.hashnode[res].ipc;
|
|
}
|
|
|
|
void tms57002_device::execute_run()
|
|
{
|
|
int ipc = -1;
|
|
|
|
while(icount > 0 && !(sti & (S_IDLE | IN_PLOAD | IN_CLOAD))) {
|
|
int iipc;
|
|
|
|
debugger_instruction_hook(this, pc);
|
|
|
|
if(ipc == -1)
|
|
ipc = decode_get_pc();
|
|
|
|
iipc = ipc;
|
|
|
|
if(sti & (S_READ|S_WRITE)) {
|
|
if(sti & S_READ)
|
|
xm_step_read();
|
|
else
|
|
xm_step_write();
|
|
}
|
|
|
|
for(;;) {
|
|
UINT32 c, d;
|
|
INT64 r;
|
|
const icd *i = cache.inst + ipc;
|
|
|
|
ipc = i->next;
|
|
switch(i->op) {
|
|
case 0:
|
|
goto inst;
|
|
|
|
case 1:
|
|
++ca;
|
|
goto inst;
|
|
|
|
case 2:
|
|
++id;
|
|
goto inst;
|
|
|
|
case 3:
|
|
++ca, ++id;
|
|
goto inst;
|
|
|
|
#define CINTRP
|
|
#include "cpu/tms57002/tms57002.hxx"
|
|
#undef CINTRP
|
|
|
|
default:
|
|
fatalerror("Unhandled opcode in tms57002_execute\n");
|
|
}
|
|
}
|
|
inst:
|
|
icount--;
|
|
|
|
if(rptc) {
|
|
rptc--;
|
|
ipc = iipc;
|
|
} else if(sti & S_BRANCH) {
|
|
sti &= ~S_BRANCH;
|
|
ipc = -1;
|
|
} else
|
|
pc++; // Wraps if it reaches 256, next wraps too
|
|
|
|
if(rptc_next) {
|
|
rptc = rptc_next;
|
|
rptc_next = 0;
|
|
}
|
|
}
|
|
|
|
if(icount > 0)
|
|
icount = 0;
|
|
}
|
|
|
|
void tms57002_device::sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples)
|
|
{
|
|
assert(samples == 1);
|
|
|
|
if(st0 & ST0_SIM) {
|
|
si[0] = (inputs[0][0] << 8) & 0xffffff;
|
|
si[1] = (inputs[1][0] << 8) & 0xffffff;
|
|
si[2] = (inputs[2][0] << 8) & 0xffffff;
|
|
si[3] = (inputs[3][0] << 8) & 0xffffff;
|
|
} else {
|
|
si[0] = inputs[0][0] & 0xffffff;
|
|
si[1] = inputs[1][0] & 0xffffff;
|
|
si[2] = inputs[2][0] & 0xffffff;
|
|
si[3] = inputs[3][0] & 0xffffff;
|
|
}
|
|
outputs[0][0] = INT16(so[0] >> 8);
|
|
outputs[1][0] = INT16(so[1] >> 8);
|
|
outputs[2][0] = INT16(so[2] >> 8);
|
|
outputs[3][0] = INT16(so[3] >> 8);
|
|
|
|
sync_w(1);
|
|
}
|
|
|
|
void tms57002_device::device_start()
|
|
{
|
|
sti = S_IDLE;
|
|
program = &space(AS_PROGRAM);
|
|
data = &space(AS_DATA);
|
|
|
|
state_add(STATE_GENPC, "GENPC", pc).noshow();
|
|
state_add(TMS57002_PC, "PC", pc);
|
|
state_add(TMS57002_ST0, "ST0", st0);
|
|
state_add(TMS57002_ST1, "ST1", st1);
|
|
state_add(TMS57002_RPTC, "RPTC", rptc);
|
|
state_add(TMS57002_AACC, "AACC", aacc);
|
|
state_add(TMS57002_MACC, "MACC", macc).mask(U64(0xfffffffffffff));
|
|
state_add(TMS57002_BA0, "BA0", ba0);
|
|
state_add(TMS57002_BA1, "BA1", ba1);
|
|
state_add(TMS57002_CREG, "CREG", creg);
|
|
state_add(TMS57002_CA, "CA", ca);
|
|
state_add(TMS57002_ID, "ID", id);
|
|
state_add(TMS57002_XBA, "XBA", xba);
|
|
state_add(TMS57002_XOA, "XOA", xoa);
|
|
state_add(TMS57002_XRD, "XRD", xrd);
|
|
state_add(TMS57002_XWR, "XWR", xwr);
|
|
state_add(TMS57002_HIDX, "HIDX", hidx);
|
|
state_add(TMS57002_HOST0, "HOST0", host[0]);
|
|
state_add(TMS57002_HOST1, "HOST1", host[1]);
|
|
state_add(TMS57002_HOST2, "HOST2", host[2]);
|
|
state_add(TMS57002_HOST3, "HOST3", host[3]);
|
|
|
|
m_icountptr = &icount;
|
|
|
|
stream_alloc(4, 4, STREAM_SYNC);
|
|
|
|
save_item(NAME(macc));
|
|
|
|
save_item(NAME(cmem));
|
|
save_item(NAME(dmem0));
|
|
save_item(NAME(dmem1));
|
|
|
|
save_item(NAME(si));
|
|
save_item(NAME(so));
|
|
|
|
save_item(NAME(st0));
|
|
save_item(NAME(st1));
|
|
save_item(NAME(sti));
|
|
save_item(NAME(aacc));
|
|
save_item(NAME(xoa));
|
|
save_item(NAME(xba));
|
|
save_item(NAME(xwr));
|
|
save_item(NAME(xrd));
|
|
save_item(NAME(txrd));
|
|
save_item(NAME(creg));
|
|
|
|
save_item(NAME(pc));
|
|
save_item(NAME(ca));
|
|
save_item(NAME(id));
|
|
save_item(NAME(ba0));
|
|
save_item(NAME(ba1));
|
|
save_item(NAME(rptc));
|
|
save_item(NAME(rptc_next));
|
|
save_item(NAME(sa));
|
|
|
|
save_item(NAME(xm_adr));
|
|
|
|
save_item(NAME(host));
|
|
save_item(NAME(hidx));
|
|
save_item(NAME(allow_update));
|
|
}
|
|
|
|
UINT32 tms57002_device::execute_min_cycles() const
|
|
{
|
|
return 1;
|
|
}
|
|
|
|
UINT32 tms57002_device::execute_max_cycles() const
|
|
{
|
|
return 3;
|
|
}
|
|
|
|
UINT32 tms57002_device::execute_input_lines() const
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
UINT32 tms57002_device::disasm_min_opcode_bytes() const
|
|
{
|
|
return 4;
|
|
}
|
|
|
|
UINT32 tms57002_device::disasm_max_opcode_bytes() const
|
|
{
|
|
return 4;
|
|
}
|
|
|
|
offs_t tms57002_device::disasm_disassemble(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram, UINT32 options)
|
|
{
|
|
extern CPU_DISASSEMBLE( tms57002 );
|
|
return CPU_DISASSEMBLE_NAME(tms57002)(this, buffer, pc, oprom, opram, options);
|
|
}
|
|
|
|
const address_space_config *tms57002_device::memory_space_config(address_spacenum spacenum) const
|
|
{
|
|
switch(spacenum) {
|
|
case AS_PROGRAM: return &program_config;
|
|
case AS_DATA: return &data_config;
|
|
default: return nullptr;
|
|
}
|
|
}
|