From b787818d0c28a4e57eabbcee7a909357a9c21019 Mon Sep 17 00:00:00 2001 From: Vas Crabb Date: Wed, 21 Mar 2018 21:01:36 +1100 Subject: dsp16: move most core state into DRC cache - keeps a lot of details out of the main header (DRC is still stubbed out) (nw) --- scripts/src/cpu.lua | 5 + src/devices/cpu/dsp16/dsp16.cpp | 704 ++++++++++++------------------------ src/devices/cpu/dsp16/dsp16.h | 68 +--- src/devices/cpu/dsp16/dsp16core.cpp | 38 ++ src/devices/cpu/dsp16/dsp16core.h | 116 ++++++ src/devices/cpu/dsp16/dsp16core.ipp | 223 ++++++++++++ src/devices/cpu/dsp16/dsp16rc.cpp | 50 +++ src/devices/cpu/dsp16/dsp16rc.h | 51 +++ 8 files changed, 736 insertions(+), 519 deletions(-) create mode 100644 src/devices/cpu/dsp16/dsp16core.cpp create mode 100644 src/devices/cpu/dsp16/dsp16core.h create mode 100644 src/devices/cpu/dsp16/dsp16core.ipp create mode 100644 src/devices/cpu/dsp16/dsp16rc.cpp create mode 100644 src/devices/cpu/dsp16/dsp16rc.h diff --git a/scripts/src/cpu.lua b/scripts/src/cpu.lua index 955c18a1dca..1388960e45e 100644 --- a/scripts/src/cpu.lua +++ b/scripts/src/cpu.lua @@ -271,8 +271,13 @@ if (CPUS["DSP16"]~=null) then files { MAME_DIR .. "src/devices/cpu/dsp16/dsp16.cpp", MAME_DIR .. "src/devices/cpu/dsp16/dsp16.h", + MAME_DIR .. "src/devices/cpu/dsp16/dsp16core.cpp", + MAME_DIR .. "src/devices/cpu/dsp16/dsp16core.h", + MAME_DIR .. "src/devices/cpu/dsp16/dsp16core.ipp", MAME_DIR .. "src/devices/cpu/dsp16/dsp16fe.cpp", MAME_DIR .. "src/devices/cpu/dsp16/dsp16fe.h", + MAME_DIR .. "src/devices/cpu/dsp16/dsp16rc.cpp", + MAME_DIR .. "src/devices/cpu/dsp16/dsp16rc.h", } end diff --git a/src/devices/cpu/dsp16/dsp16.cpp b/src/devices/cpu/dsp16/dsp16.cpp index b9b970cdeb5..2026cf5d80e 100644 --- a/src/devices/cpu/dsp16/dsp16.cpp +++ b/src/devices/cpu/dsp16/dsp16.cpp @@ -77,7 +77,8 @@ #include "emu.h" #include "dsp16.h" -#include "dsp16dis.h" +#include "dsp16core.ipp" +#include "dsp16rc.h" #include "debugger.h" @@ -184,15 +185,13 @@ dsp16_device_base::dsp16_device_base( { "rom", ENDIANNESS_BIG, 16, 16, -1, address_map_constructor(FUNC(dsp16_device_base::program_map), this) }, { "ram", ENDIANNESS_BIG, 16, yaau_bits, -1, std::move(data_map) }, { "exm", ENDIANNESS_BIG, 16, 16, -1 } } - , m_yaau_mask(u16((u32(1) << yaau_bits) - 1)), m_yaau_sign(u16(1) << (yaau_bits - 1)) + , m_yaau_bits(yaau_bits) , m_spaces{ nullptr, nullptr, nullptr }, m_direct(nullptr) - , m_icount(0), m_cache_mode(cache::NONE), m_phase(phase::PURGE), m_int_enable{ 0U, 0U }, m_flags(FLAGS_NONE), m_cache_ptr(0U), m_cache_limit(0U), m_cache_iterations(0U) + , m_drc_cache(CACHE_SIZE), m_core(nullptr, [] (core_state *core) { core->~core_state(); }), m_recompiler() + , m_cache_mode(cache::NONE), m_phase(phase::PURGE), m_int_enable{ 0U, 0U }, m_flags(FLAGS_NONE), m_cache_ptr(0U), m_cache_limit(0U), m_cache_iterations(0U) , m_exm_in(1U), m_int_in(CLEAR_LINE), m_iack_out(1U) , m_ick_in(1U), m_ild_in(CLEAR_LINE), m_do_out(1U), m_ock_in(1U), m_old_in(CLEAR_LINE), m_ose_out(1U) , m_psel_out(0U), m_pids_out(1U), m_pods_out(1U) - , m_xaau_pc(0U), m_xaau_pt(0U), m_xaau_pr(0U), m_xaau_pi(0U), m_xaau_i(0) - , m_yaau_r{ 0U, 0U, 0U, 0U }, m_yaau_rb(0U), m_yaau_re(0U), m_yaau_j(0), m_yaau_k(0) - , m_dau_x(0), m_dau_y(0), m_dau_p(0), m_dau_a{ 0, 0 }, m_dau_c{ 0, 0, 0 }, m_dau_auc(0U), m_dau_psw(0U), m_dau_temp(0) , m_sio_sioc(0U), m_sio_obuf(0U), m_sio_osr(0U), m_sio_ofsr(0U) , m_sio_clk(1U), m_sio_clk_div(0U), m_sio_clk_res(0U), m_sio_ld(1U), m_sio_ld_div(0U), m_sio_flags(SIO_FLAGS_NONE) , m_pio_pioc(0U), m_pio_pdx_in(0U), m_pio_pdx_out(0U), m_pio_pids_cnt(0U), m_pio_pods_cnt(0U) @@ -225,38 +224,43 @@ void dsp16_device_base::device_resolve_objects() void dsp16_device_base::device_start() { - m_icountptr = &m_icount; + m_core.reset(reinterpret_cast(m_drc_cache.alloc_near(sizeof(core_state)))); + new (m_core.get()) core_state(m_yaau_bits); + m_icountptr = &m_core->icount; m_spaces[AS_PROGRAM] = &space(AS_PROGRAM); m_spaces[AS_DATA] = &space(AS_DATA); m_spaces[AS_IO] = &space(AS_IO); m_direct = m_spaces[AS_PROGRAM]->direct<-1>(); - state_add(STATE_GENPC, "PC", m_xaau_pc); + if (allow_drc()) + m_recompiler.reset(new recompiler(*this, 0)); // TODO: what are UML flags for? + + state_add(STATE_GENPC, "PC", m_core->xaau_pc); state_add(STATE_GENPCBASE, "CURPC", m_st_pcbase).noshow(); state_add(STATE_GENFLAGS, "GENFLAGS", m_st_genflags).mask(0x0fU).noshow().callexport().formatstr("%16s"); - state_add(DSP16_PT, "PT", m_xaau_pt); - state_add(DSP16_PR, "PR", m_xaau_pr); - state_add(DSP16_PI, "PI", m_xaau_pi); - state_add(DSP16_I, "I", m_xaau_i).mask((s16(1) << 12) - 1).callimport(); - state_add(DSP16_R0, "R0", m_yaau_r[0]).mask(m_yaau_mask); - state_add(DSP16_R1, "R1", m_yaau_r[1]).mask(m_yaau_mask); - state_add(DSP16_R2, "R2", m_yaau_r[2]).mask(m_yaau_mask); - state_add(DSP16_R3, "R3", m_yaau_r[3]).mask(m_yaau_mask); - state_add(DSP16_RB, "RB", m_yaau_rb).mask(m_yaau_mask); - state_add(DSP16_RE, "RE", m_yaau_re).mask(m_yaau_mask); - state_add(DSP16_J, "J", m_yaau_j).mask(m_yaau_mask).callimport(); - state_add(DSP16_K, "K", m_yaau_k).mask(m_yaau_mask).callimport(); - state_add(DSP16_X, "X", m_dau_x); - state_add(DSP16_Y, "Y", m_dau_y); - state_add(DSP16_P, "P", m_dau_p); - state_add(DSP16_A0, "A0", m_dau_a[0]).mask(DAU_A_MASK).callimport(); - state_add(DSP16_A1, "A1", m_dau_a[1]).mask(DAU_A_MASK).callimport(); - state_add(DSP16_C0, "C0", m_dau_c[0]); - state_add(DSP16_C1, "C1", m_dau_c[1]); - state_add(DSP16_C2, "C2", m_dau_c[2]); - state_add(DSP16_AUC, "AUC", m_dau_auc).mask(0x7fU); - state_add(DSP16_PSW, "PSW", m_dau_psw).callimport().callexport(); + state_add(DSP16_PT, "PT", m_core->xaau_pt); + state_add(DSP16_PR, "PR", m_core->xaau_pr); + state_add(DSP16_PI, "PI", m_core->xaau_pi); + state_add(DSP16_I, "I", m_core->xaau_i).mask((s16(1) << 12) - 1).callimport(); + state_add(DSP16_R0, "R0", m_core->yaau_r[0]).mask(m_core->yaau_mask); + state_add(DSP16_R1, "R1", m_core->yaau_r[1]).mask(m_core->yaau_mask); + state_add(DSP16_R2, "R2", m_core->yaau_r[2]).mask(m_core->yaau_mask); + state_add(DSP16_R3, "R3", m_core->yaau_r[3]).mask(m_core->yaau_mask); + state_add(DSP16_RB, "RB", m_core->yaau_rb).mask(m_core->yaau_mask); + state_add(DSP16_RE, "RE", m_core->yaau_re).mask(m_core->yaau_mask); + state_add(DSP16_J, "J", m_core->yaau_j).mask(m_core->yaau_mask).callimport(); + state_add(DSP16_K, "K", m_core->yaau_k).mask(m_core->yaau_mask).callimport(); + state_add(DSP16_X, "X", m_core->dau_x); + state_add(DSP16_Y, "Y", m_core->dau_y); + state_add(DSP16_P, "P", m_core->dau_p); + state_add(DSP16_A0, "A0", m_core->dau_a[0]).mask(DAU_A_MASK).callimport(); + state_add(DSP16_A1, "A1", m_core->dau_a[1]).mask(DAU_A_MASK).callimport(); + state_add(DSP16_C0, "C0", m_core->dau_c[0]); + state_add(DSP16_C1, "C1", m_core->dau_c[1]); + state_add(DSP16_C2, "C2", m_core->dau_c[2]); + state_add(DSP16_AUC, "AUC", m_core->dau_auc).mask(0x7fU); + state_add(DSP16_PSW, "PSW", m_core->dau_psw).callimport().callexport(); state_add(DSP16_YH, "YH", m_st_yh).noshow().callimport().callexport(); state_add(DSP16_A0H, "A0H", m_st_ah[0]).noshow().callimport().callexport(); state_add(DSP16_A1H, "A1H", m_st_ah[1]).noshow().callimport().callexport(); @@ -264,6 +268,8 @@ void dsp16_device_base::device_start() state_add(DSP16_A0L, "A0L", m_st_al[0]).noshow().callimport().callexport(); state_add(DSP16_A1L, "A1L", m_st_al[1]).noshow().callimport().callexport(); + m_core->register_save_items(*this); + save_item(NAME(m_cache_mode)); save_item(NAME(m_phase)); save_item(NAME(m_int_enable)); @@ -289,27 +295,6 @@ void dsp16_device_base::device_start() save_item(NAME(m_pids_out)); save_item(NAME(m_pods_out)); - save_item(NAME(m_xaau_pc)); - save_item(NAME(m_xaau_pt)); - save_item(NAME(m_xaau_pr)); - save_item(NAME(m_xaau_pi)); - save_item(NAME(m_xaau_i)); - - save_item(NAME(m_yaau_r)); - save_item(NAME(m_yaau_rb)); - save_item(NAME(m_yaau_re)); - save_item(NAME(m_yaau_j)); - save_item(NAME(m_yaau_k)); - - save_item(NAME(m_dau_x)); - save_item(NAME(m_dau_y)); - save_item(NAME(m_dau_p)); - save_item(NAME(m_dau_a)); - save_item(NAME(m_dau_c)); - save_item(NAME(m_dau_auc)); - save_item(NAME(m_dau_psw)); - save_item(NAME(m_dau_temp)); - save_item(NAME(m_sio_sioc)); save_item(NAME(m_sio_obuf)); save_item(NAME(m_sio_osr)); @@ -333,6 +318,11 @@ void dsp16_device_base::device_start() external_memory_enable(*m_spaces[AS_PROGRAM], !m_exm_in); } +void dsp16_device_base::device_stop() +{ + m_recompiler.reset(); +} + void dsp16_device_base::device_reset() { cpu_device::device_reset(); @@ -342,9 +332,9 @@ void dsp16_device_base::device_reset() std::fill(std::begin(m_int_enable), std::end(m_int_enable), 0U); m_flags = FLAGS_NONE; m_cache_ptr = 0U; - m_xaau_pc = 0U; - m_yaau_rb = 0U; - m_yaau_re = 0U; + m_core->xaau_pc = 0U; + m_core->yaau_rb = 0U; + m_core->yaau_re = 0U; m_sio_sioc = 0U; m_sio_ofsr = 0U; m_sio_clk = 1U; @@ -391,7 +381,7 @@ void dsp16_device_base::device_reset() void dsp16_device_base::execute_run() { - while (0 < m_icount) + while (m_core->icount_remaining()) { // execute one cycle of an instruction switch (m_cache_mode) @@ -404,7 +394,7 @@ void dsp16_device_base::execute_run() execute_one_cache(); break; } - --m_icount; + m_core->decrement_icount(); // step the serial I/O clock divider if (m_sio_clk_div) @@ -538,46 +528,33 @@ void dsp16_device_base::state_import(device_state_entry const &entry) switch (entry.index()) { // extend signed registers that aren't a power-of-two size - case DSP16_I: - m_xaau_i = (m_xaau_i & XAAU_I_MASK) | ((m_xaau_i & XAAU_I_SIGN) ? XAAU_I_EXT : 0); - break; - case DSP16_J: - m_yaau_j = (m_yaau_j & m_yaau_mask) | ((m_yaau_j & m_yaau_sign) ? ~m_yaau_mask : 0); - break; - case DSP16_K: - m_yaau_k = (m_yaau_k & m_yaau_mask) | ((m_yaau_k & m_yaau_sign) ? ~m_yaau_mask : 0); - break; - case DSP16_A0: - m_dau_a[0] = (m_dau_a[0] & DAU_A_MASK) | ((m_dau_a[0] & DAU_A_SIGN) ? DAU_A_EXT : 0); - break; - case DSP16_A1: - m_dau_a[1] = (m_dau_a[1] & DAU_A_MASK) | ((m_dau_a[1] & DAU_A_SIGN) ? DAU_A_EXT : 0); - break; + case DSP16_I: m_core->xaau_extend_i(); break; + case DSP16_J: m_core->yaau_extend_j(); break; + case DSP16_K: m_core->yaau_extend_k(); break; + case DSP16_A0: m_core->dau_extend_a<0>(); break; + case DSP16_A1: m_core->dau_extend_a<1>(); break; // guard bits of accumulators are accessible via status word - case DSP16_PSW: - m_dau_a[0] = u64(u32(m_dau_a[0])) | (u64(m_dau_psw & 0x000fU) << 32) | (BIT(m_dau_psw, 3) ? DAU_A_EXT : 0U); - m_dau_a[1] = u64(u32(m_dau_a[1])) | (u64(m_dau_psw & 0x01e0U) << 27) | (BIT(m_dau_psw, 8) ? DAU_A_EXT : 0U); - break; + case DSP16_PSW: m_core->dau_import_psw(); break; // put partial registers in the appropriate places case DSP16_YH: - m_dau_y = (s32(m_st_yh) << 16) | (m_dau_y & ((s32(1) << 16) - 1)); + m_core->dau_y = (s32(m_st_yh) << 16) | (m_core->dau_y & ((s32(1) << 16) - 1)); break; case DSP16_A0H: - m_dau_a[0] = (s32(m_st_ah[0]) << 16) | s32(m_dau_a[0] & ((s32(1) << 16) - 1)); + m_core->dau_a[0] = (s32(m_st_ah[0]) << 16) | s32(m_core->dau_a[0] & ((s32(1) << 16) - 1)); break; case DSP16_A1H: - m_dau_a[1] = (s32(m_st_ah[1]) << 16) | s32(m_dau_a[1] & ((s32(1) << 16) - 1)); + m_core->dau_a[1] = (s32(m_st_ah[1]) << 16) | s32(m_core->dau_a[1] & ((s32(1) << 16) - 1)); break; case DSP16_YL: - m_dau_y = (m_dau_y & ~((s32(1) << 16) - 1)) | u32(m_st_yl); + m_core->dau_y = (m_core->dau_y & ~((s32(1) << 16) - 1)) | u32(m_st_yl); break; case DSP16_A0L: - m_dau_a[0] = (m_dau_a[0] & ~((s64(1) << 16) - 1)) | u64(m_st_al[0]); + m_core->dau_a[0] = (m_core->dau_a[0] & ~((s64(1) << 16) - 1)) | u64(m_st_al[0]); break; case DSP16_A1L: - m_dau_a[1] = (m_dau_a[1] & ~((s64(1) << 16) - 1)) | u64(m_st_al[1]); + m_core->dau_a[1] = (m_core->dau_a[1] & ~((s64(1) << 16) - 1)) | u64(m_st_al[1]); break; } } @@ -587,28 +564,26 @@ void dsp16_device_base::state_export(device_state_entry const &entry) switch (entry.index()) { // guard bits of accumulators are accessible via status word - case DSP16_PSW: - m_dau_psw = (m_dau_psw & 0xfe10U) | (u16(u64(m_dau_a[0]) >> 32) & 0x000fU) | (u16(u64(m_dau_a[1]) >> 27) & 0x01e0U); - break; + case DSP16_PSW: m_core->dau_export_psw(); break; // put partial registers in the appropriate places case DSP16_YH: - m_st_yh = m_dau_y >> 16; + m_st_yh = m_core->dau_y >> 16; break; case DSP16_A0H: - m_st_ah[0] = u16(u64(m_dau_a[0]) >> 16); + m_st_ah[0] = u16(u64(m_core->dau_a[0]) >> 16); break; case DSP16_A1H: - m_st_ah[1] = u16(u64(m_dau_a[1]) >> 16); + m_st_ah[1] = u16(u64(m_core->dau_a[1]) >> 16); break; case DSP16_YL: - m_st_yl = u16(u32(m_dau_y)); + m_st_yl = u16(u32(m_core->dau_y)); break; case DSP16_A0L: - m_st_al[0] = u16(u64(m_dau_a[0])); + m_st_al[0] = u16(u64(m_core->dau_a[0])); break; case DSP16_A1L: - m_st_al[1] = u16(u64(m_dau_a[1])); + m_st_al[1] = u16(u64(m_core->dau_a[1])); break; } } @@ -621,10 +596,10 @@ void dsp16_device_base::state_string_export(device_state_entry const &entry, std case STATE_GENFLAGS: str = util::string_format( "%s%s%s%s", - dau_psw_lmi() ? "LMI " : "", - dau_psw_leq() ? "LEQ " : "", - dau_psw_llv() ? "LLV " : "", - dau_psw_lmv() ? "LMV " : ""); + m_core->dau_psw_lmi() ? "LMI " : "", + m_core->dau_psw_leq() ? "LEQ " : "", + m_core->dau_psw_llv() ? "LLV " : "", + m_core->dau_psw_lmv() ? "LMV " : ""); break; } } @@ -655,28 +630,28 @@ dsp16_disassembler::cpu::predicate dsp16_device_base::check_con(offs_t pc, u16 o switch (con >> 1) { case 0x0: // mi/pl - result = dau_psw_lmi(); + result = m_core->dau_psw_lmi(); break; case 0x1: // eq/ne - result = dau_psw_leq(); + result = m_core->dau_psw_leq(); break; case 0x2: // lvs/lvc - result = dau_psw_llv(); + result = m_core->dau_psw_llv(); break; case 0x3: // mvs/mvc - result = dau_psw_lmv(); + result = m_core->dau_psw_lmv(); break; case 0x4: // heads/tails return predicate::INDETERMINATE; // FIXME: implement PRNG case 0x5: // c0ge/c0lt case 0x6: // c1ge/c1lt - result = 0 <= m_dau_c[(con >> 1) - 0x05]; + result = 0 <= m_core->dau_c[(con >> 1) - 0x05]; break; case 0x7: // true/false result = true; break; case 0x8: // gt/le - result = !dau_psw_lmi() && !dau_psw_leq(); + result = !m_core->dau_psw_lmi() && !m_core->dau_psw_leq(); break; default: // Reserved return predicate::INDETERMINATE; @@ -729,7 +704,7 @@ inline void dsp16_device_base::execute_one_rom() switch (m_phase) { case phase::PURGE: - fetch_addr = m_xaau_pc; + fetch_addr = m_core->xaau_pc; m_phase = phase::OP1; break; @@ -815,9 +790,9 @@ inline void dsp16_device_base::execute_one_rom() (pio_int_enable() && pio_int_status()) ? " INT" : "", m_st_pcbase); set_iack(FLAGS_IACK_SET); - fetch_addr = (m_xaau_pc & 0xf000U) | ((m_xaau_pc + 1) & 0x0fffU); + fetch_addr = m_core->xaau_next_pc(); m_int_enable[0] = m_int_enable[1]; - m_xaau_pc = 0x0001U; + m_core->xaau_pc = 0x0001U; m_phase = phase::PURGE; break; } @@ -825,7 +800,7 @@ inline void dsp16_device_base::execute_one_rom() } // normal opcode execution - fetch_addr = set_xaau_pc_offset(m_xaau_pc + 1); + fetch_addr = set_xaau_pc_offset(m_core->xaau_pc + 1); m_int_enable[0] = m_int_enable[1]; switch (op >> 11) { @@ -836,7 +811,7 @@ inline void dsp16_device_base::execute_one_rom() if (check_predicate()) { if (BIT(op, 15)) - m_xaau_pr = m_xaau_pc; + m_core->xaau_pr = m_core->xaau_pc; set_xaau_pc_offset(op_ja(op)); } m_phase = phase::PURGE; @@ -856,28 +831,28 @@ inline void dsp16_device_base::execute_one_rom() case 0x05: // F1 ; Z : aT[l] { fetch_target = nullptr; - s64 const d(dau_f1(op)); - m_dau_temp = u16(u64(dau_saturate(op_d(~op))) >> (op_x(op) ? 16 : 0)); - op_dau_ad(op) = d; - set_dau_at(op, yaau_read(op)); + 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 0x06: // F1 ; Y - op_dau_ad(op) = dau_f1(op); + m_core->op_dau_ad(op) = m_core->dau_f1(op); yaau_read(op); break; case 0x07: // F1 ; aT[l] = Y - op_dau_ad(op) = dau_f1(op); - set_dau_at(op, yaau_read(op)); + m_core->op_dau_ad(op) = m_core->dau_f1(op); + m_core->dau_set_at(op, yaau_read(op)); break; case 0x08: // aT = R assert(!(op & 0x000fU)); // reserved field? fetch_target = nullptr; - set_dau_at(op, get_r(op)); + m_core->dau_set_at(op, get_r(op)); m_phase = phase::OP2; break; @@ -903,7 +878,7 @@ inline void dsp16_device_base::execute_one_rom() case 0x0d: // Z : R fetch_target = nullptr; - m_dau_temp = get_r(op); + m_core->dau_temp = get_r(op); set_r(op, yaau_read(op)); m_phase = phase::OP2; break; @@ -940,42 +915,42 @@ inline void dsp16_device_base::execute_one_rom() case 0x12: // ifc CON F2 { bool const con(op_dau_con(op, false)); - ++m_dau_c[1]; + ++m_core->dau_c[1]; if (con) { - dau_f2(op); - m_dau_c[2] = m_dau_c[1]; + 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)) - dau_f2(op); + m_core->dau_f2(op); break; case 0x14: // F1 ; Y = y[l] fetch_target = nullptr; - op_dau_ad(op) = dau_f1(op); + m_core->op_dau_ad(op) = m_core->dau_f1(op); m_phase = phase::OP2; break; case 0x15: // F1 ; Z : y[l] fetch_target = nullptr; - op_dau_ad(op) = dau_f1(op); - m_dau_temp = u16(u32(m_dau_y) >> (op_x(op) ? 16 : 0)); - set_dau_y(op, yaau_read(op)); + 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 - op_dau_ad(op) = dau_f1(op); - m_dau_x = yaau_read(op); + 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 - op_dau_ad(op) = dau_f1(op); - set_dau_y(op, yaau_read(op)); + m_core->op_dau_ad(op) = m_core->dau_f1(op); + m_core->dau_set_y(op, yaau_read(op)); break; case 0x18: // goto B @@ -984,24 +959,24 @@ inline void dsp16_device_base::execute_one_rom() { case 0x0: // return if (check_predicate()) - m_xaau_pc = m_xaau_pr; + 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_xaau_pc = m_xaau_pi; + m_core->xaau_pc = m_core->xaau_pi; break; case 0x2: // goto pt if (check_predicate()) - m_xaau_pc = m_xaau_pt; + m_core->xaau_pc = m_core->xaau_pt; break; case 0x3: // call pt if (check_predicate()) { - m_xaau_pr = m_xaau_pc; - m_xaau_pc = m_xaau_pt; + m_core->xaau_pr = m_core->xaau_pc; + m_core->xaau_pc = m_core->xaau_pt; } break; case 0x4: // Reserved @@ -1011,7 +986,7 @@ inline void dsp16_device_base::execute_one_rom() throw emu_fatalerror("DSP16: reserved B value %01X (PC = %04X)\n", op_b(op), m_st_pcbase); } if (m_iack_out) - m_xaau_pi = m_xaau_pc; + m_core->xaau_pi = m_core->xaau_pc; m_phase = phase::PURGE; break; @@ -1019,13 +994,13 @@ inline void dsp16_device_base::execute_one_rom() case 0x1b: // F1 ; y = a1 ; x = *pt++[i] { assert(!(op & 0x000fU)); // reserved field? - s64 const d(dau_f1(op)); - s64 a(m_dau_a[BIT(op, 12)]); + 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_dau_y = u32(u64(a)); - op_dau_ad(op) = d; + 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_xaau_pt); + m_rom_data = m_spaces[AS_PROGRAM]->read_word(m_core->xaau_pt); m_phase = phase::OP2; } break; @@ -1042,11 +1017,11 @@ inline void dsp16_device_base::execute_one_rom() break; case 0x1d: // F1 ; Z : y ; x = *pt++[i] - op_dau_ad(op) = dau_f1(op); - m_dau_temp = s16(m_dau_y >> 16); - m_dau_y = (u32(u16(yaau_read(op))) << 16) | u32(BIT(m_dau_psw, 6) ? u16(u32(m_dau_y)) : u16(0)); + 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_xaau_pt); + m_rom_data = m_spaces[AS_PROGRAM]->read_word(m_core->xaau_pt); m_phase = phase::OP2; break; @@ -1055,10 +1030,10 @@ inline void dsp16_device_base::execute_one_rom() break; case 0x1f: // F1 ; y = Y ; x = *pt++[i] - op_dau_ad(op) = dau_f1(op); - m_dau_y = (u32(u16(yaau_read(op))) << 16) | u32(BIT(m_dau_psw, 6) ? u16(u32(m_dau_y)) : u16(0)); + 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_xaau_pt); + m_rom_data = m_spaces[AS_PROGRAM]->read_word(m_core->xaau_pt); m_phase = phase::OP2; break; @@ -1091,7 +1066,7 @@ inline void dsp16_device_base::execute_one_rom() 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))); - op_dau_ad(op) = dau_f1(op); + m_core->op_dau_ad(op) = m_core->dau_f1(op); break; case 0x05: // F1 ; Z : aT[l] @@ -1106,7 +1081,7 @@ inline void dsp16_device_base::execute_one_rom() break; case 0x0a: // R = N - set_xaau_pc_offset(m_xaau_pc + 1); + set_xaau_pc_offset(m_core->xaau_pc + 1); set_r(op, m_rom_data); break; @@ -1118,14 +1093,14 @@ inline void dsp16_device_base::execute_one_rom() break; case 0x14: // F1 ; Y = y[l] - yaau_write(op, u16(u32(m_dau_y) >> (op_x(op) ? 16 : 0))); + yaau_write(op, m_core->dau_get_y(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] - xaau_increment_pt(op_xaau_increment(op)); - m_dau_x = m_rom_data; + m_core->xaau_increment_pt(op); + m_core->dau_x = m_rom_data; break; case 0x1a: // icall @@ -1143,14 +1118,14 @@ inline void dsp16_device_base::execute_one_rom() (pio_int_enable() && pio_int_status()) ? " INT" : "", m_st_pcbase); set_iack(FLAGS_IACK_SET); - m_xaau_pc = 0x0002U; + m_core->xaau_pc = 0x0002U; } m_phase = phase::PURGE; break; case 0x1d: // F1 ; Z : y ; x = *pt++[i] - xaau_increment_pt(op_xaau_increment(op)); - m_dau_x = m_rom_data; + m_core->xaau_increment_pt(op); + m_core->dau_x = m_rom_data; yaau_write_z(op); break; @@ -1168,7 +1143,7 @@ inline void dsp16_device_base::execute_one_rom() } else { - fetch_addr = m_xaau_pc; + fetch_addr = m_core->xaau_pc; if (cache_load) m_cache_ptr = cache_next; } @@ -1188,7 +1163,7 @@ inline void dsp16_device_base::execute_one_rom() if (phase::OP1 == m_phase) { if (cache::EXECUTE != m_cache_mode) - m_st_pcbase = m_xaau_pc; + m_st_pcbase = m_core->xaau_pc; else m_st_pcbase = (m_cache_pcbase & 0xf000U) | ((m_cache_pcbase + m_cache_ptr) & 0x0fffU); } @@ -1219,27 +1194,27 @@ inline void dsp16_device_base::execute_one_cache() case 0x05: // F1 ; Z : aT[l] { - s64 const d(dau_f1(op)); - m_dau_temp = u16(u64(dau_saturate(op_d(~op))) >> (op_x(op) ? 16 : 0)); - op_dau_ad(op) = d; - set_dau_at(op, yaau_read(op)); + 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 0x06: // F1 ; Y - op_dau_ad(op) = dau_f1(op); + m_core->op_dau_ad(op) = m_core->dau_f1(op); yaau_read(op); break; case 0x07: // F1 ; aT[l] = Y - op_dau_ad(op) = dau_f1(op); - set_dau_at(op, yaau_read(op)); + m_core->op_dau_ad(op) = m_core->dau_f1(op); + m_core->dau_set_at(op, yaau_read(op)); break; case 0x08: // aT = R assert(!(op & 0x000fU)); // reserved field? - set_dau_at(op, get_r(op)); + m_core->dau_set_at(op, get_r(op)); m_phase = phase::OP2; break; @@ -1256,7 +1231,7 @@ inline void dsp16_device_base::execute_one_cache() break; case 0x0d: // Z : R - m_dau_temp = get_r(op); + m_core->dau_temp = get_r(op); set_r(op, yaau_read(op)); m_phase = phase::OP2; break; @@ -1270,84 +1245,84 @@ inline void dsp16_device_base::execute_one_cache() case 0x12: // ifc CON F2 { bool const con(op_dau_con(op, false)); - ++m_dau_c[1]; + ++m_core->dau_c[1]; if (con) { - dau_f2(op); - m_dau_c[2] = m_dau_c[1]; + 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)) - dau_f2(op); + m_core->dau_f2(op); break; case 0x14: // F1 ; Y = y[l] - op_dau_ad(op) = dau_f1(op); + m_core->op_dau_ad(op) = m_core->dau_f1(op); m_phase = phase::OP2; break; case 0x15: // F1 ; Z : y[l] - op_dau_ad(op) = dau_f1(op); - m_dau_temp = u16(u32(m_dau_y) >> (op_x(op) ? 16 : 0)); - set_dau_y(op, yaau_read(op)); + 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 - op_dau_ad(op) = dau_f1(op); - m_dau_x = yaau_read(op); + 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 - op_dau_ad(op) = dau_f1(op); - set_dau_y(op, yaau_read(op)); + 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(dau_f1(op)); - s64 a(m_dau_a[BIT(op, 12)]); + 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_dau_y = u32(u64(a)); - op_dau_ad(op) = d; + 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_xaau_pt); + m_rom_data = m_direct->read_word(m_core->xaau_pt); m_phase = phase::OP2; } else { - xaau_increment_pt(op_xaau_increment(op)); - m_dau_x = m_rom_data; + m_core->xaau_increment_pt(op); + m_core->dau_x = m_rom_data; } } break; case 0x1d: // F1 ; Z : y ; x = *pt++[i] - op_dau_ad(op) = dau_f1(op); - m_dau_temp = s16(m_dau_y >> 16); - m_dau_y = (u32(u16(yaau_read(op))) << 16) | u32(BIT(m_dau_psw, 6) ? u16(u32(m_dau_y)) : u16(0)); - m_rom_data = m_direct->read_word(m_xaau_pt); + 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] - op_dau_ad(op) = dau_f1(op); - m_dau_y = (u32(u16(yaau_read(op))) << 16) | u32(BIT(m_dau_psw, 6) ? u16(u32(m_dau_y)) : u16(0)); + 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_xaau_pt); + m_rom_data = m_direct->read_word(m_core->xaau_pt); m_phase = phase::OP2; } else { - xaau_increment_pt(op_xaau_increment(op)); - m_dau_x = m_rom_data; + m_core->xaau_increment_pt(op); + m_core->dau_x = m_rom_data; } break; @@ -1363,7 +1338,7 @@ inline void dsp16_device_base::execute_one_cache() 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))); - op_dau_ad(op) = dau_f1(op); + m_core->op_dau_ad(op) = m_core->dau_f1(op); break; case 0x05: // F1 ; Z : aT[l] @@ -1385,20 +1360,20 @@ inline void dsp16_device_base::execute_one_cache() break; case 0x14: // F1 ; Y = y[l] - yaau_write(op, u16(u32(m_dau_y) >> (op_x(op) ? 16 : 0))); + yaau_write(op, m_core->dau_get_y(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); - xaau_increment_pt(op_xaau_increment(op)); - m_dau_x = m_rom_data; + m_core->xaau_increment_pt(op); + m_core->dau_x = m_rom_data; break; case 0x1d: // F1 ; Z : y ; x = *pt++[i] - xaau_increment_pt(op_xaau_increment(op)); - m_dau_x = m_rom_data; + m_core->xaau_increment_pt(op); + m_core->dau_x = m_rom_data; yaau_write_z(op); break; @@ -1426,8 +1401,8 @@ inline void dsp16_device_base::execute_one_cache() { // overlapped fetch of next instruction from ROM m_cache_mode = cache::NONE; - m_cache[m_cache_ptr = 0] = m_direct->read_word(m_xaau_pc); - m_st_pcbase = m_xaau_pc; + m_cache[m_cache_ptr = 0] = m_direct->read_word(m_core->xaau_pc); + m_st_pcbase = m_core->xaau_pc; } else { @@ -1458,7 +1433,7 @@ inline void dsp16_device_base::overlap_rom_data_read() 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_rom_data = m_direct->read_word(m_xaau_pt); + m_rom_data = m_direct->read_word(m_core->xaau_pt); break; } } @@ -1470,49 +1445,48 @@ inline void dsp16_device_base::yaau_short_immediate_load(u16 op) switch (r) { case 0x0: // j - m_yaau_j = m | ((m & m_yaau_sign) ? ~m_yaau_mask : 0); + m_core->yaau_j = m | ((m & m_core->yaau_sign) ? ~m_core->yaau_mask : 0); break; case 0x1: // k - m_yaau_k = m | ((m & m_yaau_sign) ? ~m_yaau_mask : 0); + m_core->yaau_k = m | ((m & m_core->yaau_sign) ? ~m_core->yaau_mask : 0); break; case 0x2: // rb - m_yaau_rb = m; + m_core->yaau_rb = m; break; case 0x3: // re - m_yaau_re = m; + m_core->yaau_re = m; break; case 0x4: // r0 case 0x5: // r1 case 0x6: // r2 case 0x7: // r3 - m_yaau_r[r & 0x0003U] = m; + m_core->yaau_r[r & 0x0003U] = m; break; } } inline s16 dsp16_device_base::yaau_read(u16 op) { - s16 const result(m_spaces[AS_DATA]->read_word(op_yaau_r(op))); - yaau_postmodify_r(op); + s16 const result(m_spaces[AS_DATA]->read_word(m_core->op_yaau_r(op))); + m_core->yaau_postmodify_r(op); return result; } inline void dsp16_device_base::yaau_write(u16 op, s16 value) { - m_spaces[AS_DATA]->write_word(op_yaau_r(op), value); - yaau_postmodify_r(op); + m_spaces[AS_DATA]->write_word(m_core->op_yaau_r(op), value); + m_core->yaau_postmodify_r(op); } void dsp16_device_base::yaau_write_z(u16 op) { - u16 &r(op_yaau_r(op)); - m_spaces[AS_DATA]->write_word(r, m_dau_temp); + u16 &r(m_core->op_yaau_r(op)); + m_spaces[AS_DATA]->write_word(r, m_core->dau_temp); switch (op & 0x0003U) { case 0x0: // *rNzp - // TODO: does virtual shift register addressing apply here? - if (m_yaau_re && (m_yaau_re == r)) - r = m_yaau_rb; + if (m_core->yaau_re && (m_core->yaau_re == r)) + r = m_core->yaau_rb; else ++r; break; @@ -1522,134 +1496,10 @@ void dsp16_device_base::yaau_write_z(u16 op) r += 2; break; case 0x3: // *rNjk; - r += m_yaau_k; - break; - } - r &= m_yaau_mask; -} - -inline u64 dsp16_device_base::dau_f1(u16 op) -{ - s64 const &s(op_dau_as(op)); - s64 d(0); - switch (op_f1(op)) - { - case 0x0: // aD = p ; p = x*y - d = get_dau_p_aligned(); - m_dau_p = m_dau_x * (m_dau_y >> 16); - break; - case 0x1: // aD = aS + p ; p = x*y - d = s + get_dau_p_aligned(); - m_dau_p = m_dau_x * (m_dau_y >> 16); - break; - case 0x2: // p = x*y - m_dau_p = m_dau_x * (m_dau_y >> 16); - return op_dau_ad(op); - case 0x3: // aD = aS - p ; p = x*y - d = s - get_dau_p_aligned(); - m_dau_p = m_dau_x * (m_dau_y >> 16); - break; - case 0x4: // aD = p - d = get_dau_p_aligned(); - break; - case 0x5: // aD = aS + p - d = s + get_dau_p_aligned(); - break; - case 0x6: // NOP - return op_dau_ad(op); - case 0x7: // aD = aS - p - d = s - get_dau_p_aligned(); - break; - case 0x8: // aD = aS | y - d = s | m_dau_y; - break; - case 0x9: // aD = aS ^ y - d = s ^ m_dau_y; - break; - case 0xa: // aS & y - set_dau_psw_flags(s & m_dau_y); - return op_dau_ad(op); - case 0xb: // aS - y - set_dau_psw_flags(s - m_dau_y); - return op_dau_ad(op); - case 0xc: // aD = y - d = m_dau_y; - break; - case 0xd: // aD = aS + y - d = s + m_dau_y; - break; - case 0xe: // aD = aS & y - d = s & m_dau_y; - break; - case 0xf: // aD = aS - y - d = s - m_dau_y; - break; - } - return set_dau_psw_flags(d); -} - -inline void dsp16_device_base::dau_f2(u16 op) -{ - s64 const &s(op_dau_as(op)); - s64 &d(op_dau_ad(op)); - switch (op_f2(op)) - { - case 0x0: // aD = aS >> 1 - d = s >> 1; - break; - case 0x1: // aD = aS << 1 - d = s32(u32(u64(s)) << 1); - break; - case 0x2: // aD = aS >> 4 - d = s >> 4; - break; - case 0x3: // aD = aS << 4 - d = s32(u32(u64(s)) << 4); - break; - case 0x4: // aD = aS >> 8 - d = s >> 8; - break; - case 0x5: // aD = aS << 8 - d = s32(u32(u64(s)) << 8); - break; - case 0x6: // aD = aS >> 16 - d = s >> 16; - break; - case 0x7: // aD = aS << 16 - d = s32(u32(u64(s)) << 16); - break; - case 0x8: // aD = p - d = get_dau_p_aligned(); - break; - case 0x9: // aDh = aSh + 1 - d = s64(s32(u32(u64(s)) & ~((u32(1) << 16) - 1))) + (s32(1) << 16); - if (BIT(m_dau_auc, op_s(op) + 4)) - d |= op_dau_ad(op) & ((s64(1) << 16) - 1); - break; - case 0xa: // Reserved - throw emu_fatalerror("DSP16: reserved F2 value %01X (PC = %04X)\n", op_f2(op), m_st_pcbase); - case 0xb: // aD = rnd(aS) - // FIXME: behaviour is not clear - // p 3-13: "Round upper 20 bits of accumulator." - // p 3-14: "The contents of the source accumulator, aS, are rounded to 16 bits, and the sign-extended result is placed in aD[35 - 16] with zeroes in aD[15 - 0]." - // It presumably rounds to nearest, but does it yield a 16-bit or 20-bit result, and what does it do about overflow? - d = (s + ((0 > s) ? -(s16(1) << 15) : (s16(1) << 15))) & ~((u64(1) << 16) - 1); - break; - case 0xc: // aD = y - d = m_dau_y; - break; - case 0xd: // aD = aS + 1 - d = s + 1; - break; - case 0xe: // aD = aS - d = s; - break; - case 0xf: // aD = -aS - // FIXME: does this detect negation of largest negative number as overflow? - d = -s; + r += m_core->yaau_k; break; } - d = set_dau_psw_flags(d); + r &= m_core->yaau_mask; } /*********************************************************************** @@ -1707,10 +1557,10 @@ inline bool dsp16_device_base::check_predicate() inline u16 &dsp16_device_base::set_xaau_pc_offset(u16 offset) { - m_xaau_pc = (m_xaau_pc & XAAU_I_EXT) | (offset & XAAU_I_MASK); + m_core->xaau_pc = (m_core->xaau_pc & XAAU_I_EXT) | (offset & XAAU_I_MASK); if (m_iack_out) - m_xaau_pi = m_xaau_pc; - return m_xaau_pc; + m_core->xaau_pi = m_core->xaau_pc; + return m_core->xaau_pc; } inline s16 dsp16_device_base::get_r(u16 op) @@ -1721,38 +1571,38 @@ inline s16 dsp16_device_base::get_r(u16 op) case 0x01: // r1 (u) case 0x02: // r2 (u) case 0x03: // r3 (u) - return m_yaau_r[op_r(op)]; + return m_core->yaau_r[op_r(op)]; case 0x04: // j (s) - return m_yaau_j; + return m_core->yaau_j; case 0x05: // k (s) - return m_yaau_k; + return m_core->yaau_k; case 0x06: // rb (u) - return m_yaau_rb; + return m_core->yaau_rb; case 0x07: // re (u) - return m_yaau_re; + return m_core->yaau_re; case 0x08: // pt - return m_xaau_pt; + return m_core->xaau_pt; case 0x09: // pr - return m_xaau_pr; + return m_core->xaau_pr; case 0x0a: // pi - return m_xaau_pi; + return m_core->xaau_pi; case 0x0b: // i (s) - return m_xaau_i; + return m_core->xaau_i; case 0x10: // x - return m_dau_x; + return m_core->dau_x; case 0x11: // y - return u16(u32(m_dau_y >> 16)); + return u16(u32(m_core->dau_y >> 16)); case 0x12: // yl - return u16(u32(m_dau_y)); + return u16(u32(m_core->dau_y)); break; case 0x13: // auc (u) - return m_dau_auc; + return m_core->dau_auc; case 0x14: // psw - return m_dau_psw = (m_dau_psw & 0xfe10U) | (u16(u64(m_dau_a[0]) >> 32) & 0x000fU) | (u16(u64(m_dau_a[1]) >> 27) & 0x01e0U); + return m_core->dau_export_psw(); case 0x15: // c0 (s) case 0x16: // c1 (s) case 0x17: // c2 (s) - return m_dau_c[op_r(op) - 0x15]; + return m_core->dau_c[op_r(op) - 0x15]; case 0x18: // sioc return m_sio_sioc; case 0x19: // srta @@ -1782,55 +1632,54 @@ inline void dsp16_device_base::set_r(u16 op, s16 value) case 0x01: // r1 (u) case 0x02: // r2 (u) case 0x03: // r3 (u) - m_yaau_r[op_r(op)] = value & m_yaau_mask; + m_core->yaau_r[op_r(op)] = value & m_core->yaau_mask; break; case 0x04: // j (s) - m_yaau_j = (value & m_yaau_mask) | ((value & m_yaau_sign) ? ~m_yaau_mask : 0); + m_core->yaau_set_j(value); break; case 0x05: // k (s) - m_yaau_k = (value & m_yaau_mask) | ((value & m_yaau_sign) ? ~m_yaau_mask : 0); + m_core->yaau_set_k(value); break; case 0x06: // rb (u) - m_yaau_rb = value & m_yaau_mask; + m_core->yaau_set_rb(value); break; case 0x07: // re (u) - m_yaau_re = value & m_yaau_mask; + m_core->yaau_set_re(value); break; case 0x08: // pt - m_xaau_pt = value; + m_core->xaau_pt = value; break; case 0x09: // pr - m_xaau_pr = value; + m_core->xaau_pr = value; break; case 0x0a: // pi // FIXME: reset PRNG if (!m_iack_out) - m_xaau_pi = value; + m_core->xaau_pi = value; break; case 0x0b: // i (s) - m_xaau_i = (value & XAAU_I_MASK) | ((value & XAAU_I_SIGN) ? XAAU_I_EXT : 0); + m_core->xaau_i = (value & XAAU_I_MASK) | ((value & XAAU_I_SIGN) ? XAAU_I_EXT : 0); break; case 0x10: // x - m_dau_x = value; + m_core->dau_x = value; break; case 0x11: // y - m_dau_y = (u32(u16(value)) << 16) | u32(BIT(m_dau_auc, 6) ? u16(u32(m_dau_y)) : u16(0)); + m_core->dau_set_y(value); break; case 0x12: // yl - m_dau_y = (m_dau_y & 0xffff'0000) | u32(u16(value)); + m_core->dau_set_yl(value); break; case 0x13: // auc (u) - m_dau_auc = u8(value & 0x007f); + m_core->dau_auc = u8(value & 0x007f); break; case 0x14: // psw - m_dau_psw = value; - m_dau_a[0] = u64(u32(m_dau_a[0])) | (u64(value & 0x000fU) << 32) | (BIT(value, 3) ? DAU_A_EXT : 0U); - m_dau_a[1] = u64(u32(m_dau_a[1])) | (u64(value & 0x01e0U) << 27) | (BIT(value, 8) ? DAU_A_EXT : 0U); + m_core->dau_psw = value; + m_core->dau_import_psw(); break; case 0x15: // c0 (s) case 0x16: // c1 (s) case 0x17: // c2 (s) - m_dau_c[op_r(op) - 0x15] = u8(u16(value)); + m_core->dau_c[op_r(op) - 0x15] = u8(u16(value)); break; case 0x18: // sioc sio_sioc_write(value); @@ -1860,99 +1709,12 @@ inline void dsp16_device_base::set_r(u16 op, s16 value) } } -inline void dsp16_device_base::yaau_postmodify_r(u16 op) -{ - u16 &r(op_yaau_r(op)); - switch (op & 0x0003U) - { - case 0x0: // *rN - break; - case 0x1: // *rN++ - if (m_yaau_re && (m_yaau_re == r)) - r = m_yaau_rb; - else - ++r; - break; - case 0x2: // *rN-- - --r; - break; - case 0x3: // *rN++j - r += m_yaau_j; - break; - } - r &= m_yaau_mask; -} - -inline void dsp16_device_base::set_dau_y(u16 op, s16 value) -{ - if (op_x(op)) - { - bool const clear(!BIT(m_dau_psw, 6)); - m_dau_y = (u32(u16(value)) << 16) | u32(clear ? u16(0) : u16(u32(m_dau_y))); - } - else - { - m_dau_y = (m_dau_y & ~((s32(1) << 16) - 1)) | u32(u16(value)); - } -} - s64 dsp16_device_base::dau_saturate(u16 a) const { - if (dau_auc_sat(a)) - return m_dau_a[a]; - else - return std::min(std::max(m_dau_a[a], std::numeric_limits::min()), std::numeric_limits::max()); -} - -inline void dsp16_device_base::set_dau_at(u16 op, s16 value) -{ - s64 &at(op_dau_at(op)); - if (op_x(op)) - { - bool const clear(!BIT(m_dau_psw, 4 + op_d(~op))); - at = s32((u32(u16(value)) << 16) | u32(clear ? u16(0) : u16(u64(at)))); - } - else - { - at = (at & ~((s64(1) << 16) - 1)) | u64(u16(value)); - } -} - -inline u64 dsp16_device_base::set_dau_psw_flags(s64 d) -{ - m_dau_psw &= 0x0fffU; - bool const negative(d & DAU_A_SIGN); - if (negative) - m_dau_psw |= 0x8000U; - if (!(d & DAU_A_MASK)) - m_dau_psw |= 0x4000U; - if ((d >> 36) != (negative ? -1 : 0)) - m_dau_psw |= 0x2000U; - if (((d >> 32) & ((1 << 4) - 1)) != (BIT(d, 31) ? 15 : 0)) - m_dau_psw |= 0x1000U; - if (negative) - return d | DAU_A_EXT; + if (m_core->dau_auc_sat(a)) + return m_core->dau_a[a]; else - return d & DAU_A_MASK; -} - -inline u64 dsp16_device_base::get_dau_p_aligned() const -{ - // TODO: manual is contradictory - // p 2-10: "Bits 1 and 2 of the accumulator are not changed by the load of the accumulator with the data in p, since 00 is added to or copied into these accumulator bits as indicated in Figure 2-8." - // I'm reading this as copying p to aD clears the low two bits, but adding it leaves them unchanged. - switch (dau_auc_align()) - { - case 0x0: - return m_dau_p; - case 0x1: - return m_dau_p >> 2; - case 0x2: - return u64(m_dau_p) << 2; - case 0x3: - default: - throw emu_fatalerror("DSP16: reserved ALIGN value %01X (PC = %04X)\n", dau_auc_align(), m_st_pcbase); - } + return std::min(std::max(m_core->dau_a[a], std::numeric_limits::min()), std::numeric_limits::max()); } inline bool dsp16_device_base::op_dau_con(u16 op, bool inc) @@ -1962,23 +1724,23 @@ inline bool dsp16_device_base::op_dau_con(u16 op, bool inc) switch (con >> 1) { case 0x0: // mi/pl - result = dau_psw_lmi(); + result = m_core->dau_psw_lmi(); break; case 0x1: // eq/ne - result = dau_psw_leq(); + result = m_core->dau_psw_leq(); break; case 0x2: // lvs/lvc - result = dau_psw_llv(); + result = m_core->dau_psw_llv(); break; case 0x3: // mvs/mvc - result = dau_psw_lmv(); + result = m_core->dau_psw_lmv(); break; case 0x4: // heads/tails throw emu_fatalerror("DSP16: unimplemented CON value %02X (PC = %04X)\n", con, m_st_pcbase); case 0x5: // c0ge/c0lt case 0x6: // c1ge/c1lt { - s8 &c(m_dau_c[(con >> 1) - 0x05]); + s8 &c(m_core->dau_c[(con >> 1) - 0x05]); result = 0 <= c; if (inc) ++c; @@ -1988,7 +1750,7 @@ inline bool dsp16_device_base::op_dau_con(u16 op, bool inc) result = true; break; case 0x8: // gt/le - result = !dau_psw_lmi() && !dau_psw_leq(); + result = !m_core->dau_psw_lmi() && !m_core->dau_psw_leq(); break; default: // Reserved throw emu_fatalerror("DSP16: reserved CON value %02X (PC = %04X)\n", con, m_st_pcbase); diff --git a/src/devices/cpu/dsp16/dsp16.h b/src/devices/cpu/dsp16/dsp16.h index b811feabea6..5e15b42e7f8 100644 --- a/src/devices/cpu/dsp16/dsp16.h +++ b/src/devices/cpu/dsp16/dsp16.h @@ -12,6 +12,9 @@ #include "dsp16dis.h" +#include "cpu/drccache.h" + +#include #include @@ -124,6 +127,7 @@ protected: // device_t implementation virtual void device_resolve_objects() override; virtual void device_start() override; + virtual void device_stop() override; virtual void device_reset() override; // device_execute_interface implementation @@ -163,6 +167,12 @@ private: DSP16_YH, DSP16_A0H, DSP16_A1H, DSP16_YL, DSP16_A0L, DSP16_A1L }; + // recompiler setup + enum : size_t + { + CACHE_SIZE = 1U * 1024 * 1024 + }; + // masks for registers that aren't power-of-two sizes enum : s16 { @@ -214,7 +224,11 @@ private: friend sio_flags &operator|=(sio_flags &, sio_flags); // recompiler helpers + class core_state; class frontend; + class recompiler; + using core_state_ptr = std::unique_ptr; + using recompiler_ptr = std::unique_ptr; // internal address maps void program_map(address_map &map); @@ -227,8 +241,6 @@ private: s16 yaau_read(u16 op); void yaau_write(u16 op, s16 value); void yaau_write_z(u16 op); - u64 dau_f1(u16 op); - void dau_f2(u16 op); // inline helpers static bool op_interruptible(u16 op); @@ -236,25 +248,11 @@ private: flags &set_predicate(flags predicate) { return m_flags = (m_flags & ~FLAGS_PRED_MASK) | (predicate & FLAGS_PRED_MASK); } flags &set_iack(flags iack) { return m_flags = (m_flags & ~FLAGS_IACK_MASK) | (iack & FLAGS_IACK_MASK); } u16 &set_xaau_pc_offset(u16 offset); - void xaau_increment_pt(s16 increment) { m_xaau_pt = (m_xaau_pt & XAAU_I_EXT) | ((m_xaau_pt + increment) & XAAU_I_MASK); } s16 get_r(u16 op); void set_r(u16 op, s16 value); - void yaau_postmodify_r(u16 op); - void set_dau_y(u16 op, s16 value); s64 dau_saturate(u16 a) const; - void set_dau_at(u16 op, s16 value); - u64 set_dau_psw_flags(s64 d); - u64 get_dau_p_aligned() const; bool op_dau_con(u16 op, bool inc); - // flag accessors - bool dau_auc_sat(u16 a) const { return bool(BIT(m_dau_auc, 2 + a)); } - u16 dau_auc_align() const { return m_dau_auc & 0x0003U; } - bool dau_psw_lmi() const { return bool(BIT(m_dau_psw, 15)); } - bool dau_psw_leq() const { return bool(BIT(m_dau_psw, 14)); } - bool dau_psw_llv() const { return bool(BIT(m_dau_psw, 13)); } - bool dau_psw_lmv() const { return bool(BIT(m_dau_psw, 12)); } - // opcode field handling static constexpr u16 op_ja(u16 op) { return op & 0x0fffU; } static constexpr u16 op_b(u16 op) { return (op >> 8) & 0x0007U; } @@ -267,11 +265,6 @@ private: static constexpr u16 op_con(u16 op) { return op & 0x001fU; } static constexpr u16 op_ni(u16 op) { return (op >> 7) & 0x000fU; } static constexpr u16 op_k(u16 op) { return op & 0x007fU; } - s16 op_xaau_increment(u16 op) const { return op_x(op) ? m_xaau_i : 1; } - u16 &op_yaau_r(u16 op) { return m_yaau_r[(op >> 2) & 0x0003U]; } - s64 &op_dau_as(u16 op) { return m_dau_a[op_s(op)]; } - s64 &op_dau_ad(u16 op) { return m_dau_a[op_d(op)]; } - s64 &op_dau_at(u16 op) { return m_dau_a[op_d(~op)]; } // serial I/O bool sio_ld_ick() const { return !BIT(m_sio_sioc, 9); } @@ -323,15 +316,18 @@ private: // configuration address_space_config const m_space_config[3]; - u16 const m_yaau_mask; - u16 const m_yaau_sign; + u8 const m_yaau_bits; // memory system access address_space *m_spaces[3]; direct_read_data<-1> *m_direct; + // recompiler stuff + drc_cache m_drc_cache; + core_state_ptr m_core; + recompiler_ptr m_recompiler; + // execution state - int m_icount; cache m_cache_mode; phase m_phase; u8 m_int_enable[2]; @@ -358,30 +354,6 @@ private: u8 m_pids_out; // parallel input data strobe (sampled on rising edge) u8 m_pods_out; // parallel output data strobe - // XAAU - ROM Address Arithmetic Unit - u16 m_xaau_pc; // 16 bits unsigned - u16 m_xaau_pt; // 16 bits unsigned - u16 m_xaau_pr; // 16 bits unsigned - u16 m_xaau_pi; // 16 bits unsigned - s16 m_xaau_i; // 12 bits signed - - // YAAU - RAM Address Arithmetic Unit - u16 m_yaau_r[4]; // 9/16 bits unsigned - u16 m_yaau_rb; // 9/16 bits unsigned - u16 m_yaau_re; // 9/16 bits unsigned - s16 m_yaau_j; // 9/16 bits signed - s16 m_yaau_k; // 9/16 bits signed - - // DAU - Data Arithmetic Unit - s16 m_dau_x; // 16 bits signed - s32 m_dau_y; // 32 bits signed - s32 m_dau_p; // 32 bits signed - s64 m_dau_a[2]; // 36 bits signed - s8 m_dau_c[3]; // 8 bits signed - u8 m_dau_auc; // 7 bits unsigned - u16 m_dau_psw; // 16 bits - s16 m_dau_temp; // 16 bits - // SIO - Serial I/O u16 m_sio_sioc; // 10 bits u16 m_sio_obuf; // 16 bits diff --git a/src/devices/cpu/dsp16/dsp16core.cpp b/src/devices/cpu/dsp16/dsp16core.cpp new file mode 100644 index 00000000000..53fb2eca4cd --- /dev/null +++ b/src/devices/cpu/dsp16/dsp16core.cpp @@ -0,0 +1,38 @@ +// license:BSD-3-Clause +// copyright-holders:Vas Crabb +/*************************************************************************** + + WE|AT&T DSP16 series core state + +***************************************************************************/ + +#include "dsp16core.h" + + +/*********************************************************************** + setup +***********************************************************************/ + +void dsp16_device_base::core_state::register_save_items(device_t &host) +{ + host.save_item(NAME(xaau_pc)); + host.save_item(NAME(xaau_pt)); + host.save_item(NAME(xaau_pr)); + host.save_item(NAME(xaau_pi)); + host.save_item(NAME(xaau_i)); + + host.save_item(NAME(yaau_r)); + host.save_item(NAME(yaau_rb)); + host.save_item(NAME(yaau_re)); + host.save_item(NAME(yaau_j)); + host.save_item(NAME(yaau_k)); + + host.save_item(NAME(dau_x)); + host.save_item(NAME(dau_y)); + host.save_item(NAME(dau_p)); + host.save_item(NAME(dau_a)); + host.save_item(NAME(dau_c)); + host.save_item(NAME(dau_auc)); + host.save_item(NAME(dau_psw)); + host.save_item(NAME(dau_temp)); +} diff --git a/src/devices/cpu/dsp16/dsp16core.h b/src/devices/cpu/dsp16/dsp16core.h new file mode 100644 index 00000000000..5268c2815d7 --- /dev/null +++ b/src/devices/cpu/dsp16/dsp16core.h @@ -0,0 +1,116 @@ +// license:BSD-3-Clause +// copyright-holders:Vas Crabb +/*************************************************************************** + + WE|AT&T DSP16 series core state + +***************************************************************************/ +#ifndef MAME_CPU_DSP16_DSP16CORE_H +#define MAME_CPU_DSP16_DSP16CORE_H + +#pragma once + +#include "dsp16.h" + + +class dsp16_device_base::core_state +{ +public: + // construction/destruction + constexpr core_state(u8 yaau_bits) : yaau_mask(u16((u32(1) << yaau_bits) - 1)), yaau_sign(u16(1) << (yaau_bits - 1)) { } + ~core_state() = default; + + // setup + void register_save_items(device_t &host); + + // execution state helpers + constexpr bool icount_remaining() const { return 0 < icount; } + void decrement_icount() { --icount; } + + // XAAU helpers + constexpr u16 xaau_next_pc() const { return (xaau_pc & XAAU_I_EXT) | ((xaau_pc + 1) & XAAU_I_MASK); } + void xaau_increment_pt(u16 op) { xaau_pt = (xaau_pt & XAAU_I_EXT) | ((xaau_pt + op_xaau_increment(op)) & XAAU_I_MASK); } + void xaau_extend_i() { xaau_i = (xaau_i & XAAU_I_MASK) | ((xaau_i & XAAU_I_SIGN) ? XAAU_I_EXT : 0); } + + // YAAU helpers + u16 &yaau_postmodify_r(u16 op); + s16 &yaau_set_j(s16 value) { return yaau_j = yaau_extend(value); } + s16 &yaau_set_k(s16 value) { return yaau_k = yaau_extend(value); } + u16 &yaau_set_rb(s16 value) { return yaau_rb = value & yaau_mask; } + u16 &yaau_set_re(s16 value) { return yaau_re = value & yaau_mask; } + constexpr s16 yaau_extend(s16 value) { return (value & yaau_mask) | ((value & yaau_sign) ? ~yaau_mask : 0); } + s16 &yaau_extend_j() { return yaau_j = yaau_extend(yaau_j); } + s16 &yaau_extend_k() { return yaau_k = yaau_extend(yaau_k); } + + // DAU helpers + u64 dau_f1(u16 op); + void dau_f2(u16 op); + constexpr s16 dau_get_y(u16 op) const { return u16(u32(dau_y) >> (op_x(op) ? 16 : 0)); } + void dau_set_y(u16 op, s16 value) { op_x(op) ? dau_set_y(value) : dau_set_yl(value); } + void dau_set_y(s16 value) { dau_y = (u32(u16(value)) << 16) | u32(BIT(dau_auc, 6) ? u16(u32(dau_y)) : u16(0)); } + void dau_set_yl(s16 value) { dau_y = (dau_y & ~((u32(1) << 16) - 1)) | u16(value); } + s64 &dau_set_at(u16 op, s16 value); + template void dau_extend_a() { dau_a[T] = (dau_a[T] & DAU_A_MASK) | ((dau_a[T] & DAU_A_SIGN) ? DAU_A_EXT : 0); } + u16 dau_export_psw() + { + return dau_psw = (dau_psw & 0xfe10U) | (u16(u64(dau_a[0]) >> 32) & 0x000fU) | (u16(u64(dau_a[1]) >> 27) & 0x01e0U); + } + void dau_import_psw() + { + dau_a[0] = u64(u32(dau_a[0])) | (u64(dau_psw & 0x000fU) << 32) | (BIT(dau_psw, 3) ? DAU_A_EXT : 0U); + dau_a[1] = u64(u32(dau_a[1])) | (u64(dau_psw & 0x01e0U) << 27) | (BIT(dau_psw, 8) ? DAU_A_EXT : 0U); + } + + // DAU flag accessors + constexpr bool dau_auc_sat(u16 a) const { return bool(BIT(dau_auc, 2 + a)); } + constexpr u16 dau_auc_align() const { return dau_auc & 0x0003U; } + constexpr bool dau_psw_lmi() const { return bool(BIT(dau_psw, 15)); } + constexpr bool dau_psw_leq() const { return bool(BIT(dau_psw, 14)); } + constexpr bool dau_psw_llv() const { return bool(BIT(dau_psw, 13)); } + constexpr bool dau_psw_lmv() const { return bool(BIT(dau_psw, 12)); } + + // opcode field handling + constexpr s16 op_xaau_increment(u16 op) const { return op_x(op) ? xaau_i : 1; } + u16 &op_yaau_r(u16 op) { return yaau_r[(op >> 2) & 0x0003U]; } + s64 &op_dau_as(u16 op) { return dau_a[op_s(op)]; } + s64 &op_dau_ad(u16 op) { return dau_a[op_d(op)]; } + s64 &op_dau_at(u16 op) { return dau_a[op_d(~op)]; } + + // configuration + u16 const yaau_mask; + u16 const yaau_sign; + + // execution state + int icount = 0; + + // XAAU - ROM Address Arithmetic Unit + u16 xaau_pc = 0U; // 16 bits unsigned + u16 xaau_pt = 0U; // 16 bits unsigned + u16 xaau_pr = 0U; // 16 bits unsigned + u16 xaau_pi = 0U; // 16 bits unsigned + s16 xaau_i = 0; // 12 bits signed + + // YAAU - RAM Address Arithmetic Unit + u16 yaau_r[4] = { 0U, 0U, 0U, 0U }; // 9/16 bits unsigned + u16 yaau_rb = 0U; // 9/16 bits unsigned + u16 yaau_re = 0U; // 9/16 bits unsigned + s16 yaau_j = 0; // 9/16 bits signed + s16 yaau_k = 0; // 9/16 bits signed + + // DAU - Data Arithmetic Unit + s16 dau_x = 0; // 16 bits signed + s32 dau_y = 0; // 32 bits signed + s32 dau_p = 0; // 32 bits signed + s64 dau_a[2] = { 0, 0 }; // 36 bits signed + s8 dau_c[3] = { 0, 0, 0 }; // 8 bits signed + u8 dau_auc = 0U; // 7 bits unsigned + u16 dau_psw = 0U; // 16 bits + s16 dau_temp = 0; // 16 bits + +private: + // internal helpers + u64 dau_get_p_aligned() const; + u64 dau_set_psw_flags(s64 d); +}; + +#endif // MAME_CPU_DSP16_DSP16CORE_H diff --git a/src/devices/cpu/dsp16/dsp16core.ipp b/src/devices/cpu/dsp16/dsp16core.ipp new file mode 100644 index 00000000000..43920e8aec4 --- /dev/null +++ b/src/devices/cpu/dsp16/dsp16core.ipp @@ -0,0 +1,223 @@ +// license:BSD-3-Clause +// copyright-holders:Vas Crabb +/*************************************************************************** + + WE|AT&T DSP16 series core state + +***************************************************************************/ +#ifndef MAME_CPU_DSP16_DSP16CORE_IPP +#define MAME_CPU_DSP16_DSP16CORE_IPP + +#pragma once + +#include "dsp16core.h" + + +/*********************************************************************** + YAAU helpers +***********************************************************************/ + +inline u16 &dsp16_device_base::core_state::yaau_postmodify_r(u16 op) +{ + u16 &r(op_yaau_r(op)); + switch (op & 0x0003U) + { + case 0x0: // *rN + break; + case 0x1: // *rN++ + r = (yaau_re && (yaau_re == r)) ? yaau_rb : (r + 1); + break; + case 0x2: // *rN-- + --r; + break; + case 0x3: // *rN++j + r += yaau_j; + break; + } + return r &= yaau_mask; +} + +/*********************************************************************** + DAU helpers +***********************************************************************/ + +inline u64 dsp16_device_base::core_state::dau_f1(u16 op) +{ + s64 const &s(op_dau_as(op)); + s64 d(0); + switch (op_f1(op)) + { + case 0x0: // aD = p ; p = x*y + d = dau_get_p_aligned(); + dau_p = dau_x * (dau_y >> 16); + break; + case 0x1: // aD = aS + p ; p = x*y + d = s + dau_get_p_aligned(); + dau_p = dau_x * (dau_y >> 16); + break; + case 0x2: // p = x*y + dau_p = dau_x * (dau_y >> 16); + return op_dau_ad(op); + case 0x3: // aD = aS - p ; p = x*y + d = s - dau_get_p_aligned(); + dau_p = dau_x * (dau_y >> 16); + break; + case 0x4: // aD = p + d = dau_get_p_aligned(); + break; + case 0x5: // aD = aS + p + d = s + dau_get_p_aligned(); + break; + case 0x6: // NOP + return op_dau_ad(op); + case 0x7: // aD = aS - p + d = s - dau_get_p_aligned(); + break; + case 0x8: // aD = aS | y + d = s | dau_y; + break; + case 0x9: // aD = aS ^ y + d = s ^ dau_y; + break; + case 0xa: // aS & y + dau_set_psw_flags(s & dau_y); + return op_dau_ad(op); + case 0xb: // aS - y + dau_set_psw_flags(s - dau_y); + return op_dau_ad(op); + case 0xc: // aD = y + d = dau_y; + break; + case 0xd: // aD = aS + y + d = s + dau_y; + break; + case 0xe: // aD = aS & y + d = s & dau_y; + break; + case 0xf: // aD = aS - y + d = s - dau_y; + break; + } + return dau_set_psw_flags(d); +} + +inline void dsp16_device_base::core_state::dau_f2(u16 op) +{ + s64 const &s(op_dau_as(op)); + s64 &d(op_dau_ad(op)); + switch (op_f2(op)) + { + case 0x0: // aD = aS >> 1 + d = s >> 1; + break; + case 0x1: // aD = aS << 1 + d = s32(u32(u64(s)) << 1); + break; + case 0x2: // aD = aS >> 4 + d = s >> 4; + break; + case 0x3: // aD = aS << 4 + d = s32(u32(u64(s)) << 4); + break; + case 0x4: // aD = aS >> 8 + d = s >> 8; + break; + case 0x5: // aD = aS << 8 + d = s32(u32(u64(s)) << 8); + break; + case 0x6: // aD = aS >> 16 + d = s >> 16; + break; + case 0x7: // aD = aS << 16 + d = s32(u32(u64(s)) << 16); + break; + case 0x8: // aD = p + d = dau_get_p_aligned(); + break; + case 0x9: // aDh = aSh + 1 + d = s64(s32(u32(u64(s)) & ~((u32(1) << 16) - 1))) + (s32(1) << 16); + if (BIT(dau_auc, op_s(op) + 4)) + d |= op_dau_ad(op) & ((s64(1) << 16) - 1); + break; + case 0xa: // Reserved + throw emu_fatalerror("DSP16: reserved F2 value %01X (PC = %04X)\n", op_f2(op), xaau_pc/*FIXME: st_pcbase*/); + case 0xb: // aD = rnd(aS) + // FIXME: behaviour is not clear + // p 3-13: "Round upper 20 bits of accumulator." + // p 3-14: "The contents of the source accumulator, aS, are rounded to 16 bits, and the sign-extended result is placed in aD[35 - 16] with zeroes in aD[15 - 0]." + // It presumably rounds to nearest, but does it yield a 16-bit or 20-bit result, and what does it do about overflow? + d = (s + ((0 > s) ? -(s16(1) << 15) : (s16(1) << 15))) & ~((u64(1) << 16) - 1); + break; + case 0xc: // aD = y + d = dau_y; + break; + case 0xd: // aD = aS + 1 + d = s + 1; + break; + case 0xe: // aD = aS + d = s; + break; + case 0xf: // aD = -aS + // FIXME: does this detect negation of largest negative number as overflow? + d = -s; + break; + } + d = dau_set_psw_flags(d); +} + +inline s64 &dsp16_device_base::core_state::dau_set_at(u16 op, s16 value) +{ + s64 &at(op_dau_at(op)); + if (op_x(op)) + { + bool const clear(!BIT(dau_psw, 4 + op_d(~op))); + return at = s32((u32(u16(value)) << 16) | u32(clear ? u16(0) : u16(u64(at)))); + } + else + { + return at = (at & ~((s64(1) << 16) - 1)) | u64(u16(value)); + } +} + +/*********************************************************************** + internal helpers +***********************************************************************/ + +inline u64 dsp16_device_base::core_state::dau_get_p_aligned() const +{ + // TODO: manual is contradictory + // p 2-10: "Bits 1 and 2 of the accumulator are not changed by the load of the accumulator with the data in p, since 00 is added to or copied into these accumulator bits as indicated in Figure 2-8." + // I'm reading this as copying p to aD clears the low two bits, but adding it leaves them unchanged. + switch (dau_auc_align()) + { + case 0x0: + return dau_p; + case 0x1: + return dau_p >> 2; + case 0x2: + return u64(dau_p) << 2; + case 0x3: + default: + throw emu_fatalerror("DSP16: reserved ALIGN value %01X (PC = %04X)\n", dau_auc_align(), xaau_pc/*FIXME: st_pcbase*/); + } +} + +inline u64 dsp16_device_base::core_state::dau_set_psw_flags(s64 d) +{ + dau_psw &= 0x0fffU; + bool const negative(d & DAU_A_SIGN); + if (negative) + dau_psw |= 0x8000U; + if (!(d & DAU_A_MASK)) + dau_psw |= 0x4000U; + if ((d >> 36) != (negative ? -1 : 0)) + dau_psw |= 0x2000U; + if (((d >> 32) & ((1 << 4) - 1)) != (BIT(d, 31) ? 15 : 0)) + dau_psw |= 0x1000U; + if (negative) + return d | DAU_A_EXT; + else + return d & DAU_A_MASK; +} + +#endif // MAME_CPU_DSP16_DSP16CORE_IPP diff --git a/src/devices/cpu/dsp16/dsp16rc.cpp b/src/devices/cpu/dsp16/dsp16rc.cpp new file mode 100644 index 00000000000..42d174df3e7 --- /dev/null +++ b/src/devices/cpu/dsp16/dsp16rc.cpp @@ -0,0 +1,50 @@ +// license:BSD-3-Clause +// copyright-holders:Vas Crabb +/*************************************************************************** + + WE|AT&T DSP16 series recompiler + + There are a number of easy optimisations: + * The RAM space is entirely internal, so the memory system can be + bypassed if debugging is not enabled. + * The DSP16A has 16-bit YAAU registers, so sign extension can be + elided. + * The same code rarely runs with IACK asserted and clear, allowing + optimisation of PI register accesses and interrupt checks. + * The PSW is rarely accessed directly, so the accumulator guard bits + don't need to be kept in sync (interpreter already does this). + * The DAU flags are used infrequently, so it's far cheaper to + calculate them on-demand rather than preemptively. + * The same code will rarely be run with different AUC modes, so it's + cheaper to make assumptions and recompile if they break. + + There are some more complex optimisations that give good gains: + * Multiplication is free with F1, so code will sometimes multiply + when it doesn't need to - this can be elided. + * Address register accesses can be elided in many cases as the + values can be computed at translation time. + +***************************************************************************/ + +#include "dsp16rc.h" + +#include "cpu/drcumlsh.h" + + +/*********************************************************************** + construction/destruction +***********************************************************************/ + +dsp16_device_base::recompiler::recompiler(dsp16_device_base &host, u32 flags) + : m_host(host) + , m_core(*host.m_core) + , m_frontend(host, COMPILE_BACKWARDS_BYTES, COMPILE_FORWARDS_BYTES, COMPILE_MAX_SEQUENCE) + , m_uml(host, host.m_drc_cache, flags, 2, 16, 0) +{ + (void)m_host; + (void)m_core; +} + +dsp16_device_base::recompiler::~recompiler() +{ +} diff --git a/src/devices/cpu/dsp16/dsp16rc.h b/src/devices/cpu/dsp16/dsp16rc.h new file mode 100644 index 00000000000..d6ce9a77e4f --- /dev/null +++ b/src/devices/cpu/dsp16/dsp16rc.h @@ -0,0 +1,51 @@ +// license:BSD-3-Clause +// copyright-holders:Vas Crabb +/*************************************************************************** + + WE|AT&T DSP16 series recompiler + +***************************************************************************/ +#ifndef MAME_CPU_DSP16_DSP16RC_H +#define MAME_CPU_DSP16_DSP16RC_H + +#pragma once + +#include "dsp16.h" +#include "dsp16fe.h" + +#include "cpu/drcuml.h" + + +class dsp16_device_base::recompiler +{ +public: + // construction/destruction + recompiler(dsp16_device_base &host, u32 flags); + ~recompiler(); + +private: + // compilation boundaries + enum : u32 + { + COMPILE_BACKWARDS_BYTES = 64, + COMPILE_FORWARDS_BYTES = 256, + COMPILE_MAX_INSTRUCTIONS = (COMPILE_BACKWARDS_BYTES / 2) + (COMPILE_FORWARDS_BYTES / 2), + COMPILE_MAX_SEQUENCE = 64 + }; + + enum : int + { + EXEC_OUT_OF_CYCLES, + EXEC_MISSING_CODE, + EXEC_UNMAPPED_CODE, + EXEC_RESET_CACHE + }; + + // host CPU device, frontend to describe instructions, and UML engine + dsp16_device_base &m_host; + core_state &m_core; + frontend m_frontend; + drcuml_state m_uml; +}; + +#endif // MAME_CPU_DSP16_DSP16RC_H -- cgit v1.2.3