summaryrefslogtreecommitdiffstats
path: root/src/devices/cpu/dsp16/dsp16.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/cpu/dsp16/dsp16.cpp')
-rw-r--r--src/devices/cpu/dsp16/dsp16.cpp1343
1 files changed, 697 insertions, 646 deletions
diff --git a/src/devices/cpu/dsp16/dsp16.cpp b/src/devices/cpu/dsp16/dsp16.cpp
index 21cddebbf0a..ff31edc361c 100644
--- a/src/devices/cpu/dsp16/dsp16.cpp
+++ b/src/devices/cpu/dsp16/dsp16.cpp
@@ -226,7 +226,7 @@ void dsp16_device_base::device_start()
{
m_core.reset(reinterpret_cast<core_state *>(m_drc_cache.alloc_near(sizeof(core_state))));
new (m_core.get()) core_state(m_yaau_bits);
- m_icountptr = &m_core->icount;
+ set_icountptr(m_core->icount);
m_spaces[AS_PROGRAM] = &space(AS_PROGRAM);
m_spaces[AS_DATA] = &space(AS_DATA);
@@ -381,79 +381,41 @@ void dsp16_device_base::device_reset()
void dsp16_device_base::execute_run()
{
- while (m_core->icount_remaining())
+ if (machine().debug_flags & DEBUG_FLAG_ENABLED)
{
- // execute one cycle of an instruction
- switch (m_cache_mode)
+ while (m_core->icount_remaining())
{
- case cache::NONE:
- case cache::LOAD:
- execute_one_rom();
- break;
- case cache::EXECUTE:
- execute_one_cache();
- break;
- }
- m_core->decrement_icount();
-
- // step the serial I/O clock divider
- if (m_sio_clk_div)
- {
- --m_sio_clk_div;
- }
- else
- {
- bool const active(!m_sio_clk);
- m_sio_clk = active ? 1U : 0U;
- if (sio_ick_active())
+ switch (m_cache_mode)
{
- if (active)
- sio_ick_active_edge();
- m_ick_cb(m_sio_clk);
- }
- if (sio_ock_active())
- {
- m_ock_cb(m_sio_clk);
- if (active)
- sio_ock_active_edge();
- }
- m_sio_clk_div = m_sio_clk_res;
- }
-
- // udpate parallel input strobe
- if (m_pio_pids_cnt)
- {
- assert(!m_pids_out);
- if (!--m_pio_pids_cnt)
- {
- if (!m_pio_r_cb.isnull())
- m_pio_pdx_in = m_pio_r_cb(machine().dummy_space(), m_psel_out, 0xffffU);
- m_pids_cb(m_pids_out = 1U);
- LOGPIO("DSP16: PIO read active edge PSEL = %u, PDX = %04X (PC = %04X)\n", m_psel_out, m_pio_pdx_in, m_st_pcbase);
+ case cache::NONE:
+ execute_some_rom<true, false>();
+ break;
+ case cache::LOAD:
+ execute_some_rom<true, true>();
+ break;
+ case cache::EXECUTE:
+ execute_some_cache<true>();
+ break;
}
}
- else
- {
- assert(m_pids_out);
- }
-
- // udpate parallel output strobe
- if (m_pio_pods_cnt)
+ }
+ else
+ {
+ while (m_core->icount_remaining())
{
- assert(!m_pods_out);
- if (!--m_pio_pods_cnt)
+ switch (m_cache_mode)
{
- LOGPIO("DSP16: PIO write active edge PSEL = %u, PDX = %04X (PC = %04X)\n", m_psel_out, m_pio_pdx_out, m_st_pcbase);
- m_pods_cb(1U);
- m_pio_w_cb(machine().dummy_space(), m_psel_out, m_pio_pdx_out, 0xffffU);
- m_pods_out = 1U;
- m_pdb_w_cb(machine().dummy_space(), m_psel_out, 0xffffU, 0x0000U);
+ case cache::NONE:
+ execute_some_rom<false, false>();
+ break;
+ case cache::LOAD:
+ execute_some_rom<false, true>();
+ break;
+ case cache::EXECUTE:
+ execute_some_cache<false>();
+ break;
}
}
- else
- {
- assert(m_pods_out);
- }
}
}
@@ -691,605 +653,644 @@ void dsp16_device_base::program_map(address_map &map)
instruction execution
***********************************************************************/
-inline void dsp16_device_base::execute_one_rom()
+template <bool Debugger, bool Caching> inline void dsp16_device_base::execute_some_rom()
{
- u16 const op(m_cache[m_cache_ptr]);
- bool const cache_load(cache::LOAD == m_cache_mode);
- bool const last_cache_load(cache_load && (m_cache_ptr == m_cache_limit));
- u16 const cache_next((m_cache_ptr + (cache_load ? 1 : 0)) & 0x0fU);
- u16 *fetch_target(&m_cache[cache_next]);
- u16 fetch_addr(0U);
- flags predicate(FLAGS_PRED_NONE);
-
- switch (m_phase)
+ assert(bool(machine().debug_flags & DEBUG_FLAG_ENABLED) == Debugger);
+ for (bool mode_change = false; !mode_change && m_core->icount_remaining(); m_core->decrement_icount())
{
- case phase::PURGE:
- fetch_addr = m_core->xaau_pc;
- m_phase = phase::OP1;
- break;
+ assert((cache::LOAD == m_cache_mode) == Caching);
- case phase::OP1:
- if (machine().debug_flags & DEBUG_FLAG_ENABLED)
+ u16 const op(m_cache[m_cache_ptr]);
+ bool const last_cache_load(Caching && (m_cache_ptr == m_cache_limit));
+ u16 const cache_next((m_cache_ptr + (Caching ? 1 : 0)) & 0x0fU);
+ u16 *fetch_target(&m_cache[cache_next]);
+ u16 fetch_addr(0U);
+ flags predicate(FLAGS_PRED_NONE);
+
+ switch (m_phase)
{
- if (FLAGS_PRED_NONE == (m_flags & FLAGS_PRED_MASK))
- {
- debugger_instruction_hook(this, m_st_pcbase);
- }
- else
+ case phase::PURGE:
+ fetch_addr = m_core->xaau_pc;
+ m_phase = phase::OP1;
+ break;
+
+ case phase::OP1:
+ if (Debugger)
{
- switch (op >> 11)
+ if (FLAGS_PRED_NONE == (m_flags & FLAGS_PRED_MASK))
{
- case 0x00: // goto JA
- case 0x01:
- case 0x10: // call JA
- case 0x11:
- break;
- case 0x18: // goto B
- switch (op_b(op))
+ debugger_instruction_hook(m_st_pcbase);
+ }
+ else
+ {
+ switch (op >> 11)
{
- case 0x0: // return
- case 0x2: // goto pt
- case 0x3: // call pt
+ case 0x00: // goto JA
+ case 0x01:
+ case 0x10: // call JA
+ case 0x11:
+ break;
+ case 0x18: // goto B
+ switch (op_b(op))
+ {
+ case 0x0: // return
+ case 0x2: // goto pt
+ case 0x3: // call pt
+ break;
+ default:
+ debugger_instruction_hook(m_st_pcbase);
+ }
break;
default:
- debugger_instruction_hook(this, m_st_pcbase);
+ debugger_instruction_hook(m_st_pcbase);
}
- break;
- default:
- debugger_instruction_hook(this, m_st_pcbase);
}
}
- }
- // IACK is updated for the next instruction
- switch (m_flags & FLAGS_IACK_MASK)
- {
- case FLAGS_IACK_SET:
- if (m_iack_out)
- {
- LOGINT("DSP16: asserting IACK (PC = %04X)\n", m_st_pcbase);
- m_iack_cb(m_iack_out = 0U);
- standard_irq_callback(DSP16_INT_LINE);
- }
- break;
- case FLAGS_IACK_CLEAR:
- if (!m_iack_out)
+ // IACK is updated for the next instruction
+ switch (m_flags & FLAGS_IACK_MASK)
{
- LOGINT("DSP16: de-asserting IACK (PC = %04X)\n", m_st_pcbase);
- m_iack_cb(m_iack_out = 1U);
- m_pio_pioc &= 0xfffeU;
+ case FLAGS_IACK_SET:
+ if (m_iack_out)
+ {
+ LOGINT("DSP16: asserting IACK (PC = %04X)\n", m_st_pcbase);
+ m_iack_cb(m_iack_out = 0U);
+ standard_irq_callback(DSP16_INT_LINE);
+ }
+ break;
+ case FLAGS_IACK_CLEAR:
+ if (!m_iack_out)
+ {
+ LOGINT("DSP16: de-asserting IACK (PC = %04X)\n", m_st_pcbase);
+ m_iack_cb(m_iack_out = 1U);
+ m_pio_pioc &= 0xfffeU;
+ }
+ break;
+ default:
+ break;
}
- break;
- default:
- break;
- }
- set_iack(FLAGS_IACK_NONE);
+ set_iack(FLAGS_IACK_NONE);
- // if we're not servicing an interrupt or caching
- if (m_iack_out && (cache::NONE == m_cache_mode))
- {
- // TODO: is INT sampled on any instruction or only interruptible instructions?
- // if an unmasked interrupt is pending
- if ((m_pio_pioc & m_int_enable[0] & 0x001eU) || (BIT(m_int_enable[0], 0) && (CLEAR_LINE != m_int_in)))
+ // if we're not servicing an interrupt or caching
+ if (m_iack_out && !Caching)
{
- // if the current instruction is interruptible
- if (op_interruptible(op))
+ // TODO: is INT sampled on any instruction or only interruptible instructions?
+ // if an unmasked interrupt is pending
+ if ((m_pio_pioc & m_int_enable[0] & 0x001eU) || (BIT(m_int_enable[0], 0) && (CLEAR_LINE != m_int_in)))
{
- if (pio_int_enable() && (CLEAR_LINE != m_int_in))
+ // if the current instruction is interruptible
+ if (op_interruptible(op))
{
- if (ASSERT_LINE != m_int_in)
- m_int_in = CLEAR_LINE;
- m_pio_pioc |= 0x0001U;
+ if (pio_int_enable() && (CLEAR_LINE != m_int_in))
+ {
+ if (ASSERT_LINE != m_int_in)
+ m_int_in = CLEAR_LINE;
+ m_pio_pioc |= 0x0001U;
+ }
+ LOGINT(
+ "DSP16: servicing interrupts%s%s%s%s%s (PC = %04X)\n",
+ (pio_ibf_enable() && pio_ibf_status()) ? " IBF" : "",
+ (pio_obe_enable() && pio_obe_status()) ? " OBE" : "",
+ (pio_pids_enable() && pio_pids_status()) ? " PIDS" : "",
+ (pio_pods_enable() && pio_pods_status()) ? " PODS" : "",
+ (pio_int_enable() && pio_int_status()) ? " INT" : "",
+ m_st_pcbase);
+ set_iack(FLAGS_IACK_SET);
+ fetch_addr = m_core->xaau_next_pc();
+ m_int_enable[0] = m_int_enable[1];
+ m_core->xaau_pc = 0x0001U;
+ m_phase = phase::PURGE;
+ break;
}
- LOGINT(
- "DSP16: servicing interrupts%s%s%s%s%s (PC = %04X)\n",
- (pio_ibf_enable() && pio_ibf_status()) ? " IBF" : "",
- (pio_obe_enable() && pio_obe_status()) ? " OBE" : "",
- (pio_pids_enable() && pio_pids_status()) ? " PIDS" : "",
- (pio_pods_enable() && pio_pods_status()) ? " PODS" : "",
- (pio_int_enable() && pio_int_status()) ? " INT" : "",
- m_st_pcbase);
- set_iack(FLAGS_IACK_SET);
- fetch_addr = m_core->xaau_next_pc();
- m_int_enable[0] = m_int_enable[1];
- m_core->xaau_pc = 0x0001U;
- m_phase = phase::PURGE;
- break;
}
}
- }
- // normal opcode execution
- fetch_addr = set_xaau_pc_offset(m_core->xaau_pc + 1);
- m_int_enable[0] = m_int_enable[1];
- switch (op >> 11)
- {
- case 0x00: // goto JA
- case 0x01:
- case 0x10: // call JA
- case 0x11:
- if (check_predicate())
+ // normal opcode execution
+ fetch_addr = set_xaau_pc_offset(m_core->xaau_pc + 1);
+ m_int_enable[0] = m_int_enable[1];
+ switch (op >> 11)
{
- if (BIT(op, 15))
- m_core->xaau_pr = m_core->xaau_pc;
- set_xaau_pc_offset(op_ja(op));
- }
- m_phase = phase::PURGE;
- break;
-
- case 0x02: // R = M
- case 0x03:
- yaau_short_immediate_load(op);
- break;
+ case 0x00: // goto JA
+ case 0x01:
+ case 0x10: // call JA
+ case 0x11:
+ if (check_predicate())
+ {
+ if (BIT(op, 15))
+ m_core->xaau_pr = m_core->xaau_pc;
+ set_xaau_pc_offset(op_ja(op));
+ }
+ m_phase = phase::PURGE;
+ break;
- case 0x04: // F1 ; Y = a1[l]
- case 0x1c: // F1 ; Y = a0[l]
- fetch_target = nullptr;
- m_phase = phase::OP2;
- break;
+ case 0x02: // R = M
+ case 0x03:
+ yaau_short_immediate_load(op);
+ break;
- case 0x05: // F1 ; Z : aT[l]
- {
+ case 0x04: // F1 ; Y = a1[l]
+ case 0x1c: // F1 ; Y = a0[l]
fetch_target = nullptr;
- s64 const d(m_core->dau_f1(op));
- m_core->dau_temp = u16(u64(dau_saturate(op_d(~op))) >> (op_x(op) ? 16 : 0));
- m_core->op_dau_ad(op) = d;
- m_core->dau_set_at(op, yaau_read(op));
m_phase = phase::OP2;
- }
- break;
+ break;
- case 0x06: // F1 ; Y
- m_core->op_dau_ad(op) = m_core->dau_f1(op);
- yaau_read(op);
- break;
+ case 0x05: // F1 ; Z : aT[l]
+ {
+ fetch_target = nullptr;
+ s64 const d(m_core->dau_f1(op));
+ m_core->dau_temp = u16(u64(dau_saturate(op_d(~op))) >> (op_x(op) ? 16 : 0));
+ m_core->op_dau_ad(op) = d;
+ m_core->dau_set_at(op, yaau_read(op));
+ m_phase = phase::OP2;
+ }
+ break;
- case 0x07: // F1 ; aT[l] = Y
- m_core->op_dau_ad(op) = m_core->dau_f1(op);
- m_core->dau_set_at(op, yaau_read(op));
- break;
+ case 0x06: // F1 ; Y
+ m_core->op_dau_ad(op) = m_core->dau_f1(op);
+ yaau_read(op);
+ break;
- case 0x08: // aT = R
- assert(!(op & 0x000fU)); // reserved field?
- fetch_target = nullptr;
- m_core->dau_set_at(op, get_r(op));
- m_phase = phase::OP2;
- break;
+ case 0x07: // F1 ; aT[l] = Y
+ m_core->op_dau_ad(op) = m_core->dau_f1(op);
+ m_core->dau_set_at(op, yaau_read(op));
+ break;
- case 0x09: // R = a0
- case 0x0b: // R = a1
- assert(!(op & 0x040fU)); // reserved fields?
- fetch_target = nullptr;
- set_r(op, u16(u64(dau_saturate(BIT(op, 12))) >> 16));
- m_phase = phase::OP2;
- break;
+ case 0x08: // aT = R
+ assert(!(op & 0x000fU)); // reserved field?
+ fetch_target = nullptr;
+ m_core->dau_set_at(op, get_r(op));
+ m_phase = phase::OP2;
+ break;
- case 0x0a: // R = N
- assert(!(op & 0x040fU)); // reserved fields?
- m_phase = phase::OP2;
- fetch_target = &m_rom_data;
- break;
+ case 0x09: // R = a0
+ case 0x0b: // R = a1
+ assert(!(op & 0x040fU)); // reserved fields?
+ fetch_target = nullptr;
+ set_r(op, u16(u64(dau_saturate(BIT(op, 12))) >> 16));
+ m_phase = phase::OP2;
+ break;
- case 0x0c: // Y = R
- assert(!(op & 0x0400U)); // reserved field?
- fetch_target = nullptr;
- m_phase = phase::OP2;
- break;
+ case 0x0a: // R = N
+ assert(!(op & 0x040fU)); // reserved fields?
+ m_phase = phase::OP2;
+ fetch_target = &m_rom_data;
+ break;
- case 0x0d: // Z : R
- fetch_target = nullptr;
- m_core->dau_temp = get_r(op);
- set_r(op, yaau_read(op));
- m_phase = phase::OP2;
- break;
+ case 0x0c: // Y = R
+ assert(!(op & 0x0400U)); // reserved field?
+ fetch_target = nullptr;
+ m_phase = phase::OP2;
+ break;
- case 0x0e: // do K { instr1...instrIN } # redo K
- {
- u16 const ni(op_ni(op));
- if (ni)
- {
- m_cache_mode = cache::LOAD;
- fetch_target = &m_cache[m_cache_ptr = 1U];
- m_cache_limit = ni;
- m_cache_pcbase = m_st_pcbase;
- }
- else
+ case 0x0d: // Z : R
+ fetch_target = nullptr;
+ m_core->dau_temp = get_r(op);
+ set_r(op, yaau_read(op));
+ m_phase = phase::OP2;
+ break;
+
+ case 0x0e: // do K { instr1...instrIN } # redo K
{
- fetch_target = nullptr;
- m_cache_mode = cache::EXECUTE;
- m_phase = phase::PREFETCH;
- m_cache_ptr = 1U;
+ u16 const ni(op_ni(op));
+ if (ni)
+ {
+ mode_change = true;
+ fetch_target = &m_cache[m_cache_ptr = 1U];
+ m_cache_mode = cache::LOAD;
+ m_cache_limit = ni;
+ m_cache_pcbase = m_st_pcbase;
+ }
+ else
+ {
+ mode_change = true;
+ fetch_target = nullptr;
+ m_cache_mode = cache::EXECUTE;
+ m_phase = phase::PREFETCH;
+ m_cache_ptr = 1U;
+ }
+ m_cache_iterations = op_k(op);
+ assert(m_cache_iterations >= 2U); // p3-25: "The iteration count can be between 2 and 127, inclusive"
}
- m_cache_iterations = op_k(op);
- assert(m_cache_iterations >= 2U); // p3-25: "The iteration count can be between 2 and 127, inclusive"
- }
- break;
+ break;
- case 0x0f: // R = Y
- assert(!(op & 0x0400U)); // reserved field?
- fetch_target = nullptr;
- set_r(op, yaau_read(op));
- m_phase = phase::OP2;
- break;
+ case 0x0f: // R = Y
+ assert(!(op & 0x0400U)); // reserved field?
+ fetch_target = nullptr;
+ set_r(op, yaau_read(op));
+ m_phase = phase::OP2;
+ break;
- case 0x12: // ifc CON F2
- {
- bool const con(op_dau_con(op, false));
- ++m_core->dau_c[1];
- if (con)
+ case 0x12: // ifc CON F2
{
- m_core->dau_f2(op);
- m_core->dau_c[2] = m_core->dau_c[1];
+ bool const con(op_dau_con(op, false));
+ ++m_core->dau_c[1];
+ if (con)
+ {
+ m_core->dau_f2(op);
+ m_core->dau_c[2] = m_core->dau_c[1];
+ }
}
- }
- break;
-
- case 0x13: // if CON F2
- if (op_dau_con(op, true))
- m_core->dau_f2(op);
- break;
+ break;
- case 0x14: // F1 ; Y = y[l]
- fetch_target = nullptr;
- m_core->op_dau_ad(op) = m_core->dau_f1(op);
- m_phase = phase::OP2;
- break;
+ case 0x13: // if CON F2
+ if (op_dau_con(op, true))
+ m_core->dau_f2(op);
+ break;
- case 0x15: // F1 ; Z : y[l]
- fetch_target = nullptr;
- m_core->op_dau_ad(op) = m_core->dau_f1(op);
- m_core->dau_temp = m_core->dau_get_y(op);
- m_core->dau_set_y(op, yaau_read(op));
- m_phase = phase::OP2;
- break;
+ case 0x14: // F1 ; Y = y[l]
+ fetch_target = nullptr;
+ m_core->op_dau_ad(op) = m_core->dau_f1(op);
+ m_phase = phase::OP2;
+ break;
- case 0x16: // F1 ; x = Y
- m_core->op_dau_ad(op) = m_core->dau_f1(op);
- m_core->dau_x = yaau_read(op);
- break;
+ case 0x15: // F1 ; Z : y[l]
+ fetch_target = nullptr;
+ m_core->op_dau_ad(op) = m_core->dau_f1(op);
+ m_core->dau_temp = m_core->dau_get_y(op);
+ m_core->dau_set_y(op, yaau_read(op));
+ m_phase = phase::OP2;
+ break;
- case 0x17: // F1 ; y[l] = Y
- m_core->op_dau_ad(op) = m_core->dau_f1(op);
- m_core->dau_set_y(op, yaau_read(op));
- break;
+ case 0x16: // F1 ; x = Y
+ m_core->op_dau_ad(op) = m_core->dau_f1(op);
+ m_core->dau_x = yaau_read(op);
+ break;
- case 0x18: // goto B
- assert(!(op & 0x00ffU)); // reserved field?
- switch (op_b(op))
- {
- case 0x0: // return
- if (check_predicate())
- m_core->xaau_pc = m_core->xaau_pr;
+ case 0x17: // F1 ; y[l] = Y
+ m_core->op_dau_ad(op) = m_core->dau_f1(op);
+ m_core->dau_set_y(op, yaau_read(op));
break;
- case 0x1: // ireturn
+
+ case 0x18: // goto B
+ assert(!(op & 0x00ffU)); // reserved field?
+ switch (op_b(op))
+ {
+ case 0x0: // return
+ if (check_predicate())
+ m_core->xaau_pc = m_core->xaau_pr;
+ break;
+ case 0x1: // ireturn
+ if (m_iack_out)
+ logerror("DSP16: ireturn when not servicing interrupt (PC = %04X)\n", m_st_pcbase);
+ LOGINT("DSP16: return from interrupt (PC = %04X)\n", m_st_pcbase);
+ set_iack(FLAGS_IACK_CLEAR);
+ m_core->xaau_pc = m_core->xaau_pi;
+ break;
+ case 0x2: // goto pt
+ if (check_predicate())
+ m_core->xaau_pc = m_core->xaau_pt;
+ break;
+ case 0x3: // call pt
+ if (check_predicate())
+ {
+ m_core->xaau_pr = m_core->xaau_pc;
+ m_core->xaau_pc = m_core->xaau_pt;
+ }
+ break;
+ case 0x4: // Reserved
+ case 0x5:
+ case 0x6:
+ case 0x7:
+ throw emu_fatalerror("DSP16: reserved B value %01X (PC = %04X)\n", op_b(op), m_st_pcbase);
+ }
if (m_iack_out)
- logerror("DSP16: ireturn when not servicing interrupt (PC = %04X)\n", m_st_pcbase);
- LOGINT("DSP16: return from interrupt (PC = %04X)\n", m_st_pcbase);
- set_iack(FLAGS_IACK_CLEAR);
- m_core->xaau_pc = m_core->xaau_pi;
+ m_core->xaau_pi = m_core->xaau_pc;
+ m_phase = phase::PURGE;
break;
- case 0x2: // goto pt
- if (check_predicate())
- m_core->xaau_pc = m_core->xaau_pt;
+
+ case 0x19: // F1 ; y = a0 ; x = *pt++[i]
+ case 0x1b: // F1 ; y = a1 ; x = *pt++[i]
+ {
+ assert(!(op & 0x000fU)); // reserved field?
+ s64 const d(m_core->dau_f1(op));
+ s64 a(m_core->dau_a[BIT(op, 12)]);
+ // FIXME: is saturation applied when transferring a to y?
+ m_core->dau_y = u32(u64(a));
+ m_core->op_dau_ad(op) = d;
+ fetch_target = nullptr;
+ m_rom_data = m_spaces[AS_PROGRAM]->read_word(m_core->xaau_pt);
+ m_phase = phase::OP2;
+ }
break;
- case 0x3: // call pt
- if (check_predicate())
+
+ case 0x1a: // if CON # icall
+ assert(!(op & 0x03e0U)); // reserved field?
+ predicate = op_dau_con(op, true) ? FLAGS_PRED_TRUE : FLAGS_PRED_FALSE;
+ if (BIT(op, 10))
{
- m_core->xaau_pr = m_core->xaau_pc;
- m_core->xaau_pc = m_core->xaau_pt;
+ fetch_target = nullptr;
+ assert(0x000eU == op_con(op)); // CON must be true for icall?
+ m_phase = phase::OP2;
}
break;
- case 0x4: // Reserved
- case 0x5:
- case 0x6:
- case 0x7:
- throw emu_fatalerror("DSP16: reserved B value %01X (PC = %04X)\n", op_b(op), m_st_pcbase);
- }
- if (m_iack_out)
- m_core->xaau_pi = m_core->xaau_pc;
- m_phase = phase::PURGE;
- break;
- case 0x19: // F1 ; y = a0 ; x = *pt++[i]
- case 0x1b: // F1 ; y = a1 ; x = *pt++[i]
- {
- assert(!(op & 0x000fU)); // reserved field?
- s64 const d(m_core->dau_f1(op));
- s64 a(m_core->dau_a[BIT(op, 12)]);
- // FIXME: is saturation applied when transferring a to y?
- m_core->dau_y = u32(u64(a));
- m_core->op_dau_ad(op) = d;
+ case 0x1d: // F1 ; Z : y ; x = *pt++[i]
+ m_core->op_dau_ad(op) = m_core->dau_f1(op);
+ m_core->dau_temp = s16(m_core->dau_y >> 16);
+ m_core->dau_set_y(yaau_read(op));
fetch_target = nullptr;
m_rom_data = m_spaces[AS_PROGRAM]->read_word(m_core->xaau_pt);
m_phase = phase::OP2;
- }
- break;
+ break;
- case 0x1a: // if CON # icall
- assert(!(op & 0x03e0U)); // reserved field?
- predicate = op_dau_con(op, true) ? FLAGS_PRED_TRUE : FLAGS_PRED_FALSE;
- if (BIT(op, 10))
- {
+ case 0x1e: // Reserved
+ throw emu_fatalerror("DSP16: reserved op %u (PC = %04X)\n", op >> 11, m_st_pcbase);
+ break;
+
+ case 0x1f: // F1 ; y = Y ; x = *pt++[i]
+ m_core->op_dau_ad(op) = m_core->dau_f1(op);
+ m_core->dau_set_y(yaau_read(op));
fetch_target = nullptr;
- assert(0x000eU == op_con(op)); // CON must be true for icall?
+ m_rom_data = m_spaces[AS_PROGRAM]->read_word(m_core->xaau_pt);
m_phase = phase::OP2;
- }
- break;
+ break;
- case 0x1d: // F1 ; Z : y ; x = *pt++[i]
- m_core->op_dau_ad(op) = m_core->dau_f1(op);
- m_core->dau_temp = s16(m_core->dau_y >> 16);
- m_core->dau_set_y(yaau_read(op));
- fetch_target = nullptr;
- m_rom_data = m_spaces[AS_PROGRAM]->read_word(m_core->xaau_pt);
- m_phase = phase::OP2;
- break;
+ default:
+ throw emu_fatalerror("DSP16: unimplemented op %u (PC = %04X)\n", op >> 11, m_st_pcbase);
+ }
- case 0x1e: // Reserved
- throw emu_fatalerror("DSP16: reserved op %u (PC = %04X)\n", op >> 11, m_st_pcbase);
+ if (Caching && (phase::OP1 == m_phase))
+ {
+ // if the last instruction loaded to the cache completes in a single cycle, there's an extra cycle for a data fetch
+ if (last_cache_load)
+ {
+ mode_change = true;
+ fetch_target = nullptr;
+ m_cache_mode = cache::EXECUTE;
+ m_phase = phase::PREFETCH;
+ m_cache_ptr = 1U;
+ --m_cache_iterations;
+ }
+ else
+ {
+ m_cache_ptr = cache_next;
+ }
+ }
break;
- case 0x1f: // F1 ; y = Y ; x = *pt++[i]
- m_core->op_dau_ad(op) = m_core->dau_f1(op);
- m_core->dau_set_y(yaau_read(op));
- fetch_target = nullptr;
- m_rom_data = m_spaces[AS_PROGRAM]->read_word(m_core->xaau_pt);
- m_phase = phase::OP2;
- break;
+ case phase::OP2:
+ m_phase = phase::OP1;
+ switch (op >> 11)
+ {
+ case 0x04: // F1 ; Y = a1[l]
+ case 0x1c: // F1 ; Y = a0[l]
+ yaau_write(op, u16(u64(dau_saturate(BIT(~op, 14))) >> (op_x(op) ? 16 : 0)));
+ m_core->op_dau_ad(op) = m_core->dau_f1(op);
+ break;
- default:
- throw emu_fatalerror("DSP16: unimplemented op %u (PC = %04X)\n", op >> 11, m_st_pcbase);
- }
+ case 0x05: // F1 ; Z : aT[l]
+ case 0x0d: // Z : R
+ case 0x15: // F1 ; Z : y[l]
+ yaau_write_z(op);
+ break;
- if (cache_load && (phase::OP1 == m_phase))
- {
- // if the last instruction loaded to the cache completes in a single cycle, there's an extra cycle for a data fetch
- if (last_cache_load)
- {
- fetch_target = nullptr;
- m_cache_mode = cache::EXECUTE;
- m_phase = phase::PREFETCH;
- m_cache_ptr = 1U;
- --m_cache_iterations;
- }
- else
- {
- m_cache_ptr = cache_next;
- }
- }
- break;
+ case 0x08: // aT = R
+ case 0x09: // R = a0
+ case 0x0b: // R = a1
+ break;
- case phase::OP2:
- m_phase = phase::OP1;
- switch (op >> 11)
- {
- case 0x04: // F1 ; Y = a1[l]
- case 0x1c: // F1 ; Y = a0[l]
- yaau_write(op, u16(u64(dau_saturate(BIT(~op, 14))) >> (op_x(op) ? 16 : 0)));
- m_core->op_dau_ad(op) = m_core->dau_f1(op);
- break;
+ case 0x0a: // R = N
+ set_xaau_pc_offset(m_core->xaau_pc + 1);
+ set_r(op, m_rom_data);
+ break;
- case 0x05: // F1 ; Z : aT[l]
- case 0x0d: // Z : R
- case 0x15: // F1 ; Z : y[l]
- yaau_write_z(op);
- break;
+ case 0x0c: // Y = R
+ yaau_write(op, get_r(op));
+ break;
- case 0x08: // aT = R
- case 0x09: // R = a0
- case 0x0b: // R = a1
- break;
+ case 0x0f: // R = Y
+ break;
- case 0x0a: // R = N
- set_xaau_pc_offset(m_core->xaau_pc + 1);
- set_r(op, m_rom_data);
- break;
+ case 0x14: // F1 ; Y = y[l]
+ yaau_write(op, m_core->dau_get_y(op));
+ break;
- case 0x0c: // Y = R
- yaau_write(op, get_r(op));
- break;
+ case 0x19: // F1 ; y = a0 ; x = *pt++[i]
+ case 0x1b: // F1 ; y = a1 ; x = *pt++[i]
+ case 0x1f: // F1 ; y = Y ; x = *pt++[i]
+ m_core->xaau_increment_pt(op);
+ m_core->dau_x = m_rom_data;
+ break;
- case 0x0f: // R = Y
- break;
+ case 0x1a: // icall
+ // TODO: does INT get sampled or could an external interrupt be lost here?
+ assert(BIT(op, 10));
+ assert(FLAGS_PRED_TRUE == (m_flags & FLAGS_PRED_MASK));
+ if (check_predicate())
+ {
+ LOGINT(
+ "DSP16: servicing software interrupt%s%s%s%s%s (PC = %04X)\n",
+ (pio_ibf_enable() && pio_ibf_status()) ? " IBF" : "",
+ (pio_obe_enable() && pio_obe_status()) ? " OBE" : "",
+ (pio_pids_enable() && pio_pids_status()) ? " PIDS" : "",
+ (pio_pods_enable() && pio_pods_status()) ? " PODS" : "",
+ (pio_int_enable() && pio_int_status()) ? " INT" : "",
+ m_st_pcbase);
+ set_iack(FLAGS_IACK_SET);
+ m_core->xaau_pc = 0x0002U;
+ }
+ m_phase = phase::PURGE;
+ break;
- case 0x14: // F1 ; Y = y[l]
- yaau_write(op, m_core->dau_get_y(op));
- break;
+ case 0x1d: // F1 ; Z : y ; x = *pt++[i]
+ m_core->xaau_increment_pt(op);
+ m_core->dau_x = m_rom_data;
+ yaau_write_z(op);
+ break;
- case 0x19: // F1 ; y = a0 ; x = *pt++[i]
- case 0x1b: // F1 ; y = a1 ; x = *pt++[i]
- case 0x1f: // F1 ; y = Y ; x = *pt++[i]
- m_core->xaau_increment_pt(op);
- m_core->dau_x = m_rom_data;
- break;
+ default:
+ throw emu_fatalerror("DSP16: op %u doesn't take two cycles to run from ROM\n", op >> 11);
+ }
- case 0x1a: // icall
- // TODO: does INT get sampled or could an external interrupt be lost here?
- assert(BIT(op, 10));
- assert(FLAGS_PRED_TRUE == (m_flags & FLAGS_PRED_MASK));
- if (check_predicate())
+ if (last_cache_load)
{
- LOGINT(
- "DSP16: servicing software interrupt%s%s%s%s%s (PC = %04X)\n",
- (pio_ibf_enable() && pio_ibf_status()) ? " IBF" : "",
- (pio_obe_enable() && pio_obe_status()) ? " OBE" : "",
- (pio_pids_enable() && pio_pids_status()) ? " PIDS" : "",
- (pio_pods_enable() && pio_pods_status()) ? " PODS" : "",
- (pio_int_enable() && pio_int_status()) ? " INT" : "",
- m_st_pcbase);
- set_iack(FLAGS_IACK_SET);
- m_core->xaau_pc = 0x0002U;
+ mode_change = true;
+ fetch_target = nullptr;
+ m_cache_mode = cache::EXECUTE;
+ m_cache_ptr = 1U;
+ --m_cache_iterations;
+ overlap_rom_data_read();
+ }
+ else
+ {
+ fetch_addr = m_core->xaau_pc;
+ if (Caching)
+ m_cache_ptr = cache_next;
}
- m_phase = phase::PURGE;
- break;
-
- case 0x1d: // F1 ; Z : y ; x = *pt++[i]
- m_core->xaau_increment_pt(op);
- m_core->dau_x = m_rom_data;
- yaau_write_z(op);
break;
default:
- throw emu_fatalerror("DSP16: op %u doesn't take two cycles to run from ROM\n", op >> 11);
- }
-
- if (last_cache_load)
- {
- fetch_target = nullptr;
- m_cache_mode = cache::EXECUTE;
- m_cache_ptr = 1U;
- --m_cache_iterations;
- overlap_rom_data_read();
+ throw emu_fatalerror("DSP16: inappropriate phase for ROM execution\n");
}
- else
- {
- fetch_addr = m_core->xaau_pc;
- if (cache_load)
- m_cache_ptr = cache_next;
- }
- break;
- default:
- throw emu_fatalerror("DSP16: inappropriate phase for ROM execution\n");
- }
+ if (FLAGS_PRED_NONE != (m_flags & FLAGS_PRED_MASK))
+ throw emu_fatalerror("DSP16: predicate applied to ineligible op %u (PC = %04X)\n", op >> 11, m_st_pcbase);
+ set_predicate(predicate);
- if (FLAGS_PRED_NONE != (m_flags & FLAGS_PRED_MASK))
- throw emu_fatalerror("DSP16: predicate applied to ineligible op %u (PC = %04X)\n", op >> 11, m_st_pcbase);
- set_predicate(predicate);
+ if (fetch_target)
+ *fetch_target = m_direct->read_word(fetch_addr);
- if (fetch_target)
- *fetch_target = m_direct->read_word(fetch_addr);
+ if (phase::OP1 == m_phase)
+ {
+ if (cache::EXECUTE != m_cache_mode)
+ m_st_pcbase = m_core->xaau_pc;
+ else
+ m_st_pcbase = (m_cache_pcbase & 0xf000U) | ((m_cache_pcbase + m_cache_ptr) & 0x0fffU);
+ }
- if (phase::OP1 == m_phase)
- {
- if (cache::EXECUTE != m_cache_mode)
- m_st_pcbase = m_core->xaau_pc;
- else
- m_st_pcbase = (m_cache_pcbase & 0xf000U) | ((m_cache_pcbase + m_cache_ptr) & 0x0fffU);
+ sio_step();
+ pio_step();
}
}
-inline void dsp16_device_base::execute_one_cache()
+template <bool Debugger> inline void dsp16_device_base::execute_some_cache()
{
- u16 const op(m_cache[m_cache_ptr]);
- bool const at_limit(m_cache_ptr == m_cache_limit);
- bool const last_instruction(at_limit && (1U == m_cache_iterations));
- switch (m_phase)
+ assert(bool(machine().debug_flags & DEBUG_FLAG_ENABLED) == Debugger);
+ for (bool mode_change = false; !mode_change && m_core->icount_remaining(); m_core->decrement_icount())
{
- case phase::OP1:
- if (machine().debug_flags & DEBUG_FLAG_ENABLED)
- debugger_instruction_hook(this, m_st_pcbase);
- m_int_enable[0] = m_int_enable[1];
- switch (op >> 11)
+ u16 const op(m_cache[m_cache_ptr]);
+ bool const at_limit(m_cache_ptr == m_cache_limit);
+ bool const last_instruction(at_limit && (1U == m_cache_iterations));
+ switch (m_phase)
{
- case 0x02: // R = M
- case 0x03:
- yaau_short_immediate_load(op);
- break;
-
- case 0x04: // F1 ; Y = a1[l]
- case 0x1c: // F1 ; Y = a0[l]
- m_phase = phase::OP2;
- break;
-
- case 0x05: // F1 ; Z : aT[l]
+ case phase::OP1:
+ if (Debugger)
+ debugger_instruction_hook(m_st_pcbase);
+ m_int_enable[0] = m_int_enable[1];
+ switch (op >> 11)
{
- s64 const d(m_core->dau_f1(op));
- m_core->dau_temp = u16(u64(dau_saturate(op_d(~op))) >> (op_x(op) ? 16 : 0));
- m_core->op_dau_ad(op) = d;
- m_core->dau_set_at(op, yaau_read(op));
+ case 0x02: // R = M
+ case 0x03:
+ yaau_short_immediate_load(op);
+ break;
+
+ case 0x04: // F1 ; Y = a1[l]
+ case 0x1c: // F1 ; Y = a0[l]
m_phase = phase::OP2;
- }
- break;
+ break;
- case 0x06: // F1 ; Y
- m_core->op_dau_ad(op) = m_core->dau_f1(op);
- yaau_read(op);
- break;
+ case 0x05: // F1 ; Z : aT[l]
+ {
+ s64 const d(m_core->dau_f1(op));
+ m_core->dau_temp = u16(u64(dau_saturate(op_d(~op))) >> (op_x(op) ? 16 : 0));
+ m_core->op_dau_ad(op) = d;
+ m_core->dau_set_at(op, yaau_read(op));
+ m_phase = phase::OP2;
+ }
+ break;
- case 0x07: // F1 ; aT[l] = Y
- m_core->op_dau_ad(op) = m_core->dau_f1(op);
- m_core->dau_set_at(op, yaau_read(op));
- break;
+ case 0x06: // F1 ; Y
+ m_core->op_dau_ad(op) = m_core->dau_f1(op);
+ yaau_read(op);
+ break;
- case 0x08: // aT = R
- assert(!(op & 0x000fU)); // reserved field?
- m_core->dau_set_at(op, get_r(op));
- m_phase = phase::OP2;
- break;
+ case 0x07: // F1 ; aT[l] = Y
+ m_core->op_dau_ad(op) = m_core->dau_f1(op);
+ m_core->dau_set_at(op, yaau_read(op));
+ break;
- case 0x09: // R = a0
- case 0x0b: // R = a1
- assert(!(op & 0x040fU)); // reserved fields?
- set_r(op, u16(u64(dau_saturate(BIT(op, 12))) >> 16));
- m_phase = phase::OP2;
- break;
+ case 0x08: // aT = R
+ assert(!(op & 0x000fU)); // reserved field?
+ m_core->dau_set_at(op, get_r(op));
+ m_phase = phase::OP2;
+ break;
- case 0x0c: // Y = R
- assert(!(op & 0x0400U)); // reserved field?
- m_phase = phase::OP2;
- break;
+ case 0x09: // R = a0
+ case 0x0b: // R = a1
+ assert(!(op & 0x040fU)); // reserved fields?
+ set_r(op, u16(u64(dau_saturate(BIT(op, 12))) >> 16));
+ m_phase = phase::OP2;
+ break;
- case 0x0d: // Z : R
- m_core->dau_temp = get_r(op);
- set_r(op, yaau_read(op));
- m_phase = phase::OP2;
- break;
+ case 0x0c: // Y = R
+ assert(!(op & 0x0400U)); // reserved field?
+ m_phase = phase::OP2;
+ break;
- case 0x0f: // R = Y
- assert(!(op & 0x0400U)); // reserved field?
- set_r(op, yaau_read(op));
- m_phase = phase::OP2;
- break;
+ case 0x0d: // Z : R
+ m_core->dau_temp = get_r(op);
+ set_r(op, yaau_read(op));
+ m_phase = phase::OP2;
+ break;
- case 0x12: // ifc CON F2
- {
- bool const con(op_dau_con(op, false));
- ++m_core->dau_c[1];
- if (con)
+ case 0x0f: // R = Y
+ assert(!(op & 0x0400U)); // reserved field?
+ set_r(op, yaau_read(op));
+ m_phase = phase::OP2;
+ break;
+
+ case 0x12: // ifc CON F2
{
- m_core->dau_f2(op);
- m_core->dau_c[2] = m_core->dau_c[1];
+ bool const con(op_dau_con(op, false));
+ ++m_core->dau_c[1];
+ if (con)
+ {
+ m_core->dau_f2(op);
+ m_core->dau_c[2] = m_core->dau_c[1];
+ }
}
- }
- break;
+ break;
- case 0x13: // if CON F2
- if (op_dau_con(op, true))
- m_core->dau_f2(op);
- break;
+ case 0x13: // if CON F2
+ if (op_dau_con(op, true))
+ m_core->dau_f2(op);
+ break;
- case 0x14: // F1 ; Y = y[l]
- m_core->op_dau_ad(op) = m_core->dau_f1(op);
- m_phase = phase::OP2;
- break;
+ case 0x14: // F1 ; Y = y[l]
+ m_core->op_dau_ad(op) = m_core->dau_f1(op);
+ m_phase = phase::OP2;
+ break;
- case 0x15: // F1 ; Z : y[l]
- m_core->op_dau_ad(op) = m_core->dau_f1(op);
- m_core->dau_temp = m_core->dau_get_y(op);
- m_core->dau_set_y(op, yaau_read(op));
- m_phase = phase::OP2;
- break;
+ case 0x15: // F1 ; Z : y[l]
+ m_core->op_dau_ad(op) = m_core->dau_f1(op);
+ m_core->dau_temp = m_core->dau_get_y(op);
+ m_core->dau_set_y(op, yaau_read(op));
+ m_phase = phase::OP2;
+ break;
- case 0x16: // F1 ; x = Y
- m_core->op_dau_ad(op) = m_core->dau_f1(op);
- m_core->dau_x = yaau_read(op);
- break;
+ case 0x16: // F1 ; x = Y
+ m_core->op_dau_ad(op) = m_core->dau_f1(op);
+ m_core->dau_x = yaau_read(op);
+ break;
- case 0x17: // F1 ; y[l] = Y
- m_core->op_dau_ad(op) = m_core->dau_f1(op);
- m_core->dau_set_y(op, yaau_read(op));
- break;
+ case 0x17: // F1 ; y[l] = Y
+ m_core->op_dau_ad(op) = m_core->dau_f1(op);
+ m_core->dau_set_y(op, yaau_read(op));
+ break;
- case 0x19: // F1 ; y = a0 ; x = *pt++[i]
- case 0x1b: // F1 ; y = a1 ; x = *pt++[i]
- {
- assert(!(op & 0x000fU)); // reserved field?
- s64 const d(m_core->dau_f1(op));
- s64 a(m_core->dau_a[BIT(op, 12)]);
- // FIXME: is saturation applied when transferring a to y?
- m_core->dau_y = u32(u64(a));
- m_core->op_dau_ad(op) = d;
+ case 0x19: // F1 ; y = a0 ; x = *pt++[i]
+ case 0x1b: // F1 ; y = a1 ; x = *pt++[i]
+ {
+ assert(!(op & 0x000fU)); // reserved field?
+ s64 const d(m_core->dau_f1(op));
+ s64 a(m_core->dau_a[BIT(op, 12)]);
+ // FIXME: is saturation applied when transferring a to y?
+ m_core->dau_y = u32(u64(a));
+ m_core->op_dau_ad(op) = d;
+ if (last_instruction)
+ {
+ m_rom_data = m_direct->read_word(m_core->xaau_pt);
+ m_phase = phase::OP2;
+ }
+ else
+ {
+ m_core->xaau_increment_pt(op);
+ m_core->dau_x = m_rom_data;
+ }
+ }
+ break;
+
+ case 0x1d: // F1 ; Z : y ; x = *pt++[i]
+ m_core->op_dau_ad(op) = m_core->dau_f1(op);
+ m_core->dau_temp = s16(m_core->dau_y >> 16);
+ m_core->dau_set_y(yaau_read(op));
+ m_rom_data = m_direct->read_word(m_core->xaau_pt);
+ m_phase = phase::OP2;
+ break;
+
+ case 0x1f: // F1 ; y = Y ; x = *pt++[i]
+ m_core->op_dau_ad(op) = m_core->dau_f1(op);
+ m_core->dau_set_y(yaau_read(op));
if (last_instruction)
{
m_rom_data = m_direct->read_word(m_core->xaau_pt);
@@ -1300,126 +1301,107 @@ inline void dsp16_device_base::execute_one_cache()
m_core->xaau_increment_pt(op);
m_core->dau_x = m_rom_data;
}
- }
- break;
+ break;
- case 0x1d: // F1 ; Z : y ; x = *pt++[i]
- m_core->op_dau_ad(op) = m_core->dau_f1(op);
- m_core->dau_temp = s16(m_core->dau_y >> 16);
- m_core->dau_set_y(yaau_read(op));
- m_rom_data = m_direct->read_word(m_core->xaau_pt);
- m_phase = phase::OP2;
+ default:
+ throw emu_fatalerror("DSP16: inelligible op %u in cache (PC = %04X)\n", op >> 11, m_st_pcbase);
+ }
break;
- case 0x1f: // F1 ; y = Y ; x = *pt++[i]
- m_core->op_dau_ad(op) = m_core->dau_f1(op);
- m_core->dau_set_y(yaau_read(op));
- if (last_instruction)
- {
- m_rom_data = m_direct->read_word(m_core->xaau_pt);
- m_phase = phase::OP2;
- }
- else
+ case phase::OP2:
+ m_phase = phase::OP1;
+ switch (op >> 11)
{
- m_core->xaau_increment_pt(op);
- m_core->dau_x = m_rom_data;
- }
- break;
+ case 0x04: // F1 ; Y = a1[l]
+ case 0x1c: // F1 ; Y = a0[l]
+ yaau_write(op, u16(u64(dau_saturate(BIT(~op, 14))) >> (op_x(op) ? 16 : 0)));
+ m_core->op_dau_ad(op) = m_core->dau_f1(op);
+ break;
- default:
- throw emu_fatalerror("DSP16: inelligible op %u in cache (PC = %04X)\n", op >> 11, m_st_pcbase);
- }
- break;
+ case 0x05: // F1 ; Z : aT[l]
+ case 0x0d: // Z : R
+ case 0x15: // F1 ; Z : y[l]
+ yaau_write_z(op);
+ break;
- case phase::OP2:
- m_phase = phase::OP1;
- switch (op >> 11)
- {
- case 0x04: // F1 ; Y = a1[l]
- case 0x1c: // F1 ; Y = a0[l]
- yaau_write(op, u16(u64(dau_saturate(BIT(~op, 14))) >> (op_x(op) ? 16 : 0)));
- m_core->op_dau_ad(op) = m_core->dau_f1(op);
- break;
+ case 0x08: // aT = R
+ case 0x09: // R = a0
+ case 0x0b: // R = a1
+ break;
- case 0x05: // F1 ; Z : aT[l]
- case 0x0d: // Z : R
- case 0x15: // F1 ; Z : y[l]
- yaau_write_z(op);
- break;
+ case 0x0c: // Y = R
+ yaau_write(op, get_r(op));
+ break;
- case 0x08: // aT = R
- case 0x09: // R = a0
- case 0x0b: // R = a1
- break;
+ case 0x0f: // R = Y
+ break;
- case 0x0c: // Y = R
- yaau_write(op, get_r(op));
- break;
+ case 0x14: // F1 ; Y = y[l]
+ yaau_write(op, m_core->dau_get_y(op));
+ break;
- case 0x0f: // R = Y
- break;
+ case 0x19: // F1 ; y = a0 ; x = *pt++[i]
+ case 0x1b: // F1 ; y = a1 ; x = *pt++[i]
+ case 0x1f: // F1 ; y = Y ; x = *pt++[i]
+ assert(last_instruction);
+ m_core->xaau_increment_pt(op);
+ m_core->dau_x = m_rom_data;
+ break;
- case 0x14: // F1 ; Y = y[l]
- yaau_write(op, m_core->dau_get_y(op));
- break;
+ case 0x1d: // F1 ; Z : y ; x = *pt++[i]
+ m_core->xaau_increment_pt(op);
+ m_core->dau_x = m_rom_data;
+ yaau_write_z(op);
+ break;
- case 0x19: // F1 ; y = a0 ; x = *pt++[i]
- case 0x1b: // F1 ; y = a1 ; x = *pt++[i]
- case 0x1f: // F1 ; y = Y ; x = *pt++[i]
- assert(last_instruction);
- m_core->xaau_increment_pt(op);
- m_core->dau_x = m_rom_data;
+ default:
+ throw emu_fatalerror("DSP16: op %u doesn't take two cycles to run from cache\n", op >> 11);
+ }
break;
- case 0x1d: // F1 ; Z : y ; x = *pt++[i]
- m_core->xaau_increment_pt(op);
- m_core->dau_x = m_rom_data;
- yaau_write_z(op);
+ case phase::PREFETCH:
break;
default:
- throw emu_fatalerror("DSP16: op %u doesn't take two cycles to run from cache\n", op >> 11);
+ throw emu_fatalerror("DSP16: inappropriate phase for cache execution\n");
}
- break;
-
- case phase::PREFETCH:
- break;
-
- default:
- throw emu_fatalerror("DSP16: inappropriate phase for cache execution\n");
- }
- if (phase::PREFETCH == m_phase)
- {
- m_phase = phase::OP1;
- overlap_rom_data_read();
- m_st_pcbase = (m_cache_pcbase & 0xf000U) | ((m_cache_pcbase + m_cache_ptr) & 0x0fffU);
- }
- else if (phase::OP1 == m_phase)
- {
- if (last_instruction)
+ if (phase::PREFETCH == m_phase)
{
- // overlapped fetch of next instruction from ROM
- m_cache_mode = cache::NONE;
- m_cache[m_cache_ptr = 0] = m_direct->read_word(m_core->xaau_pc);
- m_st_pcbase = m_core->xaau_pc;
+ m_phase = phase::OP1;
+ overlap_rom_data_read();
+ m_st_pcbase = (m_cache_pcbase & 0xf000U) | ((m_cache_pcbase + m_cache_ptr) & 0x0fffU);
}
- else
+ else if (phase::OP1 == m_phase)
{
- if (at_limit)
+ if (last_instruction)
{
- // loop to first cached instruction
- m_cache_ptr = 1U;
- --m_cache_iterations;
+ // overlapped fetch of next instruction from ROM
+ mode_change = true;
+ m_cache_mode = cache::NONE;
+ m_cache[m_cache_ptr = 0] = m_direct->read_word(m_core->xaau_pc);
+ m_st_pcbase = m_core->xaau_pc;
}
else
{
- // move to next cached instruction
- m_cache_ptr = (m_cache_ptr + 1) & 0x0fU;
+ if (at_limit)
+ {
+ // loop to first cached instruction
+ m_cache_ptr = 1U;
+ --m_cache_iterations;
+ }
+ else
+ {
+ // move to next cached instruction
+ m_cache_ptr = (m_cache_ptr + 1) & 0x0fU;
+ }
+ overlap_rom_data_read();
+ m_st_pcbase = (m_cache_pcbase & 0xf000U) | ((m_cache_pcbase + m_cache_ptr) & 0x0fffU);
}
- overlap_rom_data_read();
- m_st_pcbase = (m_cache_pcbase & 0xf000U) | ((m_cache_pcbase + m_cache_ptr) & 0x0fffU);
}
+
+ sio_step();
+ pio_step();
}
}
@@ -1503,6 +1485,75 @@ void dsp16_device_base::yaau_write_z(u16 op)
}
/***********************************************************************
+ built-in peripherals
+***********************************************************************/
+
+inline void dsp16_device_base::sio_step()
+{
+ // step the serial I/O clock divider
+ if (m_sio_clk_div)
+ {
+ --m_sio_clk_div;
+ }
+ else
+ {
+ bool const active(!m_sio_clk);
+ m_sio_clk = active ? 1U : 0U;
+ if (sio_ick_active())
+ {
+ if (active)
+ sio_ick_active_edge();
+ m_ick_cb(m_sio_clk);
+ }
+ if (sio_ock_active())
+ {
+ m_ock_cb(m_sio_clk);
+ if (active)
+ sio_ock_active_edge();
+ }
+ m_sio_clk_div = m_sio_clk_res;
+ }
+}
+
+inline void dsp16_device_base::pio_step()
+{
+ // udpate parallel input strobe
+ if (m_pio_pids_cnt)
+ {
+ assert(!m_pids_out);
+ if (!--m_pio_pids_cnt)
+ {
+ if (!m_pio_r_cb.isnull())
+ m_pio_pdx_in = m_pio_r_cb(machine().dummy_space(), m_psel_out, 0xffffU);
+ m_pids_cb(m_pids_out = 1U);
+ LOGPIO("DSP16: PIO read active edge PSEL = %u, PDX = %04X (PC = %04X)\n", m_psel_out, m_pio_pdx_in, m_st_pcbase);
+ }
+ }
+ else
+ {
+ assert(m_pids_out);
+ }
+
+ // udpate parallel output strobe
+ if (m_pio_pods_cnt)
+ {
+ assert(!m_pods_out);
+ if (!--m_pio_pods_cnt)
+ {
+ LOGPIO("DSP16: PIO write active edge PSEL = %u, PDX = %04X (PC = %04X)\n", m_psel_out, m_pio_pdx_out, m_st_pcbase);
+ m_pods_cb(1U);
+ m_pio_w_cb(machine().dummy_space(), m_psel_out, m_pio_pdx_out, 0xffffU);
+ m_pods_out = 1U;
+ m_pdb_w_cb(machine().dummy_space(), m_psel_out, 0xffffU, 0x0000U);
+ }
+ }
+ else
+ {
+ assert(m_pods_out);
+ }
+}
+
+/***********************************************************************
inline helpers
***********************************************************************/