mirror of
https://github.com/holub/mame
synced 2025-10-06 09:00:04 +03:00

existing modern devices and the legacy wrappers to work in this environment. This in general greatly simplifies writing a modern device. [Aaron Giles] General notes: * some more cleanup probably needs to happen behind this change, but I needed to get it in before the next device modernization or import from MESS :) * new template function device_creator which automatically defines the static function that creates the device; use this instead of creating a static_alloc_device_config function * added device_stop() method which is called at around the time the previous device_t's destructor was called; if you auto_free anything, do it here because the machine is gone when the destructor is called * changed the static_set_* calls to pass a device_t & instead of a device_config * * for many devices, the static config structure member names over- lapped the device's names for devcb_* functions; in these cases the members in the interface were renamed to have a _cb suffix * changed the driver_enumerator to only cache 100 machine_configs because caching them all took a ton of memory; fortunately this implementation detail is completely hidden behind the driver_enumerator interface * got rid of the macros for creating derived classes; doing it manually is now clean enough that it isn't worth hiding the details in a macro
671 lines
20 KiB
C
671 lines
20 KiB
C
/*****************************************************************************
|
|
*
|
|
* scmp.c
|
|
*
|
|
* National Semiconductor SC/MP CPU Disassembly
|
|
*
|
|
* Initial version by Miodrag Milanovic
|
|
*
|
|
*****************************************************************************/
|
|
|
|
#include "emu.h"
|
|
#include "debugger.h"
|
|
#include "scmp.h"
|
|
|
|
#define VERBOSE 0
|
|
|
|
#define LOG(x) do { if (VERBOSE) logerror x; } while (0)
|
|
|
|
/***************************************************************************
|
|
TYPE DEFINITIONS
|
|
***************************************************************************/
|
|
|
|
typedef struct _scmp_state scmp_state;
|
|
struct _scmp_state
|
|
{
|
|
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)
|
|
{
|
|
return ((addr + val) & 0x0fff) | (addr & 0xf000);
|
|
}
|
|
|
|
INLINE UINT8 ROP(scmp_state *cpustate)
|
|
{
|
|
UINT16 pc = cpustate->PC.w.l;
|
|
cpustate->PC.w.l = ADD12(cpustate->PC.w.l,1);
|
|
return cpustate->direct->read_decrypted_byte( pc);
|
|
}
|
|
|
|
INLINE UINT8 ARG(scmp_state *cpustate)
|
|
{
|
|
UINT16 pc = cpustate->PC.w.l;
|
|
cpustate->PC.w.l = ADD12(cpustate->PC.w.l,1);
|
|
return cpustate->direct->read_raw_byte(pc);
|
|
}
|
|
|
|
INLINE UINT8 RM(scmp_state *cpustate,UINT32 a)
|
|
{
|
|
return cpustate->program->read_byte(a);
|
|
}
|
|
|
|
INLINE void WM(scmp_state *cpustate,UINT32 a, UINT8 v)
|
|
{
|
|
cpustate->program->write_byte(a, v);
|
|
}
|
|
|
|
INLINE void illegal(scmp_state *cpustate,UINT8 opcode)
|
|
{
|
|
#if VERBOSE
|
|
UINT16 pc = cpustate->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)
|
|
{
|
|
switch(num) {
|
|
case 1: return &cpustate->P1;
|
|
case 2: return &cpustate->P2;
|
|
case 3: return &cpustate->P3;
|
|
default :
|
|
return &cpustate->PC;
|
|
}
|
|
}
|
|
|
|
INLINE void BIN_ADD(scmp_state *cpustate, 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;
|
|
|
|
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;
|
|
}
|
|
|
|
INLINE void DEC_ADD(scmp_state *cpustate, UINT8 val)
|
|
{
|
|
UINT16 tmp = cpustate->AC + val + ((cpustate->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;
|
|
}
|
|
|
|
INLINE UINT16 GET_ADDR(scmp_state *cpustate, UINT8 code)
|
|
{
|
|
UINT16 addr = 0;
|
|
INT8 offset = 0;
|
|
UINT16 retVal = 0;
|
|
UINT16 ptr = GET_PTR_REG(cpustate,code & 0x03)->w.l;
|
|
|
|
UINT8 arg = ARG(cpustate);
|
|
if (arg == 0x80) {
|
|
offset = cpustate->ER;
|
|
} else {
|
|
if (arg & 0x80) {
|
|
offset = (INT8)arg;
|
|
} else {
|
|
offset = arg;
|
|
}
|
|
}
|
|
|
|
addr = ADD12(ptr,offset);
|
|
|
|
if (code & 0x04) {
|
|
if (code & 0x03) {
|
|
// Auto-indexed
|
|
if (offset < 0) {
|
|
// pre decrement
|
|
GET_PTR_REG(cpustate,code & 0x03)->w.l = addr;
|
|
retVal = addr;
|
|
} else {
|
|
// post increment
|
|
retVal = ptr;
|
|
GET_PTR_REG(cpustate,code & 0x03)->w.l = addr;
|
|
}
|
|
} else {
|
|
// Immediate
|
|
}
|
|
} else {
|
|
// Indexed
|
|
retVal = addr;
|
|
}
|
|
return retVal;
|
|
}
|
|
|
|
static void execute_one(scmp_state *cpustate, int opcode)
|
|
{
|
|
UINT8 tmp;
|
|
UINT8 ptr = opcode & 3;
|
|
if (BIT(opcode,7)) {
|
|
// two bytes instructions
|
|
switch (opcode)
|
|
{
|
|
// Memory Reference Instructions
|
|
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));
|
|
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);
|
|
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));
|
|
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));
|
|
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));
|
|
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)));
|
|
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)));
|
|
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)));
|
|
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);
|
|
}
|
|
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);
|
|
}
|
|
break;
|
|
// Immediate Instructions
|
|
case 0xc4 : // LDI
|
|
cpustate->icount -= 10;
|
|
cpustate->AC = ARG(cpustate);
|
|
break;
|
|
case 0xd4 : // ANI
|
|
cpustate->icount -= 10;
|
|
cpustate->AC &= ARG(cpustate);
|
|
break;
|
|
case 0xdc : // ORI
|
|
cpustate->icount -= 10;
|
|
cpustate->AC |= ARG(cpustate);
|
|
break;
|
|
case 0xe4 : // XRI
|
|
cpustate->icount -= 10;
|
|
cpustate->AC ^= ARG(cpustate);
|
|
break;
|
|
case 0xec : // DAI
|
|
cpustate->icount -= 15;
|
|
DEC_ADD(cpustate,ARG(cpustate));
|
|
break;
|
|
case 0xf4 : // ADI
|
|
cpustate->icount -= 11;
|
|
BIN_ADD(cpustate,ARG(cpustate));
|
|
break;
|
|
case 0xfc : // CAI
|
|
cpustate->icount -= 12;
|
|
BIN_ADD(cpustate,~ARG(cpustate));
|
|
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));
|
|
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;
|
|
}
|
|
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;
|
|
}
|
|
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;
|
|
}
|
|
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;
|
|
break;
|
|
// Others are illegal
|
|
default : cpustate->icount -= 1;
|
|
illegal (cpustate,opcode);
|
|
break;
|
|
}
|
|
} else {
|
|
// one byte instructions
|
|
switch (opcode)
|
|
{
|
|
// Extension Register Instructions
|
|
case 0x40: // LDE
|
|
cpustate->icount -= 6;
|
|
cpustate->AC = cpustate->ER;
|
|
break;
|
|
case 0x01: // XAE
|
|
cpustate->icount -= 7;
|
|
tmp = cpustate->AC;
|
|
cpustate->AC = cpustate->ER;
|
|
cpustate->ER = tmp;
|
|
break;
|
|
case 0x50: // ANE
|
|
cpustate->icount -= 6;
|
|
cpustate->AC &= cpustate->ER;
|
|
break;
|
|
case 0x58: // ORE
|
|
cpustate->icount -= 6;
|
|
cpustate->AC |= cpustate->ER;
|
|
break;
|
|
case 0x60: // XRE
|
|
cpustate->icount -= 6;
|
|
cpustate->AC ^= cpustate->ER;
|
|
break;
|
|
case 0x68: // DAE
|
|
cpustate->icount -= 11;
|
|
DEC_ADD(cpustate,cpustate->ER);
|
|
break;
|
|
case 0x70: // ADE
|
|
cpustate->icount -= 7;
|
|
BIN_ADD(cpustate,cpustate->ER);
|
|
break;
|
|
case 0x78: // CAE
|
|
cpustate->icount -= 8;
|
|
BIN_ADD(cpustate,~cpustate->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;
|
|
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;
|
|
break;
|
|
case 0x3c: case 0x3d :case 0x3e: case 0x3f:
|
|
// XPPC
|
|
{
|
|
UINT16 tmp = 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 = tmp;
|
|
// After exchange CPU increment PC
|
|
cpustate->PC.w.l = ADD12(cpustate->PC.w.l,1);
|
|
}
|
|
break;
|
|
// Shift, Rotate, Serial I/O Instructions
|
|
case 0x19: // SIO
|
|
cpustate->icount -= 5;
|
|
devcb_call_write_line(&cpustate->sout_func, cpustate->ER & 0x01);
|
|
cpustate->ER >>= 1;
|
|
cpustate->ER |= devcb_call_read_line(&cpustate->sin_func) ? 0x80 : 0x00;
|
|
break;
|
|
case 0x1c: // SR
|
|
cpustate->icount -= 5;
|
|
cpustate->AC >>= 1;
|
|
break;
|
|
case 0x1d: // SRL
|
|
cpustate->icount -= 5;
|
|
cpustate->AC >>= 1;
|
|
cpustate->AC |= cpustate->SR & 0x80; // add C/L flag
|
|
break;
|
|
case 0x1e: // RR
|
|
cpustate->icount -= 5;
|
|
cpustate->AC = (cpustate->AC >> 1) | ((cpustate->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;
|
|
break;
|
|
// Single Byte Miscellaneous Instructions
|
|
case 0x00: // HALT
|
|
cpustate->icount -= 8;
|
|
devcb_call_write_line(&cpustate->halt_func, 1);
|
|
devcb_call_write_line(&cpustate->halt_func, 0);
|
|
break;
|
|
case 0x02: // CCL
|
|
cpustate->icount -= 5;
|
|
cpustate->SR &= 0x7f;
|
|
break;
|
|
case 0x03: // SCL
|
|
cpustate->icount -= 5;
|
|
cpustate->SR |= 0x80;
|
|
break;
|
|
case 0x04: // DINT
|
|
cpustate->icount -= 6;
|
|
cpustate->SR &= 0xf7;
|
|
break;
|
|
case 0x05: // IEN
|
|
cpustate->icount -= 6;
|
|
cpustate->SR |= 0x08;
|
|
break;
|
|
case 0x06: // CSA
|
|
cpustate->icount -= 5;
|
|
cpustate->SR &= 0xcf; // clear SA and SB flags
|
|
cpustate->SR |= devcb_call_read_line(&cpustate->sensea_func) ? 0x10 : 0x00;
|
|
cpustate->SR |= devcb_call_read_line(&cpustate->senseb_func) ? 0x20 : 0x00;
|
|
cpustate->AC = cpustate->SR;
|
|
break;
|
|
case 0x07: // CAS
|
|
cpustate->icount -= 6;
|
|
cpustate->SR = cpustate->AC;
|
|
devcb_call_write8(&cpustate->flag_out_func, 0, cpustate->SR & 0x07);
|
|
break;
|
|
case 0x08: // NOP
|
|
cpustate->icount -= 5;
|
|
break;
|
|
// Others are illegal
|
|
default : cpustate->icount -= 1;
|
|
illegal (cpustate,opcode);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
COMMON EXECUTION
|
|
***************************************************************************/
|
|
static void take_interrupt(scmp_state *cpustate)
|
|
{
|
|
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
|
|
|
|
cpustate->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;
|
|
// After exchange CPU increment PC
|
|
cpustate->PC.w.l = ADD12(cpustate->PC.w.l,1);
|
|
}
|
|
|
|
static CPU_EXECUTE( scmp )
|
|
{
|
|
scmp_state *cpustate = get_safe_token(device);
|
|
|
|
do
|
|
{
|
|
if ((cpustate->SR & 0x08) && (devcb_call_read_line(&cpustate->sensea_func))) {
|
|
take_interrupt(cpustate);
|
|
}
|
|
debugger_instruction_hook(device, cpustate->PC.d);
|
|
execute_one(cpustate, ROP(cpustate));
|
|
|
|
} while (cpustate->icount > 0);
|
|
}
|
|
|
|
/***************************************************************************
|
|
CORE INITIALIZATION
|
|
***************************************************************************/
|
|
|
|
static CPU_INIT( scmp )
|
|
{
|
|
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);
|
|
}
|
|
|
|
cpustate->device = device;
|
|
|
|
cpustate->program = device->space(AS_PROGRAM);
|
|
cpustate->direct = &cpustate->program->direct();
|
|
|
|
/* resolve callbacks */
|
|
devcb_resolve_write8(&cpustate->flag_out_func, &cpustate->config.flag_out_func, device);
|
|
devcb_resolve_write_line(&cpustate->sout_func, &cpustate->config.sout_func, device);
|
|
devcb_resolve_read_line(&cpustate->sin_func, &cpustate->config.sin_func, device);
|
|
devcb_resolve_read_line(&cpustate->sensea_func, &cpustate->config.sensea_func, device);
|
|
devcb_resolve_read_line(&cpustate->senseb_func, &cpustate->config.senseb_func, device);
|
|
devcb_resolve_write_line(&cpustate->halt_func, &cpustate->config.halt_func, device);
|
|
|
|
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));
|
|
}
|
|
|
|
|
|
|
|
/***************************************************************************
|
|
COMMON RESET
|
|
***************************************************************************/
|
|
|
|
static CPU_RESET( scmp )
|
|
{
|
|
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;
|
|
}
|
|
|
|
|
|
|
|
/***************************************************************************
|
|
COMMON STATE IMPORT/EXPORT
|
|
***************************************************************************/
|
|
|
|
static CPU_IMPORT_STATE( scmp )
|
|
{
|
|
}
|
|
|
|
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' : '.');
|
|
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 DEVINFO_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 DEVINFO_INT_DATABUS_WIDTH + AS_PROGRAM: info->i = 8; break;
|
|
case DEVINFO_INT_ADDRBUS_WIDTH + AS_PROGRAM: info->i = 16; break;
|
|
case DEVINFO_INT_ADDRBUS_SHIFT + AS_PROGRAM: info->i = 0; break;
|
|
|
|
case DEVINFO_INT_DATABUS_WIDTH + AS_DATA: info->i = 0; break;
|
|
case DEVINFO_INT_ADDRBUS_WIDTH + AS_DATA: info->i = 0; break;
|
|
case DEVINFO_INT_ADDRBUS_SHIFT + AS_DATA: info->i = 0; break;
|
|
|
|
case DEVINFO_INT_DATABUS_WIDTH + AS_IO: info->i = 0; break;
|
|
case DEVINFO_INT_ADDRBUS_WIDTH + AS_IO: info->i = 0; break;
|
|
case DEVINFO_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 DEVINFO_STR_NAME: strcpy(info->s, "INS 8050 SC/MP"); break;
|
|
case DEVINFO_STR_FAMILY: strcpy(info->s, "National Semiconductor SC/MP"); break;
|
|
case DEVINFO_STR_VERSION: strcpy(info->s, "1.0"); break;
|
|
case DEVINFO_STR_SOURCE_FILE: strcpy(info->s, __FILE__); break;
|
|
case DEVINFO_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 DEVINFO_STR_NAME: strcpy(info->s, "INS 8060 SC/MP II"); break;
|
|
|
|
default: CPU_GET_INFO_CALL(scmp); break;
|
|
}
|
|
}
|
|
|
|
DEFINE_LEGACY_CPU_DEVICE(SCMP, scmp);
|
|
DEFINE_LEGACY_CPU_DEVICE(INS8060, ins8060);
|