diff options
Diffstat (limited to 'src/devices/cpu/sh/sh2.cpp')
-rw-r--r-- | src/devices/cpu/sh/sh2.cpp | 753 |
1 files changed, 192 insertions, 561 deletions
diff --git a/src/devices/cpu/sh/sh2.cpp b/src/devices/cpu/sh/sh2.cpp index c0fab41f9b0..ae8acd76ee4 100644 --- a/src/devices/cpu/sh/sh2.cpp +++ b/src/devices/cpu/sh/sh2.cpp @@ -1,8 +1,8 @@ // license:BSD-3-Clause -// copyright-holders:Juergen Buchmueller +// copyright-holders:Juergen Buchmueller, R. Belmont /***************************************************************************** * - * sh2.c + * sh2.cpp * Portable Hitachi SH-2 (SH7600 family) emulator * * This work is based on <tiraniddo@hotmail.com> C/C++ implementation of @@ -12,276 +12,98 @@ * *****************************************************************************/ -/***************************************************************************** - Changes - 20130129 Angelo Salese - - added illegal opcode exception handling, side effect of some Saturn games - on loading like Feda or Falcom Classics Vol. 1 - (i.e. Master CPU Incautiously transfers memory from CD to work RAM H, and - wipes out Slave CPU program code too while at it). - - 20051129 Mariusz Wojcieszek - - introduced memory_decrypted_read_word() for opcode fetching - - 20050813 Mariusz Wojcieszek - - fixed 64 bit / 32 bit division in division unit - - 20031015 O. Galibert - - dma fixes, thanks to sthief - - 20031013 O. Galibert, A. Giles - - timer fixes - - multi-cpu simplifications - - 20030915 O. Galibert - - fix DMA1 irq vector - - ignore writes to DRCRx - - fix cpu number issues - - fix slave/master recognition - - fix wrong-cpu-in-context problem with the timers - - 20021020 O. Galibert - - DMA implementation, lightly tested - - delay slot in debugger fixed - - add divide box mirrors - - Nicola-ify the indentation - - Uncrapify sh2_internal_* - - Put back nmi support that had been lost somehow - - 20020914 R. Belmont - - Initial SH2 internal timers implementation, based on code by O. Galibert. - Makes music work in galspanic4/s/s2, panic street, cyvern, other SKNS games. - - Fix to external division, thanks to "spice" on the E2J board. - Corrects behavior of s1945ii turret boss. - - 20020302 Olivier Galibert (galibert@mame.net) - - Fixed interrupt in delay slot - - Fixed rotcr - - Fixed div1 - - Fixed mulu - - Fixed negc - - 20020301 R. Belmont - - Fixed external division - - 20020225 Olivier Galibert (galibert@mame.net) - - Fixed interrupt handling - - 20010207 Sylvain Glaize (mokona@puupuu.org) - - - Bug fix in void MOVBM(uint32_t m, uint32_t n) (see comment) - - Support of full 32 bit addressing (RB, RW, RL and WB, WW, WL functions) - reason : when the two high bits of the address are set, access is - done directly in the cache data array. The SUPER KANEKO NOVA SYSTEM - sets the stack pointer here, using these addresses as usual RAM access. - - No real cache support has been added. - - Read/Write memory format correction (_bew to _bedw) (see also SH2 - definition in cpuintrf.c and DasmSH2(..) in sh2dasm.c ) - - 20010623 James Forshaw (TyRaNiD@totalise.net) - - - Modified operation of sh2_exception. Done cause mame irq system is stupid, and - doesnt really seem designed for any more than 8 interrupt lines. - - 20010701 James Forshaw (TyRaNiD@totalise.net) - - - Fixed DIV1 operation. Q bit now correctly generated - - 20020218 Added save states (mokona@puupuu.org) - - *****************************************************************************/ #include "emu.h" #include "sh2.h" -#include "sh2comn.h" #include "sh_dasm.h" -#include "debugger.h" +#include "cpu/drcumlsh.h" //#define VERBOSE 1 #include "logmacro.h" +constexpr int SH2_INT_15 = 15; - - -DEFINE_DEVICE_TYPE(SH1, sh1_device, "sh1", "Hitachi SH-1") -DEFINE_DEVICE_TYPE(SH2, sh2_device, "sh2", "Hitachi SH-2") -DEFINE_DEVICE_TYPE(SH2A, sh2a_device, "sh21", "Hitachi SH-2A") - -/*------------------------------------------------- - sh2_internal_a5 - read handler for - SH2 internal map --------------------------------------------------*/ - -READ32_MEMBER(sh2_device::sh2_internal_a5) -{ - return 0xa5a5a5a5; -} - - -/*------------------------------------------------- - sh2_internal_map - maps SH2 built-ins --------------------------------------------------*/ - - -void sh2_device::sh7604_map(address_map &map) +sh2_device::sh2_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, int cpu_type, address_map_constructor internal_map, int addrlines, uint32_t address_mask) + : sh_common_execution(mconfig, type, tag, owner, clock, ENDIANNESS_BIG, internal_map) + , m_am(address_mask) + , m_program_config("program", ENDIANNESS_BIG, 32, addrlines, 0, internal_map) + , m_decrypted_program_config("decrypted_opcodes", ENDIANNESS_BIG, 32, addrlines, 0) + , m_drcfe(nullptr) { - map(0x40000000, 0xbfffffff).r(FUNC(sh2_device::sh2_internal_a5)); - -// TODO: cps3boot breaks with this enabled. Needs callback -// AM_RANGE(0xc0000000, 0xc0000fff) AM_RAM // cache data array - -// map(0xe0000000, 0xe00001ff).mirror(0x1ffffe00).rw(FUNC(sh2_device::sh7604_r), FUNC(sh2_device::sh7604_w)); - // TODO: internal map takes way too much resources if mirrored with 0x1ffffe00 - // we eventually internalize again via trampoline & sh7604_device - // Also area 0xffff8000-0xffffbfff is for synchronous DRAM mode, - // so this isn't actually a full mirror - // SCI - map(0xfffffe00, 0xfffffe00).rw(FUNC(sh2_device::smr_r), FUNC(sh2_device::smr_w)); - map(0xfffffe01, 0xfffffe01).rw(FUNC(sh2_device::brr_r), FUNC(sh2_device::brr_w)); - map(0xfffffe02, 0xfffffe02).rw(FUNC(sh2_device::scr_r), FUNC(sh2_device::scr_w)); - map(0xfffffe03, 0xfffffe03).rw(FUNC(sh2_device::tdr_r), FUNC(sh2_device::tdr_w)); - map(0xfffffe04, 0xfffffe04).rw(FUNC(sh2_device::ssr_r), FUNC(sh2_device::ssr_w)); - map(0xfffffe05, 0xfffffe05).r(FUNC(sh2_device::rdr_r)); - - // FRC - map(0xfffffe10, 0xfffffe10).rw(FUNC(sh2_device::tier_r), FUNC(sh2_device::tier_w)); - map(0xfffffe11, 0xfffffe11).rw(FUNC(sh2_device::ftcsr_r), FUNC(sh2_device::ftcsr_w)); - map(0xfffffe12, 0xfffffe13).rw(FUNC(sh2_device::frc_r), FUNC(sh2_device::frc_w)); - map(0xfffffe14, 0xfffffe15).rw(FUNC(sh2_device::ocra_b_r), FUNC(sh2_device::ocra_b_w)); - map(0xfffffe16, 0xfffffe16).rw(FUNC(sh2_device::frc_tcr_r), FUNC(sh2_device::frc_tcr_w)); - map(0xfffffe17, 0xfffffe17).rw(FUNC(sh2_device::tocr_r), FUNC(sh2_device::tocr_w)); - map(0xfffffe18, 0xfffffe19).r(FUNC(sh2_device::frc_icr_r)); - - // INTC - map(0xfffffe60, 0xfffffe61).rw(FUNC(sh2_device::iprb_r), FUNC(sh2_device::iprb_w)); - map(0xfffffe62, 0xfffffe63).rw(FUNC(sh2_device::vcra_r), FUNC(sh2_device::vcra_w)); - map(0xfffffe64, 0xfffffe65).rw(FUNC(sh2_device::vcrb_r), FUNC(sh2_device::vcrb_w)); - map(0xfffffe66, 0xfffffe67).rw(FUNC(sh2_device::vcrc_r), FUNC(sh2_device::vcrc_w)); - map(0xfffffe68, 0xfffffe69).rw(FUNC(sh2_device::vcrd_r), FUNC(sh2_device::vcrd_w)); - - map(0xfffffe71, 0xfffffe71).rw(FUNC(sh2_device::drcr_r<0>), FUNC(sh2_device::drcr_w<0>)); - map(0xfffffe72, 0xfffffe72).rw(FUNC(sh2_device::drcr_r<1>), FUNC(sh2_device::drcr_w<1>)); - - // WTC - map(0xfffffe80, 0xfffffe81).rw(FUNC(sh2_device::wtcnt_r), FUNC(sh2_device::wtcnt_w)); - map(0xfffffe82, 0xfffffe83).rw(FUNC(sh2_device::rstcsr_r), FUNC(sh2_device::rstcsr_w)); - - // standby and cache control - map(0xfffffe90, 0xfffffe91).rw(FUNC(sh2_device::fmr_sbycr_r), FUNC(sh2_device::fmr_sbycr_w)); - map(0xfffffe92, 0xfffffe92).rw(FUNC(sh2_device::ccr_r), FUNC(sh2_device::ccr_w)); - - // INTC second section - map(0xfffffee0, 0xfffffee1).rw(FUNC(sh2_device::intc_icr_r), FUNC(sh2_device::intc_icr_w)); - map(0xfffffee2, 0xfffffee3).rw(FUNC(sh2_device::ipra_r), FUNC(sh2_device::ipra_w)); - map(0xfffffee4, 0xfffffee5).rw(FUNC(sh2_device::vcrwdt_r), FUNC(sh2_device::vcrwdt_w)); - - // DIVU - map(0xffffff00, 0xffffff03).rw(FUNC(sh2_device::dvsr_r), FUNC(sh2_device::dvsr_w)); - map(0xffffff04, 0xffffff07).rw(FUNC(sh2_device::dvdnt_r), FUNC(sh2_device::dvdnt_w)); - map(0xffffff08, 0xffffff0b).rw(FUNC(sh2_device::dvcr_r), FUNC(sh2_device::dvcr_w)); - // INTC third section - map(0xffffff0c, 0xffffff0f).rw(FUNC(sh2_device::vcrdiv_r), FUNC(sh2_device::vcrdiv_w)); - // DIVU continued (64-bit plus mirrors) - map(0xffffff10, 0xffffff13).rw(FUNC(sh2_device::dvdnth_r), FUNC(sh2_device::dvdnth_w)); - map(0xffffff14, 0xffffff17).rw(FUNC(sh2_device::dvdntl_r), FUNC(sh2_device::dvdntl_w)); - map(0xffffff18, 0xffffff1b).r(FUNC(sh2_device::dvdnth_r)); - map(0xffffff1c, 0xffffff1f).r(FUNC(sh2_device::dvdntl_r)); - - // DMAC - map(0xffffff80, 0xffffff83).rw(FUNC(sh2_device::sar_r<0>), FUNC(sh2_device::sar_w<0>)); - map(0xffffff84, 0xffffff87).rw(FUNC(sh2_device::dar_r<0>), FUNC(sh2_device::dar_w<0>)); - map(0xffffff88, 0xffffff8b).rw(FUNC(sh2_device::dmac_tcr_r<0>), FUNC(sh2_device::dmac_tcr_w<0>)); - map(0xffffff8c, 0xffffff8f).rw(FUNC(sh2_device::chcr_r<0>), FUNC(sh2_device::chcr_w<0>)); - - map(0xffffff90, 0xffffff93).rw(FUNC(sh2_device::sar_r<1>), FUNC(sh2_device::sar_w<1>)); - map(0xffffff94, 0xffffff97).rw(FUNC(sh2_device::dar_r<1>), FUNC(sh2_device::dar_w<1>)); - map(0xffffff98, 0xffffff9b).rw(FUNC(sh2_device::dmac_tcr_r<1>), FUNC(sh2_device::dmac_tcr_w<1>)); - map(0xffffff9c, 0xffffff9f).rw(FUNC(sh2_device::chcr_r<1>), FUNC(sh2_device::chcr_w<1>)); - - map(0xffffffa0, 0xffffffa3).rw(FUNC(sh2_device::vcrdma_r<0>), FUNC(sh2_device::vcrdma_w<0>)); - map(0xffffffa8, 0xffffffab).rw(FUNC(sh2_device::vcrdma_r<1>), FUNC(sh2_device::vcrdma_w<1>)); - map(0xffffffb0, 0xffffffb3).rw(FUNC(sh2_device::dmaor_r), FUNC(sh2_device::dmaor_w)); - - // BSC - map(0xffffffe0, 0xffffffe3).rw(FUNC(sh2_device::bcr1_r), FUNC(sh2_device::bcr1_w)); - map(0xffffffe4, 0xffffffe7).rw(FUNC(sh2_device::bcr2_r), FUNC(sh2_device::bcr2_w)); - map(0xffffffe8, 0xffffffeb).rw(FUNC(sh2_device::wcr_r), FUNC(sh2_device::wcr_w)); - map(0xffffffec, 0xffffffef).rw(FUNC(sh2_device::mcr_r), FUNC(sh2_device::mcr_w)); - map(0xfffffff0, 0xfffffff3).rw(FUNC(sh2_device::rtcsr_r), FUNC(sh2_device::rtcsr_w)); - map(0xfffffff4, 0xfffffff7).rw(FUNC(sh2_device::rtcnt_r), FUNC(sh2_device::rtcnt_w)); - map(0xfffffff8, 0xfffffffb).rw(FUNC(sh2_device::rtcor_r), FUNC(sh2_device::rtcor_w)); + m_cpu_type = cpu_type; + m_isdrc = allow_drc(); } -void sh2a_device::sh7021_map(address_map &map) +void sh2_device::device_start() { -// fall-back - map(0x05fffe00, 0x05ffffff).rw(FUNC(sh2a_device::sh7021_r), FUNC(sh2a_device::sh7021_w)); // SH-7032H internal i/o -// overrides - map(0x05ffff40, 0x05ffff43).rw(FUNC(sh2a_device::dma_sar0_r), FUNC(sh2a_device::dma_sar0_w)); - map(0x05ffff44, 0x05ffff47).rw(FUNC(sh2a_device::dma_dar0_r), FUNC(sh2a_device::dma_dar0_w)); - map(0x05ffff48, 0x05ffff49).rw(FUNC(sh2a_device::dmaor_r), FUNC(sh2a_device::dmaor_w)); - map(0x05ffff4a, 0x05ffff4b).rw(FUNC(sh2a_device::dma_tcr0_r), FUNC(sh2a_device::dma_tcr0_w)); - map(0x05ffff4e, 0x05ffff4f).rw(FUNC(sh2a_device::dma_chcr0_r), FUNC(sh2a_device::dma_chcr0_w)); -// AM_RANGE(0x07000000, 0x070003ff) AM_RAM AM_SHARE("oram")// on-chip RAM, actually at 0xf000000 (1 kb) -// AM_RANGE(0x0f000000, 0x0f0003ff) AM_RAM AM_SHARE("oram")// on-chip RAM, actually at 0xf000000 (1 kb) -} + sh_common_execution::device_start(); -void sh1_device::sh7032_map(address_map &map) -{ -// fall-back - map(0x05fffe00, 0x05ffffff).rw(FUNC(sh1_device::sh7032_r), FUNC(sh1_device::sh7032_w)); // SH-7032H internal i/o -} + m_decrypted_program = has_space(AS_OPCODES) ? &space(AS_OPCODES) : &space(AS_PROGRAM); + m_decrypted_program->cache(m_cache32); + m_pr16 = [this](offs_t address) -> u16 { return m_cache32.read_word(address); }; + if (m_decrypted_program->endianness() != ENDIANNESS_NATIVE) + m_prptr = [this](offs_t address) -> const void * { + const u16 *ptr = reinterpret_cast<u16 *>(m_cache32.read_ptr(address & ~3)); + if (!(address & 2)) + ptr++; + return ptr; + }; + else + m_prptr = [this](offs_t address) -> const void * { + const u16 *ptr = reinterpret_cast<u16 *>(m_cache32.read_ptr(address & ~3)); + if (address & 2) + ptr++; + return ptr; + }; -sh2_device::sh2_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : sh2_device(mconfig, SH2, tag, owner, clock, CPU_TYPE_SH2, address_map_constructor(FUNC(sh2_device::sh7604_map), this), 32) -{ -} + // internals + save_item(NAME(m_cpu_off)); + save_item(NAME(m_test_irq)); + save_item(NAME(m_irq_line_state)); + save_item(NAME(m_nmi_line_state)); + save_item(NAME(m_internal_irq_vector)); -sh2_device::~sh2_device() -{ -} + state_add(STATE_GENPC, "PC", m_sh2_state->pc).mask(m_am).callimport(); + state_add(STATE_GENPCBASE, "CURPC", m_sh2_state->pc).callimport().noshow(); + m_nmi_line_state = 0; -void sh2_device::device_stop() -{ + drc_start(); } - - - -sh2_device::sh2_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, int cpu_type, address_map_constructor internal_map, int addrlines) - : sh_common_execution(mconfig, type, tag, owner, clock, ENDIANNESS_BIG, internal_map) - , m_program_config("program", ENDIANNESS_BIG, 32, addrlines, 0, internal_map) - , m_decrypted_program_config("decrypted_opcodes", ENDIANNESS_BIG, 32, addrlines, 0) - , m_is_slave(0) - , m_drcfe(nullptr) - , m_debugger_temp(0) +void sh2_device::device_reset() { - m_cpu_type = cpu_type; - m_am = SH12_AM; - m_isdrc = allow_drc(); -} + std::fill(std::begin(m_sh2_state->r), std::end(m_sh2_state->r), 0); + std::fill(std::begin(m_irq_line_state), std::end(m_irq_line_state), 0); -sh2a_device::sh2a_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : sh2_device(mconfig, SH2A, tag, owner, clock, CPU_TYPE_SH2, address_map_constructor(FUNC(sh2a_device::sh7021_map), this), 28) -{ -} + m_sh2_state->pc = m_sh2_state->pr = m_sh2_state->sr = m_sh2_state->gbr = m_sh2_state->vbr = m_sh2_state->mach = m_sh2_state->macl = 0; + m_sh2_state->evec = m_sh2_state->irqsr = 0; + m_sh2_state->ea = m_sh2_state->m_delay = 0; + m_sh2_state->pending_irq = 0; + m_sh2_state->pending_nmi = 0; + m_sh2_state->sleep_mode = 0; + m_sh2_state->internal_irq_level = -1; + m_sh2_state->sr = SH_I; + m_sh2_state->pc = read_long(0); + m_sh2_state->r[15] = read_long(4); -sh1_device::sh1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : sh2_device(mconfig, SH1, tag, owner, clock, CPU_TYPE_SH1, address_map_constructor(FUNC(sh1_device::sh7032_map), this), 28) -{ + m_test_irq = 0; + m_cpu_off = 0; + m_internal_irq_vector = 0; + m_cache_dirty = true; } device_memory_interface::space_config_vector sh2_device::memory_space_config() const { - if(has_configured_map(AS_OPCODES)) - return space_config_vector { + if (has_configured_map(AS_OPCODES)) + return space_config_vector + { std::make_pair(AS_PROGRAM, &m_program_config), std::make_pair(AS_OPCODES, &m_decrypted_program_config) }; else - return space_config_vector { + return space_config_vector + { std::make_pair(AS_PROGRAM, &m_program_config) }; } @@ -291,75 +113,105 @@ std::unique_ptr<util::disasm_interface> sh2_device::create_disassembler() return std::make_unique<sh_disassembler>(false); } -uint8_t sh2_device::RB(offs_t A) +uint8_t sh2_device::read_byte(offs_t offset) { - if((A & 0xf0000000) == 0 || (A & 0xf0000000) == 0x20000000) - return m_program->read_byte(A & SH12_AM); + if ((offset & 0xf0000000) == 0 || (offset & 0xf0000000) == 0x20000000) + return m_program->read_byte(offset & m_am); - return m_program->read_byte(A); + return m_program->read_byte(offset); } -uint16_t sh2_device::RW(offs_t A) +uint16_t sh2_device::read_word(offs_t offset) { - if((A & 0xf0000000) == 0 || (A & 0xf0000000) == 0x20000000) - return m_program->read_word(A & SH12_AM); + if ((offset & 0xf0000000) == 0 || (offset & 0xf0000000) == 0x20000000) + return m_program->read_word(offset & m_am); - return m_program->read_word(A); + return m_program->read_word(offset); } -uint32_t sh2_device::RL(offs_t A) +uint32_t sh2_device::read_long(offs_t offset) { /* 0x20000000 no Cache */ /* 0x00000000 read thru Cache if CE bit is 1 */ - if((A & 0xf0000000) == 0 || (A & 0xf0000000) == 0x20000000) - return m_program->read_dword(A & SH12_AM); + if ((offset & 0xf0000000) == 0 || (offset & 0xf0000000) == 0x20000000) + return m_program->read_dword(offset & m_am); + + return m_program->read_dword(offset); +} - return m_program->read_dword(A); +uint16_t sh2_device::decrypted_read_word(offs_t offset) +{ + return m_decrypted_program->read_word(offset); } -void sh2_device::WB(offs_t A, uint8_t V) +void sh2_device::write_byte(offs_t offset, uint8_t data) { - if((A & 0xf0000000) == 0 || (A & 0xf0000000) == 0x20000000) + if ((offset & 0xf0000000) == 0 || (offset & 0xf0000000) == 0x20000000) { - m_program->write_byte(A & SH12_AM,V); + m_program->write_byte(offset & m_am, data); return; } - m_program->write_byte(A,V); + m_program->write_byte(offset, data); } -void sh2_device::WW(offs_t A, uint16_t V) +void sh2_device::write_word(offs_t offset, uint16_t data) { - if((A & 0xf0000000) == 0 || (A & 0xf0000000) == 0x20000000) + if ((offset & 0xf0000000) == 0 || (offset & 0xf0000000) == 0x20000000) { - m_program->write_word(A & SH12_AM,V); + m_program->write_word(offset & m_am, data); return; } - m_program->write_word(A,V); + m_program->write_word(offset, data); } -void sh2_device::WL(offs_t A, uint32_t V) +void sh2_device::write_long(offs_t offset, uint32_t data) { - if((A & 0xf0000000) == 0 || (A & 0xf0000000) == 0x20000000) + if ((offset & 0xf0000000) == 0 || (offset & 0xf0000000) == 0x20000000) { - m_program->write_dword(A & SH12_AM,V); + m_program->write_dword(offset & m_am, data); return; } /* 0x20000000 no Cache */ /* 0x00000000 read thru Cache if CE bit is 1 */ - m_program->write_dword(A,V); + m_program->write_dword(offset, data); +} + +void sh2_device::check_pending_irq(const char *message) +{ + if (m_sh2_state->pending_nmi) + { + sh2_exception(message, 16); + m_sh2_state->pending_nmi = 0; + } + else + { + int irq = m_sh2_state->internal_irq_level; + if (m_sh2_state->pending_irq) + { + int external_irq = 15 - (count_leading_zeros_32(m_sh2_state->pending_irq) - 16); + if (external_irq >= irq) + { + irq = external_irq; + } + } + + if (irq >= 0) + { + sh2_exception(message, irq); + } + } } /* LDC.L @Rm+,SR */ inline void sh2_device::LDCMSR(const uint16_t opcode) // passes Rn { - uint32_t x = Rn; - - m_sh2_state->ea = m_sh2_state->r[x]; - m_sh2_state->sr = RL( m_sh2_state->ea ) & SH_FLAGS; - m_sh2_state->r[x] += 4; + const uint32_t rn = REG_N; + m_sh2_state->ea = m_sh2_state->r[rn]; + m_sh2_state->sr = read_long(m_sh2_state->ea) & SH_FLAGS; + m_sh2_state->r[rn] += 4; m_sh2_state->icount -= 2; m_test_irq = 1; } @@ -367,9 +219,7 @@ inline void sh2_device::LDCMSR(const uint16_t opcode) // passes Rn /* LDC Rm,SR */ inline void sh2_device::LDCSR(const uint16_t opcode) // passes Rn { - uint32_t x = Rn; - - m_sh2_state->sr = m_sh2_state->r[x] & SH_FLAGS; + m_sh2_state->sr = m_sh2_state->r[REG_N] & SH_FLAGS; m_test_irq = 1; } @@ -377,10 +227,10 @@ inline void sh2_device::LDCSR(const uint16_t opcode) // passes Rn inline void sh2_device::RTE() { m_sh2_state->ea = m_sh2_state->r[15]; - m_sh2_state->m_delay = RL( m_sh2_state->ea ); + m_sh2_state->m_delay = read_long(m_sh2_state->ea); m_sh2_state->r[15] += 4; m_sh2_state->ea = m_sh2_state->r[15]; - m_sh2_state->sr = RL( m_sh2_state->ea ) & SH_FLAGS; + m_sh2_state->sr = read_long(m_sh2_state->ea) & SH_FLAGS; m_sh2_state->r[15] += 4; m_sh2_state->icount -= 3; m_test_irq = 1; @@ -390,15 +240,16 @@ inline void sh2_device::RTE() inline void sh2_device::TRAPA(uint32_t i) { uint32_t imm = i & 0xff; + debugger_exception_hook(imm); m_sh2_state->ea = m_sh2_state->vbr + imm * 4; m_sh2_state->r[15] -= 4; - WL( m_sh2_state->r[15], m_sh2_state->sr ); + write_long(m_sh2_state->r[15], m_sh2_state->sr); m_sh2_state->r[15] -= 4; - WL( m_sh2_state->r[15], m_sh2_state->pc ); + write_long(m_sh2_state->r[15], m_sh2_state->pc); - m_sh2_state->pc = RL( m_sh2_state->ea ); + m_sh2_state->pc = read_long(m_sh2_state->ea); m_sh2_state->icount -= 7; } @@ -407,63 +258,28 @@ inline void sh2_device::TRAPA(uint32_t i) inline void sh2_device::ILLEGAL() { //logerror("Illegal opcode at %08x\n", m_sh2_state->pc - 2); + debugger_exception_hook(4); + m_sh2_state->r[15] -= 4; - WL( m_sh2_state->r[15], m_sh2_state->sr ); /* push SR onto stack */ + write_long(m_sh2_state->r[15], m_sh2_state->sr); /* push SR onto stack */ m_sh2_state->r[15] -= 4; - WL( m_sh2_state->r[15], m_sh2_state->pc - 2 ); /* push PC onto stack */ + write_long(m_sh2_state->r[15], m_sh2_state->pc - 2); /* push PC onto stack */ /* fetch PC */ - m_sh2_state->pc = RL( m_sh2_state->vbr + 4 * 4 ); + m_sh2_state->pc = read_long(m_sh2_state->vbr + 4 * 4); /* TODO: timing is a guess */ m_sh2_state->icount -= 5; } -/***************************************************************************** - * OPCODE DISPATCHERS - *****************************************************************************/ - - void sh2_device::execute_one_f000(uint16_t opcode) { ILLEGAL(); } -/***************************************************************************** - * MAME CPU INTERFACE - *****************************************************************************/ - -void sh2_device::device_reset() -{ - m_sh2_state->pc = m_sh2_state->pr = m_sh2_state->sr = m_sh2_state->gbr = m_sh2_state->vbr = m_sh2_state->mach = m_sh2_state->macl = 0; - m_sh2_state->evec = m_sh2_state->irqsr = 0; - memset(&m_sh2_state->r[0], 0, sizeof(m_sh2_state->r[0])*16); - m_sh2_state->ea = m_sh2_state->m_delay = m_cpu_off = 0; - //m_dvsr = m_dvdnth = m_dvdntl = m_dvcr = 0; - m_sh2_state->pending_irq = m_test_irq = 0; - //memset(&m_irq_queue[0], 0, sizeof(m_irq_queue[0])*16); - memset(&m_irq_line_state[0], 0, sizeof(m_irq_line_state[0])*17); - m_frc = m_ocra = m_ocrb = m_frc_icr = 0; - m_frc_base = 0; - m_frt_input = m_sh2_state->internal_irq_level = m_internal_irq_vector = 0; - m_dma_timer_active[0] = m_dma_timer_active[1] = 0; - m_dma_irq[0] = m_dma_irq[1] = 0; - - m_sh2_state->pc = RL(0); - m_sh2_state->r[15] = RL(4); - m_sh2_state->sr = SH_I; - m_sh2_state->sleep_mode = 0; - - m_sh2_state->internal_irq_level = -1; - - m_cache_dirty = true; -} - - -/* Execute cycles - returns number of cycles actually run */ void sh2_device::execute_run() { - if ( m_isdrc ) + if (m_isdrc) { execute_run_drc(); return; @@ -471,6 +287,7 @@ void sh2_device::execute_run() if (m_cpu_off) { + debugger_wait_hook(); m_sh2_state->icount = 0; return; } @@ -479,7 +296,7 @@ void sh2_device::execute_run() { debugger_instruction_hook(m_sh2_state->pc); - const uint16_t opcode = m_decrypted_program->read_word(m_sh2_state->pc >= 0x40000000 ? m_sh2_state->pc : m_sh2_state->pc & SH12_AM); + const uint16_t opcode = m_decrypted_program->read_word(m_sh2_state->pc >= 0x40000000 ? m_sh2_state->pc : m_sh2_state->pc & m_am); if (m_sh2_state->m_delay) { @@ -491,204 +308,20 @@ void sh2_device::execute_run() execute_one(opcode); - if(m_test_irq && !m_sh2_state->m_delay) + if (m_test_irq && !m_sh2_state->m_delay) { - CHECK_PENDING_IRQ("mame_sh2_execute"); + check_pending_irq("mame_sh2_execute"); m_test_irq = 0; } m_sh2_state->icount--; - } while( m_sh2_state->icount > 0 ); + } while (m_sh2_state->icount > 0); } - void sh2_device::init_drc_frontend() { m_drcfe = std::make_unique<sh2_frontend>(this, COMPILE_BACKWARDS_BYTES, COMPILE_FORWARDS_BYTES, SINGLE_INSTRUCTION_MODE ? 1 : COMPILE_MAX_SEQUENCE); } -void sh2_device::device_start() -{ - sh_common_execution::device_start(); - - m_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(sh2_device::sh2_timer_callback), this)); - m_timer->adjust(attotime::never); - - m_dma_current_active_timer[0] = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(sh2_device::sh2_dma_current_active_callback), this)); - m_dma_current_active_timer[0]->adjust(attotime::never); - - m_dma_current_active_timer[1] = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(sh2_device::sh2_dma_current_active_callback), this)); - m_dma_current_active_timer[1]->adjust(attotime::never); - - /* resolve callbacks */ - m_dma_kludge_cb.bind_relative_to(*owner()); - m_dma_fifo_data_available_cb.bind_relative_to(*owner()); - m_ftcsr_read_cb.bind_relative_to(*owner()); - - m_decrypted_program = has_space(AS_OPCODES) ? &space(AS_OPCODES) : &space(AS_PROGRAM); - auto cache = m_decrypted_program->cache<2, 0, ENDIANNESS_BIG>(); - m_pr16 = [cache](offs_t address) -> u16 { return cache->read_word(address); }; - if (m_decrypted_program->endianness() != ENDIANNESS_NATIVE) - m_prptr = [cache](offs_t address) -> const void * { - const u16 *ptr = static_cast<u16 *>(cache->read_ptr(address & ~3)); - if(!(address & 2)) - ptr++; - return ptr; - }; - else - m_prptr = [cache](offs_t address) -> const void * { - const u16 *ptr = static_cast<u16 *>(cache->read_ptr(address & ~3)); - if(address & 2) - ptr++; - return ptr; - }; - - m_internal = &space(AS_PROGRAM); - - // SCI - save_item(NAME(m_smr)); - save_item(NAME(m_brr)); - save_item(NAME(m_scr)); - save_item(NAME(m_tdr)); - save_item(NAME(m_ssr)); - - // FRT / FRC - save_item(NAME(m_tier)); - save_item(NAME(m_ftcsr)); - save_item(NAME(m_frc_tcr)); - save_item(NAME(m_tocr)); - save_item(NAME(m_frc)); - save_item(NAME(m_ocra)); - save_item(NAME(m_ocrb)); - save_item(NAME(m_frc_icr)); - save_item(NAME(m_frc_base)); - save_item(NAME(m_frt_input)); - - // INTC - save_item(NAME(m_irq_level.frc)); - save_item(NAME(m_irq_level.sci)); - save_item(NAME(m_irq_level.divu)); - save_item(NAME(m_irq_level.dmac)); - save_item(NAME(m_irq_level.wdt)); - save_item(NAME(m_irq_vector.fic)); - save_item(NAME(m_irq_vector.foc)); - save_item(NAME(m_irq_vector.fov)); - save_item(NAME(m_irq_vector.divu)); - save_item(NAME(m_irq_vector.dmac[0])); - save_item(NAME(m_irq_vector.dmac[1])); - - save_item(NAME(m_ipra)); - save_item(NAME(m_iprb)); - save_item(NAME(m_vcra)); - save_item(NAME(m_vcrb)); - save_item(NAME(m_vcrc)); - save_item(NAME(m_vcrd)); - save_item(NAME(m_vcrwdt)); - save_item(NAME(m_vcrdiv)); - save_item(NAME(m_intc_icr)); - save_item(NAME(m_vcrdma[0])); - save_item(NAME(m_vcrdma[1])); - - save_item(NAME(m_vecmd)); - save_item(NAME(m_nmie)); - - // DIVU - save_item(NAME(m_divu_ovf)); - save_item(NAME(m_divu_ovfie)); - save_item(NAME(m_dvsr)); - save_item(NAME(m_dvdntl)); - save_item(NAME(m_dvdnth)); - - // WTC - save_item(NAME(m_wtcnt)); - save_item(NAME(m_wtcsr)); - save_item(NAME(m_rstcsr)); - save_item(NAME(m_wtcw[0])); - save_item(NAME(m_wtcw[1])); - - // DMAC - save_item(NAME(m_dmaor)); - save_item(NAME(m_dmac[0].drcr)); - save_item(NAME(m_dmac[1].drcr)); - save_item(NAME(m_dmac[0].sar)); - save_item(NAME(m_dmac[1].sar)); - save_item(NAME(m_dmac[0].dar)); - save_item(NAME(m_dmac[1].dar)); - save_item(NAME(m_dmac[0].tcr)); - save_item(NAME(m_dmac[1].tcr)); - save_item(NAME(m_dmac[0].chcr)); - save_item(NAME(m_dmac[1].chcr)); - - // misc - save_item(NAME(m_sbycr)); - save_item(NAME(m_ccr)); - - // BSC - save_item(NAME(m_bcr1)); - save_item(NAME(m_bcr2)); - save_item(NAME(m_wcr)); - save_item(NAME(m_mcr)); - save_item(NAME(m_rtcsr)); - save_item(NAME(m_rtcor)); - save_item(NAME(m_rtcnt)); - - /* - for (int i = 0; i < 16; ++i) - { - save_item(NAME(m_irq_queue[i].irq_vector), i); - save_item(NAME(m_irq_queue[i].irq_priority), i); - } - */ - - // internals - save_item(NAME(m_cpu_off)); - save_item(NAME(m_test_irq)); - save_item(NAME(m_irq_line_state)); - save_item(NAME(m_nmi_line_state)); - save_item(NAME(m_internal_irq_vector)); - save_item(NAME(m_dma_timer_active)); - save_item(NAME(m_dma_irq)); - - state_add( STATE_GENPC, "PC", m_sh2_state->pc).mask(SH12_AM).callimport(); - state_add( STATE_GENPCBASE, "CURPC", m_sh2_state->pc ).callimport().noshow(); - - // Clear state - m_cpu_off = 0; - //m_dvsr = 0; - //m_dvdnth = 0; - //m_dvdntl = 0; - //m_dvcr = 0; - m_test_irq = 0; - - memset(m_irq_line_state, 0, sizeof(m_irq_line_state)); - - m_nmi_line_state = 0; - m_frc = 0; - m_ocra = 0; - m_ocrb = 0; - m_frc_icr = 0; - m_frc_base = 0; - m_frt_input = 0; - m_internal_irq_vector = 0; - - for ( int i = 0; i < 2; i++ ) - { - m_dma_timer_active[i] = 0; - m_dma_irq[i] = 0; - m_active_dma_incs[i] = 0; - m_active_dma_incd[i] = 0; - m_active_dma_size[i] = 0; - m_active_dma_steal[i] = 0; - m_active_dma_src[i] = 0; - m_active_dma_dst[i] = 0; - m_active_dma_count[i] = 0; - } - m_wtcnt = 0; - m_wtcsr = 0; - - drc_start(); -} - - void sh2_device::state_string_export(const device_state_entry &entry, std::string &str) const { switch (entry.index()) @@ -704,7 +337,6 @@ void sh2_device::state_string_export(const device_state_entry &entry, std::strin } } - void sh2_device::state_import(const device_state_entry &entry) { switch (entry.index()) @@ -715,38 +347,48 @@ void sh2_device::state_import(const device_state_entry &entry) break; case SH_SR: - CHECK_PENDING_IRQ("sh2_set_reg"); + check_pending_irq("sh2_set_reg"); break; } } - void sh2_device::execute_set_input(int irqline, int state) { if (irqline == INPUT_LINE_NMI) { if (m_nmi_line_state == state) return; + m_nmi_line_state = state; if (state == CLEAR_LINE) { - LOG("SH-2 cleared nmi\n"); + LOG("SH-2 cleared NMI\n"); } else { - LOG("SH-2 asserted nmi\n"); + LOG("SH-2 asserted NMI\n"); - sh2_exception("Set IRQ line", 16); + m_sh2_state->pending_nmi = 1; if (m_isdrc) - m_sh2_state->pending_nmi = 1; + { + sh2_exception("Set IRQ line", 16); + } + else + { + if (m_sh2_state->m_delay) + m_test_irq = 1; + else + check_pending_irq("sh2_set_nmi_line"); + } } } else { if (m_irq_line_state[irqline] == state) return; + m_irq_line_state[irqline] = state; if (state == CLEAR_LINE) @@ -758,14 +400,17 @@ void sh2_device::execute_set_input(int irqline, int state) { LOG("SH-2 asserted irq #%d\n", irqline); m_sh2_state->pending_irq |= 1 << irqline; + if (m_isdrc) { m_test_irq = 1; - } else { - if(m_sh2_state->m_delay) + } + else + { + if (m_sh2_state->m_delay) m_test_irq = 1; else - CHECK_PENDING_IRQ("sh2_set_irq_line"); + check_pending_irq("sh2_set_irq_line"); } } } @@ -773,6 +418,7 @@ void sh2_device::execute_set_input(int irqline, int state) void sh2_device::sh2_exception(const char *message, int irqline) { + // override this at the individual CPU level when special logic is required int vector; if (irqline != 16) @@ -790,17 +436,9 @@ void sh2_device::sh2_exception(const char *message, int irqline) } else { - if(m_vecmd == true) - { - vector = standard_irq_callback(irqline); - LOG("SH-2 exception #%d (external vector: $%x) after [%s]\n", irqline, vector, message); - } - else - { - standard_irq_callback(irqline); - vector = 64 + irqline/2; - LOG("SH-2 exception #%d (autovector: $%x) after [%s]\n", irqline, vector, message); - } + standard_irq_callback(irqline, m_sh2_state->pc); + vector = 64 + irqline/2; + LOG("SH-2 exception #%d (autovector: $%x) after [%s]\n", irqline, vector, message); } } else @@ -809,10 +447,17 @@ void sh2_device::sh2_exception(const char *message, int irqline) LOG("SH-2 nmi exception (autovector: $%x) after [%s]\n", vector, message); } + sh2_exception_internal(message, irqline, vector); +} + +void sh2_device::sh2_exception_internal(const char *message, int irqline, int vector) +{ + debugger_exception_hook(vector); + if (m_isdrc) { - m_sh2_state->evec = RL( m_sh2_state->vbr + vector * 4 ); - m_sh2_state->evec &= SH12_AM; + m_sh2_state->evec = read_long(m_sh2_state->vbr + vector * 4); + m_sh2_state->evec &= m_am; m_sh2_state->irqsr = m_sh2_state->sr; /* set I flags in SR */ @@ -822,11 +467,13 @@ void sh2_device::sh2_exception(const char *message, int irqline) m_sh2_state->sr = (m_sh2_state->sr & ~SH_I) | (irqline << 4); // printf("sh2_exception [%s] irqline %x evec %x save SR %x new SR %x\n", message, irqline, m_sh2_state->evec, m_sh2_state->irqsr, m_sh2_state->sr); - } else { + } + else + { m_sh2_state->r[15] -= 4; - WL( m_sh2_state->r[15], m_sh2_state->sr ); /* push SR onto stack */ + write_long(m_sh2_state->r[15], m_sh2_state->sr); /* push SR onto stack */ m_sh2_state->r[15] -= 4; - WL( m_sh2_state->r[15], m_sh2_state->pc ); /* push PC onto stack */ + write_long(m_sh2_state->r[15], m_sh2_state->pc); /* push PC onto stack */ /* set I flags in SR */ if (irqline > SH2_INT_15) @@ -835,46 +482,32 @@ void sh2_device::sh2_exception(const char *message, int irqline) m_sh2_state->sr = (m_sh2_state->sr & ~SH_I) | (irqline << 4); /* fetch PC */ - m_sh2_state->pc = RL( m_sh2_state->vbr + vector * 4 ); + m_sh2_state->pc = read_long(m_sh2_state->vbr + vector * 4); } - if(m_sh2_state->sleep_mode == 1) { m_sh2_state->sleep_mode = 2; } + if (m_sh2_state->sleep_mode == 1) + m_sh2_state->sleep_mode = 2; } -// license:BSD-3-Clause -// copyright-holders:R. Belmont -/*************************************************************************** - - sh2drc.c - Universal machine language-based SH-2 emulator. - -***************************************************************************/ - -#include "emu.h" -#include "sh2.h" -#include "sh2comn.h" -#include "cpu/drcumlsh.h" -#include "debugger.h" - +///////// +// DRC const opcode_desc* sh2_device::get_desclist(offs_t pc) { return m_drcfe->describe_code(pc); } - +void sh2_device::func_fastirq() +{ + sh2_exception("fastirq", m_sh2_state->irqline); +} +static void cfunc_fastirq(void *param) { ((sh2_device *)param)->func_fastirq(); }; /*------------------------------------------------- static_generate_entry_point - generate a static entry point -------------------------------------------------*/ -void sh2_device::func_fastirq() -{ - sh2_exception("fastirq",m_sh2_state->irqline); -} -static void cfunc_fastirq(void *param) { ((sh2_device *)param)->func_fastirq(); }; - void sh2_device::static_generate_entry_point() { uml::code_label const skip = 1; @@ -1054,11 +687,11 @@ void sh2_device::static_generate_memory_accessor(int size, int iswrite, const ch UML_CMP(block, I0, 0x40000000); // cmp #0x40000000, r0 UML_JMPc(block, COND_AE, label); // bae label - UML_AND(block, I0, I0, SH12_AM); // and r0, r0, #AM (0xc7ffffff) + UML_AND(block, I0, I0, m_am); // and r0, r0, #AM (0xc7ffffff) UML_LABEL(block, label++); // label: - if ((machine().debug_flags & DEBUG_FLAG_ENABLED) == 0) + if (!debugger_enabled()) { for (auto & elem : m_fastram) { @@ -1158,5 +791,3 @@ void sh2_device::static_generate_memory_accessor(int size, int iswrite, const ch block.end(); } - - |