summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/cpu/sh/sh2.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/cpu/sh/sh2.cpp')
-rw-r--r--src/devices/cpu/sh/sh2.cpp753
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();
}
-
-