Pointerized the COP400 CPU cores.

This commit is contained in:
Curt Coder 2008-11-18 17:15:40 +00:00
parent 09da237dcd
commit a8475e4c1e
15 changed files with 1793 additions and 662 deletions

3
.gitattributes vendored
View File

@ -51,11 +51,14 @@ src/emu/cpu/cdp1802/cdp1802.c svneol=native#text/plain
src/emu/cpu/cdp1802/cdp1802.h svneol=native#text/plain
src/emu/cpu/cop400/410ops.c svneol=native#text/plain
src/emu/cpu/cop400/420ops.c svneol=native#text/plain
src/emu/cpu/cop400/440ops.c svneol=native#text/plain
src/emu/cpu/cop400/cop400.h svneol=native#text/plain
src/emu/cpu/cop400/cop410.c svneol=native#text/plain
src/emu/cpu/cop400/cop410ds.c svneol=native#text/plain
src/emu/cpu/cop400/cop420.c svneol=native#text/plain
src/emu/cpu/cop400/cop420ds.c svneol=native#text/plain
src/emu/cpu/cop400/cop440.c svneol=native#text/plain
src/emu/cpu/cop400/cop440ds.c svneol=native#text/plain
src/emu/cpu/cp1610/1610dasm.c svneol=native#text/plain
src/emu/cpu/cp1610/cp1610.c svneol=native#text/plain
src/emu/cpu/cp1610/cp1610.h svneol=native#text/plain

View File

@ -9,7 +9,73 @@
***************************************************************************/
#define INSTRUCTION(mnemonic) INLINE void (mnemonic)(UINT8 opcode)
#define UINT1 UINT8
#define UINT4 UINT8
#define UINT6 UINT8
#define UINT10 UINT16
typedef struct _cop400_state cop400_state;
struct _cop400_state
{
const cop400_interface *intf;
/* registers */
UINT10 pc; /* 11-bit ROM address program counter */
UINT10 prevpc; /* previous value of program counter */
UINT4 a; /* 4-bit accumulator */
UINT8 b; /* 5/6/7-bit RAM address register */
UINT1 c; /* 1-bit carry register */
UINT4 en; /* 4-bit enable register */
UINT4 g; /* 4-bit general purpose I/O port */
UINT8 q; /* 8-bit latch for L port */
UINT10 sa, sb, sc; /* subroutine save registers */
UINT4 sio; /* 4-bit shift register and counter */
UINT1 skl; /* 1-bit latch for SK output */
UINT8 si; /* serial input */
/* 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 */
UINT4 il; /* IN latch */
UINT4 in[4]; /* IN port shift register */
/* 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 device_config *device;
/* timers */
emu_timer *serial_timer;
emu_timer *counter_timer;
emu_timer *inil_timer;
emu_timer *microbus_timer;
};
/* The opcode table now is a combination of cycle counts and function pointers */
typedef struct {
unsigned cycles;
void (*function) (cop400_state *cop400, UINT8 opcode);
} s_opcode;
#define INSTRUCTION(mnemonic) INLINE void (mnemonic)(cop400_state *cop400, UINT8 opcode)
#define ROM(addr) program_decrypted_read_byte(addr)
#define RAM_W(addr, value) (data_write_byte_8le(addr, value))
@ -18,28 +84,26 @@
#define IN(addr) io_read_byte_8le(addr)
#define OUT(addr, value) io_write_byte_8le(addr, value)
#define A R.A
#define B R.B
#define C R.C
#define G R.G
#define Q R.Q
#define EN R.EN
#define SA R.SA
#define SB R.SB
#define SIO R.SIO
#define SKL R.SKL
#define PC R.PC
#define prevPC R.PREVPC
#define skip R.skip
#define skipLBI R.skipLBI
#define A cop400->a
#define B cop400->b
#define C cop400->c
#define G cop400->g
#define Q cop400->q
#define EN cop400->en
#define SA cop400->sa
#define SB cop400->sb
#define SIO cop400->sio
#define SKL cop400->skl
#define PC cop400->pc
#define prevPC cop400->prevpc
#define IN_G() IN(COP400_PORT_G)
#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 OUT_G(A) OUT(COP400_PORT_G, (A) & R.G_mask)
#define OUT_G(A) OUT(COP400_PORT_G, (A) & cop400->g_mask)
#define OUT_L(A) OUT(COP400_PORT_L, (A))
#define OUT_D(A) OUT(COP400_PORT_D, (A) & R.D_mask)
#define OUT_D(A) OUT(COP400_PORT_D, (A) & cop400->d_mask)
#define OUT_SK(A) OUT(COP400_PORT_SK, (A))
#define OUT_SO(A) OUT(COP400_PORT_SIO, (A))
@ -50,11 +114,11 @@
/* Serial I/O */
static TIMER_CALLBACK(cop410_serial_tick)
static TIMER_CALLBACK( cop400_serial_tick )
{
int cpunum = param;
cop400_state *cop400 = ptr;
cpu_push_context(machine->cpu[cpunum]);
cpu_push_context(cop400->device);
if (BIT(EN, 0))
{
@ -76,10 +140,10 @@ static TIMER_CALLBACK(cop410_serial_tick)
// serial input
R.si <<= 1;
R.si = (R.si & 0x0e) | IN_SI();
cop400->si <<= 1;
cop400->si = (cop400->si & 0x0e) | IN_SI();
if ((R.si & 0x0f) == 0x0c) // 1100
if ((cop400->si & 0x0f) == 0x0c) // 1100
{
SIO--;
SIO &= 0x0f;
@ -129,7 +193,7 @@ static TIMER_CALLBACK(cop410_serial_tick)
cpu_pop_context();
}
INLINE void WRITE_Q(UINT8 data)
INLINE void WRITE_Q(cop400_state *cop400, UINT8 data)
{
Q = data;
@ -139,11 +203,11 @@ INLINE void WRITE_Q(UINT8 data)
}
}
INLINE void WRITE_G(UINT8 data)
INLINE void WRITE_G(cop400_state *cop400, UINT8 data)
{
if (R.intf->microbus == COP400_MICROBUS_ENABLED)
if (cop400->intf->microbus == COP400_MICROBUS_ENABLED)
{
data = (data & 0x0e) | R.microbus_int;
data = (data & 0x0e) | cop400->microbus_int;
}
G = data;
@ -181,7 +245,7 @@ INSTRUCTION(asc)
if (A > 0xF)
{
C = 1;
skip = 1;
cop400->skip = 1;
A &= 0xF;
}
else
@ -203,7 +267,7 @@ INSTRUCTION(asc)
*/
INSTRUCTION(add)
INSTRUCTION( add )
{
A = (A + RAM_R(B)) & 0x0F;
}
@ -224,7 +288,7 @@ INSTRUCTION(add)
*/
INSTRUCTION(aisc)
INSTRUCTION( aisc )
{
UINT4 y = opcode & 0x0f;
@ -232,7 +296,7 @@ INSTRUCTION(aisc)
if (A > 0x0f)
{
skip = 1;
cop400->skip = 1;
A &= 0xF;
}
}
@ -250,7 +314,7 @@ INSTRUCTION(aisc)
*/
INSTRUCTION(clra)
INSTRUCTION( clra )
{
A = 0;
}
@ -268,7 +332,7 @@ INSTRUCTION(clra)
*/
INSTRUCTION(comp)
INSTRUCTION( comp )
{
A = A ^ 0xF;
}
@ -284,7 +348,7 @@ INSTRUCTION(comp)
*/
INSTRUCTION(nop)
INSTRUCTION( nop )
{
// do nothing
}
@ -302,7 +366,7 @@ INSTRUCTION(nop)
*/
INSTRUCTION(rc)
INSTRUCTION( rc )
{
C = 0;
}
@ -320,7 +384,7 @@ INSTRUCTION(rc)
*/
INSTRUCTION(sc)
INSTRUCTION( sc )
{
C = 1;
}
@ -338,7 +402,7 @@ INSTRUCTION(sc)
*/
INSTRUCTION(xor)
INSTRUCTION( xor )
{
A = A ^ RAM_R(B);
}
@ -358,7 +422,7 @@ INSTRUCTION(xor)
*/
INSTRUCTION(jid)
INSTRUCTION( jid )
{
UINT16 addr = (PC & 0x300) | (A << 4) | RAM_R(B);
PC = (PC & 0x300) | ROM(addr);
@ -378,7 +442,7 @@ INSTRUCTION(jid)
*/
INSTRUCTION(jmp)
INSTRUCTION( jmp )
{
UINT16 a = ((opcode & 0x03) << 8) | ROM(PC);
@ -405,7 +469,7 @@ INSTRUCTION(jmp)
*/
INSTRUCTION(jp)
INSTRUCTION( jp )
{
UINT4 page = PC >> 6;
@ -443,7 +507,7 @@ INSTRUCTION(jp)
*/
INSTRUCTION(jsr)
INSTRUCTION( jsr )
{
UINT16 a = ((opcode & 0x03) << 8) | ROM(PC);
@ -464,7 +528,7 @@ INSTRUCTION(jsr)
*/
INSTRUCTION(ret)
INSTRUCTION( ret )
{
POP();
}
@ -484,10 +548,10 @@ INSTRUCTION(ret)
*/
INSTRUCTION(retsk)
INSTRUCTION( retsk )
{
POP();
skip = 1;
cop400->skip = 1;
}
/*
@ -503,9 +567,9 @@ INSTRUCTION(retsk)
*/
INSTRUCTION(halt)
INSTRUCTION( halt )
{
R.halt = 1;
cop400->halt = 1;
}
/* Memory Reference Instructions */
@ -524,7 +588,7 @@ INSTRUCTION(halt)
*/
INSTRUCTION(camq)
INSTRUCTION( camq )
{
/*
@ -559,11 +623,11 @@ INSTRUCTION(camq)
UINT8 data = (A << 4) | RAM_R(B);
WRITE_Q(data);
WRITE_Q(cop400, data);
#ifdef CAMQ_BUG
WRITE_Q(0x3c);
WRITE_Q(data);
WRITE_Q(cop400, 0x3c);
WRITE_Q(cop400, data);
#endif
}
@ -582,7 +646,7 @@ INSTRUCTION(camq)
*/
INSTRUCTION(ld)
INSTRUCTION( ld )
{
UINT8 r = opcode & 0x30;
@ -604,11 +668,11 @@ INSTRUCTION(ld)
*/
INSTRUCTION(lqid)
INSTRUCTION( lqid )
{
PUSH(PC);
PC = (PC & 0x300) | (A << 4) | RAM_R(B);
WRITE_Q(ROM(PC));
WRITE_Q(cop400, ROM(PC));
POP();
}
@ -640,10 +704,10 @@ INSTRUCTION(lqid)
*/
INSTRUCTION(rmb0) { RAM_W(B, RAM_R(B) & 0xE); }
INSTRUCTION(rmb1) { RAM_W(B, RAM_R(B) & 0xD); }
INSTRUCTION(rmb2) { RAM_W(B, RAM_R(B) & 0xB); }
INSTRUCTION(rmb3) { RAM_W(B, RAM_R(B) & 0x7); }
INSTRUCTION( rmb0 ) { RAM_W(B, RAM_R(B) & 0xE); }
INSTRUCTION( rmb1 ) { RAM_W(B, RAM_R(B) & 0xD); }
INSTRUCTION( rmb2 ) { RAM_W(B, RAM_R(B) & 0xB); }
INSTRUCTION( rmb3 ) { RAM_W(B, RAM_R(B) & 0x7); }
/*
@ -673,10 +737,10 @@ INSTRUCTION(rmb3) { RAM_W(B, RAM_R(B) & 0x7); }
*/
INSTRUCTION(smb0) { RAM_W(B, RAM_R(B) | 0x1); }
INSTRUCTION(smb1) { RAM_W(B, RAM_R(B) | 0x2); }
INSTRUCTION(smb2) { RAM_W(B, RAM_R(B) | 0x4); }
INSTRUCTION(smb3) { RAM_W(B, RAM_R(B) | 0x8); }
INSTRUCTION( smb0 ) { RAM_W(B, RAM_R(B) | 0x1); }
INSTRUCTION( smb1 ) { RAM_W(B, RAM_R(B) | 0x2); }
INSTRUCTION( smb2 ) { RAM_W(B, RAM_R(B) | 0x4); }
INSTRUCTION( smb3 ) { RAM_W(B, RAM_R(B) | 0x8); }
/*
@ -693,7 +757,7 @@ INSTRUCTION(smb3) { RAM_W(B, RAM_R(B) | 0x8); }
*/
INSTRUCTION(stii)
INSTRUCTION( stii )
{
UINT4 y = opcode & 0x0f;
UINT16 Bd;
@ -719,7 +783,7 @@ INSTRUCTION(stii)
*/
INSTRUCTION(x)
INSTRUCTION( x )
{
UINT4 r = opcode & 0x30;
UINT8 t = RAM_R(B);
@ -744,7 +808,7 @@ INSTRUCTION(x)
*/
INSTRUCTION(xad)
INSTRUCTION( xad )
{
UINT8 rd = opcode & 0x3f;
UINT8 t = A;
@ -772,7 +836,7 @@ INSTRUCTION(xad)
*/
INSTRUCTION(xds)
INSTRUCTION( xds )
{
UINT8 t, Bd;
UINT4 r = opcode & 0x30;
@ -786,7 +850,7 @@ INSTRUCTION(xds)
B = B ^ r;
if (Bd == 0x0f) skip = 1;
if (Bd == 0x0f) cop400->skip = 1;
}
/*
@ -807,7 +871,7 @@ INSTRUCTION(xds)
*/
INSTRUCTION(xis)
INSTRUCTION( xis )
{
UINT8 t, Bd;
UINT4 r = opcode & 0x30;
@ -821,7 +885,7 @@ INSTRUCTION(xis)
B = B ^ r;
if (Bd == 0x00) skip = 1;
if (Bd == 0x00) cop400->skip = 1;
}
/* Register Reference Instructions */
@ -839,7 +903,7 @@ INSTRUCTION(xis)
*/
INSTRUCTION(cab)
INSTRUCTION( cab )
{
B = (B & 0x30) | A;
}
@ -857,7 +921,7 @@ INSTRUCTION(cab)
*/
INSTRUCTION(cba)
INSTRUCTION( cba )
{
A = B & 0xF;
}
@ -881,7 +945,7 @@ INSTRUCTION(cba)
*/
INSTRUCTION(lbi)
INSTRUCTION( lbi )
{
if (opcode & 0x80)
{
@ -892,7 +956,7 @@ INSTRUCTION(lbi)
B = (opcode & 0x30) | (((opcode & 0x0f) + 1) & 0x0f);
}
skipLBI = 1;
cop400->skip_lbi = 1;
}
/*
@ -909,7 +973,7 @@ INSTRUCTION(lbi)
*/
INSTRUCTION(lei)
INSTRUCTION( lei )
{
UINT4 y = opcode & 0x0f;
@ -936,9 +1000,9 @@ INSTRUCTION(lei)
*/
INSTRUCTION(skc)
INSTRUCTION( skc )
{
if (C == 1) skip = 1;
if (C == 1) cop400->skip = 1;
}
/*
@ -954,9 +1018,9 @@ INSTRUCTION(skc)
*/
INSTRUCTION(ske)
INSTRUCTION( ske )
{
if (A == RAM_R(B)) skip = 1;
if (A == RAM_R(B)) cop400->skip = 1;
}
/*
@ -972,9 +1036,9 @@ INSTRUCTION(ske)
*/
INSTRUCTION(skgz)
INSTRUCTION( skgz )
{
if (IN_G() == 0) skip = 1;
if (IN_G() == 0) cop400->skip = 1;
}
/*
@ -997,15 +1061,15 @@ INSTRUCTION(skgz)
*/
INLINE void skgbz(int bit)
INLINE void skgbz(cop400_state *cop400, int bit)
{
if (!BIT(IN_G(), bit)) skip = 1;
if (!BIT(IN_G(), bit)) cop400->skip = 1;
}
INSTRUCTION(skgbz0) { skgbz(0); }
INSTRUCTION(skgbz1) { skgbz(1); }
INSTRUCTION(skgbz2) { skgbz(2); }
INSTRUCTION(skgbz3) { skgbz(3); }
INSTRUCTION( skgbz0 ) { skgbz(cop400, 0); }
INSTRUCTION( skgbz1 ) { skgbz(cop400, 1); }
INSTRUCTION( skgbz2 ) { skgbz(cop400, 2); }
INSTRUCTION( skgbz3 ) { skgbz(cop400, 3); }
/*
@ -1027,15 +1091,15 @@ INSTRUCTION(skgbz3) { skgbz(3); }
*/
INLINE void skmbz(int bit)
INLINE void skmbz(cop400_state *cop400, int bit)
{
if (!BIT(RAM_R(B), bit)) skip = 1;
if (!BIT(RAM_R(B), bit)) cop400->skip = 1;
}
INSTRUCTION(skmbz0) { skmbz(0); }
INSTRUCTION(skmbz1) { skmbz(1); }
INSTRUCTION(skmbz2) { skmbz(2); }
INSTRUCTION(skmbz3) { skmbz(3); }
INSTRUCTION( skmbz0 ) { skmbz(cop400, 0); }
INSTRUCTION( skmbz1 ) { skmbz(cop400, 1); }
INSTRUCTION( skmbz2 ) { skmbz(cop400, 2); }
INSTRUCTION( skmbz3 ) { skmbz(cop400, 3); }
/* Input/Output Instructions */
@ -1052,7 +1116,7 @@ INSTRUCTION(skmbz3) { skmbz(3); }
*/
INSTRUCTION(ing)
INSTRUCTION( ing )
{
A = IN_G();
}
@ -1071,7 +1135,7 @@ INSTRUCTION(ing)
*/
INSTRUCTION(inl)
INSTRUCTION( inl )
{
UINT8 L = IN_L();
@ -1092,7 +1156,7 @@ INSTRUCTION(inl)
*/
INSTRUCTION(obd)
INSTRUCTION( obd )
{
OUT_D(B & 0x0f);
}
@ -1110,9 +1174,9 @@ INSTRUCTION(obd)
*/
INSTRUCTION(omg)
INSTRUCTION( omg )
{
WRITE_G(RAM_R(B));
WRITE_G(cop400, RAM_R(B));
}
/*
@ -1129,7 +1193,7 @@ INSTRUCTION(omg)
*/
INSTRUCTION(xas)
INSTRUCTION( xas )
{
UINT8 t = SIO;
SIO = A;

View File

@ -9,15 +9,101 @@
***************************************************************************/
#define SC R.SC
#define IL R.IL
#define T cop400->t
#define SC cop400->sc
#define IL cop400->il
#define PUSH(addr) { SC = SB; SB = SA; SA = addr; }
#define POP() { PC = SA; SA = SB; SB = SC; }
#include "410ops.c"
#define IN_IN() (R.IN_mask ? IN(COP400_PORT_IN) : 0)
#define IN_IN() (cop400->in_mask ? IN(COP400_PORT_IN) : 0)
/* Timer Counter */
static TIMER_CALLBACK( cop400_counter_tick )
{
cop400_state *cop400 = ptr;
cpu_push_context(cop400->device);
T++;
if (T == 0)
{
cop400->skt_latch = 1;
if (cop400->idle)
{
cop400->idle = 0;
cop400->halt = 0;
}
}
cpu_pop_context();
}
/* IN Latches */
static TIMER_CALLBACK( cop400_inil_tick )
{
cop400_state *cop400 = ptr;
UINT8 in;
int i;
cpu_push_context(cop400->device);
in = IN_IN();
for (i = 0; i < 4; i++)
{
cop400->in[i] = (cop400->in[i] << 1) | BIT(in, i);
if ((cop400->in[i] & 0x07) == 0x04) // 100
{
IL |= (1 << i);
}
}
cpu_pop_context();
}
/* Microbus */
static TIMER_CALLBACK( cop400_microbus_tick )
{
cop400_state *cop400 = ptr;
UINT8 in;
cpu_push_context(cop400->device);
in = IN_IN();
if (!BIT(in, 2))
{
// chip select
if (!BIT(in, 1))
{
// read strobe
OUT_L(Q);
cop400->microbus_int = 1;
}
else if (!BIT(in, 3))
{
// write strobe
Q = IN_L();
cop400->microbus_int = 0;
}
}
cpu_pop_context();
}
/* Arithmetic Instructions */
@ -34,7 +120,7 @@
*/
INSTRUCTION(adt)
INSTRUCTION( adt )
{
A = (A + 10) & 0x0F;
}
@ -55,14 +141,14 @@ INSTRUCTION(adt)
*/
INSTRUCTION(casc)
INSTRUCTION( casc )
{
A = (A ^ 0xF) + RAM_R(B) + C;
if (A > 0xF)
{
C = 1;
skip = 1;
cop400->skip = 1;
A &= 0xF;
}
else
@ -86,10 +172,10 @@ INSTRUCTION(casc)
*/
INSTRUCTION(cop420_ret)
INSTRUCTION( cop420_ret )
{
POP();
skip = R.last_skip;
cop400->skip = cop400->last_skip;
}
/* Memory Reference Instructions */
@ -108,7 +194,7 @@ INSTRUCTION(cop420_ret)
*/
INSTRUCTION(cqma)
INSTRUCTION( cqma )
{
RAM_W(B, Q >> 4);
A = Q & 0xF;
@ -128,7 +214,7 @@ INSTRUCTION(cqma)
*/
INSTRUCTION(ldd)
INSTRUCTION( ldd )
{
UINT8 rd = opcode & 0x3f;
@ -150,7 +236,7 @@ INSTRUCTION(ldd)
*/
INSTRUCTION(xabr)
INSTRUCTION( xabr )
{
UINT8 Br = A & 0x03;
UINT8 Bd = B & 0x0f;
@ -174,12 +260,12 @@ INSTRUCTION(xabr)
*/
INSTRUCTION(skt)
INSTRUCTION( skt )
{
if (R.timerlatch)
if (cop400->skt_latch)
{
R.timerlatch = 0;
skip = 1;
cop400->skt_latch = 0;
cop400->skip = 1;
}
}
@ -198,7 +284,7 @@ INSTRUCTION(skt)
*/
INSTRUCTION(inin)
INSTRUCTION( inin )
{
A = IN_IN();
}
@ -218,7 +304,7 @@ INSTRUCTION(inin)
*/
INSTRUCTION(cop402m_inin)
INSTRUCTION( cop402m_inin )
{
A = IN_IN() | 0x02;
}
@ -236,7 +322,7 @@ INSTRUCTION(cop402m_inin)
*/
INSTRUCTION(inil)
INSTRUCTION( inil )
{
A = (IL & 0x09) | IN_CKO() << 2;
@ -257,9 +343,9 @@ INSTRUCTION(inil)
*/
INSTRUCTION(ogi)
INSTRUCTION( ogi )
{
UINT4 y = opcode & 0x0f;
WRITE_G(y);
WRITE_G(cop400, y);
}

View File

@ -0,0 +1,68 @@
/***************************************************************************
440ops.c
National Semiconductor COP440 Emulator.
Copyright Nicola Salmoria and the MAME Team.
Visit http://mamedev.org for licensing and usage restrictions.
***************************************************************************/
#include "420ops.c"
/*
Mnemonic: CAMT
Hex Code: 33 3F
Binary:
Data Flow: A -> T7:4
RAM(B) -> T3:0
Description: Copy A, RAM to T
*/
INSTRUCTION( camt )
{
T = (A << 4) | RAM_R(B);
}
/*
Mnemonic: CTMA
Hex Code: 33 2F
Binary:
Data Flow: T7:4 -> RAM(B)
T3:0 -> A
Description: Copy T to RAM, A
*/
INSTRUCTION( ctma )
{
RAM_W(B, T >> 4);
A = T & 0x0f;
}
/*
Mnemonic: IT
Hex Code: 33 39
Binary: 0 0 1 1 0 0 1 1 0 0 1 1 1 0 0 1
Description: IDLE till Timer Overflows then Continues
*/
INSTRUCTION( it )
{
cop400->halt = 1;
cop400->idle = 1;
}

View File

@ -24,7 +24,7 @@
enum
{
COP400_PC=1,
COP400_PC = 1,
COP400_A,
COP400_B,
COP400_C,
@ -35,7 +35,8 @@ enum
COP400_SB,
COP400_SC,
COP400_SIO,
COP400_SKL
COP400_SKL,
COP400_T
};
typedef enum _cop400_cki_bond cop400_cki_bond;
@ -102,5 +103,6 @@ extern CPU_GET_INFO( cop445 );
CPU_DISASSEMBLE( cop410 );
CPU_DISASSEMBLE( cop420 );
CPU_DISASSEMBLE( cop444 );
#endif /* __COP400__ */

View File

@ -13,10 +13,11 @@
TODO:
- COP413/COP414/COP415/COP405
- get rid of LBIOps/InstLen
- run interrupt test suite
- run production test suite
- run microbus test suite
- remove LBIops
*/
@ -25,53 +26,11 @@
#include "debugger.h"
#include "cop400.h"
/* The opcode table now is a combination of cycle counts and function pointers */
typedef struct {
unsigned cycles;
void (*function) (UINT8 opcode);
} s_opcode;
#define UINT1 UINT8
#define UINT4 UINT8
#define UINT6 UINT8
#define UINT9 UINT16
typedef struct
{
const cop400_interface *intf;
UINT9 PC;
UINT9 PREVPC;
UINT4 A;
UINT6 B;
UINT1 C;
UINT4 EN;
UINT4 G;
UINT8 Q;
UINT9 SA, SB;
UINT4 SIO;
UINT1 SKL;
UINT8 skip, skipLBI;
UINT8 G_mask;
UINT8 D_mask;
UINT8 si;
int microbus_int;
int halt;
} COP410_Regs;
static COP410_Regs R;
static int cop410_ICount;
static int InstLen[256];
static int LBIops[256];
static emu_timer *cop410_serial_timer;
#include "410ops.c"
/* Opcode Maps */
static const s_opcode opcode_23_map[256]=
static const s_opcode 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 },
@ -110,14 +69,14 @@ static const s_opcode opcode_23_map[256]=
{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal }
};
static void cop410_op23(UINT8 opcode)
static void cop410_op23(cop400_state *cop400, UINT8 opcode)
{
UINT8 opcode23 = ROM(PC++);
(*(opcode_23_map[opcode23].function))(opcode23);
(*(COP410_OPCODE_23_MAP[opcode23].function))(cop400, opcode23);
}
static const s_opcode opcode_33_map[256]=
static const s_opcode 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 },
@ -156,14 +115,14 @@ static const s_opcode opcode_33_map[256]=
{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal }
};
static void cop410_op33(UINT8 opcode)
static void cop410_op33(cop400_state *cop400, UINT8 opcode)
{
UINT8 opcode33 = ROM(PC++);
(*(opcode_33_map[opcode33].function))(opcode33);
(*(COP410_OPCODE_33_MAP[opcode33].function))(cop400, opcode33);
}
static const s_opcode opcode_map[256]=
static const s_opcode 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 },
@ -217,72 +176,72 @@ ADDRESS_MAP_END
****************************************************************************/
static CPU_INIT( cop410 )
{
cop400_state *cop400 = device->token;
int i;
memset(&R, 0, sizeof(R));
R.intf = (cop400_interface *) device->static_config;
assert(R.intf != NULL);
cop400->device = device;
cop400->intf = (cop400_interface *) device->static_config;
/* set output pin masks */
R.G_mask = 0x0f;
R.D_mask = 0x0f;
cop400->g_mask = 0x0f;
cop400->d_mask = 0x0f;
/* set clock divider */
cpu_set_info_int(device, CPUINFO_INT_CLOCK_DIVIDER, R.intf->cki);
cpu_set_info_int(device, CPUINFO_INT_CLOCK_DIVIDER, cop400->intf->cki);
/* allocate serial timer */
cop410_serial_timer = timer_alloc(cop410_serial_tick, NULL);
timer_adjust_periodic(cop410_serial_timer, attotime_zero, index, ATTOTIME_IN_HZ(clock));
cop400->serial_timer = timer_alloc(cop400_serial_tick, cop400);
timer_adjust_periodic(cop400->serial_timer, attotime_zero, index, ATTOTIME_IN_HZ(clock));
/* initialize instruction length array */
for (i=0; i<256; i++) InstLen[i]=1;
for (i=0; i<256; i++) cop400->InstLen[i]=1;
InstLen[0x60] = InstLen[0x61] = InstLen[0x68] = InstLen[0x69] = InstLen[0x33] = InstLen[0x23] = 2;
cop400->InstLen[0x60] = cop400->InstLen[0x61] = cop400->InstLen[0x68] = cop400->InstLen[0x69] = cop400->InstLen[0x33] = cop400->InstLen[0x23] = 2;
/* initialize LBI opcode array */
for (i=0; i<256; i++) LBIops[i] = 0;
for (i=0x08; i<0x10; i++) LBIops[i] = 1;
for (i=0x18; i<0x20; i++) LBIops[i] = 1;
for (i=0x28; i<0x30; i++) LBIops[i] = 1;
for (i=0x38; i<0x40; i++) LBIops[i] = 1;
for (i=0; i<256; i++) cop400->LBIops[i] = 0;
for (i=0x08; i<0x10; i++) cop400->LBIops[i] = 1;
for (i=0x18; i<0x20; i++) cop400->LBIops[i] = 1;
for (i=0x28; i<0x30; i++) cop400->LBIops[i] = 1;
for (i=0x38; i<0x40; i++) cop400->LBIops[i] = 1;
/* register for state saving */
state_save_register_item("cop410", device->tag, 0, PC);
state_save_register_item("cop410", device->tag, 0, R.PREVPC);
state_save_register_item("cop410", device->tag, 0, A);
state_save_register_item("cop410", device->tag, 0, B);
state_save_register_item("cop410", device->tag, 0, C);
state_save_register_item("cop410", device->tag, 0, EN);
state_save_register_item("cop410", device->tag, 0, G);
state_save_register_item("cop410", device->tag, 0, Q);
state_save_register_item("cop410", device->tag, 0, SA);
state_save_register_item("cop410", device->tag, 0, SB);
state_save_register_item("cop410", device->tag, 0, SIO);
state_save_register_item("cop410", device->tag, 0, SKL);
state_save_register_item("cop410", device->tag, 0, skip);
state_save_register_item("cop410", device->tag, 0, skipLBI);
state_save_register_item("cop410", device->tag, 0, R.G_mask);
state_save_register_item("cop410", device->tag, 0, R.D_mask);
state_save_register_item("cop410", device->tag, 0, R.si);
state_save_register_item("cop410", device->tag, 0, R.microbus_int);
state_save_register_item("cop410", device->tag, 0, R.halt);
state_save_register_item("cop410", device->tag, 0, cop400->pc);
state_save_register_item("cop410", device->tag, 0, cop400->prevpc);
state_save_register_item("cop410", device->tag, 0, cop400->a);
state_save_register_item("cop410", device->tag, 0, cop400->b);
state_save_register_item("cop410", device->tag, 0, cop400->c);
state_save_register_item("cop410", device->tag, 0, cop400->en);
state_save_register_item("cop410", device->tag, 0, cop400->g);
state_save_register_item("cop410", device->tag, 0, cop400->q);
state_save_register_item("cop410", device->tag, 0, cop400->sa);
state_save_register_item("cop410", device->tag, 0, cop400->sb);
state_save_register_item("cop410", device->tag, 0, cop400->sio);
state_save_register_item("cop410", device->tag, 0, cop400->skl);
state_save_register_item("cop410", device->tag, 0, cop400->skip);
state_save_register_item("cop410", device->tag, 0, cop400->skip_lbi);
state_save_register_item("cop410", device->tag, 0, cop400->g_mask);
state_save_register_item("cop410", device->tag, 0, cop400->d_mask);
state_save_register_item("cop410", device->tag, 0, cop400->si);
state_save_register_item("cop410", device->tag, 0, cop400->microbus_int);
state_save_register_item("cop410", device->tag, 0, cop400->halt);
}
static CPU_INIT( cop411 )
{
cop400_state *cop400 = device->token;
CPU_INIT_CALL(cop410);
/* the COP411 is like the COP410, just with less output ports */
R.G_mask = 0x07;
R.D_mask = 0x03;
cop400->g_mask = 0x07;
cop400->d_mask = 0x03;
}
/****************************************************************************
@ -290,15 +249,18 @@ static CPU_INIT( cop411 )
****************************************************************************/
static CPU_RESET( cop410 )
{
cop400_state *cop400 = device->token;
PC = 0;
A = 0;
B = 0;
C = 0;
OUT_D(0);
EN = 0;
WRITE_G(0);
WRITE_G(cop400, 0);
SKL = 1;
R.halt = 0;
cop400->halt = 0;
}
/****************************************************************************
@ -306,9 +268,11 @@ static CPU_RESET( cop410 )
****************************************************************************/
static CPU_EXECUTE( cop410 )
{
cop400_state *cop400 = device->token;
UINT8 opcode;
cop410_ICount = cycles;
cop400->icount = cycles;
do
{
@ -316,59 +280,65 @@ static CPU_EXECUTE( cop410 )
debugger_instruction_hook(device->machine, PC);
if (R.intf->cko == COP400_CKO_HALT_IO_PORT)
if (cop400->intf->cko == COP400_CKO_HALT_IO_PORT)
{
R.halt = IN_CKO();
cop400->halt = IN_CKO();
}
if (R.halt) continue;
if (cop400->halt)
{
cop400->icount -= 1;
continue;
}
opcode = ROM(PC);
if (skipLBI == 1)
if (cop400->skip_lbi)
{
if (LBIops[opcode] == 0)
if (cop400->LBIops[opcode])
{
skipLBI = 0;
}
else {
cop410_ICount -= opcode_map[opcode].cycles;
cop400->icount -= COP410_OPCODE_MAP[opcode].cycles;
PC += InstLen[opcode];
PC += cop400->InstLen[opcode];
}
else
{
cop400->skip_lbi = 0;
}
}
if (skipLBI == 0)
if (!cop400->skip_lbi)
{
int inst_cycles = opcode_map[opcode].cycles;
int inst_cycles = COP410_OPCODE_MAP[opcode].cycles;
PC++;
(*(opcode_map[opcode].function))(opcode);
cop410_ICount -= inst_cycles;
(*(COP410_OPCODE_MAP[opcode].function))(cop400, opcode);
cop400->icount -= inst_cycles;
// skip next instruction?
if (skip == 1)
if (cop400->skip)
{
void *function = opcode_map[ROM(PC)].function;
void *function = COP410_OPCODE_MAP[ROM(PC)].function;
opcode = ROM(PC);
if ((function == lqid) || (function == jid))
{
cop410_ICount -= 1;
cop400->icount -= 1;
}
else
{
cop410_ICount -= opcode_map[opcode].cycles;
cop400->icount -= COP410_OPCODE_MAP[opcode].cycles;
}
PC += InstLen[opcode];
skip = 0;
PC += cop400->InstLen[opcode];
cop400->skip = 0;
}
}
} while (cop410_ICount > 0);
} while (cop400->icount > 0);
return cycles - cop410_ICount;
return cycles - cop400->icount;
}
/****************************************************************************
@ -376,18 +346,13 @@ static CPU_EXECUTE( cop410 )
****************************************************************************/
static CPU_GET_CONTEXT( cop410 )
{
if( dst )
*(COP410_Regs*)dst = R;
}
/****************************************************************************
* Set all registers to given values
****************************************************************************/
static CPU_SET_CONTEXT( cop410 )
{
if( src )
R = *(COP410_Regs*)src;
}
/**************************************************************************
@ -413,6 +378,8 @@ static CPU_VALIDITY_CHECK( cop410 )
static CPU_SET_INFO( cop410 )
{
cop400_state *cop400 = device->token;
switch (state)
{
/* --- the following bits of info are set as 64-bit signed integers --- */
@ -438,10 +405,12 @@ static CPU_SET_INFO( cop410 )
CPU_GET_INFO( cop410 )
{
cop400_state *cop400 = (device != NULL) ? device->token : NULL;
switch (state)
{
/* --- the following bits of info are returned as 64-bit signed integers --- */
case CPUINFO_INT_CONTEXT_SIZE: info->i = sizeof(R); break;
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 CPUINFO_INT_ENDIANNESS: info->i = CPU_IS_LE; break;
@ -456,7 +425,7 @@ CPU_GET_INFO( cop410 )
case CPUINFO_INT_ADDRBUS_WIDTH + ADDRESS_SPACE_PROGRAM: info->i = 9; break;
case CPUINFO_INT_ADDRBUS_SHIFT + ADDRESS_SPACE_PROGRAM: info->i = 0; break;
case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_DATA: info->i = 8; break;
case CPUINFO_INT_ADDRBUS_WIDTH + ADDRESS_SPACE_DATA: info->i = 8; /* Really 6 */ break;
case CPUINFO_INT_ADDRBUS_WIDTH + ADDRESS_SPACE_DATA: info->i = 6; break;
case CPUINFO_INT_ADDRBUS_SHIFT + ADDRESS_SPACE_DATA: info->i = 0; break;
case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_IO: info->i = 8; break;
case CPUINFO_INT_ADDRBUS_WIDTH + ADDRESS_SPACE_IO: info->i = 9; break;
@ -488,7 +457,7 @@ CPU_GET_INFO( cop410 )
case CPUINFO_PTR_EXECUTE: info->execute = CPU_EXECUTE_NAME(cop410); break;
case CPUINFO_PTR_BURN: info->burn = NULL; break;
case CPUINFO_PTR_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(cop410); break;
case CPUINFO_PTR_INSTRUCTION_COUNTER: info->icount = &cop410_ICount; break;
case CPUINFO_PTR_INSTRUCTION_COUNTER: info->icount = &cop400->icount; break;
case CPUINFO_PTR_VALIDITY_CHECK: info->validity_check = CPU_VALIDITY_CHECK_NAME(cop410); break;
case CPUINFO_PTR_INTERNAL_MEMORY_MAP + ADDRESS_SPACE_PROGRAM:

View File

@ -13,78 +13,26 @@
TODO:
- get rid of LBIOps/InstLen
- when is the microbus int cleared?
- CKO sync input
- save internal RAM when CKO is RAM power supply pin
- run interrupt test suite
- run production test suite
- run microbus test suite
- remove LBIops
- move cop440 stuff to cop440.c
*/
#include "driver.h"
#include "cpuintrf.h"
#include "debugger.h"
#include "cop400.h"
/* The opcode table now is a combination of cycle counts and function pointers */
typedef struct {
unsigned cycles;
void (*function) (UINT8 opcode);
} s_opcode;
#define UINT1 UINT8
#define UINT4 UINT8
#define UINT6 UINT8
#define UINT10 UINT16
typedef struct
{
const cop400_interface *intf;
UINT10 PC;
UINT10 PREVPC;
UINT4 A;
UINT6 B;
UINT1 C;
UINT4 EN;
UINT4 G;
UINT8 Q;
UINT10 SA, SB, SC;
UINT4 SIO;
UINT1 SKL;
UINT8 skip, skipLBI;
UINT1 timerlatch;
UINT16 counter;
UINT8 G_mask;
UINT8 D_mask;
UINT8 IN_mask;
UINT4 IL;
UINT4 in[4];
UINT8 si;
int last_skip;
int microbus_int;
int halt;
} COP420_Regs;
static COP420_Regs R;
static int cop420_ICount;
static int InstLen[256];
static int LBIops[256];
static int LBIops33[256];
static emu_timer *cop420_serial_timer;
static emu_timer *cop420_counter_timer;
static emu_timer *cop420_inil_timer;
static emu_timer *cop420_microbus_timer;
#include "420ops.c"
/* Opcode Maps */
static const s_opcode opcode_23_map[256]=
static const s_opcode 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 },
@ -123,14 +71,14 @@ static const s_opcode opcode_23_map[256]=
{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal }
};
static void cop420_op23(UINT8 opcode)
static void cop420_op23(cop400_state *cop400, UINT8 opcode)
{
UINT8 opcode23 = ROM(PC++);
(*(opcode_23_map[opcode23].function))(opcode23);
(*(COP420_OPCODE_23_MAP[opcode23].function))(cop400, opcode23);
}
static const s_opcode opcode_33_map[256]=
static const s_opcode 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 },
@ -169,14 +117,14 @@ static const s_opcode opcode_33_map[256]=
{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal }
};
static void cop420_op33(UINT8 opcode)
static void cop420_op33(cop400_state *cop400, UINT8 opcode)
{
UINT8 opcode33 = ROM(PC++);
(*(opcode_33_map[opcode33].function))(opcode33);
(*(COP420_OPCODE_33_MAP[opcode33].function))(cop400, opcode33);
}
static const s_opcode opcode_map[256]=
static const s_opcode 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 },
@ -225,201 +173,118 @@ static ADDRESS_MAP_START( cop420_internal_ram, ADDRESS_SPACE_DATA, 8 )
AM_RANGE(0x00, 0x3f) AM_RAM
ADDRESS_MAP_END
/* Binary Counter */
static TIMER_CALLBACK(cop420_counter_tick)
{
cpu_push_context(machine->cpu[param]);
R.counter++;
if (R.counter == 1024)
{
R.counter = 0;
R.timerlatch = 1;
}
cpu_pop_context();
}
/* IN Latches */
static TIMER_CALLBACK(cop420_inil_tick)
{
UINT8 in;
int i;
cpu_push_context(machine->cpu[param]);
in = IN_IN();
for (i = 0; i < 4; i++)
{
R.in[i] = (R.in[i] << 1) | BIT(in, i);
if ((R.in[i] & 0x07) == 0x04) // 100
{
IL |= (1 << i);
}
}
cpu_pop_context();
}
/* Microbus */
static TIMER_CALLBACK(cop420_microbus_tick)
{
UINT8 in;
cpu_push_context(machine->cpu[param]);
in = IN_IN();
if (!BIT(in, 2))
{
// chip select
if (!BIT(in, 1))
{
// read strobe
OUT_L(Q);
R.microbus_int = 1;
}
else if (!BIT(in, 3))
{
// write strobe
Q = IN_L();
R.microbus_int = 0;
}
}
cpu_pop_context();
}
/****************************************************************************
* Initialize emulation
****************************************************************************/
static CPU_INIT( cop420 )
{
cop400_state *cop400 = device->token;
int i;
memset(&R, 0, sizeof(R));
R.intf = (cop400_interface *) device->static_config;
assert(R.intf != NULL);
cop400->device = device;
cop400->intf = (cop400_interface *) device->static_config;
/* set output pin masks */
R.G_mask = 0x0f; // G0-G3 available
R.D_mask = 0x0f; // D0-D3 available
R.IN_mask = 0x0f; // IN0-IN3 available
cop400->g_mask = 0x0f; // G0-G3 available
cop400->d_mask = 0x0f; // D0-D3 available
cop400->in_mask = 0x0f; // IN0-IN3 available
/* set clock divider */
cpu_set_info_int(device, CPUINFO_INT_CLOCK_DIVIDER, R.intf->cki);
cpu_set_info_int(device, CPUINFO_INT_CLOCK_DIVIDER, cop400->intf->cki);
/* allocate serial timer */
cop420_serial_timer = timer_alloc(cop410_serial_tick, NULL);
timer_adjust_periodic(cop420_serial_timer, attotime_zero, index, ATTOTIME_IN_HZ(clock));
cop400->serial_timer = timer_alloc(cop400_serial_tick, cop400);
timer_adjust_periodic(cop400->serial_timer, attotime_zero, 0, ATTOTIME_IN_HZ(clock));
/* allocate counter timer */
cop420_counter_timer = timer_alloc(cop420_counter_tick, NULL);
timer_adjust_periodic(cop420_counter_timer, attotime_zero, index, ATTOTIME_IN_HZ(clock));
cop400->counter_timer = timer_alloc(cop400_counter_tick, cop400);
timer_adjust_periodic(cop400->counter_timer, attotime_zero, 0, ATTOTIME_IN_HZ(clock / 4));
/* allocate IN latch timer */
cop420_inil_timer = timer_alloc(cop420_inil_tick, NULL);
timer_adjust_periodic(cop420_inil_timer, attotime_zero, index, ATTOTIME_IN_HZ(clock));
cop400->inil_timer = timer_alloc(cop400_inil_tick, cop400);
timer_adjust_periodic(cop400->inil_timer, attotime_zero, 0, ATTOTIME_IN_HZ(clock));
/* allocate Microbus timer */
if (R.intf->microbus == COP400_MICROBUS_ENABLED)
if (cop400->intf->microbus == COP400_MICROBUS_ENABLED)
{
cop420_microbus_timer = timer_alloc(cop420_microbus_tick, NULL);
timer_adjust_periodic(cop420_microbus_timer, attotime_zero, index, ATTOTIME_IN_HZ(clock));
cop400->microbus_timer = timer_alloc(cop400_microbus_tick, cop400);
timer_adjust_periodic(cop400->microbus_timer, attotime_zero, 0, ATTOTIME_IN_HZ(clock));
}
/* initialize instruction length array */
for (i=0; i<256; i++) InstLen[i]=1;
for (i=0; i<256; i++) cop400->InstLen[i]=1;
InstLen[0x60] = InstLen[0x61] = InstLen[0x62] = InstLen[0x63] =
InstLen[0x68] = InstLen[0x69] = InstLen[0x6a] = InstLen[0x6b] =
InstLen[0x33] = InstLen[0x23] = 2;
cop400->InstLen[0x60] = cop400->InstLen[0x61] = cop400->InstLen[0x62] = cop400->InstLen[0x63] =
cop400->InstLen[0x68] = cop400->InstLen[0x69] = cop400->InstLen[0x6a] = cop400->InstLen[0x6b] =
cop400->InstLen[0x33] = cop400->InstLen[0x23] = 2;
/* initialize LBI opcode array */
for (i=0; i<256; i++) LBIops[i] = 0;
for (i=0x08; i<0x10; i++) LBIops[i] = 1;
for (i=0x18; i<0x20; i++) LBIops[i] = 1;
for (i=0x28; i<0x30; i++) LBIops[i] = 1;
for (i=0x38; i<0x40; i++) LBIops[i] = 1;
for (i=0; i<256; i++) cop400->LBIops[i] = 0;
for (i=0x08; i<0x10; i++) cop400->LBIops[i] = 1;
for (i=0x18; i<0x20; i++) cop400->LBIops[i] = 1;
for (i=0x28; i<0x30; i++) cop400->LBIops[i] = 1;
for (i=0x38; i<0x40; i++) cop400->LBIops[i] = 1;
for (i=0; i<256; i++) LBIops33[i] = 0;
for (i=0x80; i<0xc0; i++) LBIops33[i] = 1;
for (i=0; i<256; i++) cop400->LBIops33[i] = 0;
for (i=0x80; i<0xc0; i++) cop400->LBIops33[i] = 1;
/* register for state saving */
state_save_register_item("cop420", device->tag, 0, PC);
state_save_register_item("cop420", device->tag, 0, R.PREVPC);
state_save_register_item("cop420", device->tag, 0, A);
state_save_register_item("cop420", device->tag, 0, B);
state_save_register_item("cop420", device->tag, 0, C);
state_save_register_item("cop420", device->tag, 0, EN);
state_save_register_item("cop420", device->tag, 0, G);
state_save_register_item("cop420", device->tag, 0, Q);
state_save_register_item("cop420", device->tag, 0, SA);
state_save_register_item("cop420", device->tag, 0, SB);
state_save_register_item("cop420", device->tag, 0, SC);
state_save_register_item("cop420", device->tag, 0, SIO);
state_save_register_item("cop420", device->tag, 0, SKL);
state_save_register_item("cop420", device->tag, 0, skip);
state_save_register_item("cop420", device->tag, 0, skipLBI);
state_save_register_item("cop420", device->tag, 0, R.timerlatch);
state_save_register_item("cop420", device->tag, 0, R.counter);
state_save_register_item("cop420", device->tag, 0, R.G_mask);
state_save_register_item("cop420", device->tag, 0, R.D_mask);
state_save_register_item("cop420", device->tag, 0, R.IN_mask);
state_save_register_item("cop420", device->tag, 0, R.si);
state_save_register_item("cop420", device->tag, 0, R.last_skip);
state_save_register_item_array("cop420", device->tag, 0, R.in);
state_save_register_item("cop420", device->tag, 0, R.microbus_int);
state_save_register_item("cop420", device->tag, 0, R.halt);
state_save_register_item("cop420", device->tag, 0, cop400->pc);
state_save_register_item("cop420", device->tag, 0, cop400->prevpc);
state_save_register_item("cop420", device->tag, 0, cop400->a);
state_save_register_item("cop420", device->tag, 0, cop400->b);
state_save_register_item("cop420", device->tag, 0, cop400->c);
state_save_register_item("cop420", device->tag, 0, cop400->en);
state_save_register_item("cop420", device->tag, 0, cop400->g);
state_save_register_item("cop420", device->tag, 0, cop400->q);
state_save_register_item("cop420", device->tag, 0, cop400->sa);
state_save_register_item("cop420", device->tag, 0, cop400->sb);
state_save_register_item("cop420", device->tag, 0, cop400->sc);
state_save_register_item("cop420", device->tag, 0, cop400->sio);
state_save_register_item("cop420", device->tag, 0, cop400->skl);
state_save_register_item("cop420", device->tag, 0, cop400->skip);
state_save_register_item("cop420", device->tag, 0, cop400->skip_lbi);
state_save_register_item("cop420", device->tag, 0, cop400->t);
state_save_register_item("cop420", device->tag, 0, cop400->skt_latch);
state_save_register_item("cop420", device->tag, 0, cop400->g_mask);
state_save_register_item("cop420", device->tag, 0, cop400->d_mask);
state_save_register_item("cop420", device->tag, 0, cop400->in_mask);
state_save_register_item("cop420", device->tag, 0, cop400->si);
state_save_register_item("cop420", device->tag, 0, cop400->last_skip);
state_save_register_item_array("cop420", device->tag, 0, cop400->in);
state_save_register_item("cop420", device->tag, 0, cop400->microbus_int);
state_save_register_item("cop420", device->tag, 0, cop400->halt);
}
static CPU_INIT( cop421 )
{
cop400_state *cop400 = device->token;
CPU_INIT_CALL(cop420);
/* microbus option is not available */
assert(R.intf->microbus != COP400_MICROBUS_ENABLED);
/* set output pin masks */
R.IN_mask = 0; // IN lines not available
cop400->in_mask = 0; // IN lines not available
}
static CPU_INIT( cop422 )
{
cop400_state *cop400 = device->token;
CPU_INIT_CALL(cop420);
/* microbus option is not available */
assert(R.intf->microbus != COP400_MICROBUS_ENABLED);
/* set output pin masks */
R.G_mask = 0x0e; // only G2, G3 available
R.D_mask = 0x0e; // only D2, D3 available
R.IN_mask = 0; // IN lines not available
cop400->g_mask = 0x0e; // only G2, G3 available
cop400->d_mask = 0x0e; // only D2, D3 available
cop400->in_mask = 0; // IN lines not available
}
/****************************************************************************
@ -427,16 +292,19 @@ static CPU_INIT( cop422 )
****************************************************************************/
static CPU_RESET( cop420 )
{
cop400_state *cop400 = device->token;
PC = 0;
A = 0;
B = 0;
C = 0;
OUT_D(0);
EN = 0;
WRITE_G(0);
WRITE_G(cop400, 0);
SKL = 1;
R.counter = 0;
R.timerlatch = 1;
T = 0;
cop400->skt_latch = 1;
}
/****************************************************************************
@ -444,9 +312,11 @@ static CPU_RESET( cop420 )
****************************************************************************/
static CPU_EXECUTE( cop420 )
{
cop400_state *cop400 = device->token;
UINT8 opcode;
cop420_ICount = cycles;
cop400->icount = cycles;
do
{
@ -456,51 +326,49 @@ static CPU_EXECUTE( cop420 )
opcode = ROM(PC);
if (skipLBI == 1)
if (cop400->skip_lbi)
{
int is_lbi = 0;
if (opcode == 0x33)
{
is_lbi = LBIops33[ROM(PC+1)];
is_lbi = cop400->LBIops33[ROM(PC+1)];
}
else
{
is_lbi = LBIops[opcode];
is_lbi = cop400->LBIops[opcode];
}
if (is_lbi == 0)
if (is_lbi)
{
skipLBI = 0;
cop400->icount -= COP420_OPCODE_MAP[opcode].cycles;
PC += cop400->InstLen[opcode];
}
else
{
cop420_ICount -= opcode_map[opcode].cycles;
PC += InstLen[opcode];
cop400->skip_lbi = 0;
}
}
if (skipLBI == 0)
if (!cop400->skip_lbi)
{
int inst_cycles = opcode_map[opcode].cycles;
int inst_cycles = COP420_OPCODE_MAP[opcode].cycles;
PC++;
(*(opcode_map[opcode].function))(opcode);
cop420_ICount -= inst_cycles;
(*(COP420_OPCODE_MAP[opcode].function))(cop400, opcode);
cop400->icount -= inst_cycles;
// check for interrupt
if (BIT(EN, 1) && BIT(IL, 1))
{
void *function = opcode_map[ROM(PC)].function;
void *function = COP420_OPCODE_MAP[ROM(PC)].function;
if ((function != jp) && (function != jmp) && (function != jsr))
{
// store skip logic
R.last_skip = skip;
skip = 0;
cop400->last_skip = cop400->skip;
cop400->skip = 0;
// push next PC
PUSH(PC);
@ -517,28 +385,29 @@ static CPU_EXECUTE( cop420 )
// skip next instruction?
if (skip == 1)
if (cop400->skip)
{
void *function = opcode_map[ROM(PC)].function;
void *function = COP420_OPCODE_MAP[ROM(PC)].function;
opcode = ROM(PC);
if ((function == lqid) || (function == jid))
{
cop420_ICount -= 1;
cop400->icount -= 1;
}
else
{
cop420_ICount -= opcode_map[opcode].cycles;
cop400->icount -= COP420_OPCODE_MAP[opcode].cycles;
}
PC += InstLen[opcode];
skip = 0;
PC += cop400->InstLen[opcode];
cop400->skip = 0;
}
}
} while (cop420_ICount > 0);
} while (cop400->icount > 0);
return cycles - cop420_ICount;
return cycles - cop400->icount;
}
/****************************************************************************
@ -546,18 +415,44 @@ static CPU_EXECUTE( cop420 )
****************************************************************************/
static CPU_GET_CONTEXT( cop420 )
{
if( dst )
*(COP420_Regs*)dst = R;
}
/****************************************************************************
* Set all registers to given values
****************************************************************************/
static CPU_SET_CONTEXT( cop420 )
{
if( src )
R = *(COP420_Regs*)src;
}
/**************************************************************************
* Validity check
**************************************************************************/
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;
}
/**************************************************************************
@ -566,6 +461,8 @@ static CPU_SET_CONTEXT( cop420 )
static CPU_SET_INFO( cop420 )
{
cop400_state *cop400 = device->token;
switch (state)
{
/* --- the following bits of info are set as 64-bit signed integers --- */
@ -592,10 +489,12 @@ static CPU_SET_INFO( cop420 )
CPU_GET_INFO( cop420 )
{
cop400_state *cop400 = (device != NULL) ? device->token : NULL;
switch (state)
{
/* --- the following bits of info are returned as 64-bit signed integers --- */
case CPUINFO_INT_CONTEXT_SIZE: info->i = sizeof(R); break;
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 CPUINFO_INT_ENDIANNESS: info->i = CPU_IS_LE; break;
@ -610,7 +509,7 @@ CPU_GET_INFO( cop420 )
case CPUINFO_INT_ADDRBUS_WIDTH + ADDRESS_SPACE_PROGRAM: info->i = 10; break;
case CPUINFO_INT_ADDRBUS_SHIFT + ADDRESS_SPACE_PROGRAM: info->i = 0; break;
case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_DATA: info->i = 8; break;
case CPUINFO_INT_ADDRBUS_WIDTH + ADDRESS_SPACE_DATA: info->i = 8; /* Really 6 */ break;
case CPUINFO_INT_ADDRBUS_WIDTH + ADDRESS_SPACE_DATA: info->i = 6; break;
case CPUINFO_INT_ADDRBUS_SHIFT + ADDRESS_SPACE_DATA: info->i = 0; break;
case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_IO: info->i = 8; break;
case CPUINFO_INT_ADDRBUS_WIDTH + ADDRESS_SPACE_IO: info->i = 9; break;
@ -643,10 +542,11 @@ CPU_GET_INFO( cop420 )
case CPUINFO_PTR_EXECUTE: info->execute = CPU_EXECUTE_NAME(cop420); break;
case CPUINFO_PTR_BURN: info->burn = NULL; break;
case CPUINFO_PTR_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(cop420); break;
case CPUINFO_PTR_INSTRUCTION_COUNTER: info->icount = &cop420_ICount; break;
case CPUINFO_PTR_INSTRUCTION_COUNTER: info->icount = &cop400->icount; break;
case CPUINFO_PTR_VALIDITY_CHECK: info->validity_check = CPU_VALIDITY_CHECK_NAME(cop420); break;
/* case CPUINFO_PTR_INTERNAL_MEMORY_MAP + ADDRESS_SPACE_PROGRAM:
info->internal_map8 = ADDRESS_MAP_NAME(cop420_internal_rom); break;*/
case CPUINFO_PTR_INTERNAL_MEMORY_MAP + ADDRESS_SPACE_PROGRAM:
info->internal_map8 = ADDRESS_MAP_NAME(cop420_internal_rom); break;
case CPUINFO_PTR_INTERNAL_MEMORY_MAP + ADDRESS_SPACE_DATA:
info->internal_map8 = ADDRESS_MAP_NAME(cop420_internal_ram); break;
@ -684,6 +584,7 @@ CPU_GET_INFO( cop421 )
{
/* --- the following bits of info are returned as pointers to data or functions --- */
case CPUINFO_PTR_INIT: info->init = CPU_INIT_NAME(cop421); break;
case CPUINFO_PTR_VALIDITY_CHECK: info->validity_check = CPU_VALIDITY_CHECK_NAME(cop421); break;
/* --- the following bits of info are returned as NULL-terminated strings --- */
case CPUINFO_STR_NAME: strcpy(info->s, "COP421"); break;
@ -701,6 +602,7 @@ CPU_GET_INFO( cop422 )
{
/* --- the following bits of info are returned as pointers to data or functions --- */
case CPUINFO_PTR_INIT: info->init = CPU_INIT_NAME(cop422); break;
case CPUINFO_PTR_VALIDITY_CHECK: info->validity_check = CPU_VALIDITY_CHECK_NAME(cop421); break;
/* --- the following bits of info are returned as NULL-terminated strings --- */
case CPUINFO_STR_NAME: strcpy(info->s, "COP422"); break;
@ -727,141 +629,3 @@ CPU_GET_INFO( cop402 )
default: CPU_GET_INFO_CALL(cop420); break;
}
}
/* COP44x */
static CPU_INIT( cop426 )
{
CPU_INIT_CALL(cop420);
R.G_mask = 0x0e; // only G2, G3 available
R.D_mask = 0x0e; // only D2, D3 available
}
static CPU_INIT( cop445 )
{
CPU_INIT_CALL(cop420);
R.G_mask = 0x07;
R.D_mask = 0x03;
}
static ADDRESS_MAP_START( cop424_internal_rom, ADDRESS_SPACE_PROGRAM, 8 )
AM_RANGE(0x000, 0x3ff) AM_ROM
ADDRESS_MAP_END
static ADDRESS_MAP_START( cop424_internal_ram, ADDRESS_SPACE_DATA, 8 )
AM_RANGE(0x00, 0x3f) AM_RAM
ADDRESS_MAP_END
static ADDRESS_MAP_START( cop444_internal_rom, ADDRESS_SPACE_PROGRAM, 8 )
AM_RANGE(0x000, 0x7ff) AM_ROM
ADDRESS_MAP_END
static ADDRESS_MAP_START( cop444_internal_ram, ADDRESS_SPACE_DATA, 8 )
AM_RANGE(0x00, 0x7f) AM_RAM
ADDRESS_MAP_END
CPU_GET_INFO( cop444 )
{
switch (state)
{
/* --- the following bits of info are returned as pointers to data or functions --- */
case CPUINFO_PTR_INTERNAL_MEMORY_MAP + ADDRESS_SPACE_PROGRAM:
info->internal_map8 = ADDRESS_MAP_NAME(cop444_internal_rom); break;
case CPUINFO_PTR_INTERNAL_MEMORY_MAP + ADDRESS_SPACE_DATA:
info->internal_map8 = ADDRESS_MAP_NAME(cop444_internal_ram); break;
/* --- the following bits of info are returned as NULL-terminated strings --- */
case CPUINFO_STR_NAME: strcpy(info->s, "COP444"); break;
case CPUINFO_STR_CORE_FAMILY: strcpy(info->s, "National Semiconductor COPS"); break;
default: CPU_GET_INFO_CALL(cop420); 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_PTR_INIT: info->init = CPU_INIT_NAME(cop445); break;
/* --- the following bits of info are returned as NULL-terminated strings --- */
case CPUINFO_STR_NAME: strcpy(info->s, "COP445"); break;
case CPUINFO_STR_CORE_FAMILY: strcpy(info->s, "National Semiconductor COPS"); 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 pointers to data or functions --- */
case CPUINFO_PTR_INTERNAL_MEMORY_MAP + ADDRESS_SPACE_PROGRAM:
info->internal_map8 = ADDRESS_MAP_NAME(cop424_internal_rom); break;
case CPUINFO_PTR_INTERNAL_MEMORY_MAP + ADDRESS_SPACE_DATA:
info->internal_map8 = ADDRESS_MAP_NAME(cop424_internal_ram); break;
/* --- the following bits of info are returned as NULL-terminated strings --- */
case CPUINFO_STR_NAME: strcpy(info->s, "COP424"); break;
case CPUINFO_STR_CORE_FAMILY: strcpy(info->s, "National Semiconductor COPS"); 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 NULL-terminated strings --- */
case CPUINFO_STR_NAME: strcpy(info->s, "COP425"); break;
case CPUINFO_STR_CORE_FAMILY: strcpy(info->s, "National Semiconductor COPS"); break;
default: CPU_GET_INFO_CALL(cop444); 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_PTR_INIT: info->init = CPU_INIT_NAME(cop426); break;
/* --- the following bits of info are returned as NULL-terminated strings --- */
case CPUINFO_STR_NAME: strcpy(info->s, "COP426"); break;
case CPUINFO_STR_CORE_FAMILY: strcpy(info->s, "National Semiconductor COPS"); break;
default: CPU_GET_INFO_CALL(cop444); break;
}
}
CPU_GET_INFO( cop404 )
{
// COP404 is a ROMless version of the COP444, which can emulate a COP410 or a COP424
switch (state)
{
/* --- the following bits of info are returned as pointers to data or functions --- */
case CPUINFO_PTR_INTERNAL_MEMORY_MAP + ADDRESS_SPACE_PROGRAM:
info->internal_map8 = NULL; break;
/* --- the following bits of info are returned as NULL-terminated strings --- */
case CPUINFO_STR_NAME: strcpy(info->s, "COP404"); break;
case CPUINFO_STR_CORE_FAMILY: strcpy(info->s, "National Semiconductor COPS"); break;
default: CPU_GET_INFO_CALL(cop444); break;
}
}

690
src/emu/cpu/cop400/cop440.c Normal file
View File

@ -0,0 +1,690 @@
/***************************************************************************
cop440.c
National Semiconductor COP420 Emulator.
Copyright Nicola Salmoria and the MAME Team.
Visit http://mamedev.org for licensing and usage restrictions.
***************************************************************************/
/*
TODO:
- COP441
- COP404 emulation configuration inputs
- RAM bus width
- get rid of LBIOps/InstLen
- when is the microbus int cleared?
- CKO sync input
- save internal RAM when CKO is RAM power supply pin
- run interrupt test suite
- run production test suite
- run microbus test suite
*/
#include "driver.h"
#include "cpuintrf.h"
#include "debugger.h"
#include "cop400.h"
#include "440ops.c"
/* Opcode Maps */
static const s_opcode COP440_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, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },
{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },
{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },
{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },
{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },
{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },
{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, 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 cop440_op23(cop400_state *cop400, UINT8 opcode)
{
UINT8 opcode23 = ROM(PC++);
(*(COP440_OPCODE_23_MAP[opcode23].function))(cop400, opcode23);
}
static const s_opcode COP440_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, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },
{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },
{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },
{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },
{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },
{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },
{1, illegal },{1, illegal },{1, illegal },{1, illegal },{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 cop440_op33(cop400_state *cop400, UINT8 opcode)
{
UINT8 opcode33 = ROM(PC++);
(*(COP440_OPCODE_33_MAP[opcode33].function))(cop400, opcode33);
}
static const s_opcode COP440_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, 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, cop440_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, cop440_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 }
};
/* Memory Maps */
static ADDRESS_MAP_START( cop424_internal_rom, ADDRESS_SPACE_PROGRAM, 8 )
AM_RANGE(0x000, 0x3ff) AM_ROM
ADDRESS_MAP_END
static ADDRESS_MAP_START( cop424_internal_ram, ADDRESS_SPACE_DATA, 8 )
AM_RANGE(0x00, 0x3f) AM_RAM
ADDRESS_MAP_END
static ADDRESS_MAP_START( cop444_internal_rom, ADDRESS_SPACE_PROGRAM, 8 )
AM_RANGE(0x000, 0x7ff) AM_ROM
ADDRESS_MAP_END
static ADDRESS_MAP_START( cop444_internal_ram, ADDRESS_SPACE_DATA, 8 )
AM_RANGE(0x00, 0x7f) AM_RAM
ADDRESS_MAP_END
/****************************************************************************
* Initialize emulation
****************************************************************************/
static CPU_INIT( cop444 )
{
cop400_state *cop400 = device->token;
int i;
cop400->device = device;
cop400->intf = (cop400_interface *) device->static_config;
/* set output pin masks */
cop400->g_mask = 0x0f; // G0-G3 available
cop400->d_mask = 0x0f; // D0-D3 available
cop400->in_mask = 0x0f; // IN0-IN3 available
/* set clock divider */
cpu_set_info_int(device, CPUINFO_INT_CLOCK_DIVIDER, cop400->intf->cki);
/* allocate serial timer */
cop400->serial_timer = timer_alloc(cop400_serial_tick, cop400);
timer_adjust_periodic(cop400->serial_timer, attotime_zero, index, ATTOTIME_IN_HZ(clock));
/* allocate counter timer */
cop400->counter_timer = timer_alloc(cop400_counter_tick, cop400);
timer_adjust_periodic(cop400->counter_timer, attotime_zero, index, ATTOTIME_IN_HZ(clock / 4));
/* allocate IN latch timer */
cop400->inil_timer = timer_alloc(cop400_inil_tick, cop400);
timer_adjust_periodic(cop400->inil_timer, attotime_zero, index, ATTOTIME_IN_HZ(clock));
/* allocate Microbus timer */
if (cop400->intf->microbus == COP400_MICROBUS_ENABLED)
{
cop400->microbus_timer = timer_alloc(cop400_microbus_tick, cop400);
timer_adjust_periodic(cop400->microbus_timer, attotime_zero, index, ATTOTIME_IN_HZ(clock));
}
/* initialize instruction length array */
for (i=0; i<256; i++) cop400->InstLen[i]=1;
cop400->InstLen[0x60] = cop400->InstLen[0x61] = cop400->InstLen[0x62] = cop400->InstLen[0x63] =
cop400->InstLen[0x68] = cop400->InstLen[0x69] = cop400->InstLen[0x6a] = cop400->InstLen[0x6b] =
cop400->InstLen[0x33] = cop400->InstLen[0x23] = 2;
/* initialize LBI opcode array */
for (i=0; i<256; i++) cop400->LBIops[i] = 0;
for (i=0x08; i<0x10; i++) cop400->LBIops[i] = 1;
for (i=0x18; i<0x20; i++) cop400->LBIops[i] = 1;
for (i=0x28; i<0x30; i++) cop400->LBIops[i] = 1;
for (i=0x38; i<0x40; i++) cop400->LBIops[i] = 1;
for (i=0; i<256; i++) cop400->LBIops33[i] = 0;
for (i=0x80; i<0xc0; i++) cop400->LBIops33[i] = 1;
/* register for state saving */
state_save_register_item("cop420", device->tag, 0, cop400->pc);
state_save_register_item("cop420", device->tag, 0, cop400->prevpc);
state_save_register_item("cop420", device->tag, 0, cop400->a);
state_save_register_item("cop420", device->tag, 0, cop400->b);
state_save_register_item("cop420", device->tag, 0, cop400->c);
state_save_register_item("cop420", device->tag, 0, cop400->en);
state_save_register_item("cop420", device->tag, 0, cop400->g);
state_save_register_item("cop420", device->tag, 0, cop400->q);
state_save_register_item("cop420", device->tag, 0, cop400->sa);
state_save_register_item("cop420", device->tag, 0, cop400->sb);
state_save_register_item("cop420", device->tag, 0, cop400->sc);
state_save_register_item("cop420", device->tag, 0, cop400->sio);
state_save_register_item("cop420", device->tag, 0, cop400->skl);
state_save_register_item("cop420", device->tag, 0, cop400->skip);
state_save_register_item("cop420", device->tag, 0, cop400->skip_lbi);
state_save_register_item("cop420", device->tag, 0, cop400->t);
state_save_register_item("cop420", device->tag, 0, cop400->skt_latch);
state_save_register_item("cop420", device->tag, 0, cop400->g_mask);
state_save_register_item("cop420", device->tag, 0, cop400->d_mask);
state_save_register_item("cop420", device->tag, 0, cop400->in_mask);
state_save_register_item("cop420", device->tag, 0, cop400->si);
state_save_register_item("cop420", device->tag, 0, cop400->last_skip);
state_save_register_item_array("cop420", device->tag, 0, cop400->in);
state_save_register_item("cop420", device->tag, 0, cop400->microbus_int);
state_save_register_item("cop420", device->tag, 0, cop400->halt);
}
static CPU_INIT( cop425 )
{
cop400_state *cop400 = device->token;
CPU_INIT_CALL(cop444);
cop400->in_mask = 0;
}
static CPU_INIT( cop426 )
{
cop400_state *cop400 = device->token;
CPU_INIT_CALL(cop444);
cop400->g_mask = 0x0e; // only G2, G3 available
cop400->d_mask = 0x0e; // only D2, D3 available
}
static CPU_INIT( cop445 )
{
cop400_state *cop400 = device->token;
CPU_INIT_CALL(cop444);
cop400->g_mask = 0x07;
cop400->d_mask = 0x03;
cop400->in_mask = 0;
}
/****************************************************************************
* Reset registers to their initial values
****************************************************************************/
static CPU_RESET( cop444 )
{
cop400_state *cop400 = device->token;
PC = 0;
A = 0;
B = 0;
C = 0;
OUT_D(0);
EN = 0;
WRITE_G(cop400, 0);
SKL = 1;
T = 0;
cop400->skt_latch = 1;
cop400->halt = 0;
cop400->idle = 0;
}
/****************************************************************************
* Execute cycles CPU cycles. Return number of cycles really executed
****************************************************************************/
static CPU_EXECUTE( cop444 )
{
cop400_state *cop400 = device->token;
UINT8 opcode;
cop400->icount = cycles;
do
{
prevPC = PC;
debugger_instruction_hook(device->machine, PC);
if (cop400->intf->cko == COP400_CKO_HALT_IO_PORT)
{
cop400->halt = IN_CKO();
}
if (cop400->halt)
{
cop400->icount -= 1;
continue;
}
opcode = ROM(PC);
if (cop400->skip_lbi)
{
int is_lbi = 0;
if (opcode == 0x33)
{
is_lbi = cop400->LBIops33[ROM(PC+1)];
}
else
{
is_lbi = cop400->LBIops[opcode];
}
if (is_lbi)
{
cop400->icount -= COP440_OPCODE_MAP[opcode].cycles;
PC += cop400->InstLen[opcode];
}
else
{
cop400->skip_lbi = 0;
}
}
if (!cop400->skip_lbi)
{
int inst_cycles = COP440_OPCODE_MAP[opcode].cycles;
PC++;
(*(COP440_OPCODE_MAP[opcode].function))(cop400, opcode);
cop400->icount -= inst_cycles;
// check for interrupt
if (BIT(EN, 1) && BIT(IL, 1))
{
void *function = COP440_OPCODE_MAP[ROM(PC)].function;
if ((function != jp) && (function != jmp) && (function != jsr))
{
// store skip logic
cop400->last_skip = cop400->skip;
cop400->skip = 0;
// push next PC
PUSH(PC);
// jump to interrupt service routine
PC = 0x0ff;
// disable interrupt
EN &= ~0x02;
}
IL &= ~2;
}
// skip next instruction?
if (cop400->skip)
{
void *function = COP440_OPCODE_MAP[ROM(PC)].function;
opcode = ROM(PC);
if ((function == lqid) || (function == jid))
{
cop400->icount -= 1;
}
else
{
cop400->icount -= COP440_OPCODE_MAP[opcode].cycles;
}
PC += cop400->InstLen[opcode];
cop400->skip = 0;
}
}
} while (cop400->icount > 0);
return cycles - cop400->icount;
}
/****************************************************************************
* Get all registers in given buffer
****************************************************************************/
static CPU_GET_CONTEXT( cop444 )
{
}
/****************************************************************************
* Set all registers to given values
****************************************************************************/
static CPU_SET_CONTEXT( cop444 )
{
}
/**************************************************************************
* Validity check
**************************************************************************/
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;
}
/**************************************************************************
* Generic set_info
**************************************************************************/
static CPU_SET_INFO( cop444 )
{
cop400_state *cop400 = device->token;
switch (state)
{
/* --- the following bits of info are set as 64-bit signed integers --- */
case CPUINFO_INT_PC:
case CPUINFO_INT_REGISTER + COP400_PC: PC = info->i; break;
case CPUINFO_INT_REGISTER + COP400_A: A = info->i; break;
case CPUINFO_INT_REGISTER + COP400_B: B = info->i; break;
case CPUINFO_INT_REGISTER + COP400_C: C = info->i; break;
case CPUINFO_INT_REGISTER + COP400_EN: EN = info->i; break;
case CPUINFO_INT_REGISTER + COP400_G: G = info->i; break;
case CPUINFO_INT_REGISTER + COP400_Q: Q = info->i; break;
case CPUINFO_INT_REGISTER + COP400_SA: SA = info->i; break;
case CPUINFO_INT_REGISTER + COP400_SB: SB = info->i; break;
case CPUINFO_INT_REGISTER + COP400_SC: SC = info->i; break;
case CPUINFO_INT_REGISTER + COP400_SIO: SIO = info->i; break;
case CPUINFO_INT_REGISTER + COP400_SKL: SKL = info->i; break;
case CPUINFO_INT_REGISTER + COP400_T: T = info->i; break;
}
}
/**************************************************************************
* Generic get_info
**************************************************************************/
CPU_GET_INFO( cop444 )
{
cop400_state *cop400 = (device != NULL) ? device->token : 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 CPUINFO_INT_ENDIANNESS: info->i = CPU_IS_LE; break;
case CPUINFO_INT_CLOCK_MULTIPLIER: info->i = 1; break;
case CPUINFO_INT_CLOCK_DIVIDER: info->i = 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 CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_PROGRAM: info->i = 8; break;
case CPUINFO_INT_ADDRBUS_WIDTH + ADDRESS_SPACE_PROGRAM: info->i = 10; break;
case CPUINFO_INT_ADDRBUS_SHIFT + ADDRESS_SPACE_PROGRAM: info->i = 0; break;
case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_DATA: info->i = 8; break;
case CPUINFO_INT_ADDRBUS_WIDTH + ADDRESS_SPACE_DATA: info->i = 7; break;
case CPUINFO_INT_ADDRBUS_SHIFT + ADDRESS_SPACE_DATA: info->i = 0; break;
case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_IO: info->i = 8; break;
case CPUINFO_INT_ADDRBUS_WIDTH + ADDRESS_SPACE_IO: info->i = 9; break;
case CPUINFO_INT_ADDRBUS_SHIFT + ADDRESS_SPACE_IO: info->i = 0; break;
case CPUINFO_INT_INPUT_STATE + 0: info->i = 0; break;
case CPUINFO_INT_PREVIOUSPC: info->i = prevPC; break;
case CPUINFO_INT_PC:
case CPUINFO_INT_REGISTER + COP400_PC: info->i = PC; break;
case CPUINFO_INT_REGISTER + COP400_A: info->i = A; break;
case CPUINFO_INT_REGISTER + COP400_B: info->i = B; break;
case CPUINFO_INT_REGISTER + COP400_C: info->i = C; break;
case CPUINFO_INT_REGISTER + COP400_EN: info->i = EN; break;
case CPUINFO_INT_REGISTER + COP400_G: info->i = G; break;
case CPUINFO_INT_REGISTER + COP400_Q: info->i = Q; break;
case CPUINFO_INT_REGISTER + COP400_SA: info->i = SA; break;
case CPUINFO_INT_REGISTER + COP400_SB: info->i = SB; break;
case CPUINFO_INT_REGISTER + COP400_SC: info->i = SC; break;
case CPUINFO_INT_REGISTER + COP400_SIO: info->i = SIO; break;
case CPUINFO_INT_REGISTER + COP400_SKL: info->i = SKL; break;
/* --- the following bits of info are returned as pointers to data or functions --- */
case CPUINFO_PTR_SET_INFO: info->setinfo = CPU_SET_INFO_NAME(cop444); break;
case CPUINFO_PTR_GET_CONTEXT: info->getcontext = CPU_GET_CONTEXT_NAME(cop444); break;
case CPUINFO_PTR_SET_CONTEXT: info->setcontext = CPU_SET_CONTEXT_NAME(cop444); break;
case CPUINFO_PTR_INIT: info->init = CPU_INIT_NAME(cop444); break;
case CPUINFO_PTR_RESET: info->reset = CPU_RESET_NAME(cop444); break;
case CPUINFO_PTR_EXECUTE: info->execute = CPU_EXECUTE_NAME(cop444); break;
case CPUINFO_PTR_BURN: info->burn = NULL; break;
case CPUINFO_PTR_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(cop444); break;
case CPUINFO_PTR_INSTRUCTION_COUNTER: info->icount = &cop400->icount; break;
case CPUINFO_PTR_VALIDITY_CHECK: info->validity_check = CPU_VALIDITY_CHECK_NAME(cop444); break;
case CPUINFO_PTR_INTERNAL_MEMORY_MAP + ADDRESS_SPACE_PROGRAM:
info->internal_map8 = ADDRESS_MAP_NAME(cop444_internal_rom); break;
case CPUINFO_PTR_INTERNAL_MEMORY_MAP + ADDRESS_SPACE_DATA:
info->internal_map8 = ADDRESS_MAP_NAME(cop444_internal_ram); break;
/* --- the following bits of info are returned as NULL-terminated strings --- */
case CPUINFO_STR_NAME: strcpy(info->s, "COP444"); break;
case CPUINFO_STR_CORE_FAMILY: strcpy(info->s, "National Semiconductor COPS"); break;
case CPUINFO_STR_CORE_VERSION: strcpy(info->s, "1.0"); break;
case CPUINFO_STR_CORE_FILE: strcpy(info->s, __FILE__); break;
case CPUINFO_STR_CORE_CREDITS: strcpy(info->s, "Copyright MAME Team"); break;
case CPUINFO_STR_FLAGS:
sprintf(info->s, " ");
break;
case CPUINFO_STR_REGISTER + COP400_PC: sprintf(info->s, "PC:%04X", PC); break;
case CPUINFO_STR_REGISTER + COP400_A: sprintf(info->s, "A:%01X", A ); break;
case CPUINFO_STR_REGISTER + COP400_B: sprintf(info->s, "B:%02X", B ); break;
case CPUINFO_STR_REGISTER + COP400_C: sprintf(info->s, "C:%01X", C); break;
case CPUINFO_STR_REGISTER + COP400_EN: sprintf(info->s, "EN:%01X", EN); break;
case CPUINFO_STR_REGISTER + COP400_G: sprintf(info->s, "G:%01X", G); break;
case CPUINFO_STR_REGISTER + COP400_Q: sprintf(info->s, "Q:%02X", Q); break;
case CPUINFO_STR_REGISTER + COP400_SA: sprintf(info->s, "SA:%04X", SA); break;
case CPUINFO_STR_REGISTER + COP400_SB: sprintf(info->s, "SB:%04X", SB); break;
case CPUINFO_STR_REGISTER + COP400_SC: sprintf(info->s, "SC:%04X", SC); break;
case CPUINFO_STR_REGISTER + COP400_SIO: sprintf(info->s, "SIO:%01X", SIO); break;
case CPUINFO_STR_REGISTER + COP400_SKL: sprintf(info->s, "SKL:%01X", SKL); 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_PTR_INIT: info->init = CPU_INIT_NAME(cop445); break;
/* --- the following bits of info are returned as NULL-terminated strings --- */
case CPUINFO_STR_NAME: strcpy(info->s, "COP445"); break;
case CPUINFO_STR_CORE_FAMILY: strcpy(info->s, "National Semiconductor COPS"); 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 CPUINFO_INT_ADDRBUS_WIDTH + ADDRESS_SPACE_DATA: info->i = 6; break;
/* --- the following bits of info are returned as pointers to data or functions --- */
case CPUINFO_PTR_INTERNAL_MEMORY_MAP + ADDRESS_SPACE_PROGRAM:
info->internal_map8 = ADDRESS_MAP_NAME(cop424_internal_rom); break;
case CPUINFO_PTR_INTERNAL_MEMORY_MAP + ADDRESS_SPACE_DATA:
info->internal_map8 = ADDRESS_MAP_NAME(cop424_internal_ram); break;
/* --- the following bits of info are returned as NULL-terminated strings --- */
case CPUINFO_STR_NAME: strcpy(info->s, "COP424"); break;
case CPUINFO_STR_CORE_FAMILY: strcpy(info->s, "National Semiconductor COPS"); 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_PTR_INIT: info->init = CPU_INIT_NAME(cop425); break;
/* --- the following bits of info are returned as NULL-terminated strings --- */
case CPUINFO_STR_NAME: strcpy(info->s, "COP425"); break;
case CPUINFO_STR_CORE_FAMILY: strcpy(info->s, "National Semiconductor COPS"); 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_PTR_INIT: info->init = CPU_INIT_NAME(cop426); break;
/* --- the following bits of info are returned as NULL-terminated strings --- */
case CPUINFO_STR_NAME: strcpy(info->s, "COP426"); break;
case CPUINFO_STR_CORE_FAMILY: strcpy(info->s, "National Semiconductor COPS"); break;
default: CPU_GET_INFO_CALL(cop424); break;
}
}
CPU_GET_INFO( cop404 )
{
// COP404 is a ROMless version of the COP444, which can emulate a COP410 or a COP424
switch (state)
{
/* --- the following bits of info are returned as pointers to data or functions --- */
case CPUINFO_PTR_INTERNAL_MEMORY_MAP + ADDRESS_SPACE_PROGRAM:
info->internal_map8 = NULL; break;
/* --- the following bits of info are returned as NULL-terminated strings --- */
case CPUINFO_STR_NAME: strcpy(info->s, "COP404"); break;
case CPUINFO_STR_CORE_FAMILY: strcpy(info->s, "National Semiconductor COPS"); break;
default: CPU_GET_INFO_CALL(cop444); break;
}
}

View File

@ -0,0 +1,416 @@
/***************************************************************************
cop420ds.c
National Semiconductor COP420 Emulator.
Copyright Nicola Salmoria and the MAME Team.
Visit http://mamedev.org for licensing and usage restrictions.
***************************************************************************/
#include "cpuintrf.h"
CPU_DISASSEMBLE( cop444 )
{
UINT8 opcode = oprom[0];
UINT8 next_opcode = oprom[1];
UINT16 address;
UINT32 flags = 0;
int bytes = 1;
if ((opcode >= 0x80 && opcode <= 0xBE) || (opcode >= 0xC0 && opcode <= 0xFE))
{
if ((pc & 0x3E0) >= 0x80 && (pc & 0x3E0) < 0x100) //JP pages 2,3
{
address = (UINT16)((pc & 0x380) | (opcode & 0x7F));
sprintf(buffer, "JP %x", address);
}
else
{
if ((opcode & 0xC0) == 0xC0) //JP other pages
{
address = (UINT16)((pc & 0x3C0) | (opcode & 0x3F));
sprintf(buffer, "JP %x", address);
}
else //JSRP
{
address = (UINT16)(0x80 | (opcode & 0x3F));
sprintf(buffer, "JSRP %x", address);
flags = DASMFLAG_STEP_OVER;
}
}
}
else if (opcode >= 0x08 && opcode <= 0x0F)
{
sprintf(buffer, "LBI 0,%u", ((opcode & 0xF) + 1) & 0xF);
}
else if (opcode >= 0x18 && opcode <= 0x1F)
{
sprintf(buffer, "LBI 1,%u", ((opcode & 0xF) + 1) & 0xF);
}
else if (opcode >= 0x28 && opcode <= 0x2F)
{
sprintf(buffer, "LBI 2,%u", ((opcode & 0xF) + 1) & 0xF);
}
else if (opcode >= 0x38 && opcode <= 0x3F)
{
sprintf(buffer, "LBI 3,%u", ((opcode & 0xF) + 1) & 0xF);
}
else if (opcode >= 0x51 && opcode <= 0x5F)
{
sprintf(buffer, "AISC %u", opcode & 0xF);
}
else if (opcode >= 0x60 && opcode <= 0x63)
{
address = ((opcode & 0x03) << 8) | next_opcode;
sprintf(buffer, "JMP %x", address);
bytes = 2;
}
else if (opcode >= 0x68 && opcode <= 0x6B)
{
address = ((opcode & 0x03) << 8) | next_opcode;
sprintf(buffer, "JSR %x", address);
flags = DASMFLAG_STEP_OVER;
bytes = 2;
}
else if (opcode >= 0x70 && opcode <= 0x7F)
{
sprintf(buffer, "STII %u", opcode & 0xF);
}
else
{
switch (opcode)
{
case 0:
sprintf(buffer, "CLRA");
break;
case 1:
sprintf(buffer, "SKMBZ 0");
break;
case 2:
sprintf(buffer, "XOR");
break;
case 3:
sprintf(buffer, "SKMBZ 2");
break;
case 4:
sprintf(buffer, "XIS 0");
break;
case 5:
sprintf(buffer, "LD 0");
break;
case 6:
sprintf(buffer, "X 0");
break;
case 7:
sprintf(buffer, "XDS 0");
break;
case 0x10:
sprintf(buffer, "CASC");
break;
case 0x11:
sprintf(buffer, "SKMBZ 1");
break;
case 0x12:
sprintf(buffer, "XABR");
break;
case 0x13:
sprintf(buffer, "SKMBZ 3");
break;
case 0x14:
sprintf(buffer, "XIS 1");
break;
case 0x15:
sprintf(buffer, "LD 1");
break;
case 0x16:
sprintf(buffer, "X 1");
break;
case 0x17:
sprintf(buffer, "XDS 1");
break;
case 0x20:
sprintf(buffer, "SKC");
break;
case 0x21:
sprintf(buffer, "SKE");
break;
case 0x22:
sprintf(buffer, "SC");
break;
case 0x23:
bytes = 2;
if (next_opcode <= 0x3f)
{
address = (UINT16)(next_opcode & 0x3F);
sprintf(buffer, "LDD %x,%x", ((address & 0x30) >> 4),address & 0x0F);
}
else if (next_opcode >= 0x80 && next_opcode <= 0xbf)
{
address = (UINT16)(next_opcode & 0x3F);
sprintf(buffer, "XAD %x,%x", ((address & 0x30) >> 4),address & 0x0F);
}
else
{
sprintf(buffer, "Invalid");
}
break;
case 0x24:
sprintf(buffer, "XIS 2");
break;
case 0x25:
sprintf(buffer, "LD 2");
break;
case 0x26:
sprintf(buffer, "X 2");
break;
case 0x27:
sprintf(buffer, "XDS 2");
break;
case 0x30:
sprintf(buffer, "ASC");
break;
case 0x31:
sprintf(buffer, "ADD");
break;
case 0x32:
sprintf(buffer, "RC");
break;
case 0x33:
bytes = 2;
if (next_opcode >= 0x50 && next_opcode <= 0x5F)
{
sprintf(buffer, "OGI %u", next_opcode & 0xF);
}
else if (next_opcode >= 0x60 && next_opcode <= 0x6F)
{
sprintf(buffer, "LEI %u", next_opcode & 0xF);
}
else if (next_opcode >= 0x80 && next_opcode <= 0x8F)
{
sprintf(buffer, "LBI 0,%u", next_opcode & 0xF);
}
else if (next_opcode >= 0x90 && next_opcode <= 0x9F)
{
sprintf(buffer, "LBI 1,%u", next_opcode & 0xF);
}
else if (next_opcode >= 0xA0 && next_opcode <= 0xAF)
{
sprintf(buffer, "LBI 2,%u", next_opcode & 0xF);
}
else if (next_opcode >= 0xB0 && next_opcode <= 0xBF)
{
sprintf(buffer, "LBI 3,%u", next_opcode & 0xF);
}
else
{
switch (next_opcode)
{
case 0x01:
sprintf(buffer, "SKGBZ 0");
break;
case 0x03:
sprintf(buffer, "SKGBZ 2");
break;
case 0x11:
sprintf(buffer, "SKGBZ 1");
break;
case 0x13:
sprintf(buffer, "SKGBZ 3");
break;
case 0x21:
sprintf(buffer, "SKGZ");
break;
case 0x28:
sprintf(buffer, "ININ");
break;
case 0x29:
sprintf(buffer, "INIL");
break;
case 0x2A:
sprintf(buffer, "ING");
break;
case 0x2C:
sprintf(buffer, "CQMA");
break;
case 0x2E:
sprintf(buffer, "INL");
break;
case 0x2F:
sprintf(buffer, "CTMA");
break;
case 0x38:
sprintf(buffer, "HALT");
break;
case 0x39:
sprintf(buffer, "IT");
break;
case 0x3A:
sprintf(buffer, "OMG");
break;
case 0x3C:
sprintf(buffer, "CAMQ");
break;
case 0x3E:
sprintf(buffer, "OBD");
break;
case 0x3F:
sprintf(buffer, "CAMT");
break;
default:
sprintf(buffer, "Invalid");
break;
}
}
break;
case 0x34:
sprintf(buffer, "XIS 3");
break;
case 0x35:
sprintf(buffer, "LD 3");
break;
case 0x36:
sprintf(buffer, "X 3");
break;
case 0x37:
sprintf(buffer, "XDS 3");
break;
case 0x40:
sprintf(buffer, "COMP");
break;
case 0x41:
sprintf(buffer, "SKT");
break;
case 0x42:
sprintf(buffer, "RMB 2");
break;
case 0x43:
sprintf(buffer, "RMB 3");
break;
case 0x44:
sprintf(buffer, "NOP");
break;
case 0x45:
sprintf(buffer, "RMB 1");
break;
case 0x46:
sprintf(buffer, "SMB 2");
break;
case 0x47:
sprintf(buffer, "SMB 1");
break;
case 0x48:
sprintf(buffer, "RET");
flags = DASMFLAG_STEP_OUT;
break;
case 0x49:
sprintf(buffer, "RETSK");
flags = DASMFLAG_STEP_OUT;
break;
case 0x4A:
sprintf(buffer, "ADT");
break;
case 0x4B:
sprintf(buffer, "SMB 3");
break;
case 0x4C:
sprintf(buffer, "RMB 0");
break;
case 0x4D:
sprintf(buffer, "SMB 0");
break;
case 0x4E:
sprintf(buffer, "CBA");
break;
case 0x4F:
sprintf(buffer, "XAS");
break;
case 0x50:
sprintf(buffer, "CAB");
break;
case 0xBF:
sprintf(buffer, "LQID");
break;
case 0xFF:
sprintf(buffer, "JID");
break;
default:
sprintf(buffer, "Invalid");
break;
}
}
return bytes | flags | DASMFLAG_SUPPORTED;
}

View File

@ -291,23 +291,38 @@ $(CPUOBJ)/cdp1802/cdp1802.o: $(CPUSRC)/cdp1802/cdp1802.c \
# National Semiconductor COP4xx
#-------------------------------------------------
CPUDEFS += -DHAS_COP401=$(if $(filter COP401,$(CPUS)),1,0)
CPUDEFS += -DHAS_COP410=$(if $(filter COP410,$(CPUS)),1,0)
CPUDEFS += -DHAS_COP411=$(if $(filter COP411,$(CPUS)),1,0)
CPUDEFS += -DHAS_COP402=$(if $(filter COP402,$(CPUS)),1,0)
CPUDEFS += -DHAS_COP420=$(if $(filter COP420,$(CPUS)),1,0)
CPUDEFS += -DHAS_COP421=$(if $(filter COP421,$(CPUS)),1,0)
CPUDEFS += -DHAS_COP422=$(if $(filter COP421,$(CPUS)),1,0)
CPUDEFS += -DHAS_COP404=$(if $(filter COP404,$(CPUS)),1,0)
CPUDEFS += -DHAS_COP424=$(if $(filter COP424,$(CPUS)),1,0)
CPUDEFS += -DHAS_COP425=$(if $(filter COP425,$(CPUS)),1,0)
CPUDEFS += -DHAS_COP426=$(if $(filter COP426,$(CPUS)),1,0)
CPUDEFS += -DHAS_COP444=$(if $(filter COP444,$(CPUS)),1,0)
CPUDEFS += -DHAS_COP445=$(if $(filter COP445,$(CPUS)),1,0)
ifneq ($(filter COP410 COP411,$(CPUS)),)
ifneq ($(filter COP401 COP410 COP411,$(CPUS)),)
OBJDIRS += $(CPUOBJ)/cop400
CPUOBJS += $(CPUOBJ)/cop400/cop410.o
DBGOBJS += $(CPUOBJ)/cop400/cop410ds.o
endif
ifneq ($(filter COP420 COP421,$(CPUS)),)
ifneq ($(filter COP402 COP420 COP421 COP422,$(CPUS)),)
OBJDIRS += $(CPUOBJ)/cop400
CPUOBJS += $(CPUOBJ)/cop400/cop420.o
DBGOBJS += $(CPUOBJ)/cop400/cop420ds.o
endif
ifneq ($(filter COP404 COP424 COP425 COP426 COP444 COP445,$(CPUS)),)
OBJDIRS += $(CPUOBJ)/cop400
CPUOBJS += $(CPUOBJ)/cop400/cop440.o
DBGOBJS += $(CPUOBJ)/cop400/cop440ds.o
endif
$(CPUOBJ)/cop400/cop410.o: $(CPUSRC)/cop400/cop410.c \
$(CPUSRC)/cop400/cop400.h \
$(CPUSRC)/cop400/410ops.c
@ -317,6 +332,11 @@ $(CPUOBJ)/cop400/cop420.o: $(CPUSRC)/cop400/cop420.c \
$(CPUSRC)/cop400/410ops.c \
$(CPUSRC)/cop400/420ops.c
$(CPUOBJ)/cop400/cop440.o: $(CPUSRC)/cop400/cop440.c \
$(CPUSRC)/cop400/cop400.h \
$(CPUSRC)/cop400/410ops.c \
$(CPUSRC)/cop400/420ops.c \
$(CPUSRC)/cop400/440ops.c
#-------------------------------------------------

View File

@ -229,10 +229,19 @@ CPU_GET_INFO( rsp );
CPU_GET_INFO( alpha8201 );
CPU_GET_INFO( alpha8301 );
CPU_GET_INFO( cdp1802 );
CPU_GET_INFO( cop420 );
CPU_GET_INFO( cop421 );
CPU_GET_INFO( cop401 );
CPU_GET_INFO( cop410 );
CPU_GET_INFO( cop411 );
CPU_GET_INFO( cop402 );
CPU_GET_INFO( cop420 );
CPU_GET_INFO( cop421 );
CPU_GET_INFO( cop422 );
CPU_GET_INFO( cop404 );
CPU_GET_INFO( cop424 );
CPU_GET_INFO( cop425 );
CPU_GET_INFO( cop426 );
CPU_GET_INFO( cop444 );
CPU_GET_INFO( cop445 );
CPU_GET_INFO( tmp90840 );
CPU_GET_INFO( tmp90841 );
CPU_GET_INFO( tmp91640 );
@ -801,11 +810,8 @@ static const struct
#if (HAS_CDP1802)
{ CPU_CDP1802, CPU_GET_INFO_NAME(cdp1802) },
#endif
#if (HAS_COP420)
{ CPU_COP420, CPU_GET_INFO_NAME(cop420) },
#endif
#if (HAS_COP421)
{ CPU_COP421, CPU_GET_INFO_NAME(cop421) },
#if (HAS_COP401)
{ CPU_COP401, CPU_GET_INFO_NAME(cop401) },
#endif
#if (HAS_COP410)
{ CPU_COP410, CPU_GET_INFO_NAME(cop410) },
@ -813,6 +819,36 @@ static const struct
#if (HAS_COP411)
{ CPU_COP411, CPU_GET_INFO_NAME(cop411) },
#endif
#if (HAS_COP402)
{ CPU_COP402, CPU_GET_INFO_NAME(cop402) },
#endif
#if (HAS_COP420)
{ CPU_COP420, CPU_GET_INFO_NAME(cop420) },
#endif
#if (HAS_COP421)
{ CPU_COP421, CPU_GET_INFO_NAME(cop421) },
#endif
#if (HAS_COP422)
{ CPU_COP422, CPU_GET_INFO_NAME(cop422) },
#endif
#if (HAS_COP404)
{ CPU_COP404, CPU_GET_INFO_NAME(cop404) },
#endif
#if (HAS_COP424)
{ CPU_COP424, CPU_GET_INFO_NAME(cop424) },
#endif
#if (HAS_COP425)
{ CPU_COP425, CPU_GET_INFO_NAME(cop425) },
#endif
#if (HAS_COP426)
{ CPU_COP426, CPU_GET_INFO_NAME(cop426) },
#endif
#if (HAS_COP444)
{ CPU_COP444, CPU_GET_INFO_NAME(cop444) },
#endif
#if (HAS_COP445)
{ CPU_COP445, CPU_GET_INFO_NAME(cop445) },
#endif
#if (HAS_TLCS90)
{ CPU_TMP90840, CPU_GET_INFO_NAME(tmp90840) },
{ CPU_TMP90841, CPU_GET_INFO_NAME(tmp90841) },
@ -921,7 +957,7 @@ INLINE char *get_temp_string_buffer(void)
/*-------------------------------------------------
get_safe_classheader - makes sure that the
get_safe_classheader - makes sure that the
passed in device is, in fact, a CPU, and
return the class token
-------------------------------------------------*/
@ -944,7 +980,7 @@ INLINE cpu_class_header *get_safe_classheader(const device_config *device)
INLINE void set_cpu_context(const device_config *oldcpu, const device_config *newcpu)
{
cpu_class_header *classheader;
/* if nothing is changing, quick exit */
if (oldcpu == newcpu)
return;
@ -955,7 +991,7 @@ INLINE void set_cpu_context(const device_config *oldcpu, const device_config *ne
classheader = oldcpu->classtoken;
(*classheader->get_context)(oldcpu->token);
}
/* swap in the new context if we have one */
if (newcpu != NULL)
{
@ -1108,7 +1144,7 @@ int cpunum_get_active(void)
int cpu_get_index_slow(const device_config *cpu)
{
int cpunum;
for (cpunum = 0; cpunum < ARRAY_LENGTH(Machine->cpu); cpunum++)
if (Machine->cpu[cpunum] == cpu)
return cpunum;
@ -1131,7 +1167,7 @@ void cpu_init(const device_config *device, int index, int clock, cpu_irq_callbac
memory_set_context(device->machine, index);
device->machine->activecpu = device;
classheader->index = index;
classheader->space[ADDRESS_SPACE_PROGRAM] = active_address_space[ADDRESS_SPACE_PROGRAM];
classheader->space[ADDRESS_SPACE_DATA] = active_address_space[ADDRESS_SPACE_DATA];
@ -1139,7 +1175,7 @@ void cpu_init(const device_config *device, int index, int clock, cpu_irq_callbac
(*classheader->init)(device, index, clock, irqcallback);
(*classheader->get_context)(device->token);
device->machine->activecpu = NULL;
}
@ -1151,7 +1187,7 @@ void cpu_init(const device_config *device, int index, int clock, cpu_irq_callbac
void cpu_exit(const device_config *device)
{
cpu_class_header *classheader = get_safe_classheader(device);
if (classheader->exit != NULL)
{
set_cpu_context(device->machine->activecpu, device);
@ -1162,7 +1198,7 @@ void cpu_exit(const device_config *device)
/*-------------------------------------------------
cpu_get_info_* - return information about a
cpu_get_info_* - return information about a
live CPU
-------------------------------------------------*/
@ -1216,7 +1252,7 @@ const char *cpu_get_info_string(const device_config *device, UINT32 state)
/*-------------------------------------------------
cpu_set_info_* - set information about a
cpu_set_info_* - set information about a
live CPU
-------------------------------------------------*/
@ -1256,7 +1292,7 @@ void cpu_set_info_fct(const device_config *device, UINT32 state, genf *data)
/*-------------------------------------------------
cpu_execute - execute the requested cycles on
cpu_execute - execute the requested cycles on
a given CPU
-------------------------------------------------*/
@ -1288,7 +1324,7 @@ void cpu_reset(const device_config *device)
/*-------------------------------------------------
cpu_read_byte - read a byte from another CPU's
cpu_read_byte - read a byte from another CPU's
memory space
-------------------------------------------------*/
@ -1304,7 +1340,7 @@ UINT8 cpu_read_byte(const device_config *device, offs_t address)
/*-------------------------------------------------
cpu_write_byte - write a byte to another CPU's
cpu_write_byte - write a byte to another CPU's
memory space
-------------------------------------------------*/
@ -1317,7 +1353,7 @@ void cpu_write_byte(const device_config *device, offs_t address, UINT8 data)
/*-------------------------------------------------
cpu_get_physical_pc_byte - return the PC,
cpu_get_physical_pc_byte - return the PC,
corrected to a byte offset and translated to
physical space, on a given CPU
-------------------------------------------------*/
@ -1335,7 +1371,7 @@ offs_t cpu_get_physical_pc_byte(const device_config *device)
/*-------------------------------------------------
cpu_dasm - disassemble a line at a given PC
cpu_dasm - disassemble a line at a given PC
on a given CPU
-------------------------------------------------*/
@ -1343,7 +1379,7 @@ offs_t cpu_dasm(const device_config *device, char *buffer, offs_t pc, const UINT
{
cpu_class_header *classheader = get_safe_classheader(device);
offs_t result = 0;
cpu_push_context(device);
/* check for disassembler override */
@ -1396,7 +1432,7 @@ offs_t cpu_dasm(const device_config *device, char *buffer, offs_t pc, const UINT
/*-------------------------------------------------
cpu_set_dasm_override - set a dasm override
cpu_set_dasm_override - set a dasm override
handler
-------------------------------------------------*/
@ -1413,7 +1449,7 @@ void cpu_set_dasm_override(const device_config *device, cpu_disassemble_func das
***************************************************************************/
/*-------------------------------------------------
cputype_get_header_template - return a header
cputype_get_header_template - return a header
template for a given CPU type
-------------------------------------------------*/
@ -1425,7 +1461,7 @@ const cpu_class_header *cputype_get_header_template(cpu_type cputype)
/*-------------------------------------------------
cputype_get_info_* - return information about a
cputype_get_info_* - return information about a
given CPU type
-------------------------------------------------*/

View File

@ -395,10 +395,19 @@ enum _cpu_type
CPU_ALPHA8201,
CPU_ALPHA8301,
CPU_CDP1802,
CPU_COP420,
CPU_COP421,
CPU_COP401,
CPU_COP410,
CPU_COP411,
CPU_COP402,
CPU_COP420,
CPU_COP421,
CPU_COP422,
CPU_COP404,
CPU_COP424,
CPU_COP425,
CPU_COP426,
CPU_COP444,
CPU_COP445,
CPU_TMP90840,
CPU_TMP90841,
CPU_TMP91640,
@ -744,7 +753,7 @@ const char *cputype_get_info_string(cpu_type cputype, UINT32 state);
***************************************************************************/
/*-------------------------------------------------
safe_cpu_get_pc - return the current PC or ~0
safe_cpu_get_pc - return the current PC or ~0
if the CPU is invalid
-------------------------------------------------*/
@ -792,9 +801,9 @@ INLINE offs_t cpu_address_to_byte(const device_config *cpu, int space, offs_t ad
/*-------------------------------------------------
cpu_address_to_byte_end - convert an address
in the specified address space to a byte
offset specifying the last byte covered by
cpu_address_to_byte_end - convert an address
in the specified address space to a byte
offset specifying the last byte covered by
the address
-------------------------------------------------*/

View File

@ -579,7 +579,7 @@ static MACHINE_START( draco )
static MACHINE_RESET( cidelsa )
{
cputag_set_input_line(machine, "main", INPUT_LINE_RESET, PULSE_LINE);
cputag_set_input_line(machine, "main", INPUT_LINE_RESET, PULSE_LINE);
}
/* Machine Drivers */
@ -689,7 +689,7 @@ static MACHINE_DRIVER_START( draco )
MDRV_MACHINE_START(draco)
MDRV_MACHINE_RESET(cidelsa)
MDRV_CPU_ADD("audio", COP420, DRACO_SND_CHR1) // COP402N
MDRV_CPU_ADD("audio", COP402, DRACO_SND_CHR1) // COP402N
MDRV_CPU_PROGRAM_MAP(draco_sound_map, 0)
MDRV_CPU_IO_MAP(draco_sound_io_map, 0)
MDRV_CPU_CONFIG(draco_cop_intf)

View File

@ -571,10 +571,6 @@ static ADDRESS_MAP_START( thayers_io_map, ADDRESS_SPACE_IO, 8 )
AM_RANGE(0xf7, 0xf7) AM_WRITE(den2_w)
ADDRESS_MAP_END
static ADDRESS_MAP_START( thayers_cop_map, ADDRESS_SPACE_PROGRAM, 8 )
AM_RANGE(0x000, 0x3ff) AM_ROM
ADDRESS_MAP_END
static ADDRESS_MAP_START( thayers_cop_io_map, ADDRESS_SPACE_IO, 8 )
AM_RANGE(COP400_PORT_L, COP400_PORT_L) AM_READWRITE(cop_l_r, cop_l_w)
AM_RANGE(COP400_PORT_G, COP400_PORT_G) AM_READWRITE(cop_g_r, cop_g_w)
@ -751,7 +747,7 @@ static MACHINE_RESET( thayers )
static COP400_INTERFACE( thayers_cop_intf )
{
COP400_CKI_DIVISOR_16, // ???
COP400_CKI_DIVISOR_4, // ???
COP400_CKO_OSCILLATOR_OUTPUT, // ???
COP400_MICROBUS_DISABLED
};
@ -765,7 +761,6 @@ static MACHINE_DRIVER_START( thayers )
MDRV_CPU_IO_MAP(thayers_io_map, 0)
MDRV_CPU_ADD("mcu", COP421, XTAL_4MHz/2) // COP421L-PCA/N
MDRV_CPU_PROGRAM_MAP(thayers_cop_map, 0)
MDRV_CPU_IO_MAP(thayers_cop_io_map, 0)
MDRV_CPU_CONFIG(thayers_cop_intf)

View File

@ -204,10 +204,19 @@ CPUS += RSP
CPUS += ALPHA8201
CPUS += ALPHA8301
CPUS += CDP1802
#CPUS += COP401
CPUS += COP410
#CPUS += COP411
CPUS += COP402
CPUS += COP420
CPUS += COP421
#CPUS += COP422
#CPUS += COP404
#CPUS += COP424
#CPUS += COP425
#CPUS += COP426
#CPUS += COP444
#CPUS += COP445
CPUS += TLCS90
CPUS += MB8841
CPUS += MB8842