mirror of
https://github.com/holub/mame
synced 2025-07-03 17:08:39 +03:00
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:
parent
154d80715e
commit
64c117bb50
@ -50,7 +50,6 @@
|
|||||||
- COP410L/COP410C
|
- COP410L/COP410C
|
||||||
- save internal RAM when CKO is RAM power supply pin
|
- save internal RAM when CKO is RAM power supply pin
|
||||||
- COP404L opcode map switching, dual timer, microbus enable
|
- 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
|
#define LOG_MICROBUS 0
|
||||||
|
|
||||||
|
// step through skipped instructions in debugger
|
||||||
|
#define COP_DEBUG_SKIP 0
|
||||||
|
|
||||||
|
|
||||||
/***************************************************************************
|
/***************************************************************************
|
||||||
MACROS
|
MACROS
|
||||||
@ -181,9 +183,8 @@ cop400_cpu_device::cop400_cpu_device(const machine_config &mconfig, device_type
|
|||||||
, m_d_mask(d_mask)
|
, m_d_mask(d_mask)
|
||||||
, m_in_mask(in_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[i] = 1;
|
||||||
}
|
|
||||||
|
|
||||||
m_InstLen[0x33] = m_InstLen[0x23] = 2;
|
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:
|
case COP410_FEATURE:
|
||||||
m_opcode_map = COP410_OPCODE_MAP;
|
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[0x60 + r] = 2; // JMP
|
||||||
m_InstLen[0x68 + r] = 2; // JSR
|
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:
|
case COP420_FEATURE:
|
||||||
m_opcode_map = COP420_OPCODE_MAP;
|
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[0x60 + r] = 2; // JMP
|
||||||
m_InstLen[0x68 + r] = 2; // JSR
|
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:
|
case COP444L_FEATURE:
|
||||||
m_opcode_map = COP444L_OPCODE_MAP;
|
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[0x60 + r] = 2; // JMP
|
||||||
m_InstLen[0x68 + r] = 2; // JSR
|
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:
|
case COP424C_FEATURE:
|
||||||
m_opcode_map = COP424C_OPCODE_MAP;
|
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[0x60 + r] = 2; // JMP
|
||||||
m_InstLen[0x68 + r] = 2; // JSR
|
m_InstLen[0x68 + r] = 2; // JSR
|
||||||
}
|
}
|
||||||
@ -369,16 +374,39 @@ void cop400_cpu_device::WRITE_G(uint8_t data)
|
|||||||
OUT_G(G);
|
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
|
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
|
#define OP(mnemonic) &cop400_cpu_device::mnemonic
|
||||||
|
|
||||||
INSTRUCTION(illegal)
|
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"
|
#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)
|
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);
|
(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)
|
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);
|
(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)
|
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);
|
(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)
|
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);
|
(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)
|
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);
|
(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)
|
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);
|
(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)
|
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);
|
(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)
|
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);
|
(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)
|
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
|
TIMER CALLBACKS
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
@ -931,10 +977,6 @@ void cop400_cpu_device::serial_tick()
|
|||||||
|
|
||||||
OUT_SO(BIT(EN, 3));
|
OUT_SO(BIT(EN, 3));
|
||||||
|
|
||||||
// serial clock
|
|
||||||
|
|
||||||
OUT_SK(SKL);
|
|
||||||
|
|
||||||
// serial input
|
// serial input
|
||||||
|
|
||||||
m_si <<= 1;
|
m_si <<= 1;
|
||||||
@ -971,17 +1013,6 @@ void cop400_cpu_device::serial_tick()
|
|||||||
OUT_SO(0);
|
OUT_SO(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// serial clock
|
|
||||||
|
|
||||||
if (SKL)
|
|
||||||
{
|
|
||||||
OUT_SK(1); // SYNC
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
OUT_SK(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
// serial input
|
// serial input
|
||||||
|
|
||||||
SIO = ((SIO << 1) | IN_SI()) & 0x0f;
|
SIO = ((SIO << 1) | IN_SI()) & 0x0f;
|
||||||
@ -992,7 +1023,8 @@ void cop400_cpu_device::counter_tick()
|
|||||||
{
|
{
|
||||||
T++;
|
T++;
|
||||||
|
|
||||||
if (!T) {
|
if (!T)
|
||||||
|
{
|
||||||
m_skt_latch = 1;
|
m_skt_latch = 1;
|
||||||
m_idle = false;
|
m_idle = false;
|
||||||
}
|
}
|
||||||
@ -1000,12 +1032,9 @@ void cop400_cpu_device::counter_tick()
|
|||||||
|
|
||||||
void cop400_cpu_device::inil_tick()
|
void cop400_cpu_device::inil_tick()
|
||||||
{
|
{
|
||||||
uint8_t in;
|
uint8_t in = IN_IN();
|
||||||
int i;
|
|
||||||
|
|
||||||
in = IN_IN();
|
for (int i = 0; i < 4; i++)
|
||||||
|
|
||||||
for (i = 0; i < 4; i++)
|
|
||||||
{
|
{
|
||||||
m_in[i] = (m_in[i] << 1) | BIT(in, 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)
|
switch (id)
|
||||||
{
|
{
|
||||||
case TIMER_SERIAL:
|
|
||||||
serial_tick();
|
|
||||||
break;
|
|
||||||
|
|
||||||
case TIMER_COUNTER:
|
case TIMER_COUNTER:
|
||||||
counter_tick();
|
counter_tick();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TIMER_INIL:
|
|
||||||
inil_tick();
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1059,10 +1080,6 @@ void cop400_cpu_device::device_start()
|
|||||||
m_write_sk.resolve_safe();
|
m_write_sk.resolve_safe();
|
||||||
m_read_cko.resolve_safe(0);
|
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 */
|
/* allocate counter timer */
|
||||||
m_counter_timer = nullptr;
|
m_counter_timer = nullptr;
|
||||||
if (m_has_counter)
|
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()));
|
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 */
|
/* register for state saving */
|
||||||
save_item(NAME(m_pc));
|
save_item(NAME(m_pc));
|
||||||
save_item(NAME(m_prevpc));
|
save_item(NAME(m_prevpc));
|
||||||
@ -1102,6 +1111,8 @@ void cop400_cpu_device::device_start()
|
|||||||
save_item(NAME(m_in));
|
save_item(NAME(m_in));
|
||||||
save_item(NAME(m_halt));
|
save_item(NAME(m_halt));
|
||||||
save_item(NAME(m_idle));
|
save_item(NAME(m_idle));
|
||||||
|
save_item(NAME(m_opcode));
|
||||||
|
save_item(NAME(m_second_byte));
|
||||||
|
|
||||||
// setup debugger state display
|
// setup debugger state display
|
||||||
offs_t pc_mask = m_program->addrmask();
|
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_PC, "PC", m_pc).mask(pc_mask);
|
||||||
state_add(COP400_SA, "SA", m_sa).mask(pc_mask);
|
state_add(COP400_SA, "SA", m_sa).mask(pc_mask);
|
||||||
state_add(COP400_SB, "SB", m_sb).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_SC, "SC", m_sc).mask(pc_mask);
|
||||||
}
|
|
||||||
state_add(COP400_B, "B", m_b);
|
state_add(COP400_B, "B", m_b);
|
||||||
state_add(COP400_A, "A", m_a).mask(0xf);
|
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_G, "G", m_g).mask(0xf);
|
||||||
state_add(COP400_Q, "Q", m_q);
|
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);
|
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);
|
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;
|
m_icountptr = &m_icount;
|
||||||
|
|
||||||
@ -1133,12 +1146,14 @@ void cop400_cpu_device::device_start()
|
|||||||
m_sc = 0;
|
m_sc = 0;
|
||||||
m_sio = 0;
|
m_sio = 0;
|
||||||
m_flags = 0;
|
m_flags = 0;
|
||||||
|
m_temp_m = 0;
|
||||||
m_il = 0;
|
m_il = 0;
|
||||||
m_in[0] = m_in[1] = m_in[2] = m_in[3] = 0;
|
m_in[0] = m_in[1] = m_in[2] = m_in[3] = 0;
|
||||||
m_si = 0;
|
m_si = 0;
|
||||||
m_skip_lbi = 0;
|
m_skip_lbi = 0;
|
||||||
m_last_skip = false;
|
m_last_skip = false;
|
||||||
m_skip = false;
|
m_skip = false;
|
||||||
|
m_opcode = 0x44;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1154,55 +1169,80 @@ void cop400_cpu_device::device_reset()
|
|||||||
C = 0;
|
C = 0;
|
||||||
OUT_D(0);
|
OUT_D(0);
|
||||||
EN = 0;
|
EN = 0;
|
||||||
|
OUT_L(m_read_l_tristate(0, 0xff));
|
||||||
WRITE_G(0);
|
WRITE_G(0);
|
||||||
SKL = 1;
|
SKL = 1;
|
||||||
|
OUT_SK(0);
|
||||||
|
|
||||||
T = 0;
|
T = 0;
|
||||||
m_skt_latch = 1;
|
m_skt_latch = 1;
|
||||||
|
|
||||||
m_halt = false;
|
m_halt = false;
|
||||||
m_idle = false;
|
m_idle = false;
|
||||||
|
m_second_byte = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/***************************************************************************
|
/***************************************************************************
|
||||||
EXECUTION
|
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()
|
void cop400_cpu_device::execute_run()
|
||||||
{
|
{
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
if (!m_skip) {
|
if (!m_second_byte && (!m_skip || COP_DEBUG_SKIP))
|
||||||
|
{
|
||||||
// debugger hook
|
// debugger hook
|
||||||
m_prevpc = PC;
|
m_prevpc = PC;
|
||||||
debugger_instruction_hook(this, PC);
|
debugger_instruction_hook(this, PC);
|
||||||
}
|
}
|
||||||
|
|
||||||
// halt logic
|
// halt logic
|
||||||
if (m_cko == COP400_CKO_HALT_IO_PORT) {
|
if (m_cko == COP400_CKO_HALT_IO_PORT)
|
||||||
m_halt = IN_CKO();
|
m_halt = IN_CKO();
|
||||||
}
|
|
||||||
|
|
||||||
if (m_halt || m_idle) {
|
if (!m_halt && !m_idle)
|
||||||
m_icount--;
|
{
|
||||||
continue;
|
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
|
// fetch opcode/operand
|
||||||
uint8_t opcode = fetch();
|
uint8_t operand = ROM(PC++);
|
||||||
cop400_opcode_func function = m_opcode_map[opcode];
|
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
|
// store skip logic
|
||||||
m_last_skip = m_skip;
|
m_last_skip = m_skip;
|
||||||
m_skip = false;
|
m_skip = false;
|
||||||
@ -1213,31 +1253,53 @@ void cop400_cpu_device::execute_run()
|
|||||||
// jump to interrupt service routine
|
// jump to interrupt service routine
|
||||||
PC = 0x0ff;
|
PC = 0x0ff;
|
||||||
|
|
||||||
// disable interrupt
|
// disable interrupts
|
||||||
EN &= ~0x02;
|
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;
|
serial_tick();
|
||||||
}
|
if (m_has_inil)
|
||||||
|
inil_tick();
|
||||||
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--;
|
|
||||||
}
|
}
|
||||||
|
m_icount--;
|
||||||
} while (m_icount > 0);
|
} 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_c = BIT(m_flags, 1);
|
||||||
m_skl = BIT(m_flags, 0);
|
m_skl = BIT(m_flags, 0);
|
||||||
break;
|
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:
|
case STATE_GENFLAGS:
|
||||||
m_flags = (m_skt_latch ? 0x04 : 0x00) | (m_c ? 0x02 : 0x00) | (m_skl ? 0x01 : 0x00);
|
m_flags = (m_skt_latch ? 0x04 : 0x00) | (m_c ? 0x02 : 0x00) | (m_skl ? 0x01 : 0x00);
|
||||||
break;
|
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_skl ? 'S' : '.',
|
||||||
m_skt_latch ? 'T' : '.');
|
m_skt_latch ? 'T' : '.');
|
||||||
break;
|
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -68,11 +68,13 @@ enum
|
|||||||
COP400_B,
|
COP400_B,
|
||||||
COP400_C,
|
COP400_C,
|
||||||
COP400_G,
|
COP400_G,
|
||||||
|
COP400_M,
|
||||||
COP400_Q,
|
COP400_Q,
|
||||||
COP400_EN,
|
COP400_EN,
|
||||||
COP400_SIO,
|
COP400_SIO,
|
||||||
COP400_SKL,
|
COP400_SKL,
|
||||||
COP400_T
|
COP400_T,
|
||||||
|
COP400_SKIP
|
||||||
};
|
};
|
||||||
|
|
||||||
/* input lines */
|
/* input lines */
|
||||||
@ -224,7 +226,8 @@ protected:
|
|||||||
uint16_t m_sa, m_sb, m_sc; /* subroutine save registers */
|
uint16_t m_sa, m_sb, m_sc; /* subroutine save registers */
|
||||||
uint8_t m_sio; /* 4-bit shift register and counter */
|
uint8_t m_sio; /* 4-bit shift register and counter */
|
||||||
int m_skl; /* 1-bit latch for SK output */
|
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 */
|
/* counter */
|
||||||
uint8_t m_t; /* 8-bit timer */
|
uint8_t m_t; /* 8-bit timer */
|
||||||
@ -248,13 +251,13 @@ protected:
|
|||||||
/* execution logic */
|
/* execution logic */
|
||||||
int m_InstLen[256]; /* instruction length in bytes */
|
int m_InstLen[256]; /* instruction length in bytes */
|
||||||
int m_icount; /* instruction counter */
|
int m_icount; /* instruction counter */
|
||||||
|
uint8_t m_opcode; /* opcode being executed */
|
||||||
|
bool m_second_byte; /* second byte of opcode */
|
||||||
|
|
||||||
/* timers */
|
/* timers */
|
||||||
emu_timer *m_serial_timer;
|
|
||||||
emu_timer *m_counter_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;
|
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_33_MAP[256];
|
||||||
static const cop400_opcode_func COP424C_OPCODE_MAP[256];
|
static const cop400_opcode_func COP424C_OPCODE_MAP[256];
|
||||||
|
|
||||||
|
inline static bool is_control_transfer(uint8_t opcode);
|
||||||
|
|
||||||
void serial_tick();
|
void serial_tick();
|
||||||
void counter_tick();
|
void counter_tick();
|
||||||
void inil_tick();
|
void inil_tick();
|
||||||
@ -279,85 +284,87 @@ protected:
|
|||||||
void POP();
|
void POP();
|
||||||
void WRITE_Q(uint8_t data);
|
void WRITE_Q(uint8_t data);
|
||||||
void WRITE_G(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 illegal(uint8_t operand);
|
||||||
void asc(uint8_t opcode);
|
void asc(uint8_t operand);
|
||||||
void add(uint8_t opcode);
|
void add(uint8_t operand);
|
||||||
void aisc(uint8_t opcode);
|
void aisc(uint8_t operand);
|
||||||
void clra(uint8_t opcode);
|
void clra(uint8_t operand);
|
||||||
void comp(uint8_t opcode);
|
void comp(uint8_t operand);
|
||||||
void nop(uint8_t opcode);
|
void nop(uint8_t operand);
|
||||||
void rc(uint8_t opcode);
|
void rc(uint8_t operand);
|
||||||
void sc(uint8_t opcode);
|
void sc(uint8_t operand);
|
||||||
void xor_(uint8_t opcode);
|
void xor_(uint8_t operand);
|
||||||
void adt(uint8_t opcode);
|
void adt(uint8_t operand);
|
||||||
void casc(uint8_t opcode);
|
void casc(uint8_t operand);
|
||||||
void jid(uint8_t opcode);
|
void jid(uint8_t operand);
|
||||||
void jmp(uint8_t opcode);
|
void jmp(uint8_t operand);
|
||||||
void jp(uint8_t opcode);
|
void jp(uint8_t operand);
|
||||||
void jsr(uint8_t opcode);
|
void jsr(uint8_t operand);
|
||||||
void ret(uint8_t opcode);
|
void ret(uint8_t operand);
|
||||||
void cop420_ret(uint8_t opcode);
|
void cop420_ret(uint8_t operand);
|
||||||
void retsk(uint8_t opcode);
|
void retsk(uint8_t operand);
|
||||||
void halt(uint8_t opcode);
|
void halt(uint8_t operand);
|
||||||
void it(uint8_t opcode);
|
void it(uint8_t operand);
|
||||||
void camq(uint8_t opcode);
|
void camq(uint8_t operand);
|
||||||
void ld(uint8_t opcode);
|
void ld(uint8_t operand);
|
||||||
void lqid(uint8_t opcode);
|
void lqid(uint8_t operand);
|
||||||
void rmb0(uint8_t opcode);
|
void rmb0(uint8_t operand);
|
||||||
void rmb1(uint8_t opcode);
|
void rmb1(uint8_t operand);
|
||||||
void rmb2(uint8_t opcode);
|
void rmb2(uint8_t operand);
|
||||||
void rmb3(uint8_t opcode);
|
void rmb3(uint8_t operand);
|
||||||
void smb0(uint8_t opcode);
|
void smb0(uint8_t operand);
|
||||||
void smb1(uint8_t opcode);
|
void smb1(uint8_t operand);
|
||||||
void smb2(uint8_t opcode);
|
void smb2(uint8_t operand);
|
||||||
void smb3(uint8_t opcode);
|
void smb3(uint8_t operand);
|
||||||
void stii(uint8_t opcode);
|
void stii(uint8_t operand);
|
||||||
void x(uint8_t opcode);
|
void x(uint8_t operand);
|
||||||
void xad(uint8_t opcode);
|
void xad(uint8_t operand);
|
||||||
void xds(uint8_t opcode);
|
void xds(uint8_t operand);
|
||||||
void xis(uint8_t opcode);
|
void xis(uint8_t operand);
|
||||||
void cqma(uint8_t opcode);
|
void cqma(uint8_t operand);
|
||||||
void ldd(uint8_t opcode);
|
void ldd(uint8_t operand);
|
||||||
void camt(uint8_t opcode);
|
void camt(uint8_t operand);
|
||||||
void ctma(uint8_t opcode);
|
void ctma(uint8_t operand);
|
||||||
void cab(uint8_t opcode);
|
void cab(uint8_t operand);
|
||||||
void cba(uint8_t opcode);
|
void cba(uint8_t operand);
|
||||||
void lbi(uint8_t opcode);
|
void lbi(uint8_t operand);
|
||||||
void lei(uint8_t opcode);
|
void lei(uint8_t operand);
|
||||||
void xabr(uint8_t opcode);
|
void xabr(uint8_t operand);
|
||||||
void cop444l_xabr(uint8_t opcode);
|
void cop444l_xabr(uint8_t operand);
|
||||||
void skc(uint8_t opcode);
|
void skc(uint8_t operand);
|
||||||
void ske(uint8_t opcode);
|
void ske(uint8_t operand);
|
||||||
void skgz(uint8_t opcode);
|
void skgz(uint8_t operand);
|
||||||
void skgbz0(uint8_t opcode);
|
void skgbz0(uint8_t operand);
|
||||||
void skgbz1(uint8_t opcode);
|
void skgbz1(uint8_t operand);
|
||||||
void skgbz2(uint8_t opcode);
|
void skgbz2(uint8_t operand);
|
||||||
void skgbz3(uint8_t opcode);
|
void skgbz3(uint8_t operand);
|
||||||
void skmbz0(uint8_t opcode);
|
void skmbz0(uint8_t operand);
|
||||||
void skmbz1(uint8_t opcode);
|
void skmbz1(uint8_t operand);
|
||||||
void skmbz2(uint8_t opcode);
|
void skmbz2(uint8_t operand);
|
||||||
void skmbz3(uint8_t opcode);
|
void skmbz3(uint8_t operand);
|
||||||
void skt(uint8_t opcode);
|
void skt(uint8_t operand);
|
||||||
void ing(uint8_t opcode);
|
void ing(uint8_t operand);
|
||||||
void inl(uint8_t opcode);
|
void inl(uint8_t operand);
|
||||||
void obd(uint8_t opcode);
|
void obd(uint8_t operand);
|
||||||
void omg(uint8_t opcode);
|
void omg(uint8_t operand);
|
||||||
void xas(uint8_t opcode);
|
void xas(uint8_t operand);
|
||||||
void inin(uint8_t opcode);
|
void inin(uint8_t operand);
|
||||||
void cop402m_inin(uint8_t opcode);
|
void cop402m_inin(uint8_t operand);
|
||||||
void inil(uint8_t opcode);
|
void inil(uint8_t operand);
|
||||||
void ogi(uint8_t opcode);
|
void ogi(uint8_t operand);
|
||||||
void cop410_op23(uint8_t opcode);
|
void cop410_op23(uint8_t operand);
|
||||||
void cop410_op33(uint8_t opcode);
|
void cop410_op33(uint8_t operand);
|
||||||
void cop420_op23(uint8_t opcode);
|
void cop420_op23(uint8_t operand);
|
||||||
void cop420_op33(uint8_t opcode);
|
void cop420_op33(uint8_t operand);
|
||||||
void cop444l_op23(uint8_t opcode);
|
void cop444l_op23(uint8_t operand);
|
||||||
void cop444l_op33(uint8_t opcode);
|
void cop444l_op33(uint8_t operand);
|
||||||
void cop424c_op23(uint8_t opcode);
|
void cop424c_op23(uint8_t operand);
|
||||||
void cop424c_op33(uint8_t opcode);
|
void cop424c_op33(uint8_t operand);
|
||||||
void skgbz(int bit);
|
void skgbz(int bit);
|
||||||
void skmbz(int bit);
|
void skmbz(int bit);
|
||||||
};
|
};
|
||||||
|
@ -35,7 +35,7 @@ INSTRUCTION( asc )
|
|||||||
if (A > 0xF)
|
if (A > 0xF)
|
||||||
{
|
{
|
||||||
C = 1;
|
C = 1;
|
||||||
m_skip = true;
|
skip();
|
||||||
A &= 0xF;
|
A &= 0xF;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -80,13 +80,13 @@ INSTRUCTION( add )
|
|||||||
|
|
||||||
INSTRUCTION( aisc )
|
INSTRUCTION( aisc )
|
||||||
{
|
{
|
||||||
uint8_t y = opcode & 0x0f;
|
uint8_t y = m_opcode & 0x0f;
|
||||||
|
|
||||||
A = A + y;
|
A = A + y;
|
||||||
|
|
||||||
if (A > 0x0f)
|
if (A > 0x0f)
|
||||||
{
|
{
|
||||||
m_skip = true;
|
skip();
|
||||||
A &= 0xF;
|
A &= 0xF;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -238,7 +238,7 @@ INSTRUCTION( casc )
|
|||||||
if (A > 0xF)
|
if (A > 0xF)
|
||||||
{
|
{
|
||||||
C = 1;
|
C = 1;
|
||||||
m_skip = true;
|
skip();
|
||||||
A &= 0xF;
|
A &= 0xF;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -266,8 +266,6 @@ INSTRUCTION( casc )
|
|||||||
|
|
||||||
INSTRUCTION( jid )
|
INSTRUCTION( jid )
|
||||||
{
|
{
|
||||||
PC = (PC & 0x700) | (A << 4) | RAM_R(B);
|
|
||||||
uint8_t operand = fetch();
|
|
||||||
PC = (PC & 0x700) | operand;
|
PC = (PC & 0x700) | operand;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -287,8 +285,7 @@ INSTRUCTION( jid )
|
|||||||
|
|
||||||
INSTRUCTION( jmp )
|
INSTRUCTION( jmp )
|
||||||
{
|
{
|
||||||
uint8_t operand = fetch();
|
PC = ((m_opcode & 0x07) << 8) | operand;
|
||||||
PC = ((opcode & 0x07) << 8) | operand;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -317,18 +314,18 @@ INSTRUCTION( jp )
|
|||||||
|
|
||||||
if (page == 2 || page == 3)
|
if (page == 2 || page == 3)
|
||||||
{
|
{
|
||||||
uint8_t a = opcode & 0x7f;
|
uint8_t a = m_opcode & 0x7f;
|
||||||
PC = (PC & 0x780) | a;
|
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;
|
PC = (PC & 0x7c0) | a;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// JSRP
|
// JSRP
|
||||||
uint8_t a = opcode & 0x3f;
|
uint8_t a = m_opcode & 0x3f;
|
||||||
PUSH(PC);
|
PUSH(PC);
|
||||||
PC = 0x80 | a;
|
PC = 0x80 | a;
|
||||||
}
|
}
|
||||||
@ -351,9 +348,8 @@ INSTRUCTION( jp )
|
|||||||
|
|
||||||
INSTRUCTION( jsr )
|
INSTRUCTION( jsr )
|
||||||
{
|
{
|
||||||
uint8_t operand = fetch();
|
|
||||||
PUSH(PC);
|
PUSH(PC);
|
||||||
PC = ((opcode & 0x07) << 8) | operand;
|
PC = ((m_opcode & 0x07) << 8) | operand;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -413,7 +409,7 @@ INSTRUCTION( cop420_ret )
|
|||||||
INSTRUCTION( retsk )
|
INSTRUCTION( retsk )
|
||||||
{
|
{
|
||||||
POP();
|
POP();
|
||||||
m_skip = true;
|
skip();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -529,7 +525,7 @@ INSTRUCTION( camq )
|
|||||||
|
|
||||||
INSTRUCTION( ld )
|
INSTRUCTION( ld )
|
||||||
{
|
{
|
||||||
uint8_t r = opcode & 0x30;
|
uint8_t r = m_opcode & 0x30;
|
||||||
|
|
||||||
A = RAM_R(B);
|
A = RAM_R(B);
|
||||||
B = B ^ r;
|
B = B ^ r;
|
||||||
@ -551,9 +547,6 @@ INSTRUCTION( ld )
|
|||||||
|
|
||||||
INSTRUCTION( lqid )
|
INSTRUCTION( lqid )
|
||||||
{
|
{
|
||||||
PUSH(PC);
|
|
||||||
PC = (PC & 0x700) | (A << 4) | RAM_R(B);
|
|
||||||
uint8_t operand = fetch();
|
|
||||||
WRITE_Q(operand);
|
WRITE_Q(operand);
|
||||||
POP();
|
POP();
|
||||||
}
|
}
|
||||||
@ -641,7 +634,7 @@ INSTRUCTION( smb3 ) { RAM_W(B, RAM_R(B) | 0x8); }
|
|||||||
|
|
||||||
INSTRUCTION( stii )
|
INSTRUCTION( stii )
|
||||||
{
|
{
|
||||||
uint8_t y = opcode & 0x0f;
|
uint8_t y = m_opcode & 0x0f;
|
||||||
uint16_t Bd;
|
uint16_t Bd;
|
||||||
|
|
||||||
RAM_W(B, y);
|
RAM_W(B, y);
|
||||||
@ -667,7 +660,7 @@ INSTRUCTION( stii )
|
|||||||
|
|
||||||
INSTRUCTION( x )
|
INSTRUCTION( x )
|
||||||
{
|
{
|
||||||
uint8_t r = opcode & 0x30;
|
uint8_t r = m_opcode & 0x30;
|
||||||
uint8_t t = RAM_R(B);
|
uint8_t t = RAM_R(B);
|
||||||
|
|
||||||
RAM_W(B, A);
|
RAM_W(B, A);
|
||||||
@ -692,7 +685,7 @@ INSTRUCTION( x )
|
|||||||
|
|
||||||
INSTRUCTION( xad )
|
INSTRUCTION( xad )
|
||||||
{
|
{
|
||||||
uint8_t rd = opcode & 0x7f;
|
uint8_t rd = operand & 0x7f;
|
||||||
uint8_t t = A;
|
uint8_t t = A;
|
||||||
|
|
||||||
A = RAM_R(rd);
|
A = RAM_R(rd);
|
||||||
@ -721,7 +714,7 @@ INSTRUCTION( xad )
|
|||||||
INSTRUCTION( xds )
|
INSTRUCTION( xds )
|
||||||
{
|
{
|
||||||
uint8_t t, Bd;
|
uint8_t t, Bd;
|
||||||
uint8_t r = opcode & 0x30;
|
uint8_t r = m_opcode & 0x30;
|
||||||
|
|
||||||
t = RAM_R(B);
|
t = RAM_R(B);
|
||||||
RAM_W(B, A);
|
RAM_W(B, A);
|
||||||
@ -732,7 +725,8 @@ INSTRUCTION( xds )
|
|||||||
|
|
||||||
B = B ^ r;
|
B = B ^ r;
|
||||||
|
|
||||||
if (Bd == 0x0f) m_skip = true;
|
if (Bd == 0x0f)
|
||||||
|
skip();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -756,7 +750,7 @@ INSTRUCTION( xds )
|
|||||||
INSTRUCTION( xis )
|
INSTRUCTION( xis )
|
||||||
{
|
{
|
||||||
uint8_t t, Bd;
|
uint8_t t, Bd;
|
||||||
uint8_t r = opcode & 0x30;
|
uint8_t r = m_opcode & 0x30;
|
||||||
|
|
||||||
t = RAM_R(B);
|
t = RAM_R(B);
|
||||||
RAM_W(B, A);
|
RAM_W(B, A);
|
||||||
@ -767,7 +761,8 @@ INSTRUCTION( xis )
|
|||||||
|
|
||||||
B = B ^ r;
|
B = B ^ r;
|
||||||
|
|
||||||
if (Bd == 0x00) m_skip = true;
|
if (Bd == 0x00)
|
||||||
|
skip();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -806,7 +801,7 @@ INSTRUCTION( cqma )
|
|||||||
|
|
||||||
INSTRUCTION( ldd )
|
INSTRUCTION( ldd )
|
||||||
{
|
{
|
||||||
uint8_t rd = opcode & 0x7f;
|
uint8_t rd = operand & 0x7f;
|
||||||
|
|
||||||
A = RAM_R(rd);
|
A = RAM_R(rd);
|
||||||
}
|
}
|
||||||
@ -914,13 +909,13 @@ INSTRUCTION( lbi )
|
|||||||
if (m_skip_lbi > 1) return;
|
if (m_skip_lbi > 1) return;
|
||||||
m_skip_lbi++;
|
m_skip_lbi++;
|
||||||
|
|
||||||
if (opcode & 0x80)
|
if (operand & 0x80)
|
||||||
{
|
{
|
||||||
B = opcode & 0x7f;
|
B = operand & 0x7f;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
B = (opcode & 0x30) | (((opcode & 0x0f) + 1) & 0x0f);
|
B = (operand & 0x30) | (((operand & 0x0f) + 1) & 0x0f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -940,19 +935,9 @@ INSTRUCTION( lbi )
|
|||||||
|
|
||||||
INSTRUCTION( lei )
|
INSTRUCTION( lei )
|
||||||
{
|
{
|
||||||
uint8_t y = opcode & 0x0f;
|
uint8_t y = operand & 0x0f;
|
||||||
|
|
||||||
EN = y;
|
WRITE_EN(y);
|
||||||
|
|
||||||
if (BIT(EN, 2))
|
|
||||||
{
|
|
||||||
OUT_L(Q);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// tri-state(floating) pins
|
|
||||||
OUT_L(m_read_l_tristate(0, 0xff));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1020,7 +1005,8 @@ INSTRUCTION( cop444l_xabr )
|
|||||||
|
|
||||||
INSTRUCTION( skc )
|
INSTRUCTION( skc )
|
||||||
{
|
{
|
||||||
if (C == 1) m_skip = true;
|
if (C == 1)
|
||||||
|
skip();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1038,7 +1024,8 @@ INSTRUCTION( skc )
|
|||||||
|
|
||||||
INSTRUCTION( ske )
|
INSTRUCTION( ske )
|
||||||
{
|
{
|
||||||
if (A == RAM_R(B)) m_skip = true;
|
if (A == RAM_R(B))
|
||||||
|
skip();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1056,7 +1043,8 @@ INSTRUCTION( ske )
|
|||||||
|
|
||||||
INSTRUCTION( skgz )
|
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)
|
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); }
|
INSTRUCTION( skgbz0 ) { skgbz(0); }
|
||||||
@ -1111,7 +1100,8 @@ INSTRUCTION( skgbz3 ) { skgbz(3); }
|
|||||||
|
|
||||||
void cop400_cpu_device::skmbz(int bit)
|
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); }
|
INSTRUCTION( skmbz0 ) { skmbz(0); }
|
||||||
@ -1137,7 +1127,7 @@ INSTRUCTION( skt )
|
|||||||
if (m_skt_latch)
|
if (m_skt_latch)
|
||||||
{
|
{
|
||||||
m_skt_latch = 0;
|
m_skt_latch = 0;
|
||||||
m_skip = true;
|
skip();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1241,7 +1231,11 @@ INSTRUCTION( xas )
|
|||||||
SIO = A;
|
SIO = A;
|
||||||
A = t;
|
A = t;
|
||||||
|
|
||||||
SKL = C;
|
if (SKL != C)
|
||||||
|
{
|
||||||
|
SKL = C;
|
||||||
|
sk_update();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1318,7 +1312,7 @@ INSTRUCTION( inil )
|
|||||||
|
|
||||||
INSTRUCTION( ogi )
|
INSTRUCTION( ogi )
|
||||||
{
|
{
|
||||||
uint8_t y = opcode & 0x0f;
|
uint8_t y = operand & 0x0f;
|
||||||
|
|
||||||
WRITE_G(y);
|
WRITE_G(y);
|
||||||
}
|
}
|
||||||
|
@ -32,7 +32,7 @@ PCB Layout
|
|||||||
| YM3014 MAHJONG28 |
|
| YM3014 MAHJONG28 |
|
||||||
|---------------------------------------------|
|
|---------------------------------------------|
|
||||||
Notes:
|
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
|
pins 4,3,2 of 93C46 tied to COP pins 23,24,25
|
||||||
All clocks unknown, PCB not working
|
All clocks unknown, PCB not working
|
||||||
Possibly Z80's @ 4MHz and YM2203 @ 2MHz
|
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( "u1", 0x00000, 0x10000, CRC(58506040) SHA1(9d8bed2585e8f188a20270fccd9cfbdb91e48599) )
|
||||||
ROM_LOAD( "u2", 0x10000, 0x10000, CRC(9294a19c) SHA1(cd7109262e5f68b946c84aa390108bcc47ee1300) )
|
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_LOAD( "93c46", 0x00, 0x80, CRC(4d244cc8) SHA1(6593d5b7ac1ebb77fee4648ad1d3d9b59a25fdc8) BAD_DUMP ) // backup ram error
|
||||||
ROM_END
|
ROM_END
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user