Added Intel 8008 and National Semiconductor SC/MP CPU cores
This commit is contained in:
parent
65250dc49c
commit
d98fa09e1f
6
.gitattributes
vendored
6
.gitattributes
vendored
@ -141,6 +141,9 @@ src/emu/cpu/i386/x87ops.c svneol=native#text/plain
|
||||
src/emu/cpu/i4004/4004dasm.c svneol=native#text/plain
|
||||
src/emu/cpu/i4004/i4004.c svneol=native#text/plain
|
||||
src/emu/cpu/i4004/i4004.h svneol=native#text/plain
|
||||
src/emu/cpu/i8008/8008dasm.c svneol=native#text/plain
|
||||
src/emu/cpu/i8008/i8008.c svneol=native#text/plain
|
||||
src/emu/cpu/i8008/i8008.h svneol=native#text/plain
|
||||
src/emu/cpu/i8085/8085dasm.c svneol=native#text/plain
|
||||
src/emu/cpu/i8085/i8085.c svneol=native#text/plain
|
||||
src/emu/cpu/i8085/i8085.h svneol=native#text/plain
|
||||
@ -345,6 +348,9 @@ src/emu/cpu/sc61860/sc61860.h svneol=native#text/plain
|
||||
src/emu/cpu/sc61860/scdasm.c svneol=native#text/plain
|
||||
src/emu/cpu/sc61860/scops.c svneol=native#text/plain
|
||||
src/emu/cpu/sc61860/sctable.c svneol=native#text/plain
|
||||
src/emu/cpu/scmp/scmp.c svneol=native#text/plain
|
||||
src/emu/cpu/scmp/scmp.h svneol=native#text/plain
|
||||
src/emu/cpu/scmp/scmpdasm.c svneol=native#text/plain
|
||||
src/emu/cpu/se3208/se3208.c svneol=native#text/plain
|
||||
src/emu/cpu/se3208/se3208.h svneol=native#text/plain
|
||||
src/emu/cpu/se3208/se3208dis.c svneol=native#text/plain
|
||||
|
@ -544,6 +544,32 @@ $(CPUOBJ)/i4004/i4004.o: $(CPUSRC)/i4004/i4004.c \
|
||||
$(CPUSRC)/i4004/i4004.h
|
||||
|
||||
|
||||
#-------------------------------------------------
|
||||
# Intel 8008
|
||||
#-------------------------------------------------
|
||||
|
||||
ifneq ($(filter I8008,$(CPUS)),)
|
||||
OBJDIRS += $(CPUOBJ)/i8008
|
||||
CPUOBJS += $(CPUOBJ)/i8008/i8008.o
|
||||
DASMOBJS += $(CPUOBJ)/i8008/8008dasm.o
|
||||
endif
|
||||
|
||||
$(CPUOBJ)/i8008/i8008.o: $(CPUSRC)/i8008/i8008.c \
|
||||
$(CPUSRC)/i8008/i8008.h
|
||||
|
||||
#-------------------------------------------------
|
||||
# National Semiconductor SC/MP
|
||||
#-------------------------------------------------
|
||||
|
||||
ifneq ($(filter SCMP,$(CPUS)),)
|
||||
OBJDIRS += $(CPUOBJ)/scmp
|
||||
CPUOBJS += $(CPUOBJ)/scmp/scmp.o
|
||||
DASMOBJS += $(CPUOBJ)/scmp/scmpdasm.o
|
||||
endif
|
||||
|
||||
$(CPUOBJ)/scmp/scmp.o: $(CPUSRC)/scmp/scmp.c \
|
||||
$(CPUSRC)/scmp/scmp.h
|
||||
|
||||
|
||||
#-------------------------------------------------
|
||||
# Intel 8080/8085A
|
||||
|
115
src/emu/cpu/i8008/8008dasm.c
Normal file
115
src/emu/cpu/i8008/8008dasm.c
Normal file
@ -0,0 +1,115 @@
|
||||
/*****************************************************************************
|
||||
*
|
||||
* 8008dasm.c
|
||||
*
|
||||
* Intel 8008 CPU Disassembly
|
||||
*
|
||||
* Initial version by Miodrag Milanovic
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#include "cpuintrf.h"
|
||||
|
||||
#define OP(A) oprom[(A) - PC]
|
||||
#define ARG(A) opram[(A) - PC]
|
||||
|
||||
static char reg[] = { 'a', 'b', 'c', 'd', 'e', 'h', 'l', 'm' };
|
||||
static char flag_names[] = { 'c', 'z', 's', 'p' };
|
||||
|
||||
CPU_DISASSEMBLE( i8008 )
|
||||
{
|
||||
UINT32 flags = 0;
|
||||
unsigned PC = pc;
|
||||
UINT8 op = OP(pc++);
|
||||
switch (op >> 6)
|
||||
{
|
||||
case 0x03: // starting with 11
|
||||
if (op==0xff) {
|
||||
sprintf (buffer,"hlt");
|
||||
} else {
|
||||
sprintf (buffer,"l%c%c",reg[(op >> 3) & 7],reg[op & 7]);
|
||||
}
|
||||
break;
|
||||
case 0x00: // starting with 00
|
||||
switch(op & 7) {
|
||||
case 0 : if(((op >> 3) & 7)==0) {
|
||||
sprintf (buffer,"hlt");
|
||||
} else {
|
||||
if(((op >> 3) & 7)==7) {
|
||||
sprintf (buffer,"illegal");
|
||||
} else {
|
||||
sprintf (buffer,"in%c",reg[(op >> 3) & 7]);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 1 : if(((op >> 3) & 7)==0) {
|
||||
sprintf (buffer,"hlt");
|
||||
} else {
|
||||
if(((op >> 3) & 7)==7) {
|
||||
sprintf (buffer,"illegal");
|
||||
} else {
|
||||
sprintf (buffer,"dc%c",reg[(op >> 3) & 7]);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 2 : {
|
||||
switch((op >> 3) & 7) {
|
||||
case 0 : sprintf (buffer,"rlc"); break;
|
||||
case 1 : sprintf (buffer,"rrc"); break;
|
||||
case 2 : sprintf (buffer,"ral"); break;
|
||||
case 3 : sprintf (buffer,"rar"); break;
|
||||
default : sprintf (buffer,"illegal"); break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 3 : sprintf (buffer,"r%c%c",(BIT(op,5) ? 't' : 'f'),flag_names[(op>>3)&3]); break;
|
||||
case 4 : {
|
||||
switch((op >> 3) & 7) {
|
||||
case 0 : sprintf (buffer,"adi %02x",ARG(pc)); pc++; break;
|
||||
case 1 : sprintf (buffer,"aci %02x",ARG(pc)); pc++; break;
|
||||
case 2 : sprintf (buffer,"sui %02x",ARG(pc)); pc++; break;
|
||||
case 3 : sprintf (buffer,"sbi %02x",ARG(pc)); pc++; break;
|
||||
case 4 : sprintf (buffer,"ndi %02x",ARG(pc)); pc++; break;
|
||||
case 5 : sprintf (buffer,"xri %02x",ARG(pc)); pc++; break;
|
||||
case 6 : sprintf (buffer,"ori %02x",ARG(pc)); pc++; break;
|
||||
case 7 : sprintf (buffer,"cpi %02x",ARG(pc)); pc++; break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 5 : sprintf (buffer,"rst %02x",(op>>3) & 7); break;
|
||||
case 6 : sprintf (buffer,"l%ci %02x",reg[(op >> 3) & 7],ARG(pc)); pc++; break;
|
||||
case 7 : sprintf (buffer,"ret"); break;
|
||||
}
|
||||
break;
|
||||
case 0x01: // starting with 01
|
||||
switch(op & 7) {
|
||||
case 0 : sprintf (buffer,"j%c%c %02x%02x",(BIT(op,5)? 't' : 'f'),flag_names[(op>>3)&3], ARG(pc+1) & 0x3f,ARG(pc)); pc+=2; break;
|
||||
case 2 : sprintf (buffer,"c%c%c %02x%02x",(BIT(op,5)? 't' : 'f'),flag_names[(op>>3)&3], ARG(pc+1) & 0x3f,ARG(pc)); pc+=2; break;
|
||||
case 4 : sprintf (buffer,"jmp %02x%02x",ARG(pc+1) & 0x3f,ARG(pc)); pc+=2; break;
|
||||
case 6 : sprintf (buffer,"cal %02x%02x",ARG(pc+1) & 0x3f,ARG(pc)); pc+=2; break;
|
||||
case 1 :
|
||||
case 3 :
|
||||
case 5 :
|
||||
case 7 : if (((op>>4)&3)==0) {
|
||||
sprintf (buffer,"inp %02x",(op >> 1) & 0x07);
|
||||
} else {
|
||||
sprintf (buffer,"out %02x",(op >> 1) & 0x1f);
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 0x02: // starting with 10
|
||||
switch((op >> 3) & 7) {
|
||||
case 0 : sprintf (buffer,"ad%c",reg[op & 7]); break;
|
||||
case 1 : sprintf (buffer,"ac%c",reg[op & 7]); break;
|
||||
case 2 : sprintf (buffer,"su%c",reg[op & 7]); break;
|
||||
case 3 : sprintf (buffer,"sb%c",reg[op & 7]); break;
|
||||
case 4 : sprintf (buffer,"nd%c",reg[op & 7]); break;
|
||||
case 5 : sprintf (buffer,"xr%c",reg[op & 7]); break;
|
||||
case 6 : sprintf (buffer,"or%c",reg[op & 7]); break;
|
||||
case 7 : sprintf (buffer,"cp%c",reg[op & 7]); break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return (pc - PC) | flags | DASMFLAG_SUPPORTED;
|
||||
}
|
710
src/emu/cpu/i8008/i8008.c
Normal file
710
src/emu/cpu/i8008/i8008.c
Normal file
@ -0,0 +1,710 @@
|
||||
/*****************************************************************************
|
||||
*
|
||||
* i8008.c
|
||||
*
|
||||
* Intel 8008 CPU
|
||||
*
|
||||
* Initial version by Miodrag Milanovic
|
||||
*
|
||||
*****************************************************************************/
|
||||
#include "debugger.h"
|
||||
#include "i8008.h"
|
||||
|
||||
#define VERBOSE 0
|
||||
|
||||
#define LOG(x) do { if (VERBOSE) logerror x; } while (0)
|
||||
|
||||
static UINT8 PARITY[256];
|
||||
|
||||
/***************************************************************************
|
||||
TYPE DEFINITIONS
|
||||
***************************************************************************/
|
||||
|
||||
typedef struct _i8008_state i8008_state;
|
||||
struct _i8008_state
|
||||
{
|
||||
UINT8 A,B,C,D,E,H,L;
|
||||
PAIR PC; // It is in fact one of ADDR regs
|
||||
PAIR ADDR[8]; // Address registers
|
||||
UINT8 CF; // Carry flag
|
||||
UINT8 ZF; // Zero flag
|
||||
UINT8 SF; // Sign flag
|
||||
UINT8 PF; // Parity flag
|
||||
UINT8 HALT;
|
||||
const device_config *device;
|
||||
const address_space *program;
|
||||
const address_space *io;
|
||||
cpu_state_table state;
|
||||
int icount;
|
||||
int pc_pos; // PC possition in ADDR
|
||||
|
||||
cpu_irq_callback irq_callback;
|
||||
UINT8 irq_state;
|
||||
};
|
||||
|
||||
/***************************************************************************
|
||||
MACROS
|
||||
***************************************************************************/
|
||||
#define REG_1 ((opcode >> 3) & 7)
|
||||
#define REG_2 (opcode & 7)
|
||||
#define GET_PC (cpustate->ADDR[cpustate->pc_pos])
|
||||
|
||||
/***************************************************************************
|
||||
CPU STATE DESCRIPTION
|
||||
***************************************************************************/
|
||||
|
||||
#define I8008_STATE_ENTRY(_name, _format, _member, _datamask, _flags) \
|
||||
CPU_STATE_ENTRY(I8008_##_name, #_name, _format, i8008_state, _member, _datamask, ~0, _flags)
|
||||
|
||||
static const cpu_state_entry state_array[] =
|
||||
{
|
||||
I8008_STATE_ENTRY(PC, "%04X", PC.w.l, 0x3fff, 0)
|
||||
I8008_STATE_ENTRY(GENPC,"%04X", PC.w.l, 0x3fff, CPUSTATE_NOSHOW)
|
||||
I8008_STATE_ENTRY(A, "%02X", A, 0xff, 0)
|
||||
I8008_STATE_ENTRY(B, "%02X", B, 0xff, 0)
|
||||
I8008_STATE_ENTRY(C, "%02X", C, 0xff, 0)
|
||||
I8008_STATE_ENTRY(D, "%02X", D, 0xff, 0)
|
||||
I8008_STATE_ENTRY(E, "%02X", E, 0xff, 0)
|
||||
I8008_STATE_ENTRY(H, "%02X", H, 0xff, 0)
|
||||
I8008_STATE_ENTRY(L, "%02X", L, 0xff, 0)
|
||||
I8008_STATE_ENTRY(ADDR1, "%04X", ADDR[0].w.l, 0x0fff, 0)
|
||||
I8008_STATE_ENTRY(ADDR2, "%04X", ADDR[1].w.l, 0x0fff, 0)
|
||||
I8008_STATE_ENTRY(ADDR3, "%04X", ADDR[2].w.l, 0x0fff, 0)
|
||||
I8008_STATE_ENTRY(ADDR4, "%04X", ADDR[3].w.l, 0x0fff, 0)
|
||||
I8008_STATE_ENTRY(ADDR5, "%04X", ADDR[4].w.l, 0x0fff, 0)
|
||||
I8008_STATE_ENTRY(ADDR6, "%04X", ADDR[5].w.l, 0x0fff, 0)
|
||||
I8008_STATE_ENTRY(ADDR7, "%04X", ADDR[6].w.l, 0x0fff, 0)
|
||||
I8008_STATE_ENTRY(ADDR8, "%04X", ADDR[7].w.l, 0x0fff, 0)
|
||||
};
|
||||
|
||||
static const cpu_state_table state_table_template =
|
||||
{
|
||||
NULL, /* pointer to the base of state (offsets are relative to this) */
|
||||
0, /* subtype this table refers to */
|
||||
ARRAY_LENGTH(state_array), /* number of entries */
|
||||
state_array /* array of entries */
|
||||
};
|
||||
|
||||
/***************************************************************************
|
||||
INLINE FUNCTIONS
|
||||
***************************************************************************/
|
||||
|
||||
INLINE i8008_state *get_safe_token(const device_config *device)
|
||||
{
|
||||
assert(device != NULL);
|
||||
assert(device->token != NULL);
|
||||
assert(device->type == CPU);
|
||||
assert(cpu_get_type(device) == CPU_I8008);
|
||||
return (i8008_state *)device->token;
|
||||
}
|
||||
|
||||
INLINE void PUSH_STACK(i8008_state *cpustate)
|
||||
{
|
||||
cpustate->pc_pos = (cpustate->pc_pos + 1) & 7;
|
||||
}
|
||||
|
||||
INLINE void POP_STACK(i8008_state *cpustate)
|
||||
{
|
||||
cpustate->ADDR[cpustate->pc_pos].d = 0;
|
||||
cpustate->pc_pos = (cpustate->pc_pos - 1) & 7;
|
||||
}
|
||||
|
||||
INLINE UINT8 ROP(i8008_state *cpustate)
|
||||
{
|
||||
UINT8 retVal = memory_decrypted_read_byte(cpustate->program, GET_PC.w.l);
|
||||
GET_PC.w.l = (GET_PC.w.l + 1) & 0x3fff;
|
||||
cpustate->PC = GET_PC;
|
||||
return retVal;
|
||||
}
|
||||
|
||||
INLINE UINT8 GET_REG(i8008_state *cpustate,UINT8 reg)
|
||||
{
|
||||
UINT8 retVal;
|
||||
switch(reg) {
|
||||
case 0 : retVal = cpustate->A; break;
|
||||
case 1 : retVal = cpustate->B; break;
|
||||
case 2 : retVal = cpustate->C; break;
|
||||
case 3 : retVal = cpustate->D; break;
|
||||
case 4 : retVal = cpustate->E; break;
|
||||
case 5 : retVal = cpustate->H; break;
|
||||
case 6 : retVal = cpustate->L; break;
|
||||
default: retVal = memory_read_byte_8le(cpustate->program, (cpustate->H << 8) + cpustate->L); break;
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
|
||||
INLINE void SET_REG(i8008_state *cpustate,UINT8 reg, UINT8 val)
|
||||
{
|
||||
switch(reg) {
|
||||
case 0 : cpustate->A = val; break;
|
||||
case 1 : cpustate->B = val; break;
|
||||
case 2 : cpustate->C = val; break;
|
||||
case 3 : cpustate->D = val; break;
|
||||
case 4 : cpustate->E = val; break;
|
||||
case 5 : cpustate->H = val; break;
|
||||
case 6 : cpustate->L = val; break;
|
||||
default: memory_write_byte_8le(cpustate->program, (cpustate->H << 8) + cpustate->L, val); break;
|
||||
}
|
||||
}
|
||||
|
||||
INLINE UINT8 ARG(i8008_state *cpustate)
|
||||
{
|
||||
UINT8 retVal = memory_raw_read_byte(cpustate->program, GET_PC.w.l);
|
||||
GET_PC.w.l = (GET_PC.w.l + 1) & 0x3fff;
|
||||
cpustate->PC = GET_PC;
|
||||
return retVal;
|
||||
}
|
||||
|
||||
INLINE void UPDATE_FLAGS(i8008_state *cpustate,UINT8 val)
|
||||
{
|
||||
cpustate->ZF = (val == 0) ? 1 : 0;
|
||||
cpustate->SF = (val & 0x80) ? 1 : 0;
|
||||
cpustate->PF = PARITY[val];
|
||||
}
|
||||
|
||||
INLINE UINT8 DO_CONDITION(i8008_state *cpustate, UINT8 val)
|
||||
{
|
||||
UINT8 v = (val >> 5) & 1;
|
||||
UINT8 cond = 0;
|
||||
switch((val>> 3) & 0x03) {
|
||||
case 0 :
|
||||
if (cpustate->CF==v) cond = 1;
|
||||
break;
|
||||
case 1 :
|
||||
if (cpustate->ZF==v) cond = 1;
|
||||
break;
|
||||
case 2 :
|
||||
if (cpustate->SF==v) cond = 1;
|
||||
break;
|
||||
case 3 :
|
||||
if (cpustate->PF==v) cond = 1;
|
||||
break;
|
||||
}
|
||||
return cond;
|
||||
}
|
||||
|
||||
INLINE UINT16 GET_ADDR(i8008_state *cpustate)
|
||||
{
|
||||
UINT8 lo = ARG(cpustate);
|
||||
UINT8 hi = ARG(cpustate);
|
||||
return ((hi & 0x3f) << 8) + lo;
|
||||
}
|
||||
|
||||
INLINE void illegal(i8008_state *cpustate,UINT8 opcode)
|
||||
{
|
||||
#if VERBOSE
|
||||
UINT16 pc = cpustate->PC.w.l;
|
||||
LOG(("I8008 illegal instruction %04X $%02X\n", pc, opcode));
|
||||
#endif
|
||||
}
|
||||
|
||||
static void execute_one(i8008_state *cpustate, int opcode)
|
||||
{
|
||||
UINT16 tmp;
|
||||
|
||||
switch (opcode >> 6)
|
||||
{
|
||||
case 0x03: // starting with 11
|
||||
if (opcode==0xff) {
|
||||
// HLT
|
||||
cpustate->icount -= 4;
|
||||
GET_PC.w.l = GET_PC.w.l - 1;
|
||||
cpustate->PC = GET_PC;
|
||||
cpustate->HALT = 1;
|
||||
} else {
|
||||
// Lrr
|
||||
cpustate->icount -= 5;
|
||||
if (REG_1==7) cpustate->icount -= 2;
|
||||
if (REG_2==7) cpustate->icount -= 3;
|
||||
SET_REG(cpustate,REG_1, GET_REG(cpustate,REG_2));
|
||||
}
|
||||
break;
|
||||
case 0x00: // starting with 00
|
||||
switch(opcode & 7) {
|
||||
case 0 : if(((opcode >> 3) & 7)==0) {
|
||||
// HLT
|
||||
cpustate->icount -= 4;
|
||||
GET_PC.w.l = GET_PC.w.l - 1;
|
||||
cpustate->PC = GET_PC;
|
||||
cpustate->HALT = 1;
|
||||
} else {
|
||||
if(((opcode >> 3) & 7)==7) {
|
||||
// ILLEGAL
|
||||
cpustate->icount -= 5;
|
||||
illegal(cpustate,opcode);
|
||||
} else {
|
||||
// INr
|
||||
cpustate->icount -= 5;
|
||||
tmp = GET_REG(cpustate,REG_1) + 1;
|
||||
SET_REG(cpustate,REG_1, tmp & 0xff);
|
||||
UPDATE_FLAGS(cpustate,tmp & 0xff);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 1 : if(((opcode >> 3) & 7)==0) {
|
||||
// HLT
|
||||
cpustate->icount -= 4;
|
||||
GET_PC.w.l = GET_PC.w.l - 1;
|
||||
cpustate->PC = GET_PC;
|
||||
cpustate->HALT = 1;
|
||||
} else {
|
||||
if(((opcode >> 3) & 7)==7) {
|
||||
// ILLEGAL
|
||||
cpustate->icount -= 5;
|
||||
illegal(cpustate,opcode);
|
||||
} else {
|
||||
// DCr
|
||||
cpustate->icount -= 5;
|
||||
tmp = GET_REG(cpustate,REG_1) - 1;
|
||||
SET_REG(cpustate,REG_1, tmp & 0xff);
|
||||
UPDATE_FLAGS(cpustate,tmp & 0xff);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 2 : {
|
||||
// All instuction from this group have same timing
|
||||
cpustate->icount -= 5;
|
||||
switch((opcode >> 3) & 7) {
|
||||
case 0 :
|
||||
// RLC
|
||||
tmp = cpustate->A;
|
||||
cpustate->A = (cpustate->A << 1) | BIT(tmp,7);
|
||||
cpustate->CF = BIT(tmp,7);
|
||||
break;
|
||||
case 1 :
|
||||
// RRC
|
||||
tmp = cpustate->A;
|
||||
cpustate->A = (cpustate->A >> 1) | (BIT(tmp,0) ? 0x80 : 0x00);
|
||||
cpustate->CF = BIT(tmp,0);
|
||||
break;
|
||||
case 2 :
|
||||
// RAL
|
||||
tmp = cpustate->A;
|
||||
cpustate->A = (cpustate->A << 1) | cpustate->CF;
|
||||
cpustate->CF = BIT(tmp,7);
|
||||
break;
|
||||
case 3 :
|
||||
// RAR
|
||||
tmp = cpustate->A;
|
||||
cpustate->A = (cpustate->A >> 1) | (cpustate->CF ? 0x80 : 0x00);
|
||||
cpustate->CF = BIT(tmp,0);
|
||||
break;
|
||||
default :
|
||||
// ILLEGAL
|
||||
illegal(cpustate,opcode);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 3 :
|
||||
// Rcc
|
||||
{
|
||||
cpustate->icount -= 3;
|
||||
if (DO_CONDITION(cpustate,opcode)==1) {
|
||||
cpustate->icount -= 2;
|
||||
POP_STACK(cpustate);
|
||||
cpustate->PC = GET_PC;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 4 : {
|
||||
cpustate->icount -= 8;
|
||||
switch((opcode >> 3) & 7) {
|
||||
case 0 :
|
||||
// ADI
|
||||
tmp = GET_REG(cpustate,0) + ARG(cpustate);
|
||||
SET_REG(cpustate,0,tmp & 0xff);
|
||||
UPDATE_FLAGS(cpustate,tmp & 0xff);
|
||||
cpustate->CF = (tmp >> 8) & 1;
|
||||
break;
|
||||
case 1 :
|
||||
// ACI
|
||||
tmp = GET_REG(cpustate,0) + ARG(cpustate) + cpustate->CF;
|
||||
SET_REG(cpustate,0,tmp & 0xff);
|
||||
UPDATE_FLAGS(cpustate,tmp & 0xff);
|
||||
cpustate->CF = (tmp >> 8) & 1;
|
||||
break;
|
||||
case 2 :
|
||||
// SUI
|
||||
tmp = GET_REG(cpustate,0) - ARG(cpustate);
|
||||
SET_REG(cpustate,0,tmp & 0xff);
|
||||
UPDATE_FLAGS(cpustate,tmp & 0xff);
|
||||
cpustate->CF = (tmp >> 8) & 1;
|
||||
break;
|
||||
case 3 :
|
||||
// SBI
|
||||
tmp = GET_REG(cpustate,0) - ARG(cpustate) - cpustate->CF;
|
||||
SET_REG(cpustate,0,tmp & 0xff);
|
||||
UPDATE_FLAGS(cpustate,tmp & 0xff);
|
||||
cpustate->CF = (tmp >> 8) & 1;
|
||||
break;
|
||||
case 4 :
|
||||
// NDI
|
||||
tmp = GET_REG(cpustate,0) & ARG(cpustate);
|
||||
SET_REG(cpustate,0,tmp & 0xff);
|
||||
UPDATE_FLAGS(cpustate,tmp & 0xff);
|
||||
break;
|
||||
case 5 :
|
||||
// XRI
|
||||
tmp = GET_REG(cpustate,0) ^ ARG(cpustate);
|
||||
SET_REG(cpustate,0,tmp & 0xff);
|
||||
UPDATE_FLAGS(cpustate,tmp & 0xff);
|
||||
break;
|
||||
case 6 :
|
||||
// ORI
|
||||
tmp = GET_REG(cpustate,0) | ARG(cpustate);
|
||||
SET_REG(cpustate,0,tmp & 0xff);
|
||||
UPDATE_FLAGS(cpustate,tmp & 0xff);
|
||||
break;
|
||||
case 7 :
|
||||
// CPI
|
||||
tmp = GET_REG(cpustate,0) - ARG(cpustate);
|
||||
UPDATE_FLAGS(cpustate,tmp & 0xff);
|
||||
cpustate->CF = (tmp >> 8) & 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 5 : // RST
|
||||
cpustate->icount -= 5;
|
||||
PUSH_STACK(cpustate);
|
||||
GET_PC.w.l = opcode & 0x38;
|
||||
cpustate->PC = GET_PC;
|
||||
break;
|
||||
case 6 : // LrI
|
||||
cpustate->icount -= 8;
|
||||
if (REG_1==7) cpustate->icount -= 1; // LMI
|
||||
SET_REG(cpustate,REG_1, ARG(cpustate)); break;
|
||||
case 7 : // RET
|
||||
cpustate->icount -= 5;
|
||||
POP_STACK(cpustate);
|
||||
cpustate->PC = GET_PC;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x01: // starting with 01
|
||||
switch(opcode & 7) {
|
||||
case 0 :
|
||||
// Jcc
|
||||
cpustate->icount -= 9;
|
||||
tmp = GET_ADDR(cpustate);
|
||||
if (DO_CONDITION(cpustate,opcode)==1) {
|
||||
cpustate->icount -= 2;
|
||||
GET_PC.w.l = tmp;
|
||||
cpustate->PC = GET_PC;
|
||||
}
|
||||
break;
|
||||
case 2 :
|
||||
// Ccc
|
||||
cpustate->icount -= 9;
|
||||
tmp = GET_ADDR(cpustate);
|
||||
if (DO_CONDITION(cpustate,opcode)==1) {
|
||||
cpustate->icount -= 2;
|
||||
PUSH_STACK(cpustate);
|
||||
GET_PC.w.l = tmp;
|
||||
cpustate->PC = GET_PC;
|
||||
}
|
||||
break;
|
||||
case 4 :
|
||||
// JMP
|
||||
cpustate->icount -= 11;
|
||||
GET_PC.w.l = GET_ADDR(cpustate);
|
||||
cpustate->PC = GET_PC;
|
||||
break;
|
||||
case 6 :
|
||||
// CAL
|
||||
cpustate->icount -= 11;
|
||||
tmp = GET_ADDR(cpustate);
|
||||
PUSH_STACK(cpustate);
|
||||
GET_PC.w.l = tmp;
|
||||
cpustate->PC = GET_PC;
|
||||
break;
|
||||
default :
|
||||
if (((opcode>>4)&3)==0) {
|
||||
// INP
|
||||
cpustate->icount -= 8;
|
||||
cpustate->A = memory_read_byte_8le(cpustate->io, (opcode >> 1) & 0x1f);
|
||||
} else {
|
||||
// OUT
|
||||
cpustate->icount -= 6;
|
||||
memory_write_byte_8le(cpustate->io, (opcode >> 1) & 0x1f, cpustate->A);
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 0x02: // starting with 10
|
||||
cpustate->icount -= 5;
|
||||
if ((opcode & 7)==7) cpustate->icount -= 3; // operations with memory
|
||||
switch((opcode >> 3) & 7) {
|
||||
case 0 :
|
||||
// ADx
|
||||
tmp = GET_REG(cpustate,0) + GET_REG(cpustate,opcode & 7);
|
||||
SET_REG(cpustate,0,tmp & 0xff);
|
||||
UPDATE_FLAGS(cpustate,tmp & 0xff);
|
||||
cpustate->CF = (tmp >> 8) & 1;
|
||||
break;
|
||||
case 1 :
|
||||
// ACx
|
||||
tmp = GET_REG(cpustate,0) + GET_REG(cpustate,opcode & 7) + cpustate->CF;
|
||||
SET_REG(cpustate,0,tmp & 0xff);
|
||||
UPDATE_FLAGS(cpustate,tmp & 0xff);
|
||||
cpustate->CF = (tmp >> 8) & 1;
|
||||
break;
|
||||
case 2 :
|
||||
// SUx
|
||||
tmp = GET_REG(cpustate,0) - GET_REG(cpustate,opcode & 7);
|
||||
SET_REG(cpustate,0,tmp & 0xff);
|
||||
UPDATE_FLAGS(cpustate,tmp & 0xff);
|
||||
cpustate->CF = (tmp >> 8) & 1;
|
||||
break;
|
||||
case 3 :
|
||||
// SBx
|
||||
tmp = GET_REG(cpustate,0) - GET_REG(cpustate,opcode & 7) - cpustate->CF;
|
||||
SET_REG(cpustate,0,tmp & 0xff);
|
||||
UPDATE_FLAGS(cpustate,tmp & 0xff);
|
||||
cpustate->CF = (tmp >> 8) & 1;
|
||||
break;
|
||||
case 4 :
|
||||
// NDx
|
||||
tmp = GET_REG(cpustate,0) & GET_REG(cpustate,opcode & 7);
|
||||
SET_REG(cpustate,0,tmp & 0xff);
|
||||
UPDATE_FLAGS(cpustate,tmp & 0xff);
|
||||
break;
|
||||
case 5 :
|
||||
// XRx
|
||||
tmp = GET_REG(cpustate,0) ^ GET_REG(cpustate,opcode & 7);
|
||||
SET_REG(cpustate,0,tmp & 0xff);
|
||||
UPDATE_FLAGS(cpustate,tmp & 0xff);
|
||||
break;
|
||||
case 6 :
|
||||
// ORx
|
||||
tmp = GET_REG(cpustate,0) | GET_REG(cpustate,opcode & 7);
|
||||
SET_REG(cpustate,0,tmp & 0xff);
|
||||
UPDATE_FLAGS(cpustate,tmp & 0xff);
|
||||
break;
|
||||
case 7 :
|
||||
// CPx
|
||||
tmp = GET_REG(cpustate,0) - GET_REG(cpustate,opcode & 7);
|
||||
UPDATE_FLAGS(cpustate,tmp & 0xff);
|
||||
cpustate->CF = (tmp >> 8) & 1;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
COMMON EXECUTION
|
||||
***************************************************************************/
|
||||
static void take_interrupt(i8008_state *cpustate)
|
||||
{
|
||||
if (cpustate->HALT) {
|
||||
GET_PC.w.l = (GET_PC.w.l + 1) & 0x3fff;
|
||||
cpustate->PC = GET_PC;
|
||||
cpustate->HALT = 0;
|
||||
}
|
||||
// For now only support one byte operation to be executed
|
||||
execute_one(cpustate,(*cpustate->irq_callback)(cpustate->device, 0));
|
||||
}
|
||||
|
||||
static CPU_EXECUTE( i8008 )
|
||||
{
|
||||
i8008_state *cpustate = get_safe_token(device);
|
||||
|
||||
cpustate->icount = cycles;
|
||||
|
||||
do
|
||||
{
|
||||
if (cpustate->irq_state != CLEAR_LINE) {
|
||||
take_interrupt(cpustate);
|
||||
}
|
||||
debugger_instruction_hook(device, cpustate->PC.d);
|
||||
execute_one(cpustate, ROP(cpustate));
|
||||
|
||||
} while (cpustate->icount > 0);
|
||||
|
||||
return cycles - cpustate->icount;
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
CORE INITIALIZATION
|
||||
***************************************************************************/
|
||||
static void init_tables (void)
|
||||
{
|
||||
int i;
|
||||
UINT8 p;
|
||||
for (i = 0; i < 256; i++)
|
||||
{
|
||||
p = 0;
|
||||
if (BIT(i,0)) p++;
|
||||
if (BIT(i,1)) p++;
|
||||
if (BIT(i,2)) p++;
|
||||
if (BIT(i,3)) p++;
|
||||
if (BIT(i,4)) p++;
|
||||
if (BIT(i,5)) p++;
|
||||
if (BIT(i,6)) p++;
|
||||
if (BIT(i,7)) p++;
|
||||
PARITY[i] = ((p&1) ? 0 : 1);
|
||||
}
|
||||
}
|
||||
|
||||
static CPU_INIT( i8008 )
|
||||
{
|
||||
i8008_state *cpustate = get_safe_token(device);
|
||||
|
||||
/* set up the state table */
|
||||
cpustate->state = state_table_template;
|
||||
cpustate->state.baseptr = cpustate;
|
||||
cpustate->state.subtypemask = 1;
|
||||
|
||||
cpustate->device = device;
|
||||
|
||||
cpustate->program = memory_find_address_space(device, ADDRESS_SPACE_PROGRAM);
|
||||
cpustate->io = memory_find_address_space(device, ADDRESS_SPACE_IO);
|
||||
|
||||
cpustate->irq_callback = irqcallback;
|
||||
|
||||
init_tables();
|
||||
|
||||
state_save_register_device_item(device, 0, cpustate->PC);
|
||||
state_save_register_device_item(device, 0, cpustate->A);
|
||||
state_save_register_device_item(device, 0, cpustate->B);
|
||||
state_save_register_device_item(device, 0, cpustate->C);
|
||||
state_save_register_device_item(device, 0, cpustate->D);
|
||||
state_save_register_device_item(device, 0, cpustate->E);
|
||||
state_save_register_device_item(device, 0, cpustate->H);
|
||||
state_save_register_device_item(device, 0, cpustate->L);
|
||||
state_save_register_device_item(device, 0, cpustate->CF);
|
||||
state_save_register_device_item(device, 0, cpustate->SF);
|
||||
state_save_register_device_item(device, 0, cpustate->ZF);
|
||||
state_save_register_device_item(device, 0, cpustate->PF);
|
||||
state_save_register_device_item(device, 0, cpustate->pc_pos);
|
||||
state_save_register_device_item(device, 0, cpustate->ADDR[0]);
|
||||
state_save_register_device_item(device, 0, cpustate->ADDR[1]);
|
||||
state_save_register_device_item(device, 0, cpustate->ADDR[2]);
|
||||
state_save_register_device_item(device, 0, cpustate->ADDR[3]);
|
||||
state_save_register_device_item(device, 0, cpustate->ADDR[4]);
|
||||
state_save_register_device_item(device, 0, cpustate->ADDR[5]);
|
||||
state_save_register_device_item(device, 0, cpustate->ADDR[6]);
|
||||
state_save_register_device_item(device, 0, cpustate->ADDR[7]);
|
||||
state_save_register_device_item(device, 0, cpustate->HALT);
|
||||
state_save_register_device_item(device, 0, cpustate->irq_state);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
COMMON RESET
|
||||
***************************************************************************/
|
||||
|
||||
static CPU_RESET( i8008 )
|
||||
{
|
||||
i8008_state *cpustate = get_safe_token(device);
|
||||
|
||||
cpustate->CF = cpustate->SF = cpustate->ZF = cpustate->PF = 0;
|
||||
cpustate->A = cpustate->B = cpustate->C = cpustate->D = cpustate->E = cpustate->H = cpustate->L = 0;
|
||||
cpustate->PC.d = 0;
|
||||
cpustate->pc_pos = 0;
|
||||
cpustate->HALT = 0;
|
||||
cpustate->irq_state = CLEAR_LINE;
|
||||
memset(cpustate->ADDR,0,sizeof(cpustate->ADDR));
|
||||
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Set IRQ line state
|
||||
****************************************************************************/
|
||||
static void set_irq_line(i8008_state *cpustate, int irqline, int state)
|
||||
{
|
||||
cpustate->irq_state = state;
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
COMMON STATE IMPORT/EXPORT
|
||||
***************************************************************************/
|
||||
|
||||
static CPU_IMPORT_STATE( i8008 )
|
||||
{
|
||||
}
|
||||
|
||||
static CPU_EXPORT_STATE( i8008 )
|
||||
{
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
COMMON SET INFO
|
||||
***************************************************************************/
|
||||
static CPU_SET_INFO( i8008 )
|
||||
{
|
||||
i8008_state *cpustate = get_safe_token(device);
|
||||
switch (state)
|
||||
{
|
||||
/* --- the following bits of info are set as 64-bit signed integers --- */
|
||||
case CPUINFO_INT_INPUT_STATE + 0: set_irq_line(cpustate, 0, info->i); break;
|
||||
}
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
8008 GET INFO
|
||||
***************************************************************************/
|
||||
|
||||
CPU_GET_INFO( i8008 )
|
||||
{
|
||||
i8008_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(i8008_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 = 3; break;
|
||||
case CPUINFO_INT_MIN_CYCLES: info->i = 8; break;
|
||||
case CPUINFO_INT_MAX_CYCLES: info->i = 16; break;
|
||||
|
||||
case CPUINFO_INT_DATABUS_WIDTH_PROGRAM: info->i = 8; break;
|
||||
case CPUINFO_INT_ADDRBUS_WIDTH_PROGRAM: info->i = 14; break;
|
||||
case CPUINFO_INT_ADDRBUS_SHIFT_PROGRAM: info->i = 0; break;
|
||||
|
||||
case CPUINFO_INT_DATABUS_WIDTH_DATA: info->i = 0; break;
|
||||
case CPUINFO_INT_ADDRBUS_WIDTH_DATA: info->i = 0; break;
|
||||
case CPUINFO_INT_ADDRBUS_SHIFT_DATA: info->i = 0; break;
|
||||
|
||||
case CPUINFO_INT_DATABUS_WIDTH_IO: info->i = 8; break;
|
||||
case CPUINFO_INT_ADDRBUS_WIDTH_IO: info->i = 8; break;
|
||||
case CPUINFO_INT_ADDRBUS_SHIFT_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(i8008); break;
|
||||
case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(i8008); break;
|
||||
case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(i8008); break;
|
||||
case CPUINFO_FCT_EXECUTE: info->execute = CPU_EXECUTE_NAME(i8008); break;
|
||||
case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(i8008); break;
|
||||
case CPUINFO_FCT_IMPORT_STATE: info->import_state = CPU_IMPORT_STATE_NAME(i8008); break;
|
||||
case CPUINFO_FCT_EXPORT_STATE: info->export_state = CPU_EXPORT_STATE_NAME(i8008); break;
|
||||
|
||||
/* --- the following bits of info are returned as pointers --- */
|
||||
case CPUINFO_PTR_INSTRUCTION_COUNTER: info->icount = &cpustate->icount; break;
|
||||
case CPUINFO_PTR_STATE_TABLE: info->state_table = &cpustate->state; break;
|
||||
|
||||
/* --- the following bits of info are returned as NULL-terminated strings --- */
|
||||
case DEVINFO_STR_NAME: strcpy(info->s, "8008"); break;
|
||||
case DEVINFO_STR_FAMILY: strcpy(info->s, "Intel 8008"); 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;
|
||||
|
||||
case CPUINFO_STR_FLAGS:
|
||||
sprintf(info->s, "%c%c%c%c",
|
||||
cpustate->CF ? 'C':'.',
|
||||
cpustate->ZF ? 'Z':'.',
|
||||
cpustate->SF ? 'S':'.',
|
||||
cpustate->PF ? 'P':'.');
|
||||
break;
|
||||
}
|
||||
}
|
33
src/emu/cpu/i8008/i8008.h
Normal file
33
src/emu/cpu/i8008/i8008.h
Normal file
@ -0,0 +1,33 @@
|
||||
#ifndef __I8008_H__
|
||||
#define __I8008_H__
|
||||
|
||||
#include "cpuintrf.h"
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
CONSTANTS
|
||||
***************************************************************************/
|
||||
|
||||
enum
|
||||
{
|
||||
I8008_PC,
|
||||
I8008_A,I8008_B,I8008_C,I8008_D,I8008_E,I8008_H,I8008_L,
|
||||
I8008_ADDR1,I8008_ADDR2,I8008_ADDR3,I8008_ADDR4,I8008_ADDR5,I8008_ADDR6,I8008_ADDR7,I8008_ADDR8,
|
||||
I8008_GENPC = REG_GENPC,
|
||||
I8008_GENSP = REG_GENSP,
|
||||
I8008_GENPCBASE = REG_GENPCBASE
|
||||
};
|
||||
|
||||
/***************************************************************************
|
||||
TYPE DEFINITIONS
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
FUNCTION PROTOTYPES
|
||||
***************************************************************************/
|
||||
|
||||
CPU_GET_INFO( i8008 );
|
||||
#define CPU_I8008 CPU_GET_INFO_NAME( i8008 )
|
||||
|
||||
CPU_DISASSEMBLE( i8008 );
|
||||
#endif
|
663
src/emu/cpu/scmp/scmp.c
Normal file
663
src/emu/cpu/scmp/scmp.c
Normal file
@ -0,0 +1,663 @@
|
||||
/*****************************************************************************
|
||||
*
|
||||
* scmp.c
|
||||
*
|
||||
* National Semiconductor SC/MP CPU Disassembly
|
||||
*
|
||||
* Initial version by Miodrag Milanovic
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#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;
|
||||
|
||||
const device_config *device;
|
||||
const address_space *program;
|
||||
const address_space *io;
|
||||
cpu_state_table state;
|
||||
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
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
CPU STATE DESCRIPTION
|
||||
***************************************************************************/
|
||||
|
||||
#define SCMP_STATE_ENTRY(_name, _format, _member, _datamask, _flags) \
|
||||
CPU_STATE_ENTRY(SCMP_##_name, #_name, _format, scmp_state, _member, _datamask, ~0, _flags)
|
||||
|
||||
static const cpu_state_entry state_array[] =
|
||||
{
|
||||
SCMP_STATE_ENTRY(PC, "%04X", PC.w.l, 0xffff, 0)
|
||||
SCMP_STATE_ENTRY(GENPC,"%04X", PC.w.l, 0xffff, CPUSTATE_NOSHOW)
|
||||
SCMP_STATE_ENTRY(P1, "%04X", P1.w.l, 0xffff, 0)
|
||||
SCMP_STATE_ENTRY(P2, "%04X", P2.w.l, 0xffff, 0)
|
||||
SCMP_STATE_ENTRY(P3, "%04X", P3.w.l, 0xffff, 0)
|
||||
SCMP_STATE_ENTRY(AC, "%02X", AC, 0xff, 0)
|
||||
SCMP_STATE_ENTRY(ER, "%02X", ER, 0xff, 0)
|
||||
SCMP_STATE_ENTRY(SR, "%02X", SR, 0xff, 0)
|
||||
|
||||
};
|
||||
|
||||
static const cpu_state_table state_table_template =
|
||||
{
|
||||
NULL, /* pointer to the base of state (offsets are relative to this) */
|
||||
0, /* subtype this table refers to */
|
||||
ARRAY_LENGTH(state_array), /* number of entries */
|
||||
state_array /* array of entries */
|
||||
};
|
||||
|
||||
/***************************************************************************
|
||||
INLINE FUNCTIONS
|
||||
***************************************************************************/
|
||||
|
||||
INLINE scmp_state *get_safe_token(const device_config *device)
|
||||
{
|
||||
assert(device != NULL);
|
||||
assert(device->token != NULL);
|
||||
assert(device->type == CPU);
|
||||
assert(cpu_get_type(device) == CPU_SCMP);
|
||||
return (scmp_state *)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 memory_decrypted_read_byte(cpustate->program, pc);
|
||||
}
|
||||
|
||||
INLINE UINT8 ARG(scmp_state *cpustate)
|
||||
{
|
||||
UINT16 pc = cpustate->PC.w.l;
|
||||
cpustate->PC.w.l = ADD12(cpustate->PC.w.l,1);
|
||||
return memory_raw_read_byte(cpustate->program, pc);
|
||||
}
|
||||
|
||||
INLINE UINT8 RM(scmp_state *cpustate,UINT32 a)
|
||||
{
|
||||
return memory_read_byte_8le(cpustate->program, a);
|
||||
}
|
||||
|
||||
INLINE void WM(scmp_state *cpustate,UINT32 a, UINT8 v)
|
||||
{
|
||||
memory_write_byte_8le(cpustate->program, 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);
|
||||
|
||||
cpustate->icount = cycles;
|
||||
|
||||
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);
|
||||
|
||||
return cycles - cpustate->icount;
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
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 */
|
||||
cpustate->state = state_table_template;
|
||||
cpustate->state.baseptr = cpustate;
|
||||
cpustate->state.subtypemask = 1;
|
||||
|
||||
cpustate->device = device;
|
||||
|
||||
cpustate->program = memory_find_address_space(device, ADDRESS_SPACE_PROGRAM);
|
||||
|
||||
/* 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);
|
||||
|
||||
state_save_register_device_item(device, 0, cpustate->PC);
|
||||
state_save_register_device_item(device, 0, cpustate->P1);
|
||||
state_save_register_device_item(device, 0, cpustate->P2);
|
||||
state_save_register_device_item(device, 0, cpustate->P3);
|
||||
state_save_register_device_item(device, 0, cpustate->AC);
|
||||
state_save_register_device_item(device, 0, cpustate->ER);
|
||||
state_save_register_device_item(device, 0, 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 )
|
||||
{
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
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 CPUINFO_INT_DATABUS_WIDTH_PROGRAM: info->i = 8; break;
|
||||
case CPUINFO_INT_ADDRBUS_WIDTH_PROGRAM: info->i = 16; break;
|
||||
case CPUINFO_INT_ADDRBUS_SHIFT_PROGRAM: info->i = 0; break;
|
||||
|
||||
case CPUINFO_INT_DATABUS_WIDTH_DATA: info->i = 0; break;
|
||||
case CPUINFO_INT_ADDRBUS_WIDTH_DATA: info->i = 0; break;
|
||||
case CPUINFO_INT_ADDRBUS_SHIFT_DATA: info->i = 0; break;
|
||||
|
||||
case CPUINFO_INT_DATABUS_WIDTH_IO: info->i = 0; break;
|
||||
case CPUINFO_INT_ADDRBUS_WIDTH_IO: info->i = 0; break;
|
||||
case CPUINFO_INT_ADDRBUS_SHIFT_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;
|
||||
|
||||
/* --- the following bits of info are returned as pointers --- */
|
||||
case CPUINFO_PTR_INSTRUCTION_COUNTER: info->icount = &cpustate->icount; break;
|
||||
case CPUINFO_PTR_STATE_TABLE: info->state_table = &cpustate->state; break;
|
||||
|
||||
/* --- the following bits of info are returned as NULL-terminated strings --- */
|
||||
case DEVINFO_STR_NAME: strcpy(info->s, "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;
|
||||
|
||||
case CPUINFO_STR_FLAGS:
|
||||
sprintf(info->s, "%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;
|
||||
}
|
||||
}
|
43
src/emu/cpu/scmp/scmp.h
Normal file
43
src/emu/cpu/scmp/scmp.h
Normal file
@ -0,0 +1,43 @@
|
||||
#ifndef __SCMP_H__
|
||||
#define __SCMP_H__
|
||||
|
||||
#include "cpuintrf.h"
|
||||
#include "devcb.h"
|
||||
|
||||
/***************************************************************************
|
||||
CONSTANTS
|
||||
***************************************************************************/
|
||||
|
||||
enum
|
||||
{
|
||||
SCMP_PC, SCMP_P1, SCMP_P2, SCMP_P3, SCMP_AC, SCMP_ER, SCMP_SR,
|
||||
SCMP_GENPC = REG_GENPC,
|
||||
SCMP_GENSP = REG_GENSP,
|
||||
SCMP_GENPCBASE = REG_GENPCBASE
|
||||
};
|
||||
|
||||
/***************************************************************************
|
||||
TYPE DEFINITIONS
|
||||
***************************************************************************/
|
||||
typedef struct _scmp_config scmp_config;
|
||||
struct _scmp_config
|
||||
{
|
||||
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;
|
||||
};
|
||||
#define SCMP_CONFIG(name) const scmp_config (name) =
|
||||
|
||||
/***************************************************************************
|
||||
FUNCTION PROTOTYPES
|
||||
***************************************************************************/
|
||||
|
||||
CPU_GET_INFO( scmp );
|
||||
#define CPU_SCMP CPU_GET_INFO_NAME( scmp )
|
||||
|
||||
CPU_DISASSEMBLE( scmp );
|
||||
|
||||
#endif
|
153
src/emu/cpu/scmp/scmpdasm.c
Normal file
153
src/emu/cpu/scmp/scmpdasm.c
Normal file
@ -0,0 +1,153 @@
|
||||
/*****************************************************************************
|
||||
*
|
||||
* scmpdasm.c
|
||||
*
|
||||
* National Semiconductor SC/MP CPU Disassembly
|
||||
*
|
||||
* Initial version by Miodrag Milanovic
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#include "cpuintrf.h"
|
||||
|
||||
#define OP(A) oprom[(A) - PC]
|
||||
#define ARG(A) opram[(A) - PC]
|
||||
|
||||
CPU_DISASSEMBLE( scmp )
|
||||
{
|
||||
unsigned PC = pc;
|
||||
UINT8 op = OP(pc++);
|
||||
UINT8 ptr = op & 3;
|
||||
|
||||
if (BIT(op,7)) {
|
||||
// two bytes instructions
|
||||
char as[10];
|
||||
char aspr[10];
|
||||
UINT8 arg = ARG(pc); pc++;
|
||||
if (arg==0x80) {
|
||||
sprintf(as,"E");
|
||||
} else {
|
||||
if (arg & 0x80) {
|
||||
sprintf(as,"-$%02x",0x100-arg);
|
||||
} else {
|
||||
sprintf(as,"+$%02x",arg);
|
||||
}
|
||||
}
|
||||
sprintf(aspr,"%s(%d)",as,ptr);
|
||||
|
||||
switch (op)
|
||||
{
|
||||
// Memory Reference Instructions
|
||||
case 0xc0 : sprintf (buffer,"ld %s",as); break;
|
||||
case 0xc1 : case 0xc2 : case 0xc3 :
|
||||
sprintf (buffer,"ld %s",aspr);break;
|
||||
case 0xc5 : case 0xc6 : case 0xc7 :
|
||||
sprintf (buffer,"ld @%s",aspr); break;
|
||||
case 0xc8 : sprintf (buffer,"st %s",as); break;
|
||||
case 0xc9 : case 0xca : case 0xcb :
|
||||
sprintf (buffer,"st %s",aspr);break;
|
||||
case 0xcd : case 0xce : case 0xcf :
|
||||
sprintf (buffer,"st @%s",aspr); break;
|
||||
case 0xd0 : sprintf (buffer,"and %s",as); break;
|
||||
case 0xd1 : case 0xd2 : case 0xd3 :
|
||||
sprintf (buffer,"and %s",aspr);break;
|
||||
case 0xd5 : case 0xd6 : case 0xd7 :
|
||||
sprintf (buffer,"and @%s",aspr); break;
|
||||
case 0xd8 : sprintf (buffer,"or %s",as); break;
|
||||
case 0xd9 : case 0xda : case 0xdb :
|
||||
sprintf (buffer,"or %s",aspr);break;
|
||||
case 0xdd : case 0xde : case 0xdf :
|
||||
sprintf (buffer,"or @%s",aspr); break;
|
||||
case 0xe0 : sprintf (buffer,"xor %s",as); break;
|
||||
case 0xe1 : case 0xe2 : case 0xe3 :
|
||||
sprintf (buffer,"xor %s",aspr);break;
|
||||
case 0xe5 : case 0xe6 : case 0xe7 :
|
||||
sprintf (buffer,"xor @%s",aspr); break;
|
||||
case 0xe8 : sprintf (buffer,"dad %s",as); break;
|
||||
case 0xe9 : case 0xea : case 0xeb :
|
||||
sprintf (buffer,"dad %s",aspr);break;
|
||||
case 0xed : case 0xee : case 0xef :
|
||||
sprintf (buffer,"dad @%s",aspr); break;
|
||||
case 0xf0 : sprintf (buffer,"add %s",as); break;
|
||||
case 0xf1 : case 0xf2 : case 0xf3 :
|
||||
sprintf (buffer,"add %s",aspr);break;
|
||||
case 0xf5 : case 0xf6 : case 0xf7 :
|
||||
sprintf (buffer,"add @%s",aspr); break;
|
||||
case 0xf8 : sprintf (buffer,"cad %s",as); break;
|
||||
case 0xf9 : case 0xfa : case 0xfb :
|
||||
sprintf (buffer,"cad %s",aspr);break;
|
||||
case 0xfd : case 0xfe : case 0xff :
|
||||
sprintf (buffer,"cad @%s",aspr); break;
|
||||
// Memory Increment/Decrement Instructions
|
||||
case 0xa8 : case 0xa9 : case 0xaa : case 0xab :
|
||||
sprintf (buffer,"ild %s",aspr); break;
|
||||
case 0xb8 : case 0xb9 : case 0xba : case 0xbb :
|
||||
sprintf (buffer,"dld %s",aspr); break;
|
||||
// Immediate Instructions
|
||||
case 0xc4 : sprintf (buffer,"ldi $%02x",arg); break;
|
||||
case 0xd4 : sprintf (buffer,"ani $%02x",arg); break;
|
||||
case 0xdc : sprintf (buffer,"ori $%02x",arg); break;
|
||||
case 0xe4 : sprintf (buffer,"xri $%02x",arg); break;
|
||||
case 0xec : sprintf (buffer,"dai $%02x",arg); break;
|
||||
case 0xf4 : sprintf (buffer,"adi $%02x",arg); break;
|
||||
case 0xfc : sprintf (buffer,"cai $%02x",arg); break;
|
||||
// Transfer Instructions
|
||||
case 0x90 : sprintf (buffer,"jmp %s",as);break;
|
||||
case 0x91 : case 0x92 : case 0x93 :
|
||||
sprintf (buffer,"jmp %s",aspr);break;
|
||||
case 0x94 : sprintf (buffer,"jp %s",as); break;
|
||||
case 0x95 : case 0x96 : case 0x97 :
|
||||
sprintf (buffer,"jp %s",aspr); break;
|
||||
case 0x98 : sprintf (buffer,"jz %s",as); break;
|
||||
case 0x99 : case 0x9a : case 0x9b :
|
||||
sprintf (buffer,"jz %s",aspr); break;
|
||||
case 0x9c : sprintf (buffer,"jnz %s",as); break;
|
||||
case 0x9d : case 0x9e : case 0x9f :
|
||||
sprintf (buffer,"jnz %s",aspr); break;
|
||||
// Double-Byte Miscellaneous Instructions
|
||||
case 0x8f: sprintf (buffer,"dly $%02x",arg); break;
|
||||
// Others are illegal
|
||||
default : sprintf (buffer,"illegal"); pc--; break; // Illegal we consider without param
|
||||
}
|
||||
} else {
|
||||
// one byte instructions
|
||||
switch (op)
|
||||
{
|
||||
// Extension Register Instructions
|
||||
case 0x40: sprintf (buffer,"lde"); break;
|
||||
case 0x01: sprintf (buffer,"xae"); break;
|
||||
case 0x50: sprintf (buffer,"ane"); break;
|
||||
case 0x58: sprintf (buffer,"ore"); break;
|
||||
case 0x60: sprintf (buffer,"xre"); break;
|
||||
case 0x68: sprintf (buffer,"dae"); break;
|
||||
case 0x70: sprintf (buffer,"ade"); break;
|
||||
case 0x78: sprintf (buffer,"cae"); break;
|
||||
// Pointer Register Move Instructions
|
||||
case 0x30: case 0x31 :case 0x32: case 0x33:
|
||||
sprintf (buffer,"xpal %d",ptr); break;
|
||||
case 0x34: case 0x35 :case 0x36: case 0x37:
|
||||
sprintf (buffer,"xpah %d",ptr); break;
|
||||
case 0x3c: case 0x3d :case 0x3e: case 0x3f:
|
||||
sprintf (buffer,"xppc %d",ptr); break;
|
||||
// Shift, Rotate, Serial I/O Instructions
|
||||
case 0x19: sprintf (buffer,"sio"); break;
|
||||
case 0x1c: sprintf (buffer,"sr"); break;
|
||||
case 0x1d: sprintf (buffer,"srl"); break;
|
||||
case 0x1e: sprintf (buffer,"rr"); break;
|
||||
case 0x1f: sprintf (buffer,"rrl"); break;
|
||||
// Single Byte Miscellaneous Instructions
|
||||
case 0x00: sprintf (buffer,"halt"); break;
|
||||
case 0x02: sprintf (buffer,"ccl"); break;
|
||||
case 0x03: sprintf (buffer,"scl"); break;
|
||||
case 0x04: sprintf (buffer,"dint"); break;
|
||||
case 0x05: sprintf (buffer,"ien"); break;
|
||||
case 0x06: sprintf (buffer,"csa"); break;
|
||||
case 0x07: sprintf (buffer,"cas"); break;
|
||||
case 0x08: sprintf (buffer,"nop"); break;
|
||||
// Others are illegal
|
||||
default : sprintf (buffer,"illegal"); break;
|
||||
}
|
||||
}
|
||||
|
||||
return (pc - PC);
|
||||
}
|
@ -116,6 +116,8 @@ CPUS += TMS0980
|
||||
CPUS += I4004
|
||||
CPUS += SUPERFX
|
||||
CPUS += Z8
|
||||
CPUS += I8008
|
||||
CPUS += SCMP
|
||||
|
||||
|
||||
#-------------------------------------------------
|
||||
|
@ -113,6 +113,7 @@ CPU_DISASSEMBLE( h6280 );
|
||||
CPU_DISASSEMBLE( h8 );
|
||||
CPU_DISASSEMBLE( hd6309 );
|
||||
CPU_DISASSEMBLE( i4004 );
|
||||
CPU_DISASSEMBLE( i8008 );
|
||||
CPU_DISASSEMBLE( i8085 );
|
||||
CPU_DISASSEMBLE( x86_16 );
|
||||
CPU_DISASSEMBLE( x86_32 );
|
||||
@ -170,6 +171,7 @@ CPU_DISASSEMBLE( rsp );
|
||||
CPU_DISASSEMBLE( s2650 );
|
||||
CPU_DISASSEMBLE( saturn );
|
||||
CPU_DISASSEMBLE( sc61860 );
|
||||
CPU_DISASSEMBLE( scmp );
|
||||
CPU_DISASSEMBLE( se3208 );
|
||||
CPU_DISASSEMBLE( sh2 );
|
||||
CPU_DISASSEMBLE( sh4 );
|
||||
@ -234,6 +236,7 @@ static const dasm_table_entry dasm_table[] =
|
||||
{ "hd6309", _8bit, 0, CPU_DISASSEMBLE_NAME(hd6309) },
|
||||
{ "i386", _8bit, 0, CPU_DISASSEMBLE_NAME(x86_32) },
|
||||
{ "i4004", _8bit, 0, CPU_DISASSEMBLE_NAME(i4004) },
|
||||
{ "i8008", _8bit, 0, CPU_DISASSEMBLE_NAME(i8008) },
|
||||
{ "i8085", _8bit, 0, CPU_DISASSEMBLE_NAME(i8085) },
|
||||
{ "i80286", _8bit, 0, CPU_DISASSEMBLE_NAME(x86_16) },
|
||||
{ "i8086", _8bit, 0, CPU_DISASSEMBLE_NAME(x86_16) },
|
||||
@ -293,6 +296,7 @@ static const dasm_table_entry dasm_table[] =
|
||||
{ "s2650", _8bit, 0, CPU_DISASSEMBLE_NAME(s2650) },
|
||||
{ "saturn", _8bit, 0, CPU_DISASSEMBLE_NAME(saturn) },
|
||||
{ "sc61860", _8bit, 0, CPU_DISASSEMBLE_NAME(sc61860) },
|
||||
{ "scmp", _8bit, 0, CPU_DISASSEMBLE_NAME(scmp) },
|
||||
{ "se3208", _16le, 0, CPU_DISASSEMBLE_NAME(se3208) },
|
||||
{ "sh2", _16be, 0, CPU_DISASSEMBLE_NAME(sh2) },
|
||||
{ "sh4", _16le, 0, CPU_DISASSEMBLE_NAME(sh4) },
|
||||
|
Loading…
Reference in New Issue
Block a user