COP400 overhaul

- Rewrite the execution control logic to fetch each byte of an instruction separately in one pass of the main loop. This provides EEPROM-compatible timing for the SIO shift register, allowing the 93C46 on quizpun2 to be read and written properly (though its default contents are a bad dump).
- Add M pseudo-register (internal RAM referenced by B) to debugger state.
- Add T register to debugger state on devices where it only affects SKT.
- The SIO state is now displayed in binary when it is defined as a shift register.
- Skipped instructions and the SKIP flag can be debugged by compile-time switch (disabled by default).
This commit is contained in:
AJR 2017-09-11 08:38:25 -04:00
parent 154d80715e
commit 64c117bb50
4 changed files with 333 additions and 244 deletions

View File

@ -50,7 +50,6 @@
- COP410L/COP410C
- save internal RAM when CKO is RAM power supply pin
- COP404L opcode map switching, dual timer, microbus enable
- improve SIO output timing for interface with 93CXX serial EEPROMs
*/
@ -85,6 +84,9 @@ DEFINE_DEVICE_TYPE(COP446C, cop446c_cpu_device, "cop446c", "COP446C")
#define LOG_MICROBUS 0
// step through skipped instructions in debugger
#define COP_DEBUG_SKIP 0
/***************************************************************************
MACROS
@ -181,9 +183,8 @@ cop400_cpu_device::cop400_cpu_device(const machine_config &mconfig, device_type
, m_d_mask(d_mask)
, m_in_mask(in_mask)
{
for (int i = 0; i < 256; i++) {
for (int i = 0; i < 256; i++)
m_InstLen[i] = 1;
}
m_InstLen[0x33] = m_InstLen[0x23] = 2;
@ -192,7 +193,8 @@ cop400_cpu_device::cop400_cpu_device(const machine_config &mconfig, device_type
case COP410_FEATURE:
m_opcode_map = COP410_OPCODE_MAP;
for (int r = 0; r < 2; r++) {
for (int r = 0; r < 2; r++)
{
m_InstLen[0x60 + r] = 2; // JMP
m_InstLen[0x68 + r] = 2; // JSR
}
@ -201,7 +203,8 @@ cop400_cpu_device::cop400_cpu_device(const machine_config &mconfig, device_type
case COP420_FEATURE:
m_opcode_map = COP420_OPCODE_MAP;
for (int r = 0; r < 4; r++) {
for (int r = 0; r < 4; r++)
{
m_InstLen[0x60 + r] = 2; // JMP
m_InstLen[0x68 + r] = 2; // JSR
}
@ -210,7 +213,8 @@ cop400_cpu_device::cop400_cpu_device(const machine_config &mconfig, device_type
case COP444L_FEATURE:
m_opcode_map = COP444L_OPCODE_MAP;
for (int r = 0; r < 8; r++) {
for (int r = 0; r < 8; r++)
{
m_InstLen[0x60 + r] = 2; // JMP
m_InstLen[0x68 + r] = 2; // JSR
}
@ -219,7 +223,8 @@ cop400_cpu_device::cop400_cpu_device(const machine_config &mconfig, device_type
case COP424C_FEATURE:
m_opcode_map = COP424C_OPCODE_MAP;
for (int r = 0; r < 8; r++) {
for (int r = 0; r < 8; r++)
{
m_InstLen[0x60 + r] = 2; // JMP
m_InstLen[0x68 + r] = 2; // JSR
}
@ -369,16 +374,39 @@ void cop400_cpu_device::WRITE_G(uint8_t data)
OUT_G(G);
}
void cop400_cpu_device::WRITE_EN(uint8_t data)
{
if (EN != data)
{
EN = data;
if (BIT(EN, 2))
{
OUT_L(Q);
}
else
{
// tri-state(floating) pins
OUT_L(m_read_l_tristate(0, 0xff));
}
sk_update();
}
}
/***************************************************************************
OPCODE HANDLERS
***************************************************************************/
#define INSTRUCTION(mnemonic) void (cop400_cpu_device::mnemonic)(uint8_t opcode)
#define INSTRUCTION(mnemonic) void (cop400_cpu_device::mnemonic)(uint8_t operand)
#define OP(mnemonic) &cop400_cpu_device::mnemonic
INSTRUCTION(illegal)
{
logerror("COP400: PC = %03x, Illegal opcode = %02x\n", PC-1, ROM(PC-1));
if (m_second_byte)
logerror("COP400: PC = %03x, Illegal opcode = %02x %02x\n", m_prevpc, m_opcode, operand);
else
logerror("COP400: PC = %03x, Illegal opcode = %02x\n", m_prevpc, m_opcode);
}
#include "cop400op.hxx"
@ -426,9 +454,9 @@ const cop400_cpu_device::cop400_opcode_func cop400_cpu_device::COP410_OPCODE_23_
OP(illegal) , OP(illegal) , OP(illegal) , OP(illegal) , OP(illegal) , OP(illegal) , OP(illegal) , OP(illegal)
};
void cop400_cpu_device::cop410_op23(uint8_t opcode)
void cop400_cpu_device::cop410_op23(uint8_t operand)
{
uint8_t opcode23 = fetch();
uint8_t opcode23 = operand;
(this->*COP410_OPCODE_23_MAP[opcode23])(opcode23);
}
@ -472,9 +500,9 @@ const cop400_cpu_device::cop400_opcode_func cop400_cpu_device::COP410_OPCODE_33_
OP(illegal) , OP(illegal) , OP(illegal) , OP(illegal) , OP(illegal) , OP(illegal) , OP(illegal) , OP(illegal)
};
void cop400_cpu_device::cop410_op33(uint8_t opcode)
void cop400_cpu_device::cop410_op33(uint8_t operand)
{
uint8_t opcode33 = fetch();
uint8_t opcode33 = operand;
(this->*COP410_OPCODE_33_MAP[opcode33])(opcode33);
}
@ -557,9 +585,9 @@ const cop400_cpu_device::cop400_opcode_func cop400_cpu_device::COP420_OPCODE_23_
OP(illegal) , OP(illegal) , OP(illegal) , OP(illegal) , OP(illegal) , OP(illegal) , OP(illegal) , OP(illegal)
};
void cop400_cpu_device::cop420_op23(uint8_t opcode)
void cop400_cpu_device::cop420_op23(uint8_t operand)
{
uint8_t opcode23 = fetch();
uint8_t opcode23 = operand;
(this->*COP420_OPCODE_23_MAP[opcode23])(opcode23);
}
@ -603,9 +631,9 @@ const cop400_cpu_device::cop400_opcode_func cop400_cpu_device::COP420_OPCODE_33_
OP(illegal) , OP(illegal) , OP(illegal) , OP(illegal) , OP(illegal) , OP(illegal) , OP(illegal) , OP(illegal)
};
void cop400_cpu_device::cop420_op33(uint8_t opcode)
void cop400_cpu_device::cop420_op33(uint8_t operand)
{
uint8_t opcode33 = fetch();
uint8_t opcode33 = operand;
(this->*COP420_OPCODE_33_MAP[opcode33])(opcode33);
}
@ -688,9 +716,9 @@ const cop400_cpu_device::cop400_opcode_func cop400_cpu_device::COP444L_OPCODE_23
OP(xad) , OP(xad) , OP(xad) , OP(xad) , OP(xad) , OP(xad) , OP(xad) , OP(xad)
};
void cop400_cpu_device::cop444l_op23(uint8_t opcode)
void cop400_cpu_device::cop444l_op23(uint8_t operand)
{
uint8_t opcode23 = fetch();
uint8_t opcode23 = operand;
(this->*COP444L_OPCODE_23_MAP[opcode23])(opcode23);
}
@ -734,9 +762,9 @@ const cop400_cpu_device::cop400_opcode_func cop400_cpu_device::COP444L_OPCODE_33
OP(lbi) , OP(lbi) , OP(lbi) , OP(lbi) , OP(lbi) , OP(lbi) , OP(lbi) , OP(lbi)
};
void cop400_cpu_device::cop444l_op33(uint8_t opcode)
void cop400_cpu_device::cop444l_op33(uint8_t operand)
{
uint8_t opcode33 = fetch();
uint8_t opcode33 = operand;
(this->*COP444L_OPCODE_33_MAP[opcode33])(opcode33);
}
@ -819,9 +847,9 @@ const cop400_cpu_device::cop400_opcode_func cop400_cpu_device::COP424C_OPCODE_23
OP(xad) , OP(xad) , OP(xad) , OP(xad) , OP(xad) , OP(xad) , OP(xad) , OP(xad)
};
void cop400_cpu_device::cop424c_op23(uint8_t opcode)
void cop400_cpu_device::cop424c_op23(uint8_t operand)
{
uint8_t opcode23 = fetch();
uint8_t opcode23 = operand;
(this->*COP424C_OPCODE_23_MAP[opcode23])(opcode23);
}
@ -865,9 +893,9 @@ const cop400_cpu_device::cop400_opcode_func cop400_cpu_device::COP424C_OPCODE_33
OP(lbi) , OP(lbi) , OP(lbi) , OP(lbi) , OP(lbi) , OP(lbi) , OP(lbi) , OP(lbi)
};
void cop400_cpu_device::cop424c_op33(uint8_t opcode)
void cop400_cpu_device::cop424c_op33(uint8_t operand)
{
uint8_t opcode33 = fetch();
uint8_t opcode33 = operand;
(this->*COP424C_OPCODE_33_MAP[opcode33])(opcode33);
}
@ -911,6 +939,24 @@ const cop400_cpu_device::cop400_opcode_func cop400_cpu_device::COP424C_OPCODE_MA
OP(jp) , OP(jp) , OP(jp) , OP(jp) , OP(jp) , OP(jp) , OP(jp) , OP(jid)
};
inline bool cop400_cpu_device::is_control_transfer(uint8_t opcode)
{
// JP, JSRP, JID or LQID
// (TODO: verify that LQID inhibits interrupts since it transfers control temporarily)
if ((opcode & 0x80) == 0x80)
return true;
// JMP or JSR
if ((opcode & 0xf0) == 0x60)
return true;
// RET or RETSK
if ((opcode & 0xfe) == 0x48)
return true;
return false;
}
/***************************************************************************
TIMER CALLBACKS
***************************************************************************/
@ -931,10 +977,6 @@ void cop400_cpu_device::serial_tick()
OUT_SO(BIT(EN, 3));
// serial clock
OUT_SK(SKL);
// serial input
m_si <<= 1;
@ -971,17 +1013,6 @@ void cop400_cpu_device::serial_tick()
OUT_SO(0);
}
// serial clock
if (SKL)
{
OUT_SK(1); // SYNC
}
else
{
OUT_SK(0);
}
// serial input
SIO = ((SIO << 1) | IN_SI()) & 0x0f;
@ -992,7 +1023,8 @@ void cop400_cpu_device::counter_tick()
{
T++;
if (!T) {
if (!T)
{
m_skt_latch = 1;
m_idle = false;
}
@ -1000,12 +1032,9 @@ void cop400_cpu_device::counter_tick()
void cop400_cpu_device::inil_tick()
{
uint8_t in;
int i;
uint8_t in = IN_IN();
in = IN_IN();
for (i = 0; i < 4; i++)
for (int i = 0; i < 4; i++)
{
m_in[i] = (m_in[i] << 1) | BIT(in, i);
@ -1024,17 +1053,9 @@ void cop400_cpu_device::device_timer(emu_timer &timer, device_timer_id id, int p
{
switch (id)
{
case TIMER_SERIAL:
serial_tick();
break;
case TIMER_COUNTER:
counter_tick();
break;
case TIMER_INIL:
inil_tick();
break;
}
}
@ -1059,10 +1080,6 @@ void cop400_cpu_device::device_start()
m_write_sk.resolve_safe();
m_read_cko.resolve_safe(0);
/* allocate serial timer */
m_serial_timer = timer_alloc(TIMER_SERIAL);
m_serial_timer->adjust(attotime::zero, 0, attotime::from_ticks(m_cki, clock()));
/* allocate counter timer */
m_counter_timer = nullptr;
if (m_has_counter)
@ -1071,14 +1088,6 @@ void cop400_cpu_device::device_start()
m_counter_timer->adjust(attotime::zero, 0, attotime::from_ticks(m_cki * 4, clock()));
}
/* allocate IN latch timer */
m_inil_timer = nullptr;
if (m_has_inil)
{
m_inil_timer = timer_alloc(TIMER_INIL);
m_inil_timer->adjust(attotime::zero, 0, attotime::from_ticks(m_cki, clock()));
}
/* register for state saving */
save_item(NAME(m_pc));
save_item(NAME(m_prevpc));
@ -1102,6 +1111,8 @@ void cop400_cpu_device::device_start()
save_item(NAME(m_in));
save_item(NAME(m_halt));
save_item(NAME(m_idle));
save_item(NAME(m_opcode));
save_item(NAME(m_second_byte));
// setup debugger state display
offs_t pc_mask = m_program->addrmask();
@ -1112,18 +1123,20 @@ void cop400_cpu_device::device_start()
state_add(COP400_PC, "PC", m_pc).mask(pc_mask);
state_add(COP400_SA, "SA", m_sa).mask(pc_mask);
state_add(COP400_SB, "SB", m_sb).mask(pc_mask);
if (!(m_featuremask & COP410_FEATURE)) {
if (!(m_featuremask & COP410_FEATURE))
state_add(COP400_SC, "SC", m_sc).mask(pc_mask);
}
state_add(COP400_B, "B", m_b);
state_add(COP400_A, "A", m_a).mask(0xf);
state_add(COP400_M, "M", m_temp_m).mask(0xf).callimport().callexport();
state_add(COP400_G, "G", m_g).mask(0xf);
state_add(COP400_Q, "Q", m_q);
state_add(COP400_SIO, "SIO", m_sio).mask(0xf);
state_add(COP400_SIO, "SIO", m_sio).mask(0xf).formatstr("%4s");
state_add(COP400_EN, "EN", m_en).mask(0xf);
if (m_featuremask & COP424C_FEATURE) {
if (m_has_counter)
state_add(COP400_T, "T", m_t);
}
#if COP_DEBUG_SKIP
state_add(COP400_SKIP, "SKIP", m_skip).mask(1);
#endif
m_icountptr = &m_icount;
@ -1133,12 +1146,14 @@ void cop400_cpu_device::device_start()
m_sc = 0;
m_sio = 0;
m_flags = 0;
m_temp_m = 0;
m_il = 0;
m_in[0] = m_in[1] = m_in[2] = m_in[3] = 0;
m_si = 0;
m_skip_lbi = 0;
m_last_skip = false;
m_skip = false;
m_opcode = 0x44;
}
@ -1154,55 +1169,80 @@ void cop400_cpu_device::device_reset()
C = 0;
OUT_D(0);
EN = 0;
OUT_L(m_read_l_tristate(0, 0xff));
WRITE_G(0);
SKL = 1;
OUT_SK(0);
T = 0;
m_skt_latch = 1;
m_halt = false;
m_idle = false;
m_second_byte = false;
}
/***************************************************************************
EXECUTION
***************************************************************************/
uint8_t cop400_cpu_device::fetch()
void cop400_cpu_device::skip()
{
m_icount--;
// skip the next instruction (TODO: this flag can become an output)
m_skip = true;
}
return ROM(PC++);
void cop400_cpu_device::sk_update()
{
// update SK output after XAS or LEI
if (BIT(EN, 0))
{
// SK = SKL when EN0 = 1 (binary counter mode)
OUT_SK(SKL);
}
else
{
// SK = clock or 0 when EN0 = 0 (shift register mode)
OUT_SK(0);
}
}
void cop400_cpu_device::execute_run()
{
do
{
if (!m_skip) {
if (!m_second_byte && (!m_skip || COP_DEBUG_SKIP))
{
// debugger hook
m_prevpc = PC;
debugger_instruction_hook(this, PC);
}
// halt logic
if (m_cko == COP400_CKO_HALT_IO_PORT) {
if (m_cko == COP400_CKO_HALT_IO_PORT)
m_halt = IN_CKO();
}
if (m_halt || m_idle) {
m_icount--;
continue;
}
if (!m_halt && !m_idle)
{
if (!BIT(EN, 0) && SKL)
{
// Sync pulse actually has a 50% duty cycle, coinciding with address latch for external program
// This implementation, however, is good enough to interface with 93CXX serial EEPROMs
OUT_SK(0);
OUT_SK(1);
}
// fetch opcode
uint8_t opcode = fetch();
cop400_opcode_func function = m_opcode_map[opcode];
// fetch opcode/operand
uint8_t operand = ROM(PC++);
if (!m_second_byte)
m_opcode = operand;
// check for interrupt when all successive transfer of control instructions and successive LBIs have been completed
if (!m_second_byte && BIT(EN, 1) && BIT(IL, 1) && !is_control_transfer(m_opcode) && !m_skip_lbi)
{
// acknowledge interrupt
IL &= ~2;
// check for interrupt
if (BIT(EN, 1) && BIT(IL, 1)) {
// all successive transfer of control instructions and successive LBIs have been completed
if ((function != OP(jp)) && (function != OP(jmp)) && (function != OP(jsr)) && !m_skip_lbi) {
// store skip logic
m_last_skip = m_skip;
m_skip = false;
@ -1213,31 +1253,53 @@ void cop400_cpu_device::execute_run()
// jump to interrupt service routine
PC = 0x0ff;
// disable interrupt
EN &= ~0x02;
// disable interrupts
EN &= ~2;
}
else if (!m_second_byte && m_InstLen[m_opcode] > 1)
{
m_second_byte = true;
}
else if (m_skip)
{
// finish skipping and execute next instruction
m_skip = false;
m_second_byte = false;
}
else
{
cop400_opcode_func function = m_opcode_map[m_opcode];
if (!m_second_byte && (function == OP(jid) || function == OP(lqid)))
{
// JID and LQID must first transfer control and then fetch the operand
// LQID saves the old program counter on the stack; JID doesn't and just jumps again
if (function == OP(lqid))
PUSH(PC);
// jump within page to operand at A/M
PC = (PC & 0x700) | (A << 4) | RAM_R(B);
m_second_byte = true;
}
else
{
// execute instruction
(this->*(function))(operand);
// LBI skip logic
if (m_skip_lbi > 0)
m_skip_lbi--;
// ready for the next instruction
m_second_byte = false;
}
}
IL &= ~2;
}
if (m_skip) {
// skip instruction
if (m_InstLen[opcode] == 2) {
// fetch second byte
opcode = fetch();
}
m_skip = false;
continue;
}
// execute instruction
(this->*(function))(opcode);
// LBI skip logic
if (m_skip_lbi > 0) {
m_skip_lbi--;
serial_tick();
if (m_has_inil)
inil_tick();
}
m_icount--;
} while (m_icount > 0);
}
@ -1256,6 +1318,11 @@ void cop400_cpu_device::state_import(const device_state_entry &entry)
m_c = BIT(m_flags, 1);
m_skl = BIT(m_flags, 0);
break;
case COP400_M:
auto dis = machine().disable_side_effect();
RAM_W(B, m_temp_m);
break;
}
}
@ -1266,6 +1333,11 @@ void cop400_cpu_device::state_export(const device_state_entry &entry)
case STATE_GENFLAGS:
m_flags = (m_skt_latch ? 0x04 : 0x00) | (m_c ? 0x02 : 0x00) | (m_skl ? 0x01 : 0x00);
break;
case COP400_M:
auto dis = machine().disable_side_effect();
m_temp_m = RAM_R(B);
break;
}
}
@ -1279,6 +1351,22 @@ void cop400_cpu_device::state_string_export(const device_state_entry &entry, std
m_skl ? 'S' : '.',
m_skt_latch ? 'T' : '.');
break;
case COP400_SIO:
if (BIT(EN, 0))
{
// display counter in hex
str = string_format("%X ", m_sio);
}
else
{
// display shift register in binary
str = string_format("%d%d%d%d",
BIT(m_sio, 3),
BIT(m_sio, 2),
BIT(m_sio, 1),
BIT(m_sio, 0));
}
break;
}
}

View File

@ -68,11 +68,13 @@ enum
COP400_B,
COP400_C,
COP400_G,
COP400_M,
COP400_Q,
COP400_EN,
COP400_SIO,
COP400_SKL,
COP400_T
COP400_T,
COP400_SKIP
};
/* input lines */
@ -224,7 +226,8 @@ protected:
uint16_t m_sa, m_sb, m_sc; /* subroutine save registers */
uint8_t m_sio; /* 4-bit shift register and counter */
int m_skl; /* 1-bit latch for SK output */
uint8_t m_flags; // used for I/O only
uint8_t m_flags; // used for debugger state only
uint8_t m_temp_m; // 4-bit RAM at B (for debugger state only)
/* counter */
uint8_t m_t; /* 8-bit timer */
@ -248,13 +251,13 @@ protected:
/* execution logic */
int m_InstLen[256]; /* instruction length in bytes */
int m_icount; /* instruction counter */
uint8_t m_opcode; /* opcode being executed */
bool m_second_byte; /* second byte of opcode */
/* timers */
emu_timer *m_serial_timer;
emu_timer *m_counter_timer;
emu_timer *m_inil_timer;
typedef void ( cop400_cpu_device::*cop400_opcode_func ) (uint8_t opcode);
typedef void (cop400_cpu_device::*cop400_opcode_func)(uint8_t operand);
const cop400_opcode_func *m_opcode_map;
@ -271,6 +274,8 @@ protected:
static const cop400_opcode_func COP424C_OPCODE_33_MAP[256];
static const cop400_opcode_func COP424C_OPCODE_MAP[256];
inline static bool is_control_transfer(uint8_t opcode);
void serial_tick();
void counter_tick();
void inil_tick();
@ -279,85 +284,87 @@ protected:
void POP();
void WRITE_Q(uint8_t data);
void WRITE_G(uint8_t data);
void WRITE_EN(uint8_t data);
uint8_t fetch();
void skip();
void sk_update();
void illegal(uint8_t opcode);
void asc(uint8_t opcode);
void add(uint8_t opcode);
void aisc(uint8_t opcode);
void clra(uint8_t opcode);
void comp(uint8_t opcode);
void nop(uint8_t opcode);
void rc(uint8_t opcode);
void sc(uint8_t opcode);
void xor_(uint8_t opcode);
void adt(uint8_t opcode);
void casc(uint8_t opcode);
void jid(uint8_t opcode);
void jmp(uint8_t opcode);
void jp(uint8_t opcode);
void jsr(uint8_t opcode);
void ret(uint8_t opcode);
void cop420_ret(uint8_t opcode);
void retsk(uint8_t opcode);
void halt(uint8_t opcode);
void it(uint8_t opcode);
void camq(uint8_t opcode);
void ld(uint8_t opcode);
void lqid(uint8_t opcode);
void rmb0(uint8_t opcode);
void rmb1(uint8_t opcode);
void rmb2(uint8_t opcode);
void rmb3(uint8_t opcode);
void smb0(uint8_t opcode);
void smb1(uint8_t opcode);
void smb2(uint8_t opcode);
void smb3(uint8_t opcode);
void stii(uint8_t opcode);
void x(uint8_t opcode);
void xad(uint8_t opcode);
void xds(uint8_t opcode);
void xis(uint8_t opcode);
void cqma(uint8_t opcode);
void ldd(uint8_t opcode);
void camt(uint8_t opcode);
void ctma(uint8_t opcode);
void cab(uint8_t opcode);
void cba(uint8_t opcode);
void lbi(uint8_t opcode);
void lei(uint8_t opcode);
void xabr(uint8_t opcode);
void cop444l_xabr(uint8_t opcode);
void skc(uint8_t opcode);
void ske(uint8_t opcode);
void skgz(uint8_t opcode);
void skgbz0(uint8_t opcode);
void skgbz1(uint8_t opcode);
void skgbz2(uint8_t opcode);
void skgbz3(uint8_t opcode);
void skmbz0(uint8_t opcode);
void skmbz1(uint8_t opcode);
void skmbz2(uint8_t opcode);
void skmbz3(uint8_t opcode);
void skt(uint8_t opcode);
void ing(uint8_t opcode);
void inl(uint8_t opcode);
void obd(uint8_t opcode);
void omg(uint8_t opcode);
void xas(uint8_t opcode);
void inin(uint8_t opcode);
void cop402m_inin(uint8_t opcode);
void inil(uint8_t opcode);
void ogi(uint8_t opcode);
void cop410_op23(uint8_t opcode);
void cop410_op33(uint8_t opcode);
void cop420_op23(uint8_t opcode);
void cop420_op33(uint8_t opcode);
void cop444l_op23(uint8_t opcode);
void cop444l_op33(uint8_t opcode);
void cop424c_op23(uint8_t opcode);
void cop424c_op33(uint8_t opcode);
void illegal(uint8_t operand);
void asc(uint8_t operand);
void add(uint8_t operand);
void aisc(uint8_t operand);
void clra(uint8_t operand);
void comp(uint8_t operand);
void nop(uint8_t operand);
void rc(uint8_t operand);
void sc(uint8_t operand);
void xor_(uint8_t operand);
void adt(uint8_t operand);
void casc(uint8_t operand);
void jid(uint8_t operand);
void jmp(uint8_t operand);
void jp(uint8_t operand);
void jsr(uint8_t operand);
void ret(uint8_t operand);
void cop420_ret(uint8_t operand);
void retsk(uint8_t operand);
void halt(uint8_t operand);
void it(uint8_t operand);
void camq(uint8_t operand);
void ld(uint8_t operand);
void lqid(uint8_t operand);
void rmb0(uint8_t operand);
void rmb1(uint8_t operand);
void rmb2(uint8_t operand);
void rmb3(uint8_t operand);
void smb0(uint8_t operand);
void smb1(uint8_t operand);
void smb2(uint8_t operand);
void smb3(uint8_t operand);
void stii(uint8_t operand);
void x(uint8_t operand);
void xad(uint8_t operand);
void xds(uint8_t operand);
void xis(uint8_t operand);
void cqma(uint8_t operand);
void ldd(uint8_t operand);
void camt(uint8_t operand);
void ctma(uint8_t operand);
void cab(uint8_t operand);
void cba(uint8_t operand);
void lbi(uint8_t operand);
void lei(uint8_t operand);
void xabr(uint8_t operand);
void cop444l_xabr(uint8_t operand);
void skc(uint8_t operand);
void ske(uint8_t operand);
void skgz(uint8_t operand);
void skgbz0(uint8_t operand);
void skgbz1(uint8_t operand);
void skgbz2(uint8_t operand);
void skgbz3(uint8_t operand);
void skmbz0(uint8_t operand);
void skmbz1(uint8_t operand);
void skmbz2(uint8_t operand);
void skmbz3(uint8_t operand);
void skt(uint8_t operand);
void ing(uint8_t operand);
void inl(uint8_t operand);
void obd(uint8_t operand);
void omg(uint8_t operand);
void xas(uint8_t operand);
void inin(uint8_t operand);
void cop402m_inin(uint8_t operand);
void inil(uint8_t operand);
void ogi(uint8_t operand);
void cop410_op23(uint8_t operand);
void cop410_op33(uint8_t operand);
void cop420_op23(uint8_t operand);
void cop420_op33(uint8_t operand);
void cop444l_op23(uint8_t operand);
void cop444l_op33(uint8_t operand);
void cop424c_op23(uint8_t operand);
void cop424c_op33(uint8_t operand);
void skgbz(int bit);
void skmbz(int bit);
};

View File

@ -35,7 +35,7 @@ INSTRUCTION( asc )
if (A > 0xF)
{
C = 1;
m_skip = true;
skip();
A &= 0xF;
}
else
@ -80,13 +80,13 @@ INSTRUCTION( add )
INSTRUCTION( aisc )
{
uint8_t y = opcode & 0x0f;
uint8_t y = m_opcode & 0x0f;
A = A + y;
if (A > 0x0f)
{
m_skip = true;
skip();
A &= 0xF;
}
}
@ -238,7 +238,7 @@ INSTRUCTION( casc )
if (A > 0xF)
{
C = 1;
m_skip = true;
skip();
A &= 0xF;
}
else
@ -266,8 +266,6 @@ INSTRUCTION( casc )
INSTRUCTION( jid )
{
PC = (PC & 0x700) | (A << 4) | RAM_R(B);
uint8_t operand = fetch();
PC = (PC & 0x700) | operand;
}
@ -287,8 +285,7 @@ INSTRUCTION( jid )
INSTRUCTION( jmp )
{
uint8_t operand = fetch();
PC = ((opcode & 0x07) << 8) | operand;
PC = ((m_opcode & 0x07) << 8) | operand;
}
/*
@ -317,18 +314,18 @@ INSTRUCTION( jp )
if (page == 2 || page == 3)
{
uint8_t a = opcode & 0x7f;
uint8_t a = m_opcode & 0x7f;
PC = (PC & 0x780) | a;
}
else if ((opcode & 0xc0) == 0xc0)
else if ((m_opcode & 0xc0) == 0xc0)
{
uint8_t a = opcode & 0x3f;
uint8_t a = m_opcode & 0x3f;
PC = (PC & 0x7c0) | a;
}
else
{
// JSRP
uint8_t a = opcode & 0x3f;
uint8_t a = m_opcode & 0x3f;
PUSH(PC);
PC = 0x80 | a;
}
@ -351,9 +348,8 @@ INSTRUCTION( jp )
INSTRUCTION( jsr )
{
uint8_t operand = fetch();
PUSH(PC);
PC = ((opcode & 0x07) << 8) | operand;
PC = ((m_opcode & 0x07) << 8) | operand;
}
/*
@ -413,7 +409,7 @@ INSTRUCTION( cop420_ret )
INSTRUCTION( retsk )
{
POP();
m_skip = true;
skip();
}
/*
@ -529,7 +525,7 @@ INSTRUCTION( camq )
INSTRUCTION( ld )
{
uint8_t r = opcode & 0x30;
uint8_t r = m_opcode & 0x30;
A = RAM_R(B);
B = B ^ r;
@ -551,9 +547,6 @@ INSTRUCTION( ld )
INSTRUCTION( lqid )
{
PUSH(PC);
PC = (PC & 0x700) | (A << 4) | RAM_R(B);
uint8_t operand = fetch();
WRITE_Q(operand);
POP();
}
@ -641,7 +634,7 @@ INSTRUCTION( smb3 ) { RAM_W(B, RAM_R(B) | 0x8); }
INSTRUCTION( stii )
{
uint8_t y = opcode & 0x0f;
uint8_t y = m_opcode & 0x0f;
uint16_t Bd;
RAM_W(B, y);
@ -667,7 +660,7 @@ INSTRUCTION( stii )
INSTRUCTION( x )
{
uint8_t r = opcode & 0x30;
uint8_t r = m_opcode & 0x30;
uint8_t t = RAM_R(B);
RAM_W(B, A);
@ -692,7 +685,7 @@ INSTRUCTION( x )
INSTRUCTION( xad )
{
uint8_t rd = opcode & 0x7f;
uint8_t rd = operand & 0x7f;
uint8_t t = A;
A = RAM_R(rd);
@ -721,7 +714,7 @@ INSTRUCTION( xad )
INSTRUCTION( xds )
{
uint8_t t, Bd;
uint8_t r = opcode & 0x30;
uint8_t r = m_opcode & 0x30;
t = RAM_R(B);
RAM_W(B, A);
@ -732,7 +725,8 @@ INSTRUCTION( xds )
B = B ^ r;
if (Bd == 0x0f) m_skip = true;
if (Bd == 0x0f)
skip();
}
/*
@ -756,7 +750,7 @@ INSTRUCTION( xds )
INSTRUCTION( xis )
{
uint8_t t, Bd;
uint8_t r = opcode & 0x30;
uint8_t r = m_opcode & 0x30;
t = RAM_R(B);
RAM_W(B, A);
@ -767,7 +761,8 @@ INSTRUCTION( xis )
B = B ^ r;
if (Bd == 0x00) m_skip = true;
if (Bd == 0x00)
skip();
}
/*
@ -806,7 +801,7 @@ INSTRUCTION( cqma )
INSTRUCTION( ldd )
{
uint8_t rd = opcode & 0x7f;
uint8_t rd = operand & 0x7f;
A = RAM_R(rd);
}
@ -914,13 +909,13 @@ INSTRUCTION( lbi )
if (m_skip_lbi > 1) return;
m_skip_lbi++;
if (opcode & 0x80)
if (operand & 0x80)
{
B = opcode & 0x7f;
B = operand & 0x7f;
}
else
{
B = (opcode & 0x30) | (((opcode & 0x0f) + 1) & 0x0f);
B = (operand & 0x30) | (((operand & 0x0f) + 1) & 0x0f);
}
}
@ -940,19 +935,9 @@ INSTRUCTION( lbi )
INSTRUCTION( lei )
{
uint8_t y = opcode & 0x0f;
uint8_t y = operand & 0x0f;
EN = y;
if (BIT(EN, 2))
{
OUT_L(Q);
}
else
{
// tri-state(floating) pins
OUT_L(m_read_l_tristate(0, 0xff));
}
WRITE_EN(y);
}
/*
@ -1020,7 +1005,8 @@ INSTRUCTION( cop444l_xabr )
INSTRUCTION( skc )
{
if (C == 1) m_skip = true;
if (C == 1)
skip();
}
/*
@ -1038,7 +1024,8 @@ INSTRUCTION( skc )
INSTRUCTION( ske )
{
if (A == RAM_R(B)) m_skip = true;
if (A == RAM_R(B))
skip();
}
/*
@ -1056,7 +1043,8 @@ INSTRUCTION( ske )
INSTRUCTION( skgz )
{
if (IN_G() == 0) m_skip = true;
if (IN_G() == 0)
skip();
}
/*
@ -1081,7 +1069,8 @@ INSTRUCTION( skgz )
void cop400_cpu_device::skgbz(int bit)
{
if (!BIT(IN_G(), bit)) m_skip = true;
if (!BIT(IN_G(), bit))
skip();
}
INSTRUCTION( skgbz0 ) { skgbz(0); }
@ -1111,7 +1100,8 @@ INSTRUCTION( skgbz3 ) { skgbz(3); }
void cop400_cpu_device::skmbz(int bit)
{
if (!BIT(RAM_R(B), bit)) m_skip = true;
if (!BIT(RAM_R(B), bit))
skip();
}
INSTRUCTION( skmbz0 ) { skmbz(0); }
@ -1137,7 +1127,7 @@ INSTRUCTION( skt )
if (m_skt_latch)
{
m_skt_latch = 0;
m_skip = true;
skip();
}
}
@ -1241,7 +1231,11 @@ INSTRUCTION( xas )
SIO = A;
A = t;
SKL = C;
if (SKL != C)
{
SKL = C;
sk_update();
}
}
/*
@ -1318,7 +1312,7 @@ INSTRUCTION( inil )
INSTRUCTION( ogi )
{
uint8_t y = opcode & 0x0f;
uint8_t y = operand & 0x0f;
WRITE_G(y);
}

View File

@ -32,7 +32,7 @@ PCB Layout
| YM3014 MAHJONG28 |
|---------------------------------------------|
Notes:
COP - COP402 or COP404 MCU (DIP40, +5V on pin 17, GND on pin 22).
COP - DIP40 identified as COP402 MCU (+5V on pin 17, GND on pin 22).
pins 4,3,2 of 93C46 tied to COP pins 23,24,25
All clocks unknown, PCB not working
Possibly Z80's @ 4MHz and YM2203 @ 2MHz
@ -655,7 +655,7 @@ ROM_START( quizpun2 )
ROM_LOAD( "u1", 0x00000, 0x10000, CRC(58506040) SHA1(9d8bed2585e8f188a20270fccd9cfbdb91e48599) )
ROM_LOAD( "u2", 0x10000, 0x10000, CRC(9294a19c) SHA1(cd7109262e5f68b946c84aa390108bcc47ee1300) )
ROM_REGION16_BE( 0x80, "eeprom", 0 ) // EEPROM (tied to the unknown DIP40)
ROM_REGION16_BE( 0x80, "eeprom", 0 ) // EEPROM
ROM_LOAD( "93c46", 0x00, 0x80, CRC(4d244cc8) SHA1(6593d5b7ac1ebb77fee4648ad1d3d9b59a25fdc8) BAD_DUMP ) // backup ram error
ROM_END