diff options
Diffstat (limited to 'trunk/src/emu/cpu/cop400/cop400.c')
-rw-r--r-- | trunk/src/emu/cpu/cop400/cop400.c | 1709 |
1 files changed, 1709 insertions, 0 deletions
diff --git a/trunk/src/emu/cpu/cop400/cop400.c b/trunk/src/emu/cpu/cop400/cop400.c new file mode 100644 index 00000000000..e21d2a91008 --- /dev/null +++ b/trunk/src/emu/cpu/cop400/cop400.c @@ -0,0 +1,1709 @@ +/*************************************************************************** + + cop400.c + + National Semiconductor COP400 Emulator. + + Copyright Nicola Salmoria and the MAME Team. + Visit http://mamedev.org for licensing and usage restrictions. + +**************************************************************************** + + Type ROM RAM G D IN + + COP410 512x8 32x4 none + COP411 512x8 32x4 0-2 0-1 none + COP401 none 32x4 none + COP413? + COP414? + COP415? + COP405? + + COP420 1024x8 64x4 + COP421 1024x8 64x4 none + COP422 1024x8 64x4 2-3 2-3 none + COP402 none 64x4 + + COP444 2048x8 128x4 + COP445 2048x8 128x4 none + COP424 1024x8 64x4 + COP425 1024x8 64x4 none + COP426 1024x8 64x4 2-3 2-3 + COP404 none none + + COP440 2048x8 160x4 + COP441 2048x8 160x4 + COP442 2048x8 160x4 + +**************************************************************************** + + Prefix Temperature Range + + COP4xx 0C ... 70C + COP3xx -40C ... +85C + COP2xx -55C ... +125C + +***************************************************************************/ + +/* + + TODO: + + - remove LBIOps + - remove InstLen + - run interrupt test suite + - run production test suite + - run microbus test suite + - when is the microbus int cleared? + - opcode support for 2048x8 and 128x4/160x4 memory sizes + - CKO sync input + - save internal RAM when CKO is RAM power supply pin + - COP413/COP414/COP415/COP405 + - COP404 opcode map switching, dual timer, microbus enable + - COP440/COP441/COP442 (new registers: 2-bit N, 4-bit H, 8-bit R; some new opcodes, 2Kx8 ROM, 160x4 RAM) + +*/ + +#include "emu.h" +#include "debugger.h" +#include "cop400.h" + +/*************************************************************************** + CONSTANTS +***************************************************************************/ + +/* feature masks */ +#define COP410_FEATURE 0x01 +#define COP420_FEATURE 0x02 +#define COP444_FEATURE 0x04 +#define COP440_FEATURE 0x08 + +/*************************************************************************** + TYPE DEFINITIONS +***************************************************************************/ + +typedef struct _cop400_opcode_map cop400_opcode_map; + +typedef struct _cop400_state cop400_state; +struct _cop400_state +{ + const cop400_interface *intf; + + address_space *program; + direct_read_data *direct; + address_space *data; + address_space *io; + + UINT8 featuremask; + + /* registers */ + UINT16 pc; /* 9/10/11-bit ROM address program counter */ + UINT16 prevpc; /* previous value of program counter */ + UINT8 a; /* 4-bit accumulator */ + UINT8 b; /* 5/6/7-bit RAM address register */ + int c; /* 1-bit carry register */ + UINT8 n; /* 2-bit stack pointer (COP440 only) */ + UINT8 en; /* 4-bit enable register */ + UINT8 g; /* 4-bit general purpose I/O port */ + UINT8 q; /* 8-bit latch for L port */ + UINT16 sa, sb, sc; /* subroutine save registers (not present in COP440) */ + UINT8 sio; /* 4-bit shift register and counter */ + int skl; /* 1-bit latch for SK output */ + UINT8 h; /* 4-bit general purpose I/O port (COP440 only) */ + UINT8 r; /* 8-bit general purpose I/O port (COP440 only) */ + UINT8 flags; // used for I/O only + + /* counter */ + UINT8 t; /* 8-bit timer */ + int skt_latch; /* timer overflow latch */ + + /* input/output ports */ + UINT8 g_mask; /* G port mask */ + UINT8 d_mask; /* D port mask */ + UINT8 in_mask; /* IN port mask */ + UINT8 il; /* IN latch */ + UINT8 in[4]; /* IN port shift register */ + UINT8 si; /* serial input */ + + /* skipping logic */ + int skip; /* skip next instruction */ + int skip_lbi; /* skip until next non-LBI instruction */ + int last_skip; /* last value of skip */ + int halt; /* halt mode */ + int idle; /* idle mode */ + + /* microbus */ + int microbus_int; /* microbus interrupt */ + + /* execution logic */ + int InstLen[256]; /* instruction length in bytes */ + int LBIops[256]; + int LBIops33[256]; + int icount; /* instruction counter */ + + const cop400_opcode_map *opcode_map; + + /* timers */ + emu_timer *serial_timer; + emu_timer *counter_timer; + emu_timer *inil_timer; + emu_timer *microbus_timer; +}; + +typedef void (*cop400_opcode_func) (cop400_state *cpustate, UINT8 opcode); + +struct _cop400_opcode_map { + unsigned cycles; + cop400_opcode_func function; +}; + +/*************************************************************************** + MACROS +***************************************************************************/ + +#define ROM(a) cpustate->direct->read_decrypted_byte(a) +#define RAM_R(a) cpustate->data->read_byte(a) +#define RAM_W(a, v) cpustate->data->write_byte(a, v) +#define IN(a) cpustate->io->read_byte(a) +#define OUT(a, v) cpustate->io->write_byte(a, v) + +#define IN_G() (IN(COP400_PORT_G) & cpustate->g_mask) +#define IN_L() IN(COP400_PORT_L) +#define IN_SI() BIT(IN(COP400_PORT_SIO), 0) +#define IN_CKO() BIT(IN(COP400_PORT_CKO), 0) +#define IN_IN() (cpustate->in_mask ? IN(COP400_PORT_IN) : 0) + +#define OUT_G(v) OUT(COP400_PORT_G, (v) & cpustate->g_mask) +#define OUT_L(v) OUT(COP400_PORT_L, (v)) +#define OUT_D(v) OUT(COP400_PORT_D, (v) & cpustate->d_mask) +#define OUT_SK(v) OUT(COP400_PORT_SK, (v)) +#define OUT_SO(v) OUT(COP400_PORT_SIO, (v)) + +#define PC cpustate->pc +#define A cpustate->a +#define B cpustate->b +#define C cpustate->c +#define G cpustate->g +#define Q cpustate->q +#define H cpustate->h +#define R cpustate->r +#define EN cpustate->en +#define SA cpustate->sa +#define SB cpustate->sb +#define SC cpustate->sc +#define SIO cpustate->sio +#define SKL cpustate->skl +#define T cpustate->t +#define IL cpustate->il + +/*************************************************************************** + INLINE FUNCTIONS +***************************************************************************/ + +INLINE cop400_state *get_safe_token(device_t *device) +{ + assert(device != NULL); + assert(device->type() == COP401 || + device->type() == COP410 || + device->type() == COP411 || + device->type() == COP402 || + device->type() == COP420 || + device->type() == COP421 || + device->type() == COP422 || + device->type() == COP404 || + device->type() == COP424 || + device->type() == COP425 || + device->type() == COP426 || + device->type() == COP444 || + device->type() == COP445); + return (cop400_state *)downcast<legacy_cpu_device *>(device)->token(); +} + +INLINE void PUSH(cop400_state *cpustate, UINT16 data) +{ + if (cpustate->featuremask != COP410_FEATURE) + { + SC = SB; + } + + SB = SA; + SA = data; +} + +INLINE void POP(cop400_state *cpustate) +{ + PC = SA; + SA = SB; + + if (cpustate->featuremask != COP410_FEATURE) + { + SB = SC; + } +} + +INLINE void WRITE_Q(cop400_state *cpustate, UINT8 data) +{ + Q = data; + + if (BIT(EN, 2)) + { + OUT_L(Q); + } +} + +INLINE void WRITE_G(cop400_state *cpustate, UINT8 data) +{ + if (cpustate->intf->microbus == COP400_MICROBUS_ENABLED) + { + data = (data & 0x0e) | cpustate->microbus_int; + } + + G = data; + + OUT_G(G); +} + +/*************************************************************************** + OPCODE HANDLERS +***************************************************************************/ + +#define INSTRUCTION(mnemonic) INLINE void (mnemonic)(cop400_state *cpustate, UINT8 opcode) + +INSTRUCTION(illegal) +{ + logerror("COP400: PC = %04x, Illegal opcode = %02x\n", PC-1, ROM(PC-1)); +} + +#include "cop400op.c" + +/*************************************************************************** + OPCODE TABLES +***************************************************************************/ + +static const cop400_opcode_map COP410_OPCODE_23_MAP[] = +{ + {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal }, + {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal }, + {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal }, + {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal }, + {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal }, + {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal }, + {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal }, + {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal }, + + {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal }, + {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal }, + {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal }, + {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal }, + {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal }, + {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal }, + {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal }, + {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal }, + + {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal }, + {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal }, + {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal }, + {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal }, + {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal }, + {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal }, + {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal }, + {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, xad }, + + {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal }, + {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal }, + {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal }, + {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal }, + {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal }, + {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal }, + {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal }, + {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal } +}; + +static void cop410_op23(cop400_state *cpustate, UINT8 opcode) +{ + UINT8 opcode23 = ROM(PC++); + + (*(COP410_OPCODE_23_MAP[opcode23].function))(cpustate, opcode23); +} + +static const cop400_opcode_map COP410_OPCODE_33_MAP[] = +{ + {1, illegal },{1, skgbz0 },{1, illegal },{1, skgbz2 },{1, illegal },{1, illegal },{1, illegal },{1, illegal }, + {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal }, + {1, illegal },{1, skgbz1 },{1, illegal },{1, skgbz3 },{1, illegal },{1, illegal },{1, illegal },{1, illegal }, + {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal }, + {1, illegal },{1, skgz },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal }, + {1, illegal },{1, illegal },{1, ing },{1, illegal },{1, illegal },{1, illegal },{1, inl },{1, illegal }, + {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal }, + {1, halt },{1, illegal },{1, omg },{1, illegal },{1, camq },{1, illegal },{1, obd },{1, illegal }, + + {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal }, + {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal }, + {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal }, + {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal }, + {1, lei },{1, lei },{1, lei },{1, lei },{1, lei },{1, lei },{1, lei },{1, lei }, + {1, lei },{1, lei },{1, lei },{1, lei },{1, lei },{1, lei },{1, lei },{1, lei }, + {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal }, + {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal }, + + {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal }, + {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal }, + {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal }, + {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal }, + {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal }, + {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal }, + {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal }, + {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal }, + + {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal }, + {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal }, + {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal }, + {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal }, + {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal }, + {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal }, + {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal }, + {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal } +}; + +static void cop410_op33(cop400_state *cpustate, UINT8 opcode) +{ + UINT8 opcode33 = ROM(PC++); + + (*(COP410_OPCODE_33_MAP[opcode33].function))(cpustate, opcode33); +} + +static const cop400_opcode_map COP410_OPCODE_MAP[] = +{ + {1, clra },{1, skmbz0 },{1, xor_ },{1, skmbz2 },{1, xis },{1, ld },{1, x },{1, xds }, + {1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi }, + {0, illegal },{1, skmbz1 },{0, illegal },{1, skmbz3 },{1, xis },{1, ld },{1, x },{1, xds }, + {1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi }, + {1, skc },{1, ske },{1, sc },{1, cop410_op23 },{1, xis },{1, ld },{1, x },{1, xds }, + {1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi }, + {1, asc },{1, add },{1, rc },{1, cop410_op33 },{1, xis },{1, ld },{1, x },{1, xds }, + {1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi }, + + {1, comp },{0, illegal },{1, rmb2 },{1, rmb3 },{1, nop },{1, rmb1 },{1, smb2 },{1, smb1 }, + {1, ret },{1, retsk },{0, illegal },{1, smb3 },{1, rmb0 },{1, smb0 },{1, cba },{1, xas }, + {1, cab },{1, aisc },{1, aisc },{1, aisc },{1, aisc },{1, aisc },{1, aisc },{1, aisc }, + {1, aisc },{1, aisc },{1, aisc },{1, aisc },{1, aisc },{1, aisc },{1, aisc },{1, aisc }, + {2, jmp },{2, jmp },{0, illegal },{0, illegal },{0, illegal },{0, illegal },{0, illegal },{0, illegal }, + {2, jsr },{2, jsr },{0, illegal },{0, illegal },{0, illegal },{0, illegal },{0, illegal },{0, illegal }, + {1, stii },{1, stii },{1, stii },{1, stii },{1, stii },{1, stii },{1, stii },{1, stii }, + {1, stii },{1, stii },{1, stii },{1, stii },{1, stii },{1, stii },{1, stii },{1, stii }, + + {1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp }, + {1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp }, + {1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp }, + {1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp }, + {1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp }, + {1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp }, + {1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp }, + {1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{2, lqid }, + + {1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp }, + {1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp }, + {1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp }, + {1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp }, + {1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp }, + {1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp }, + {1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp }, + {1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{2, jid } +}; + +static const cop400_opcode_map COP420_OPCODE_23_MAP[] = +{ + {1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd }, + {1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd }, + {1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd }, + {1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd }, + {1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd }, + {1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd }, + {1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd }, + {1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd }, + + {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal }, + {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal }, + {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal }, + {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal }, + {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal }, + {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal }, + {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal }, + {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal }, + + {1, xad },{1, xad },{1, xad },{1, xad },{1, xad },{1, xad },{1, xad },{1, xad }, + {1, xad },{1, xad },{1, xad },{1, xad },{1, xad },{1, xad },{1, xad },{1, xad }, + {1, xad },{1, xad },{1, xad },{1, xad },{1, xad },{1, xad },{1, xad },{1, xad }, + {1, xad },{1, xad },{1, xad },{1, xad },{1, xad },{1, xad },{1, xad },{1, xad }, + {1, xad },{1, xad },{1, xad },{1, xad },{1, xad },{1, xad },{1, xad },{1, xad }, + {1, xad },{1, xad },{1, xad },{1, xad },{1, xad },{1, xad },{1, xad },{1, xad }, + {1, xad },{1, xad },{1, xad },{1, xad },{1, xad },{1, xad },{1, xad },{1, xad }, + {1, xad },{1, xad },{1, xad },{1, xad },{1, xad },{1, xad },{1, xad },{1, xad }, + + {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal }, + {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal }, + {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal }, + {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal }, + {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal }, + {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal }, + {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal }, + {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal } +}; + +static void cop420_op23(cop400_state *cpustate, UINT8 opcode) +{ + UINT8 opcode23 = ROM(PC++); + + (*(COP420_OPCODE_23_MAP[opcode23].function))(cpustate, opcode23); +} + +static const cop400_opcode_map COP420_OPCODE_33_MAP[] = +{ + {1, illegal },{1, skgbz0 },{1, illegal },{1, skgbz2 },{1, illegal },{1, illegal },{1, illegal },{1, illegal }, + {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal }, + {1, illegal },{1, skgbz1 },{1, illegal },{1, skgbz3 },{1, illegal },{1, illegal },{1, illegal },{1, illegal }, + {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal }, + {1, illegal },{1, skgz },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal }, + {1, inin },{1, inil },{1, ing },{1, illegal },{1, cqma },{1, illegal },{1, inl },{1, illegal }, + {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal }, + {1, illegal },{1, illegal },{1, omg },{1, illegal },{1, camq },{1, illegal },{1, obd },{1, illegal }, + + {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal }, + {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal }, + {1, ogi },{1, ogi },{1, ogi },{1, ogi },{1, ogi },{1, ogi },{1, ogi },{1, ogi }, + {1, ogi },{1, ogi },{1, ogi },{1, ogi },{1, ogi },{1, ogi },{1, ogi },{1, ogi }, + {1, lei },{1, lei },{1, lei },{1, lei },{1, lei },{1, lei },{1, lei },{1, lei }, + {1, lei },{1, lei },{1, lei },{1, lei },{1, lei },{1, lei },{1, lei },{1, lei }, + {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal }, + {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal }, + + {1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi }, + {1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi }, + {1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi }, + {1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi }, + {1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi }, + {1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi }, + {1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi }, + {1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi }, + + {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal }, + {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal }, + {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal }, + {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal }, + {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal }, + {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal }, + {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal }, + {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal } +}; + +static void cop420_op33(cop400_state *cpustate, UINT8 opcode) +{ + UINT8 opcode33 = ROM(PC++); + + (*(COP420_OPCODE_33_MAP[opcode33].function))(cpustate, opcode33); +} + +static const cop400_opcode_map COP420_OPCODE_MAP[] = +{ + {1, clra },{1, skmbz0 },{1, xor_ },{1, skmbz2 },{1, xis },{1, ld },{1, x },{1, xds }, + {1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi }, + {1, casc },{1, skmbz1 },{1, xabr },{1, skmbz3 },{1, xis },{1, ld },{1, x },{1, xds }, + {1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi }, + {1, skc },{1, ske },{1, sc },{1, cop420_op23 },{1, xis },{1, ld },{1, x },{1, xds }, + {1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi }, + {1, asc },{1, add },{1, rc },{1, cop420_op33 },{1, xis },{1, ld },{1, x },{1, xds }, + {1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi }, + + {1, comp },{1, skt },{1, rmb2 },{1, rmb3 },{1, nop },{1, rmb1 },{1, smb2 },{1, smb1 }, + {1, cop420_ret },{1, retsk },{1, adt },{1, smb3 },{1, rmb0 },{1, smb0 },{1, cba },{1, xas }, + {1, cab },{1, aisc },{1, aisc },{1, aisc },{1, aisc },{1, aisc },{1, aisc },{1, aisc }, + {1, aisc },{1, aisc },{1, aisc },{1, aisc },{1, aisc },{1, aisc },{1, aisc },{1, aisc }, + {2, jmp },{2, jmp },{2, jmp },{2, jmp },{0, illegal },{0, illegal },{0, illegal },{0, illegal }, + {2, jsr },{2, jsr },{2, jsr },{2, jsr },{0, illegal },{0, illegal },{0, illegal },{0, illegal }, + {1, stii },{1, stii },{1, stii },{1, stii },{1, stii },{1, stii },{1, stii },{1, stii }, + {1, stii },{1, stii },{1, stii },{1, stii },{1, stii },{1, stii },{1, stii },{1, stii }, + + {1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp }, + {1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp }, + {1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp }, + {1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp }, + {1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp }, + {1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp }, + {1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp }, + {1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{2, lqid }, + + {1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp }, + {1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp }, + {1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp }, + {1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp }, + {1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp }, + {1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp }, + {1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp }, + {1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{2, jid } +}; + +static const cop400_opcode_map COP444_OPCODE_23_MAP[256] = +{ + {1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd }, + {1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd }, + {1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd }, + {1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd }, + {1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd }, + {1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd }, + {1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd }, + {1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd }, + + {1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd }, + {1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd }, + {1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd }, + {1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd }, + {1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd }, + {1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd }, + {1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd }, + {1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd }, + + {1, xad },{1, xad },{1, xad },{1, xad },{1, xad },{1, xad },{1, xad },{1, xad }, + {1, xad },{1, xad },{1, xad },{1, xad },{1, xad },{1, xad },{1, xad },{1, xad }, + {1, xad },{1, xad },{1, xad },{1, xad },{1, xad },{1, xad },{1, xad },{1, xad }, + {1, xad },{1, xad },{1, xad },{1, xad },{1, xad },{1, xad },{1, xad },{1, xad }, + {1, xad },{1, xad },{1, xad },{1, xad },{1, xad },{1, xad },{1, xad },{1, xad }, + {1, xad },{1, xad },{1, xad },{1, xad },{1, xad },{1, xad },{1, xad },{1, xad }, + {1, xad },{1, xad },{1, xad },{1, xad },{1, xad },{1, xad },{1, xad },{1, xad }, + {1, xad },{1, xad },{1, xad },{1, xad },{1, xad },{1, xad },{1, xad },{1, xad }, + + {1, xad },{1, xad },{1, xad },{1, xad },{1, xad },{1, xad },{1, xad },{1, xad }, + {1, xad },{1, xad },{1, xad },{1, xad },{1, xad },{1, xad },{1, xad },{1, xad }, + {1, xad },{1, xad },{1, xad },{1, xad },{1, xad },{1, xad },{1, xad },{1, xad }, + {1, xad },{1, xad },{1, xad },{1, xad },{1, xad },{1, xad },{1, xad },{1, xad }, + {1, xad },{1, xad },{1, xad },{1, xad },{1, xad },{1, xad },{1, xad },{1, xad }, + {1, xad },{1, xad },{1, xad },{1, xad },{1, xad },{1, xad },{1, xad },{1, xad }, + {1, xad },{1, xad },{1, xad },{1, xad },{1, xad },{1, xad },{1, xad },{1, xad }, + {1, xad },{1, xad },{1, xad },{1, xad },{1, xad },{1, xad },{1, xad },{1, xad }, +}; + +static void cop444_op23(cop400_state *cpustate, UINT8 opcode) +{ + UINT8 opcode23 = ROM(PC++); + + (*(COP444_OPCODE_23_MAP[opcode23].function))(cpustate, opcode23); +} + +static const cop400_opcode_map COP444_OPCODE_33_MAP[256] = +{ + {1, illegal },{1, skgbz0 },{1, illegal },{1, skgbz2 },{1, illegal },{1, illegal },{1, illegal },{1, illegal }, + {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal }, + {1, illegal },{1, skgbz1 },{1, illegal },{1, skgbz3 },{1, illegal },{1, illegal },{1, illegal },{1, illegal }, + {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal }, + {1, illegal },{1, skgz },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal }, + {1, inin },{1, inil },{1, ing },{1, illegal },{1, cqma },{1, illegal },{1, inl },{1, ctma }, + {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal }, + {1, it },{1, illegal },{1, omg },{1, illegal },{1, camq },{1, illegal },{1, obd },{1, camt }, + + {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal }, + {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal }, + {1, ogi },{1, ogi },{1, ogi },{1, ogi },{1, ogi },{1, ogi },{1, ogi },{1, ogi }, + {1, ogi },{1, ogi },{1, ogi },{1, ogi },{1, ogi },{1, ogi },{1, ogi },{1, ogi }, + {1, lei },{1, lei },{1, lei },{1, lei },{1, lei },{1, lei },{1, lei },{1, lei }, + {1, lei },{1, lei },{1, lei },{1, lei },{1, lei },{1, lei },{1, lei },{1, lei }, + {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal }, + {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal }, + + {1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi }, + {1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi }, + {1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi }, + {1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi }, + {1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi }, + {1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi }, + {1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi }, + {1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi }, + + {1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi }, + {1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi }, + {1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi }, + {1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi }, + {1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi }, + {1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi }, + {1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi }, + {1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi }, +}; + +static void cop444_op33(cop400_state *cpustate, UINT8 opcode) +{ + UINT8 opcode33 = ROM(PC++); + + (*(COP444_OPCODE_33_MAP[opcode33].function))(cpustate, opcode33); +} + +static const cop400_opcode_map COP444_OPCODE_MAP[256] = +{ + {1, clra },{1, skmbz0 },{1, xor_ },{1, skmbz2 },{1, xis },{1, ld },{1, x },{1, xds }, + {1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi }, + {1, casc },{1, skmbz1 },{1, cop444_xabr},{1, skmbz3 },{1, xis },{1, ld },{1, x },{1, xds }, + {1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi }, + {1, skc },{1, ske },{1, sc },{1, cop444_op23 },{1, xis },{1, ld },{1, x },{1, xds }, + {1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi }, + {1, asc },{1, add },{1, rc },{1, cop444_op33 },{1, xis },{1, ld },{1, x },{1, xds }, + {1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi }, + + {1, comp },{1, skt },{1, rmb2 },{1, rmb3 },{1, nop },{1, rmb1 },{1, smb2 },{1, smb1 }, + {1, cop420_ret },{1, retsk },{1, adt },{1, smb3 },{1, rmb0 },{1, smb0 },{1, cba },{1, xas }, + {1, cab },{1, aisc },{1, aisc },{1, aisc },{1, aisc },{1, aisc },{1, aisc },{1, aisc }, + {1, aisc },{1, aisc },{1, aisc },{1, aisc },{1, aisc },{1, aisc },{1, aisc },{1, aisc }, + {2, jmp },{2, jmp },{2, jmp },{2, jmp },{2, jmp },{2, jmp },{2, jmp },{2, jmp }, + {2, jsr },{2, jsr },{2, jsr },{2, jsr },{2, jsr },{2, jsr },{2, jsr },{2, jsr }, + {1, stii },{1, stii },{1, stii },{1, stii },{1, stii },{1, stii },{1, stii },{1, stii }, + {1, stii },{1, stii },{1, stii },{1, stii },{1, stii },{1, stii },{1, stii },{1, stii }, + + {1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp }, + {1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp }, + {1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp }, + {1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp }, + {1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp }, + {1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp }, + {1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp }, + {1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{2, lqid }, + + {1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp }, + {1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp }, + {1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp }, + {1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp }, + {1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp }, + {1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp }, + {1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp }, + {1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{2, jid } +}; + +/*************************************************************************** + TIMER CALLBACKS +***************************************************************************/ + +static TIMER_CALLBACK( serial_tick ) +{ + cop400_state *cpustate = (cop400_state *)ptr; + + if (BIT(EN, 0)) + { + /* + + SIO is an asynchronous binary counter decrementing its value by one upon each low-going pulse ("1" to "0") occurring on the SI input. + Each pulse must remain at each logic level at least two instruction cycles. SK outputs the value of the C upon the execution of an XAS + and remains latched until the execution of another XAS instruction. The SO output is equal to the value of EN3. + + */ + + // serial output + + OUT_SO(BIT(EN, 3)); + + // serial clock + + OUT_SK(SKL); + + // serial input + + cpustate->si <<= 1; + cpustate->si = (cpustate->si & 0x0e) | IN_SI(); + + if ((cpustate->si & 0x0f) == 0x0c) // 1100 + { + SIO--; + SIO &= 0x0f; + } + } + else + { + /* + + SIO is a serial shift register, shifting continuously left each instruction cycle time. The data present at SI goes into the least + significant bit of SIO: SO can be enabled to output the most significant bit of SIO each cycle time. SK output becomes a logic- + controlled clock, providing a SYNC signal each instruction time. It will start outputting a SYNC pulse upon the execution of an XAS + instruction with C = "1," stopping upon the execution of a subsequent XAS with C = "0". + + If EN0 is changed from "1" to "0" ("0" to "1") the SK output will change from "1" to SYNC (SYNC to "1") without the execution of + an XAS instruction. + + */ + + // serial output + + if (BIT(EN, 3)) + { + OUT_SO(BIT(SIO, 3)); + } + else + { + OUT_SO(0); + } + + // serial clock + + if (SKL) + { + OUT_SK(1); // SYNC + } + else + { + OUT_SK(0); + } + + // serial input + + SIO = ((SIO << 1) | IN_SI()) & 0x0f; + } +} + +static TIMER_CALLBACK( counter_tick ) +{ + cop400_state *cpustate = (cop400_state *)ptr; + + T++; + + if (T == 0) + { + cpustate->skt_latch = 1; + + if (cpustate->idle) + { + cpustate->idle = 0; + cpustate->halt = 0; + } + } +} + +static TIMER_CALLBACK( inil_tick ) +{ + cop400_state *cpustate = (cop400_state *)ptr; + UINT8 in; + int i; + + in = IN_IN(); + + for (i = 0; i < 4; i++) + { + cpustate->in[i] = (cpustate->in[i] << 1) | BIT(in, i); + + if ((cpustate->in[i] & 0x07) == 0x04) // 100 + { + IL |= (1 << i); + } + } +} + +static TIMER_CALLBACK( microbus_tick ) +{ + cop400_state *cpustate = (cop400_state *)ptr; + UINT8 in; + + in = IN_IN(); + + if (!BIT(in, 2)) + { + // chip select + + if (!BIT(in, 1)) + { + // read strobe + + OUT_L(Q); + + cpustate->microbus_int = 1; + } + else if (!BIT(in, 3)) + { + // write strobe + + Q = IN_L(); + + cpustate->microbus_int = 0; + } + } +} + +/*************************************************************************** + INITIALIZATION +***************************************************************************/ + +static void define_state_table(device_t *device) +{ + cop400_state *cpustate = get_safe_token(device); + + device_state_interface *state; + device->interface(state); + state->state_add(STATE_GENPC, "GENPC", cpustate->pc).mask(0xfff).noshow(); + state->state_add(STATE_GENPCBASE, "GENPCBASE", cpustate->prevpc).mask(0xfff).noshow(); + state->state_add(STATE_GENSP, "GENSP", cpustate->n).mask(0x3).noshow(); + state->state_add(STATE_GENFLAGS, "GENFLAGS", cpustate->flags).mask(0x3).callimport().callexport().noshow().formatstr("%2s"); + + state->state_add(COP400_PC, "PC", cpustate->pc).mask(0xfff); + + if (cpustate->featuremask & (COP410_FEATURE | COP420_FEATURE | COP444_FEATURE)) + { + state->state_add(COP400_SA, "SA", cpustate->sa).mask(0xfff); + state->state_add(COP400_SB, "SB", cpustate->sb).mask(0xfff); + if (cpustate->featuremask & (COP420_FEATURE | COP444_FEATURE)) + state->state_add(COP400_SC, "SC", cpustate->sc).mask(0xfff); + } + if (cpustate->featuremask & COP440_FEATURE) + state->state_add(COP400_N, "N", cpustate->n).mask(0x3); + + state->state_add(COP400_A, "A", cpustate->a).mask(0xf); + state->state_add(COP400_B, "B", cpustate->b); + state->state_add(COP400_C, "C", cpustate->c).mask(0x1); + + state->state_add(COP400_EN, "EN", cpustate->en).mask(0xf); + state->state_add(COP400_G, "G", cpustate->g).mask(0xf); + if (cpustate->featuremask & COP440_FEATURE) + state->state_add(COP400_H, "H", cpustate->h).mask(0xf); + state->state_add(COP400_Q, "Q", cpustate->q); + if (cpustate->featuremask & COP440_FEATURE) + state->state_add(COP400_R, "R", cpustate->r); + + state->state_add(COP400_SIO, "SIO", cpustate->sio).mask(0xf); + state->state_add(COP400_SKL, "SKL", cpustate->skl).mask(0x1); + + if (cpustate->featuremask & (COP420_FEATURE | COP444_FEATURE | COP440_FEATURE)) + state->state_add(COP400_T, "T", cpustate->t); +} + +static void cop400_init(legacy_cpu_device *device, UINT8 g_mask, UINT8 d_mask, UINT8 in_mask, int has_counter, int has_inil) +{ + cop400_state *cpustate = get_safe_token(device); + + cpustate->intf = (cop400_interface *) device->static_config(); + + /* find address spaces */ + + cpustate->program = device->space(AS_PROGRAM); + cpustate->direct = &cpustate->program->direct(); + cpustate->data = device->space(AS_DATA); + cpustate->io = device->space(AS_IO); + + /* set output pin masks */ + + cpustate->g_mask = g_mask; + cpustate->d_mask = d_mask; + cpustate->in_mask = in_mask; + + /* allocate serial timer */ + + cpustate->serial_timer = device->machine().scheduler().timer_alloc(FUNC(serial_tick), cpustate); + cpustate->serial_timer->adjust(attotime::zero, 0, attotime::from_hz(device->clock() / 16)); + + /* allocate counter timer */ + + if (has_counter) + { + cpustate->counter_timer = device->machine().scheduler().timer_alloc(FUNC(counter_tick), cpustate); + cpustate->counter_timer->adjust(attotime::zero, 0, attotime::from_hz(device->clock() / 16 / 4)); + } + + /* allocate IN latch timer */ + + if (has_inil) + { + cpustate->inil_timer = device->machine().scheduler().timer_alloc(FUNC(inil_tick), cpustate); + cpustate->inil_timer->adjust(attotime::zero, 0, attotime::from_hz(device->clock() / 16)); + } + + /* allocate Microbus timer */ + + if (cpustate->intf->microbus == COP400_MICROBUS_ENABLED) + { + cpustate->microbus_timer = device->machine().scheduler().timer_alloc(FUNC(microbus_tick), cpustate); + cpustate->microbus_timer->adjust(attotime::zero, 0, attotime::from_hz(device->clock() / 16)); + } + + /* register for state saving */ + + device->save_item(NAME(cpustate->pc)); + device->save_item(NAME(cpustate->prevpc)); + device->save_item(NAME(cpustate->n)); + device->save_item(NAME(cpustate->sa)); + device->save_item(NAME(cpustate->sb)); + device->save_item(NAME(cpustate->sc)); + device->save_item(NAME(cpustate->a)); + device->save_item(NAME(cpustate->b)); + device->save_item(NAME(cpustate->c)); + device->save_item(NAME(cpustate->g)); + device->save_item(NAME(cpustate->h)); + device->save_item(NAME(cpustate->q)); + device->save_item(NAME(cpustate->r)); + device->save_item(NAME(cpustate->en)); + device->save_item(NAME(cpustate->sio)); + device->save_item(NAME(cpustate->skl)); + device->save_item(NAME(cpustate->t)); + device->save_item(NAME(cpustate->skip)); + device->save_item(NAME(cpustate->skip_lbi)); + device->save_item(NAME(cpustate->skt_latch)); + device->save_item(NAME(cpustate->si)); + device->save_item(NAME(cpustate->last_skip)); + device->save_item(NAME(cpustate->in)); + device->save_item(NAME(cpustate->microbus_int)); + device->save_item(NAME(cpustate->halt)); + device->save_item(NAME(cpustate->idle)); +} + +static void cop410_init_opcodes(device_t *device) +{ + cop400_state *cpustate = get_safe_token(device); + int i; + + /* set up the state table */ + + cpustate->featuremask = COP410_FEATURE; + define_state_table(device); + + /* initialize instruction length array */ + + for (i=0; i<256; i++) cpustate->InstLen[i]=1; + + cpustate->InstLen[0x60] = cpustate->InstLen[0x61] = cpustate->InstLen[0x68] = + cpustate->InstLen[0x69] = cpustate->InstLen[0x33] = cpustate->InstLen[0x23] = 2; + + /* initialize LBI opcode array */ + + for (i=0x00; i<0x100; i++) cpustate->LBIops[i] = 0; + for (i=0x08; i<0x10; i++) cpustate->LBIops[i] = 1; + for (i=0x18; i<0x20; i++) cpustate->LBIops[i] = 1; + for (i=0x28; i<0x30; i++) cpustate->LBIops[i] = 1; + for (i=0x38; i<0x40; i++) cpustate->LBIops[i] = 1; + + /* select opcode map */ + + cpustate->opcode_map = COP410_OPCODE_MAP; +} + +static void cop420_init_opcodes(device_t *device) +{ + cop400_state *cpustate = get_safe_token(device); + int i; + + /* set up the state table */ + + cpustate->featuremask = COP420_FEATURE; + define_state_table(device); + + /* initialize instruction length array */ + + for (i=0; i<256; i++) cpustate->InstLen[i]=1; + + cpustate->InstLen[0x60] = cpustate->InstLen[0x61] = cpustate->InstLen[0x62] = cpustate->InstLen[0x63] = + cpustate->InstLen[0x68] = cpustate->InstLen[0x69] = cpustate->InstLen[0x6a] = cpustate->InstLen[0x6b] = + cpustate->InstLen[0x33] = cpustate->InstLen[0x23] = 2; + + /* initialize LBI opcode array */ + + for (i=0x00; i<0x100; i++) cpustate->LBIops[i] = 0; + for (i=0x08; i<0x10; i++) cpustate->LBIops[i] = 1; + for (i=0x18; i<0x20; i++) cpustate->LBIops[i] = 1; + for (i=0x28; i<0x30; i++) cpustate->LBIops[i] = 1; + for (i=0x38; i<0x40; i++) cpustate->LBIops[i] = 1; + + for (i=0; i<256; i++) cpustate->LBIops33[i] = 0; + for (i=0x80; i<0xc0; i++) cpustate->LBIops33[i] = 1; + + /* select opcode map */ + + cpustate->opcode_map = COP420_OPCODE_MAP; +} + +static void cop444_init_opcodes(device_t *device) +{ + cop400_state *cpustate = get_safe_token(device); + int i; + + /* set up the state table */ + + cpustate->featuremask = COP444_FEATURE; + define_state_table(device); + + /* initialize instruction length array */ + + for (i=0; i<256; i++) cpustate->InstLen[i]=1; + + cpustate->InstLen[0x60] = cpustate->InstLen[0x61] = cpustate->InstLen[0x62] = cpustate->InstLen[0x63] = + cpustate->InstLen[0x68] = cpustate->InstLen[0x69] = cpustate->InstLen[0x6a] = cpustate->InstLen[0x6b] = + cpustate->InstLen[0x33] = cpustate->InstLen[0x23] = 2; + + /* initialize LBI opcode array */ + + for (i=0x00; i<0x100; i++) cpustate->LBIops[i] = 0; + for (i=0x08; i<0x10; i++) cpustate->LBIops[i] = 1; + for (i=0x18; i<0x20; i++) cpustate->LBIops[i] = 1; + for (i=0x28; i<0x30; i++) cpustate->LBIops[i] = 1; + for (i=0x38; i<0x40; i++) cpustate->LBIops[i] = 1; + + for (i=0; i<256; i++) cpustate->LBIops33[i] = 0; + for (i=0x80; i<0xc0; i++) cpustate->LBIops33[i] = 1; + + /* select opcode map */ + + cpustate->opcode_map = COP444_OPCODE_MAP; +} + +static CPU_INIT( cop410 ) +{ + cop410_init_opcodes(device); + cop400_init(device, 0xf, 0xf, 0, 0, 0); +} + +static CPU_INIT( cop411 ) +{ + cop410_init_opcodes(device); + cop400_init(device, 0x7, 0x3, 0, 0, 0); +} + +static CPU_INIT( cop420 ) +{ + cop420_init_opcodes(device); + cop400_init(device, 0xf, 0xf, 0xf, 1, 1); +} + +static CPU_INIT( cop421 ) +{ + cop420_init_opcodes(device); + cop400_init(device, 0xf, 0xf, 0, 1, 0); +} + +static CPU_INIT( cop422 ) +{ + cop420_init_opcodes(device); + cop400_init(device, 0xe, 0xe, 0, 1, 0); +} + +static CPU_INIT( cop444 ) +{ + cop444_init_opcodes(device); + cop400_init(device, 0xf, 0xf, 0xf, 1, 1); +} + +static CPU_INIT( cop425 ) +{ + cop444_init_opcodes(device); + cop400_init(device, 0xf, 0xf, 0, 1, 0); +} + +static CPU_INIT( cop426 ) +{ + cop444_init_opcodes(device); + cop400_init(device, 0xe, 0xe, 0xf, 1, 1); +} + +static CPU_INIT( cop445 ) +{ + cop444_init_opcodes(device); + cop400_init(device, 0x7, 0x3, 0, 1, 0); +} + +/*************************************************************************** + RESET +***************************************************************************/ + +static CPU_RESET( cop400 ) +{ + cop400_state *cpustate = get_safe_token(device); + + PC = 0; + A = 0; + B = 0; + C = 0; + OUT_D(0); + EN = 0; + WRITE_G(cpustate, 0); + SKL = 1; + + T = 0; + cpustate->skt_latch = 1; + + cpustate->halt = 0; + cpustate->idle = 0; +} + +/*************************************************************************** + EXECUTION +***************************************************************************/ + +static CPU_EXECUTE( cop400 ) +{ + cop400_state *cpustate = get_safe_token(device); + + UINT8 opcode; + + do + { + cpustate->prevpc = PC; + + debugger_instruction_hook(device, PC); + + if (cpustate->intf->cko == COP400_CKO_HALT_IO_PORT) + { + cpustate->halt = IN_CKO(); + } + + if (cpustate->halt) + { + cpustate->icount -= 1; + continue; + } + + opcode = ROM(PC); + + if (cpustate->skip_lbi) + { + int is_lbi = 0; + + if (opcode == 0x33) + { + is_lbi = cpustate->LBIops33[ROM(PC+1)]; + } + else + { + is_lbi = cpustate->LBIops[opcode]; + } + + if (is_lbi) + { + cpustate->icount -= cpustate->opcode_map[opcode].cycles; + + PC += cpustate->InstLen[opcode]; + } + else + { + cpustate->skip_lbi = 0; + } + } + + if (!cpustate->skip_lbi) + { + int inst_cycles = cpustate->opcode_map[opcode].cycles; + + PC++; + + (*(cpustate->opcode_map[opcode].function))(cpustate, opcode); + cpustate->icount -= inst_cycles; + + // check for interrupt + + if (BIT(EN, 1) && BIT(IL, 1)) + { + cop400_opcode_func function = cpustate->opcode_map[ROM(PC)].function; + + if ((function != jp) && (function != jmp) && (function != jsr)) + { + // store skip logic + cpustate->last_skip = cpustate->skip; + cpustate->skip = 0; + + // push next PC + PUSH(cpustate, PC); + + // jump to interrupt service routine + PC = 0x0ff; + + // disable interrupt + EN &= ~0x02; + } + + IL &= ~2; + } + + // skip next instruction? + + if (cpustate->skip) + { + cop400_opcode_func function = cpustate->opcode_map[ROM(PC)].function; + + opcode = ROM(PC); + + if ((function == lqid) || (function == jid)) + { + cpustate->icount -= 1; + } + else + { + cpustate->icount -= cpustate->opcode_map[opcode].cycles; + } + + PC += cpustate->InstLen[opcode]; + + cpustate->skip = 0; + } + } + } while (cpustate->icount > 0); +} + +/*************************************************************************** + ADDRESS MAPS +***************************************************************************/ + +static ADDRESS_MAP_START( program_512b, AS_PROGRAM, 8, legacy_cpu_device ) + AM_RANGE(0x000, 0x1ff) AM_ROM +ADDRESS_MAP_END + +static ADDRESS_MAP_START( program_1kb, AS_PROGRAM, 8, legacy_cpu_device ) + AM_RANGE(0x000, 0x3ff) AM_ROM +ADDRESS_MAP_END + +static ADDRESS_MAP_START( program_2kb, AS_PROGRAM, 8, legacy_cpu_device ) + AM_RANGE(0x000, 0x7ff) AM_ROM +ADDRESS_MAP_END + +static ADDRESS_MAP_START( data_32b, AS_DATA, 8, legacy_cpu_device ) + AM_RANGE(0x00, 0x1f) AM_RAM +ADDRESS_MAP_END + +static ADDRESS_MAP_START( data_64b, AS_DATA, 8, legacy_cpu_device ) + AM_RANGE(0x00, 0x3f) AM_RAM +ADDRESS_MAP_END + +static ADDRESS_MAP_START( data_128b, AS_DATA, 8, legacy_cpu_device ) + AM_RANGE(0x00, 0x7f) AM_RAM +ADDRESS_MAP_END + +#ifdef UNUSED_CODE +static ADDRESS_MAP_START( data_160b, AS_DATA, 8, legacy_cpu_device ) + AM_RANGE(0x00, 0x9f) AM_RAM +ADDRESS_MAP_END +#endif + +/*************************************************************************** + VALIDITY CHECKS +***************************************************************************/ + +#if 0 +static CPU_VALIDITY_CHECK( cop410 ) +{ + int error = FALSE; + const cop400_interface *intf = (const cop400_interface *) config; + + if ((intf == NULL) || (intf->cki <= 0)) + { + mame_printf_error("%s: %s has an invalid CPU configuration\n", driver->source_file, driver->name); + error = TRUE; + } + + return error; +} + +static CPU_VALIDITY_CHECK( cop420 ) +{ + int error = FALSE; + const cop400_interface *intf = (const cop400_interface *) config; + + if ((intf == NULL) || (intf->cki <= 0)) + { + mame_printf_error("%s: %s has an invalid CPU configuration\n", driver->source_file, driver->name); + error = TRUE; + } + + return error; +} + +static CPU_VALIDITY_CHECK( cop421 ) +{ + int error = FALSE; + const cop400_interface *intf = (const cop400_interface *) config; + + if ((intf == NULL) || (intf->cki <= 0) || (intf->microbus == COP400_MICROBUS_ENABLED)) + { + mame_printf_error("%s: %s has an invalid CPU configuration\n", driver->source_file, driver->name); + error = TRUE; + } + + return error; +} + +static CPU_VALIDITY_CHECK( cop444 ) +{ + int error = FALSE; + const cop400_interface *intf = (const cop400_interface *) config; + + if ((intf == NULL) || (intf->cki <= 0)) + { + mame_printf_error("%s: %s has an invalid CPU configuration\n", driver->source_file, driver->name); + error = TRUE; + } + + return error; +} +#endif + +/*************************************************************************** + GENERAL CONTEXT ACCESS +***************************************************************************/ + +static CPU_IMPORT_STATE( cop400 ) +{ + cop400_state *cpustate = get_safe_token(device); + + switch (entry.index()) + { + case STATE_GENFLAGS: + cpustate->c = (cpustate->flags >> 1) & 1; + cpustate->skl = (cpustate->flags >> 0) & 1; + break; + } +} + +static CPU_EXPORT_STATE( cop400 ) +{ + cop400_state *cpustate = get_safe_token(device); + + switch (entry.index()) + { + case STATE_GENFLAGS: + cpustate->flags = (cpustate->c ? 0x02 : 0x00) | + (cpustate->skl ? 0x01 : 0x00); + break; + } +} + +static CPU_EXPORT_STRING( cop400 ) +{ + cop400_state *cpustate = get_safe_token(device); + + switch (entry.index()) + { + case STATE_GENFLAGS: + string.printf("%c%c", + cpustate->c ? 'C' : '.', + cpustate->skl ? 'S' : '.'); + break; + } +} + +static CPU_SET_INFO( cop400 ) +{ + /* nothing to set */ +} + +static CPU_GET_INFO( cop400 ) +{ + cop400_state *cpustate = (device != NULL && device->token() != NULL) ? get_safe_token(device) : NULL; + cop400_interface *intf = (device->static_config() != NULL) ? (cop400_interface *)device->static_config() : NULL; + + switch (state) + { + /* --- the following bits of info are returned as 64-bit signed integers --- */ + case CPUINFO_INT_CONTEXT_SIZE: info->i = sizeof(cop400_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 = (intf != NULL) ? intf->cki : 16; 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 = 1; break; + case CPUINFO_INT_MAX_CYCLES: info->i = 2; break; + + case DEVINFO_INT_DATABUS_WIDTH + AS_PROGRAM: info->i = 8; break; + case DEVINFO_INT_ADDRBUS_WIDTH + AS_PROGRAM: /* set per-core */ break; + case DEVINFO_INT_ADDRBUS_SHIFT + AS_PROGRAM: info->i = 0; break; + case DEVINFO_INT_DATABUS_WIDTH + AS_DATA: info->i = 8; /* really 4 */ break; + case DEVINFO_INT_ADDRBUS_WIDTH + AS_DATA: /* set per-core */ break; + case DEVINFO_INT_ADDRBUS_SHIFT + AS_DATA: info->i = 0; break; + case DEVINFO_INT_DATABUS_WIDTH + AS_IO: info->i = 8; break; + case DEVINFO_INT_ADDRBUS_WIDTH + AS_IO: info->i = 9; 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(cop400); break; + case CPUINFO_FCT_INIT: /* set per-core */ break; + case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(cop400); break; + case CPUINFO_FCT_EXECUTE: info->execute = CPU_EXECUTE_NAME(cop400); break; + case CPUINFO_FCT_DISASSEMBLE: /* set per-core */ break; +// case CPUINFO_FCT_VALIDITY_CHECK: /* set per-core */ break; + case CPUINFO_FCT_IMPORT_STATE: info->import_state = CPU_IMPORT_STATE_NAME(cop400); break; + case CPUINFO_FCT_EXPORT_STATE: info->export_state = CPU_EXPORT_STATE_NAME(cop400); break; + case CPUINFO_FCT_EXPORT_STRING: info->export_string = CPU_EXPORT_STRING_NAME(cop400); break; + + /* --- the following bits of info are returned as pointers --- */ + case CPUINFO_PTR_INSTRUCTION_COUNTER: info->icount = &cpustate->icount; break; + case DEVINFO_PTR_INTERNAL_MEMORY_MAP + AS_PROGRAM: /* set per-core */ break; + case DEVINFO_PTR_INTERNAL_MEMORY_MAP + AS_DATA: /* set per-core */ break; + + /* --- the following bits of info are returned as NULL-terminated strings --- */ + case DEVINFO_STR_NAME: strcpy(info->s, "COP400"); break; + case DEVINFO_STR_FAMILY: strcpy(info->s, "National Semiconductor COPS"); 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 MAME Team"); break; + } +} + +/*************************************************************************** + CPU-SPECIFIC CONTEXT ACCESS +***************************************************************************/ + +CPU_GET_INFO( cop410 ) +{ + switch (state) + { + /* --- the following bits of info are returned as 64-bit signed integers --- */ + case DEVINFO_INT_ADDRBUS_WIDTH + AS_PROGRAM: info->i = 9; break; + case DEVINFO_INT_ADDRBUS_WIDTH + AS_DATA: info->i = 5; break; + + /* --- the following bits of info are returned as pointers to functions --- */ + case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(cop410); break; + case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(cop410); break; +// case CPUINFO_FCT_VALIDITY_CHECK: info->validity_check = CPU_VALIDITY_CHECK_NAME(cop410); break; + + /* --- the following bits of info are returned as pointers --- */ + case DEVINFO_PTR_INTERNAL_MEMORY_MAP + AS_PROGRAM: info->internal_map8 = ADDRESS_MAP_NAME(program_512b); break; + case DEVINFO_PTR_INTERNAL_MEMORY_MAP + AS_DATA: info->internal_map8 = ADDRESS_MAP_NAME(data_32b); break; + + /* --- the following bits of info are returned as NULL-terminated strings --- */ + case DEVINFO_STR_NAME: strcpy(info->s, "COP410"); break; + + default: CPU_GET_INFO_CALL(cop400); break; + } +} + +CPU_GET_INFO( cop411 ) +{ + // COP411 is a 20-pin package version of the COP410, missing D2/D3/G3/CKO + + switch (state) + { + /* --- the following bits of info are returned as pointers to data or functions --- */ + case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(cop411); break; + + /* --- the following bits of info are returned as NULL-terminated strings --- */ + case DEVINFO_STR_NAME: strcpy(info->s, "COP411"); break; + + default: CPU_GET_INFO_CALL(cop410); break; + } +} + +CPU_GET_INFO( cop401 ) +{ + // COP401 is a ROMless version of the COP410 + + switch (state) + { + /* --- the following bits of info are returned as pointers --- */ + case DEVINFO_PTR_INTERNAL_MEMORY_MAP + AS_PROGRAM: info->internal_map8 = NULL; break; + + /* --- the following bits of info are returned as NULL-terminated strings --- */ + case DEVINFO_STR_NAME: strcpy(info->s, "COP401"); break; + + default: CPU_GET_INFO_CALL(cop410); break; + } +} + +CPU_GET_INFO( cop420 ) +{ + cop400_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 DEVINFO_INT_ADDRBUS_WIDTH + AS_PROGRAM: info->i = 10; break; + case DEVINFO_INT_ADDRBUS_WIDTH + AS_DATA: info->i = 6; break; + + /* --- the following bits of info are returned as pointers to functions --- */ + case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(cop420); break; + case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(cop420); break; +// case CPUINFO_FCT_VALIDITY_CHECK: info->validity_check = CPU_VALIDITY_CHECK_NAME(cop420); break; + + /* --- the following bits of info are returned as pointers --- */ + case DEVINFO_PTR_INTERNAL_MEMORY_MAP + AS_PROGRAM: info->internal_map8 = ADDRESS_MAP_NAME(program_1kb); break; + case DEVINFO_PTR_INTERNAL_MEMORY_MAP + AS_DATA: info->internal_map8 = ADDRESS_MAP_NAME(data_64b); break; + + /* --- the following bits of info are returned as NULL-terminated strings --- */ + case DEVINFO_STR_NAME: strcpy(info->s, "COP420"); break; + + case CPUINFO_STR_FLAGS: sprintf(info->s, + "%c%c%c", + cpustate->c ? 'C' : '.', + cpustate->skl ? 'S' : '.', + cpustate->skt_latch ? 'T' : '.'); break; + + default: CPU_GET_INFO_CALL(cop400); break; + } +} + +CPU_GET_INFO( cop421 ) +{ + // COP421 is a 24-pin package version of the COP420, lacking the IN ports + + switch (state) + { + /* --- the following bits of info are returned as pointers to data or functions --- */ + case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(cop421); break; +// case CPUINFO_FCT_VALIDITY_CHECK: info->validity_check = CPU_VALIDITY_CHECK_NAME(cop421); break; + + /* --- the following bits of info are returned as NULL-terminated strings --- */ + case DEVINFO_STR_NAME: strcpy(info->s, "COP421"); break; + + default: CPU_GET_INFO_CALL(cop420); break; + } +} + +CPU_GET_INFO( cop422 ) +{ + // COP422 is a 20-pin package version of the COP420, lacking G0/G1, D0/D1, and the IN ports + + switch (state) + { + /* --- the following bits of info are returned as pointers to data or functions --- */ + case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(cop422); break; + + /* --- the following bits of info are returned as NULL-terminated strings --- */ + case DEVINFO_STR_NAME: strcpy(info->s, "COP422"); break; + + default: CPU_GET_INFO_CALL(cop421); break; + } +} + +CPU_GET_INFO( cop402 ) +{ + // COP402 is a ROMless version of the COP420 + + switch (state) + { + /* --- the following bits of info are returned as pointers to data or functions --- */ + case DEVINFO_PTR_INTERNAL_MEMORY_MAP + AS_PROGRAM: info->internal_map8 = NULL; break; + + /* --- the following bits of info are returned as NULL-terminated strings --- */ + case DEVINFO_STR_NAME: strcpy(info->s, "COP402"); break; + + default: CPU_GET_INFO_CALL(cop420); break; + } +} + +CPU_GET_INFO( cop444 ) +{ + cop400_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 DEVINFO_INT_ADDRBUS_WIDTH + AS_PROGRAM: info->i = 11; break; + case DEVINFO_INT_ADDRBUS_WIDTH + AS_DATA: info->i = 7; break; + + /* --- the following bits of info are returned as pointers to functions --- */ + case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(cop444); break; + case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(cop444); break; +// case CPUINFO_FCT_VALIDITY_CHECK: info->validity_check = CPU_VALIDITY_CHECK_NAME(cop444); break; + + /* --- the following bits of info are returned as pointers --- */ + case DEVINFO_PTR_INTERNAL_MEMORY_MAP + AS_PROGRAM: info->internal_map8 = ADDRESS_MAP_NAME(program_2kb); break; + case DEVINFO_PTR_INTERNAL_MEMORY_MAP + AS_DATA: info->internal_map8 = ADDRESS_MAP_NAME(data_128b); break; + + /* --- the following bits of info are returned as NULL-terminated strings --- */ + case DEVINFO_STR_NAME: strcpy(info->s, "COP444"); break; + + case CPUINFO_STR_FLAGS: sprintf(info->s, + "%c%c%c", + cpustate->c ? 'C' : '.', + cpustate->skl ? 'S' : '.', + cpustate->skt_latch ? 'T' : '.'); break; + + default: CPU_GET_INFO_CALL(cop400); break; + } +} + +CPU_GET_INFO( cop445 ) +{ + // COP445 is a 24-pin package version of the COP444, lacking the IN ports + + switch (state) + { + /* --- the following bits of info are returned as pointers to data or functions --- */ + case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(cop445); break; + + /* --- the following bits of info are returned as NULL-terminated strings --- */ + case DEVINFO_STR_NAME: strcpy(info->s, "COP445"); break; + + default: CPU_GET_INFO_CALL(cop444); break; + } +} + +CPU_GET_INFO( cop424 ) +{ + // COP424 is functionally equivalent to COP444, with only 1K ROM and 64x4 bytes RAM + + switch (state) + { + /* --- the following bits of info are returned as 64-bit signed integers --- */ + case DEVINFO_INT_ADDRBUS_WIDTH + AS_PROGRAM: info->i = 10; break; + case DEVINFO_INT_ADDRBUS_WIDTH + AS_DATA: info->i = 6; break; + + /* --- the following bits of info are returned as pointers to data or functions --- */ + case DEVINFO_PTR_INTERNAL_MEMORY_MAP + AS_PROGRAM: info->internal_map8 = ADDRESS_MAP_NAME(program_1kb); break; + case DEVINFO_PTR_INTERNAL_MEMORY_MAP + AS_DATA: info->internal_map8 = ADDRESS_MAP_NAME(data_64b); break; + + /* --- the following bits of info are returned as NULL-terminated strings --- */ + case DEVINFO_STR_NAME: strcpy(info->s, "COP424"); break; + + default: CPU_GET_INFO_CALL(cop444); break; + } +} + +CPU_GET_INFO( cop425 ) +{ + // COP425 is a 24-pin package version of the COP424, lacking the IN ports + + switch (state) + { + /* --- the following bits of info are returned as pointers to data or functions --- */ + case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(cop425); break; + + /* --- the following bits of info are returned as NULL-terminated strings --- */ + case DEVINFO_STR_NAME: strcpy(info->s, "COP425"); break; + + default: CPU_GET_INFO_CALL(cop424); break; + } +} + +CPU_GET_INFO( cop426 ) +{ + // COP426 is a 20-pin package version of the COP424, with only L0-L7, G2-G3, D2-D3 ports + + switch (state) + { + /* --- the following bits of info are returned as pointers to data or functions --- */ + case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(cop426); break; + + /* --- the following bits of info are returned as NULL-terminated strings --- */ + case DEVINFO_STR_NAME: strcpy(info->s, "COP426"); break; + + default: CPU_GET_INFO_CALL(cop424); break; + } +} + +CPU_GET_INFO( cop404 ) +{ + // COP404 is a ROMless version of the COP444, which can emulate a COP410C/COP411C, COP424C/COP425C, or a COP444C/COP445C + + switch (state) + { + /* --- the following bits of info are returned as pointers to data or functions --- */ + case DEVINFO_PTR_INTERNAL_MEMORY_MAP + AS_PROGRAM: info->internal_map8 = NULL; break; + + /* --- the following bits of info are returned as NULL-terminated strings --- */ + case DEVINFO_STR_NAME: strcpy(info->s, "COP404"); break; + + default: CPU_GET_INFO_CALL(cop444); break; + } +} + +/* COP410 family */ +DEFINE_LEGACY_CPU_DEVICE(COP401, cop401); +DEFINE_LEGACY_CPU_DEVICE(COP410, cop410); +DEFINE_LEGACY_CPU_DEVICE(COP411, cop411); + +/* COP420 family */ +DEFINE_LEGACY_CPU_DEVICE(COP402, cop402); +DEFINE_LEGACY_CPU_DEVICE(COP420, cop420); +DEFINE_LEGACY_CPU_DEVICE(COP421, cop421); +DEFINE_LEGACY_CPU_DEVICE(COP422, cop422); + +/* COP444 family */ +DEFINE_LEGACY_CPU_DEVICE(COP404, cop404); +DEFINE_LEGACY_CPU_DEVICE(COP424, cop424); +DEFINE_LEGACY_CPU_DEVICE(COP425, cop425); +DEFINE_LEGACY_CPU_DEVICE(COP426, cop426); +DEFINE_LEGACY_CPU_DEVICE(COP444, cop444); +DEFINE_LEGACY_CPU_DEVICE(COP445, cop445); |