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.cpp426
1 files changed, 327 insertions, 99 deletions
diff --git a/src/devices/cpu/rii/riscii.cpp b/src/devices/cpu/rii/riscii.cpp
index 0317c5c9c4b..9889e35c822 100644
--- a/src/devices/cpu/rii/riscii.cpp
+++ b/src/devices/cpu/rii/riscii.cpp
@@ -19,6 +19,10 @@
#include "riscii.h"
#include "riidasm.h"
+#define LOG_TBRD (1U << 1)
+#define LOG_PROD (1U << 2)
+#include "logmacro.h"
+
// device type definitions
DEFINE_DEVICE_TYPE(EPG3231, epg3231_device, "epg3231", "Elan ePG3231")
@@ -57,19 +61,15 @@ std::unique_ptr<util::disasm_interface> epg3231_device::create_disassembler()
return std::make_unique<epg3231_disassembler>();
}
-riscii_series_device::riscii_series_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, unsigned addrbits, unsigned pcbits, u32 datastart, unsigned bankbits, u8 maxbank, u8 post_id_mask, address_map_constructor regs)
+riscii_series_device::riscii_series_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, unsigned addrbits, unsigned pcbits, unsigned bankbits, u8 maxbank, u8 post_id_mask, address_map_constructor regs)
: cpu_device(mconfig, type, tag, owner, clock)
, m_program_config("program", ENDIANNESS_LITTLE, 16, addrbits, -1)
, m_regs_config("register", ENDIANNESS_LITTLE, 8, 8 + bankbits, 0, regs)
- , m_program(nullptr)
- , m_regs(nullptr)
- , m_cache(nullptr)
- , m_porta_in_cb(*this)
- , m_port_in_cb{{*this}, {*this}, {*this}, {*this}, {*this}, {*this}, {*this}, {*this}, {*this}, {*this}}
- , m_port_out_cb{{*this}, {*this}, {*this}, {*this}, {*this}, {*this}, {*this}, {*this}, {*this}, {*this}}
+ , m_porta_in_cb(*this, 0xff)
+ , m_port_in_cb(*this, 0xff)
+ , m_port_out_cb(*this)
, m_pcmask((1 << pcbits) - 1)
- , m_datastart(datastart)
- , m_tbptmask(((1 << (addrbits + 1)) - 1) | (datastart != 0 ? 0x800000 : 0))
+ , m_tbptmask(((1 << (addrbits + 1)) - 1) | 0x800000)
, m_bankmask((1 << bankbits) - 1)
, m_maxbank(maxbank)
, m_post_id_mask(post_id_mask)
@@ -90,6 +90,7 @@ riscii_series_device::riscii_series_device(const machine_config &mconfig, device
, m_port_dcr{0, 0, 0, 0, 0, 0}
, m_port_control{0, 0}
, m_stbcon(0)
+ , m_pa(0xff)
, m_painten(0)
, m_paintsta(0)
, m_pawake(0)
@@ -139,7 +140,7 @@ void epg3231_device::regs_map(address_map &map)
map(0x0026, 0x0026).rw(FUNC(epg3231_device::trl1_r), FUNC(epg3231_device::trl1_w));
map(0x0027, 0x0027).rw(FUNC(epg3231_device::tr01con_r), FUNC(epg3231_device::tr01con_w));
map(0x0028, 0x0028).rw(FUNC(epg3231_device::tr2con_r), FUNC(epg3231_device::tr2con_w));
- map(0x0028, 0x0028).rw(FUNC(epg3231_device::trlir_r), FUNC(epg3231_device::trlir_w));
+ map(0x0029, 0x0029).rw(FUNC(epg3231_device::trlir_r), FUNC(epg3231_device::trlir_w));
// R2Ah is reserved
map(0x002b, 0x002b).rw(FUNC(epg3231_device::post_id_r), FUNC(epg3231_device::post_id_w));
// TODO: ADCON (R2Ch)
@@ -175,7 +176,7 @@ void epg3231_device::regs_map(address_map &map)
}
epg3231_device::epg3231_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
- : riscii_series_device(mconfig, EPG3231, tag, owner, clock, 22, 18, 0x40000, 5, 0x1f, 0xbb,
+ : riscii_series_device(mconfig, EPG3231, tag, owner, clock, 22, 18, 5, 0x1f, 0xbb,
address_map_constructor(FUNC(epg3231_device::regs_map), this))
{
}
@@ -188,26 +189,22 @@ device_memory_interface::space_config_vector riscii_series_device::memory_space_
};
}
-void riscii_series_device::device_resolve_objects()
-{
- m_porta_in_cb.resolve_safe(0xff);
- for (auto &cb : m_port_in_cb)
- cb.resolve_safe(0xff);
- for (auto &cb : m_port_out_cb)
- cb.resolve_safe();
-}
-
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>();
+ space(AS_PROGRAM).cache(m_cache);
+ space(AS_PROGRAM).specific(m_program);
+ space(AS_DATA).specific(m_regs);
if (m_pcmask > 0xffff)
m_pchstack = make_unique_clear<u8[]>(128);
set_icountptr(m_icount);
+ m_timer[0] = timer_alloc(FUNC(riscii_series_device::timer0), this);
+ m_timer[1] = timer_alloc(FUNC(riscii_series_device::timer1), this);
+ m_timer[2] = timer_alloc(FUNC(riscii_series_device::timer2), this);
+ m_speech_timer = timer_alloc(FUNC(riscii_series_device::speech_timer), this);
+
state_add<u32>(RII_PC, "PC", [this]() { return m_pc; }, [this](u32 pc) { debug_set_pc(pc); }).mask(m_pcmask);
state_add<u32>(STATE_GENPC, "GENPC", [this]() { return m_pc; }, [this](u32 pc) { debug_set_pc(pc); }).mask(m_pcmask).noshow();
state_add(STATE_GENPCBASE, "CURPC", m_ppc).mask(m_pcmask).noshow();
@@ -287,6 +284,7 @@ void riscii_series_device::device_start()
save_item(NAME(m_port_dcr));
save_item(NAME(m_port_control));
save_item(NAME(m_stbcon));
+ save_item(NAME(m_pa));
save_item(NAME(m_painten));
save_item(NAME(m_paintsta));
save_item(NAME(m_pawake));
@@ -350,6 +348,9 @@ void riscii_series_device::device_reset()
m_tr01con = 0x00;
m_tr2con = 0x00;
m_sfcr = 0x00;
+ m_timer[0]->adjust(attotime::never);
+ m_timer[1]->adjust(attotime::never);
+ m_timer[2]->adjust(attotime::never);
// reset synthesizer
std::fill_n(&m_env[0], 4, 0x00);
@@ -359,6 +360,7 @@ void riscii_series_device::device_reset()
m_sphtcon = 0x00;
m_sphtrl = 0x00;
m_vocon = 0x07;
+ m_speech_timer->adjust(attotime::never);
}
void riscii_series_device::debug_set_pc(u32 pc)
@@ -580,7 +582,7 @@ void riscii_series_device::post_id_w(u8 data)
u8 riscii_series_device::porta_r()
{
// Port A is read-only
- return m_porta_in_cb();
+ return m_pa & m_porta_in_cb();
}
u8 riscii_series_device::port_r(offs_t offset)
@@ -610,7 +612,10 @@ u8 riscii_series_device::port_r(offs_t offset)
void riscii_series_device::port_w(offs_t offset, u8 data)
{
+ if (m_port_data[offset] == data)
+ return;
m_port_data[offset] = data;
+
if (offset < 2)
{
u8 dc = m_port_dcr[offset];
@@ -634,6 +639,29 @@ u8 riscii_series_device::stbcon_r()
void riscii_series_device::stbcon_w(u8 data)
{
m_stbcon = data;
+ if (BIT(data, 5))
+ {
+ if (BIT(data, 4))
+ {
+ // All key mode
+ port_w(8, 0x00);
+ port_w(9, 0x00);
+ }
+ else
+ {
+ // Key strobe output on ports J and K
+ if (BIT(data, 3))
+ {
+ port_w(9, 0xff);
+ port_w(8, (1 << (data & 7)) ^ 0xff);
+ }
+ else
+ {
+ port_w(8, 0xff);
+ port_w(9, (1 << (data & 7)) ^ 0xff);
+ }
+ }
+ }
}
u8 riscii_series_device::painten_r()
@@ -795,6 +823,93 @@ void riscii_series_device::sprh_w(u8 data)
// TIMER HANDLERS
//**************************************************************************
+void riscii_series_device::timer0_reload()
+{
+ // Prescaler values are 1:1, 1:4, 1:16, 1:64
+ const unsigned prescale = 1 << ((m_tr01con & 0x03) << 1);
+ if (BIT(m_tr01con, 2))
+ m_timer[0]->adjust(cycles_to_attotime((m_trl0 + 1) * prescale * 2));
+ else
+ m_timer[0]->adjust(attotime::from_ticks((m_trl0 + 1) * prescale, 32768));
+}
+
+TIMER_CALLBACK_MEMBER(riscii_series_device::timer0)
+{
+ m_intsta |= 0x01;
+ timer0_reload();
+}
+
+u16 riscii_series_device::timer0_count() const
+{
+ if (!m_timer[0]->enabled())
+ return 0;
+ else
+ {
+ // Timer 0 counts up
+ const unsigned prescale = 1 << ((m_tr01con & 0x03) << 1);
+ if (BIT(m_tr01con, 2))
+ return m_trl0 - attotime_to_cycles(m_timer[0]->remaining()) / 2 / prescale;
+ else
+ return m_trl0 - m_timer[0]->remaining().as_ticks(32768) / prescale;
+ }
+}
+
+void riscii_series_device::timer1_reload()
+{
+ // Prescaler values are 1:4, 1:16, 1:64, 1:256
+ const unsigned prescale = 1 << (((m_tr01con & 0x30) >> 3) + 2);
+ m_timer[1]->adjust(attotime::from_ticks((m_trl1 + 1) * prescale, 32768));
+}
+
+TIMER_CALLBACK_MEMBER(riscii_series_device::timer1)
+{
+ m_intsta |= 0x02;
+ timer1_reload();
+}
+
+u8 riscii_series_device::timer1_count() const
+{
+ if (!m_timer[1]->enabled())
+ return 0;
+ else
+ {
+ // Timer 1 counts down
+ const unsigned prescale = 1 << (((m_tr01con & 0x30) >> 3) + 2);
+ return m_timer[1]->remaining().as_ticks(32768) / prescale;
+ }
+}
+
+void riscii_series_device::timer2_reload()
+{
+ // Prescaler values are 1:1, 1:2, 1:4, 1:8
+ const unsigned prescale = 1 << (m_tr2con & 0x03);
+ if (BIT(m_tr2con, 2))
+ m_timer[2]->adjust(cycles_to_attotime((m_trl2 + 1) * prescale * 2));
+ else
+ m_timer[2]->adjust(attotime::from_ticks((m_trl2 + 1) * prescale, 32768));
+}
+
+TIMER_CALLBACK_MEMBER(riscii_series_device::timer2)
+{
+ m_intsta |= 0x04;
+ timer2_reload();
+}
+
+u8 riscii_series_device::timer2_count() const
+{
+ if (!m_timer[2]->enabled())
+ return 0;
+ else
+ {
+ // Timer 2 counts down
+ const unsigned prescale = 1 << (m_tr2con & 0x03);
+ if (BIT(m_tr2con, 2))
+ return attotime_to_cycles(m_timer[2]->remaining()) / 2 / prescale;
+ else
+ return m_timer[2]->remaining().as_ticks(32768) / prescale;
+ }
+}
+
u8 riscii_series_device::trl0l_r()
{
return m_trl0 & 0x00ff;
@@ -842,7 +957,11 @@ u8 riscii_series_device::tr01con_r()
void riscii_series_device::tr01con_w(u8 data)
{
- m_tr01con = data;
+ u8 old_tr01con = std::exchange(m_tr01con, data);
+ if (BIT(data, 6) && !BIT(old_tr01con, 6))
+ timer1_reload();
+ else if (!BIT(data, 6) && BIT(old_tr01con, 6))
+ m_timer[1]->adjust(attotime::never);
}
u8 riscii_series_device::tr2con_r()
@@ -852,7 +971,16 @@ u8 riscii_series_device::tr2con_r()
void riscii_series_device::tr2con_w(u8 data)
{
- m_tr2con = data;
+ // TODO: Timer 0 capture mode, event counter mode
+ u8 old_tr2con = std::exchange(m_tr2con, data);
+ if ((data & 0x30) == 0x10 && (old_tr2con & 0x30) == 0)
+ timer0_reload();
+ else if ((data & 0x30) == 0x10 && (old_tr2con & 0x30) == 0)
+ m_timer[0]->adjust(attotime::never);
+ if (BIT(data, 3) && !BIT(old_tr2con, 3))
+ timer2_reload();
+ else if (!BIT(data, 3) && BIT(old_tr2con, 3))
+ m_timer[2]->adjust(attotime::never);
}
u8 riscii_series_device::trlir_r()
@@ -867,22 +995,22 @@ void riscii_series_device::trlir_w(u8 data)
u8 riscii_series_device::t0cl_r()
{
- return 0x00;
+ return timer0_count() & 0x00ff;
}
u8 riscii_series_device::t0ch_r()
{
- return 0x00;
+ return timer0_count() >> 8;
}
u8 riscii_series_device::tr1c_r()
{
- return 0xff;
+ return timer1_count();
}
u8 riscii_series_device::tr2c_r()
{
- return 0xff;
+ return timer2_count();
}
u8 riscii_series_device::sfcr_r()
@@ -900,6 +1028,21 @@ void riscii_series_device::sfcr_w(u8 data)
// MUSIC/SPEECH SYNTHESIZER
//**************************************************************************
+void riscii_series_device::spht_reload()
+{
+ unsigned sphtpsr_shift = ((m_sphtcon & 0xc0) >> 5) + 1;
+ m_speech_timer->adjust(clocks_to_attotime(((u16(m_sphtcon & 0x07) << 8 | m_sphtrl) + 1) << sphtpsr_shift));
+}
+
+TIMER_CALLBACK_MEMBER(riscii_series_device::speech_timer)
+{
+ // Speech timer interrupt
+ if (BIT(m_sphtcon, 4))
+ m_sphtcon |= 0x20;
+
+ spht_reload();
+}
+
u8 riscii_series_device::addl_r()
{
return m_add[BIT(m_sfcr, 2) ? 3 : m_sfcr & 0x03] & 0x0000ff;
@@ -960,7 +1103,13 @@ u8 riscii_series_device::mtcon_sphtcon_r()
void riscii_series_device::mtcon_sphtcon_w(u8 data)
{
if (BIT(m_sfcr, 2))
- m_sphtcon = data;
+ {
+ bool old_data = std::exchange(m_sphtcon, data);
+ if (BIT(data, 3) && !BIT(old_data, 3))
+ spht_reload();
+ else if (!BIT(data, 3))
+ m_speech_timer->adjust(attotime::never);
+ }
else
m_mtcon[m_sfcr & 0x03] = data;
}
@@ -998,7 +1147,7 @@ void riscii_series_device::vocon_w(u8 data)
u16 riscii_series_device::fetch_program_word()
{
- return m_cache->read_word(std::exchange(m_pc, (m_pc + 1) & m_pcmask));
+ return m_cache.read_word(std::exchange(m_pc, (m_pc + 1) & m_pcmask));
}
u16 riscii_series_device::get_banked_address(u8 reg)
@@ -1111,22 +1260,22 @@ void riscii_series_device::multi_byte_borrow(u16 addr, bool cy)
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);
+ 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);
+ u8 data = m_regs.read_byte(addr);
+ s16 tmp = s16(s8(data)) + s8(m_acc) + (c ? m_status & 0x01 : 0);
bool cy = u16(data) + m_acc + (c ? m_status & 0x01 : 0) >= 0x100;
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_regs.write_byte(addr, tmp & 0xff);
multi_byte_carry(addr, cy);
}
m_status = (m_status & 0xc0)
@@ -1141,15 +1290,18 @@ void riscii_series_device::execute_add(u8 reg, bool a, bool c)
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 cy = u8(data) >= m_acc + (c ? m_status & 0x01 : 0); // borrow is inverted
+ u8 data = m_regs.read_byte(addr);
+ // HACK: BSR1 needs to be decremented when FSR1 rolls under 0x80
+ if (!a && addr == 0x0009)
+ data &= 0x7f;
+ s16 tmp = s16(s8(data)) - s8(m_acc) - (c ? ~m_status & 0x01 : 0);
+ bool cy = u16(data) >= m_acc + (c ? ~m_status & 0x01 : 0); // borrow is inverted
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_regs.write_byte(addr, tmp & 0xff);
multi_byte_borrow(addr, cy);
}
m_status = (m_status & 0xc0)
@@ -1179,7 +1331,7 @@ void riscii_series_device::execute_add_imm(u8 data, bool c)
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 cy = u8(data) >= m_acc + (c ? m_status & 0x01 : 0); // borrow is inverted
+ bool cy = u8(data) >= m_acc + (c ? ~m_status & 0x01 : 0); // borrow is inverted
bool dc = (data & 0x0f) + (m_acc & 0x0f) + (c ? ~m_status & 0x01 : 0) >= 0x10;
acc_w(tmp & 0xff);
m_status = (m_status & 0xc0)
@@ -1194,7 +1346,7 @@ void riscii_series_device::execute_sub_imm(u8 data, bool c)
void riscii_series_device::execute_adddc(u8 reg, bool a)
{
u16 addr = get_banked_address(reg);
- u8 data = m_regs->read_byte(addr);
+ 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)
@@ -1204,7 +1356,7 @@ void riscii_series_device::execute_adddc(u8 reg, bool a)
if (a)
acc_w(tmp & 0xff);
else
- m_regs->write_byte(addr, tmp & 0xff);
+ m_regs.write_byte(addr, tmp & 0xff);
m_status = (m_status & 0xf8)
| (BIT(tmp, 8) ? 0x01 : 0x00)
| (dc ? 0x02 : 0x00)
@@ -1214,7 +1366,10 @@ void riscii_series_device::execute_adddc(u8 reg, bool a)
void riscii_series_device::execute_subdb(u8 reg, bool a)
{
u16 addr = get_banked_address(reg);
- u8 data = m_regs->read_byte(addr);
+ u8 data = m_regs.read_byte(addr);
+ // HACK: BSR1 needs to be decremented when FSR1 rolls under 0x80
+ if (!a && addr == 0x0009)
+ data &= 0x7f;
u16 tmp = u16(data) - m_acc - (~m_status & 0x01);
bool dc = (data & 0x0f) + (~m_acc & 0x0f) + (m_status & 0x01) >= 0x0a;
if (dc)
@@ -1224,7 +1379,7 @@ void riscii_series_device::execute_subdb(u8 reg, bool a)
if (a)
acc_w(tmp & 0xff);
else
- m_regs->write_byte(addr, tmp & 0xff);
+ m_regs.write_byte(addr, tmp & 0xff);
m_status = (m_status & 0xf8)
| (BIT(tmp, 8) ? 0x00 : 0x01) // borrow is inverted
| (dc ? 0x02 : 0x00)
@@ -1233,7 +1388,7 @@ void riscii_series_device::execute_subdb(u8 reg, bool a)
void riscii_series_device::execute_mul(u8 reg)
{
- execute_mul_imm(m_regs->read_byte(get_banked_address(reg)));
+ execute_mul_imm(m_regs.read_byte(get_banked_address(reg)));
}
void riscii_series_device::execute_mul_imm(u8 data)
@@ -1241,16 +1396,17 @@ void riscii_series_device::execute_mul_imm(u8 data)
int mier = BIT(m_cpucon, 3) ? int(s8(m_acc)) : int(m_acc);
int mcand = BIT(m_cpucon, 4) ? int(s8(data)) : int(data);
m_prod = u16(mier * mcand);
+ LOGMASKED(LOG_PROD, "%s: %d * %d = %04X\n", machine().describe_context(), mier, mcand, m_prod);
}
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);
+ u8 tmp = m_acc | m_regs.read_byte(addr);
if (a)
acc_w(tmp);
else
- m_regs->write_byte(addr, tmp);
+ m_regs.write_byte(addr, tmp);
if (tmp == 0)
m_status |= 0x04;
else
@@ -1260,11 +1416,11 @@ void riscii_series_device::execute_or(u8 reg, bool a)
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);
+ u8 tmp = m_acc & m_regs.read_byte(addr);
if (a)
acc_w(tmp);
else
- m_regs->write_byte(addr, tmp);
+ m_regs.write_byte(addr, tmp);
if (tmp == 0)
m_status |= 0x04;
else
@@ -1274,11 +1430,11 @@ void riscii_series_device::execute_and(u8 reg, bool a)
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);
+ u8 tmp = m_acc ^ m_regs.read_byte(addr);
if (a)
acc_w(tmp);
else
- m_regs->write_byte(addr, tmp);
+ m_regs.write_byte(addr, tmp);
if (tmp == 0)
m_status |= 0x04;
else
@@ -1288,11 +1444,11 @@ void riscii_series_device::execute_xor(u8 reg, bool a)
void riscii_series_device::execute_com(u8 reg, bool a)
{
u16 addr = get_banked_address(reg);
- u8 tmp = ~m_regs->read_byte(addr);
+ u8 tmp = ~m_regs.read_byte(addr);
if (a)
acc_w(tmp);
else
- m_regs->write_byte(addr, tmp);
+ m_regs.write_byte(addr, tmp);
if (tmp == 0)
m_status |= 0x04;
else
@@ -1301,41 +1457,41 @@ void riscii_series_device::execute_com(u8 reg, bool a)
void riscii_series_device::execute_clr(u8 reg)
{
- m_regs->write_byte(get_banked_address(reg), 0);
+ 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;
+ 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_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);
+ 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_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));
+ 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));
+ u8 tmp = m_regs.read_byte(get_banked_address(reg));
acc_w((tmp << 1) | (m_status & 0x01));
}
@@ -1349,7 +1505,7 @@ void riscii_series_device::execute_call(u32 addr)
// Push PC to the stack region at the end of banked RAM
m_stkptr -= 2;
u16 stkaddr = u16(m_maxbank - (BIT(m_stkptr, 7) ? 0 : 1)) << 8 | 0x80 | (m_stkptr & 0x7e);
- m_regs->write_word(stkaddr, swapendian_int16(m_pc & 0xffff));
+ m_regs.write_word(stkaddr, swapendian_int16(m_pc & 0xffff));
// PCH (on relevant models) must be saved somewhere. This implementation assumes a private buffer is used.
if (m_pcmask > 0xffff)
@@ -1369,12 +1525,12 @@ void riscii_series_device::execute_jcc(bool condition)
void riscii_series_device::execute_jdnz(u8 reg, bool a)
{
u16 addr = get_banked_address(reg);
- u8 tmp = m_regs->read_byte(addr) - 1;
+ u8 tmp = m_regs.read_byte(addr) - 1;
if (a)
acc_w(tmp);
else
{
- m_regs->write_byte(addr, tmp);
+ m_regs.write_byte(addr, tmp);
multi_byte_borrow(addr, tmp != 0xff);
}
execute_jcc(tmp != 0);
@@ -1383,12 +1539,12 @@ void riscii_series_device::execute_jdnz(u8 reg, bool a)
void riscii_series_device::execute_jinz(u8 reg, bool a)
{
u16 addr = get_banked_address(reg);
- u8 tmp = m_regs->read_byte(addr) + 1;
+ u8 tmp = m_regs.read_byte(addr) + 1;
if (a)
acc_w(tmp);
else
{
- m_regs->write_byte(addr, tmp);
+ m_regs.write_byte(addr, tmp);
multi_byte_carry(addr, tmp == 0);
}
execute_jcc(tmp != 0);
@@ -1405,17 +1561,17 @@ void riscii_series_device::set_z_acc(u8 tmp)
void riscii_series_device::execute_load(u8 reg)
{
- set_z_acc(m_regs->read_byte(get_banked_address(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);
+ 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));
+ u8 tmp = m_regs.read_byte(get_banked_address(reg));
if (tmp == 0)
m_status |= 0x04;
else
@@ -1425,82 +1581,83 @@ void riscii_series_device::execute_test(u8 reg)
void riscii_series_device::execute_swap(u8 reg, bool a)
{
u16 addr = get_banked_address(reg);
- u8 tmp = m_regs->read_byte(addr);
+ 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));
+ 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));
+ 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));
+ 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);
+ 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);
+ 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);
+ 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;
+ u16 tmp = u16(m_regs.read_byte(addr)) + 1;
if (a)
acc_w(tmp & 0xff);
else
{
- m_regs->write_byte(addr, tmp & 0xff);
+ m_regs.write_byte(addr, tmp & 0xff);
multi_byte_carry(addr, (tmp >> 8) != 0);
}
- m_status = (m_status & 0xfa) | ((tmp & 0xff) == 0 ? 0x04 : 0x00) | (tmp >> 8);
+ m_status = (m_status & 0xfa) | (tmp == 0x100 ? 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;
+ u16 tmp = u16(m_regs.read_byte(addr)) + 0xff;
if (a)
acc_w(tmp & 0xff);
else
{
- m_regs->write_byte(addr, tmp & 0xff);
- multi_byte_borrow(addr, (tmp >> 8) != 0);
+ m_regs.write_byte(addr, tmp & 0xff);
+ // HACK: BSR1 needs to be decremented when FSR1 rolls under 0x80
+ multi_byte_borrow(addr, tmp == (addr == 0x0009 ? 0x7f : 0xff));
}
- m_status = (m_status & 0xfa) | ((tmp & 0xff) == 0 ? 0x04 : 0x00) | (tmp >> 8);
+ m_status = (m_status & 0xfa) | (tmp == 0x100 ? 0x04 : 0x00) | (tmp >> 8);
}
void riscii_series_device::execute_rpt(u8 reg)
{
- m_repeat = m_regs->read_byte(get_banked_address(reg)) - 1;
+ m_repeat = m_regs.read_byte(get_banked_address(reg)) - 1;
}
void riscii_series_device::execute_ret(bool inte)
{
// Pop PC from the stack region at the end of banked RAM
u16 stkaddr = u16(m_maxbank - (BIT(m_stkptr, 7) ? 0 : 1)) << 8 | 0x80 | (m_stkptr & 0x7e);
- u32 dest = swapendian_int16(m_regs->read_word(stkaddr));
+ u32 dest = swapendian_int16(m_regs.read_word(stkaddr));
if (m_pcmask > 0xffff)
dest |= u32(m_pchstack[m_stkptr >> 1]) << 16;
execute_jump(dest);
@@ -1519,6 +1676,7 @@ void riscii_series_device::execute_wdtc()
void riscii_series_device::execute_slep()
{
logerror("%s mode entered (PC = %05X)\n", BIT(m_cpucon, 1) ? "Idle" : "Sleep", m_ppc);
+ m_exec_state = EXEC_IDLE;
}
void riscii_series_device::execute_undef(u16 opcode)
@@ -1765,15 +1923,15 @@ void riscii_series_device::execute_cycle1(u16 opcode)
break;
case 0x5500:
- execute_jcc(m_acc >= m_regs->read_byte(get_banked_address(opcode & 0x00ff)));
+ 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)));
+ 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)));
+ execute_jcc(m_acc == m_regs.read_byte(get_banked_address(opcode & 0x00ff)));
break;
case 0x5800: case 0x5900: case 0x5a00: case 0x5b00:
@@ -1811,21 +1969,59 @@ void riscii_series_device::execute_tbrd(u32 ptr)
{
u16 addr = get_banked_address(m_curreg);
u32 memaddr = (ptr & 0x7ffffe) >> 1;
- if (BIT(ptr, 23))
- memaddr += m_datastart;
- else
+ if (!BIT(ptr, 23))
memaddr &= m_pcmask;
- u16 data = m_program->read_word(memaddr);
+ u16 data = m_program.read_word(memaddr);
if (BIT(ptr, 0))
- m_regs->write_byte(addr, data >> 8);
+ data >>= 8;
else
- m_regs->write_byte(addr, data);
+ data &= 0x00ff;
+ LOGMASKED(LOG_TBRD, "%05X: TBRD(%06Xh) = %02Xh -> %02X:%02Xh\n", m_ppc, ptr, data, addr >> 8, addr & 0x00ff);
+ m_regs.write_byte(addr, data);
+
if (m_repeat != 0)
--m_repeat;
else
m_exec_state = EXEC_CYCLE1;
}
+bool riscii_series_device::interrupt_active() const
+{
+ if (!BIT(m_cpucon, 2))
+ return false;
+ else
+ return (m_intcon & m_intsta) != 0
+ || (m_painten & m_paintsta) != 0
+ || (m_spista & 0x30) == 0x30
+ || (m_sphtcon & 0x30) == 0x30;
+}
+
+u32 riscii_series_device::vector_interrupt() const
+{
+ // Input port A
+ if ((m_painten & m_paintsta) != 0)
+ return 0x00002;
+
+ // Capture
+ if ((m_intcon & m_intsta & 0x80) != 0)
+ return 0x00004;
+
+ // Speech timer
+ if ((m_sphtcon & 0x30) == 0x30)
+ return 0x00006;
+
+ // Timers 0–2
+ if ((m_intcon & m_intsta & 0x07) != 0)
+ return 0x00008;
+
+ // Peripheral
+ if ((m_intcon & m_intsta & 0x78) != 0 || (m_spista & 0x30) == 0x30)
+ return 0x0000a;
+
+ // Should not reach here
+ return 0x00000;
+}
+
void riscii_series_device::execute_run()
{
while (m_icount > 0)
@@ -1844,6 +2040,12 @@ void riscii_series_device::execute_run()
m_pc = m_ppc;
}
}
+ else if (interrupt_active())
+ {
+ // Disable interrupts and call handler
+ m_cpucon &= 0xfb;
+ execute_call(vector_interrupt());
+ }
else
execute_cycle1(fetch_program_word());
break;
@@ -1906,15 +2108,41 @@ void riscii_series_device::execute_run()
(void)fetch_program_word();
m_exec_state = EXEC_CYCLE1;
break;
+
+ case EXEC_IDLE:
+ debugger_wait_hook();
+ m_icount = 0;
+ return;
}
m_icount--;
}
}
+void riscii_series_device::idle_wakeup()
+{
+ if (m_exec_state == EXEC_IDLE)
+ m_exec_state = EXEC_CYCLE1;
+}
+
void riscii_series_device::execute_set_input(int inputnum, int state)
{
- // TODO
+ if (inputnum >= PA0_LINE && inputnum <= PA7_LINE)
+ {
+ if (state != CLEAR_LINE)
+ {
+ // Interrupt/wake-up on pin falling edge
+ if (BIT(m_pa, inputnum - PA0_LINE))
+ {
+ m_pa &= ~(1 << (inputnum - PA0_LINE));
+ m_paintsta |= 1 << (inputnum - PA0_LINE);
+ if (BIT(m_pawake, inputnum - PA0_LINE))
+ idle_wakeup();
+ }
+ }
+ else
+ m_pa |= 1 << (inputnum - PA0_LINE);
+ }
}
void riscii_series_device::state_string_export(const device_state_entry &entry, std::string &str) const