mirror of
https://github.com/holub/mame
synced 2025-04-24 17:30:55 +03:00
added i/o opcodes
This commit is contained in:
parent
8908bdc264
commit
f148f7f609
@ -10,6 +10,19 @@
|
||||
|
||||
*/
|
||||
|
||||
enum
|
||||
{
|
||||
FAMILY_HMCS42 = 0,
|
||||
FAMILY_HMCS43,
|
||||
FAMILY_HMCS44,
|
||||
FAMILY_HMCS45,
|
||||
FAMILY_HMCS46,
|
||||
FAMILY_HMCS47,
|
||||
};
|
||||
|
||||
#define IS_CMOS true
|
||||
#define IS_PMOS false
|
||||
|
||||
#include "hmcs40.h"
|
||||
#include "debugger.h"
|
||||
|
||||
@ -75,16 +88,30 @@ ADDRESS_MAP_END
|
||||
|
||||
|
||||
// device definitions
|
||||
hmcs43_cpu_device::hmcs43_cpu_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, bool is_cmos, const char *shortname)
|
||||
: hmcs40_cpu_device(mconfig, type, name, tag, owner, clock, FAMILY_HMCS43, is_cmos, 3, 12, ADDRESS_MAP_NAME(program_1k), 7, ADDRESS_MAP_NAME(data_80x4), shortname, __FILE__)
|
||||
{ }
|
||||
|
||||
hd38750_device::hd38750_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
|
||||
: hmcs40_cpu_device(mconfig, HD38750, "HD38750", tag, owner, clock, 3, 12, ADDRESS_MAP_NAME(program_1k), 7, ADDRESS_MAP_NAME(data_80x4), "hd38750", __FILE__)
|
||||
: hmcs43_cpu_device(mconfig, HD38750, "HD38750", tag, owner, clock, IS_PMOS, "hd38750")
|
||||
{ }
|
||||
|
||||
|
||||
hmcs44_cpu_device::hmcs44_cpu_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, bool is_cmos, const char *shortname)
|
||||
: hmcs40_cpu_device(mconfig, type, name, tag, owner, clock, FAMILY_HMCS44, is_cmos, 4, 13, ADDRESS_MAP_NAME(program_2k), 8, ADDRESS_MAP_NAME(data_160x4), shortname, __FILE__)
|
||||
{ }
|
||||
|
||||
hd38800_device::hd38800_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
|
||||
: hmcs40_cpu_device(mconfig, HD38800, "HD38800", tag, owner, clock, 4, 13, ADDRESS_MAP_NAME(program_2k), 8, ADDRESS_MAP_NAME(data_160x4), "hd38800", __FILE__)
|
||||
: hmcs44_cpu_device(mconfig, HD38800, "HD38800", tag, owner, clock, IS_PMOS, "hd38800")
|
||||
{ }
|
||||
|
||||
|
||||
hmcs45_cpu_device::hmcs45_cpu_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, bool is_cmos, const char *shortname)
|
||||
: hmcs40_cpu_device(mconfig, type, name, tag, owner, clock, FAMILY_HMCS45, is_cmos, 4, 13, ADDRESS_MAP_NAME(program_2k), 8, ADDRESS_MAP_NAME(data_160x4), shortname, __FILE__)
|
||||
{ }
|
||||
|
||||
hd38820_device::hd38820_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
|
||||
: hmcs40_cpu_device(mconfig, HD38820, "HD38820", tag, owner, clock, 4, 13, ADDRESS_MAP_NAME(program_2k), 8, ADDRESS_MAP_NAME(data_160x4), "hd38820", __FILE__)
|
||||
: hmcs45_cpu_device(mconfig, HD38820, "HD38820", tag, owner, clock, IS_PMOS, "hd38820")
|
||||
{ }
|
||||
|
||||
|
||||
@ -101,7 +128,7 @@ void hmcs40_cpu_device::state_string_export(const device_state_entry &entry, ast
|
||||
break;
|
||||
|
||||
case STATE_GENPC:
|
||||
string.printf("%03X", m_pc << 1);
|
||||
string.printf("%04X", m_pc << 1);
|
||||
break;
|
||||
|
||||
default: break;
|
||||
@ -132,17 +159,35 @@ void hmcs40_cpu_device::device_start()
|
||||
m_data = &space(AS_DATA);
|
||||
m_prgmask = (1 << m_prgwidth) - 1;
|
||||
m_datamask = (1 << m_datawidth) - 1;
|
||||
m_xmask = (1 << (m_datawidth - 4)) - 1;
|
||||
|
||||
UINT8 defval = (m_is_cmos) ? 0xf : 0;
|
||||
m_read_r0.resolve_safe(defval);
|
||||
m_read_r1.resolve_safe(defval);
|
||||
m_read_r2.resolve_safe(defval);
|
||||
m_read_r3.resolve_safe(defval);
|
||||
m_read_r4.resolve_safe(defval);
|
||||
m_read_r5.resolve_safe(defval);
|
||||
m_read_r6.resolve_safe(defval);
|
||||
m_read_r7.resolve_safe(defval);
|
||||
|
||||
m_write_r0.resolve_safe();
|
||||
m_write_r1.resolve_safe();
|
||||
m_write_r2.resolve_safe();
|
||||
m_write_r3.resolve_safe();
|
||||
m_write_r4.resolve_safe();
|
||||
m_write_r5.resolve_safe();
|
||||
m_write_r6.resolve_safe();
|
||||
m_write_r7.resolve_safe();
|
||||
|
||||
m_read_d.resolve_safe(0);
|
||||
m_read_d.resolve_safe((m_is_cmos) ? 0xffff : 0);
|
||||
m_write_d.resolve_safe();
|
||||
|
||||
// zerofill
|
||||
memset(m_stack, 0, sizeof(m_stack));
|
||||
m_op = 0;
|
||||
m_prev_op = 0;
|
||||
m_arg = 0;
|
||||
m_pc = 0;
|
||||
m_prev_pc = 0;
|
||||
m_page = 0;
|
||||
m_a = 0;
|
||||
m_b = 0;
|
||||
@ -150,15 +195,17 @@ void hmcs40_cpu_device::device_start()
|
||||
m_spx = 0;
|
||||
m_y = 0;
|
||||
m_spy = 0;
|
||||
m_s = 0;
|
||||
m_s = 1;
|
||||
m_c = 0;
|
||||
memset(m_r, 0, sizeof(m_r));
|
||||
m_d = 0;
|
||||
|
||||
// register for savestates
|
||||
save_item(NAME(m_stack));
|
||||
save_item(NAME(m_op));
|
||||
save_item(NAME(m_prev_op));
|
||||
save_item(NAME(m_arg));
|
||||
save_item(NAME(m_pc));
|
||||
save_item(NAME(m_prev_pc));
|
||||
save_item(NAME(m_page));
|
||||
save_item(NAME(m_a));
|
||||
save_item(NAME(m_b));
|
||||
@ -168,6 +215,8 @@ void hmcs40_cpu_device::device_start()
|
||||
save_item(NAME(m_spy));
|
||||
save_item(NAME(m_s));
|
||||
save_item(NAME(m_c));
|
||||
save_item(NAME(m_r));
|
||||
save_item(NAME(m_d));
|
||||
|
||||
// register state for debugger
|
||||
state_add(HMCS40_PC, "PC", m_pc).formatstr("%04X");
|
||||
@ -178,7 +227,7 @@ void hmcs40_cpu_device::device_start()
|
||||
state_add(HMCS40_Y, "Y", m_y).formatstr("%01X");
|
||||
state_add(HMCS40_SPY, "SPY", m_spy).formatstr("%01X");
|
||||
|
||||
state_add(STATE_GENPC, "curpc", m_pc).formatstr("%03X").noshow();
|
||||
state_add(STATE_GENPC, "curpc", m_pc).formatstr("%04X").noshow();
|
||||
state_add(STATE_GENFLAGS, "GENFLAGS", m_s).formatstr("%2s").noshow();
|
||||
|
||||
m_icountptr = &m_icount;
|
||||
@ -192,8 +241,16 @@ void hmcs40_cpu_device::device_start()
|
||||
|
||||
void hmcs40_cpu_device::device_reset()
|
||||
{
|
||||
m_pc = 0xffff & m_prgmask;
|
||||
m_op = 0;
|
||||
m_pc = m_prgmask;
|
||||
m_prev_op = m_op = 0;
|
||||
|
||||
// clear i/o
|
||||
m_d = (m_is_cmos) ? 0xffff : 0;
|
||||
for (int i = 0; i < 16; i++)
|
||||
hmcs40_cpu_device::write_d(i, (m_is_cmos) ? 1 : 0);
|
||||
|
||||
for (int i = 0; i < 8; i++)
|
||||
hmcs40_cpu_device::write_r(i, (m_is_cmos) ? 0xf : 0);
|
||||
}
|
||||
|
||||
|
||||
@ -217,17 +274,6 @@ inline void hmcs40_cpu_device::increment_pc()
|
||||
m_pc = (m_pc & ~mask) | ((m_pc << 1 | fb) & mask);
|
||||
}
|
||||
|
||||
inline void hmcs40_cpu_device::fetch_arg()
|
||||
{
|
||||
// P is the only 2-byte opcode
|
||||
if ((m_op & 0x3f8) == 0x368)
|
||||
{
|
||||
m_icount--;
|
||||
m_arg = m_program->read_word(m_pc << 1);
|
||||
increment_pc();
|
||||
}
|
||||
}
|
||||
|
||||
void hmcs40_cpu_device::execute_run()
|
||||
{
|
||||
while (m_icount > 0)
|
||||
@ -238,13 +284,13 @@ void hmcs40_cpu_device::execute_run()
|
||||
if ((m_prev_op & 0x3e0) == 0x340)
|
||||
m_pc = ((m_page << 6) | (m_pc & 0x3f)) & m_prgmask;
|
||||
|
||||
// remember previous opcode
|
||||
// remember previous state
|
||||
m_prev_op = m_op;
|
||||
m_prev_pc = m_pc;
|
||||
|
||||
// fetch next opcode
|
||||
debugger_instruction_hook(this, m_pc << 1);
|
||||
m_op = m_program->read_word(m_pc << 1);
|
||||
increment_pc();
|
||||
fetch_arg();
|
||||
}
|
||||
}
|
||||
|
@ -13,6 +13,14 @@
|
||||
|
||||
|
||||
// I/O ports setup
|
||||
|
||||
// max 8 4-bit R ports
|
||||
#define MCFG_HMCS40_READ_R_CB(_r, _devcb) \
|
||||
hmcs40_cpu_device::set_read_r##_r_callback(*device, DEVCB_##_devcb);
|
||||
#define MCFG_HMCS40_WRITE_R_CB(_r, _devcb) \
|
||||
hmcs40_cpu_device::set_write_r##_r_callback(*device, DEVCB_##_devcb);
|
||||
|
||||
// 16-bit discrete
|
||||
#define MCFG_HMCS40_READ_A_CB(_devcb) \
|
||||
hmcs40_cpu_device::set_read_d_callback(*device, DEVCB_##_devcb);
|
||||
#define MCFG_HMCS40_WRITE_D_CB(_devcb) \
|
||||
@ -24,18 +32,40 @@ class hmcs40_cpu_device : public cpu_device
|
||||
{
|
||||
public:
|
||||
// construction/destruction
|
||||
hmcs40_cpu_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, int stack_levels, int prgwidth, address_map_constructor program, int datawidth, address_map_constructor data, const char *shortname, const char *source)
|
||||
hmcs40_cpu_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, int family, bool is_cmos, int stack_levels, int prgwidth, address_map_constructor program, int datawidth, address_map_constructor data, const char *shortname, const char *source)
|
||||
: cpu_device(mconfig, type, name, tag, owner, clock, shortname, source)
|
||||
, m_program_config("program", ENDIANNESS_LITTLE, 16, prgwidth, 0, program)
|
||||
, m_data_config("data", ENDIANNESS_LITTLE, 8, datawidth, 0, data)
|
||||
, m_prgwidth(prgwidth-1)
|
||||
, m_datawidth(datawidth)
|
||||
, m_family(family)
|
||||
, m_is_cmos(is_cmos)
|
||||
, m_stack_levels(stack_levels)
|
||||
, m_read_r0(*this), m_read_r1(*this), m_read_r2(*this), m_read_r3(*this), m_read_r4(*this), m_read_r5(*this), m_read_r6(*this), m_read_r7(*this)
|
||||
, m_write_r0(*this), m_write_r1(*this), m_write_r2(*this), m_write_r3(*this), m_write_r4(*this), m_write_r5(*this), m_write_r6(*this), m_write_r7(*this)
|
||||
, m_read_d(*this)
|
||||
, m_write_d(*this)
|
||||
{ }
|
||||
|
||||
// static configuration helpers
|
||||
template<class _Object> static devcb_base &set_read_r0_callback(device_t &device, _Object object) { return downcast<hmcs40_cpu_device &>(device).m_read_r0.set_callback(object); }
|
||||
template<class _Object> static devcb_base &set_read_r1_callback(device_t &device, _Object object) { return downcast<hmcs40_cpu_device &>(device).m_read_r1.set_callback(object); }
|
||||
template<class _Object> static devcb_base &set_read_r2_callback(device_t &device, _Object object) { return downcast<hmcs40_cpu_device &>(device).m_read_r2.set_callback(object); }
|
||||
template<class _Object> static devcb_base &set_read_r3_callback(device_t &device, _Object object) { return downcast<hmcs40_cpu_device &>(device).m_read_r3.set_callback(object); }
|
||||
template<class _Object> static devcb_base &set_read_r4_callback(device_t &device, _Object object) { return downcast<hmcs40_cpu_device &>(device).m_read_r4.set_callback(object); }
|
||||
template<class _Object> static devcb_base &set_read_r5_callback(device_t &device, _Object object) { return downcast<hmcs40_cpu_device &>(device).m_read_r5.set_callback(object); }
|
||||
template<class _Object> static devcb_base &set_read_r6_callback(device_t &device, _Object object) { return downcast<hmcs40_cpu_device &>(device).m_read_r6.set_callback(object); }
|
||||
template<class _Object> static devcb_base &set_read_r7_callback(device_t &device, _Object object) { return downcast<hmcs40_cpu_device &>(device).m_read_r7.set_callback(object); }
|
||||
|
||||
template<class _Object> static devcb_base &set_write_r0_callback(device_t &device, _Object object) { return downcast<hmcs40_cpu_device &>(device).m_write_r0.set_callback(object); }
|
||||
template<class _Object> static devcb_base &set_write_r1_callback(device_t &device, _Object object) { return downcast<hmcs40_cpu_device &>(device).m_write_r1.set_callback(object); }
|
||||
template<class _Object> static devcb_base &set_write_r2_callback(device_t &device, _Object object) { return downcast<hmcs40_cpu_device &>(device).m_write_r2.set_callback(object); }
|
||||
template<class _Object> static devcb_base &set_write_r3_callback(device_t &device, _Object object) { return downcast<hmcs40_cpu_device &>(device).m_write_r3.set_callback(object); }
|
||||
template<class _Object> static devcb_base &set_write_r4_callback(device_t &device, _Object object) { return downcast<hmcs40_cpu_device &>(device).m_write_r4.set_callback(object); }
|
||||
template<class _Object> static devcb_base &set_write_r5_callback(device_t &device, _Object object) { return downcast<hmcs40_cpu_device &>(device).m_write_r5.set_callback(object); }
|
||||
template<class _Object> static devcb_base &set_write_r6_callback(device_t &device, _Object object) { return downcast<hmcs40_cpu_device &>(device).m_write_r6.set_callback(object); }
|
||||
template<class _Object> static devcb_base &set_write_r7_callback(device_t &device, _Object object) { return downcast<hmcs40_cpu_device &>(device).m_write_r7.set_callback(object); }
|
||||
|
||||
template<class _Object> static devcb_base &set_read_d_callback(device_t &device, _Object object) { return downcast<hmcs40_cpu_device &>(device).m_read_d.set_callback(object); }
|
||||
template<class _Object> static devcb_base &set_write_d_callback(device_t &device, _Object object) { return downcast<hmcs40_cpu_device &>(device).m_write_d.set_callback(object); }
|
||||
|
||||
@ -54,7 +84,7 @@ protected:
|
||||
virtual const address_space_config *memory_space_config(address_spacenum spacenum = AS_0) const { return(spacenum == AS_PROGRAM) ? &m_program_config :((spacenum == AS_DATA) ? &m_data_config : NULL); }
|
||||
|
||||
// device_disasm_interface overrides
|
||||
virtual UINT32 disasm_min_opcode_bytes() const { return 1; }
|
||||
virtual UINT32 disasm_min_opcode_bytes() const { return 2; }
|
||||
virtual UINT32 disasm_max_opcode_bytes() const { return 2; }
|
||||
virtual offs_t disasm_disassemble(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram, UINT32 options);
|
||||
void state_string_export(const device_state_entry &entry, astring &string);
|
||||
@ -68,15 +98,16 @@ protected:
|
||||
int m_datawidth;
|
||||
int m_prgmask;
|
||||
int m_datamask;
|
||||
int m_xmask;
|
||||
int m_family; // MCU family (42-47)
|
||||
bool m_is_cmos;
|
||||
int m_stack_levels; // number of callstack levels
|
||||
UINT16 m_stack[4]; // max 4
|
||||
UINT16 m_op;
|
||||
UINT16 m_op; // current opcode
|
||||
UINT16 m_prev_op;
|
||||
UINT16 m_arg;
|
||||
int m_icount;
|
||||
|
||||
UINT16 m_pc; // Program Counter
|
||||
UINT16 m_prev_pc;
|
||||
UINT8 m_page; // LPU prepared page
|
||||
UINT8 m_a; // 4-bit Accumulator
|
||||
UINT8 m_b; // 4-bit B register
|
||||
@ -86,20 +117,28 @@ protected:
|
||||
UINT8 m_spy; // 4-bit SPY register
|
||||
UINT8 m_s; // Status F/F
|
||||
UINT8 m_c; // Carry F/F
|
||||
UINT8 m_r[8]; // R outputs state
|
||||
UINT16 m_d; // D pins state
|
||||
|
||||
// i/o handlers
|
||||
devcb_read8 m_read_r0, m_read_r1, m_read_r2, m_read_r3, m_read_r4, m_read_r5, m_read_r6, m_read_r7;
|
||||
devcb_write8 m_write_r0, m_write_r1, m_write_r2, m_write_r3, m_write_r4, m_write_r5, m_write_r6, m_write_r7;
|
||||
devcb_read16 m_read_d;
|
||||
devcb_write16 m_write_d;
|
||||
|
||||
// misc internal helpers
|
||||
void increment_pc();
|
||||
void fetch_arg();
|
||||
|
||||
|
||||
UINT8 ram_r();
|
||||
void ram_w(UINT8 data);
|
||||
void pop_stack();
|
||||
void push_stack();
|
||||
|
||||
virtual UINT8 read_r(int index);
|
||||
virtual void write_r(int index, UINT8 data);
|
||||
virtual int read_d(int index);
|
||||
virtual void write_d(int index, int state);
|
||||
|
||||
// opcode handlers
|
||||
void op_lab();
|
||||
void op_lba();
|
||||
@ -202,21 +241,55 @@ protected:
|
||||
};
|
||||
|
||||
|
||||
class hd38750_device : public hmcs40_cpu_device
|
||||
class hmcs43_cpu_device : public hmcs40_cpu_device
|
||||
{
|
||||
public:
|
||||
hmcs43_cpu_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, bool is_cmos, const char *shortname);
|
||||
|
||||
protected:
|
||||
// overrides
|
||||
virtual UINT8 read_r(int index);
|
||||
virtual void write_r(int index, UINT8 data);
|
||||
virtual int read_d(int index);
|
||||
};
|
||||
|
||||
class hd38750_device : public hmcs43_cpu_device
|
||||
{
|
||||
public:
|
||||
hd38750_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
|
||||
};
|
||||
|
||||
|
||||
class hd38800_device : public hmcs40_cpu_device
|
||||
class hmcs44_cpu_device : public hmcs40_cpu_device
|
||||
{
|
||||
public:
|
||||
hmcs44_cpu_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, bool is_cmos, const char *shortname);
|
||||
|
||||
protected:
|
||||
// overrides
|
||||
virtual UINT8 read_r(int index);
|
||||
virtual void write_r(int index, UINT8 data);
|
||||
};
|
||||
|
||||
class hd38800_device : public hmcs44_cpu_device
|
||||
{
|
||||
public:
|
||||
hd38800_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
|
||||
};
|
||||
|
||||
|
||||
class hd38820_device : public hmcs40_cpu_device
|
||||
class hmcs45_cpu_device : public hmcs40_cpu_device
|
||||
{
|
||||
public:
|
||||
hmcs45_cpu_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, bool is_cmos, const char *shortname);
|
||||
|
||||
protected:
|
||||
// overrides
|
||||
virtual UINT8 read_r(int index);
|
||||
virtual void write_r(int index, UINT8 data);
|
||||
};
|
||||
|
||||
class hd38820_device : public hmcs45_cpu_device
|
||||
{
|
||||
public:
|
||||
hd38820_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
|
||||
|
@ -28,11 +28,144 @@ void hmcs40_cpu_device::push_stack()
|
||||
m_stack[0] = m_pc;
|
||||
}
|
||||
|
||||
void hmcs40_cpu_device::op_illegal()
|
||||
|
||||
// i/o
|
||||
|
||||
UINT8 hmcs40_cpu_device::read_r(int index)
|
||||
{
|
||||
logerror("%s unknown opcode $%03X at $%04X\n", tag(), m_op, m_pc);
|
||||
index &= 7;
|
||||
UINT8 inp = 0xf;
|
||||
|
||||
switch (index)
|
||||
{
|
||||
case 0: inp = m_read_r0(index, 0xff); break;
|
||||
case 1: inp = m_read_r1(index, 0xff); break;
|
||||
case 2: inp = m_read_r2(index, 0xff); break;
|
||||
case 3: inp = m_read_r3(index, 0xff); break;
|
||||
case 4: inp = m_read_r4(index, 0xff); break;
|
||||
case 5: inp = m_read_r5(index, 0xff); break;
|
||||
case 6: inp = m_read_r6(index, 0xff); break;
|
||||
case 7: inp = m_read_r7(index, 0xff); break;
|
||||
}
|
||||
|
||||
if (m_is_cmos)
|
||||
return inp & m_r[index];
|
||||
else
|
||||
return inp | m_r[index];
|
||||
}
|
||||
|
||||
void hmcs40_cpu_device::write_r(int index, UINT8 data)
|
||||
{
|
||||
index &= 7;
|
||||
m_r[index] = data & 0xf;
|
||||
|
||||
switch (index)
|
||||
{
|
||||
case 0: m_write_r0(index, m_r[index], 0xff); break;
|
||||
case 1: m_write_r1(index, m_r[index], 0xff); break;
|
||||
case 2: m_write_r2(index, m_r[index], 0xff); break;
|
||||
case 3: m_write_r3(index, m_r[index], 0xff); break;
|
||||
case 4: m_write_r4(index, m_r[index], 0xff); break;
|
||||
case 5: m_write_r5(index, m_r[index], 0xff); break;
|
||||
case 6: m_write_r6(index, m_r[index], 0xff); break;
|
||||
case 7: m_write_r7(index, m_r[index], 0xff); break;
|
||||
}
|
||||
}
|
||||
|
||||
int hmcs40_cpu_device::read_d(int index)
|
||||
{
|
||||
index &= 15;
|
||||
|
||||
if (m_is_cmos)
|
||||
return (m_read_d(index, 0xffff) & m_d) >> index & 1;
|
||||
else
|
||||
return (m_read_d(index, 0xffff) | m_d) >> index & 1;
|
||||
}
|
||||
|
||||
void hmcs40_cpu_device::write_d(int index, int state)
|
||||
{
|
||||
index &= 15;
|
||||
|
||||
m_d = (m_d & ~(1 << index)) | (state << index);
|
||||
m_write_d(index, m_d, 0xffff);
|
||||
}
|
||||
|
||||
// HMCS43:
|
||||
// R0 is input-only, R1 is i/o, R2,R3 are output-only, no R4-R7
|
||||
// D0-D3 are i/o, D4-D15 are output-only
|
||||
|
||||
UINT8 hmcs43_cpu_device::read_r(int index)
|
||||
{
|
||||
if ((index & 7) >= 4)
|
||||
logerror("%s read from unknown port R%d at $%04X\n", tag(), index & 7, m_prev_pc << 1);
|
||||
|
||||
return hmcs40_cpu_device::read_r(index);
|
||||
}
|
||||
|
||||
void hmcs43_cpu_device::write_r(int index, UINT8 data)
|
||||
{
|
||||
index &= 7;
|
||||
|
||||
if (index != 0 && index < 4)
|
||||
hmcs40_cpu_device::write_r(index, data);
|
||||
else
|
||||
logerror("%s ineffective write to port R%d = $%X at $%04X\n", tag(), index, data & 0xf, m_prev_pc << 1);
|
||||
}
|
||||
|
||||
int hmcs43_cpu_device::read_d(int index)
|
||||
{
|
||||
if ((index & 15) >= 4)
|
||||
return m_d >> index & 1;
|
||||
else
|
||||
return hmcs40_cpu_device::read_d(index);
|
||||
}
|
||||
|
||||
// HMCS44:
|
||||
// R0-R3 are i/o, R4,R5 are extra registers, no R6,R7
|
||||
// D0-D15 are i/o
|
||||
|
||||
UINT8 hmcs44_cpu_device::read_r(int index)
|
||||
{
|
||||
if ((index & 7) >= 6)
|
||||
logerror("%s read from unknown port R%d at $%04X\n", tag(), index & 7, m_prev_pc << 1);
|
||||
|
||||
return hmcs40_cpu_device::read_r(index);
|
||||
}
|
||||
|
||||
void hmcs44_cpu_device::write_r(int index, UINT8 data)
|
||||
{
|
||||
index &= 7;
|
||||
|
||||
if (index < 6)
|
||||
hmcs40_cpu_device::write_r(index, data);
|
||||
else
|
||||
logerror("%s ineffective write to port R%d = $%X at $%04X\n", tag(), index, data & 0xf, m_prev_pc << 1);
|
||||
}
|
||||
|
||||
// HMCS45:
|
||||
// R0-R5 are i/o, R6 is output-only, no R7
|
||||
// D0-D15 are i/o
|
||||
|
||||
UINT8 hmcs45_cpu_device::read_r(int index)
|
||||
{
|
||||
if ((index & 7) == 7)
|
||||
logerror("%s read from unknown port R%d at $%04X\n", tag(), index & 7, m_prev_pc << 1);
|
||||
|
||||
return hmcs40_cpu_device::read_r(index);
|
||||
}
|
||||
|
||||
void hmcs45_cpu_device::write_r(int index, UINT8 data)
|
||||
{
|
||||
index &= 7;
|
||||
|
||||
if (index != 7)
|
||||
hmcs40_cpu_device::write_r(index, data);
|
||||
else
|
||||
logerror("%s ineffective write to port R%d = $%X at $%04X\n", tag(), index, data & 0xf, m_prev_pc << 1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// instruction set
|
||||
@ -461,7 +594,7 @@ void hmcs40_cpu_device::op_lpu()
|
||||
void hmcs40_cpu_device::op_tbr()
|
||||
{
|
||||
// TBR p: Table Branch
|
||||
m_pc = (m_a | m_b << 4 | m_c << 8 | ((m_op & 7) << 9)) & m_prgmask;
|
||||
m_pc = (m_a | m_b << 4 | m_c << 8 | (m_op & 7) << 9) & m_prgmask;
|
||||
}
|
||||
|
||||
void hmcs40_cpu_device::op_rtn()
|
||||
@ -593,61 +726,75 @@ void hmcs40_cpu_device::op_rtni()
|
||||
void hmcs40_cpu_device::op_sed()
|
||||
{
|
||||
// SED: Set Discrete I/O Latch
|
||||
op_illegal();
|
||||
write_d(m_y, 1);
|
||||
}
|
||||
|
||||
void hmcs40_cpu_device::op_red()
|
||||
{
|
||||
// RED: Reset Discrete I/O Latch
|
||||
op_illegal();
|
||||
write_d(m_y, 0);
|
||||
}
|
||||
|
||||
void hmcs40_cpu_device::op_td()
|
||||
{
|
||||
// TD: Test Discrete I/O Latch
|
||||
op_illegal();
|
||||
m_s = read_d(m_y);
|
||||
}
|
||||
|
||||
void hmcs40_cpu_device::op_sedd()
|
||||
{
|
||||
// SEDD n: Set Discrete I/O Latch Direct
|
||||
op_illegal();
|
||||
write_d(m_op & 0xf, 1);
|
||||
}
|
||||
|
||||
void hmcs40_cpu_device::op_redd()
|
||||
{
|
||||
// REDD n: Reset Discrete I/O Latch Direct
|
||||
op_illegal();
|
||||
write_d(m_op & 0xf, 0);
|
||||
}
|
||||
|
||||
void hmcs40_cpu_device::op_lar()
|
||||
{
|
||||
// LAR p: Load A from R-Port Register
|
||||
op_illegal();
|
||||
m_a = read_r(m_op & 7);
|
||||
}
|
||||
|
||||
void hmcs40_cpu_device::op_lbr()
|
||||
{
|
||||
// LBR p: Load B from R-Port Register
|
||||
op_illegal();
|
||||
m_b = read_r(m_op & 7);
|
||||
}
|
||||
|
||||
void hmcs40_cpu_device::op_lra()
|
||||
{
|
||||
// LRA p: Load R-Port Register from A
|
||||
op_illegal();
|
||||
write_r(m_op & 7, m_a);
|
||||
}
|
||||
|
||||
void hmcs40_cpu_device::op_lrb()
|
||||
{
|
||||
// LRB p: Load R-Port Register from B
|
||||
op_illegal();
|
||||
write_r(m_op & 7, m_b);
|
||||
}
|
||||
|
||||
void hmcs40_cpu_device::op_p()
|
||||
{
|
||||
// P p: Pattern Generation
|
||||
op_illegal();
|
||||
m_icount--;
|
||||
UINT16 address = (m_a | m_b << 4 | m_c << 8 | (m_op & 7) << 9) | (m_pc & ~0x3f);
|
||||
UINT16 o = m_program->read_word(address << 1);
|
||||
|
||||
// destination is determined by the 2 highest bits
|
||||
if (o & 0x100)
|
||||
{
|
||||
m_a = o & 0xf;
|
||||
m_b = o >> 4 & 0xf;
|
||||
}
|
||||
if (o & 0x200)
|
||||
{
|
||||
write_r(2, o >> 4 & 0xf);
|
||||
write_r(3, o & 0xf);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -657,3 +804,9 @@ void hmcs40_cpu_device::op_nop()
|
||||
{
|
||||
// NOP: No Operation
|
||||
}
|
||||
|
||||
|
||||
void hmcs40_cpu_device::op_illegal()
|
||||
{
|
||||
logerror("%s unknown opcode $%03X at $%04X\n", tag(), m_op, m_prev_pc << 1);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user