summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/cpu/rii/riscii.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/cpu/rii/riscii.cpp')
-rw-r--r--src/devices/cpu/rii/riscii.cpp1039
1 files changed, 1018 insertions, 21 deletions
diff --git a/src/devices/cpu/rii/riscii.cpp b/src/devices/cpu/rii/riscii.cpp
index ea1b95594ab..96a5cd99430 100644
--- a/src/devices/cpu/rii/riscii.cpp
+++ b/src/devices/cpu/rii/riscii.cpp
@@ -10,7 +10,8 @@
first generation of PIC-like microcontrollers, the EM78 series, has
13-bit opcodes.)
- Currently this device is just a stub with no actual execution core.
+ Currently the execution core is mostly complete, though interrupts and
+ on-chip peripherals are completely unemulated.
***************************************************************************/
@@ -21,10 +22,37 @@
// device type definitions
DEFINE_DEVICE_TYPE(RISCII, riscii_series_device, "riscii", "Elan RISC II")
+ALLOW_SAVE_TYPE(riscii_series_device::exec_state);
+
+
+//**************************************************************************
+// DEVICE CONSTRUCTION AND INITIALIZATION
+//**************************************************************************
void riscii_series_device::regs_map(address_map &map)
{
- map(0x0000, 0x007f).mirror(m_bankmask << 8).ram(); // TODO: special function registers
+ // 0x00 (INDF0) is not physically implemented
+ map(0x0001, 0x0001).rw(FUNC(riscii_series_device::fsr0_r), FUNC(riscii_series_device::fsr0_w));
+ map(0x0002, 0x0002).rw(FUNC(riscii_series_device::pcl_r), FUNC(riscii_series_device::pcl_w));
+ map(0x0003, 0x0003).rw(FUNC(riscii_series_device::pcm_r), FUNC(riscii_series_device::pcm_w));
+ map(0x0004, 0x0004).rw(FUNC(riscii_series_device::pch_r), FUNC(riscii_series_device::pch_w));
+ map(0x0005, 0x0005).rw(FUNC(riscii_series_device::bsr_r), FUNC(riscii_series_device::bsr_w));
+ map(0x0006, 0x0006).rw(FUNC(riscii_series_device::stkptr_r), FUNC(riscii_series_device::stkptr_w));
+ map(0x0007, 0x0007).rw(FUNC(riscii_series_device::bsr1_r), FUNC(riscii_series_device::bsr1_w));
+ // 0x08 (INDF1) is not physically implemented
+ map(0x0009, 0x0009).rw(FUNC(riscii_series_device::fsr1_r), FUNC(riscii_series_device::fsr1_w));
+ map(0x000a, 0x000a).rw(FUNC(riscii_series_device::acc_r), FUNC(riscii_series_device::acc_w));
+ map(0x000b, 0x000b).rw(FUNC(riscii_series_device::tabptrl_r), FUNC(riscii_series_device::tabptrl_w));
+ map(0x000c, 0x000c).rw(FUNC(riscii_series_device::tabptrm_r), FUNC(riscii_series_device::tabptrm_w));
+ map(0x000d, 0x000d).rw(FUNC(riscii_series_device::tabptrh_r), FUNC(riscii_series_device::tabptrh_w));
+ map(0x000e, 0x000e).rw(FUNC(riscii_series_device::cpucon_r), FUNC(riscii_series_device::cpucon_w));
+ map(0x000f, 0x000f).rw(FUNC(riscii_series_device::status_r), FUNC(riscii_series_device::status_w));
+ map(0x0010, 0x0010).ram(); // TODO: TRL2
+ map(0x0011, 0x0011).rw(FUNC(riscii_series_device::prodl_r), FUNC(riscii_series_device::prodl_w));
+ map(0x0012, 0x0012).rw(FUNC(riscii_series_device::prodh_r), FUNC(riscii_series_device::prodh_w));
+ map(0x0013, 0x0029).ram(); // TODO: other special function registers
+ map(0x002b, 0x002b).rw(FUNC(riscii_series_device::post_id_r), FUNC(riscii_series_device::post_id_w));
+ map(0x002c, 0x007f).ram(); // TODO: other special function registers
for (unsigned b = 0; b <= m_maxbank; b++)
map(0x0080 | (b << 8), 0x00ff | (b << 8)).ram();
}
@@ -40,21 +68,25 @@ riscii_series_device::riscii_series_device(const machine_config &mconfig, device
, m_regs_config("register", ENDIANNESS_LITTLE, 8, 8 + bankbits, 0, address_map_constructor(FUNC(riscii_series_device::regs_map), this))
, m_program(nullptr)
, m_regs(nullptr)
+ , m_cache(nullptr)
, m_prgbits(prgbits)
, m_bankmask((1 << bankbits) - 1)
, m_maxbank(maxbank)
, m_pc(0)
, m_acc(0)
- , m_fsr0(0)
- , m_bsr(0)
+ , m_fsr{0, 0}
+ , m_bsr{0, 0}
, m_tabptr(0)
, m_stkptr(0)
, m_cpucon(0)
, m_status(0)
+ , m_prod(0)
+ , m_post_id(0)
, m_icount(0)
+ , m_exec_state(EXEC_CYCLE1)
+ , m_repeat(0)
+ , m_curreg(0)
{
- m_fsr1.w = 0;
- m_prod.w = 0;
}
riscii_series_device::riscii_series_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
@@ -74,51 +106,1016 @@ void riscii_series_device::device_start()
{
m_program = &space(AS_PROGRAM);
m_regs = &space(AS_DATA);
+ m_cache = m_program->cache<1, -1, ENDIANNESS_LITTLE>();
set_icountptr(m_icount);
state_add(RII_PC, "PC", m_pc).mask((1 << m_prgbits) - 1);
state_add(STATE_GENPC, "GENPC", m_pc).callimport().noshow();
- state_add(STATE_GENPCBASE, "CURPC", m_pc).callimport().noshow();
+ state_add(STATE_GENPCBASE, "CURPC", m_ppc).callimport().noshow();
+ state_add(RII_REPEAT, "REPEAT", m_repeat);
state_add(RII_ACC, "ACC", m_acc);
- state_add(RII_BSR, "BSR", m_bsr).mask(m_bankmask);
- state_add(RII_FSR0, "FSR0", m_fsr0);
- state_add(RII_BSR1, "BSR1", m_fsr1.b.h).mask(m_bankmask);
- state_add(RII_FSR1, "FSR1", m_fsr1.b.l); // TODO: high bit forced to 1
+ state_add(RII_BSR, "BSR", m_bsr[0]).mask(m_bankmask);
+ state_add(RII_FSR0, "FSR0", m_fsr[0]);
+ state_add(RII_BSR1, "BSR1", m_bsr[1]).mask(m_bankmask);
+ state_add(RII_FSR1, "FSR1", m_fsr[1]); // TODO: high bit forced to 1
state_add(RII_TABPTR, "TABPTR", m_tabptr).mask(0x800000 + (1 << (m_prgbits + 1)) - 1);
state_add(RII_STKPTR, "STKPTR", m_stkptr);
state_add(RII_CPUCON, "CPUCON", m_cpucon).mask(0x9f);
state_add(RII_STATUS, "STATUS", m_status);
- state_add(RII_PROD, "PROD", m_prod.w);
+ state_add(RII_PROD, "PROD", m_prod);
+ state_add(RII_POST_ID, "POST_ID", m_post_id);
save_item(NAME(m_pc));
+ save_item(NAME(m_ppc));
save_item(NAME(m_acc));
- save_item(NAME(m_fsr0));
save_item(NAME(m_bsr));
- save_item(NAME(m_fsr1.w));
+ save_item(NAME(m_fsr));
save_item(NAME(m_tabptr));
save_item(NAME(m_stkptr));
save_item(NAME(m_cpucon));
save_item(NAME(m_status));
- save_item(NAME(m_prod.w));
+ save_item(NAME(m_prod));
+ save_item(NAME(m_post_id));
+ save_item(NAME(m_exec_state));
+ save_item(NAME(m_repeat));
+ save_item(NAME(m_curreg));
}
void riscii_series_device::device_reset()
{
- m_pc = 0x00000;
- m_fsr0 = 0x00;
- m_bsr = 0x00;
- m_fsr1.w = 0x0080;
+ m_pc = m_ppc = 0x00000;
+ m_fsr[0] = 0x00;
+ m_bsr[0] = 0x00;
+ m_fsr[1] = 0x80;
+ m_bsr[1] = 0x00;
m_tabptr = 0x000000;
m_stkptr = 0x00;
m_cpucon &= 0x01;
+ m_post_id = 0xf0;
+ m_exec_state = EXEC_CYCLE1;
+ m_repeat = 0x00;
+}
+
+
+//**************************************************************************
+// REGISTER HANDLERS
+//**************************************************************************
+
+u8 riscii_series_device::fsr0_r()
+{
+ return m_fsr[0];
+}
+
+void riscii_series_device::fsr0_w(u8 data)
+{
+ m_fsr[0] = data;
+}
+
+u8 riscii_series_device::bsr_r()
+{
+ return m_bsr[0];
+}
+
+void riscii_series_device::bsr_w(u8 data)
+{
+ m_bsr[0] = data & m_bankmask;
+}
+
+u8 riscii_series_device::fsr1_r()
+{
+ return m_fsr[1];
+}
+
+void riscii_series_device::fsr1_w(u8 data)
+{
+ m_fsr[1] = data | 0x80;
+}
+
+u8 riscii_series_device::bsr1_r()
+{
+ return m_bsr[1];
+}
+
+void riscii_series_device::bsr1_w(u8 data)
+{
+ m_bsr[1] = data & m_bankmask;
+}
+
+u8 riscii_series_device::pcl_r()
+{
+ return m_pc & 0x000ff;
+}
+
+void riscii_series_device::pcl_w(u8 data)
+{
+ m_pc = (m_pc & 0xfff00) | data;
+}
+
+u8 riscii_series_device::pcm_r()
+{
+ return (m_pc & 0x0ff00) >> 8;
+}
+
+void riscii_series_device::pcm_w(u8 data)
+{
+ m_pc = (m_pc & 0xf00ff) | u32(data) << 8;
+}
+
+u8 riscii_series_device::pch_r()
+{
+ return (m_pc & 0xf0000) >> 16;
+}
+
+void riscii_series_device::pch_w(u8 data)
+{
+ if (m_prgbits > 16)
+ m_pc = (m_pc & 0x0ffff) | u32(data & ((1 << (m_prgbits - 16)) - 1)) << 16;
+}
+
+u8 riscii_series_device::tabptrl_r()
+{
+ return m_tabptr & 0x0000ff;
+}
+
+void riscii_series_device::tabptrl_w(u8 data)
+{
+ m_tabptr = (m_tabptr & 0xffff00) | data;
+}
+
+u8 riscii_series_device::tabptrm_r()
+{
+ return (m_tabptr & 0x00ff00) >> 8;
+}
+
+void riscii_series_device::tabptrm_w(u8 data)
+{
+ m_tabptr = (m_tabptr & 0xff00ff) | u32(data) << 8;
+}
+
+u8 riscii_series_device::tabptrh_r()
+{
+ return (m_tabptr & 0xff0000) >> 16;
+}
+
+void riscii_series_device::tabptrh_w(u8 data)
+{
+ m_tabptr = (m_tabptr & 0x00ffff) | u32(data & (0x80 | ((1 << (m_prgbits - 16)) - 1))) << 16;
+}
+
+u8 riscii_series_device::acc_r()
+{
+ return m_acc;
+}
+
+void riscii_series_device::acc_w(u8 data)
+{
+ m_acc = data;
+}
+
+u8 riscii_series_device::stkptr_r()
+{
+ return m_stkptr;
+}
+
+void riscii_series_device::stkptr_w(u8 data)
+{
+ m_stkptr = data;
+}
+
+u8 riscii_series_device::cpucon_r()
+{
+ return m_cpucon;
+}
+
+void riscii_series_device::cpucon_w(u8 data)
+{
+ m_cpucon = data & 0x9f;
+}
+
+u8 riscii_series_device::status_r()
+{
+ return m_status;
+}
+
+void riscii_series_device::status_w(u8 data)
+{
+ m_status = data;
+}
+
+u8 riscii_series_device::prodl_r()
+{
+ return m_prod & 0x00ff;
+}
+
+void riscii_series_device::prodl_w(u8 data)
+{
+ m_prod = (m_prod & 0xff00) | data;
+}
+
+u8 riscii_series_device::prodh_r()
+{
+ return m_prod >> 8;
+}
+
+void riscii_series_device::prodh_w(u8 data)
+{
+ m_prod = (m_prod & 0x00ff) | u16(data) << 8;
+}
+
+u8 riscii_series_device::post_id_r()
+{
+ return m_post_id;
+}
+
+void riscii_series_device::post_id_w(u8 data)
+{
+ m_post_id = data;
+}
+
+
+//**************************************************************************
+// MEMORY HELPERS
+//**************************************************************************
+
+u16 riscii_series_device::get_banked_address(u8 reg)
+{
+ if (reg == 0x00)
+ {
+ // INDF0 address comes from BSR and FSR0
+ u16 bfsr0 = u16(m_bsr[0]) << 8 | m_fsr[0];
+ if (BIT(m_post_id, 0))
+ {
+ // Auto increment/decrement (no carry into BSR)
+ if (BIT(m_post_id, 4))
+ ++m_fsr[0];
+ else
+ --m_fsr[0];
+ }
+ return bfsr0;
+ }
+ else if (reg == 0x08)
+ {
+ // INDF1 address comes from BSR1 and FSR1
+ u16 bfsr1 = u16(m_bsr[1]) << 8 | m_fsr[1];
+ if (BIT(m_post_id, 1))
+ {
+ // Auto increment/decrement (carry into BSR1)
+ if (BIT(m_post_id, 5))
+ {
+ m_fsr[1] = (m_fsr[1] + 1) | 0x80;
+ if (m_fsr[1] == 0x80)
+ ++m_bsr[1];
+ }
+ else
+ {
+ m_fsr[1] = (m_fsr[1] - 1) | 0x80;
+ if (m_fsr[1] == 0xff)
+ --m_bsr[1];
+ }
+ }
+ return bfsr1;
+ }
+ else if (reg >= 0x80)
+ return u16(m_bsr[0]) << 8 | reg;
+ else
+ return reg;
+}
+
+
+//**************************************************************************
+// EXECUTION CORE
+//**************************************************************************
+
+void riscii_series_device::execute_move(u8 dstreg, u8 srcreg)
+{
+ u8 tmp = m_regs->read_byte(get_banked_address(srcreg));
+ m_regs->write_byte(get_banked_address(dstreg), tmp);
+}
+
+void riscii_series_device::execute_add(u8 reg, bool a, bool c)
+{
+ u16 addr = get_banked_address(reg);
+ s8 data = m_regs->read_byte(addr);
+ s16 tmp = s16(data) + s8(m_acc) + (c ? m_status & 0x01 : 0);
+ bool dc = (data & 0x0f) + (m_acc & 0x0f) + (c ? m_status & 0x01 : 0) >= 0x10;
+ if (a)
+ acc_w(tmp & 0xff);
+ else
+ m_regs->write_byte(addr, tmp & 0xff);
+ m_status = (m_status & 0xc0)
+ | (BIT(tmp, 8) ? 0x01 : 0x00)
+ | (dc ? 0x02 : 0x00)
+ | ((tmp & 0xff) == 0 ? 0x04 : 0x00)
+ | ((tmp < 0) != BIT(tmp, 7) ? 0x08 : 0x00)
+ | (tmp <= 0 ? 0x10 : 0x00)
+ | (tmp >= 0 ? 0x20 : 0x00);
+}
+
+void riscii_series_device::execute_sub(u8 reg, bool a, bool c)
+{
+ u16 addr = get_banked_address(reg);
+ s8 data = m_regs->read_byte(addr);
+ s16 tmp = s16(data) - s8(m_acc) - (c ? ~m_status & 0x01 : 0);
+ bool dc = (data & 0x0f) >= (m_acc & 0x0f) + (c ? ~m_status & 0x01 : 0);
+ if (a)
+ acc_w(tmp & 0xff);
+ else
+ m_regs->write_byte(addr, tmp & 0xff);
+ m_status = (m_status & 0xc0)
+ | (BIT(tmp, 8) ? 0x00 : 0x01) // borrow is inverted
+ | (dc ? 0x02 : 0x00)
+ | ((tmp & 0xff) == 0 ? 0x04 : 0x00)
+ | ((tmp < 0) != BIT(tmp, 7) ? 0x08 : 0x00)
+ | (tmp <= 0 ? 0x10 : 0x00)
+ | (tmp >= 0 ? 0x20 : 0x00);
+}
+
+void riscii_series_device::execute_add_imm(u8 data, bool c)
+{
+ s16 tmp = s16(s8(data)) + s8(m_acc) + (c ? m_status & 0x01 : 0);
+ bool dc = (data & 0x0f) + (m_acc & 0x0f) + (c ? m_status & 0x01 : 0) >= 0x10;
+ acc_w(tmp & 0xff);
+ m_status = (m_status & 0xc0)
+ | (BIT(tmp, 8) ? 0x01 : 0x00)
+ | (dc ? 0x02 : 0x00)
+ | ((tmp & 0xff) == 0 ? 0x04 : 0x00)
+ | ((tmp < 0) != BIT(tmp, 7) ? 0x08 : 0x00)
+ | (tmp <= 0 ? 0x10 : 0x00)
+ | (tmp >= 0 ? 0x20 : 0x00);
+}
+
+void riscii_series_device::execute_sub_imm(u8 data, bool c)
+{
+ s16 tmp = s16(s8(data)) - s8(m_acc) - (c ? ~m_status & 0x01 : 0);
+ bool dc = (data & 0x0f) + (m_acc & 0x0f) + (c ? ~m_status & 0x01 : 0) >= 0x10;
+ acc_w(tmp & 0xff);
+ m_status = (m_status & 0xc0)
+ | (BIT(tmp, 8) ? 0x00 : 0x01) // borrow is inverted
+ | (dc ? 0x02 : 0x00)
+ | ((tmp & 0xff) == 0 ? 0x04 : 0x00)
+ | ((tmp < 0) != BIT(tmp, 7) ? 0x08 : 0x00)
+ | (tmp <= 0 ? 0x10 : 0x00)
+ | (tmp >= 0 ? 0x20 : 0x00);
+}
+
+void riscii_series_device::execute_adddc(u8 reg, bool a)
+{
+ u16 addr = get_banked_address(reg);
+ u8 data = m_regs->read_byte(addr);
+ u16 tmp = u16(data) + m_acc + (m_status & 0x01);
+ bool dc = (data & 0x0f) + (m_acc & 0x0f) + (m_status & 0x01) >= 0x0a;
+ if (dc)
+ tmp += 0x06;
+ if ((tmp & 0x1ff) >= 0xa0)
+ tmp += 0x60;
+ if (a)
+ acc_w(tmp & 0xff);
+ else
+ m_regs->write_byte(addr, tmp & 0xff);
+ m_status = (m_status & 0xf8)
+ | (BIT(tmp, 8) ? 0x01 : 0x00)
+ | (dc ? 0x02 : 0x00)
+ | ((tmp & 0xff) == 0 ? 0x04 : 0x00);
+}
+
+void riscii_series_device::execute_subdb(u8 reg, bool a)
+{
+ u16 addr = get_banked_address(reg);
+ u8 data = m_regs->read_byte(addr);
+ u16 tmp = u16(data) - m_acc - (~m_status & 0x01);
+ bool dc = (data & 0x0f) + (~m_acc & 0x0f) + (m_status & 0x01) >= 0x0a;
+ if (dc)
+ tmp -= 0x06;
+ if ((tmp & 0x1ff) >= 0xa0)
+ tmp -= 0x60;
+ if (a)
+ acc_w(tmp & 0xff);
+ else
+ m_regs->write_byte(addr, tmp & 0xff);
+ m_status = (m_status & 0xf8)
+ | (BIT(tmp, 8) ? 0x00 : 0x01) // borrow is inverted
+ | (dc ? 0x02 : 0x00)
+ | ((tmp & 0xff) == 0 ? 0x04 : 0x00);
+}
+
+void riscii_series_device::execute_mul(u8 reg)
+{
+ m_prod = u16(m_acc) * m_regs->read_byte(get_banked_address(reg));
+}
+
+void riscii_series_device::execute_mul_imm(u8 data)
+{
+ m_prod = u16(m_acc) * data;
+}
+
+void riscii_series_device::execute_or(u8 reg, bool a)
+{
+ u16 addr = get_banked_address(reg);
+ u8 tmp = m_acc | m_regs->read_byte(addr);
+ if (a)
+ acc_w(tmp);
+ else
+ m_regs->write_byte(addr, tmp);
+ if (tmp == 0)
+ m_status |= 0x04;
+ else
+ m_status &= 0xfb;
+}
+
+void riscii_series_device::execute_and(u8 reg, bool a)
+{
+ u16 addr = get_banked_address(reg);
+ u8 tmp = m_acc & m_regs->read_byte(addr);
+ if (a)
+ acc_w(tmp);
+ else
+ m_regs->write_byte(addr, tmp);
+ if (tmp == 0)
+ m_status |= 0x04;
+ else
+ m_status &= 0xfb;
+}
+
+void riscii_series_device::execute_xor(u8 reg, bool a)
+{
+ u16 addr = get_banked_address(reg);
+ u8 tmp = m_acc ^ m_regs->read_byte(addr);
+ if (a)
+ acc_w(tmp);
+ else
+ m_regs->write_byte(addr, tmp);
+ if (tmp == 0)
+ m_status |= 0x04;
+ else
+ m_status &= 0xfb;
+}
+
+void riscii_series_device::execute_com(u8 reg, bool a)
+{
+ u16 addr = get_banked_address(reg);
+ u8 tmp = ~m_regs->read_byte(addr);
+ if (a)
+ acc_w(tmp);
+ else
+ m_regs->write_byte(addr, tmp);
+ if (tmp == 0)
+ m_status |= 0x04;
+ else
+ m_status &= 0xfb;
+}
+
+void riscii_series_device::execute_clr(u8 reg)
+{
+ m_regs->write_byte(get_banked_address(reg), 0);
+ m_status |= 0x04;
+}
+
+void riscii_series_device::execute_rrc(u8 reg, bool a)
+{
+ u16 addr = get_banked_address(reg);
+ u16 tmp = m_regs->read_byte(addr) | u16(m_status & 0x01) << 8;
+ if (a)
+ acc_w(tmp >> 1);
+ else
+ m_regs->write_byte(addr, tmp >> 1);
+ m_status = (m_status & 0xfe) | (tmp & 0x01);
+}
+
+void riscii_series_device::execute_rlc(u8 reg, bool a)
+{
+ u16 addr = get_banked_address(reg);
+ u16 tmp = u16(m_regs->read_byte(addr)) << 1 | (m_status & 0x01);
+ if (a)
+ acc_w(tmp & 0xff);
+ else
+ m_regs->write_byte(addr, tmp & 0xff);
+ m_status = (m_status & 0xfe) | (tmp >> 8);
+}
+
+void riscii_series_device::execute_shra(u8 reg)
+{
+ u8 tmp = m_regs->read_byte(get_banked_address(reg));
+ acc_w((tmp >> 1) | (m_status & 0x01) << 7);
+}
+
+void riscii_series_device::execute_shla(u8 reg)
+{
+ u8 tmp = m_regs->read_byte(get_banked_address(reg));
+ acc_w((tmp << 1) | (m_status & 0x01));
+}
+
+void riscii_series_device::execute_jump(u32 addr)
+{
+ m_pc = addr;
+}
+
+void riscii_series_device::execute_call(u32 addr)
+{
+ m_stkptr -= 2;
+ m_regs->write_word((BIT(m_stkptr, 7) ? m_maxbank : m_maxbank - 1) << 8 | 0x80 | (m_stkptr & 0x7e), m_pc & 0xffff);
+ execute_jump(addr);
+}
+
+void riscii_series_device::execute_jcc(bool condition)
+{
+ if (condition)
+ m_exec_state = static_cast<exec_state>(EXEC_L0JMP + (m_pc >> 16));
+ else
+ m_exec_state = EXEC_NOJMP;
+}
+
+void riscii_series_device::execute_jdnz(u8 reg, bool a)
+{
+ u16 addr = get_banked_address(reg);
+ u8 tmp = m_regs->read_byte(addr) - 1;
+ if (a)
+ acc_w(tmp);
+ else
+ m_regs->write_byte(addr, tmp);
+ execute_jcc(tmp != 0);
+}
+
+void riscii_series_device::execute_jinz(u8 reg, bool a)
+{
+ u16 addr = get_banked_address(reg);
+ u8 tmp = m_regs->read_byte(addr) + 1;
+ if (a)
+ acc_w(tmp);
+ else
+ m_regs->write_byte(addr, tmp);
+ execute_jcc(tmp != 0);
+}
+
+void riscii_series_device::set_z_acc(u8 tmp)
+{
+ acc_w(tmp);
+ if (tmp == 0)
+ m_status |= 0x04;
+ else
+ m_status &= 0xfb;
+}
+
+void riscii_series_device::execute_load(u8 reg)
+{
+ set_z_acc(m_regs->read_byte(get_banked_address(reg)));
+}
+
+void riscii_series_device::execute_store(u8 reg)
+{
+ m_regs->write_byte(get_banked_address(reg), m_acc);
+}
+
+void riscii_series_device::execute_test(u8 reg)
+{
+ u8 tmp = m_regs->read_byte(get_banked_address(reg));
+ if (tmp == 0)
+ m_status |= 0x04;
+ else
+ m_status &= 0xfb;
+}
+
+void riscii_series_device::execute_swap(u8 reg, bool a)
+{
+ u16 addr = get_banked_address(reg);
+ u8 tmp = m_regs->read_byte(addr);
+ if (a)
+ acc_w((tmp >> 4) | (tmp << 4));
+ else
+ m_regs->write_byte(addr, (tmp >> 4) | (tmp << 4));
+}
+
+void riscii_series_device::execute_jbc(u8 reg, int b)
+{
+ execute_jcc(!BIT(m_regs->read_byte(get_banked_address(reg)), b));
+}
+
+void riscii_series_device::execute_jbs(u8 reg, int b)
+{
+ execute_jcc(BIT(m_regs->read_byte(get_banked_address(reg)), b));
+}
+
+void riscii_series_device::execute_bc(u8 reg, int b)
+{
+ u16 addr = get_banked_address(reg);
+ u8 tmp = m_regs->read_byte(addr) & ~(1 << b);
+ m_regs->write_byte(addr, tmp);
+}
+
+void riscii_series_device::execute_bs(u8 reg, int b)
+{
+ u16 addr = get_banked_address(reg);
+ u8 tmp = m_regs->read_byte(addr) | (1 << b);
+ m_regs->write_byte(addr, tmp);
+}
+
+void riscii_series_device::execute_btg(u8 reg, int b)
+{
+ u16 addr = get_banked_address(reg);
+ u8 tmp = m_regs->read_byte(addr) ^ (1 << b);
+ m_regs->write_byte(addr, tmp);
+}
+
+void riscii_series_device::execute_inc(u8 reg, bool a)
+{
+ u16 addr = get_banked_address(reg);
+ u16 tmp = u16(m_regs->read_byte(addr)) + 1;
+ if (a)
+ acc_w(tmp & 0xff);
+ else
+ m_regs->write_byte(addr, tmp & 0xff);
+ m_status = (m_status & 0xfa) | ((tmp & 0xff) == 0 ? 0x04 : 0x00) | (tmp >> 8);
+}
+
+void riscii_series_device::execute_dec(u8 reg, bool a)
+{
+ u16 addr = get_banked_address(reg);
+ u16 tmp = (u16(m_regs->read_byte(addr)) - 1) & 0x1ff;
+ if (a)
+ acc_w(tmp & 0xff);
+ else
+ m_regs->write_byte(addr, tmp & 0xff);
+ m_status = (m_status & 0xfa) | ((tmp & 0xff) == 0 ? 0x04 : 0x00) | (tmp >> 8);
+}
+
+void riscii_series_device::execute_rpt(u8 reg)
+{
+ m_repeat = m_regs->read_byte(get_banked_address(reg)) - 1;
+}
+
+void riscii_series_device::execute_ret(bool inte)
+{
+ execute_jump((m_pc & 0xf0000) | m_regs->read_word((BIT(m_stkptr, 7) ? m_maxbank : m_maxbank - 1) << 8 | 0x80 | (m_stkptr & 0x7e)));
+ m_stkptr += 2;
+ if (inte)
+ m_cpucon |= 0x08;
+}
+
+void riscii_series_device::execute_wdtc()
+{
+ logerror("WDTC (PC = %05X)\n", m_ppc);
+}
+
+void riscii_series_device::execute_slep()
+{
+ logerror("SLEP (PC = %05X)\n", m_ppc);
+}
+
+void riscii_series_device::execute_undef(u16 opcode)
+{
+ logerror("Undefined opcode %04Xh encountered (PC = %05X)\n", opcode, m_ppc);
+}
+
+void riscii_series_device::execute_cycle1(u16 opcode)
+{
+ if (BIT(opcode, 15))
+ {
+ if (BIT(opcode, 14))
+ {
+ if (BIT(opcode, 13))
+ execute_call((m_pc & 0x3e000) | (opcode & 0x1fff));
+ else
+ execute_jump((m_pc & 0x3e000) | (opcode & 0x1fff));
+ }
+ else
+ {
+ if (BIT(opcode, 13))
+ execute_move(opcode & 0x00ff, (opcode & 0x1f00) >> 8);
+ else
+ execute_move((opcode & 0x1f00) >> 8, opcode & 0x00ff);
+ }
+ }
+ else switch (opcode & 0xff00)
+ {
+ case 0x0000:
+ if (opcode == 0x0001)
+ execute_wdtc();
+ else if (opcode == 0x0002)
+ execute_slep();
+ else if ((opcode & 0x00e0) == 0x0020)
+ m_exec_state = static_cast<exec_state>((BIT(opcode, 4) ? EXEC_L0CALL : EXEC_L0JMP) + (opcode & 0x000f));
+ else if (opcode != 0x0000) // NOP
+ execute_undef(opcode);
+ break;
+
+ case 0x0200: case 0x0300:
+ execute_or(opcode & 0x00ff, !BIT(opcode, 8));
+ break;
+
+ case 0x0400: case 0x0500:
+ execute_and(opcode & 0x00ff, !BIT(opcode, 8));
+ break;
+
+ case 0x0600: case 0x0700:
+ execute_xor(opcode & 0x00ff, !BIT(opcode, 8));
+ break;
+
+ case 0x0800: case 0x0900:
+ execute_com(opcode & 0x00ff, !BIT(opcode, 8));
+ break;
+
+ case 0x0a00: case 0x0b00:
+ execute_rrc(opcode & 0x00ff, !BIT(opcode, 8));
+ break;
+
+ case 0x0c00: case 0x0d00:
+ execute_rlc(opcode & 0x00ff, !BIT(opcode, 8));
+ break;
+
+ case 0x0e00: case 0x0f00:
+ execute_swap(opcode & 0x00ff, !BIT(opcode, 8));
+ break;
+
+ case 0x1000: case 0x1100:
+ execute_add(opcode & 0x00ff, !BIT(opcode, 8), false);
+ break;
+
+ case 0x1200: case 0x1300:
+ execute_add(opcode & 0x00ff, !BIT(opcode, 8), true);
+ break;
+
+ case 0x1400: case 0x1500:
+ execute_adddc(opcode & 0x00ff, !BIT(opcode, 8));
+ break;
+
+ case 0x1600: case 0x1700:
+ execute_sub(opcode & 0x00ff, !BIT(opcode, 8), false);
+ break;
+
+ case 0x1800: case 0x1900:
+ execute_sub(opcode & 0x00ff, !BIT(opcode, 8), true);
+ break;
+
+ case 0x1a00: case 0x1b00:
+ execute_subdb(opcode & 0x00ff, !BIT(opcode, 8));
+ break;
+
+ case 0x1c00: case 0x1d00:
+ execute_inc(opcode & 0x00ff, !BIT(opcode, 8));
+ break;
+
+ case 0x1e00: case 0x1f00:
+ execute_dec(opcode & 0x00ff, !BIT(opcode, 8));
+ break;
+
+ case 0x2000:
+ execute_load(opcode & 0x00ff);
+ break;
+
+ case 0x2100:
+ execute_store(opcode & 0x00ff);
+ break;
+
+ case 0x2200:
+ execute_shra(opcode & 0x00ff);
+ break;
+
+ case 0x2300:
+ execute_shla(opcode & 0x00ff);
+ break;
+
+ case 0x2400:
+ execute_clr(opcode & 0x00ff);
+ break;
+
+ case 0x2500:
+ execute_test(opcode & 0x00ff);
+ break;
+
+ case 0x2600:
+ execute_mul(opcode & 0x00ff);
+ break;
+
+ case 0x2700:
+ execute_rpt(opcode & 0x00ff);
+ break;
+
+ case 0x2b00:
+ if ((opcode & 0x00fe) == 0x00fe)
+ execute_ret(BIT(opcode, 0));
+ else
+ execute_undef(opcode);
+ break;
+
+ case 0x2c00:
+ m_curreg = opcode & 0x00ff;
+ m_exec_state = EXEC_TBRD0;
+ break;
+
+ case 0x2d00:
+ m_curreg = opcode & 0x00ff;
+ m_exec_state = EXEC_TBRD1;
+ break;
+
+ case 0x2e00:
+ m_curreg = opcode & 0x00ff;
+ m_exec_state = EXEC_TBRD2;
+ break;
+
+ case 0x2f00:
+ m_curreg = opcode & 0x00ff;
+ m_exec_state = EXEC_TBRDA;
+ break;
+
+ case 0x3000: case 0x3100: case 0x3200: case 0x3300:
+ case 0x3400: case 0x3500: case 0x3600: case 0x3700:
+ case 0x3800: case 0x3900: case 0x3a00: case 0x3b00:
+ case 0x3c00: case 0x3d00: case 0x3e00: case 0x3f00:
+ execute_call(opcode & 0x0fff);
+ break;
+
+ case 0x4000:
+ tabptrl_w(opcode & 0x00ff);
+ break;
+
+ case 0x4100:
+ tabptrm_w(opcode & 0x00ff);
+ break;
+
+ case 0x4200:
+ tabptrh_w(opcode & 0x00ff);
+ break;
+
+ case 0x4300:
+ bsr_w(opcode & 0x00ff);
+ break;
+
+ case 0x4400:
+ set_z_acc(m_acc | (opcode & 0x00ff));
+ break;
+
+ case 0x4500:
+ set_z_acc(m_acc & opcode & 0x00ff);
+ break;
+
+ case 0x4600:
+ set_z_acc(m_acc ^ (opcode & 0x00ff));
+ break;
+
+ case 0x4700:
+ execute_jcc(m_acc >= (opcode & 0x00ff));
+ break;
+
+ case 0x4800:
+ execute_jcc(m_acc <= (opcode & 0x00ff));
+ break;
+
+ case 0x4900:
+ execute_jcc(m_acc == (opcode & 0x00ff));
+ break;
+
+ case 0x4a00:
+ execute_add_imm(opcode & 0x00ff, false);
+ break;
+
+ case 0x4b00:
+ execute_add_imm(opcode & 0x00ff, true);
+ break;
+
+ case 0x4c00:
+ execute_sub_imm(opcode & 0x00ff, false);
+ break;
+
+ case 0x4d00:
+ execute_sub_imm(opcode & 0x00ff, true);
+ break;
+
+ case 0x4e00:
+ acc_w(opcode & 0x00ff);
+ break;
+
+ case 0x4f00:
+ execute_mul_imm(opcode & 0x00ff);
+ break;
+
+ case 0x5000:
+ execute_jdnz(opcode & 0x00ff, true);
+ break;
+
+ case 0x5100:
+ execute_jdnz(opcode & 0x00ff, false);
+ break;
+
+ case 0x5200:
+ execute_jinz(opcode & 0x00ff, true);
+ break;
+
+ case 0x5300:
+ execute_jinz(opcode & 0x00ff, false);
+ break;
+
+ case 0x5500:
+ execute_jcc(m_acc >= m_regs->read_byte(get_banked_address(opcode & 0x00ff)));
+ break;
+
+ case 0x5600:
+ execute_jcc(m_acc <= m_regs->read_byte(get_banked_address(opcode & 0x00ff)));
+ break;
+
+ case 0x5700:
+ execute_jcc(m_acc == m_regs->read_byte(get_banked_address(opcode & 0x00ff)));
+ break;
+
+ case 0x5800: case 0x5900: case 0x5a00: case 0x5b00:
+ case 0x5c00: case 0x5d00: case 0x5e00: case 0x5f00:
+ execute_jbc(opcode & 0x00ff, (opcode & 0x0700) >> 8);
+ break;
+
+ case 0x6000: case 0x6100: case 0x6200: case 0x6300:
+ case 0x6400: case 0x6500: case 0x6600: case 0x6700:
+ execute_jbs(opcode & 0x00ff, (opcode & 0x0700) >> 8);
+ break;
+
+ case 0x6800: case 0x6900: case 0x6a00: case 0x6b00:
+ case 0x6c00: case 0x6d00: case 0x6e00: case 0x6f00:
+ execute_bc(opcode & 0x00ff, (opcode & 0x0700) >> 8);
+ break;
+
+ case 0x7000: case 0x7100: case 0x7200: case 0x7300:
+ case 0x7400: case 0x7500: case 0x7600: case 0x7700:
+ execute_bs(opcode & 0x00ff, (opcode & 0x0700) >> 8);
+ break;
+
+ case 0x7800: case 0x7900: case 0x7a00: case 0x7b00:
+ case 0x7c00: case 0x7d00: case 0x7e00: case 0x7f00:
+ execute_btg(opcode & 0x00ff, (opcode & 0x0700) >> 8);
+ break;
+
+ default:
+ execute_undef(opcode);
+ break;
+ }
+}
+
+void riscii_series_device::execute_tbrd(u32 ptr)
+{
+ u16 addr = get_banked_address(m_curreg);
+ u16 data = m_program->read_word(ptr >> 1);
+ if (BIT(ptr, 0))
+ m_regs->write_byte(addr, data >> 8);
+ else
+ m_regs->write_byte(addr, data);
+ m_exec_state = EXEC_CYCLE1;
}
void riscii_series_device::execute_run()
{
- debugger_instruction_hook(m_pc);
+ while (m_icount > 0)
+ {
+ switch (m_exec_state)
+ {
+ case EXEC_CYCLE1:
+ m_ppc = m_pc;
+ debugger_instruction_hook(m_pc);
+ if (m_repeat != 0)
+ {
+ --m_repeat;
+ execute_cycle1(m_cache->read_word(m_pc));
+ }
+ else
+ execute_cycle1(m_cache->read_word(m_pc++));
+ break;
+
+ case EXEC_TBRD0:
+ execute_tbrd(m_tabptr);
+ break;
+
+ case EXEC_TBRD1:
+ execute_tbrd(m_tabptr++);
+ break;
+
+ case EXEC_TBRD2:
+ execute_tbrd(m_tabptr--);
+ break;
+
+ case EXEC_TBRDA:
+ execute_tbrd(m_tabptr + m_acc);
+ break;
+
+ case EXEC_L0JMP: case EXEC_L1JMP: case EXEC_L2JMP: case EXEC_L3JMP:
+ case EXEC_L4JMP: case EXEC_L5JMP: case EXEC_L6JMP: case EXEC_L7JMP:
+ case EXEC_L8JMP: case EXEC_L9JMP: case EXEC_LAJMP: case EXEC_LBJMP:
+ case EXEC_LCJMP: case EXEC_LDJMP: case EXEC_LEJMP: case EXEC_LFJMP:
+ execute_jump(u32(m_exec_state - EXEC_L0JMP) << 16 | m_cache->read_word(m_pc++));
+ m_exec_state = EXEC_CYCLE1;
+ break;
+
+ case EXEC_L0CALL: case EXEC_L1CALL: case EXEC_L2CALL: case EXEC_L3CALL:
+ case EXEC_L4CALL: case EXEC_L5CALL: case EXEC_L6CALL: case EXEC_L7CALL:
+ case EXEC_L8CALL: case EXEC_L9CALL: case EXEC_LACALL: case EXEC_LBCALL:
+ case EXEC_LCCALL: case EXEC_LDCALL: case EXEC_LECALL: case EXEC_LFCALL:
+ execute_call(u32(m_exec_state - EXEC_L0CALL) << 16 | m_cache->read_word(m_pc++));
+ m_exec_state = EXEC_CYCLE1;
+ break;
+
+ case EXEC_NOJMP:
+ (void)m_cache->read_word(m_pc++);
+ m_exec_state = EXEC_CYCLE1;
+ break;
+ }
- m_icount = 0;
+ m_icount--;
+ }
}
void riscii_series_device::execute_set_input(int inputnum, int state)