scmp.c: Modernized cpu core. [Wilbert Pol]

This commit is contained in:
Wilbert Pol 2013-12-28 20:53:14 +00:00
parent e477d12877
commit 1eac5f4e9e
2 changed files with 358 additions and 385 deletions

View File

@ -16,128 +16,128 @@
#define LOG(x) do { if (VERBOSE) logerror x; } while (0)
/***************************************************************************
TYPE DEFINITIONS
***************************************************************************/
struct scmp_state
const device_type SCMP = &device_creator<scmp_device>;
const device_type INS8060 = &device_creator<ins8060_device>;
scmp_device::scmp_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
: cpu_device(mconfig, SCMP, "INS 8050 SC/MP", tag, owner, clock, "ins8050", __FILE__)
, m_program_config("program", ENDIANNESS_LITTLE, 8, 16, 0)
, m_flag_out_func(*this)
, m_sout_func(*this)
, m_sin_func(*this)
, m_sensea_func(*this)
, m_senseb_func(*this)
, m_halt_func(*this)
{
scmp_config config;
PAIR PC;
PAIR P1;
PAIR P2;
PAIR P3;
UINT8 AC;
UINT8 ER;
UINT8 SR;
legacy_cpu_device *device;
address_space *program;
direct_read_data *direct;
address_space *io;
int icount;
devcb_resolved_write8 flag_out_func;
devcb_resolved_write_line sout_func;
devcb_resolved_read_line sin_func;
devcb_resolved_read_line sensea_func;
devcb_resolved_read_line senseb_func;
devcb_resolved_write_line halt_func;
};
/***************************************************************************
MACROS
***************************************************************************/
/***************************************************************************
INLINE FUNCTIONS
***************************************************************************/
INLINE scmp_state *get_safe_token(device_t *device)
{
assert(device != NULL);
assert(device->type() == SCMP || device->type() == INS8060);
return (scmp_state *)downcast<legacy_cpu_device *>(device)->token();
}
INLINE UINT16 ADD12(UINT16 addr, INT8 val)
scmp_device::scmp_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source)
: cpu_device(mconfig, type, name, tag, owner, clock, shortname, source)
, m_program_config("program", ENDIANNESS_LITTLE, 8, 16, 0)
, m_flag_out_func(*this)
, m_sout_func(*this)
, m_sin_func(*this)
, m_sensea_func(*this)
, m_senseb_func(*this)
, m_halt_func(*this)
{
}
ins8060_device::ins8060_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
: scmp_device(mconfig, INS8060, "INS 8060 SC/MP II", tag, owner, clock, "ins8060", __FILE__)
{
}
offs_t scmp_device::disasm_disassemble(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram, UINT32 options)
{
extern CPU_DISASSEMBLE( scmp );
return CPU_DISASSEMBLE_NAME(scmp)(this, buffer, pc, oprom, opram, options);
}
UINT16 scmp_device::ADD12(UINT16 addr, INT8 val)
{
return ((addr + val) & 0x0fff) | (addr & 0xf000);
}
INLINE UINT8 ROP(scmp_state *cpustate)
UINT8 scmp_device::ROP()
{
UINT16 pc = cpustate->PC.w.l;
cpustate->PC.w.l = ADD12(cpustate->PC.w.l,1);
return cpustate->direct->read_decrypted_byte( pc);
UINT16 pc = m_PC.w.l;
m_PC.w.l = ADD12(m_PC.w.l,1);
return m_direct->read_decrypted_byte( pc);
}
INLINE UINT8 ARG(scmp_state *cpustate)
UINT8 scmp_device::ARG()
{
UINT16 pc = cpustate->PC.w.l;
cpustate->PC.w.l = ADD12(cpustate->PC.w.l,1);
return cpustate->direct->read_raw_byte(pc);
UINT16 pc = m_PC.w.l;
m_PC.w.l = ADD12(m_PC.w.l,1);
return m_direct->read_raw_byte(pc);
}
INLINE UINT8 RM(scmp_state *cpustate,UINT32 a)
UINT8 scmp_device::RM(UINT32 a)
{
return cpustate->program->read_byte(a);
return m_program->read_byte(a);
}
INLINE void WM(scmp_state *cpustate,UINT32 a, UINT8 v)
void scmp_device::WM(UINT32 a, UINT8 v)
{
cpustate->program->write_byte(a, v);
m_program->write_byte(a, v);
}
INLINE void illegal(scmp_state *cpustate,UINT8 opcode)
void scmp_device::illegal(UINT8 opcode)
{
#if VERBOSE
UINT16 pc = cpustate->PC.w.l;
UINT16 pc = m_PC.w.l;
LOG(("SC/MP illegal instruction %04X $%02X\n", pc-1, opcode));
#endif
}
INLINE PAIR *GET_PTR_REG(scmp_state *cpustate, int num)
PAIR *scmp_device::GET_PTR_REG(int num)
{
switch(num) {
case 1: return &cpustate->P1;
case 2: return &cpustate->P2;
case 3: return &cpustate->P3;
case 1: return &m_P1;
case 2: return &m_P2;
case 3: return &m_P3;
default :
return &cpustate->PC;
return &m_PC;
}
}
INLINE void BIN_ADD(scmp_state *cpustate, UINT8 val)
void scmp_device::BIN_ADD(UINT8 val)
{
UINT16 tmp = cpustate->AC + val + ((cpustate->SR >> 7) & 1);
UINT8 ov = (((cpustate->AC & 0x80)==(val & 0x80)) && ((cpustate->AC & 0x80)!=(tmp & 0x80))) ? 0x40 : 0x00;
UINT16 tmp = m_AC + val + ((m_SR >> 7) & 1);
UINT8 ov = (((m_AC & 0x80)==(val & 0x80)) && ((m_AC & 0x80)!=(tmp & 0x80))) ? 0x40 : 0x00;
cpustate->AC = tmp & 0xff;
cpustate->SR &= 0x3f; // clear CY/L and OV flag
cpustate->SR |= (tmp & 0x100) ? 0x80 : 0x00; // set CY/L
cpustate->SR |= ov;
m_AC = tmp & 0xff;
m_SR &= 0x3f; // clear CY/L and OV flag
m_SR |= (tmp & 0x100) ? 0x80 : 0x00; // set CY/L
m_SR |= ov;
}
INLINE void DEC_ADD(scmp_state *cpustate, UINT8 val)
void scmp_device::DEC_ADD(UINT8 val)
{
UINT16 tmp = cpustate->AC + val + ((cpustate->SR >> 7) & 1);
UINT16 tmp = m_AC + val + ((m_SR >> 7) & 1);
if ((tmp & 0x0f) > 9) tmp +=6;
cpustate->AC = tmp % 0xa0;
cpustate->SR &= 0x7f; // clear CY/L flag
cpustate->SR |= (tmp > 0x99) ? 0x80 : 0x00;
m_AC = tmp % 0xa0;
m_SR &= 0x7f; // clear CY/L flag
m_SR |= (tmp > 0x99) ? 0x80 : 0x00;
}
INLINE UINT16 GET_ADDR(scmp_state *cpustate, UINT8 code)
UINT16 scmp_device::GET_ADDR(UINT8 code)
{
UINT16 addr = 0;
INT8 offset = 0;
UINT16 retVal = 0;
UINT16 ptr = GET_PTR_REG(cpustate,code & 0x03)->w.l;
UINT16 ptr = GET_PTR_REG(code & 0x03)->w.l;
UINT8 arg = ARG(cpustate);
UINT8 arg = ARG();
if (arg == 0x80) {
offset = cpustate->ER;
offset = m_ER;
} else {
if (arg & 0x80) {
offset = (INT8)arg;
@ -153,12 +153,12 @@ INLINE UINT16 GET_ADDR(scmp_state *cpustate, UINT8 code)
// Auto-indexed
if (offset < 0) {
// pre decrement
GET_PTR_REG(cpustate,code & 0x03)->w.l = addr;
GET_PTR_REG(code & 0x03)->w.l = addr;
retVal = addr;
} else {
// post increment
retVal = ptr;
GET_PTR_REG(cpustate,code & 0x03)->w.l = addr;
GET_PTR_REG(code & 0x03)->w.l = addr;
}
} else {
// Immediate
@ -170,7 +170,7 @@ INLINE UINT16 GET_ADDR(scmp_state *cpustate, UINT8 code)
return retVal;
}
static void execute_one(scmp_state *cpustate, int opcode)
void scmp_device::execute_one(int opcode)
{
UINT8 tmp;
UINT8 ptr = opcode & 3;
@ -182,140 +182,140 @@ static void execute_one(scmp_state *cpustate, int opcode)
case 0xc0 : case 0xc1 : case 0xc2 : case 0xc3 :
case 0xc5 : case 0xc6 : case 0xc7 :
//LD
cpustate->icount -= 18;
cpustate->AC = RM(cpustate,GET_ADDR(cpustate,opcode));
m_icount -= 18;
m_AC = RM(GET_ADDR(opcode));
break;
case 0xc8 : case 0xc9 : case 0xca : case 0xcb :
case 0xcd : case 0xce : case 0xcf :
// ST
cpustate->icount -= 18;
WM(cpustate,GET_ADDR(cpustate,opcode),cpustate->AC);
m_icount -= 18;
WM(GET_ADDR(opcode),m_AC);
break;
case 0xd0 : case 0xd1 : case 0xd2 : case 0xd3 :
case 0xd5 : case 0xd6 : case 0xd7 :
// AND
cpustate->icount -= 18;
cpustate->AC &= RM(cpustate,GET_ADDR(cpustate,opcode));
m_icount -= 18;
m_AC &= RM(GET_ADDR(opcode));
break;
case 0xd8 : case 0xd9 : case 0xda : case 0xdb :
case 0xdd : case 0xde : case 0xdf :
//OR
cpustate->icount -= 18;
cpustate->AC |= RM(cpustate,GET_ADDR(cpustate,opcode));
m_icount -= 18;
m_AC |= RM(GET_ADDR(opcode));
break;
case 0xe0 : case 0xe1 : case 0xe2 : case 0xe3 :
case 0xe5 : case 0xe6 : case 0xe7 :
// XOR
cpustate->icount -= 18;
cpustate->AC ^= RM(cpustate,GET_ADDR(cpustate,opcode));
m_icount -= 18;
m_AC ^= RM(GET_ADDR(opcode));
break;
case 0xe8 : case 0xe9 : case 0xea : case 0xeb :
case 0xed : case 0xee : case 0xef :
// DAD
cpustate->icount -= 23;
DEC_ADD(cpustate,RM(cpustate,GET_ADDR(cpustate,opcode)));
m_icount -= 23;
DEC_ADD(RM(GET_ADDR(opcode)));
break;
case 0xf0 : case 0xf1 : case 0xf2 : case 0xf3 :
case 0xf5 : case 0xf6 : case 0xf7 :
// ADD
cpustate->icount -= 19;
BIN_ADD(cpustate,RM(cpustate,GET_ADDR(cpustate,opcode)));
m_icount -= 19;
BIN_ADD(RM(GET_ADDR(opcode)));
break;
case 0xf8 : case 0xf9 : case 0xfa : case 0xfb :
case 0xfd : case 0xfe : case 0xff :
// CAD
cpustate->icount -= 20;
BIN_ADD(cpustate,~RM(cpustate,GET_ADDR(cpustate,opcode)));
m_icount -= 20;
BIN_ADD(~RM(GET_ADDR(opcode)));
break;
// Memory Increment/Decrement Instructions
case 0xa8 : case 0xa9 : case 0xaa : case 0xab :
// IDL
{
UINT16 addr = GET_ADDR(cpustate,opcode);
cpustate->icount -= 22;
cpustate->AC = RM(cpustate,addr) + 1;
WM(cpustate,addr,cpustate->AC);
UINT16 addr = GET_ADDR(opcode);
m_icount -= 22;
m_AC = RM(addr) + 1;
WM(addr,m_AC);
}
break;
case 0xb8 : case 0xb9 : case 0xba : case 0xbb :
// DLD
{
UINT16 addr = GET_ADDR(cpustate,opcode);
cpustate->icount -= 22;
cpustate->AC = RM(cpustate,addr) - 1;
WM(cpustate,addr,cpustate->AC);
UINT16 addr = GET_ADDR(opcode);
m_icount -= 22;
m_AC = RM(addr) - 1;
WM(addr,m_AC);
}
break;
// Immediate Instructions
case 0xc4 : // LDI
cpustate->icount -= 10;
cpustate->AC = ARG(cpustate);
m_icount -= 10;
m_AC = ARG();
break;
case 0xd4 : // ANI
cpustate->icount -= 10;
cpustate->AC &= ARG(cpustate);
m_icount -= 10;
m_AC &= ARG();
break;
case 0xdc : // ORI
cpustate->icount -= 10;
cpustate->AC |= ARG(cpustate);
m_icount -= 10;
m_AC |= ARG();
break;
case 0xe4 : // XRI
cpustate->icount -= 10;
cpustate->AC ^= ARG(cpustate);
m_icount -= 10;
m_AC ^= ARG();
break;
case 0xec : // DAI
cpustate->icount -= 15;
DEC_ADD(cpustate,ARG(cpustate));
m_icount -= 15;
DEC_ADD(ARG());
break;
case 0xf4 : // ADI
cpustate->icount -= 11;
BIN_ADD(cpustate,ARG(cpustate));
m_icount -= 11;
BIN_ADD(ARG());
break;
case 0xfc : // CAI
cpustate->icount -= 12;
BIN_ADD(cpustate,~ARG(cpustate));
m_icount -= 12;
BIN_ADD(~ARG());
break;
// Transfer Instructions
case 0x90 : case 0x91 : case 0x92 : case 0x93 :// JMP
cpustate->icount -= 11;
cpustate->PC.w.l = ADD12(GET_PTR_REG(cpustate,ptr)->w.l,(INT8)ARG(cpustate));
m_icount -= 11;
m_PC.w.l = ADD12(GET_PTR_REG(ptr)->w.l,(INT8)ARG());
break;
case 0x94 : case 0x95 : case 0x96 : case 0x97 :
// JP
cpustate->icount -= 9;
tmp = ARG(cpustate);
if (!(cpustate->AC & 0x80)) {
cpustate->PC.w.l = ADD12(GET_PTR_REG(cpustate,ptr)->w.l,(INT8)tmp);
cpustate->icount -= 2;
m_icount -= 9;
tmp = ARG();
if (!(m_AC & 0x80)) {
m_PC.w.l = ADD12(GET_PTR_REG(ptr)->w.l,(INT8)tmp);
m_icount -= 2;
}
break;
case 0x98 : case 0x99 : case 0x9a : case 0x9b :
// JZ
cpustate->icount -= 9;
tmp = ARG(cpustate);
if (!cpustate->AC) {
cpustate->PC.w.l = ADD12(GET_PTR_REG(cpustate,ptr)->w.l,(INT8)tmp);
cpustate->icount -= 2;
m_icount -= 9;
tmp = ARG();
if (!m_AC) {
m_PC.w.l = ADD12(GET_PTR_REG(ptr)->w.l,(INT8)tmp);
m_icount -= 2;
}
break;
case 0x9c : case 0x9d : case 0x9e : case 0x9f :
// JNZ
cpustate->icount -= 9;
tmp = ARG(cpustate);
if (cpustate->AC) {
cpustate->PC.w.l = ADD12(GET_PTR_REG(cpustate,ptr)->w.l,(INT8)tmp);
cpustate->icount -= 2;
m_icount -= 9;
tmp = ARG();
if (m_AC) {
m_PC.w.l = ADD12(GET_PTR_REG(ptr)->w.l,(INT8)tmp);
m_icount -= 2;
}
break;
// Double-Byte Miscellaneous Instructions
case 0x8f: // DLY
tmp = ARG(cpustate);
cpustate->icount -= 13 + (cpustate->AC * 2) + (((UINT32)tmp) << 1) + (((UINT32)tmp) << 9);
cpustate->AC = 0xff;
tmp = ARG();
m_icount -= 13 + (m_AC * 2) + (((UINT32)tmp) << 1) + (((UINT32)tmp) << 9);
m_AC = 0xff;
break;
// Others are illegal
default : cpustate->icount -= 1;
illegal (cpustate,opcode);
default : m_icount -= 1;
illegal (opcode);
break;
}
} else {
@ -324,130 +324,130 @@ static void execute_one(scmp_state *cpustate, int opcode)
{
// Extension Register Instructions
case 0x40: // LDE
cpustate->icount -= 6;
cpustate->AC = cpustate->ER;
m_icount -= 6;
m_AC = m_ER;
break;
case 0x01: // XAE
cpustate->icount -= 7;
tmp = cpustate->AC;
cpustate->AC = cpustate->ER;
cpustate->ER = tmp;
m_icount -= 7;
tmp = m_AC;
m_AC = m_ER;
m_ER = tmp;
break;
case 0x50: // ANE
cpustate->icount -= 6;
cpustate->AC &= cpustate->ER;
m_icount -= 6;
m_AC &= m_ER;
break;
case 0x58: // ORE
cpustate->icount -= 6;
cpustate->AC |= cpustate->ER;
m_icount -= 6;
m_AC |= m_ER;
break;
case 0x60: // XRE
cpustate->icount -= 6;
cpustate->AC ^= cpustate->ER;
m_icount -= 6;
m_AC ^= m_ER;
break;
case 0x68: // DAE
cpustate->icount -= 11;
DEC_ADD(cpustate,cpustate->ER);
m_icount -= 11;
DEC_ADD(m_ER);
break;
case 0x70: // ADE
cpustate->icount -= 7;
BIN_ADD(cpustate,cpustate->ER);
m_icount -= 7;
BIN_ADD(m_ER);
break;
case 0x78: // CAE
cpustate->icount -= 8;
BIN_ADD(cpustate,~cpustate->ER);
m_icount -= 8;
BIN_ADD(~m_ER);
break;
// Pointer Register Move Instructions
case 0x30: case 0x31: case 0x32: case 0x33: // XPAL
cpustate->icount -= 8;
tmp = cpustate->AC;
cpustate->AC = GET_PTR_REG(cpustate,ptr)->b.l;
GET_PTR_REG(cpustate,ptr)->b.l = tmp;
m_icount -= 8;
tmp = m_AC;
m_AC = GET_PTR_REG(ptr)->b.l;
GET_PTR_REG(ptr)->b.l = tmp;
break;
case 0x34: case 0x35 :case 0x36: case 0x37:
// XPAH
cpustate->icount -= 8;
tmp = cpustate->AC;
cpustate->AC = GET_PTR_REG(cpustate,ptr)->b.h;
GET_PTR_REG(cpustate,ptr)->b.h = tmp;
m_icount -= 8;
tmp = m_AC;
m_AC = GET_PTR_REG(ptr)->b.h;
GET_PTR_REG(ptr)->b.h = tmp;
break;
case 0x3c: case 0x3d :case 0x3e: case 0x3f:
// XPPC
{
UINT16 tmp16 = ADD12(cpustate->PC.w.l,-1); // Since PC is incremented we need to fix it
cpustate->icount -= 7;
cpustate->PC.w.l = GET_PTR_REG(cpustate,ptr)->w.l;
GET_PTR_REG(cpustate,ptr)->w.l = tmp16;
UINT16 tmp16 = ADD12(m_PC.w.l,-1); // Since PC is incremented we need to fix it
m_icount -= 7;
m_PC.w.l = GET_PTR_REG(ptr)->w.l;
GET_PTR_REG(ptr)->w.l = tmp16;
// After exchange CPU increment PC
cpustate->PC.w.l = ADD12(cpustate->PC.w.l,1);
m_PC.w.l = ADD12(m_PC.w.l,1);
}
break;
// Shift, Rotate, Serial I/O Instructions
case 0x19: // SIO
cpustate->icount -= 5;
cpustate->sout_func(cpustate->ER & 0x01);
cpustate->ER >>= 1;
cpustate->ER |= cpustate->sin_func() ? 0x80 : 0x00;
m_icount -= 5;
m_sout_func(m_ER & 0x01);
m_ER >>= 1;
m_ER |= m_sin_func() ? 0x80 : 0x00;
break;
case 0x1c: // SR
cpustate->icount -= 5;
cpustate->AC >>= 1;
m_icount -= 5;
m_AC >>= 1;
break;
case 0x1d: // SRL
cpustate->icount -= 5;
cpustate->AC >>= 1;
cpustate->AC |= cpustate->SR & 0x80; // add C/L flag
m_icount -= 5;
m_AC >>= 1;
m_AC |= m_SR & 0x80; // add C/L flag
break;
case 0x1e: // RR
cpustate->icount -= 5;
cpustate->AC = (cpustate->AC >> 1) | ((cpustate->AC & 0x01) << 7);
m_icount -= 5;
m_AC = (m_AC >> 1) | ((m_AC & 0x01) << 7);
break;
case 0x1f: // RRL
cpustate->icount -= 5;
tmp = (cpustate->AC & 0x01) << 7;
cpustate->AC = (cpustate->AC >> 1) | (cpustate->SR & 0x80);
cpustate->SR = (cpustate->SR & 0x7f) | tmp;
m_icount -= 5;
tmp = (m_AC & 0x01) << 7;
m_AC = (m_AC >> 1) | (m_SR & 0x80);
m_SR = (m_SR & 0x7f) | tmp;
break;
// Single Byte Miscellaneous Instructions
case 0x00: // HALT
cpustate->icount -= 8;
cpustate->halt_func(1);
cpustate->halt_func(0);
m_icount -= 8;
m_halt_func(1);
m_halt_func(0);
break;
case 0x02: // CCL
cpustate->icount -= 5;
cpustate->SR &= 0x7f;
m_icount -= 5;
m_SR &= 0x7f;
break;
case 0x03: // SCL
cpustate->icount -= 5;
cpustate->SR |= 0x80;
m_icount -= 5;
m_SR |= 0x80;
break;
case 0x04: // DINT
cpustate->icount -= 6;
cpustate->SR &= 0xf7;
m_icount -= 6;
m_SR &= 0xf7;
break;
case 0x05: // IEN
cpustate->icount -= 6;
cpustate->SR |= 0x08;
m_icount -= 6;
m_SR |= 0x08;
break;
case 0x06: // CSA
cpustate->icount -= 5;
cpustate->SR &= 0xcf; // clear SA and SB flags
cpustate->SR |= cpustate->sensea_func() ? 0x10 : 0x00;
cpustate->SR |= cpustate->senseb_func() ? 0x20 : 0x00;
cpustate->AC = cpustate->SR;
m_icount -= 5;
m_SR &= 0xcf; // clear SA and SB flags
m_SR |= m_sensea_func() ? 0x10 : 0x00;
m_SR |= m_senseb_func() ? 0x20 : 0x00;
m_AC = m_SR;
break;
case 0x07: // CAS
cpustate->icount -= 6;
cpustate->SR = cpustate->AC;
cpustate->flag_out_func(0, cpustate->SR & 0x07);
m_icount -= 6;
m_SR = m_AC;
m_flag_out_func(m_SR & 0x07);
break;
case 0x08: // NOP
cpustate->icount -= 5;
m_icount -= 5;
break;
// Others are illegal
default : cpustate->icount -= 1;
illegal (cpustate,opcode);
default : m_icount -= 1;
illegal (opcode);
break;
}
}
@ -457,80 +457,71 @@ static void execute_one(scmp_state *cpustate, int opcode)
/***************************************************************************
COMMON EXECUTION
***************************************************************************/
static void take_interrupt(scmp_state *cpustate)
void scmp_device::take_interrupt()
{
UINT16 tmp = ADD12(cpustate->PC.w.l,-1); // We fix PC so at return it goes to current location
cpustate->SR &= 0xf7; // clear IE flag
UINT16 tmp = ADD12(m_PC.w.l,-1); // We fix PC so at return it goes to current location
m_SR &= 0xf7; // clear IE flag
cpustate->icount -= 8; // assumption
m_icount -= 8; // assumption
// do XPPC 3
cpustate->PC.w.l = GET_PTR_REG(cpustate,3)->w.l;
GET_PTR_REG(cpustate,3)->w.l = tmp;
m_PC.w.l = GET_PTR_REG(3)->w.l;
GET_PTR_REG(3)->w.l = tmp;
// After exchange CPU increment PC
cpustate->PC.w.l = ADD12(cpustate->PC.w.l,1);
m_PC.w.l = ADD12(m_PC.w.l,1);
}
static CPU_EXECUTE( scmp )
void scmp_device::execute_run()
{
scmp_state *cpustate = get_safe_token(device);
do
{
if ((cpustate->SR & 0x08) && (cpustate->sensea_func())) {
take_interrupt(cpustate);
if ((m_SR & 0x08) && (m_sensea_func())) {
take_interrupt();
}
debugger_instruction_hook(device, cpustate->PC.d);
execute_one(cpustate, ROP(cpustate));
debugger_instruction_hook(this, m_PC.d);
execute_one(ROP());
} while (cpustate->icount > 0);
} while (m_icount > 0);
}
/***************************************************************************
CORE INITIALIZATION
***************************************************************************/
static CPU_INIT( scmp )
void scmp_device::device_start()
{
scmp_state *cpustate = get_safe_token(device);
if (device->static_config() != NULL)
cpustate->config = *(scmp_config *)device->static_config();
/* set up the state table */
{
device_state_interface *state;
device->interface(state);
state->state_add(SCMP_PC, "PC", cpustate->PC.w.l);
state->state_add(STATE_GENPC, "GENPC", cpustate->PC.w.l).noshow();
state->state_add(STATE_GENFLAGS, "GENFLAGS", cpustate->SR).noshow().formatstr("%8s");
state->state_add(SCMP_P1, "P1", cpustate->P1.w.l);
state->state_add(SCMP_P2, "P2", cpustate->P2.w.l);
state->state_add(SCMP_P3, "P3", cpustate->P3.w.l);
state->state_add(SCMP_AC, "AC", cpustate->AC);
state->state_add(SCMP_ER, "ER", cpustate->ER);
state->state_add(SCMP_SR, "SR", cpustate->SR);
state_add(SCMP_PC, "PC", m_PC.w.l);
state_add(STATE_GENPC, "GENPC", m_PC.w.l).noshow();
state_add(STATE_GENFLAGS, "GENFLAGS", m_SR).noshow().formatstr("%8s");
state_add(SCMP_P1, "P1", m_P1.w.l);
state_add(SCMP_P2, "P2", m_P2.w.l);
state_add(SCMP_P3, "P3", m_P3.w.l);
state_add(SCMP_AC, "AC", m_AC);
state_add(SCMP_ER, "ER", m_ER);
state_add(SCMP_SR, "SR", m_SR);
}
cpustate->device = device;
cpustate->program = &device->space(AS_PROGRAM);
cpustate->direct = &cpustate->program->direct();
m_program = &space(AS_PROGRAM);
m_direct = &m_program->direct();
/* resolve callbacks */
cpustate->flag_out_func.resolve(cpustate->config.flag_out_func, *device);
cpustate->sout_func.resolve(cpustate->config.sout_func, *device);
cpustate->sin_func.resolve(cpustate->config.sin_func, *device);
cpustate->sensea_func.resolve(cpustate->config.sensea_func, *device);
cpustate->senseb_func.resolve(cpustate->config.senseb_func, *device);
cpustate->halt_func.resolve(cpustate->config.halt_func, *device);
m_flag_out_func.resolve_safe();
m_sout_func.resolve_safe();
m_sin_func.resolve_safe(0);
m_sensea_func.resolve_safe(0);
m_senseb_func.resolve_safe(0);
m_halt_func.resolve_safe();
device->save_item(NAME(cpustate->PC));
device->save_item(NAME(cpustate->P1));
device->save_item(NAME(cpustate->P2));
device->save_item(NAME(cpustate->P3));
device->save_item(NAME(cpustate->AC));
device->save_item(NAME(cpustate->ER));
device->save_item(NAME(cpustate->SR));
save_item(NAME(m_PC));
save_item(NAME(m_P1));
save_item(NAME(m_P2));
save_item(NAME(m_P3));
save_item(NAME(m_AC));
save_item(NAME(m_ER));
save_item(NAME(m_SR));
m_icountptr = &m_icount;
}
@ -539,17 +530,15 @@ static CPU_INIT( scmp )
COMMON RESET
***************************************************************************/
static CPU_RESET( scmp )
void scmp_device::device_reset()
{
scmp_state *cpustate = get_safe_token(device);
cpustate->PC.d = 0;
cpustate->P1.d = 0;
cpustate->P2.d = 0;
cpustate->P3.d = 0;
cpustate->AC = 0;
cpustate->ER = 0;
cpustate->SR = 0;
m_PC.d = 0;
m_P1.d = 0;
m_P2.d = 0;
m_P3.d = 0;
m_AC = 0;
m_ER = 0;
m_SR = 0;
}
@ -558,114 +547,21 @@ static CPU_RESET( scmp )
COMMON STATE IMPORT/EXPORT
***************************************************************************/
static CPU_IMPORT_STATE( scmp )
void scmp_device::state_string_export(const device_state_entry &entry, astring &string)
{
}
static CPU_EXPORT_STATE( scmp )
{
}
static CPU_EXPORT_STRING( scmp )
{
scmp_state *cpustate = get_safe_token(device);
switch (entry.index())
{
case STATE_GENFLAGS:
string.printf("%c%c%c%c%c%c%c%c",
(cpustate->SR & 0x80) ? 'C' : '.',
(cpustate->SR & 0x40) ? 'V' : '.',
(cpustate->SR & 0x20) ? 'B' : '.',
(cpustate->SR & 0x10) ? 'A' : '.',
(cpustate->SR & 0x08) ? 'I' : '.',
(cpustate->SR & 0x04) ? '2' : '.',
(cpustate->SR & 0x02) ? '1' : '.',
(cpustate->SR & 0x01) ? '0' : '.');
(m_SR & 0x80) ? 'C' : '.',
(m_SR & 0x40) ? 'V' : '.',
(m_SR & 0x20) ? 'B' : '.',
(m_SR & 0x10) ? 'A' : '.',
(m_SR & 0x08) ? 'I' : '.',
(m_SR & 0x04) ? '2' : '.',
(m_SR & 0x02) ? '1' : '.',
(m_SR & 0x01) ? '0' : '.');
break;
}
}
/***************************************************************************
COMMON SET INFO
***************************************************************************/
static CPU_SET_INFO( scmp )
{
}
/***************************************************************************
SCMP GET INFO
***************************************************************************/
CPU_GET_INFO( scmp )
{
scmp_state *cpustate = (device != NULL && device->token() != NULL) ? get_safe_token(device) : NULL;
switch (state)
{
/* --- the following bits of info are returned as 64-bit signed integers --- */
case CPUINFO_INT_CONTEXT_SIZE: info->i = sizeof(scmp_state); break;
case CPUINFO_INT_INPUT_LINES: info->i = 0; break;
case CPUINFO_INT_DEFAULT_IRQ_VECTOR: info->i = 0; break;
case CPUINFO_INT_ENDIANNESS: info->i = ENDIANNESS_LITTLE; break;
case CPUINFO_INT_CLOCK_MULTIPLIER: info->i = 1; break;
case CPUINFO_INT_CLOCK_DIVIDER: info->i = 1; break;
case CPUINFO_INT_MIN_INSTRUCTION_BYTES: info->i = 1; break;
case CPUINFO_INT_MAX_INSTRUCTION_BYTES: info->i = 2; break;
case CPUINFO_INT_MIN_CYCLES: info->i = 5; break;
case CPUINFO_INT_MAX_CYCLES: info->i = 131593; break; // DLY instruction max time
case CPUINFO_INT_DATABUS_WIDTH + AS_PROGRAM: info->i = 8; break;
case CPUINFO_INT_ADDRBUS_WIDTH + AS_PROGRAM: info->i = 16; break;
case CPUINFO_INT_ADDRBUS_SHIFT + AS_PROGRAM: info->i = 0; break;
case CPUINFO_INT_DATABUS_WIDTH + AS_DATA: info->i = 0; break;
case CPUINFO_INT_ADDRBUS_WIDTH + AS_DATA: info->i = 0; break;
case CPUINFO_INT_ADDRBUS_SHIFT + AS_DATA: info->i = 0; break;
case CPUINFO_INT_DATABUS_WIDTH + AS_IO: info->i = 0; break;
case CPUINFO_INT_ADDRBUS_WIDTH + AS_IO: info->i = 0; break;
case CPUINFO_INT_ADDRBUS_SHIFT + AS_IO: info->i = 0; break;
/* --- the following bits of info are returned as pointers to functions --- */
case CPUINFO_FCT_SET_INFO: info->setinfo = CPU_SET_INFO_NAME(scmp); break;
case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(scmp); break;
case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(scmp); break;
case CPUINFO_FCT_EXECUTE: info->execute = CPU_EXECUTE_NAME(scmp); break;
case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(scmp); break;
case CPUINFO_FCT_IMPORT_STATE: info->import_state = CPU_IMPORT_STATE_NAME(scmp); break;
case CPUINFO_FCT_EXPORT_STATE: info->export_state = CPU_EXPORT_STATE_NAME(scmp); break;
case CPUINFO_FCT_EXPORT_STRING: info->export_string = CPU_EXPORT_STRING_NAME(scmp); break;
/* --- the following bits of info are returned as pointers --- */
case CPUINFO_PTR_INSTRUCTION_COUNTER: info->icount = &cpustate->icount; break;
/* --- the following bits of info are returned as NULL-terminated strings --- */
case CPUINFO_STR_NAME: strcpy(info->s, "INS 8050 SC/MP"); break;
case CPUINFO_STR_SHORTNAME: strcpy(info->s, "ins8050"); break;
case CPUINFO_STR_FAMILY: strcpy(info->s, "National Semiconductor SC/MP"); break;
case CPUINFO_STR_VERSION: strcpy(info->s, "1.0"); break;
case CPUINFO_STR_SOURCE_FILE: strcpy(info->s, __FILE__); break;
case CPUINFO_STR_CREDITS: strcpy(info->s, "Copyright Miodrag Milanovic"); break;
}
}
/**************************************************************************
* CPU-specific set_info
**************************************************************************/
CPU_GET_INFO( ins8060 )
{
switch (state)
{
/* --- the following bits of info are returned as pointers to data or functions --- */
case CPUINFO_INT_CLOCK_DIVIDER: info->i = 2; break;
/* --- the following bits of info are returned as NULL-terminated strings --- */
case CPUINFO_STR_NAME: strcpy(info->s, "INS 8060 SC/MP II"); break;
case CPUINFO_STR_SHORTNAME: strcpy(info->s, "ins8060"); break;
default: CPU_GET_INFO_CALL(scmp); break;
}
}
DEFINE_LEGACY_CPU_DEVICE(SCMP, scmp);
DEFINE_LEGACY_CPU_DEVICE(INS8060, ins8060);

View File

@ -16,28 +16,105 @@ enum
SCMP_GENPCBASE = STATE_GENPCBASE
};
/***************************************************************************
TYPE DEFINITIONS
***************************************************************************/
struct scmp_config
#define MCFG_SCMP_CONFIG(_flag_out_devcb, _sout_devcb, _sin_devcb, _sensea_devcb, _senseb_devcb, _halt_devcb) \
scmp_device::set_flag_out_cb(*device, DEVCB2_##_flag_out_devcb); \
scmp_device::set_sout_cb(*device, DEVCB2_##_sout_devcb); \
scmp_device::set_sin_cb(*device, DEVCB2_##_sin_devcb); \
scmp_device::set_sensea_cb(*device, DEVCB2_##_sensea_devcb); \
scmp_device::set_senseb_cb(*device, DEVCB2_##_senseb_devcb); \
scmp_device::set_halt_cb(*device, DEVCB2_##_halt_devcb);
class scmp_device : public cpu_device
{
devcb_write8 flag_out_func;
devcb_write_line sout_func;
devcb_read_line sin_func;
devcb_read_line sensea_func;
devcb_read_line senseb_func;
devcb_write_line halt_func;
public:
// construction/destruction
scmp_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
scmp_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source);
// static configuration helpers
template<class _Object> static devcb2_base &set_flag_out_cb(device_t &device, _Object object) { return downcast<scmp_device &>(device).m_flag_out_func.set_callback(object); }
template<class _Object> static devcb2_base &set_sout_cb(device_t &device, _Object object) { return downcast<scmp_device &>(device).m_sout_func.set_callback(object); }
template<class _Object> static devcb2_base &set_sin_cb(device_t &device, _Object object) { return downcast<scmp_device &>(device).m_sin_func.set_callback(object); }
template<class _Object> static devcb2_base &set_sensea_cb(device_t &device, _Object object) { return downcast<scmp_device &>(device).m_sensea_func.set_callback(object); }
template<class _Object> static devcb2_base &set_senseb_cb(device_t &device, _Object object) { return downcast<scmp_device &>(device).m_senseb_func.set_callback(object); }
template<class _Object> static devcb2_base &set_halt_cb(device_t &device, _Object object) { return downcast<scmp_device &>(device).m_halt_func.set_callback(object); }
protected:
// device-level overrides
virtual void device_start();
virtual void device_reset();
// device_execute_interface overrides
virtual UINT32 execute_min_cycles() const { return 5; }
virtual UINT32 execute_max_cycles() const { return 131593; }
virtual UINT32 execute_input_lines() const { return 0; }
virtual void execute_run();
// device_memory_interface overrides
virtual const address_space_config *memory_space_config(address_spacenum spacenum = AS_0) const { return (spacenum == AS_PROGRAM) ? &m_program_config : NULL; }
// device_state_interface overrides
void state_string_export(const device_state_entry &entry, astring &string);
// device_disasm_interface overrides
virtual UINT32 disasm_min_opcode_bytes() const { return 1; }
virtual UINT32 disasm_max_opcode_bytes() const { return 2; }
virtual offs_t disasm_disassemble(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram, UINT32 options);
private:
address_space_config m_program_config;
PAIR m_PC;
PAIR m_P1;
PAIR m_P2;
PAIR m_P3;
UINT8 m_AC;
UINT8 m_ER;
UINT8 m_SR;
address_space *m_program;
direct_read_data *m_direct;
int m_icount;
devcb2_write8 m_flag_out_func;
devcb2_write_line m_sout_func;
devcb2_read_line m_sin_func;
devcb2_read_line m_sensea_func;
devcb2_read_line m_senseb_func;
devcb2_write_line m_halt_func;
inline UINT16 ADD12(UINT16 addr, INT8 val);
inline UINT8 ROP();
inline UINT8 ARG();
inline UINT8 RM(UINT32 a);
inline void WM(UINT32 a, UINT8 v);
inline void illegal(UINT8 opcode);
inline PAIR *GET_PTR_REG(int num);
inline void BIN_ADD(UINT8 val);
inline void DEC_ADD(UINT8 val);
inline UINT16 GET_ADDR(UINT8 code);
void execute_one(int opcode);
void take_interrupt();
};
#define SCMP_CONFIG(name) const scmp_config (name) =
/***************************************************************************
FUNCTION PROTOTYPES
***************************************************************************/
DECLARE_LEGACY_CPU_DEVICE(SCMP, scmp);
class ins8060_device : public scmp_device
{
public:
// construction/destruction
ins8060_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
CPU_DISASSEMBLE( scmp );
protected:
virtual UINT64 execute_clocks_to_cycles(UINT64 clocks) const { return (clocks + 2 - 1) / 2; }
virtual UINT64 execute_cycles_to_clocks(UINT64 cycles) const { return (cycles * 2); }
};
extern const device_type SCMP;
extern const device_type INS8060;
DECLARE_LEGACY_CPU_DEVICE(INS8060, ins8060);
#endif