From c0ee79f3db1d019c74cd199a99398bb5a04065c5 Mon Sep 17 00:00:00 2001 From: David Haywood Date: Mon, 2 Oct 2017 19:47:35 +0100 Subject: use 'sh' instead of 'superh' --- scripts/src/cpu.lua | 62 +- scripts/target/mame/arcade.lua | 2 +- scripts/target/mame/mess.lua | 2 +- src/devices/cpu/sh/sh2.cpp | 2704 +++++++++++++++++++ src/devices/cpu/sh/sh2.h | 557 ++++ src/devices/cpu/sh/sh2comn.cpp | 946 +++++++ src/devices/cpu/sh/sh2comn.h | 85 + src/devices/cpu/sh/sh2dasm.cpp | 610 +++++ src/devices/cpu/sh/sh2drc.cpp | 2982 +++++++++++++++++++++ src/devices/cpu/sh/sh2fe.cpp | 762 ++++++ src/devices/cpu/sh/sh3comn.cpp | 681 +++++ src/devices/cpu/sh/sh3comn.h | 96 + src/devices/cpu/sh/sh4.cpp | 4743 +++++++++++++++++++++++++++++++++ src/devices/cpu/sh/sh4.h | 844 ++++++ src/devices/cpu/sh/sh4comn.cpp | 1465 ++++++++++ src/devices/cpu/sh/sh4comn.h | 174 ++ src/devices/cpu/sh/sh4dasm.cpp | 905 +++++++ src/devices/cpu/sh/sh4dmac.cpp | 666 +++++ src/devices/cpu/sh/sh4dmac.h | 63 + src/devices/cpu/sh/sh4regs.h | 183 ++ src/devices/cpu/sh/sh4tmu.cpp | 324 +++ src/devices/cpu/sh/sh4tmu.h | 3 + src/devices/cpu/sh/sh7604_bus.cpp | 162 ++ src/devices/cpu/sh/sh7604_bus.h | 77 + src/devices/cpu/sh/sh7604_sci.cpp | 156 ++ src/devices/cpu/sh/sh7604_sci.h | 83 + src/devices/cpu/sh/sh7604_wdt.cpp | 83 + src/devices/cpu/sh/sh7604_wdt.h | 54 + src/devices/cpu/superh/sh2.cpp | 2704 ------------------- src/devices/cpu/superh/sh2.h | 557 ---- src/devices/cpu/superh/sh2comn.cpp | 946 ------- src/devices/cpu/superh/sh2comn.h | 85 - src/devices/cpu/superh/sh2dasm.cpp | 610 ----- src/devices/cpu/superh/sh2drc.cpp | 2982 --------------------- src/devices/cpu/superh/sh2fe.cpp | 762 ------ src/devices/cpu/superh/sh3comn.cpp | 681 ----- src/devices/cpu/superh/sh3comn.h | 96 - src/devices/cpu/superh/sh4.cpp | 4743 --------------------------------- src/devices/cpu/superh/sh4.h | 844 ------ src/devices/cpu/superh/sh4comn.cpp | 1465 ---------- src/devices/cpu/superh/sh4comn.h | 174 -- src/devices/cpu/superh/sh4dasm.cpp | 905 ------- src/devices/cpu/superh/sh4dmac.cpp | 666 ----- src/devices/cpu/superh/sh4dmac.h | 63 - src/devices/cpu/superh/sh4regs.h | 183 -- src/devices/cpu/superh/sh4tmu.cpp | 324 --- src/devices/cpu/superh/sh4tmu.h | 3 - src/devices/cpu/superh/sh7604_bus.cpp | 162 -- src/devices/cpu/superh/sh7604_bus.h | 77 - src/devices/cpu/superh/sh7604_sci.cpp | 156 -- src/devices/cpu/superh/sh7604_sci.h | 83 - src/devices/cpu/superh/sh7604_wdt.cpp | 83 - src/devices/cpu/superh/sh7604_wdt.h | 54 - src/mame/drivers/alien.cpp | 2 +- src/mame/drivers/aristmk6.cpp | 2 +- src/mame/drivers/atvtrack.cpp | 2 +- src/mame/drivers/casloopy.cpp | 2 +- src/mame/drivers/coolridr.cpp | 2 +- src/mame/drivers/cps3.cpp | 2 +- src/mame/drivers/cv1k.cpp | 4 +- src/mame/drivers/dccons.cpp | 2 +- src/mame/drivers/deco_mlc.cpp | 2 +- src/mame/drivers/feversoc.cpp | 2 +- src/mame/drivers/hideseek.cpp | 2 +- src/mame/drivers/hikaru.cpp | 2 +- src/mame/drivers/namcos23.cpp | 2 +- src/mame/drivers/psikyosh.cpp | 2 +- src/mame/drivers/saturn.cpp | 2 +- src/mame/drivers/segasp.cpp | 2 +- src/mame/drivers/sh4robot.cpp | 2 +- src/mame/drivers/stv.cpp | 2 +- src/mame/drivers/suprnova.cpp | 2 +- src/mame/includes/cps3.h | 2 +- src/mame/includes/naomi.h | 2 +- src/mame/includes/psikyo4.h | 2 +- src/mame/includes/psikyosh.h | 2 +- src/mame/includes/saturn.h | 2 +- src/mame/includes/suprnova.h | 2 +- src/mame/machine/dc.cpp | 2 +- src/mame/machine/dccons.cpp | 2 +- src/mame/machine/maple-dc.h | 2 +- src/mame/machine/mega32x.h | 4 +- src/mame/machine/naomig1.h | 2 +- src/mame/machine/saturn.cpp | 2 +- src/mame/machine/saturn_cdb.h | 2 +- src/mame/video/powervr2.cpp | 2 +- 86 files changed, 19476 insertions(+), 19476 deletions(-) create mode 100644 src/devices/cpu/sh/sh2.cpp create mode 100644 src/devices/cpu/sh/sh2.h create mode 100644 src/devices/cpu/sh/sh2comn.cpp create mode 100644 src/devices/cpu/sh/sh2comn.h create mode 100644 src/devices/cpu/sh/sh2dasm.cpp create mode 100644 src/devices/cpu/sh/sh2drc.cpp create mode 100644 src/devices/cpu/sh/sh2fe.cpp create mode 100644 src/devices/cpu/sh/sh3comn.cpp create mode 100644 src/devices/cpu/sh/sh3comn.h create mode 100644 src/devices/cpu/sh/sh4.cpp create mode 100644 src/devices/cpu/sh/sh4.h create mode 100644 src/devices/cpu/sh/sh4comn.cpp create mode 100644 src/devices/cpu/sh/sh4comn.h create mode 100644 src/devices/cpu/sh/sh4dasm.cpp create mode 100644 src/devices/cpu/sh/sh4dmac.cpp create mode 100644 src/devices/cpu/sh/sh4dmac.h create mode 100644 src/devices/cpu/sh/sh4regs.h create mode 100644 src/devices/cpu/sh/sh4tmu.cpp create mode 100644 src/devices/cpu/sh/sh4tmu.h create mode 100644 src/devices/cpu/sh/sh7604_bus.cpp create mode 100644 src/devices/cpu/sh/sh7604_bus.h create mode 100644 src/devices/cpu/sh/sh7604_sci.cpp create mode 100644 src/devices/cpu/sh/sh7604_sci.h create mode 100644 src/devices/cpu/sh/sh7604_wdt.cpp create mode 100644 src/devices/cpu/sh/sh7604_wdt.h delete mode 100644 src/devices/cpu/superh/sh2.cpp delete mode 100644 src/devices/cpu/superh/sh2.h delete mode 100644 src/devices/cpu/superh/sh2comn.cpp delete mode 100644 src/devices/cpu/superh/sh2comn.h delete mode 100644 src/devices/cpu/superh/sh2dasm.cpp delete mode 100644 src/devices/cpu/superh/sh2drc.cpp delete mode 100644 src/devices/cpu/superh/sh2fe.cpp delete mode 100644 src/devices/cpu/superh/sh3comn.cpp delete mode 100644 src/devices/cpu/superh/sh3comn.h delete mode 100644 src/devices/cpu/superh/sh4.cpp delete mode 100644 src/devices/cpu/superh/sh4.h delete mode 100644 src/devices/cpu/superh/sh4comn.cpp delete mode 100644 src/devices/cpu/superh/sh4comn.h delete mode 100644 src/devices/cpu/superh/sh4dasm.cpp delete mode 100644 src/devices/cpu/superh/sh4dmac.cpp delete mode 100644 src/devices/cpu/superh/sh4dmac.h delete mode 100644 src/devices/cpu/superh/sh4regs.h delete mode 100644 src/devices/cpu/superh/sh4tmu.cpp delete mode 100644 src/devices/cpu/superh/sh4tmu.h delete mode 100644 src/devices/cpu/superh/sh7604_bus.cpp delete mode 100644 src/devices/cpu/superh/sh7604_bus.h delete mode 100644 src/devices/cpu/superh/sh7604_sci.cpp delete mode 100644 src/devices/cpu/superh/sh7604_sci.h delete mode 100644 src/devices/cpu/superh/sh7604_wdt.cpp delete mode 100644 src/devices/cpu/superh/sh7604_wdt.h diff --git a/scripts/src/cpu.lua b/scripts/src/cpu.lua index bb5496f39f4..365aa3bd6bb 100644 --- a/scripts/src/cpu.lua +++ b/scripts/src/cpu.lua @@ -13,7 +13,7 @@ -- Dynamic recompiler objects -------------------------------------------------- -if (CPUS["SUPERH"]~=null or CPUS["MIPS"]~=null or CPUS["POWERPC"]~=null or CPUS["RSP"]~=null or CPUS["ARM7"]~=null or CPUS["ADSP21062"]~=null or CPUS["MB86235"]~=null) then +if (CPUS["SH"]~=null or CPUS["MIPS"]~=null or CPUS["POWERPC"]~=null or CPUS["RSP"]~=null or CPUS["ARM7"]~=null or CPUS["ADSP21062"]~=null or CPUS["MB86235"]~=null) then files { MAME_DIR .. "src/devices/cpu/drcbec.cpp", MAME_DIR .. "src/devices/cpu/drcbec.h", @@ -637,41 +637,41 @@ end -------------------------------------------------- -- Hitachi SuperH series (SH1/SH2/SH3/SH4) ---@src/devices/cpu/superh/sh2.h,CPUS["SUPERH"] = true ---@src/devices/cpu/superh/sh4.h,CPUS["SUPERH"] = true +--@src/devices/cpu/sh/sh2.h,CPUS["SH"] = true +--@src/devices/cpu/sh/sh4.h,CPUS["SH"] = true -------------------------------------------------- -if (CPUS["SUPERH"]~=null) then +if (CPUS["SH"]~=null) then files { - MAME_DIR .. "src/devices/cpu/superh/sh2.cpp", - MAME_DIR .. "src/devices/cpu/superh/sh2.h", - MAME_DIR .. "src/devices/cpu/superh/sh2comn.cpp", - MAME_DIR .. "src/devices/cpu/superh/sh2comn.h", - MAME_DIR .. "src/devices/cpu/superh/sh2fe.cpp", - MAME_DIR .. "src/devices/cpu/superh/sh7604_bus.cpp", - MAME_DIR .. "src/devices/cpu/superh/sh7604_bus.h", - MAME_DIR .. "src/devices/cpu/superh/sh7604_sci.cpp", - MAME_DIR .. "src/devices/cpu/superh/sh7604_sci.h", - MAME_DIR .. "src/devices/cpu/superh/sh7604_wdt.cpp", - MAME_DIR .. "src/devices/cpu/superh/sh7604_wdt.h", - --MAME_DIR .. "src/devices/cpu/superh/sh2drc.cpp", - MAME_DIR .. "src/devices/cpu/superh/sh4.cpp", - MAME_DIR .. "src/devices/cpu/superh/sh4.h", - MAME_DIR .. "src/devices/cpu/superh/sh4comn.cpp", - MAME_DIR .. "src/devices/cpu/superh/sh4comn.h", - MAME_DIR .. "src/devices/cpu/superh/sh3comn.cpp", - MAME_DIR .. "src/devices/cpu/superh/sh3comn.h", - MAME_DIR .. "src/devices/cpu/superh/sh4tmu.cpp", - MAME_DIR .. "src/devices/cpu/superh/sh4tmu.h", - MAME_DIR .. "src/devices/cpu/superh/sh4dmac.cpp", - MAME_DIR .. "src/devices/cpu/superh/sh4dmac.h", - MAME_DIR .. "src/devices/cpu/superh/sh4regs.h", + MAME_DIR .. "src/devices/cpu/sh/sh2.cpp", + MAME_DIR .. "src/devices/cpu/sh/sh2.h", + MAME_DIR .. "src/devices/cpu/sh/sh2comn.cpp", + MAME_DIR .. "src/devices/cpu/sh/sh2comn.h", + MAME_DIR .. "src/devices/cpu/sh/sh2fe.cpp", + MAME_DIR .. "src/devices/cpu/sh/sh7604_bus.cpp", + MAME_DIR .. "src/devices/cpu/sh/sh7604_bus.h", + MAME_DIR .. "src/devices/cpu/sh/sh7604_sci.cpp", + MAME_DIR .. "src/devices/cpu/sh/sh7604_sci.h", + MAME_DIR .. "src/devices/cpu/sh/sh7604_wdt.cpp", + MAME_DIR .. "src/devices/cpu/sh/sh7604_wdt.h", + --MAME_DIR .. "src/devices/cpu/sh/sh2drc.cpp", + MAME_DIR .. "src/devices/cpu/sh/sh4.cpp", + MAME_DIR .. "src/devices/cpu/sh/sh4.h", + MAME_DIR .. "src/devices/cpu/sh/sh4comn.cpp", + MAME_DIR .. "src/devices/cpu/sh/sh4comn.h", + MAME_DIR .. "src/devices/cpu/sh/sh3comn.cpp", + MAME_DIR .. "src/devices/cpu/sh/sh3comn.h", + MAME_DIR .. "src/devices/cpu/sh/sh4tmu.cpp", + MAME_DIR .. "src/devices/cpu/sh/sh4tmu.h", + MAME_DIR .. "src/devices/cpu/sh/sh4dmac.cpp", + MAME_DIR .. "src/devices/cpu/sh/sh4dmac.h", + MAME_DIR .. "src/devices/cpu/sh/sh4regs.h", } end -if (CPUS["SUPERH"]~=null or _OPTIONS["with-tools"]) then - table.insert(disasm_files , MAME_DIR .. "src/devices/cpu/superh/sh2dasm.cpp") - table.insert(disasm_files , MAME_DIR .. "src/devices/cpu/superh/sh4dasm.cpp") +if (CPUS["SH"]~=null or _OPTIONS["with-tools"]) then + table.insert(disasm_files , MAME_DIR .. "src/devices/cpu/sh/sh2dasm.cpp") + table.insert(disasm_files , MAME_DIR .. "src/devices/cpu/sh/sh4dasm.cpp") end -------------------------------------------------- @@ -936,7 +936,7 @@ if (CPUS["I86"]~=null) then } end -if (CPUS["SUPERH"]~=null or CPUS["MIPS"]~=null or CPUS["POWERPC"]~=null or CPUS["RSP"]~=null or CPUS["ARM7"]~=null or CPUS["ADSP21062"]~=null or CPUS["MB86235"]~=null or CPUS["I86"]~=null or CPUS["I386"]~=null or _OPTIONS["with-tools"]) then +if (CPUS["SH"]~=null or CPUS["MIPS"]~=null or CPUS["POWERPC"]~=null or CPUS["RSP"]~=null or CPUS["ARM7"]~=null or CPUS["ADSP21062"]~=null or CPUS["MB86235"]~=null or CPUS["I86"]~=null or CPUS["I386"]~=null or _OPTIONS["with-tools"]) then table.insert(disasm_files , MAME_DIR .. "src/devices/cpu/i386/i386dasm.cpp") table.insert(disasm_files , MAME_DIR .. "src/devices/cpu/i386/i386dasm.h") end diff --git a/scripts/target/mame/arcade.lua b/scripts/target/mame/arcade.lua index 41966d3d130..e88f1d84b4b 100644 --- a/scripts/target/mame/arcade.lua +++ b/scripts/target/mame/arcade.lua @@ -60,7 +60,7 @@ CPUS["ESRIP"] = true CPUS["MIPS"] = true CPUS["R3000"] = true CPUS["PSX"] = true -CPUS["SUPERH"] = true +CPUS["SH"] = true CPUS["DSP16A"] = true CPUS["DSP32C"] = true CPUS["PIC16C5X"] = true diff --git a/scripts/target/mame/mess.lua b/scripts/target/mame/mess.lua index 71efe6c8cfb..80f974121ba 100644 --- a/scripts/target/mame/mess.lua +++ b/scripts/target/mame/mess.lua @@ -60,7 +60,7 @@ CPUS["ESRIP"] = true CPUS["MIPS"] = true CPUS["R3000"] = true CPUS["PSX"] = true -CPUS["SUPERH"] = true +CPUS["SH"] = true CPUS["DSP16A"] = true CPUS["DSP32C"] = true CPUS["PIC16C5X"] = true diff --git a/src/devices/cpu/sh/sh2.cpp b/src/devices/cpu/sh/sh2.cpp new file mode 100644 index 00000000000..9b1cf8dcbbf --- /dev/null +++ b/src/devices/cpu/sh/sh2.cpp @@ -0,0 +1,2704 @@ +// license:BSD-3-Clause +// copyright-holders:Juergen Buchmueller +/***************************************************************************** + * + * sh2.c + * Portable Hitachi SH-2 (SH7600 family) emulator + * + * This work is based on C/C++ implementation of + * the SH-2 CPU core and was adapted to the MAME CPU core requirements. + * Thanks also go to Chuck Mason and Olivier Galibert + * for letting me peek into their SEMU code :-) + * + *****************************************************************************/ + +/***************************************************************************** + 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 "debugger.h" + +//#define VERBOSE 1 +#include "logmacro.h" + + +/*************************************************************************** + DEBUGGING +***************************************************************************/ + +#define DISABLE_FAST_REGISTERS (0) // set to 1 to turn off usage of register caching +#define SINGLE_INSTRUCTION_MODE (0) + + +/*************************************************************************** + CONSTANTS +***************************************************************************/ + +/* size of the execution code cache */ +#define CACHE_SIZE (32 * 1024 * 1024) + +/* compilation boundaries -- how far back/forward does the analysis extend? */ +#define COMPILE_BACKWARDS_BYTES 64 +#define COMPILE_FORWARDS_BYTES 256 +#define COMPILE_MAX_INSTRUCTIONS ((COMPILE_BACKWARDS_BYTES/2) + (COMPILE_FORWARDS_BYTES/2)) +#define COMPILE_MAX_SEQUENCE 64 + + +DEFINE_DEVICE_TYPE(SH1, sh1_device, "sh1", "SH-1") +DEFINE_DEVICE_TYPE(SH2, sh2_device, "sh2", "SH-2") +DEFINE_DEVICE_TYPE(SH2A, sh2a_device, "sh21", "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 +-------------------------------------------------*/ + +static ADDRESS_MAP_START( sh7604_map, AS_PROGRAM, 32, sh2_device ) + AM_RANGE(0x40000000, 0xbfffffff) AM_READ(sh2_internal_a5) +/*! + @todo: cps3boot breaks with this enabled. Needs customization ... + */ +// AM_RANGE(0xc0000000, 0xc0000fff) AM_RAM // cache data array +// AM_RANGE(0xffffff88, 0xffffff8b) AM_READWRITE(dma_dtcr0_r,dma_dtcr0_w) + AM_RANGE(0xe0000000, 0xe00001ff) AM_MIRROR(0x1ffffe00) AM_READWRITE(sh7604_r, sh7604_w) +ADDRESS_MAP_END + +static ADDRESS_MAP_START( sh7021_map, AS_PROGRAM, 32, sh2a_device ) +// overrides + AM_RANGE(0x05ffff40, 0x05ffff43) AM_READWRITE(dma_sar0_r, dma_sar0_w) + AM_RANGE(0x05ffff44, 0x05ffff47) AM_READWRITE(dma_dar0_r, dma_dar0_w) + AM_RANGE(0x05ffff48, 0x05ffff4b) AM_READWRITE16(dmaor_r, dmaor_w,0xffff0000) + AM_RANGE(0x05ffff48, 0x05ffff4b) AM_READWRITE16(dma_tcr0_r, dma_tcr0_w,0x0000ffff) + AM_RANGE(0x05ffff4c, 0x05ffff4f) AM_READWRITE16(dma_chcr0_r, dma_chcr0_w, 0x0000ffff) +// fall-back + AM_RANGE(0x05fffe00, 0x05ffffff) AM_READWRITE16(sh7021_r,sh7021_w,0xffffffff) // SH-7032H internal i/o +// 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) +ADDRESS_MAP_END + +static ADDRESS_MAP_START( sh7032_map, AS_PROGRAM, 32, sh1_device ) +// fall-back + AM_RANGE(0x05fffe00, 0x05ffffff) AM_READWRITE16(sh7032_r,sh7032_w,0xffffffff) // SH-7032H internal i/o +ADDRESS_MAP_END + +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_NAME(sh7604_map), 32) +{ +} + + +void sh2_device::device_stop() +{ +} + + +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) + : cpu_device(mconfig, type, tag, owner, clock) + , 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_cpu_type(cpu_type) + , m_cache(CACHE_SIZE + sizeof(internal_sh2_state)) + , m_drcuml(nullptr) +// , m_drcuml(*this, m_cache, 0, 1, 32, 1) + , m_drcfe(nullptr) + , m_drcoptions(0) + , m_sh2_state(nullptr) + , m_entry(nullptr) + , m_read8(nullptr) + , m_write8(nullptr) + , m_read16(nullptr) + , m_write16(nullptr) + , m_read32(nullptr) + , m_write32(nullptr) + , m_interrupt(nullptr) + , m_nocode(nullptr) + , m_out_of_cycles(nullptr) + , m_debugger_temp(0) +{ + m_isdrc = allow_drc(); +} + +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_NAME(sh7021_map), 28) +{ +} + +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_NAME(sh7032_map), 28) +{ +} + +device_memory_interface::space_config_vector sh2_device::memory_space_config() const +{ + 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 { + std::make_pair(AS_PROGRAM, &m_program_config) + }; +} + +offs_t sh2_device::disasm_disassemble(std::ostream &stream, offs_t pc, const uint8_t *oprom, const uint8_t *opram, uint32_t options) +{ + extern CPU_DISASSEMBLE( sh2 ); + return CPU_DISASSEMBLE_NAME( sh2 )(this, stream, pc, oprom, opram, options); +} + + +/* speed up delay loops, bail out of tight loops */ +#define BUSY_LOOP_HACKS 1 + +uint8_t sh2_device::RB(offs_t A) +{ + if((A & 0xf0000000) == 0 || (A & 0xf0000000) == 0x20000000) + return m_program->read_byte(A & AM); + + return m_program->read_byte(A); +} + +uint16_t sh2_device::RW(offs_t A) +{ + if((A & 0xf0000000) == 0 || (A & 0xf0000000) == 0x20000000) + return m_program->read_word(A & AM); + + return m_program->read_word(A); +} + +uint32_t sh2_device::RL(offs_t A) +{ + /* 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 & AM); + + return m_program->read_dword(A); +} + +void sh2_device::WB(offs_t A, uint8_t V) +{ + if((A & 0xf0000000) == 0 || (A & 0xf0000000) == 0x20000000) + { + m_program->write_byte(A & AM,V); + return; + } + + m_program->write_byte(A,V); +} + +void sh2_device::WW(offs_t A, uint16_t V) +{ + if((A & 0xf0000000) == 0 || (A & 0xf0000000) == 0x20000000) + { + m_program->write_word(A & AM,V); + return; + } + + m_program->write_word(A,V); +} + +void sh2_device::WL(offs_t A, uint32_t V) +{ + if((A & 0xf0000000) == 0 || (A & 0xf0000000) == 0x20000000) + { + m_program->write_dword(A & AM,V); + return; + } + + /* 0x20000000 no Cache */ + /* 0x00000000 read thru Cache if CE bit is 1 */ + m_program->write_dword(A,V); +} + +/* code cycles t-bit + * 0011 nnnn mmmm 1100 1 - + * ADD Rm,Rn + */ +void sh2_device::ADD(uint32_t m, uint32_t n) +{ + m_sh2_state->r[n] += m_sh2_state->r[m]; +} + +/* code cycles t-bit + * 0111 nnnn iiii iiii 1 - + * ADD #imm,Rn + */ +void sh2_device::ADDI(uint32_t i, uint32_t n) +{ + m_sh2_state->r[n] += (int32_t)(int16_t)(int8_t)i; +} + +/* code cycles t-bit + * 0011 nnnn mmmm 1110 1 carry + * ADDC Rm,Rn + */ +void sh2_device::ADDC(uint32_t m, uint32_t n) +{ + uint32_t tmp0, tmp1; + + tmp1 = m_sh2_state->r[n] + m_sh2_state->r[m]; + tmp0 = m_sh2_state->r[n]; + m_sh2_state->r[n] = tmp1 + (m_sh2_state->sr & T); + if (tmp0 > tmp1) + m_sh2_state->sr |= T; + else + m_sh2_state->sr &= ~T; + if (tmp1 > m_sh2_state->r[n]) + m_sh2_state->sr |= T; +} + +/* code cycles t-bit + * 0011 nnnn mmmm 1111 1 overflow + * ADDV Rm,Rn + */ +void sh2_device::ADDV(uint32_t m, uint32_t n) +{ + int32_t dest, src, ans; + + if ((int32_t) m_sh2_state->r[n] >= 0) + dest = 0; + else + dest = 1; + if ((int32_t) m_sh2_state->r[m] >= 0) + src = 0; + else + src = 1; + src += dest; + m_sh2_state->r[n] += m_sh2_state->r[m]; + if ((int32_t) m_sh2_state->r[n] >= 0) + ans = 0; + else + ans = 1; + ans += dest; + if (src == 0 || src == 2) + { + if (ans == 1) + m_sh2_state->sr |= T; + else + m_sh2_state->sr &= ~T; + } + else + m_sh2_state->sr &= ~T; +} + +/* code cycles t-bit + * 0010 nnnn mmmm 1001 1 - + * AND Rm,Rn + */ +void sh2_device::AND(uint32_t m, uint32_t n) +{ + m_sh2_state->r[n] &= m_sh2_state->r[m]; +} + + +/* code cycles t-bit + * 1100 1001 iiii iiii 1 - + * AND #imm,R0 + */ +void sh2_device::ANDI(uint32_t i) +{ + m_sh2_state->r[0] &= i; +} + +/* code cycles t-bit + * 1100 1101 iiii iiii 1 - + * AND.B #imm,@(R0,GBR) + */ +void sh2_device::ANDM(uint32_t i) +{ + uint32_t temp; + + m_sh2_state->ea = m_sh2_state->gbr + m_sh2_state->r[0]; + temp = i & RB( m_sh2_state->ea ); + WB( m_sh2_state->ea, temp ); + m_sh2_state->icount -= 2; +} + +/* code cycles t-bit + * 1000 1011 dddd dddd 3/1 - + * BF disp8 + */ +void sh2_device::BF(uint32_t d) +{ + if ((m_sh2_state->sr & T) == 0) + { + int32_t disp = ((int32_t)d << 24) >> 24; + m_sh2_state->pc = m_sh2_state->ea = m_sh2_state->pc + disp * 2 + 2; + m_sh2_state->icount -= 2; + } +} + +/* code cycles t-bit + * 1000 1111 dddd dddd 3/1 - + * BFS disp8 + */ +void sh2_device::BFS(uint32_t d) +{ + if ((m_sh2_state->sr & T) == 0) + { + int32_t disp = ((int32_t)d << 24) >> 24; + m_delay = m_sh2_state->ea = m_sh2_state->pc + disp * 2 + 2; + m_sh2_state->icount--; + } +} + +/* code cycles t-bit + * 1010 dddd dddd dddd 2 - + * BRA disp12 + */ +void sh2_device::BRA(uint32_t d) +{ + int32_t disp = ((int32_t)d << 20) >> 20; + +#if BUSY_LOOP_HACKS + if (disp == -2) + { + uint32_t next_opcode = RW(m_sh2_state->pc & AM); + /* BRA $ + * NOP + */ + if (next_opcode == 0x0009) + m_sh2_state->icount %= 3; /* cycles for BRA $ and NOP taken (3) */ + } +#endif + m_delay = m_sh2_state->ea = m_sh2_state->pc + disp * 2 + 2; + m_sh2_state->icount--; +} + +/* code cycles t-bit + * 0000 mmmm 0010 0011 2 - + * BRAF Rm + */ +void sh2_device::BRAF(uint32_t m) +{ + m_delay = m_sh2_state->pc + m_sh2_state->r[m] + 2; + m_sh2_state->icount--; +} + +/* code cycles t-bit + * 1011 dddd dddd dddd 2 - + * BSR disp12 + */ +void sh2_device::BSR(uint32_t d) +{ + int32_t disp = ((int32_t)d << 20) >> 20; + + m_sh2_state->pr = m_sh2_state->pc + 2; + m_delay = m_sh2_state->ea = m_sh2_state->pc + disp * 2 + 2; + m_sh2_state->icount--; +} + +/* code cycles t-bit + * 0000 mmmm 0000 0011 2 - + * BSRF Rm + */ +void sh2_device::BSRF(uint32_t m) +{ + m_sh2_state->pr = m_sh2_state->pc + 2; + m_delay = m_sh2_state->pc + m_sh2_state->r[m] + 2; + m_sh2_state->icount--; +} + +/* code cycles t-bit + * 1000 1001 dddd dddd 3/1 - + * BT disp8 + */ +void sh2_device::BT(uint32_t d) +{ + if ((m_sh2_state->sr & T) != 0) + { + int32_t disp = ((int32_t)d << 24) >> 24; + m_sh2_state->pc = m_sh2_state->ea = m_sh2_state->pc + disp * 2 + 2; + m_sh2_state->icount -= 2; + } +} + +/* code cycles t-bit + * 1000 1101 dddd dddd 2/1 - + * BTS disp8 + */ +void sh2_device::BTS(uint32_t d) +{ + if ((m_sh2_state->sr & T) != 0) + { + int32_t disp = ((int32_t)d << 24) >> 24; + m_delay = m_sh2_state->ea = m_sh2_state->pc + disp * 2 + 2; + m_sh2_state->icount--; + } +} + +/* code cycles t-bit + * 0000 0000 0010 1000 1 - + * CLRMAC + */ +void sh2_device::CLRMAC() +{ + m_sh2_state->mach = 0; + m_sh2_state->macl = 0; +} + +/* code cycles t-bit + * 0000 0000 0000 1000 1 - + * CLRT + */ +void sh2_device::CLRT() +{ + m_sh2_state->sr &= ~T; +} + +/* code cycles t-bit + * 0011 nnnn mmmm 0000 1 comparison result + * CMP_EQ Rm,Rn + */ +void sh2_device::CMPEQ(uint32_t m, uint32_t n) +{ + if (m_sh2_state->r[n] == m_sh2_state->r[m]) + m_sh2_state->sr |= T; + else + m_sh2_state->sr &= ~T; +} + +/* code cycles t-bit + * 0011 nnnn mmmm 0011 1 comparison result + * CMP_GE Rm,Rn + */ +void sh2_device::CMPGE(uint32_t m, uint32_t n) +{ + if ((int32_t) m_sh2_state->r[n] >= (int32_t) m_sh2_state->r[m]) + m_sh2_state->sr |= T; + else + m_sh2_state->sr &= ~T; +} + +/* code cycles t-bit + * 0011 nnnn mmmm 0111 1 comparison result + * CMP_GT Rm,Rn + */ +void sh2_device::CMPGT(uint32_t m, uint32_t n) +{ + if ((int32_t) m_sh2_state->r[n] > (int32_t) m_sh2_state->r[m]) + m_sh2_state->sr |= T; + else + m_sh2_state->sr &= ~T; +} + +/* code cycles t-bit + * 0011 nnnn mmmm 0110 1 comparison result + * CMP_HI Rm,Rn + */ +void sh2_device::CMPHI(uint32_t m, uint32_t n) +{ + if ((uint32_t) m_sh2_state->r[n] > (uint32_t) m_sh2_state->r[m]) + m_sh2_state->sr |= T; + else + m_sh2_state->sr &= ~T; +} + +/* code cycles t-bit + * 0011 nnnn mmmm 0010 1 comparison result + * CMP_HS Rm,Rn + */ +void sh2_device::CMPHS(uint32_t m, uint32_t n) +{ + if ((uint32_t) m_sh2_state->r[n] >= (uint32_t) m_sh2_state->r[m]) + m_sh2_state->sr |= T; + else + m_sh2_state->sr &= ~T; +} + + +/* code cycles t-bit + * 0100 nnnn 0001 0101 1 comparison result + * CMP_PL Rn + */ +void sh2_device::CMPPL(uint32_t n) +{ + if ((int32_t) m_sh2_state->r[n] > 0) + m_sh2_state->sr |= T; + else + m_sh2_state->sr &= ~T; +} + +/* code cycles t-bit + * 0100 nnnn 0001 0001 1 comparison result + * CMP_PZ Rn + */ +void sh2_device::CMPPZ(uint32_t n) +{ + if ((int32_t) m_sh2_state->r[n] >= 0) + m_sh2_state->sr |= T; + else + m_sh2_state->sr &= ~T; +} + +/* code cycles t-bit + * 0010 nnnn mmmm 1100 1 comparison result + * CMP_STR Rm,Rn + */ +void sh2_device::CMPSTR(uint32_t m, uint32_t n) + { + uint32_t temp; + int32_t HH, HL, LH, LL; + temp = m_sh2_state->r[n] ^ m_sh2_state->r[m]; + HH = (temp >> 24) & 0xff; + HL = (temp >> 16) & 0xff; + LH = (temp >> 8) & 0xff; + LL = temp & 0xff; + if (HH && HL && LH && LL) + m_sh2_state->sr &= ~T; + else + m_sh2_state->sr |= T; + } + + +/* code cycles t-bit + * 1000 1000 iiii iiii 1 comparison result + * CMP/EQ #imm,R0 + */ +void sh2_device::CMPIM(uint32_t i) +{ + uint32_t imm = (uint32_t)(int32_t)(int16_t)(int8_t)i; + + if (m_sh2_state->r[0] == imm) + m_sh2_state->sr |= T; + else + m_sh2_state->sr &= ~T; +} + +/* code cycles t-bit + * 0010 nnnn mmmm 0111 1 calculation result + * DIV0S Rm,Rn + */ +void sh2_device::DIV0S(uint32_t m, uint32_t n) +{ + if ((m_sh2_state->r[n] & 0x80000000) == 0) + m_sh2_state->sr &= ~Q; + else + m_sh2_state->sr |= Q; + if ((m_sh2_state->r[m] & 0x80000000) == 0) + m_sh2_state->sr &= ~M; + else + m_sh2_state->sr |= M; + if ((m_sh2_state->r[m] ^ m_sh2_state->r[n]) & 0x80000000) + m_sh2_state->sr |= T; + else + m_sh2_state->sr &= ~T; +} + +/* code cycles t-bit + * 0000 0000 0001 1001 1 0 + * DIV0U + */ +void sh2_device::DIV0U() +{ + m_sh2_state->sr &= ~(M | Q | T); +} + +/* code cycles t-bit + * 0011 nnnn mmmm 0100 1 calculation result + * DIV1 Rm,Rn + */ +void sh2_device::DIV1(uint32_t m, uint32_t n) +{ + uint32_t tmp0; + uint32_t old_q; + + old_q = m_sh2_state->sr & Q; + if (0x80000000 & m_sh2_state->r[n]) + m_sh2_state->sr |= Q; + else + m_sh2_state->sr &= ~Q; + + m_sh2_state->r[n] = (m_sh2_state->r[n] << 1) | (m_sh2_state->sr & T); + + if (!old_q) + { + if (!(m_sh2_state->sr & M)) + { + tmp0 = m_sh2_state->r[n]; + m_sh2_state->r[n] -= m_sh2_state->r[m]; + if(!(m_sh2_state->sr & Q)) + if(m_sh2_state->r[n] > tmp0) + m_sh2_state->sr |= Q; + else + m_sh2_state->sr &= ~Q; + else + if(m_sh2_state->r[n] > tmp0) + m_sh2_state->sr &= ~Q; + else + m_sh2_state->sr |= Q; + } + else + { + tmp0 = m_sh2_state->r[n]; + m_sh2_state->r[n] += m_sh2_state->r[m]; + if(!(m_sh2_state->sr & Q)) + { + if(m_sh2_state->r[n] < tmp0) + m_sh2_state->sr &= ~Q; + else + m_sh2_state->sr |= Q; + } + else + { + if(m_sh2_state->r[n] < tmp0) + m_sh2_state->sr |= Q; + else + m_sh2_state->sr &= ~Q; + } + } + } + else + { + if (!(m_sh2_state->sr & M)) + { + tmp0 = m_sh2_state->r[n]; + m_sh2_state->r[n] += m_sh2_state->r[m]; + if(!(m_sh2_state->sr & Q)) + if(m_sh2_state->r[n] < tmp0) + m_sh2_state->sr |= Q; + else + m_sh2_state->sr &= ~Q; + else + if(m_sh2_state->r[n] < tmp0) + m_sh2_state->sr &= ~Q; + else + m_sh2_state->sr |= Q; + } + else + { + tmp0 = m_sh2_state->r[n]; + m_sh2_state->r[n] -= m_sh2_state->r[m]; + if(!(m_sh2_state->sr & Q)) + if(m_sh2_state->r[n] > tmp0) + m_sh2_state->sr &= ~Q; + else + m_sh2_state->sr |= Q; + else + if(m_sh2_state->r[n] > tmp0) + m_sh2_state->sr |= Q; + else + m_sh2_state->sr &= ~Q; + } + } + + tmp0 = (m_sh2_state->sr & (Q | M)); + if((!tmp0) || (tmp0 == 0x300)) /* if Q == M set T else clear T */ + m_sh2_state->sr |= T; + else + m_sh2_state->sr &= ~T; +} + +/* DMULS.L Rm,Rn */ +void sh2_device::DMULS(uint32_t m, uint32_t n) +{ + uint32_t RnL, RnH, RmL, RmH, Res0, Res1, Res2; + uint32_t temp0, temp1, temp2, temp3; + int32_t tempm, tempn, fnLmL; + + tempn = (int32_t) m_sh2_state->r[n]; + tempm = (int32_t) m_sh2_state->r[m]; + if (tempn < 0) + tempn = 0 - tempn; + if (tempm < 0) + tempm = 0 - tempm; + if ((int32_t) (m_sh2_state->r[n] ^ m_sh2_state->r[m]) < 0) + fnLmL = -1; + else + fnLmL = 0; + temp1 = (uint32_t) tempn; + temp2 = (uint32_t) tempm; + RnL = temp1 & 0x0000ffff; + RnH = (temp1 >> 16) & 0x0000ffff; + RmL = temp2 & 0x0000ffff; + RmH = (temp2 >> 16) & 0x0000ffff; + temp0 = RmL * RnL; + temp1 = RmH * RnL; + temp2 = RmL * RnH; + temp3 = RmH * RnH; + Res2 = 0; + Res1 = temp1 + temp2; + if (Res1 < temp1) + Res2 += 0x00010000; + temp1 = (Res1 << 16) & 0xffff0000; + Res0 = temp0 + temp1; + if (Res0 < temp0) + Res2++; + Res2 = Res2 + ((Res1 >> 16) & 0x0000ffff) + temp3; + if (fnLmL < 0) + { + Res2 = ~Res2; + if (Res0 == 0) + Res2++; + else + Res0 = (~Res0) + 1; + } + m_sh2_state->mach = Res2; + m_sh2_state->macl = Res0; + m_sh2_state->icount--; +} + +/* DMULU.L Rm,Rn */ +void sh2_device::DMULU(uint32_t m, uint32_t n) +{ + uint32_t RnL, RnH, RmL, RmH, Res0, Res1, Res2; + uint32_t temp0, temp1, temp2, temp3; + + RnL = m_sh2_state->r[n] & 0x0000ffff; + RnH = (m_sh2_state->r[n] >> 16) & 0x0000ffff; + RmL = m_sh2_state->r[m] & 0x0000ffff; + RmH = (m_sh2_state->r[m] >> 16) & 0x0000ffff; + temp0 = RmL * RnL; + temp1 = RmH * RnL; + temp2 = RmL * RnH; + temp3 = RmH * RnH; + Res2 = 0; + Res1 = temp1 + temp2; + if (Res1 < temp1) + Res2 += 0x00010000; + temp1 = (Res1 << 16) & 0xffff0000; + Res0 = temp0 + temp1; + if (Res0 < temp0) + Res2++; + Res2 = Res2 + ((Res1 >> 16) & 0x0000ffff) + temp3; + m_sh2_state->mach = Res2; + m_sh2_state->macl = Res0; + m_sh2_state->icount--; +} + +/* DT Rn */ +void sh2_device::DT(uint32_t n) +{ + m_sh2_state->r[n]--; + if (m_sh2_state->r[n] == 0) + m_sh2_state->sr |= T; + else + m_sh2_state->sr &= ~T; +#if BUSY_LOOP_HACKS + { + uint32_t next_opcode = RW(m_sh2_state->pc & AM); + /* DT Rn + * BF $-2 + */ + if (next_opcode == 0x8bfd) + { + while (m_sh2_state->r[n] > 1 && m_sh2_state->icount > 4) + { + m_sh2_state->r[n]--; + m_sh2_state->icount -= 4; /* cycles for DT (1) and BF taken (3) */ + } + } + } +#endif +} + +/* EXTS.B Rm,Rn */ +void sh2_device::EXTSB(uint32_t m, uint32_t n) +{ + m_sh2_state->r[n] = ((int32_t)m_sh2_state->r[m] << 24) >> 24; +} + +/* EXTS.W Rm,Rn */ +void sh2_device::EXTSW(uint32_t m, uint32_t n) +{ + m_sh2_state->r[n] = ((int32_t)m_sh2_state->r[m] << 16) >> 16; +} + +/* EXTU.B Rm,Rn */ +void sh2_device::EXTUB(uint32_t m, uint32_t n) +{ + m_sh2_state->r[n] = m_sh2_state->r[m] & 0x000000ff; +} + +/* EXTU.W Rm,Rn */ +void sh2_device::EXTUW(uint32_t m, uint32_t n) +{ + m_sh2_state->r[n] = m_sh2_state->r[m] & 0x0000ffff; +} + +/* ILLEGAL */ +void sh2_device::ILLEGAL() +{ + logerror("SH2.%s: Illegal opcode at %08x\n", tag(), m_sh2_state->pc - 2); + m_sh2_state->r[15] -= 4; + WL( 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 */ + + /* fetch PC */ + m_sh2_state->pc = RL( m_sh2_state->vbr + 4 * 4 ); + + /* TODO: timing is a guess */ + m_sh2_state->icount -= 5; +} + + +/* JMP @Rm */ +void sh2_device::JMP(uint32_t m) +{ + m_delay = m_sh2_state->ea = m_sh2_state->r[m]; + m_sh2_state->icount--; +} + +/* JSR @Rm */ +void sh2_device::JSR(uint32_t m) +{ + m_sh2_state->pr = m_sh2_state->pc + 2; + m_delay = m_sh2_state->ea = m_sh2_state->r[m]; + m_sh2_state->icount--; +} + + +/* LDC Rm,SR */ +void sh2_device::LDCSR(uint32_t m) +{ + m_sh2_state->sr = m_sh2_state->r[m] & FLAGS; + m_test_irq = 1; +} + +/* LDC Rm,GBR */ +void sh2_device::LDCGBR(uint32_t m) +{ + m_sh2_state->gbr = m_sh2_state->r[m]; +} + +/* LDC Rm,VBR */ +void sh2_device::LDCVBR(uint32_t m) +{ + m_sh2_state->vbr = m_sh2_state->r[m]; +} + +/* LDC.L @Rm+,SR */ +void sh2_device::LDCMSR(uint32_t m) +{ + m_sh2_state->ea = m_sh2_state->r[m]; + m_sh2_state->sr = RL( m_sh2_state->ea ) & FLAGS; + m_sh2_state->r[m] += 4; + m_sh2_state->icount -= 2; + m_test_irq = 1; +} + +/* LDC.L @Rm+,GBR */ +void sh2_device::LDCMGBR(uint32_t m) +{ + m_sh2_state->ea = m_sh2_state->r[m]; + m_sh2_state->gbr = RL( m_sh2_state->ea ); + m_sh2_state->r[m] += 4; + m_sh2_state->icount -= 2; +} + +/* LDC.L @Rm+,VBR */ +void sh2_device::LDCMVBR(uint32_t m) +{ + m_sh2_state->ea = m_sh2_state->r[m]; + m_sh2_state->vbr = RL( m_sh2_state->ea ); + m_sh2_state->r[m] += 4; + m_sh2_state->icount -= 2; +} + +/* LDS Rm,MACH */ +void sh2_device::LDSMACH(uint32_t m) +{ + m_sh2_state->mach = m_sh2_state->r[m]; +} + +/* LDS Rm,MACL */ +void sh2_device::LDSMACL(uint32_t m) +{ + m_sh2_state->macl = m_sh2_state->r[m]; +} + +/* LDS Rm,PR */ +void sh2_device::LDSPR(uint32_t m) +{ + m_sh2_state->pr = m_sh2_state->r[m]; +} + +/* LDS.L @Rm+,MACH */ +void sh2_device::LDSMMACH(uint32_t m) +{ + m_sh2_state->ea = m_sh2_state->r[m]; + m_sh2_state->mach = RL( m_sh2_state->ea ); + m_sh2_state->r[m] += 4; +} + +/* LDS.L @Rm+,MACL */ +void sh2_device::LDSMMACL(uint32_t m) +{ + m_sh2_state->ea = m_sh2_state->r[m]; + m_sh2_state->macl = RL( m_sh2_state->ea ); + m_sh2_state->r[m] += 4; +} + +/* LDS.L @Rm+,PR */ +void sh2_device::LDSMPR(uint32_t m) +{ + m_sh2_state->ea = m_sh2_state->r[m]; + m_sh2_state->pr = RL( m_sh2_state->ea ); + m_sh2_state->r[m] += 4; +} + +/* MAC.L @Rm+,@Rn+ */ +void sh2_device::MAC_L(uint32_t m, uint32_t n) +{ + uint32_t RnL, RnH, RmL, RmH, Res0, Res1, Res2; + uint32_t temp0, temp1, temp2, temp3; + int32_t tempm, tempn, fnLmL; + + tempn = (int32_t) RL( m_sh2_state->r[n] ); + m_sh2_state->r[n] += 4; + tempm = (int32_t) RL( m_sh2_state->r[m] ); + m_sh2_state->r[m] += 4; + if ((int32_t) (tempn ^ tempm) < 0) + fnLmL = -1; + else + fnLmL = 0; + if (tempn < 0) + tempn = 0 - tempn; + if (tempm < 0) + tempm = 0 - tempm; + temp1 = (uint32_t) tempn; + temp2 = (uint32_t) tempm; + RnL = temp1 & 0x0000ffff; + RnH = (temp1 >> 16) & 0x0000ffff; + RmL = temp2 & 0x0000ffff; + RmH = (temp2 >> 16) & 0x0000ffff; + temp0 = RmL * RnL; + temp1 = RmH * RnL; + temp2 = RmL * RnH; + temp3 = RmH * RnH; + Res2 = 0; + Res1 = temp1 + temp2; + if (Res1 < temp1) + Res2 += 0x00010000; + temp1 = (Res1 << 16) & 0xffff0000; + Res0 = temp0 + temp1; + if (Res0 < temp0) + Res2++; + Res2 = Res2 + ((Res1 >> 16) & 0x0000ffff) + temp3; + if (fnLmL < 0) + { + Res2 = ~Res2; + if (Res0 == 0) + Res2++; + else + Res0 = (~Res0) + 1; + } + if (m_sh2_state->sr & S) + { + Res0 = m_sh2_state->macl + Res0; + if (m_sh2_state->macl > Res0) + Res2++; + Res2 += (m_sh2_state->mach & 0x0000ffff); + if (((int32_t) Res2 < 0) && (Res2 < 0xffff8000)) + { + Res2 = 0x00008000; + Res0 = 0x00000000; + } + else if (((int32_t) Res2 > 0) && (Res2 > 0x00007fff)) + { + Res2 = 0x00007fff; + Res0 = 0xffffffff; + } + m_sh2_state->mach = Res2; + m_sh2_state->macl = Res0; + } + else + { + Res0 = m_sh2_state->macl + Res0; + if (m_sh2_state->macl > Res0) + Res2++; + Res2 += m_sh2_state->mach; + m_sh2_state->mach = Res2; + m_sh2_state->macl = Res0; + } + m_sh2_state->icount -= 2; +} + +/* MAC.W @Rm+,@Rn+ */ +void sh2_device::MAC_W(uint32_t m, uint32_t n) +{ + int32_t tempm, tempn, dest, src, ans; + uint32_t templ; + + tempn = (int32_t) RW( m_sh2_state->r[n] ); + m_sh2_state->r[n] += 2; + tempm = (int32_t) RW( m_sh2_state->r[m] ); + m_sh2_state->r[m] += 2; + templ = m_sh2_state->macl; + tempm = ((int32_t) (short) tempn * (int32_t) (short) tempm); + if ((int32_t) m_sh2_state->macl >= 0) + dest = 0; + else + dest = 1; + if ((int32_t) tempm >= 0) + { + src = 0; + tempn = 0; + } + else + { + src = 1; + tempn = 0xffffffff; + } + src += dest; + m_sh2_state->macl += tempm; + if ((int32_t) m_sh2_state->macl >= 0) + ans = 0; + else + ans = 1; + ans += dest; + if (m_sh2_state->sr & S) + { + if (ans == 1) + { + if (src == 0) + m_sh2_state->macl = 0x7fffffff; + if (src == 2) + m_sh2_state->macl = 0x80000000; + } + } + else + { + m_sh2_state->mach += tempn; + if (templ > m_sh2_state->macl) + m_sh2_state->mach += 1; + } + m_sh2_state->icount -= 2; +} + +/* MOV Rm,Rn */ +void sh2_device::MOV(uint32_t m, uint32_t n) +{ + m_sh2_state->r[n] = m_sh2_state->r[m]; +} + +/* MOV.B Rm,@Rn */ +void sh2_device::MOVBS(uint32_t m, uint32_t n) +{ + m_sh2_state->ea = m_sh2_state->r[n]; + WB( m_sh2_state->ea, m_sh2_state->r[m] & 0x000000ff); +} + +/* MOV.W Rm,@Rn */ +void sh2_device::MOVWS(uint32_t m, uint32_t n) +{ + m_sh2_state->ea = m_sh2_state->r[n]; + WW( m_sh2_state->ea, m_sh2_state->r[m] & 0x0000ffff); +} + +/* MOV.L Rm,@Rn */ +void sh2_device::MOVLS(uint32_t m, uint32_t n) +{ + m_sh2_state->ea = m_sh2_state->r[n]; + WL( m_sh2_state->ea, m_sh2_state->r[m] ); +} + +/* MOV.B @Rm,Rn */ +void sh2_device::MOVBL(uint32_t m, uint32_t n) +{ + m_sh2_state->ea = m_sh2_state->r[m]; + m_sh2_state->r[n] = (uint32_t)(int32_t)(int16_t)(int8_t) RB( m_sh2_state->ea ); +} + +/* MOV.W @Rm,Rn */ +void sh2_device::MOVWL(uint32_t m, uint32_t n) +{ + m_sh2_state->ea = m_sh2_state->r[m]; + m_sh2_state->r[n] = (uint32_t)(int32_t)(int16_t) RW( m_sh2_state->ea ); +} + +/* MOV.L @Rm,Rn */ +void sh2_device::MOVLL(uint32_t m, uint32_t n) +{ + m_sh2_state->ea = m_sh2_state->r[m]; + m_sh2_state->r[n] = RL( m_sh2_state->ea ); +} + +/* MOV.B Rm,@-Rn */ +void sh2_device::MOVBM(uint32_t m, uint32_t n) +{ + /* SMG : bug fix, was reading m_sh2_state->r[n] */ + uint32_t data = m_sh2_state->r[m] & 0x000000ff; + + m_sh2_state->r[n] -= 1; + WB( m_sh2_state->r[n], data ); +} + +/* MOV.W Rm,@-Rn */ +void sh2_device::MOVWM(uint32_t m, uint32_t n) +{ + uint32_t data = m_sh2_state->r[m] & 0x0000ffff; + + m_sh2_state->r[n] -= 2; + WW( m_sh2_state->r[n], data ); +} + +/* MOV.L Rm,@-Rn */ +void sh2_device::MOVLM(uint32_t m, uint32_t n) +{ + uint32_t data = m_sh2_state->r[m]; + + m_sh2_state->r[n] -= 4; + WL( m_sh2_state->r[n], data ); +} + +/* MOV.B @Rm+,Rn */ +void sh2_device::MOVBP(uint32_t m, uint32_t n) +{ + m_sh2_state->r[n] = (uint32_t)(int32_t)(int16_t)(int8_t) RB( m_sh2_state->r[m] ); + if (n != m) + m_sh2_state->r[m] += 1; +} + +/* MOV.W @Rm+,Rn */ +void sh2_device::MOVWP(uint32_t m, uint32_t n) +{ + m_sh2_state->r[n] = (uint32_t)(int32_t)(int16_t) RW( m_sh2_state->r[m] ); + if (n != m) + m_sh2_state->r[m] += 2; +} + +/* MOV.L @Rm+,Rn */ +void sh2_device::MOVLP(uint32_t m, uint32_t n) +{ + m_sh2_state->r[n] = RL( m_sh2_state->r[m] ); + if (n != m) + m_sh2_state->r[m] += 4; +} + +/* MOV.B Rm,@(R0,Rn) */ +void sh2_device::MOVBS0(uint32_t m, uint32_t n) +{ + m_sh2_state->ea = m_sh2_state->r[n] + m_sh2_state->r[0]; + WB( m_sh2_state->ea, m_sh2_state->r[m] & 0x000000ff ); +} + +/* MOV.W Rm,@(R0,Rn) */ +void sh2_device::MOVWS0(uint32_t m, uint32_t n) +{ + m_sh2_state->ea = m_sh2_state->r[n] + m_sh2_state->r[0]; + WW( m_sh2_state->ea, m_sh2_state->r[m] & 0x0000ffff ); +} + +/* MOV.L Rm,@(R0,Rn) */ +void sh2_device::MOVLS0(uint32_t m, uint32_t n) +{ + m_sh2_state->ea = m_sh2_state->r[n] + m_sh2_state->r[0]; + WL( m_sh2_state->ea, m_sh2_state->r[m] ); +} + +/* MOV.B @(R0,Rm),Rn */ +void sh2_device::MOVBL0(uint32_t m, uint32_t n) +{ + m_sh2_state->ea = m_sh2_state->r[m] + m_sh2_state->r[0]; + m_sh2_state->r[n] = (uint32_t)(int32_t)(int16_t)(int8_t) RB( m_sh2_state->ea ); +} + +/* MOV.W @(R0,Rm),Rn */ +void sh2_device::MOVWL0(uint32_t m, uint32_t n) +{ + m_sh2_state->ea = m_sh2_state->r[m] + m_sh2_state->r[0]; + m_sh2_state->r[n] = (uint32_t)(int32_t)(int16_t) RW( m_sh2_state->ea ); +} + +/* MOV.L @(R0,Rm),Rn */ +void sh2_device::MOVLL0(uint32_t m, uint32_t n) +{ + m_sh2_state->ea = m_sh2_state->r[m] + m_sh2_state->r[0]; + m_sh2_state->r[n] = RL( m_sh2_state->ea ); +} + +/* MOV #imm,Rn */ +void sh2_device::MOVI(uint32_t i, uint32_t n) +{ + m_sh2_state->r[n] = (uint32_t)(int32_t)(int16_t)(int8_t) i; +} + +/* MOV.W @(disp8,PC),Rn */ +void sh2_device::MOVWI(uint32_t d, uint32_t n) +{ + uint32_t disp = d & 0xff; + m_sh2_state->ea = m_sh2_state->pc + disp * 2 + 2; + m_sh2_state->r[n] = (uint32_t)(int32_t)(int16_t) RW( m_sh2_state->ea ); +} + +/* MOV.L @(disp8,PC),Rn */ +void sh2_device::MOVLI(uint32_t d, uint32_t n) +{ + uint32_t disp = d & 0xff; + m_sh2_state->ea = ((m_sh2_state->pc + 2) & ~3) + disp * 4; + m_sh2_state->r[n] = RL( m_sh2_state->ea ); +} + +/* MOV.B @(disp8,GBR),R0 */ +void sh2_device::MOVBLG(uint32_t d) +{ + uint32_t disp = d & 0xff; + m_sh2_state->ea = m_sh2_state->gbr + disp; + m_sh2_state->r[0] = (uint32_t)(int32_t)(int16_t)(int8_t) RB( m_sh2_state->ea ); +} + +/* MOV.W @(disp8,GBR),R0 */ +void sh2_device::MOVWLG(uint32_t d) +{ + uint32_t disp = d & 0xff; + m_sh2_state->ea = m_sh2_state->gbr + disp * 2; + m_sh2_state->r[0] = (int32_t)(int16_t) RW( m_sh2_state->ea ); +} + +/* MOV.L @(disp8,GBR),R0 */ +void sh2_device::MOVLLG(uint32_t d) +{ + uint32_t disp = d & 0xff; + m_sh2_state->ea = m_sh2_state->gbr + disp * 4; + m_sh2_state->r[0] = RL( m_sh2_state->ea ); +} + +/* MOV.B R0,@(disp8,GBR) */ +void sh2_device::MOVBSG(uint32_t d) +{ + uint32_t disp = d & 0xff; + m_sh2_state->ea = m_sh2_state->gbr + disp; + WB( m_sh2_state->ea, m_sh2_state->r[0] & 0x000000ff ); +} + +/* MOV.W R0,@(disp8,GBR) */ +void sh2_device::MOVWSG(uint32_t d) +{ + uint32_t disp = d & 0xff; + m_sh2_state->ea = m_sh2_state->gbr + disp * 2; + WW( m_sh2_state->ea, m_sh2_state->r[0] & 0x0000ffff ); +} + +/* MOV.L R0,@(disp8,GBR) */ +void sh2_device::MOVLSG(uint32_t d) +{ + uint32_t disp = d & 0xff; + m_sh2_state->ea = m_sh2_state->gbr + disp * 4; + WL( m_sh2_state->ea, m_sh2_state->r[0] ); +} + +/* MOV.B R0,@(disp4,Rn) */ +void sh2_device::MOVBS4(uint32_t d, uint32_t n) +{ + uint32_t disp = d & 0x0f; + m_sh2_state->ea = m_sh2_state->r[n] + disp; + WB( m_sh2_state->ea, m_sh2_state->r[0] & 0x000000ff ); +} + +/* MOV.W R0,@(disp4,Rn) */ +void sh2_device::MOVWS4(uint32_t d, uint32_t n) +{ + uint32_t disp = d & 0x0f; + m_sh2_state->ea = m_sh2_state->r[n] + disp * 2; + WW( m_sh2_state->ea, m_sh2_state->r[0] & 0x0000ffff ); +} + +/* MOV.L Rm,@(disp4,Rn) */ +void sh2_device::MOVLS4(uint32_t m, uint32_t d, uint32_t n) +{ + uint32_t disp = d & 0x0f; + m_sh2_state->ea = m_sh2_state->r[n] + disp * 4; + WL( m_sh2_state->ea, m_sh2_state->r[m] ); +} + +/* MOV.B @(disp4,Rm),R0 */ +void sh2_device::MOVBL4(uint32_t m, uint32_t d) +{ + uint32_t disp = d & 0x0f; + m_sh2_state->ea = m_sh2_state->r[m] + disp; + m_sh2_state->r[0] = (uint32_t)(int32_t)(int16_t)(int8_t) RB( m_sh2_state->ea ); +} + +/* MOV.W @(disp4,Rm),R0 */ +void sh2_device::MOVWL4(uint32_t m, uint32_t d) +{ + uint32_t disp = d & 0x0f; + m_sh2_state->ea = m_sh2_state->r[m] + disp * 2; + m_sh2_state->r[0] = (uint32_t)(int32_t)(int16_t) RW( m_sh2_state->ea ); +} + +/* MOV.L @(disp4,Rm),Rn */ +void sh2_device::MOVLL4(uint32_t m, uint32_t d, uint32_t n) +{ + uint32_t disp = d & 0x0f; + m_sh2_state->ea = m_sh2_state->r[m] + disp * 4; + m_sh2_state->r[n] = RL( m_sh2_state->ea ); +} + +/* MOVA @(disp8,PC),R0 */ +void sh2_device::MOVA(uint32_t d) +{ + uint32_t disp = d & 0xff; + m_sh2_state->ea = ((m_sh2_state->pc + 2) & ~3) + disp * 4; + m_sh2_state->r[0] = m_sh2_state->ea; +} + +/* MOVT Rn */ +void sh2_device::MOVT(uint32_t n) +{ + m_sh2_state->r[n] = m_sh2_state->sr & T; +} + +/* MUL.L Rm,Rn */ +void sh2_device::MULL(uint32_t m, uint32_t n) +{ + m_sh2_state->macl = m_sh2_state->r[n] * m_sh2_state->r[m]; + m_sh2_state->icount--; +} + +/* MULS Rm,Rn */ +void sh2_device::MULS(uint32_t m, uint32_t n) +{ + m_sh2_state->macl = (int16_t) m_sh2_state->r[n] * (int16_t) m_sh2_state->r[m]; +} + +/* MULU Rm,Rn */ +void sh2_device::MULU(uint32_t m, uint32_t n) +{ + m_sh2_state->macl = (uint16_t) m_sh2_state->r[n] * (uint16_t) m_sh2_state->r[m]; +} + +/* NEG Rm,Rn */ +void sh2_device::NEG(uint32_t m, uint32_t n) +{ + m_sh2_state->r[n] = 0 - m_sh2_state->r[m]; +} + +/* NEGC Rm,Rn */ +void sh2_device::NEGC(uint32_t m, uint32_t n) +{ + uint32_t temp; + + temp = m_sh2_state->r[m]; + m_sh2_state->r[n] = -temp - (m_sh2_state->sr & T); + if (temp || (m_sh2_state->sr & T)) + m_sh2_state->sr |= T; + else + m_sh2_state->sr &= ~T; +} + +/* NOP */ +void sh2_device::NOP(void) +{ +} + +/* NOT Rm,Rn */ +void sh2_device::NOT(uint32_t m, uint32_t n) +{ + m_sh2_state->r[n] = ~m_sh2_state->r[m]; +} + +/* OR Rm,Rn */ +void sh2_device::OR(uint32_t m, uint32_t n) +{ + m_sh2_state->r[n] |= m_sh2_state->r[m]; +} + +/* OR #imm,R0 */ +void sh2_device::ORI(uint32_t i) +{ + m_sh2_state->r[0] |= i; +} + +/* OR.B #imm,@(R0,GBR) */ +void sh2_device::ORM(uint32_t i) +{ + uint32_t temp; + + m_sh2_state->ea = m_sh2_state->gbr + m_sh2_state->r[0]; + temp = RB( m_sh2_state->ea ); + temp |= i; + WB( m_sh2_state->ea, temp ); + m_sh2_state->icount -= 2; +} + +/* ROTCL Rn */ +void sh2_device::ROTCL(uint32_t n) +{ + uint32_t temp; + + temp = (m_sh2_state->r[n] >> 31) & T; + m_sh2_state->r[n] = (m_sh2_state->r[n] << 1) | (m_sh2_state->sr & T); + m_sh2_state->sr = (m_sh2_state->sr & ~T) | temp; +} + +/* ROTCR Rn */ +void sh2_device::ROTCR(uint32_t n) +{ + uint32_t temp; + temp = (m_sh2_state->sr & T) << 31; + if (m_sh2_state->r[n] & T) + m_sh2_state->sr |= T; + else + m_sh2_state->sr &= ~T; + m_sh2_state->r[n] = (m_sh2_state->r[n] >> 1) | temp; +} + +/* ROTL Rn */ +void sh2_device::ROTL(uint32_t n) +{ + m_sh2_state->sr = (m_sh2_state->sr & ~T) | ((m_sh2_state->r[n] >> 31) & T); + m_sh2_state->r[n] = (m_sh2_state->r[n] << 1) | (m_sh2_state->r[n] >> 31); +} + +/* ROTR Rn */ +void sh2_device::ROTR(uint32_t n) +{ + m_sh2_state->sr = (m_sh2_state->sr & ~T) | (m_sh2_state->r[n] & T); + m_sh2_state->r[n] = (m_sh2_state->r[n] >> 1) | (m_sh2_state->r[n] << 31); +} + +/* RTE */ +void sh2_device::RTE() +{ + m_sh2_state->ea = m_sh2_state->r[15]; + m_delay = RL( 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 ) & FLAGS; + m_sh2_state->r[15] += 4; + m_sh2_state->icount -= 3; + m_test_irq = 1; +} + +/* RTS */ +void sh2_device::RTS() +{ + m_delay = m_sh2_state->ea = m_sh2_state->pr; + m_sh2_state->icount--; +} + +/* SETT */ +void sh2_device::SETT() +{ + m_sh2_state->sr |= T; +} + +/* SHAL Rn (same as SHLL) */ +void sh2_device::SHAL(uint32_t n) +{ + m_sh2_state->sr = (m_sh2_state->sr & ~T) | ((m_sh2_state->r[n] >> 31) & T); + m_sh2_state->r[n] <<= 1; +} + +/* SHAR Rn */ +void sh2_device::SHAR(uint32_t n) +{ + m_sh2_state->sr = (m_sh2_state->sr & ~T) | (m_sh2_state->r[n] & T); + m_sh2_state->r[n] = (uint32_t)((int32_t)m_sh2_state->r[n] >> 1); +} + +/* SHLL Rn (same as SHAL) */ +void sh2_device::SHLL(uint32_t n) +{ + m_sh2_state->sr = (m_sh2_state->sr & ~T) | ((m_sh2_state->r[n] >> 31) & T); + m_sh2_state->r[n] <<= 1; +} + +/* SHLL2 Rn */ +void sh2_device::SHLL2(uint32_t n) +{ + m_sh2_state->r[n] <<= 2; +} + +/* SHLL8 Rn */ +void sh2_device::SHLL8(uint32_t n) +{ + m_sh2_state->r[n] <<= 8; +} + +/* SHLL16 Rn */ +void sh2_device::SHLL16(uint32_t n) +{ + m_sh2_state->r[n] <<= 16; +} + +/* SHLR Rn */ +void sh2_device::SHLR(uint32_t n) +{ + m_sh2_state->sr = (m_sh2_state->sr & ~T) | (m_sh2_state->r[n] & T); + m_sh2_state->r[n] >>= 1; +} + +/* SHLR2 Rn */ +void sh2_device::SHLR2(uint32_t n) +{ + m_sh2_state->r[n] >>= 2; +} + +/* SHLR8 Rn */ +void sh2_device::SHLR8(uint32_t n) +{ + m_sh2_state->r[n] >>= 8; +} + +/* SHLR16 Rn */ +void sh2_device::SHLR16(uint32_t n) +{ + m_sh2_state->r[n] >>= 16; +} + +/* SLEEP */ +void sh2_device::SLEEP() +{ + if(m_sh2_state->sleep_mode != 2) + m_sh2_state->pc -= 2; + m_sh2_state->icount -= 2; + /* Wait_for_exception; */ + if(m_sh2_state->sleep_mode == 0) + m_sh2_state->sleep_mode = 1; + else if(m_sh2_state->sleep_mode == 2) + m_sh2_state->sleep_mode = 0; +} + +/* STC SR,Rn */ +void sh2_device::STCSR(uint32_t n) +{ + m_sh2_state->r[n] = m_sh2_state->sr; +} + +/* STC GBR,Rn */ +void sh2_device::STCGBR(uint32_t n) +{ + m_sh2_state->r[n] = m_sh2_state->gbr; +} + +/* STC VBR,Rn */ +void sh2_device::STCVBR(uint32_t n) +{ + m_sh2_state->r[n] = m_sh2_state->vbr; +} + +/* STC.L SR,@-Rn */ +void sh2_device::STCMSR(uint32_t n) +{ + m_sh2_state->r[n] -= 4; + m_sh2_state->ea = m_sh2_state->r[n]; + WL( m_sh2_state->ea, m_sh2_state->sr ); + m_sh2_state->icount--; +} + +/* STC.L GBR,@-Rn */ +void sh2_device::STCMGBR(uint32_t n) +{ + m_sh2_state->r[n] -= 4; + m_sh2_state->ea = m_sh2_state->r[n]; + WL( m_sh2_state->ea, m_sh2_state->gbr ); + m_sh2_state->icount--; +} + +/* STC.L VBR,@-Rn */ +void sh2_device::STCMVBR(uint32_t n) +{ + m_sh2_state->r[n] -= 4; + m_sh2_state->ea = m_sh2_state->r[n]; + WL( m_sh2_state->ea, m_sh2_state->vbr ); + m_sh2_state->icount--; +} + +/* STS MACH,Rn */ +void sh2_device::STSMACH(uint32_t n) +{ + m_sh2_state->r[n] = m_sh2_state->mach; +} + +/* STS MACL,Rn */ +void sh2_device::STSMACL(uint32_t n) +{ + m_sh2_state->r[n] = m_sh2_state->macl; +} + +/* STS PR,Rn */ +void sh2_device::STSPR(uint32_t n) +{ + m_sh2_state->r[n] = m_sh2_state->pr; +} + +/* STS.L MACH,@-Rn */ +void sh2_device::STSMMACH(uint32_t n) +{ + m_sh2_state->r[n] -= 4; + m_sh2_state->ea = m_sh2_state->r[n]; + WL( m_sh2_state->ea, m_sh2_state->mach ); +} + +/* STS.L MACL,@-Rn */ +void sh2_device::STSMMACL(uint32_t n) +{ + m_sh2_state->r[n] -= 4; + m_sh2_state->ea = m_sh2_state->r[n]; + WL( m_sh2_state->ea, m_sh2_state->macl ); +} + +/* STS.L PR,@-Rn */ +void sh2_device::STSMPR(uint32_t n) +{ + m_sh2_state->r[n] -= 4; + m_sh2_state->ea = m_sh2_state->r[n]; + WL( m_sh2_state->ea, m_sh2_state->pr ); +} + +/* SUB Rm,Rn */ +void sh2_device::SUB(uint32_t m, uint32_t n) +{ + m_sh2_state->r[n] -= m_sh2_state->r[m]; +} + +/* SUBC Rm,Rn */ +void sh2_device::SUBC(uint32_t m, uint32_t n) +{ + uint32_t tmp0, tmp1; + + tmp1 = m_sh2_state->r[n] - m_sh2_state->r[m]; + tmp0 = m_sh2_state->r[n]; + m_sh2_state->r[n] = tmp1 - (m_sh2_state->sr & T); + if (tmp0 < tmp1) + m_sh2_state->sr |= T; + else + m_sh2_state->sr &= ~T; + if (tmp1 < m_sh2_state->r[n]) + m_sh2_state->sr |= T; +} + +/* SUBV Rm,Rn */ +void sh2_device::SUBV(uint32_t m, uint32_t n) +{ + int32_t dest, src, ans; + + if ((int32_t) m_sh2_state->r[n] >= 0) + dest = 0; + else + dest = 1; + if ((int32_t) m_sh2_state->r[m] >= 0) + src = 0; + else + src = 1; + src += dest; + m_sh2_state->r[n] -= m_sh2_state->r[m]; + if ((int32_t) m_sh2_state->r[n] >= 0) + ans = 0; + else + ans = 1; + ans += dest; + if (src == 1) + { + if (ans == 1) + m_sh2_state->sr |= T; + else + m_sh2_state->sr &= ~T; + } + else + m_sh2_state->sr &= ~T; +} + +/* SWAP.B Rm,Rn */ +void sh2_device::SWAPB(uint32_t m, uint32_t n) +{ + uint32_t temp0, temp1; + + temp0 = m_sh2_state->r[m] & 0xffff0000; + temp1 = (m_sh2_state->r[m] & 0x000000ff) << 8; + m_sh2_state->r[n] = (m_sh2_state->r[m] >> 8) & 0x000000ff; + m_sh2_state->r[n] = m_sh2_state->r[n] | temp1 | temp0; +} + +/* SWAP.W Rm,Rn */ +void sh2_device::SWAPW(uint32_t m, uint32_t n) +{ + uint32_t temp; + + temp = (m_sh2_state->r[m] >> 16) & 0x0000ffff; + m_sh2_state->r[n] = (m_sh2_state->r[m] << 16) | temp; +} + +/* TAS.B @Rn */ +void sh2_device::TAS(uint32_t n) +{ + uint32_t temp; + m_sh2_state->ea = m_sh2_state->r[n]; + /* Bus Lock enable */ + temp = RB( m_sh2_state->ea ); + if (temp == 0) + m_sh2_state->sr |= T; + else + m_sh2_state->sr &= ~T; + temp |= 0x80; + /* Bus Lock disable */ + WB( m_sh2_state->ea, temp ); + m_sh2_state->icount -= 3; +} + +/* TRAPA #imm */ +void sh2_device::TRAPA(uint32_t i) +{ + uint32_t imm = i & 0xff; + + 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 ); + m_sh2_state->r[15] -= 4; + WL( m_sh2_state->r[15], m_sh2_state->pc ); + + m_sh2_state->pc = RL( m_sh2_state->ea ); + + m_sh2_state->icount -= 7; +} + +/* TST Rm,Rn */ +void sh2_device::TST(uint32_t m, uint32_t n) +{ + if ((m_sh2_state->r[n] & m_sh2_state->r[m]) == 0) + m_sh2_state->sr |= T; + else + m_sh2_state->sr &= ~T; +} + +/* TST #imm,R0 */ +void sh2_device::TSTI(uint32_t i) +{ + uint32_t imm = i & 0xff; + + if ((imm & m_sh2_state->r[0]) == 0) + m_sh2_state->sr |= T; + else + m_sh2_state->sr &= ~T; +} + +/* TST.B #imm,@(R0,GBR) */ +void sh2_device::TSTM(uint32_t i) +{ + uint32_t imm = i & 0xff; + + m_sh2_state->ea = m_sh2_state->gbr + m_sh2_state->r[0]; + if ((imm & RB( m_sh2_state->ea )) == 0) + m_sh2_state->sr |= T; + else + m_sh2_state->sr &= ~T; + m_sh2_state->icount -= 2; +} + +/* XOR Rm,Rn */ +void sh2_device::XOR(uint32_t m, uint32_t n) +{ + m_sh2_state->r[n] ^= m_sh2_state->r[m]; +} + +/* XOR #imm,R0 */ +void sh2_device::XORI(uint32_t i) +{ + uint32_t imm = i & 0xff; + m_sh2_state->r[0] ^= imm; +} + +/* XOR.B #imm,@(R0,GBR) */ +void sh2_device::XORM(uint32_t i) +{ + uint32_t imm = i & 0xff; + uint32_t temp; + + m_sh2_state->ea = m_sh2_state->gbr + m_sh2_state->r[0]; + temp = RB( m_sh2_state->ea ); + temp ^= imm; + WB( m_sh2_state->ea, temp ); + m_sh2_state->icount -= 2; +} + +/* XTRCT Rm,Rn */ +void sh2_device::XTRCT(uint32_t m, uint32_t n) +{ + uint32_t temp; + + temp = (m_sh2_state->r[m] << 16) & 0xffff0000; + m_sh2_state->r[n] = (m_sh2_state->r[n] >> 16) & 0x0000ffff; + m_sh2_state->r[n] |= temp; +} + +/***************************************************************************** + * OPCODE DISPATCHERS + *****************************************************************************/ + +void sh2_device::op0000(uint16_t opcode) +{ + switch (opcode & 0x3F) + { + case 0x00: ILLEGAL(); break; + case 0x01: ILLEGAL(); break; + case 0x02: STCSR(Rn); break; + case 0x03: BSRF(Rn); break; + case 0x04: MOVBS0(Rm, Rn); break; + case 0x05: MOVWS0(Rm, Rn); break; + case 0x06: MOVLS0(Rm, Rn); break; + case 0x07: MULL(Rm, Rn); break; + case 0x08: CLRT(); break; + case 0x09: NOP(); break; + case 0x0a: STSMACH(Rn); break; + case 0x0b: RTS(); break; + case 0x0c: MOVBL0(Rm, Rn); break; + case 0x0d: MOVWL0(Rm, Rn); break; + case 0x0e: MOVLL0(Rm, Rn); break; + case 0x0f: MAC_L(Rm, Rn); break; + + case 0x10: ILLEGAL(); break; + case 0x11: ILLEGAL(); break; + case 0x12: STCGBR(Rn); break; + case 0x13: ILLEGAL(); break; + case 0x14: MOVBS0(Rm, Rn); break; + case 0x15: MOVWS0(Rm, Rn); break; + case 0x16: MOVLS0(Rm, Rn); break; + case 0x17: MULL(Rm, Rn); break; + case 0x18: SETT(); break; + case 0x19: DIV0U(); break; + case 0x1a: STSMACL(Rn); break; + case 0x1b: SLEEP(); break; + case 0x1c: MOVBL0(Rm, Rn); break; + case 0x1d: MOVWL0(Rm, Rn); break; + case 0x1e: MOVLL0(Rm, Rn); break; + case 0x1f: MAC_L(Rm, Rn); break; + + case 0x20: ILLEGAL(); break; + case 0x21: ILLEGAL(); break; + case 0x22: STCVBR(Rn); break; + case 0x23: BRAF(Rn); break; + case 0x24: MOVBS0(Rm, Rn); break; + case 0x25: MOVWS0(Rm, Rn); break; + case 0x26: MOVLS0(Rm, Rn); break; + case 0x27: MULL(Rm, Rn); break; + case 0x28: CLRMAC(); break; + case 0x29: MOVT(Rn); break; + case 0x2a: STSPR(Rn); break; + case 0x2b: RTE(); break; + case 0x2c: MOVBL0(Rm, Rn); break; + case 0x2d: MOVWL0(Rm, Rn); break; + case 0x2e: MOVLL0(Rm, Rn); break; + case 0x2f: MAC_L(Rm, Rn); break; + + case 0x30: ILLEGAL(); break; + case 0x31: ILLEGAL(); break; + case 0x32: ILLEGAL(); break; + case 0x33: ILLEGAL(); break; + case 0x34: MOVBS0(Rm, Rn); break; + case 0x35: MOVWS0(Rm, Rn); break; + case 0x36: MOVLS0(Rm, Rn); break; + case 0x37: MULL(Rm, Rn); break; + case 0x38: ILLEGAL(); break; + case 0x39: ILLEGAL(); break; + case 0x3c: MOVBL0(Rm, Rn); break; + case 0x3d: MOVWL0(Rm, Rn); break; + case 0x3e: MOVLL0(Rm, Rn); break; + case 0x3f: MAC_L(Rm, Rn); break; + case 0x3a: ILLEGAL(); break; + case 0x3b: ILLEGAL(); break; + + + + } +} + +void sh2_device::op0001(uint16_t opcode) +{ + MOVLS4(Rm, opcode & 0x0f, Rn); +} + +void sh2_device::op0010(uint16_t opcode) +{ + switch (opcode & 15) + { + case 0: MOVBS(Rm, Rn); break; + case 1: MOVWS(Rm, Rn); break; + case 2: MOVLS(Rm, Rn); break; + case 3: ILLEGAL(); break; + case 4: MOVBM(Rm, Rn); break; + case 5: MOVWM(Rm, Rn); break; + case 6: MOVLM(Rm, Rn); break; + case 7: DIV0S(Rm, Rn); break; + case 8: TST(Rm, Rn); break; + case 9: AND(Rm, Rn); break; + case 10: XOR(Rm, Rn); break; + case 11: OR(Rm, Rn); break; + case 12: CMPSTR(Rm, Rn); break; + case 13: XTRCT(Rm, Rn); break; + case 14: MULU(Rm, Rn); break; + case 15: MULS(Rm, Rn); break; + } +} + +void sh2_device::op0011(uint16_t opcode) +{ + switch (opcode & 15) + { + case 0: CMPEQ(Rm, Rn); break; + case 1: ILLEGAL(); break; + case 2: CMPHS(Rm, Rn); break; + case 3: CMPGE(Rm, Rn); break; + case 4: DIV1(Rm, Rn); break; + case 5: DMULU(Rm, Rn); break; + case 6: CMPHI(Rm, Rn); break; + case 7: CMPGT(Rm, Rn); break; + case 8: SUB(Rm, Rn); break; + case 9: ILLEGAL(); break; + case 10: SUBC(Rm, Rn); break; + case 11: SUBV(Rm, Rn); break; + case 12: ADD(Rm, Rn); break; + case 13: DMULS(Rm, Rn); break; + case 14: ADDC(Rm, Rn); break; + case 15: ADDV(Rm, Rn); break; + } +} + +void sh2_device::op0100(uint16_t opcode) +{ + switch (opcode & 0x3F) + { + case 0x00: SHLL(Rn); break; + case 0x01: SHLR(Rn); break; + case 0x02: STSMMACH(Rn); break; + case 0x03: STCMSR(Rn); break; + case 0x04: ROTL(Rn); break; + case 0x05: ROTR(Rn); break; + case 0x06: LDSMMACH(Rn); break; + case 0x07: LDCMSR(Rn); break; + case 0x08: SHLL2(Rn); break; + case 0x09: SHLR2(Rn); break; + case 0x0a: LDSMACH(Rn); break; + case 0x0b: JSR(Rn); break; + case 0x0c: ILLEGAL(); break; + case 0x0d: ILLEGAL(); break; + case 0x0e: LDCSR(Rn); break; + case 0x0f: MAC_W(Rm, Rn); break; + + case 0x10: DT(Rn); break; + case 0x11: CMPPZ(Rn); break; + case 0x12: STSMMACL(Rn); break; + case 0x13: STCMGBR(Rn); break; + case 0x14: ILLEGAL(); break; + case 0x15: CMPPL(Rn); break; + case 0x16: LDSMMACL(Rn); break; + case 0x17: LDCMGBR(Rn); break; + case 0x18: SHLL8(Rn); break; + case 0x19: SHLR8(Rn); break; + case 0x1a: LDSMACL(Rn); break; + case 0x1b: TAS(Rn); break; + case 0x1c: ILLEGAL(); break; + case 0x1d: ILLEGAL(); break; + case 0x1e: LDCGBR(Rn); break; + case 0x1f: MAC_W(Rm, Rn); break; + + case 0x20: SHAL(Rn); break; + case 0x21: SHAR(Rn); break; + case 0x22: STSMPR(Rn); break; + case 0x23: STCMVBR(Rn); break; + case 0x24: ROTCL(Rn); break; + case 0x25: ROTCR(Rn); break; + case 0x26: LDSMPR(Rn); break; + case 0x27: LDCMVBR(Rn); break; + case 0x28: SHLL16(Rn); break; + case 0x29: SHLR16(Rn); break; + case 0x2a: LDSPR(Rn); break; + case 0x2b: JMP(Rn); break; + case 0x2c: ILLEGAL(); break; + case 0x2d: ILLEGAL(); break; + case 0x2e: LDCVBR(Rn); break; + case 0x2f: MAC_W(Rm, Rn); break; + + case 0x30: ILLEGAL(); break; + case 0x31: ILLEGAL(); break; + case 0x32: ILLEGAL(); break; + case 0x33: ILLEGAL(); break; + case 0x34: ILLEGAL(); break; + case 0x35: ILLEGAL(); break; + case 0x36: ILLEGAL(); break; + case 0x37: ILLEGAL(); break; + case 0x38: ILLEGAL(); break; + case 0x39: ILLEGAL(); break; + case 0x3a: ILLEGAL(); break; + case 0x3b: ILLEGAL(); break; + case 0x3c: ILLEGAL(); break; + case 0x3d: ILLEGAL(); break; + case 0x3e: ILLEGAL(); break; + case 0x3f: MAC_W(Rm, Rn); break; + + } +} + +void sh2_device::op0101(uint16_t opcode) +{ + MOVLL4(Rm, opcode & 0x0f, Rn); +} + +void sh2_device::op0110(uint16_t opcode) +{ + switch (opcode & 15) + { + case 0: MOVBL(Rm, Rn); break; + case 1: MOVWL(Rm, Rn); break; + case 2: MOVLL(Rm, Rn); break; + case 3: MOV(Rm, Rn); break; + case 4: MOVBP(Rm, Rn); break; + case 5: MOVWP(Rm, Rn); break; + case 6: MOVLP(Rm, Rn); break; + case 7: NOT(Rm, Rn); break; + case 8: SWAPB(Rm, Rn); break; + case 9: SWAPW(Rm, Rn); break; + case 10: NEGC(Rm, Rn); break; + case 11: NEG(Rm, Rn); break; + case 12: EXTUB(Rm, Rn); break; + case 13: EXTUW(Rm, Rn); break; + case 14: EXTSB(Rm, Rn); break; + case 15: EXTSW(Rm, Rn); break; + } +} + +void sh2_device::op0111(uint16_t opcode) +{ + ADDI(opcode & 0xff, Rn); +} + +void sh2_device::op1000(uint16_t opcode) +{ + switch ( opcode & (15<<8) ) + { + case 0 << 8: MOVBS4(opcode & 0x0f, Rm); break; + case 1 << 8: MOVWS4(opcode & 0x0f, Rm); break; + case 2<< 8: ILLEGAL(); break; + case 3<< 8: ILLEGAL(); break; + case 4<< 8: MOVBL4(Rm, opcode & 0x0f); break; + case 5<< 8: MOVWL4(Rm, opcode & 0x0f); break; + case 6<< 8: ILLEGAL(); break; + case 7<< 8: ILLEGAL(); break; + case 8<< 8: CMPIM(opcode & 0xff); break; + case 9<< 8: BT(opcode & 0xff); break; + case 10<< 8: ILLEGAL(); break; + case 11<< 8: BF(opcode & 0xff); break; + case 12<< 8: ILLEGAL(); break; + case 13<< 8: BTS(opcode & 0xff); break; + case 14<< 8: ILLEGAL(); break; + case 15<< 8: BFS(opcode & 0xff); break; + } +} + + +void sh2_device::op1001(uint16_t opcode) +{ + MOVWI(opcode & 0xff, Rn); +} + +void sh2_device::op1010(uint16_t opcode) +{ + BRA(opcode & 0xfff); +} + +void sh2_device::op1011(uint16_t opcode) +{ + BSR(opcode & 0xfff); +} + +void sh2_device::op1100(uint16_t opcode) +{ + switch (opcode & (15<<8)) + { + case 0<<8: MOVBSG(opcode & 0xff); break; + case 1<<8: MOVWSG(opcode & 0xff); break; + case 2<<8: MOVLSG(opcode & 0xff); break; + case 3<<8: TRAPA(opcode & 0xff); break; + case 4<<8: MOVBLG(opcode & 0xff); break; + case 5<<8: MOVWLG(opcode & 0xff); break; + case 6<<8: MOVLLG(opcode & 0xff); break; + case 7<<8: MOVA(opcode & 0xff); break; + case 8<<8: TSTI(opcode & 0xff); break; + case 9<<8: ANDI(opcode & 0xff); break; + case 10<<8: XORI(opcode & 0xff); break; + case 11<<8: ORI(opcode & 0xff); break; + case 12<<8: TSTM(opcode & 0xff); break; + case 13<<8: ANDM(opcode & 0xff); break; + case 14<<8: XORM(opcode & 0xff); break; + case 15<<8: ORM(opcode & 0xff); break; + } +} + +void sh2_device::op1101(uint16_t opcode) +{ + MOVLI(opcode & 0xff, Rn); +} + +void sh2_device::op1110(uint16_t opcode) +{ + MOVI(opcode & 0xff, Rn); +} + +void sh2_device::op1111(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_delay = m_cpu_off = 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_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; + + memset(m_m, 0, 0x200); + + m_sh2_state->pc = RL(0); + m_sh2_state->r[15] = RL(4); + m_sh2_state->sr = 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 ) + { + execute_run_drc(); + return; + } + + if (m_cpu_off) + { + m_sh2_state->icount = 0; + return; + } + + // run any active DMAs now +#ifndef USE_TIMER_FOR_DMA + for ( int i = 0; i < m_sh2_state->icount ; i++) + { + for( int dma=0;dma<1;dma++) + { + if (m_dma_timer_active[dma]) + sh2_do_dma(dma); + } + } +#endif + + do + { + uint32_t opcode; + + debugger_instruction_hook(this, m_sh2_state->pc); + + opcode = m_program->read_word(m_sh2_state->pc & AM); + + if (m_delay) + { + m_sh2_state->pc = m_delay; + m_delay = 0; + } + else + m_sh2_state->pc += 2; + + switch (opcode & ( 15 << 12)) + { + case 0<<12: op0000(opcode); break; + case 1<<12: op0001(opcode); break; + case 2<<12: op0010(opcode); break; + case 3<<12: op0011(opcode); break; + case 4<<12: op0100(opcode); break; + case 5<<12: op0101(opcode); break; + case 6<<12: op0110(opcode); break; + case 7<<12: op0111(opcode); break; + case 8<<12: op1000(opcode); break; + case 9<<12: op1001(opcode); break; + case 10<<12: op1010(opcode); break; + case 11<<12: op1011(opcode); break; + case 12<<12: op1100(opcode); break; + case 13<<12: op1101(opcode); break; + case 14<<12: op1110(opcode); break; + default: op1111(opcode); break; + } + + if(m_test_irq && !m_delay) + { + CHECK_PENDING_IRQ("mame_sh2_execute"); + m_test_irq = 0; + } + m_sh2_state->icount--; + } while( m_sh2_state->icount > 0 ); +} + +void sh2_device::device_start() +{ + /* allocate the implementation-specific state from the full cache */ + m_sh2_state = (internal_sh2_state *)m_cache.alloc_near(sizeof(internal_sh2_state)); + + 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_program = &space(AS_PROGRAM); + m_decrypted_program = has_space(AS_OPCODES) ? &space(AS_OPCODES) : &space(AS_PROGRAM); + m_direct = &m_decrypted_program->direct(); + m_internal = &space(AS_PROGRAM); + + save_item(NAME(m_sh2_state->pc)); + save_item(NAME(m_sh2_state->sr)); + save_item(NAME(m_sh2_state->pr)); + save_item(NAME(m_sh2_state->gbr)); + save_item(NAME(m_sh2_state->vbr)); + save_item(NAME(m_sh2_state->mach)); + save_item(NAME(m_sh2_state->macl)); + save_item(NAME(m_sh2_state->r)); + save_item(NAME(m_sh2_state->ea)); + save_item(NAME(m_delay)); + save_item(NAME(m_cpu_off)); + save_item(NAME(m_dvsr)); + save_item(NAME(m_dvdnth)); + save_item(NAME(m_dvdntl)); + save_item(NAME(m_dvcr)); + save_item(NAME(m_sh2_state->pending_irq)); + save_item(NAME(m_test_irq)); + save_item(NAME(m_sh2_state->pending_nmi)); + save_item(NAME(m_sh2_state->irqline)); + save_item(NAME(m_sh2_state->evec)); + save_item(NAME(m_sh2_state->irqsr)); + save_item(NAME(m_sh2_state->target)); + 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); + } + save_item(NAME(m_pcfsel)); + save_item(NAME(m_maxpcfsel)); + save_item(NAME(m_pcflushes)); + save_item(NAME(m_irq_line_state)); + save_item(NAME(m_m)); + save_item(NAME(m_nmi_line_state)); + save_item(NAME(m_frc)); + save_item(NAME(m_ocra)); + save_item(NAME(m_ocrb)); + save_item(NAME(m_icr)); + save_item(NAME(m_frc_base)); + save_item(NAME(m_frt_input)); + save_item(NAME(m_sh2_state->internal_irq_level)); + save_item(NAME(m_internal_irq_vector)); + save_item(NAME(m_dma_timer_active)); + save_item(NAME(m_dma_irq)); + save_item(NAME(m_wtcnt)); + save_item(NAME(m_wtcsr)); + save_item(NAME(m_sh2_state->sleep_mode)); + + state_add( STATE_GENPC, "PC", m_sh2_state->pc).mask(AM).callimport(); + state_add( SH2_SR, "SR", m_sh2_state->sr).callimport().formatstr("%08X"); + state_add( SH2_PR, "PR", m_sh2_state->pr).formatstr("%08X"); + state_add( SH2_GBR, "GBR", m_sh2_state->gbr).formatstr("%08X"); + state_add( SH2_VBR, "VBR", m_sh2_state->vbr).formatstr("%08X"); + state_add( SH2_MACH, "MACH", m_sh2_state->mach).formatstr("%08X"); + state_add( SH2_MACL, "MACL", m_sh2_state->macl).formatstr("%08X"); + state_add( SH2_R0, "R0", m_sh2_state->r[ 0]).formatstr("%08X"); + state_add( SH2_R1, "R1", m_sh2_state->r[ 1]).formatstr("%08X"); + state_add( SH2_R2, "R2", m_sh2_state->r[ 2]).formatstr("%08X"); + state_add( SH2_R3, "R3", m_sh2_state->r[ 3]).formatstr("%08X"); + state_add( SH2_R4, "R4", m_sh2_state->r[ 4]).formatstr("%08X"); + state_add( SH2_R5, "R5", m_sh2_state->r[ 5]).formatstr("%08X"); + state_add( SH2_R6, "R6", m_sh2_state->r[ 6]).formatstr("%08X"); + state_add( SH2_R7, "R7", m_sh2_state->r[ 7]).formatstr("%08X"); + state_add( SH2_R8, "R8", m_sh2_state->r[ 8]).formatstr("%08X"); + state_add( SH2_R9, "R9", m_sh2_state->r[ 9]).formatstr("%08X"); + state_add( SH2_R10, "R10", m_sh2_state->r[10]).formatstr("%08X"); + state_add( SH2_R11, "R11", m_sh2_state->r[11]).formatstr("%08X"); + state_add( SH2_R12, "R12", m_sh2_state->r[12]).formatstr("%08X"); + state_add( SH2_R13, "R13", m_sh2_state->r[13]).formatstr("%08X"); + state_add( SH2_R14, "R14", m_sh2_state->r[14]).formatstr("%08X"); + state_add( SH2_R15, "R15", m_sh2_state->r[15]).formatstr("%08X"); + state_add( SH2_EA, "EA", m_sh2_state->ea).formatstr("%08X"); + + state_add( STATE_GENPCBASE, "CURPC", m_sh2_state->pc ).callimport().noshow(); + state_add( STATE_GENSP, "GENSP", m_sh2_state->r[15] ).noshow(); + state_add( STATE_GENFLAGS, "GENFLAGS", m_sh2_state->sr ).formatstr("%6s").noshow(); + + m_icountptr = &m_sh2_state->icount; + + // Clear state + m_sh2_state->pc = 0; + m_sh2_state->pr = 0; + m_sh2_state->sr = 0; + m_sh2_state->gbr = 0; + m_sh2_state->vbr = 0; + m_sh2_state->mach = 0; + m_sh2_state->macl = 0; + memset(m_sh2_state->r, 0, sizeof(m_sh2_state->r)); + m_sh2_state->ea = 0; + m_delay = 0; + m_cpu_off = 0; + m_dvsr = 0; + m_dvdnth = 0; + m_dvdntl = 0; + m_dvcr = 0; + m_sh2_state->pending_irq = 0; + m_test_irq = 0; + m_sh2_state->pending_nmi = 0; + m_sh2_state->irqline = 0; + m_sh2_state->evec = 0; + m_sh2_state->irqsr = 0; + m_sh2_state->target = 0; + memset(m_irq_queue, 0, sizeof(m_irq_queue)); + m_maxpcfsel = 0; + memset(m_pcflushes, 0, sizeof(m_pcflushes)); + memset(m_irq_line_state, 0, sizeof(m_irq_line_state)); + memset(m_m, 0, sizeof(m_m)); + m_nmi_line_state = 0; + m_frc = 0; + m_ocra = 0; + m_ocrb = 0; + m_icr = 0; + m_frc_base = 0; + m_frt_input = 0; + m_sh2_state->internal_irq_level = 0; + m_internal_irq_vector = 0; + m_sh2_state->icount = 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; + m_sh2_state->sleep_mode = 0; + m_numcycles = 0; + m_sh2_state->arg0 = 0; + m_arg1 = 0; + m_irq = 0; + m_fastram_select = 0; + memset(m_fastram, 0, sizeof(m_fastram)); + + /* reset per-driver pcflushes */ + m_pcfsel = 0; + + /* initialize the UML generator */ + uint32_t flags = 0; + m_drcuml = std::make_unique(*this, m_cache, flags, 1, 32, 1); + + /* add symbols for our stuff */ + m_drcuml->symbol_add(&m_sh2_state->pc, sizeof(m_sh2_state->pc), "pc"); + m_drcuml->symbol_add(&m_sh2_state->icount, sizeof(m_sh2_state->icount), "icount"); + for (int regnum = 0; regnum < 16; regnum++) + { + char buf[10]; + sprintf(buf, "r%d", regnum); + m_drcuml->symbol_add(&m_sh2_state->r[regnum], sizeof(m_sh2_state->r[regnum]), buf); + } + m_drcuml->symbol_add(&m_sh2_state->pr, sizeof(m_sh2_state->pr), "pr"); + m_drcuml->symbol_add(&m_sh2_state->sr, sizeof(m_sh2_state->sr), "sr"); + m_drcuml->symbol_add(&m_sh2_state->gbr, sizeof(m_sh2_state->gbr), "gbr"); + m_drcuml->symbol_add(&m_sh2_state->vbr, sizeof(m_sh2_state->vbr), "vbr"); + m_drcuml->symbol_add(&m_sh2_state->macl, sizeof(m_sh2_state->macl), "macl"); + m_drcuml->symbol_add(&m_sh2_state->mach, sizeof(m_sh2_state->macl), "mach"); + + /* initialize the front-end helper */ + m_drcfe = std::make_unique(this, COMPILE_BACKWARDS_BYTES, COMPILE_FORWARDS_BYTES, SINGLE_INSTRUCTION_MODE ? 1 : COMPILE_MAX_SEQUENCE); + + /* compute the register parameters */ + for (int regnum = 0; regnum < 16; regnum++) + { + m_regmap[regnum] = uml::mem(&m_sh2_state->r[regnum]); + } + + /* if we have registers to spare, assign r0, r1, r2 to leftovers */ + /* WARNING: do not use synthetic registers that are mapped here! */ + if (!DISABLE_FAST_REGISTERS) + { + drcbe_info beinfo; + m_drcuml->get_backend_info(beinfo); + if (beinfo.direct_iregs > 4) + { + m_regmap[0] = uml::I4; + } + if (beinfo.direct_iregs > 5) + { + m_regmap[1] = uml::I5; + } + if (beinfo.direct_iregs > 6) + { + m_regmap[2] = uml::I6; + } + } + + /* mark the cache dirty so it is updated on next execute */ + m_cache_dirty = true; +} + + +void sh2_device::state_string_export(const device_state_entry &entry, std::string &str) const +{ + switch (entry.index()) + { + case STATE_GENFLAGS: + str = string_format("%c%c%d%c%c", + m_sh2_state->sr & M ? 'M':'.', + m_sh2_state->sr & Q ? 'Q':'.', + (m_sh2_state->sr & I) >> 4, + m_sh2_state->sr & S ? 'S':'.', + m_sh2_state->sr & T ? 'T':'.'); + break; + } +} + + +void sh2_device::state_import(const device_state_entry &entry) +{ + switch (entry.index()) + { + case STATE_GENPC: + case STATE_GENPCBASE: + m_delay = 0; + break; + + case SH2_SR: + 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"); + } + else + { + LOG("SH-2 asserted nmi\n"); + + sh2_exception("Set IRQ line", 16); + + if (m_isdrc) + m_sh2_state->pending_nmi = 1; + } + } + else + { + if (m_irq_line_state[irqline] == state) + return; + m_irq_line_state[irqline] = state; + + if (state == CLEAR_LINE) + { + LOG("SH-2 cleared irq #%d\n", irqline); + m_sh2_state->pending_irq &= ~(1 << irqline); + } + else + { + 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_delay) + m_test_irq = 1; + else + CHECK_PENDING_IRQ("sh2_set_irq_line"); + } + } + } +} + +void sh2_device::sh2_exception(const char *message, int irqline) +{ + int vector; + + if (irqline != 16) + { + if (irqline <= ((m_sh2_state->sr >> 4) & 15)) /* If the cpu forbids this interrupt */ + return; + + // if this is an sh2 internal irq, use its vector + if (m_sh2_state->internal_irq_level == irqline) + { + vector = m_internal_irq_vector; + /* avoid spurious irqs with this (TODO: needs a better fix) */ + m_sh2_state->internal_irq_level = -1; + LOG("SH-2 exception #%d (internal vector: $%x) after [%s]\n", irqline, vector, message); + } + else + { + if(m_m[0x38] & 0x00010000) + { + 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); + } + } + } + else + { + vector = 11; + LOG("SH-2 nmi exception (autovector: $%x) after [%s]\n", vector, message); + } + + if (m_isdrc) + { + m_sh2_state->evec = RL( m_sh2_state->vbr + vector * 4 ); + m_sh2_state->evec &= AM; + m_sh2_state->irqsr = m_sh2_state->sr; + + /* set I flags in SR */ + if (irqline > SH2_INT_15) + m_sh2_state->sr = m_sh2_state->sr | I; + else + m_sh2_state->sr = (m_sh2_state->sr & ~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 { + m_sh2_state->r[15] -= 4; + WL( 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 */ + + /* set I flags in SR */ + if (irqline > SH2_INT_15) + m_sh2_state->sr = m_sh2_state->sr | I; + else + m_sh2_state->sr = (m_sh2_state->sr & ~I) | (irqline << 4); + + /* fetch PC */ + m_sh2_state->pc = RL( m_sh2_state->vbr + vector * 4 ); + } + + if(m_sh2_state->sleep_mode == 1) { m_sh2_state->sleep_mode = 2; } +} + +#include "sh2drc.cpp" diff --git a/src/devices/cpu/sh/sh2.h b/src/devices/cpu/sh/sh2.h new file mode 100644 index 00000000000..50ecf680c88 --- /dev/null +++ b/src/devices/cpu/sh/sh2.h @@ -0,0 +1,557 @@ +// license:BSD-3-Clause +// copyright-holders:Juergen Buchmueller +/***************************************************************************** + * + * sh2.h + * Portable Hitachi SH-2 (SH7600 family) emulator interface + * + * This work is based on C/C++ implementation of + * the SH-2 CPU core and was heavily changed to the MAME CPU requirements. + * Thanks also go to Chuck Mason and Olivier Galibert + * for letting me peek into their SEMU code :-) + * + *****************************************************************************/ + +#ifndef MAME_CPU_SH2_SH2_H +#define MAME_CPU_SH2_SH2_H + +#pragma once + +#include "cpu/drcfe.h" +#include "cpu/drcuml.h" + + +#define SH2_INT_NONE -1 +#define SH2_INT_VBLIN 0 +#define SH2_INT_VBLOUT 1 +#define SH2_INT_HBLIN 2 +#define SH2_INT_TIMER0 3 +#define SH2_INT_TIMER1 4 +#define SH2_INT_DSP 5 +#define SH2_INT_SOUND 6 +#define SH2_INT_SMPC 7 +#define SH2_INT_PAD 8 +#define SH2_INT_DMA2 9 +#define SH2_INT_DMA1 10 +#define SH2_INT_DMA0 11 +#define SH2_INT_DMAILL 12 +#define SH2_INT_SPRITE 13 +#define SH2_INT_14 14 +#define SH2_INT_15 15 +#define SH2_INT_ABUS 16 + +enum +{ + SH2_PC = STATE_GENPC, SH2_SR=1, SH2_PR, SH2_GBR, SH2_VBR, SH2_MACH, SH2_MACL, + SH2_R0, SH2_R1, SH2_R2, SH2_R3, SH2_R4, SH2_R5, SH2_R6, SH2_R7, + SH2_R8, SH2_R9, SH2_R10, SH2_R11, SH2_R12, SH2_R13, SH2_R14, SH2_R15, SH2_EA +}; + + +#define SH2_DMA_KLUDGE_CB(name) int name(uint32_t src, uint32_t dst, uint32_t data, int size) + +#define SH2_DMA_FIFO_DATA_AVAILABLE_CB(name) int name(uint32_t src, uint32_t dst, uint32_t data, int size) + +#define SH2_FTCSR_READ_CB(name) void name(uint32_t data) + + +#define MCFG_SH2_IS_SLAVE(_slave) \ + sh2_device::set_is_slave(*device, _slave); + +#define MCFG_SH2_DMA_KLUDGE_CB(_class, _method) \ + sh2_device::set_dma_kludge_callback(*device, sh2_device::dma_kludge_delegate(&_class::_method, #_class "::" #_method, downcast<_class *>(owner))); + +#define MCFG_SH2_FIFO_DATA_AVAIL_CB(_class, _method) \ + sh2_device::set_dma_fifo_data_available_callback(*device, sh2_device::dma_fifo_data_available_delegate(&_class::_method, #_class "::" #_method, downcast<_class *>(owner))); + +#define MCFG_SH2_FTCSR_READ_CB(_class, _method) \ + sh2_device::set_ftcsr_read_callback(*device, sh2_device::ftcsr_read_delegate(&_class::_method, #_class "::" #_method, downcast<_class *>(owner))); + + +/*************************************************************************** + COMPILER-SPECIFIC OPTIONS +***************************************************************************/ + +#define SH2DRC_STRICT_VERIFY 0x0001 /* verify all instructions */ +#define SH2DRC_FLUSH_PC 0x0002 /* flush the PC value before each memory access */ +#define SH2DRC_STRICT_PCREL 0x0004 /* do actual loads on MOVLI/MOVWI instead of collapsing to immediates */ + +#define SH2DRC_COMPATIBLE_OPTIONS (SH2DRC_STRICT_VERIFY | SH2DRC_FLUSH_PC | SH2DRC_STRICT_PCREL) +#define SH2DRC_FASTEST_OPTIONS (0) + +#define SH2_MAX_FASTRAM 4 + +class sh2_frontend; + +class sh2_device : public cpu_device +{ + friend class sh2_frontend; + +public: + typedef device_delegate dma_kludge_delegate; + typedef device_delegate dma_fifo_data_available_delegate; + typedef device_delegate ftcsr_read_delegate; + + // construction/destruction + sh2_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + + static void set_is_slave(device_t &device, int slave) { downcast(device).m_is_slave = slave; } + static void set_dma_kludge_callback(device_t &device, dma_kludge_delegate callback) { downcast(device).m_dma_kludge_cb = callback; } + static void set_dma_fifo_data_available_callback(device_t &device, dma_fifo_data_available_delegate callback) { downcast(device).m_dma_fifo_data_available_cb = callback; } + static void set_ftcsr_read_callback(device_t &device, ftcsr_read_delegate callback) { downcast(device).m_ftcsr_read_cb = callback; } + + DECLARE_WRITE32_MEMBER( sh7604_w ); + DECLARE_READ32_MEMBER( sh7604_r ); + DECLARE_READ32_MEMBER(sh2_internal_a5); + + void sh2_set_frt_input(int state); + void sh2drc_set_options(uint32_t options); + void sh2drc_add_pcflush(offs_t address); + void sh2drc_add_fastram(offs_t start, offs_t end, uint8_t readonly, void *base); + + void sh2_notify_dma_data_available(); + +protected: + 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); + + // device-level overrides + virtual void device_start() override; + virtual void device_reset() override; + virtual void device_stop() override; + + // device_execute_interface overrides + virtual uint32_t execute_min_cycles() const override { return 1; } + virtual uint32_t execute_max_cycles() const override { return 4; } + virtual uint32_t execute_input_lines() const override { return 16; } + virtual uint32_t execute_default_irq_vector() const override { return 0; } + virtual void execute_run() override; + virtual void execute_set_input(int inputnum, int state) override; + + // device_memory_interface overrides + virtual space_config_vector memory_space_config() const override; + + // device_state_interface overrides + virtual void state_import(const device_state_entry &entry) override; + virtual void state_string_export(const device_state_entry &entry, std::string &str) const override; + + // device_disasm_interface overrides + virtual uint32_t disasm_min_opcode_bytes() const override { return 2; } + virtual uint32_t disasm_max_opcode_bytes() const override { return 2; } + virtual offs_t disasm_disassemble(std::ostream &stream, offs_t pc, const uint8_t *oprom, const uint8_t *opram, uint32_t options) override; + address_space *m_program, *m_decrypted_program; + +private: + address_space_config m_program_config, m_decrypted_program_config; + + // Data that needs to be stored close to the generated DRC code + struct internal_sh2_state + { + uint32_t pc; + uint32_t pr; + uint32_t sr; + uint32_t gbr; + uint32_t vbr; + uint32_t mach; + uint32_t macl; + uint32_t r[16]; + uint32_t ea; + uint32_t pending_irq; + uint32_t pending_nmi; + int32_t irqline; + uint32_t evec; // exception vector for DRC + uint32_t irqsr; // IRQ-time old SR for DRC + uint32_t target; // target for jmp/jsr/etc so the delay slot can't kill it + int internal_irq_level; + int icount; + uint8_t sleep_mode; + uint32_t arg0; /* print_debug argument 1 */ + }; + + uint32_t m_delay; + uint32_t m_cpu_off; + uint32_t m_dvsr, m_dvdnth, m_dvdntl, m_dvcr; + uint32_t m_test_irq; + struct + { + int irq_vector; + int irq_priority; + } m_irq_queue[16]; + + bool m_isdrc; + + int m_pcfsel; // last pcflush entry set + int m_maxpcfsel; // highest valid pcflush entry + uint32_t m_pcflushes[16]; // pcflush entries + + int8_t m_irq_line_state[17]; +protected: + direct_read_data *m_direct; +private: + address_space *m_internal; + uint32_t m_m[0x200/4]; + int8_t m_nmi_line_state; + + uint16_t m_frc; + uint16_t m_ocra, m_ocrb, m_icr; + uint64_t m_frc_base; + + int m_frt_input; + int m_internal_irq_vector; + + emu_timer *m_timer; + emu_timer *m_dma_current_active_timer[2]; + int m_dma_timer_active[2]; + uint8_t m_dma_irq[2]; + + int m_active_dma_incs[2]; + int m_active_dma_incd[2]; + int m_active_dma_size[2]; + int m_active_dma_steal[2]; + uint32_t m_active_dma_src[2]; + uint32_t m_active_dma_dst[2]; + uint32_t m_active_dma_count[2]; + uint16_t m_wtcnt; + uint8_t m_wtcsr; + + int m_is_slave, m_cpu_type; + dma_kludge_delegate m_dma_kludge_cb; + dma_fifo_data_available_delegate m_dma_fifo_data_available_cb; + ftcsr_read_delegate m_ftcsr_read_cb; + + drc_cache m_cache; /* pointer to the DRC code cache */ + std::unique_ptr m_drcuml; /* DRC UML generator state */ + std::unique_ptr m_drcfe; /* pointer to the DRC front-end state */ + uint32_t m_drcoptions; /* configurable DRC options */ + + internal_sh2_state *m_sh2_state; + + /* internal stuff */ + uint8_t m_cache_dirty; /* true if we need to flush the cache */ + + /* parameters for subroutines */ + uint64_t m_numcycles; /* return value from gettotalcycles */ + uint32_t m_arg1; /* print_debug argument 2 */ + uint32_t m_irq; /* irq we're taking */ + + /* register mappings */ + uml::parameter m_regmap[16]; /* parameter to register mappings for all 16 integer registers */ + + uml::code_handle * m_entry; /* entry point */ + uml::code_handle * m_read8; /* read byte */ + uml::code_handle * m_write8; /* write byte */ + uml::code_handle * m_read16; /* read half */ + uml::code_handle * m_write16; /* write half */ + uml::code_handle * m_read32; /* read word */ + uml::code_handle * m_write32; /* write word */ + + uml::code_handle * m_interrupt; /* interrupt */ + uml::code_handle * m_nocode; /* nocode */ + uml::code_handle * m_out_of_cycles; /* out of cycles exception handler */ + + /* fast RAM */ + uint32_t m_fastram_select; + struct + { + offs_t start; /* start of the RAM block */ + offs_t end; /* end of the RAM block */ + bool readonly; /* true if read-only */ + void * base; /* base in memory where the RAM lives */ + } m_fastram[SH2_MAX_FASTRAM]; + + uint32_t m_debugger_temp; + + inline uint8_t RB(offs_t A); + inline uint16_t RW(offs_t A); + inline uint32_t RL(offs_t A); + inline void WB(offs_t A, uint8_t V); + inline void WW(offs_t A, uint16_t V); + inline void WL(offs_t A, uint32_t V); + inline void ADD(uint32_t m, uint32_t n); + inline void ADDI(uint32_t i, uint32_t n); + inline void ADDC(uint32_t m, uint32_t n); + inline void ADDV(uint32_t m, uint32_t n); + inline void AND(uint32_t m, uint32_t n); + inline void ANDI(uint32_t i); + inline void ANDM(uint32_t i); + inline void BF(uint32_t d); + inline void BFS(uint32_t d); + inline void BRA(uint32_t d); + inline void BRAF(uint32_t m); + inline void BSR(uint32_t d); + inline void BSRF(uint32_t m); + inline void BT(uint32_t d); + inline void BTS(uint32_t d); + inline void CLRMAC(); + inline void CLRT(); + inline void CMPEQ(uint32_t m, uint32_t n); + inline void CMPGE(uint32_t m, uint32_t n); + inline void CMPGT(uint32_t m, uint32_t n); + inline void CMPHI(uint32_t m, uint32_t n); + inline void CMPHS(uint32_t m, uint32_t n); + inline void CMPPL(uint32_t n); + inline void CMPPZ(uint32_t n); + inline void CMPSTR(uint32_t m, uint32_t n); + inline void CMPIM(uint32_t i); + inline void DIV0S(uint32_t m, uint32_t n); + inline void DIV0U(); + inline void DIV1(uint32_t m, uint32_t n); + inline void DMULS(uint32_t m, uint32_t n); + inline void DMULU(uint32_t m, uint32_t n); + inline void DT(uint32_t n); + inline void EXTSB(uint32_t m, uint32_t n); + inline void EXTSW(uint32_t m, uint32_t n); + inline void EXTUB(uint32_t m, uint32_t n); + inline void EXTUW(uint32_t m, uint32_t n); + inline void ILLEGAL(); + inline void JMP(uint32_t m); + inline void JSR(uint32_t m); + inline void LDCSR(uint32_t m); + inline void LDCGBR(uint32_t m); + inline void LDCVBR(uint32_t m); + inline void LDCMSR(uint32_t m); + inline void LDCMGBR(uint32_t m); + inline void LDCMVBR(uint32_t m); + inline void LDSMACH(uint32_t m); + inline void LDSMACL(uint32_t m); + inline void LDSPR(uint32_t m); + inline void LDSMMACH(uint32_t m); + inline void LDSMMACL(uint32_t m); + inline void LDSMPR(uint32_t m); + inline void MAC_L(uint32_t m, uint32_t n); + inline void MAC_W(uint32_t m, uint32_t n); + inline void MOV(uint32_t m, uint32_t n); + inline void MOVBS(uint32_t m, uint32_t n); + inline void MOVWS(uint32_t m, uint32_t n); + inline void MOVLS(uint32_t m, uint32_t n); + inline void MOVBL(uint32_t m, uint32_t n); + inline void MOVWL(uint32_t m, uint32_t n); + inline void MOVLL(uint32_t m, uint32_t n); + inline void MOVBM(uint32_t m, uint32_t n); + inline void MOVWM(uint32_t m, uint32_t n); + inline void MOVLM(uint32_t m, uint32_t n); + inline void MOVBP(uint32_t m, uint32_t n); + inline void MOVWP(uint32_t m, uint32_t n); + inline void MOVLP(uint32_t m, uint32_t n); + inline void MOVBS0(uint32_t m, uint32_t n); + inline void MOVWS0(uint32_t m, uint32_t n); + inline void MOVLS0(uint32_t m, uint32_t n); + inline void MOVBL0(uint32_t m, uint32_t n); + inline void MOVWL0(uint32_t m, uint32_t n); + inline void MOVLL0(uint32_t m, uint32_t n); + inline void MOVI(uint32_t i, uint32_t n); + inline void MOVWI(uint32_t d, uint32_t n); + inline void MOVLI(uint32_t d, uint32_t n); + inline void MOVBLG(uint32_t d); + inline void MOVWLG(uint32_t d); + inline void MOVLLG(uint32_t d); + inline void MOVBSG(uint32_t d); + inline void MOVWSG(uint32_t d); + inline void MOVLSG(uint32_t d); + inline void MOVBS4(uint32_t d, uint32_t n); + inline void MOVWS4(uint32_t d, uint32_t n); + inline void MOVLS4(uint32_t m, uint32_t d, uint32_t n); + inline void MOVBL4(uint32_t m, uint32_t d); + inline void MOVWL4(uint32_t m, uint32_t d); + inline void MOVLL4(uint32_t m, uint32_t d, uint32_t n); + inline void MOVA(uint32_t d); + inline void MOVT(uint32_t n); + inline void MULL(uint32_t m, uint32_t n); + inline void MULS(uint32_t m, uint32_t n); + inline void MULU(uint32_t m, uint32_t n); + inline void NEG(uint32_t m, uint32_t n); + inline void NEGC(uint32_t m, uint32_t n); + inline void NOP(void); + inline void NOT(uint32_t m, uint32_t n); + inline void OR(uint32_t m, uint32_t n); + inline void ORI(uint32_t i); + inline void ORM(uint32_t i); + inline void ROTCL(uint32_t n); + inline void ROTCR(uint32_t n); + inline void ROTL(uint32_t n); + inline void ROTR(uint32_t n); + inline void RTE(); + inline void RTS(); + inline void SETT(); + inline void SHAL(uint32_t n); + inline void SHAR(uint32_t n); + inline void SHLL(uint32_t n); + inline void SHLL2(uint32_t n); + inline void SHLL8(uint32_t n); + inline void SHLL16(uint32_t n); + inline void SHLR(uint32_t n); + inline void SHLR2(uint32_t n); + inline void SHLR8(uint32_t n); + inline void SHLR16(uint32_t n); + inline void SLEEP(); + inline void STCSR(uint32_t n); + inline void STCGBR(uint32_t n); + inline void STCVBR(uint32_t n); + inline void STCMSR(uint32_t n); + inline void STCMGBR(uint32_t n); + inline void STCMVBR(uint32_t n); + inline void STSMACH(uint32_t n); + inline void STSMACL(uint32_t n); + inline void STSPR(uint32_t n); + inline void STSMMACH(uint32_t n); + inline void STSMMACL(uint32_t n); + inline void STSMPR(uint32_t n); + inline void SUB(uint32_t m, uint32_t n); + inline void SUBC(uint32_t m, uint32_t n); + inline void SUBV(uint32_t m, uint32_t n); + inline void SWAPB(uint32_t m, uint32_t n); + inline void SWAPW(uint32_t m, uint32_t n); + inline void TAS(uint32_t n); + inline void TRAPA(uint32_t i); + inline void TST(uint32_t m, uint32_t n); + inline void TSTI(uint32_t i); + inline void TSTM(uint32_t i); + inline void XOR(uint32_t m, uint32_t n); + inline void XORI(uint32_t i); + inline void XORM(uint32_t i); + inline void XTRCT(uint32_t m, uint32_t n); + inline void op0000(uint16_t opcode); + inline void op0001(uint16_t opcode); + inline void op0010(uint16_t opcode); + inline void op0011(uint16_t opcode); + inline void op0100(uint16_t opcode); + inline void op0101(uint16_t opcode); + inline void op0110(uint16_t opcode); + inline void op0111(uint16_t opcode); + inline void op1000(uint16_t opcode); + inline void op1001(uint16_t opcode); + inline void op1010(uint16_t opcode); + inline void op1011(uint16_t opcode); + inline void op1100(uint16_t opcode); + inline void op1101(uint16_t opcode); + inline void op1110(uint16_t opcode); + inline void op1111(uint16_t opcode); + TIMER_CALLBACK_MEMBER( sh2_timer_callback ); + TIMER_CALLBACK_MEMBER( sh2_dma_current_active_callback ); + void sh2_timer_resync(); + void sh2_timer_activate(); + void sh2_do_dma(int dma); + void sh2_exception(const char *message, int irqline); + void sh2_dmac_check(int dma); + void sh2_recalc_irq(); + + /* internal compiler state */ + struct compiler_state + { + uint32_t cycles; /* accumulated cycles */ + uint8_t checkints; /* need to check interrupts before next instruction */ + uml::code_label labelnum; /* index for local labels */ + }; + + inline uint32_t epc(const opcode_desc *desc); + inline void alloc_handle(drcuml_state *drcuml, uml::code_handle **handleptr, const char *name); + inline void load_fast_iregs(drcuml_block *block); + inline void save_fast_iregs(drcuml_block *block); + + void code_flush_cache(); + void execute_run_drc(); + void code_compile_block(uint8_t mode, offs_t pc); + void static_generate_entry_point(); + void static_generate_nocode_handler(); + void static_generate_out_of_cycles(); + void static_generate_memory_accessor(int size, int iswrite, const char *name, uml::code_handle **handleptr); + const char *log_desc_flags_to_string(uint32_t flags); + void log_register_list(drcuml_state *drcuml, const char *string, const uint32_t *reglist, const uint32_t *regnostarlist); + void log_opcode_desc(drcuml_state *drcuml, const opcode_desc *desclist, int indent); + void log_add_disasm_comment(drcuml_block *block, uint32_t pc, uint32_t op); + void generate_update_cycles(drcuml_block *block, compiler_state *compiler, uml::parameter param, bool allow_exception); + void generate_checksum_block(drcuml_block *block, compiler_state *compiler, const opcode_desc *seqhead, const opcode_desc *seqlast); + void generate_sequence_instruction(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint32_t ovrpc); + void generate_delay_slot(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint32_t ovrpc); + bool generate_opcode(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint32_t ovrpc); + bool generate_group_0(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc); + bool generate_group_2(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc); + bool generate_group_3(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, uint32_t ovrpc); + bool generate_group_4(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc); + bool generate_group_6(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc); + bool generate_group_8(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc); + bool generate_group_12(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc); + +public: + void func_printf_probe(); + void func_unimplemented(); + void func_fastirq(); + void func_MAC_W(); + void func_MAC_L(); + void func_DIV1(); + void func_ADDV(); + void func_SUBV(); +}; + +class sh2a_device : public sh2_device +{ +public: + // construction/destruction + sh2a_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + + DECLARE_READ32_MEMBER(dma_sar0_r); + DECLARE_WRITE32_MEMBER(dma_sar0_w); + DECLARE_READ32_MEMBER(dma_dar0_r); + DECLARE_WRITE32_MEMBER(dma_dar0_w); + DECLARE_READ16_MEMBER(dmaor_r); + DECLARE_WRITE16_MEMBER(dmaor_w); + DECLARE_READ16_MEMBER(dma_tcr0_r); + DECLARE_WRITE16_MEMBER(dma_tcr0_w); + DECLARE_READ16_MEMBER(dma_chcr0_r); + DECLARE_WRITE16_MEMBER(dma_chcr0_w); + DECLARE_READ16_MEMBER(sh7021_r); + DECLARE_WRITE16_MEMBER(sh7021_w); + void sh7032_dma_exec(int ch); + +private: + uint16_t m_sh7021_regs[0x200]; + struct + { + uint32_t sar; /**< Source Address Register */ + uint32_t dar; /**< Destination Address Register */ + uint16_t tcr; /**< Transfer Count Register */ + uint16_t chcr; /**< Channel Control Register */ + } m_dma[4]; + uint16_t m_dmaor; /**< DMA Operation Register (status flags) */ + +}; + +class sh1_device : public sh2_device +{ +public: + // construction/destruction + sh1_device(const machine_config &mconfig, const char *_tag, device_t *_owner, uint32_t _clock); + + DECLARE_READ16_MEMBER(sh7032_r); + DECLARE_WRITE16_MEMBER(sh7032_w); +private: + uint16_t m_sh7032_regs[0x200]; +}; + + +class sh2_frontend : public drc_frontend +{ +public: + sh2_frontend(sh2_device *device, uint32_t window_start, uint32_t window_end, uint32_t max_sequence); + +protected: + virtual bool describe(opcode_desc &desc, const opcode_desc *prev) override; + +private: + bool describe_group_0(opcode_desc &desc, const opcode_desc *prev, uint16_t opcode); + bool describe_group_2(opcode_desc &desc, const opcode_desc *prev, uint16_t opcode); + bool describe_group_3(opcode_desc &desc, const opcode_desc *prev, uint16_t opcode); + bool describe_group_4(opcode_desc &desc, const opcode_desc *prev, uint16_t opcode); + bool describe_group_6(opcode_desc &desc, const opcode_desc *prev, uint16_t opcode); + bool describe_group_8(opcode_desc &desc, const opcode_desc *prev, uint16_t opcode); + bool describe_group_12(opcode_desc &desc, const opcode_desc *prev, uint16_t opcode); + + sh2_device *m_sh2; +}; + + +DECLARE_DEVICE_TYPE(SH1, sh1_device) +DECLARE_DEVICE_TYPE(SH2, sh2_device) +DECLARE_DEVICE_TYPE(SH2A, sh2a_device) + + +#endif // MAME_CPU_SH2_SH2_H diff --git a/src/devices/cpu/sh/sh2comn.cpp b/src/devices/cpu/sh/sh2comn.cpp new file mode 100644 index 00000000000..b6ac0e1cc65 --- /dev/null +++ b/src/devices/cpu/sh/sh2comn.cpp @@ -0,0 +1,946 @@ +// license:BSD-3-Clause +// copyright-holders:R. Belmont +/***************************************************************************** + * + * sh2common.c + * + * SH-2 non-specific components + * + *****************************************************************************/ + +#include "emu.h" +#include "sh2.h" +#include "sh2comn.h" + +#include "debugger.h" + +//#define VERBOSE 1 +#include "logmacro.h" + +static const int div_tab[4] = { 3, 5, 7, 0 }; + + +void sh2_device::sh2_timer_resync() +{ + int divider = div_tab[(m_m[5] >> 8) & 3]; + uint64_t cur_time = total_cycles(); + uint64_t add = (cur_time - m_frc_base) >> divider; + + if (add > 0) + { + if(divider) + m_frc += add; + + m_frc_base = cur_time; + } +} + +void sh2_device::sh2_timer_activate() +{ + int max_delta = 0xfffff; + uint16_t frc; + + m_timer->adjust(attotime::never); + + frc = m_frc; + if(!(m_m[4] & OCFA)) { + uint16_t delta = m_ocra - frc; + if(delta < max_delta) + max_delta = delta; + } + + if(!(m_m[4] & OCFB) && (m_ocra <= m_ocrb || !(m_m[4] & 0x010000))) { + uint16_t delta = m_ocrb - frc; + if(delta < max_delta) + max_delta = delta; + } + + if(!(m_m[4] & OVF) && !(m_m[4] & 0x010000)) { + int delta = 0x10000 - frc; + if(delta < max_delta) + max_delta = delta; + } + + if(max_delta != 0xfffff) { + int divider = div_tab[(m_m[5] >> 8) & 3]; + if(divider) { + max_delta <<= divider; + m_frc_base = total_cycles(); + m_timer->adjust(cycles_to_attotime(max_delta)); + } else { + logerror("SH2.%s: Timer event in %d cycles of external clock", tag(), max_delta); + } + } +} + +TIMER_CALLBACK_MEMBER( sh2_device::sh2_timer_callback ) +{ + uint16_t frc; + + sh2_timer_resync(); + + frc = m_frc; + + if(frc == m_ocrb) + m_m[4] |= OCFB; + + if(frc == 0x0000) + m_m[4] |= OVF; + + if(frc == m_ocra) + { + m_m[4] |= OCFA; + + if(m_m[4] & 0x010000) + m_frc = 0; + } + + sh2_recalc_irq(); + sh2_timer_activate(); +} + + +/* + We have to do DMA on a timer (or at least, in chunks) due to the way some systems use it. + The 32x is a difficult case, they set the SOURCE of the DMA to a FIFO buffer, which at most + can have 8 words in it. Attempting to do an 'instant DMA' in this scenario is impossible + because the game is expecting the 68k of the system to feed data into the FIFO at the same + time as the SH2 is transfering it out via DMA + + There are two ways we can do this + + a) with a high frequency timer (more accurate, but a large performance hit) + + or + + b) in the CPU_EXECUTE loop + + + we're currently doing a) + + b) causes problems with ST-V games + +*/ + + + +void sh2_device::sh2_notify_dma_data_available() +{ + //printf("call notify\n"); + + for (int dma=0;dma<2;dma++) + { + //printf("m_dma_timer_active[dma] %04x\n",m_dma_timer_active[dma]); + + if (m_dma_timer_active[dma]==2) // 2 = stalled + { + // printf("resuming stalled dma\n"); + m_dma_timer_active[dma]=1; + m_dma_current_active_timer[dma]->adjust(attotime::zero, dma); + } + } + +} + +void sh2_device::sh2_do_dma(int dma) +{ + uint32_t dmadata; + + uint32_t tempsrc, tempdst; + + if (m_active_dma_count[dma] > 0) + { + // process current DMA + switch(m_active_dma_size[dma]) + { + case 0: + { + // we need to know the src / dest ahead of time without changing them + // to allow for the callback to check if we can process the DMA at this + // time (we need to know where we're reading / writing to/from) + + if(m_active_dma_incs[dma] == 2) + tempsrc = m_active_dma_src[dma] - 1; + else + tempsrc = m_active_dma_src[dma]; + + if(m_active_dma_incd[dma] == 2) + tempdst = m_active_dma_dst[dma] - 1; + else + tempdst = m_active_dma_dst[dma]; + + if (!m_dma_fifo_data_available_cb.isnull()) + { + int available = m_dma_fifo_data_available_cb(tempsrc, tempdst, 0, m_active_dma_size[dma]); + + if (!available) + { + //printf("dma stalled\n"); + m_dma_timer_active[dma]=2;// mark as stalled + return; + } + } + + #ifdef USE_TIMER_FOR_DMA + //schedule next DMA callback + m_dma_current_active_timer[dma]->adjust(cycles_to_attotime(2), dma); + #endif + + + dmadata = m_program->read_byte(tempsrc); + if (!m_dma_kludge_cb.isnull()) dmadata = m_dma_kludge_cb(tempsrc, tempdst, dmadata, m_active_dma_size[dma]); + m_program->write_byte(tempdst, dmadata); + + if(m_active_dma_incs[dma] == 2) + m_active_dma_src[dma] --; + if(m_active_dma_incd[dma] == 2) + m_active_dma_dst[dma] --; + + + if(m_active_dma_incs[dma] == 1) + m_active_dma_src[dma] ++; + if(m_active_dma_incd[dma] == 1) + m_active_dma_dst[dma] ++; + + m_active_dma_count[dma] --; + } + break; + case 1: + { + if(m_active_dma_incs[dma] == 2) + tempsrc = m_active_dma_src[dma] - 2; + else + tempsrc = m_active_dma_src[dma]; + + if(m_active_dma_incd[dma] == 2) + tempdst = m_active_dma_dst[dma] - 2; + else + tempdst = m_active_dma_dst[dma]; + + if (!m_dma_fifo_data_available_cb.isnull()) + { + int available = m_dma_fifo_data_available_cb(tempsrc, tempdst, 0, m_active_dma_size[dma]); + + if (!available) + { + //printf("dma stalled\n"); + m_dma_timer_active[dma]=2;// mark as stalled + return; + } + } + + #ifdef USE_TIMER_FOR_DMA + //schedule next DMA callback + m_dma_current_active_timer[dma]->adjust(cycles_to_attotime(2), dma); + #endif + + // check: should this really be using read_word_32 / write_word_32? + dmadata = m_program->read_word(tempsrc); + if (!m_dma_kludge_cb.isnull()) dmadata = m_dma_kludge_cb(tempsrc, tempdst, dmadata, m_active_dma_size[dma]); + m_program->write_word(tempdst, dmadata); + + if(m_active_dma_incs[dma] == 2) + m_active_dma_src[dma] -= 2; + if(m_active_dma_incd[dma] == 2) + m_active_dma_dst[dma] -= 2; + + if(m_active_dma_incs[dma] == 1) + m_active_dma_src[dma] += 2; + if(m_active_dma_incd[dma] == 1) + m_active_dma_dst[dma] += 2; + + m_active_dma_count[dma] --; + } + break; + case 2: + { + if(m_active_dma_incs[dma] == 2) + tempsrc = m_active_dma_src[dma] - 4; + else + tempsrc = m_active_dma_src[dma]; + + if(m_active_dma_incd[dma] == 2) + tempdst = m_active_dma_dst[dma] - 4; + else + tempdst = m_active_dma_dst[dma]; + + if (!m_dma_fifo_data_available_cb.isnull()) + { + int available = m_dma_fifo_data_available_cb(tempsrc, tempdst, 0, m_active_dma_size[dma]); + + if (!available) + { + //printf("dma stalled\n"); + m_dma_timer_active[dma]=2;// mark as stalled + return; + } + } + + #ifdef USE_TIMER_FOR_DMA + //schedule next DMA callback + m_dma_current_active_timer[dma]->adjust(cycles_to_attotime(2), dma); + #endif + + dmadata = m_program->read_dword(tempsrc); + if (!m_dma_kludge_cb.isnull()) dmadata = m_dma_kludge_cb(tempsrc, tempdst, dmadata, m_active_dma_size[dma]); + m_program->write_dword(tempdst, dmadata); + + if(m_active_dma_incs[dma] == 2) + m_active_dma_src[dma] -= 4; + if(m_active_dma_incd[dma] == 2) + m_active_dma_dst[dma] -= 4; + + if(m_active_dma_incs[dma] == 1) + m_active_dma_src[dma] += 4; + if(m_active_dma_incd[dma] == 1) + m_active_dma_dst[dma] += 4; + + m_active_dma_count[dma] --; + } + break; + case 3: + { + // shouldn't this really be 4 calls here instead? + + tempsrc = m_active_dma_src[dma]; + + if(m_active_dma_incd[dma] == 2) + tempdst = m_active_dma_dst[dma] - 16; + else + tempdst = m_active_dma_dst[dma]; + + if (!m_dma_fifo_data_available_cb.isnull()) + { + int available = m_dma_fifo_data_available_cb(tempsrc, tempdst, 0, m_active_dma_size[dma]); + + if (!available) + { + //printf("dma stalled\n"); + m_dma_timer_active[dma]=2;// mark as stalled + fatalerror("SH2 dma_callback_fifo_data_available == 0 in unsupported mode\n"); + } + } + + #ifdef USE_TIMER_FOR_DMA + //schedule next DMA callback + m_dma_current_active_timer[dma]->adjust(cycles_to_attotime(2), dma); + #endif + + dmadata = m_program->read_dword(tempsrc); + if (!m_dma_kludge_cb.isnull()) dmadata = m_dma_kludge_cb(tempsrc, tempdst, dmadata, m_active_dma_size[dma]); + m_program->write_dword(tempdst, dmadata); + + dmadata = m_program->read_dword(tempsrc+4); + if (!m_dma_kludge_cb.isnull()) dmadata = m_dma_kludge_cb(tempsrc, tempdst, dmadata, m_active_dma_size[dma]); + m_program->write_dword(tempdst+4, dmadata); + + dmadata = m_program->read_dword(tempsrc+8); + if (!m_dma_kludge_cb.isnull()) dmadata = m_dma_kludge_cb(tempsrc, tempdst, dmadata, m_active_dma_size[dma]); + m_program->write_dword(tempdst+8, dmadata); + + dmadata = m_program->read_dword(tempsrc+12); + if (!m_dma_kludge_cb.isnull()) dmadata = m_dma_kludge_cb(tempsrc, tempdst, dmadata, m_active_dma_size[dma]); + m_program->write_dword(tempdst+12, dmadata); + + if(m_active_dma_incd[dma] == 2) + m_active_dma_dst[dma] -= 16; + + m_active_dma_src[dma] += 16; + if(m_active_dma_incd[dma] == 1) + m_active_dma_dst[dma] += 16; + + m_active_dma_count[dma]-=4; + } + break; + } + } + else // the dma is complete + { + // int dma = param & 1; + + // fever soccer uses cycle-stealing mode, resume the CPU now DMA has finished + if (m_active_dma_steal[dma]) + { + resume(SUSPEND_REASON_HALT ); + } + + + LOG("SH2: DMA %d complete\n", dma); + m_m[0x62+4*dma] = 0; + m_m[0x63+4*dma] |= 2; + m_dma_timer_active[dma] = 0; + m_dma_irq[dma] |= 1; + sh2_recalc_irq(); + + } +} + +TIMER_CALLBACK_MEMBER( sh2_device::sh2_dma_current_active_callback ) +{ + int dma = param & 1; + + sh2_do_dma(dma); +} + + +void sh2_device::sh2_dmac_check(int dma) +{ + if(m_m[0x63+4*dma] & m_m[0x6c] & 1) + { + if(!m_dma_timer_active[dma] && !(m_m[0x63+4*dma] & 2)) + { + m_active_dma_incd[dma] = (m_m[0x63+4*dma] >> 14) & 3; + m_active_dma_incs[dma] = (m_m[0x63+4*dma] >> 12) & 3; + m_active_dma_size[dma] = (m_m[0x63+4*dma] >> 10) & 3; + m_active_dma_steal[dma] = (m_m[0x63+4*dma] &0x10); + + if(m_active_dma_incd[dma] == 3 || m_active_dma_incs[dma] == 3) + { + logerror("SH2: DMA: bad increment values (%d, %d, %d, %04x)\n", m_active_dma_incd[dma], m_active_dma_incs[dma], m_active_dma_size[dma], m_m[0x63+4*dma]); + return; + } + m_active_dma_src[dma] = m_m[0x60+4*dma]; + m_active_dma_dst[dma] = m_m[0x61+4*dma]; + m_active_dma_count[dma] = m_m[0x62+4*dma]; + if(!m_active_dma_count[dma]) + m_active_dma_count[dma] = 0x1000000; + + LOG("SH2: DMA %d start %x, %x, %x, %04x, %d, %d, %d\n", dma, m_active_dma_src[dma], m_active_dma_dst[dma], m_active_dma_count[dma], m_m[0x63+4*dma], m_active_dma_incs[dma], m_active_dma_incd[dma], m_active_dma_size[dma]); + + m_dma_timer_active[dma] = 1; + + m_active_dma_src[dma] &= AM; + m_active_dma_dst[dma] &= AM; + + switch(m_active_dma_size[dma]) + { + case 0: + break; + case 1: + m_active_dma_src[dma] &= ~1; + m_active_dma_dst[dma] &= ~1; + break; + case 2: + m_active_dma_src[dma] &= ~3; + m_active_dma_dst[dma] &= ~3; + break; + case 3: + m_active_dma_src[dma] &= ~3; + m_active_dma_dst[dma] &= ~3; + m_active_dma_count[dma] &= ~3; + break; + } + + + + +#ifdef USE_TIMER_FOR_DMA + // start DMA timer + + // fever soccer uses cycle-stealing mode, requiring the CPU to be halted + if (m_active_dma_steal[dma]) + { + //printf("cycle stealing DMA\n"); + suspend(SUSPEND_REASON_HALT, 1 ); + } + + m_dma_current_active_timer[dma]->adjust(cycles_to_attotime(2), dma); +#endif + + } + } + else + { + if(m_dma_timer_active[dma]) + { + logerror("SH2: DMA %d cancelled in-flight\n", dma); + //m_dma_complete_timer[dma]->adjust(attotime::never); + m_dma_current_active_timer[dma]->adjust(attotime::never); + + m_dma_timer_active[dma] = 0; + } + } +} + + +WRITE32_MEMBER( sh2_device::sh7604_w ) +{ + uint32_t old; + + old = m_m[offset]; + COMBINE_DATA(m_m+offset); + + // if(offset != 0x20) + // logerror("sh2_internal_w: Write %08x (%x), %08x @ %08x\n", 0xfffffe00+offset*4, offset, data, mem_mask); + +// if(offset != 0x20) +// printf("sh2_internal_w: Write %08x (%x), %08x @ %08x (PC %x)\n", 0xfffffe00+offset*4, offset, data, mem_mask, space.device().safe_pc()); + + switch( offset ) + { + case 0x00: + //if(mem_mask == 0xff) + // printf("%c",data & 0xff); + break; + case 0x01: + //printf("%08x %02x %02x\n",mem_mask,offset,data); + break; + // Timers + case 0x04: // TIER, FTCSR, FRC + if((mem_mask & 0x00ffffff) != 0) + { + sh2_timer_resync(); + } +// printf("SH2.%s: TIER write %04x @ %04x\n", m_device->tag(), data >> 16, mem_mask>>16); + m_m[4] = (m_m[4] & ~(ICF|OCFA|OCFB|OVF)) | (old & m_m[4] & (ICF|OCFA|OCFB|OVF)); + COMBINE_DATA(&m_frc); + if((mem_mask & 0x00ffffff) != 0) + sh2_timer_activate(); + sh2_recalc_irq(); + break; + case 0x05: // OCRx, TCR, TOCR +// printf("SH2.%s: TCR write %08x @ %08x\n", m_device->tag(), data, mem_mask); + sh2_timer_resync(); + if(m_m[5] & 0x10) + m_ocrb = (m_ocrb & (~mem_mask >> 16)) | ((data & mem_mask) >> 16); + else + m_ocra = (m_ocra & (~mem_mask >> 16)) | ((data & mem_mask) >> 16); + sh2_timer_activate(); + break; + + case 0x06: // ICR + break; + + // Interrupt vectors + case 0x18: // IPRB, VCRA + case 0x19: // VCRB, VCRC + case 0x1a: // VCRD + sh2_recalc_irq(); + break; + + // DMA + case 0x1c: // DRCR0, DRCR1 + break; + + // Watchdog + case 0x20: // WTCNT, RSTCSR + if((m_m[0x20] & 0xff000000) == 0x5a000000) + m_wtcnt = (m_m[0x20] >> 16) & 0xff; + + if((m_m[0x20] & 0xff000000) == 0xa5000000) + { + /* + WTCSR + x--- ---- Overflow in IT mode + -x-- ---- Timer mode (0: IT 1: watchdog) + --x- ---- Timer enable + ---1 1--- + ---- -xxx Clock select + */ + + m_wtcsr = (m_m[0x20] >> 16) & 0xff; + } + + if((m_m[0x20] & 0x0000ff00) == 0x00005a00) + { + // -x-- ---- RSTE (1: resets wtcnt when overflows 0: no reset) + // --x- ---- RSTS (0: power-on reset 1: Manual reset) + // ... + } + + if((m_m[0x20] & 0x0000ff00) == 0x0000a500) + { + // clear WOVF + // ... + } + + + + break; + + // Standby and cache + case 0x24: // SBYCR, CCR + /* + CCR + xx-- ---- ---- ---- Way 0/1 + ---x ---- ---- ---- Cache Purge (CP) + ---- x--- ---- ---- Two-Way Mode (TW) + ---- -x-- ---- ---- Data Replacement Disable (OD) + ---- --x- ---- ---- Instruction Replacement Disable (ID) + ---- ---x ---- ---- Cache Enable (CE) + */ + break; + + // Interrupt vectors cont. + case 0x38: // ICR, IRPA + break; + case 0x39: // VCRWDT + break; + + // Division box + case 0x40: // DVSR + break; + case 0x41: // DVDNT + { + int32_t a = m_m[0x41]; + int32_t b = m_m[0x40]; + LOG("SH2 div+mod %d/%d\n", a, b); + if (b) + { + m_m[0x45] = a / b; + m_m[0x44] = a % b; + } + else + { + m_m[0x42] |= 0x00010000; + m_m[0x45] = 0x7fffffff; + m_m[0x44] = 0x7fffffff; + sh2_recalc_irq(); + } + break; + } + case 0x42: // DVCR + m_m[0x42] = (m_m[0x42] & ~0x00001000) | (old & m_m[0x42] & 0x00010000); + sh2_recalc_irq(); + break; + case 0x43: // VCRDIV + sh2_recalc_irq(); + break; + case 0x44: // DVDNTH + break; + case 0x45: // DVDNTL + { + int64_t a = m_m[0x45] | ((uint64_t)(m_m[0x44]) << 32); + int64_t b = (int32_t)m_m[0x40]; + LOG("SH2 div+mod %d/%d\n", a, b); + if (b) + { + int64_t q = a / b; + if (q != (int32_t)q) + { + m_m[0x42] |= 0x00010000; + m_m[0x45] = 0x7fffffff; + m_m[0x44] = 0x7fffffff; + sh2_recalc_irq(); + } + else + { + m_m[0x45] = q; + m_m[0x44] = a % b; + } + } + else + { + m_m[0x42] |= 0x00010000; + m_m[0x45] = 0x7fffffff; + m_m[0x44] = 0x7fffffff; + sh2_recalc_irq(); + } + break; + } + + // DMA controller + case 0x60: // SAR0 + case 0x61: // DAR0 + break; + case 0x62: // DTCR0 + m_m[0x62] &= 0xffffff; + break; + case 0x63: // CHCR0 + m_m[0x63] = (m_m[0x63] & ~2) | (old & m_m[0x63] & 2); + sh2_dmac_check(0); + break; + case 0x64: // SAR1 + case 0x65: // DAR1 + break; + case 0x66: // DTCR1 + m_m[0x66] &= 0xffffff; + break; + case 0x67: // CHCR1 + m_m[0x67] = (m_m[0x67] & ~2) | (old & m_m[0x67] & 2); + sh2_dmac_check(1); + break; + case 0x68: // VCRDMA0 + case 0x6a: // VCRDMA1 + sh2_recalc_irq(); + break; + case 0x6c: // DMAOR + m_m[0x6c] = (m_m[0x6c] & ~6) | (old & m_m[0x6c] & 6); + sh2_dmac_check(0); + sh2_dmac_check(1); + break; + + // Bus controller + case 0x78: // BCR1 + case 0x79: // BCR2 + case 0x7a: // WCR + case 0x7b: // MCR + case 0x7c: // RTCSR + case 0x7d: // RTCNT + case 0x7e: // RTCOR + break; + + default: + logerror("sh2_internal_w: Unmapped write %08x, %08x @ %08x\n", 0xfffffe00+offset*4, data, mem_mask); + break; + } +} + +READ32_MEMBER( sh2_device::sh7604_r ) +{ +// logerror("sh2_internal_r: Read %08x (%x) @ %08x\n", 0xfffffe00+offset*4, offset, mem_mask); + switch( offset ) + { + case 0x00: + break; + case 0x01: +// return m_m[1] | 0; // bit31 is TDRE: Trasmit Data Register Empty. Forcing it to be '1' breaks Saturn ... + return m_m[1] | (0x84 << 24); // ... but this is actually needed to make EGWord on SS to boot? + + case 0x04: // TIER, FTCSR, FRC + if ( mem_mask == 0x00ff0000 ) + { + if (!m_ftcsr_read_cb.isnull()) + { + m_ftcsr_read_cb((m_m[4] & 0xffff0000) | m_frc); + } + } + sh2_timer_resync(); + return (m_m[4] & 0xffff0000) | m_frc; + case 0x05: // OCRx, TCR, TOCR + if(m_m[5] & 0x10) + return (m_ocrb << 16) | (m_m[5] & 0xffff); + else + return (m_ocra << 16) | (m_m[5] & 0xffff); + case 0x06: // ICR + return m_icr << 16; + + case 0x20: + return (((m_wtcsr | 0x18) & 0xff) << 24) | ((m_wtcnt & 0xff) << 16); + + case 0x24: // SBYCR, CCR + return m_m[0x24] & ~0x3000; /* bit 4-5 of CCR are always zero */ + + case 0x38: // ICR, IPRA + return (m_m[0x38] & 0x7fffffff) | (m_nmi_line_state == ASSERT_LINE ? 0 : 0x80000000); + + case 0x78: // BCR1 + return (m_is_slave ? 0x00008000 : 0) | (m_m[0x78] & 0x7fff); + + case 0x41: // dvdntl mirrors + case 0x47: + return m_m[0x45]; + + case 0x46: // dvdnth mirror + return m_m[0x44]; + } + return m_m[offset]; +} + +void sh2_device::sh2_set_frt_input(int state) +{ + if(state == PULSE_LINE) + { + sh2_set_frt_input(ASSERT_LINE); + sh2_set_frt_input(CLEAR_LINE); + return; + } + + if(m_frt_input == state) { + return; + } + + m_frt_input = state; + + if(m_m[5] & 0x8000) { + if(state == CLEAR_LINE) { + return; + } + } else { + if(state == ASSERT_LINE) { + return; + } + } + + sh2_timer_resync(); + m_icr = m_frc; + m_m[4] |= ICF; + //logerror("SH2.%s: ICF activated (%x)\n", tag(), m_sh2_state->pc & AM); + sh2_recalc_irq(); +} + +void sh2_device::sh2_recalc_irq() +{ + int irq = 0, vector = -1; + int level; + + // Timer irqs + if((m_m[4]>>8) & m_m[4] & (ICF|OCFA|OCFB|OVF)) + { + level = (m_m[0x18] >> 24) & 15; + if(level > irq) + { + int mask = (m_m[4]>>8) & m_m[4]; + irq = level; + if(mask & ICF) + vector = (m_m[0x19] >> 8) & 0x7f; + else if(mask & (OCFA|OCFB)) + vector = m_m[0x19] & 0x7f; + else + vector = (m_m[0x1a] >> 24) & 0x7f; + } + } + + // DMA irqs + if((m_m[0x63] & 6) == 6 && m_dma_irq[0]) { + level = (m_m[0x38] >> 8) & 15; + if(level > irq) { + irq = level; + m_dma_irq[0] &= ~1; + vector = (m_m[0x68]) & 0x7f; + } + } + else if((m_m[0x67] & 6) == 6 && m_dma_irq[1]) { + level = (m_m[0x38] >> 8) & 15; + if(level > irq) { + irq = level; + m_dma_irq[1] &= ~1; + vector = (m_m[0x6a]) & 0x7f; + } + } + + m_sh2_state->internal_irq_level = irq; + m_internal_irq_vector = vector; + m_test_irq = 1; +} + +/* + SH-7021 on-chip device + */ + +void sh2a_device::sh7032_dma_exec(int ch) +{ + const short dma_word_size[4] = { 0, +1, -1, 0 }; + uint8_t rs = (m_dma[ch].chcr >> 8) & 0xf; /**< Resource Select bits */ + if(rs != 0xc) // Auto-Request + { + logerror("Warning: SH7032 DMA enables non auto-request transfer\n"); + return; + } + + // channel enable & master enable + if((m_dma[ch].chcr & 1) == 0 || (m_dmaor & 1) == 0) + return; + + printf("%08x %08x %04x\n",m_dma[ch].sar,m_dma[ch].dar,m_dma[ch].chcr); + uint8_t dm = (m_dma[ch].chcr >> 14) & 3; /**< Destination Address Mode bits */ + uint8_t sm = (m_dma[ch].chcr >> 12) & 3; /**< Source Address Mode bits */ + bool ts = (m_dma[ch].chcr & 8); /**< Transfer Size bit */ + int src_word_size = dma_word_size[sm] * ((ts == true) ? 2 : 1); + int dst_word_size = dma_word_size[dm] * ((ts == true) ? 2 : 1); + uint32_t src_addr = m_dma[ch].sar; + uint32_t dst_addr = m_dma[ch].dar; + uint32_t size_index = m_dma[ch].tcr; + if(size_index == 0) + size_index = 0x10000; + + if(ts == false) + logerror("SH7032: DMA byte mode check\n"); + + for(int index = size_index;index>-1;index--) + { + if(ts == true) + m_program->write_word(dst_addr,m_program->read_word(src_addr)); + else + m_program->write_byte(dst_addr,m_program->read_byte(src_addr)); + + src_addr += src_word_size; + dst_addr += dst_word_size; + } + + m_dma[ch].chcr &= ~1; /**< @todo non-instant DMA */ + printf("%02x %02x %02x %1d\n",sm,dm,rs,ts); +} + +READ32_MEMBER(sh2a_device::dma_sar0_r) +{ + return m_dma[0].sar; +} + +WRITE32_MEMBER(sh2a_device::dma_sar0_w) +{ + COMBINE_DATA(&m_dma[0].sar); +} + +READ32_MEMBER(sh2a_device::dma_dar0_r) +{ + return m_dma[0].dar; +} + +WRITE32_MEMBER(sh2a_device::dma_dar0_w) +{ + COMBINE_DATA(&m_dma[0].dar); +} + +READ16_MEMBER(sh2a_device::dma_tcr0_r) +{ + return m_dma[0].tcr; +} + +WRITE16_MEMBER(sh2a_device::dma_tcr0_w) +{ + //printf("%04x\n",data); + COMBINE_DATA(&m_dma[0].tcr); +} + +READ16_MEMBER(sh2a_device::dma_chcr0_r) +{ + return m_dma[0].chcr; +} + +WRITE16_MEMBER(sh2a_device::dma_chcr0_w) +{ + //printf("%04x CHCR0\n",data); + COMBINE_DATA(&m_dma[0].chcr); + sh7032_dma_exec(0); +} + +READ16_MEMBER(sh2a_device::dmaor_r) +{ + return m_dmaor; +} + +WRITE16_MEMBER(sh2a_device::dmaor_w) +{ + COMBINE_DATA(&m_dmaor); + sh7032_dma_exec(0); +} + +/*! + @brief Dummy debug interface + */ +READ16_MEMBER(sh1_device::sh7032_r) +{ + return m_sh7032_regs[offset]; +} + +/*! + @brief Dummy debug interface + */ +WRITE16_MEMBER(sh1_device::sh7032_w) +{ + COMBINE_DATA(&m_sh7032_regs[offset]); +} + +READ16_MEMBER(sh2a_device::sh7021_r) +{ + return m_sh7021_regs[offset]; +} + +/*! + @brief Dummy debug interface + */ +WRITE16_MEMBER(sh2a_device::sh7021_w) +{ + COMBINE_DATA(&m_sh7021_regs[offset]); +} diff --git a/src/devices/cpu/sh/sh2comn.h b/src/devices/cpu/sh/sh2comn.h new file mode 100644 index 00000000000..1c859e227d6 --- /dev/null +++ b/src/devices/cpu/sh/sh2comn.h @@ -0,0 +1,85 @@ +// license:BSD-3-Clause +// copyright-holders:R. Belmont +/***************************************************************************** + * + * sh2common.h + * + * SH-2 non-specific components + * + *****************************************************************************/ + +#ifndef MAME_CPU_SH2_SH2COMN_H +#define MAME_CPU_SH2_SH2COMN_H + +#pragma once + + + +// do we use a timer for the DMA, or have it in CPU_EXECUTE +#define USE_TIMER_FOR_DMA + +#include "cpu/drcuml.h" +#include "cpu/drcumlsh.h" + +#define SH2_CODE_XOR(a) ((a) ^ NATIVE_ENDIAN_VALUE_LE_BE(2,0)) + +enum +{ + ICF = 0x00800000, + OCFA = 0x00080000, + OCFB = 0x00040000, + OVF = 0x00020000 +}; + +#define T 0x00000001 +#define S 0x00000002 +#define I 0x000000f0 +#define Q 0x00000100 +#define M 0x00000200 + +#define AM 0xc7ffffff + +#define FLAGS (M|Q|I|S|T) + +#define Rn ((opcode>>8)&15) +#define Rm ((opcode>>4)&15) + +#define CPU_TYPE_SH1 (0) +#define CPU_TYPE_SH2 (1) + +#define REGFLAG_R(n) (1 << (n)) + +/* register flags 1 */ +#define REGFLAG_PR (1 << 0) +#define REGFLAG_MACL (1 << 1) +#define REGFLAG_MACH (1 << 2) +#define REGFLAG_GBR (1 << 3) +#define REGFLAG_VBR (1 << 4) +#define REGFLAG_SR (1 << 5) + +#define CHECK_PENDING_IRQ(message) \ +do { \ + int irq = -1; \ + if (m_sh2_state->pending_irq & (1 << 0)) irq = 0; \ + if (m_sh2_state->pending_irq & (1 << 1)) irq = 1; \ + if (m_sh2_state->pending_irq & (1 << 2)) irq = 2; \ + if (m_sh2_state->pending_irq & (1 << 3)) irq = 3; \ + if (m_sh2_state->pending_irq & (1 << 4)) irq = 4; \ + if (m_sh2_state->pending_irq & (1 << 5)) irq = 5; \ + if (m_sh2_state->pending_irq & (1 << 6)) irq = 6; \ + if (m_sh2_state->pending_irq & (1 << 7)) irq = 7; \ + if (m_sh2_state->pending_irq & (1 << 8)) irq = 8; \ + if (m_sh2_state->pending_irq & (1 << 9)) irq = 9; \ + if (m_sh2_state->pending_irq & (1 << 10)) irq = 10; \ + if (m_sh2_state->pending_irq & (1 << 11)) irq = 11; \ + if (m_sh2_state->pending_irq & (1 << 12)) irq = 12; \ + if (m_sh2_state->pending_irq & (1 << 13)) irq = 13; \ + if (m_sh2_state->pending_irq & (1 << 14)) irq = 14; \ + if (m_sh2_state->pending_irq & (1 << 15)) irq = 15; \ + if ((m_sh2_state->internal_irq_level != -1) && (m_sh2_state->internal_irq_level > irq)) irq = m_sh2_state->internal_irq_level; \ + if (irq >= 0) \ + sh2_exception(message,irq); \ +} while(0) + + +#endif // MAME_CPU_SH2_SH2COMN_H diff --git a/src/devices/cpu/sh/sh2dasm.cpp b/src/devices/cpu/sh/sh2dasm.cpp new file mode 100644 index 00000000000..ef823ee28a5 --- /dev/null +++ b/src/devices/cpu/sh/sh2dasm.cpp @@ -0,0 +1,610 @@ +// license:BSD-3-Clause +// copyright-holders:Juergen Buchmueller +#include "emu.h" +#include "debugger.h" +#include "sh2.h" + +#define SIGNX8(x) (((int32_t)(x) << 24) >> 24) +#define SIGNX12(x) (((int32_t)(x) << 20) >> 20) + +#define Rn ((opcode >> 8) & 15) +#define Rm ((opcode >> 4) & 15) + +static const char *const regname[16] = { + "R0", "R1", "R2", "R3", "R4", "R5", "R6", "R7", + "R8", "R9", "R10","R11","R12","R13","R14","SP" +}; + +static uint32_t op0000(std::ostream &stream, uint32_t pc, uint16_t opcode) +{ + uint32_t flags = 0; + switch(opcode & 0x3f) + { + case 0x02: + util::stream_format(stream, "STC SR,%s", regname[Rn]); + break; + case 0x03: + util::stream_format(stream, "BSRF %s", regname[Rn]); + break; + case 0x08: + stream << "CLRT"; + break; + case 0x09: + stream << "NOP"; + break; + case 0x0A: + util::stream_format(stream, "STS MACH,%s", regname[Rn]); + break; + case 0x0B: + stream << "RTS"; + flags = DASMFLAG_STEP_OUT; + break; + case 0x12: + util::stream_format(stream, "STS GBR,%s", regname[Rn]); + break; + case 0x18: + stream << "SETT"; + break; + case 0x19: + stream << "DIV0U"; + break; + case 0x1A: + util::stream_format(stream, "STS MACL,%s", regname[Rn]); + break; + case 0x1B: + stream << "SLEEP"; + break; + case 0x22: + util::stream_format(stream, "STC VBR,%s", regname[Rn]); + break; + case 0x23: + util::stream_format(stream, "BRAF %s", regname[Rn]); + break; + case 0x28: + stream << "CLRMAC"; + break; + case 0x29: + util::stream_format(stream, "MOVT %s", regname[Rn]); + break; + case 0x2A: + util::stream_format(stream, "STS PR,%s", regname[Rn]); + break; + case 0x2B: + stream << "RTE"; + flags = DASMFLAG_STEP_OUT; + break; + default: + switch(opcode & 15) + { + case 0: + util::stream_format(stream, "?????? $%04X", opcode); + break; + case 1: + util::stream_format(stream, "?????? $%04X", opcode); + break; + case 2: + util::stream_format(stream, "?????? $%04X", opcode); + break; + case 3: + util::stream_format(stream, "?????? $%04X", opcode); + break; + case 4: + util::stream_format(stream, "MOV.B %s,@(R0,%s)", regname[Rm], regname[Rn]); + break; + case 5: + util::stream_format(stream, "MOV.W %s,@(R0,%s)", regname[Rm], regname[Rn]); + break; + case 6: + util::stream_format(stream, "MOV.L %s,@(R0,%s)", regname[Rm], regname[Rn]); + break; + case 7: + util::stream_format(stream, "MUL.L %s,%s", regname[Rm], regname[Rn]); + break; + case 8: + util::stream_format(stream, "?????? $%04X", opcode); + break; + case 9: + util::stream_format(stream, "?????? $%04X", opcode); + break; + case 10: + util::stream_format(stream, "?????? $%04X", opcode); + break; + case 11: + util::stream_format(stream, "?????? $%04X", opcode); + break; + case 12: + util::stream_format(stream, "MOV.B @(R0,%s),%s", regname[Rm], regname[Rn]); + break; + case 13: + util::stream_format(stream, "MOV.W @(R0,%s),%s", regname[Rm], regname[Rn]); + break; + case 14: + util::stream_format(stream, "MOV.L @(R0,%s),%s", regname[Rm], regname[Rn]); + break; + case 15: + util::stream_format(stream, "MAC.L @%s+,@%s+", regname[Rn], regname[Rm]); + break; + } + } + return flags; +} + +static uint32_t op0001(std::ostream &stream, uint32_t pc, uint16_t opcode) +{ + util::stream_format(stream, "MOV.L %s,@($%02X,%s)", regname[Rm], (opcode & 15) * 4, regname[Rn]); + return 0; +} + +static uint32_t op0010(std::ostream &stream, uint32_t pc, uint16_t opcode) +{ + switch (opcode & 15) + { + case 0: + util::stream_format(stream, "MOV.B %s,@%s", regname[Rm], regname[Rn]); + break; + case 1: + util::stream_format(stream, "MOV.W %s,@%s", regname[Rm], regname[Rn]); + break; + case 2: + util::stream_format(stream, "MOV.L %s,@%s", regname[Rm], regname[Rn]); + break; + case 3: + util::stream_format(stream, "?????? $%04X", opcode); + break; + case 4: + util::stream_format(stream, "MOV.B %s,@-%s", regname[Rm], regname[Rn]); + break; + case 5: + util::stream_format(stream, "MOV.W %s,@-%s", regname[Rm], regname[Rn]); + break; + case 6: + util::stream_format(stream, "MOV.L %s,@-%s", regname[Rm], regname[Rn]); + break; + case 7: + util::stream_format(stream, "DIV0S %s,%s", regname[Rm], regname[Rn]); + break; + case 8: + util::stream_format(stream, "TST %s,%s", regname[Rm], regname[Rn]); + break; + case 9: + util::stream_format(stream, "AND %s,%s", regname[Rm], regname[Rn]); + break; + case 10: + util::stream_format(stream, "XOR %s,%s", regname[Rm], regname[Rn]); + break; + case 11: + util::stream_format(stream, "OR %s,%s", regname[Rm], regname[Rn]); + break; + case 12: + util::stream_format(stream, "CMP/STR %s,%s", regname[Rm], regname[Rn]); + break; + case 13: + util::stream_format(stream, "XTRCT %s,%s", regname[Rm], regname[Rn]); + break; + case 14: + util::stream_format(stream, "MULU.W %s,%s", regname[Rm], regname[Rn]); + break; + case 15: + util::stream_format(stream, "MULS.W %s,%s", regname[Rm], regname[Rn]); + break; + } + return 0; +} + +static uint32_t op0011(std::ostream &stream, uint32_t pc, uint16_t opcode) +{ + switch (opcode & 15) + { + case 0: + util::stream_format(stream, "CMP/EQ %s,%s", regname[Rm], regname[Rn]); + break; + case 1: + util::stream_format(stream, "?????? %s,%s", regname[Rm], regname[Rn]); + break; + case 2: + util::stream_format(stream, "CMP/HS %s,%s", regname[Rm], regname[Rn]); + break; + case 3: + util::stream_format(stream, "CMP/GE %s,%s", regname[Rm], regname[Rn]); + break; + case 4: + util::stream_format(stream, "DIV1 %s,%s", regname[Rm], regname[Rn]); + break; + case 5: + util::stream_format(stream, "DMULU.L %s,%s", regname[Rm], regname[Rn]); + break; + case 6: + util::stream_format(stream, "CMP/HI %s,%s", regname[Rm], regname[Rn]); + break; + case 7: + util::stream_format(stream, "CMP/GT %s,%s", regname[Rm], regname[Rn]); + break; + case 8: + util::stream_format(stream, "SUB %s,%s", regname[Rm], regname[Rn]); + break; + case 9: + util::stream_format(stream, "?????? %s,%s", regname[Rm], regname[Rn]); + break; + case 10: + util::stream_format(stream, "SUBC %s,%s", regname[Rm], regname[Rn]); + break; + case 11: + util::stream_format(stream, "SUBV %s,%s", regname[Rm], regname[Rn]); + break; + case 12: + util::stream_format(stream, "ADD %s,%s", regname[Rm], regname[Rn]); + break; + case 13: + util::stream_format(stream, "DMULS.L %s,%s", regname[Rm], regname[Rn]); + break; + case 14: + util::stream_format(stream, "ADDC %s,%s", regname[Rm], regname[Rn]); + break; + case 15: + util::stream_format(stream, "ADDV %s,%s", regname[Rm], regname[Rn]); + break; + } + return 0; +} + +static uint32_t op0100(std::ostream &stream, uint32_t pc, uint16_t opcode) +{ + uint32_t flags = 0; + switch(opcode & 0x3F) + { + case 0x00: + util::stream_format(stream, "SHLL %s", regname[Rn]); + break; + case 0x01: + util::stream_format(stream, "SHLR %s", regname[Rn]); + break; + case 0x02: + util::stream_format(stream, "STS.L MACH,@-%s", regname[Rn]); + break; + case 0x03: + util::stream_format(stream, "STC.L SR,@-%s", regname[Rn]); + break; + case 0x04: + util::stream_format(stream, "ROTL %s", regname[Rn]); + break; + case 0x05: + util::stream_format(stream, "ROTR %s", regname[Rn]); + break; + case 0x06: + util::stream_format(stream, "LDS.L @%s+,MACH", regname[Rn]); + break; + case 0x07: + util::stream_format(stream, "LDC.L @%s+,SR", regname[Rn]); + break; + case 0x08: + util::stream_format(stream, "SHLL2 %s", regname[Rn]); + break; + case 0x09: + util::stream_format(stream, "SHLR2 %s", regname[Rn]); + break; + case 0x0a: + util::stream_format(stream, "LDS %s,MACH", regname[Rn]); + break; + case 0x0b: + util::stream_format(stream, "JSR %s", regname[Rn]); + flags = DASMFLAG_STEP_OVER | DASMFLAG_STEP_OVER_EXTRA(1); + break; + case 0x0e: + util::stream_format(stream, "LDC %s,SR", regname[Rn]); + break; + case 0x10: + util::stream_format(stream, "DT %s", regname[Rn]); + break; + case 0x11: + util::stream_format(stream, "CMP/PZ %s", regname[Rn]); + break; + case 0x12: + util::stream_format(stream, "STS.L MACL,@-%s", regname[Rn]); + break; + case 0x13: + util::stream_format(stream, "STC.L GBR,@-%s", regname[Rn]); + break; + case 0x15: + util::stream_format(stream, "CMP/PL %s", regname[Rn]); + break; + case 0x16: + util::stream_format(stream, "LDS.L @%s+,MACL", regname[Rn]); + break; + case 0x17: + util::stream_format(stream, "LDC.L @%s+,GBR", regname[Rn]); + break; + case 0x18: + util::stream_format(stream, "SHLL8 %s", regname[Rn]); + break; + case 0x19: + util::stream_format(stream, "SHLR8 %s", regname[Rn]); + break; + case 0x1a: + util::stream_format(stream, "LDS %s,MACL", regname[Rn]); + break; + case 0x1b: + util::stream_format(stream, "TAS %s", regname[Rn]); + break; + case 0x1e: + util::stream_format(stream, "LDC %s,GBR", regname[Rn]); + break; + case 0x20: + util::stream_format(stream, "SHAL %s", regname[Rn]); + break; + case 0x21: + util::stream_format(stream, "SHAR %s", regname[Rn]); + break; + case 0x22: + util::stream_format(stream, "STS.L PR,@-%s", regname[Rn]); + break; + case 0x23: + util::stream_format(stream, "STC.L VBR,@-%s", regname[Rn]); + break; + case 0x24: + util::stream_format(stream, "ROTCL %s", regname[Rn]); + break; + case 0x25: + util::stream_format(stream, "ROTCR %s", regname[Rn]); + break; + case 0x26: + util::stream_format(stream, "LDS.L @%s+,PR", regname[Rn]); + break; + case 0x27: + util::stream_format(stream, "LDC.L @%s+,VBR", regname[Rn]); + break; + case 0x28: + util::stream_format(stream, "SHLL16 %s", regname[Rn]); + break; + case 0x29: + util::stream_format(stream, "SHLR16 %s", regname[Rn]); + break; + case 0x2a: + util::stream_format(stream, "LDS %s,PR", regname[Rn]); + break; + case 0x2b: + util::stream_format(stream, "JMP %s", regname[Rn]); + break; + case 0x2e: + util::stream_format(stream, "LDC %s,VBR", regname[Rn]); + break; + default: + if ((opcode & 15) == 15) + util::stream_format(stream, "MAC.W @%s+,@%s+", regname[Rm], regname[Rn]); + else + util::stream_format(stream, "?????? $%04X", opcode); + } + return flags; +} + +static uint32_t op0101(std::ostream &stream, uint32_t pc, uint16_t opcode) +{ + util::stream_format(stream, "MOV.L @($%02X,%s),%s", (opcode & 15) * 4, regname[Rm], regname[Rn]); + return 0; +} + +static uint32_t op0110(std::ostream &stream, uint32_t pc, uint16_t opcode) + +{ + switch(opcode & 0xF) + { + case 0x00: + util::stream_format(stream, "MOV.B @%s,%s", regname[Rm], regname[Rn]); + break; + case 0x01: + util::stream_format(stream, "MOV.W @%s,%s", regname[Rm], regname[Rn]); + break; + case 0x02: + util::stream_format(stream, "MOV.L @%s,%s", regname[Rm], regname[Rn]); + break; + case 0x03: + util::stream_format(stream, "MOV %s,%s", regname[Rm], regname[Rn]); + break; + case 0x04: + util::stream_format(stream, "MOV.B @%s+,%s", regname[Rm], regname[Rn]); + break; + case 0x05: + util::stream_format(stream, "MOV.W @%s+,%s", regname[Rm], regname[Rn]); + break; + case 0x06: + util::stream_format(stream, "MOV.L @%s+,%s", regname[Rm], regname[Rn]); + break; + case 0x07: + util::stream_format(stream, "NOT %s,%s", regname[Rm], regname[Rn]); + break; + case 0x08: + util::stream_format(stream, "SWAP.B %s,%s", regname[Rm], regname[Rn]); + break; + case 0x09: + util::stream_format(stream, "SWAP.W %s,%s", regname[Rm], regname[Rn]); + break; + case 0x0a: + util::stream_format(stream, "NEGC %s,%s", regname[Rm], regname[Rn]); + break; + case 0x0b: + util::stream_format(stream, "NEG %s,%s", regname[Rm], regname[Rn]); + break; + case 0x0c: + util::stream_format(stream, "EXTU.B %s,%s", regname[Rm], regname[Rn]); + break; + case 0x0d: + util::stream_format(stream, "EXTU.W %s,%s", regname[Rm], regname[Rn]); + break; + case 0x0e: + util::stream_format(stream, "EXTS.B %s,%s", regname[Rm], regname[Rn]); + break; + case 0x0f: + util::stream_format(stream, "EXTS.W %s,%s", regname[Rm], regname[Rn]); + break; + } + return 0; +} + +static uint32_t op0111(std::ostream &stream, uint32_t pc, uint16_t opcode) +{ + util::stream_format(stream, "ADD #$%02X,%s", opcode & 0xff, regname[Rn]); + return 0; +} + +static uint32_t op1000(std::ostream &stream, uint32_t pc, uint16_t opcode) +{ + switch((opcode >> 8) & 15) + { + case 0: + util::stream_format(stream, "MOV.B R0,@($%02X,%s)", (opcode & 15), regname[Rm]); + break; + case 1: + util::stream_format(stream, "MOV.W R0,@($%02X,%s)", (opcode & 15) * 2, regname[Rm]); + break; + case 4: + util::stream_format(stream, "MOV.B @($%02X,%s),R0", (opcode & 15), regname[Rm]); + break; + case 5: + util::stream_format(stream, "MOV.W @($%02X,%s),R0", (opcode & 15), regname[Rm]); + break; + case 8: + util::stream_format(stream, "CMP/EQ #$%02X,R0", (opcode & 0xff)); + break; + case 9: + util::stream_format(stream, "BT $%08X", pc + SIGNX8(opcode & 0xff) * 2 + 2); + break; + case 11: + util::stream_format(stream, "BF $%08X", pc + SIGNX8(opcode & 0xff) * 2 + 2); + break; + case 13: + util::stream_format(stream, "BTS $%08X", pc + SIGNX8(opcode & 0xff) * 2 + 2); + break; + case 15: + util::stream_format(stream, "BFS $%08X", pc + SIGNX8(opcode & 0xff) * 2 + 2); + break; + default : + util::stream_format(stream, "invalid $%04X", opcode); + } + return 0; +} + +static uint32_t op1001(std::ostream &stream, uint32_t pc, uint16_t opcode) +{ + util::stream_format(stream, "MOV.W @($%04X,PC),%s [%08X]", (opcode & 0xff) * 2, regname[Rn], pc+((opcode & 0xff) * 2)+2); + return 0; +} + +static uint32_t op1010(std::ostream &stream, uint32_t pc, uint16_t opcode) +{ + util::stream_format(stream, "BRA $%08X", SIGNX12(opcode & 0xfff) * 2 + pc + 2); + return 0; +} + +static uint32_t op1011(std::ostream &stream, uint32_t pc, uint16_t opcode) +{ + util::stream_format(stream, "BSR $%08X", SIGNX12(opcode & 0xfff) * 2 + pc + 2); + return DASMFLAG_STEP_OVER | DASMFLAG_STEP_OVER_EXTRA(1); +} + +static uint32_t op1100(std::ostream &stream, uint32_t pc, uint16_t opcode) +{ + uint32_t flags = 0; + switch((opcode >> 8) & 15) + { + case 0: + util::stream_format(stream, "MOV.B R0,@($%02X,GBR)", opcode & 0xff); + break; + case 1: + util::stream_format(stream, "MOV.W R0,@($%04X,GBR)", (opcode & 0xff) * 2); + break; + case 2: + util::stream_format(stream, "MOV.L R0,@($%04X,GBR)", (opcode & 0xff) * 4); + break; + case 3: + util::stream_format(stream, "TRAPA #$%02X", opcode & 0xff); + flags = DASMFLAG_STEP_OVER; + break; + case 4: + util::stream_format(stream, "MOV.B @($%02X,GBR),R0", opcode & 0xff); + break; + case 5: + util::stream_format(stream, "MOV.W @($%04X,GBR),R0", (opcode & 0xff) * 2); + break; + case 6: + util::stream_format(stream, "MOV.L @($%04X,GBR),R0", (opcode & 0xff) * 4); + break; + case 7: + util::stream_format(stream, "MOVA @($%04X,PC),R0 [%08X]", (opcode & 0xff) * 4, ((pc + 2) & ~3) + (opcode & 0xff) * 4); + break; + case 8: + util::stream_format(stream, "TST #$%02X,R0", opcode & 0xff); + break; + case 9: + util::stream_format(stream, "AND #$%02X,R0", opcode & 0xff); + break; + case 10: + util::stream_format(stream, "XOR #$%02X,R0", opcode & 0xff); + break; + case 11: + util::stream_format(stream, "OR #$%02X,R0", opcode & 0xff); + break; + case 12: + util::stream_format(stream, "TST.B #$%02X,@(R0,GBR)", opcode & 0xff); + break; + case 13: + util::stream_format(stream, "AND.B #$%02X,@(R0,GBR)", opcode & 0xff); + break; + case 14: + util::stream_format(stream, "XOR.B #$%02X,@(R0,GBR)", opcode & 0xff); + break; + case 15: + util::stream_format(stream, "OR.B #$%02X,@(R0,GBR)", opcode & 0xff); + break; + } + return flags; +} + +static uint32_t op1101(std::ostream &stream, uint32_t pc, uint16_t opcode) +{ + util::stream_format(stream, "MOV.L @($%02X,PC),%s [%08X]", (opcode * 4) & 0xff, regname[Rn], ((pc + 2) & ~3) + (opcode & 0xff) * 4); + return 0; +} + +static uint32_t op1110(std::ostream &stream, uint32_t pc, uint16_t opcode) +{ + util::stream_format(stream, "MOV #$%02X,%s", (opcode & 0xff), regname[Rn]); + return 0; +} + +static uint32_t op1111(std::ostream &stream, uint32_t pc, uint16_t opcode) +{ + util::stream_format(stream, "unknown $%04X", opcode); + return 0; +} + +unsigned DasmSH2(std::ostream &stream, unsigned pc, uint16_t opcode) +{ + uint32_t flags; + + pc += 2; + + switch ((opcode >> 12) & 15) + { + case 0: flags = op0000(stream, pc, opcode); break; + case 1: flags = op0001(stream, pc, opcode); break; + case 2: flags = op0010(stream, pc, opcode); break; + case 3: flags = op0011(stream, pc, opcode); break; + case 4: flags = op0100(stream, pc, opcode); break; + case 5: flags = op0101(stream, pc, opcode); break; + case 6: flags = op0110(stream, pc, opcode); break; + case 7: flags = op0111(stream, pc, opcode); break; + case 8: flags = op1000(stream, pc, opcode); break; + case 9: flags = op1001(stream, pc, opcode); break; + case 10: flags = op1010(stream, pc, opcode); break; + case 11: flags = op1011(stream, pc, opcode); break; + case 12: flags = op1100(stream, pc, opcode); break; + case 13: flags = op1101(stream, pc, opcode); break; + case 14: flags = op1110(stream, pc, opcode); break; + default: flags = op1111(stream, pc, opcode); break; + } + return 2 | flags | DASMFLAG_SUPPORTED; +} + +CPU_DISASSEMBLE(sh2) +{ + return DasmSH2(stream, pc, (oprom[0] << 8) | oprom[1]); +} diff --git a/src/devices/cpu/sh/sh2drc.cpp b/src/devices/cpu/sh/sh2drc.cpp new file mode 100644 index 00000000000..1003463b97a --- /dev/null +++ b/src/devices/cpu/sh/sh2drc.cpp @@ -0,0 +1,2982 @@ +// license:BSD-3-Clause +// copyright-holders:R. Belmont +/*************************************************************************** + + sh2drc.c + Universal machine language-based SH-2 emulator. + +***************************************************************************/ + +#include "emu.h" +#include "debugger.h" +#include "sh2.h" +#include "sh2comn.h" + +extern unsigned DasmSH2(std::ostream &stream, unsigned pc, uint16_t opcode); + +using namespace uml; + +/*************************************************************************** + DEBUGGING +***************************************************************************/ + +#define SET_EA (0) // makes slower but "shows work" in the EA fake register like the interpreter + +#define ADDSUBV_DIRECT (0) + +#if SET_EA +#define SETEA(x) UML_MOV(block, mem(&m_sh2_state->ea), ireg(x)) +#else +#define SETEA(x) +#endif + +/*************************************************************************** + CONSTANTS +***************************************************************************/ + +/* map variables */ +#define MAPVAR_PC M0 +#define MAPVAR_CYCLES M1 + +/* exit codes */ +#define EXECUTE_OUT_OF_CYCLES 0 +#define EXECUTE_MISSING_CODE 1 +#define EXECUTE_UNMAPPED_CODE 2 +#define EXECUTE_RESET_CACHE 3 + +#define PROBE_ADDRESS ~0 + + +/*************************************************************************** + MACROS +***************************************************************************/ + +#define R32(reg) m_regmap[reg] + +/*************************************************************************** + INLINE FUNCTIONS +***************************************************************************/ + +/*------------------------------------------------- + epc - compute the exception PC from a + descriptor +-------------------------------------------------*/ + +uint32_t sh2_device::epc(const opcode_desc *desc) +{ + return (desc->flags & OPFLAG_IN_DELAY_SLOT) ? (desc->pc - 1) : desc->pc; +} + +/*------------------------------------------------- + alloc_handle - allocate a handle if not + already allocated +-------------------------------------------------*/ + +void sh2_device::alloc_handle(drcuml_state *drcuml, code_handle **handleptr, const char *name) +{ + if (*handleptr == nullptr) + *handleptr = drcuml->handle_alloc(name); +} + +/*------------------------------------------------- + load_fast_iregs - load any fast integer + registers +-------------------------------------------------*/ + +void sh2_device::load_fast_iregs(drcuml_block *block) +{ + int regnum; + + for (regnum = 0; regnum < ARRAY_LENGTH(m_regmap); regnum++) + { + if (m_regmap[regnum].is_int_register()) + { + UML_MOV(block, uml::parameter::make_ireg(m_regmap[regnum].ireg()), mem(&m_sh2_state->r[regnum])); + } + } +} + + +/*------------------------------------------------- + save_fast_iregs - save any fast integer + registers +-------------------------------------------------*/ + +void sh2_device::save_fast_iregs(drcuml_block *block) +{ + int regnum; + + for (regnum = 0; regnum < ARRAY_LENGTH(m_regmap); regnum++) + { + if (m_regmap[regnum].is_int_register()) + { + UML_MOV(block, mem(&m_sh2_state->r[regnum]), uml::parameter::make_ireg(m_regmap[regnum].ireg())); + } + } +} + +/*------------------------------------------------- + cfunc_printf_probe - print the current CPU + state and return +-------------------------------------------------*/ + +static void cfunc_printf_probe(void *param) +{ + ((sh2_device *)param)->func_printf_probe(); +} + +void sh2_device::func_printf_probe() +{ + uint32_t pc = m_sh2_state->pc; + + printf(" PC=%08X r0=%08X r1=%08X r2=%08X\n", + pc, + (uint32_t)m_sh2_state->r[0], + (uint32_t)m_sh2_state->r[1], + (uint32_t)m_sh2_state->r[2]); + printf(" r3=%08X r4=%08X r5=%08X r6=%08X\n", + (uint32_t)m_sh2_state->r[3], + (uint32_t)m_sh2_state->r[4], + (uint32_t)m_sh2_state->r[5], + (uint32_t)m_sh2_state->r[6]); + printf(" r7=%08X r8=%08X r9=%08X r10=%08X\n", + (uint32_t)m_sh2_state->r[7], + (uint32_t)m_sh2_state->r[8], + (uint32_t)m_sh2_state->r[9], + (uint32_t)m_sh2_state->r[10]); + printf(" r11=%08X r12=%08X r13=%08X r14=%08X\n", + (uint32_t)m_sh2_state->r[11], + (uint32_t)m_sh2_state->r[12], + (uint32_t)m_sh2_state->r[13], + (uint32_t)m_sh2_state->r[14]); + printf(" r15=%08X macl=%08X mach=%08X gbr=%08X\n", + (uint32_t)m_sh2_state->r[15], + (uint32_t)m_sh2_state->macl, + (uint32_t)m_sh2_state->mach, + (uint32_t)m_sh2_state->gbr); + printf(" evec %x irqsr %x pc=%08x\n", + (uint32_t)m_sh2_state->evec, + (uint32_t)m_sh2_state->irqsr, (uint32_t)m_sh2_state->pc); +} + +/*------------------------------------------------- + cfunc_unimplemented - handler for + unimplemented opcdes +-------------------------------------------------*/ + +static void cfunc_unimplemented(void *param) +{ + ((sh2_device *)param)->func_unimplemented(); +} + +void sh2_device::func_unimplemented() +{ + // set up an invalid opcode exception + m_sh2_state->evec = RL( m_sh2_state->vbr + 4 * 4 ); + m_sh2_state->evec &= AM; + m_sh2_state->irqsr = m_sh2_state->sr; + // claim it's an NMI, because it pretty much is + m_sh2_state->pending_nmi = 1; +} + +/*------------------------------------------------- + cfunc_fastirq - checks for pending IRQs +-------------------------------------------------*/ +static void cfunc_fastirq(void *param) +{ + ((sh2_device *)param)->func_fastirq(); +} + +void sh2_device::func_fastirq() +{ + sh2_exception("fastirq",m_sh2_state->irqline); +} + +/*------------------------------------------------- + cfunc_MAC_W - implementation of MAC_W Rm,Rn +-------------------------------------------------*/ +static void cfunc_MAC_W(void *param) +{ + ((sh2_device *)param)->func_MAC_W(); +} + +void sh2_device::func_MAC_W() +{ + int32_t tempm, tempn, dest, src, ans; + uint32_t templ; + uint16_t opcode; + int n, m; + + // recover the opcode + opcode = m_sh2_state->arg0; + + // extract the operands + n = Rn; + m = Rm; + + tempn = (int32_t) RW( m_sh2_state->r[n] ); + m_sh2_state->r[n] += 2; + tempm = (int32_t) RW( m_sh2_state->r[m] ); + m_sh2_state->r[m] += 2; + templ = m_sh2_state->macl; + tempm = ((int32_t) (short) tempn * (int32_t) (short) tempm); + if ((int32_t) m_sh2_state->macl >= 0) + dest = 0; + else + dest = 1; + if ((int32_t) tempm >= 0) + { + src = 0; + tempn = 0; + } + else + { + src = 1; + tempn = 0xffffffff; + } + src += dest; + m_sh2_state->macl += tempm; + if ((int32_t) m_sh2_state->macl >= 0) + ans = 0; + else + ans = 1; + ans += dest; + if (m_sh2_state->sr & S) + { + if (ans == 1) + { + if ((m_cpu_type == CPU_TYPE_SH1) && ((src == 0) || (src == 2))) + { + m_sh2_state->mach |= 0x00000001; + } + + if (src == 0) + m_sh2_state->macl = 0x7fffffff; + if (src == 2) + m_sh2_state->macl = 0x80000000; + } + } + else + { + m_sh2_state->mach += tempn; + if (templ > m_sh2_state->macl) + m_sh2_state->mach += 1; + + // SH-1 has limited precision + if (m_cpu_type == CPU_TYPE_SH1) + { + if ((m_sh2_state->mach & 0x200) == 0) + { + m_sh2_state->mach &= 0x3ff; + } + else + { + m_sh2_state->mach |= 0xfffffc00; + } + } + + + } +} + +/*------------------------------------------------- + cfunc_MAC_L - implementation of MAC_L Rm,Rn +-------------------------------------------------*/ +static void cfunc_MAC_L(void *param) +{ + ((sh2_device *)param)->func_MAC_L(); +} + +void sh2_device::func_MAC_L() +{ + uint32_t RnL, RnH, RmL, RmH, Res0, Res1, Res2; + uint32_t temp0, temp1, temp2, temp3; + int32_t tempm, tempn, fnLmL; + uint16_t opcode; + int n, m; + + // recover the opcode + opcode = m_sh2_state->arg0; + + // extract the operands + n = Rn; + m = Rm; + + tempn = (int32_t) RL( m_sh2_state->r[n] ); + m_sh2_state->r[n] += 4; + tempm = (int32_t) RL( m_sh2_state->r[m] ); + m_sh2_state->r[m] += 4; + if ((int32_t) (tempn ^ tempm) < 0) + fnLmL = -1; + else + fnLmL = 0; + if (tempn < 0) + tempn = 0 - tempn; + if (tempm < 0) + tempm = 0 - tempm; + temp1 = (uint32_t) tempn; + temp2 = (uint32_t) tempm; + RnL = temp1 & 0x0000ffff; + RnH = (temp1 >> 16) & 0x0000ffff; + RmL = temp2 & 0x0000ffff; + RmH = (temp2 >> 16) & 0x0000ffff; + temp0 = RmL * RnL; + temp1 = RmH * RnL; + temp2 = RmL * RnH; + temp3 = RmH * RnH; + Res2 = 0; + Res1 = temp1 + temp2; + if (Res1 < temp1) + Res2 += 0x00010000; + temp1 = (Res1 << 16) & 0xffff0000; + Res0 = temp0 + temp1; + if (Res0 < temp0) + Res2++; + Res2 = Res2 + ((Res1 >> 16) & 0x0000ffff) + temp3; + if (fnLmL < 0) + { + Res2 = ~Res2; + if (Res0 == 0) + Res2++; + else + Res0 = (~Res0) + 1; + } + if (m_sh2_state->sr & S) + { + Res0 = m_sh2_state->macl + Res0; + if (m_sh2_state->macl > Res0) + Res2++; + Res2 += (m_sh2_state->mach & 0x0000ffff); + if (((int32_t) Res2 < 0) && (Res2 < 0xffff8000)) + { + Res2 = 0x00008000; + Res0 = 0x00000000; + } + else if (((int32_t) Res2 > 0) && (Res2 > 0x00007fff)) + { + Res2 = 0x00007fff; + Res0 = 0xffffffff; + } + m_sh2_state->mach = Res2; + m_sh2_state->macl = Res0; + } + else + { + Res0 = m_sh2_state->macl + Res0; + if (m_sh2_state->macl > Res0) + Res2++; + Res2 += m_sh2_state->mach; + m_sh2_state->mach = Res2; + m_sh2_state->macl = Res0; + } +} + +/*------------------------------------------------- + cfunc_DIV1 - implementation of DIV1 Rm,Rn +-------------------------------------------------*/ +static void cfunc_DIV1(void *param) +{ + ((sh2_device *)param)->func_DIV1(); +} + +void sh2_device::func_DIV1() +{ + uint32_t tmp0; + uint32_t old_q; + uint16_t opcode; + int n, m; + + // recover the opcode + opcode = m_sh2_state->arg0; + + // extract the operands + n = Rn; + m = Rm; + + old_q = m_sh2_state->sr & Q; + if (0x80000000 & m_sh2_state->r[n]) + m_sh2_state->sr |= Q; + else + m_sh2_state->sr &= ~Q; + + m_sh2_state->r[n] = (m_sh2_state->r[n] << 1) | (m_sh2_state->sr & T); + + if (!old_q) + { + if (!(m_sh2_state->sr & M)) + { + tmp0 = m_sh2_state->r[n]; + m_sh2_state->r[n] -= m_sh2_state->r[m]; + if(!(m_sh2_state->sr & Q)) + if(m_sh2_state->r[n] > tmp0) + m_sh2_state->sr |= Q; + else + m_sh2_state->sr &= ~Q; + else + if(m_sh2_state->r[n] > tmp0) + m_sh2_state->sr &= ~Q; + else + m_sh2_state->sr |= Q; + } + else + { + tmp0 = m_sh2_state->r[n]; + m_sh2_state->r[n] += m_sh2_state->r[m]; + if(!(m_sh2_state->sr & Q)) + { + if(m_sh2_state->r[n] < tmp0) + m_sh2_state->sr &= ~Q; + else + m_sh2_state->sr |= Q; + } + else + { + if(m_sh2_state->r[n] < tmp0) + m_sh2_state->sr |= Q; + else + m_sh2_state->sr &= ~Q; + } + } + } + else + { + if (!(m_sh2_state->sr & M)) + { + tmp0 = m_sh2_state->r[n]; + m_sh2_state->r[n] += m_sh2_state->r[m]; + if(!(m_sh2_state->sr & Q)) + if(m_sh2_state->r[n] < tmp0) + m_sh2_state->sr |= Q; + else + m_sh2_state->sr &= ~Q; + else + if(m_sh2_state->r[n] < tmp0) + m_sh2_state->sr &= ~Q; + else + m_sh2_state->sr |= Q; + } + else + { + tmp0 = m_sh2_state->r[n]; + m_sh2_state->r[n] -= m_sh2_state->r[m]; + if(!(m_sh2_state->sr & Q)) + if(m_sh2_state->r[n] > tmp0) + m_sh2_state->sr &= ~Q; + else + m_sh2_state->sr |= Q; + else + if(m_sh2_state->r[n] > tmp0) + m_sh2_state->sr |= Q; + else + m_sh2_state->sr &= ~Q; + } + } + + tmp0 = (m_sh2_state->sr & (Q | M)); + if((!tmp0) || (tmp0 == 0x300)) /* if Q == M set T else clear T */ + m_sh2_state->sr |= T; + else + m_sh2_state->sr &= ~T; +} + +#if (!ADDSUBV_DIRECT) +/*------------------------------------------------- + cfunc_ADDV - implementation of ADDV Rm,Rn +-------------------------------------------------*/ +static void cfunc_ADDV(void *param) +{ + ((sh2_device *)param)->func_ADDV(); +} + +void sh2_device::func_ADDV() +{ + int32_t dest, src, ans; + uint16_t opcode; + int n, m; + + // recover the opcode + opcode = m_sh2_state->arg0; + + // extract the operands + n = Rn; + m = Rm; + + if ((int32_t) m_sh2_state->r[n] >= 0) + dest = 0; + else + dest = 1; + if ((int32_t) m_sh2_state->r[m] >= 0) + src = 0; + else + src = 1; + src += dest; + m_sh2_state->r[n] += m_sh2_state->r[m]; + if ((int32_t) m_sh2_state->r[n] >= 0) + ans = 0; + else + ans = 1; + ans += dest; + if (src == 0 || src == 2) + { + if (ans == 1) + m_sh2_state->sr |= T; + else + m_sh2_state->sr &= ~T; + } + else + m_sh2_state->sr &= ~T; +} + +/*------------------------------------------------- + cfunc_SUBV - implementation of SUBV Rm,Rn +-------------------------------------------------*/ +static void cfunc_SUBV(void *param) +{ + ((sh2_device *)param)->func_SUBV(); +} + +void sh2_device::func_SUBV() +{ + int32_t dest, src, ans; + uint16_t opcode; + int n, m; + + // recover the opcode + opcode = m_sh2_state->arg0; + + // extract the operands + n = Rn; + m = Rm; + + if ((int32_t) m_sh2_state->r[n] >= 0) + dest = 0; + else + dest = 1; + if ((int32_t) m_sh2_state->r[m] >= 0) + src = 0; + else + src = 1; + src += dest; + m_sh2_state->r[n] -= m_sh2_state->r[m]; + if ((int32_t) m_sh2_state->r[n] >= 0) + ans = 0; + else + ans = 1; + ans += dest; + if (src == 1) + { + if (ans == 1) + m_sh2_state->sr |= T; + else + m_sh2_state->sr &= ~T; + } + else + m_sh2_state->sr &= ~T; +} +#else +void sh2_device::func_ADDV() {} +void sh2_device::func_SUBV() {} +#endif + +/*------------------------------------------------- + code_flush_cache - flush the cache and + regenerate static code +-------------------------------------------------*/ + +void sh2_device::code_flush_cache() +{ + drcuml_state *drcuml = m_drcuml.get(); + + /* empty the transient cache contents */ + drcuml->reset(); + + try + { + /* generate the entry point and out-of-cycles handlers */ + static_generate_nocode_handler(); + static_generate_out_of_cycles(); + static_generate_entry_point(); + + /* add subroutines for memory accesses */ + static_generate_memory_accessor(1, false, "read8", &m_read8); + static_generate_memory_accessor(1, true, "write8", &m_write8); + static_generate_memory_accessor(2, false, "read16", &m_read16); + static_generate_memory_accessor(2, true, "write16", &m_write16); + static_generate_memory_accessor(4, false, "read32", &m_read32); + static_generate_memory_accessor(4, true, "write32", &m_write32); + } + catch (drcuml_block::abort_compilation &) + { + fatalerror("Unable to generate SH2 static code\n"); + } + + m_cache_dirty = false; +} + +/* Execute cycles - returns number of cycles actually run */ +void sh2_device::execute_run_drc() +{ + drcuml_state *drcuml = m_drcuml.get(); + int execute_result; + + // run any active DMAs now +#ifndef USE_TIMER_FOR_DMA + for ( int i = 0; i < m_sh2_state->icount ; i++) + { + for( int dma=0;dma<1;dma++) + { + if (m_dma_timer_active[dma]) + sh2_do_dma(dma); + } + } +#endif + + /* reset the cache if dirty */ + if (m_cache_dirty) + code_flush_cache(); + + /* execute */ + do + { + /* run as much as we can */ + execute_result = drcuml->execute(*m_entry); + + /* if we need to recompile, do it */ + if (execute_result == EXECUTE_MISSING_CODE) + { + code_compile_block(0, m_sh2_state->pc); + } + else if (execute_result == EXECUTE_UNMAPPED_CODE) + { + fatalerror("Attempted to execute unmapped code at PC=%08X\n", m_sh2_state->pc); + } + else if (execute_result == EXECUTE_RESET_CACHE) + { + code_flush_cache(); + } + } while (execute_result != EXECUTE_OUT_OF_CYCLES); +} + +/*------------------------------------------------- + code_compile_block - compile a block of the + given mode at the specified pc +-------------------------------------------------*/ + +void sh2_device::code_compile_block(uint8_t mode, offs_t pc) +{ + drcuml_state *drcuml = m_drcuml.get(); + compiler_state compiler = { 0 }; + const opcode_desc *seqhead, *seqlast; + const opcode_desc *desclist; + bool override = false; + drcuml_block *block; + + g_profiler.start(PROFILER_DRC_COMPILE); + + /* get a description of this sequence */ + desclist = m_drcfe->describe_code(pc); + if (drcuml->logging() || drcuml->logging_native()) + log_opcode_desc(drcuml, desclist, 0); + + bool succeeded = false; + while (!succeeded) + { + try + { + /* start the block */ + block = drcuml->begin_block(4096); + + /* loop until we get through all instruction sequences */ + for (seqhead = desclist; seqhead != nullptr; seqhead = seqlast->next()) + { + const opcode_desc *curdesc; + uint32_t nextpc; + + /* add a code log entry */ + if (drcuml->logging()) + block->append_comment("-------------------------"); // comment + + /* determine the last instruction in this sequence */ + for (seqlast = seqhead; seqlast != nullptr; seqlast = seqlast->next()) + if (seqlast->flags & OPFLAG_END_SEQUENCE) + break; + assert(seqlast != nullptr); + + /* if we don't have a hash for this mode/pc, or if we are overriding all, add one */ + if (override || !drcuml->hash_exists(mode, seqhead->pc)) + UML_HASH(block, mode, seqhead->pc); // hash mode,pc + + /* if we already have a hash, and this is the first sequence, assume that we */ + /* are recompiling due to being out of sync and allow future overrides */ + else if (seqhead == desclist) + { + override = true; + UML_HASH(block, mode, seqhead->pc); // hash mode,pc + } + + /* otherwise, redispatch to that fixed PC and skip the rest of the processing */ + else + { + UML_LABEL(block, seqhead->pc | 0x80000000); // label seqhead->pc | 0x80000000 + UML_HASHJMP(block, 0, seqhead->pc, *m_nocode); + // hashjmp ,seqhead->pc,nocode + continue; + } + + /* validate this code block if we're not pointing into ROM */ + if (m_program->get_write_ptr(seqhead->physpc) != nullptr) + generate_checksum_block(block, &compiler, seqhead, seqlast); + + /* label this instruction, if it may be jumped to locally */ + if (seqhead->flags & OPFLAG_IS_BRANCH_TARGET) + { + UML_LABEL(block, seqhead->pc | 0x80000000); // label seqhead->pc | 0x80000000 + } + + /* iterate over instructions in the sequence and compile them */ + for (curdesc = seqhead; curdesc != seqlast->next(); curdesc = curdesc->next()) + { + generate_sequence_instruction(block, &compiler, curdesc, 0xffffffff); + } + + /* if we need to return to the start, do it */ + if (seqlast->flags & OPFLAG_RETURN_TO_START) + { + nextpc = pc; + } + /* otherwise we just go to the next instruction */ + else + { + nextpc = seqlast->pc + (seqlast->skipslots + 1) * 2; + } + + /* count off cycles and go there */ + generate_update_cycles(block, &compiler, nextpc, true); // + + /* SH2 has no modes */ + if (seqlast->next() == nullptr || seqlast->next()->pc != nextpc) + { + UML_HASHJMP(block, 0, nextpc, *m_nocode); + } + // hashjmp ,nextpc,nocode + } + + /* end the sequence */ + block->end(); + g_profiler.stop(); + succeeded = true; + } + catch (drcuml_block::abort_compilation &) + { + code_flush_cache(); + } + } +} + +/*------------------------------------------------- + static_generate_entry_point - generate a + static entry point +-------------------------------------------------*/ + +void sh2_device::static_generate_entry_point() +{ + drcuml_state *drcuml = m_drcuml.get(); + code_label skip = 1; + drcuml_block *block; + + /* begin generating */ + block = drcuml->begin_block(200); + + /* forward references */ + alloc_handle(drcuml, &m_nocode, "nocode"); + alloc_handle(drcuml, &m_write32, "write32"); // necessary? + alloc_handle(drcuml, &m_entry, "entry"); + UML_HANDLE(block, *m_entry); // handle entry + + /* load fast integer registers */ + load_fast_iregs(block); + + /* check for interrupts */ + UML_MOV(block, mem(&m_sh2_state->irqline), 0xffffffff); // mov irqline, #-1 + UML_CMP(block, mem(&m_sh2_state->pending_nmi), 0); // cmp pending_nmi, #0 + UML_JMPc(block, COND_Z, skip+2); // jz skip+2 + + UML_MOV(block, mem(&m_sh2_state->pending_nmi), 0); // zap pending_nmi + UML_JMP(block, skip+1); // and then go take it (evec is already set) + + UML_LABEL(block, skip+2); // skip+2: + UML_MOV(block, mem(&m_sh2_state->evec), 0xffffffff); // mov evec, -1 + UML_MOV(block, I0, 0xffffffff); // mov r0, -1 (r0 = irq) + UML_AND(block, I1, I0, 0xffff); // and r1, 0xffff + + UML_LZCNT(block, I1, mem(&m_sh2_state->pending_irq)); // lzcnt r1, r1 + UML_CMP(block, I1, 32); // cmp r1, #32 + UML_JMPc(block, COND_Z, skip+4); // jz skip+4 + + UML_SUB(block, mem(&m_sh2_state->irqline), 31, I1); // sub irqline, #31, r1 + + UML_LABEL(block, skip+4); // skip+4: + UML_CMP(block, mem(&m_sh2_state->internal_irq_level), 0xffffffff); // cmp internal_irq_level, #-1 + UML_JMPc(block, COND_Z, skip+3); // jz skip+3 + UML_CMP(block, mem(&m_sh2_state->internal_irq_level), mem(&m_sh2_state->irqline)); // cmp internal_irq_level, irqline + UML_JMPc(block, COND_LE, skip+3); // jle skip+3 + + UML_MOV(block, mem(&m_sh2_state->irqline), mem(&m_sh2_state->internal_irq_level)); // mov r0, internal_irq_level + + UML_LABEL(block, skip+3); // skip+3: + UML_CMP(block, mem(&m_sh2_state->irqline), 0xffffffff); // cmp irqline, #-1 + UML_JMPc(block, COND_Z, skip+1); // jz skip+1 + UML_CALLC(block, cfunc_fastirq, this); // callc fastirq + + UML_LABEL(block, skip+1); // skip+1: + + UML_CMP(block, mem(&m_sh2_state->evec), 0xffffffff); // cmp evec, 0xffffffff + UML_JMPc(block, COND_Z, skip); // jz skip + + UML_SUB(block, R32(15), R32(15), 4); // sub R15, R15, #4 + UML_MOV(block, I0, R32(15)); // mov r0, R15 + UML_MOV(block, I1, mem(&m_sh2_state->irqsr)); // mov r1, irqsr + UML_CALLH(block, *m_write32); // call write32 + + UML_SUB(block, R32(15), R32(15), 4); // sub R15, R15, #4 + UML_MOV(block, I0, R32(15)); // mov r0, R15 + UML_MOV(block, I1, mem(&m_sh2_state->pc)); // mov r1, pc + UML_CALLH(block, *m_write32); // call write32 + + UML_MOV(block, mem(&m_sh2_state->pc), mem(&m_sh2_state->evec)); // mov pc, evec + + UML_LABEL(block, skip); // skip: + + /* generate a hash jump via the current mode and PC */ + UML_HASHJMP(block, 0, mem(&m_sh2_state->pc), *m_nocode); // hashjmp ,,nocode + + block->end(); +} + +/*------------------------------------------------- + static_generate_nocode_handler - generate an + exception handler for "out of code" +-------------------------------------------------*/ + +void sh2_device::static_generate_nocode_handler() +{ + drcuml_state *drcuml = m_drcuml.get(); + drcuml_block *block; + + /* begin generating */ + block = drcuml->begin_block(10); + + /* generate a hash jump via the current mode and PC */ + alloc_handle(drcuml, &m_nocode, "nocode"); + UML_HANDLE(block, *m_nocode); // handle nocode + UML_GETEXP(block, I0); // getexp i0 + UML_MOV(block, mem(&m_sh2_state->pc), I0); // mov [pc],i0 + save_fast_iregs(block); + UML_EXIT(block, EXECUTE_MISSING_CODE); // exit EXECUTE_MISSING_CODE + + block->end(); +} + + +/*------------------------------------------------- + static_generate_out_of_cycles - generate an + out of cycles exception handler +-------------------------------------------------*/ + +void sh2_device::static_generate_out_of_cycles() +{ + drcuml_state *drcuml = m_drcuml.get(); + drcuml_block *block; + + /* begin generating */ + block = drcuml->begin_block(10); + + /* generate a hash jump via the current mode and PC */ + alloc_handle(drcuml, &m_out_of_cycles, "out_of_cycles"); + UML_HANDLE(block, *m_out_of_cycles); // handle out_of_cycles + UML_GETEXP(block, I0); // getexp i0 + UML_MOV(block, mem(&m_sh2_state->pc), I0); // mov ,i0 + save_fast_iregs(block); + UML_EXIT(block, EXECUTE_OUT_OF_CYCLES); // exit EXECUTE_OUT_OF_CYCLES + + block->end(); +} + +/*------------------------------------------------------------------ + static_generate_memory_accessor +------------------------------------------------------------------*/ + +void sh2_device::static_generate_memory_accessor(int size, int iswrite, const char *name, code_handle **handleptr) +{ + /* on entry, address is in I0; data for writes is in I1 */ + /* on exit, read result is in I0 */ + /* routine trashes I0 */ + drcuml_state *drcuml = m_drcuml.get(); + drcuml_block *block; + int label = 1; + + /* begin generating */ + block = drcuml->begin_block(1024); + + /* add a global entry for this */ + alloc_handle(drcuml, handleptr, name); + UML_HANDLE(block, **handleptr); // handle *handleptr + + // with internal handlers this becomes easier. + // if addr < 0x40000000 AND it with AM and do the read/write, else just do the read/write + UML_TEST(block, I0, 0x80000000); // test r0, #0x80000000 + UML_JMPc(block, COND_NZ, label); // if high bit is set, don't mask + + UML_CMP(block, I0, 0x40000000); // cmp #0x40000000, r0 + UML_JMPc(block, COND_AE, label); // bae label + + UML_AND(block, I0, I0, AM); // and r0, r0, #AM (0xc7ffffff) + + UML_LABEL(block, label++); // label: + + for (auto & elem : m_fastram) + { + if (elem.base != nullptr && (!iswrite || !elem.readonly)) + { + void *fastbase = (uint8_t *)elem.base - elem.start; + uint32_t skip = label++; + if (elem.end != 0xffffffff) + { + UML_CMP(block, I0, elem.end); // cmp i0,end + UML_JMPc(block, COND_A, skip); // ja skip + } + if (elem.start != 0x00000000) + { + UML_CMP(block, I0, elem.start);// cmp i0,fastram_start + UML_JMPc(block, COND_B, skip); // jb skip + } + + if (!iswrite) + { + if (size == 1) + { + UML_XOR(block, I0, I0, BYTE4_XOR_BE(0)); + UML_LOAD(block, I0, fastbase, I0, SIZE_BYTE, SCALE_x1); // load i0,fastbase,i0,byte + } + else if (size == 2) + { + UML_XOR(block, I0, I0, WORD_XOR_BE(0)); + UML_LOAD(block, I0, fastbase, I0, SIZE_WORD, SCALE_x1); // load i0,fastbase,i0,word_x1 + } + else if (size == 4) + { + UML_LOAD(block, I0, fastbase, I0, SIZE_DWORD, SCALE_x1); // load i0,fastbase,i0,dword_x1 + } + UML_RET(block); // ret + } + else + { + if (size == 1) + { + UML_XOR(block, I0, I0, BYTE4_XOR_BE(0)); + UML_STORE(block, fastbase, I0, I1, SIZE_BYTE, SCALE_x1);// store fastbase,i0,i1,byte + } + else if (size == 2) + { + UML_XOR(block, I0, I0, WORD_XOR_BE(0)); + UML_STORE(block, fastbase, I0, I1, SIZE_WORD, SCALE_x1);// store fastbase,i0,i1,word_x1 + } + else if (size == 4) + { + UML_STORE(block, fastbase, I0, I1, SIZE_DWORD, SCALE_x1); // store fastbase,i0,i1,dword_x1 + } + UML_RET(block); // ret + } + + UML_LABEL(block, skip); // skip: + } + } + + if (iswrite) + { + switch (size) + { + case 1: + UML_WRITE(block, I0, I1, SIZE_BYTE, SPACE_PROGRAM); // write r0, r1, program_byte + break; + + case 2: + UML_WRITE(block, I0, I1, SIZE_WORD, SPACE_PROGRAM); // write r0, r1, program_word + break; + + case 4: + UML_WRITE(block, I0, I1, SIZE_DWORD, SPACE_PROGRAM); // write r0, r1, program_dword + break; + } + } + else + { + switch (size) + { + case 1: + UML_READ(block, I0, I0, SIZE_BYTE, SPACE_PROGRAM); // read r0, program_byte + break; + + case 2: + UML_READ(block, I0, I0, SIZE_WORD, SPACE_PROGRAM); // read r0, program_word + break; + + case 4: + UML_READ(block, I0, I0, SIZE_DWORD, SPACE_PROGRAM); // read r0, program_dword + break; + } + } + + UML_RET(block); // ret + + block->end(); +} + +/*------------------------------------------------- + log_desc_flags_to_string - generate a string + representing the instruction description + flags +-------------------------------------------------*/ + +const char *sh2_device::log_desc_flags_to_string(uint32_t flags) +{ + static char tempbuf[30]; + char *dest = tempbuf; + + /* branches */ + if (flags & OPFLAG_IS_UNCONDITIONAL_BRANCH) + *dest++ = 'U'; + else if (flags & OPFLAG_IS_CONDITIONAL_BRANCH) + *dest++ = 'C'; + else + *dest++ = '.'; + + /* intrablock branches */ + *dest++ = (flags & OPFLAG_INTRABLOCK_BRANCH) ? 'i' : '.'; + + /* branch targets */ + *dest++ = (flags & OPFLAG_IS_BRANCH_TARGET) ? 'B' : '.'; + + /* delay slots */ + *dest++ = (flags & OPFLAG_IN_DELAY_SLOT) ? 'D' : '.'; + + /* exceptions */ + if (flags & OPFLAG_WILL_CAUSE_EXCEPTION) + *dest++ = 'E'; + else if (flags & OPFLAG_CAN_CAUSE_EXCEPTION) + *dest++ = 'e'; + else + *dest++ = '.'; + + /* read/write */ + if (flags & OPFLAG_READS_MEMORY) + *dest++ = 'R'; + else if (flags & OPFLAG_WRITES_MEMORY) + *dest++ = 'W'; + else + *dest++ = '.'; + + /* TLB validation */ + *dest++ = (flags & OPFLAG_VALIDATE_TLB) ? 'V' : '.'; + + /* TLB modification */ + *dest++ = (flags & OPFLAG_MODIFIES_TRANSLATION) ? 'T' : '.'; + + /* redispatch */ + *dest++ = (flags & OPFLAG_REDISPATCH) ? 'R' : '.'; + return tempbuf; +} + + +/*------------------------------------------------- + log_register_list - log a list of GPR registers +-------------------------------------------------*/ + +void sh2_device::log_register_list(drcuml_state *drcuml, const char *string, const uint32_t *reglist, const uint32_t *regnostarlist) +{ + int count = 0; + int regnum; + + /* skip if nothing */ + if (reglist[0] == 0 && reglist[1] == 0 && reglist[2] == 0) + return; + + drcuml->log_printf("[%s:", string); + + for (regnum = 0; regnum < 16; regnum++) + { + if (reglist[0] & REGFLAG_R(regnum)) + { + drcuml->log_printf("%sr%d", (count++ == 0) ? "" : ",", regnum); + if (regnostarlist != nullptr && !(regnostarlist[0] & REGFLAG_R(regnum))) + drcuml->log_printf("*"); + } + } + + if (reglist[1] & REGFLAG_PR) + { + drcuml->log_printf("%spr", (count++ == 0) ? "" : ","); + if (regnostarlist != nullptr && !(regnostarlist[1] & REGFLAG_PR)) + drcuml->log_printf("*"); + } + + if (reglist[1] & REGFLAG_SR) + { + drcuml->log_printf("%ssr", (count++ == 0) ? "" : ","); + if (regnostarlist != nullptr && !(regnostarlist[1] & REGFLAG_SR)) + drcuml->log_printf("*"); + } + + if (reglist[1] & REGFLAG_MACL) + { + drcuml->log_printf("%smacl", (count++ == 0) ? "" : ","); + if (regnostarlist != nullptr && !(regnostarlist[1] & REGFLAG_MACL)) + drcuml->log_printf("*"); + } + + if (reglist[1] & REGFLAG_MACH) + { + drcuml->log_printf("%smach", (count++ == 0) ? "" : ","); + if (regnostarlist != nullptr && !(regnostarlist[1] & REGFLAG_MACH)) + drcuml->log_printf("*"); + } + + if (reglist[1] & REGFLAG_GBR) + { + drcuml->log_printf("%sgbr", (count++ == 0) ? "" : ","); + if (regnostarlist != nullptr && !(regnostarlist[1] & REGFLAG_GBR)) + drcuml->log_printf("*"); + } + + if (reglist[1] & REGFLAG_VBR) + { + drcuml->log_printf("%svbr", (count++ == 0) ? "" : ","); + if (regnostarlist != nullptr && !(regnostarlist[1] & REGFLAG_VBR)) + drcuml->log_printf("*"); + } + + drcuml->log_printf("] "); +} + +/*------------------------------------------------- + log_opcode_desc - log a list of descriptions +-------------------------------------------------*/ + +void sh2_device::log_opcode_desc(drcuml_state *drcuml, const opcode_desc *desclist, int indent) +{ + /* open the file, creating it if necessary */ + if (indent == 0) + drcuml->log_printf("\nDescriptor list @ %08X\n", desclist->pc); + + /* output each descriptor */ + for ( ; desclist != nullptr; desclist = desclist->next()) + { + std::ostringstream stream; + + /* disassemle the current instruction and output it to the log */ + if (drcuml->logging() || drcuml->logging_native()) + { + if (desclist->flags & OPFLAG_VIRTUAL_NOOP) + stream << ""; + else + DasmSH2(stream, desclist->pc, desclist->opptr.w[0]); + } + else + stream << "???"; + drcuml->log_printf("%08X [%08X] t:%08X f:%s: %-30s", desclist->pc, desclist->physpc, desclist->targetpc, log_desc_flags_to_string(desclist->flags), stream.str().c_str()); + + /* output register states */ + log_register_list(drcuml, "use", desclist->regin, nullptr); + log_register_list(drcuml, "mod", desclist->regout, desclist->regreq); + drcuml->log_printf("\n"); + + /* if we have a delay slot, output it recursively */ + if (desclist->delay.first() != nullptr) + log_opcode_desc(drcuml, desclist->delay.first(), indent + 1); + + /* at the end of a sequence add a dividing line */ + if (desclist->flags & OPFLAG_END_SEQUENCE) + drcuml->log_printf("-----\n"); + } +} + +/*------------------------------------------------- + log_add_disasm_comment - add a comment + including disassembly of an SH2 instruction +-------------------------------------------------*/ + +void sh2_device::log_add_disasm_comment(drcuml_block *block, uint32_t pc, uint32_t op) +{ + if (m_drcuml->logging()) + { + std::ostringstream stream; + DasmSH2(stream, pc, op); + block->append_comment("%08X: %s", pc, stream.str().c_str()); + } +} + +/*------------------------------------------------- + generate_update_cycles - generate code to + subtract cycles from the icount and generate + an exception if out +-------------------------------------------------*/ +void sh2_device::generate_update_cycles(drcuml_block *block, compiler_state *compiler, uml::parameter param, bool allow_exception) +{ + /* check full interrupts if pending */ + if (compiler->checkints) + { + code_label skip = compiler->labelnum++; + + compiler->checkints = false; + compiler->labelnum += 4; + + /* check for interrupts */ + UML_MOV(block, mem(&m_sh2_state->irqline), 0xffffffff); // mov irqline, #-1 + UML_CMP(block, mem(&m_sh2_state->pending_nmi), 0); // cmp pending_nmi, #0 + UML_JMPc(block, COND_Z, skip+2); // jz skip+2 + + UML_MOV(block, mem(&m_sh2_state->pending_nmi), 0); // zap pending_nmi + UML_JMP(block, skip+1); // and then go take it (evec is already set) + + UML_LABEL(block, skip+2); // skip+2: + UML_MOV(block, mem(&m_sh2_state->evec), 0xffffffff); // mov evec, -1 + UML_MOV(block, I0, 0xffffffff); // mov r0, -1 (r0 = irq) + UML_AND(block, I1, I0, 0xffff); // and r1, r0, 0xffff + + UML_LZCNT(block, I1, mem(&m_sh2_state->pending_irq)); // lzcnt r1, pending_irq + UML_CMP(block, I1, 32); // cmp r1, #32 + UML_JMPc(block, COND_Z, skip+4); // jz skip+4 + + UML_SUB(block, mem(&m_sh2_state->irqline), 31, I1); // sub irqline, #31, r1 + + UML_LABEL(block, skip+4); // skip+4: + UML_CMP(block, mem(&m_sh2_state->internal_irq_level), 0xffffffff); // cmp internal_irq_level, #-1 + UML_JMPc(block, COND_Z, skip+3); // jz skip+3 + UML_CMP(block, mem(&m_sh2_state->internal_irq_level), mem(&m_sh2_state->irqline)); // cmp internal_irq_level, irqline + UML_JMPc(block, COND_LE, skip+3); // jle skip+3 + + UML_MOV(block, mem(&m_sh2_state->irqline), mem(&m_sh2_state->internal_irq_level)); // mov r0, internal_irq_level + + UML_LABEL(block, skip+3); // skip+3: + UML_CMP(block, mem(&m_sh2_state->irqline), 0xffffffff); // cmp irqline, #-1 + UML_JMPc(block, COND_Z, skip+1); // jz skip+1 + UML_CALLC(block, cfunc_fastirq, this); // callc fastirq + + UML_LABEL(block, skip+1); // skip+1: + UML_CMP(block, mem(&m_sh2_state->evec), 0xffffffff); // cmp evec, 0xffffffff + UML_JMPc(block, COND_Z, skip); // jz skip + + UML_SUB(block, R32(15), R32(15), 4); // sub R15, R15, #4 + UML_MOV(block, I0, R32(15)); // mov r0, R15 + UML_MOV(block, I1, mem(&m_sh2_state->irqsr)); // mov r1, irqsr + UML_CALLH(block, *m_write32); // call write32 + + UML_SUB(block, R32(15), R32(15), 4); // sub R15, R15, #4 + UML_MOV(block, I0, R32(15)); // mov r0, R15 + UML_MOV(block, I1, param); // mov r1, nextpc + UML_CALLH(block, *m_write32); // call write32 + + UML_HASHJMP(block, 0, mem(&m_sh2_state->evec), *m_nocode); // hashjmp m_sh2_state->evec + + UML_LABEL(block, skip); // skip: + } + + /* account for cycles */ + if (compiler->cycles > 0) + { + UML_SUB(block, mem(&m_sh2_state->icount), mem(&m_sh2_state->icount), MAPVAR_CYCLES); // sub icount,icount,cycles + UML_MAPVAR(block, MAPVAR_CYCLES, 0); // mapvar cycles,0 + if (allow_exception) + UML_EXHc(block, COND_S, *m_out_of_cycles, param); + // exh out_of_cycles,nextpc + } + compiler->cycles = 0; +} + +/*------------------------------------------------- + generate_checksum_block - generate code to + validate a sequence of opcodes +-------------------------------------------------*/ + +void sh2_device::generate_checksum_block(drcuml_block *block, compiler_state *compiler, const opcode_desc *seqhead, const opcode_desc *seqlast) +{ + const opcode_desc *curdesc; + if (m_drcuml->logging()) + block->append_comment("[Validation for %08X]", seqhead->pc); // comment + + /* loose verify or single instruction: just compare and fail */ + if (!(m_drcoptions & SH2DRC_STRICT_VERIFY) || seqhead->next() == nullptr) + { + if (!(seqhead->flags & OPFLAG_VIRTUAL_NOOP)) + { + void *base = m_direct->read_ptr(seqhead->physpc, SH2_CODE_XOR(0)); + UML_LOAD(block, I0, base, 0, SIZE_WORD, SCALE_x2); // load i0,base,word + UML_CMP(block, I0, seqhead->opptr.w[0]); // cmp i0,*opptr + UML_EXHc(block, COND_NE, *m_nocode, epc(seqhead)); // exne nocode,seqhead->pc + } + } + + /* full verification; sum up everything */ + else + { +#if 0 + for (curdesc = seqhead->next(); curdesc != seqlast->next(); curdesc = curdesc->next()) + if (!(curdesc->flags & OPFLAG_VIRTUAL_NOOP)) + { + base = m_direct->read_ptr(curdesc->physpc, SH2_CODE_XOR(0)); + UML_LOAD(block, I0, curdesc->opptr.w, 0, SIZE_WORD, SCALE_x2); // load i0,*opptr,0,word + UML_CMP(block, I0, curdesc->opptr.w[0]); // cmp i0,*opptr + UML_EXHc(block, COND_NE, *m_nocode, epc(seqhead)); // exne nocode,seqhead->pc + } +#else + uint32_t sum = 0; + void *base = m_direct->read_ptr(seqhead->physpc, SH2_CODE_XOR(0)); + UML_LOAD(block, I0, base, 0, SIZE_WORD, SCALE_x4); // load i0,base,word + sum += seqhead->opptr.w[0]; + for (curdesc = seqhead->next(); curdesc != seqlast->next(); curdesc = curdesc->next()) + if (!(curdesc->flags & OPFLAG_VIRTUAL_NOOP)) + { + base = m_direct->read_ptr(curdesc->physpc, SH2_CODE_XOR(0)); + UML_LOAD(block, I1, base, 0, SIZE_WORD, SCALE_x2); // load i1,*opptr,word + UML_ADD(block, I0, I0, I1); // add i0,i0,i1 + sum += curdesc->opptr.w[0]; + } + UML_CMP(block, I0, sum); // cmp i0,sum + UML_EXHc(block, COND_NE, *m_nocode, epc(seqhead)); // exne nocode,seqhead->pc +#endif + } +} + + +/*------------------------------------------------- + generate_sequence_instruction - generate code + for a single instruction in a sequence +-------------------------------------------------*/ + +void sh2_device::generate_sequence_instruction(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint32_t ovrpc) +{ + offs_t expc; + + /* add an entry for the log */ + if (m_drcuml->logging() && !(desc->flags & OPFLAG_VIRTUAL_NOOP)) + log_add_disasm_comment(block, desc->pc, desc->opptr.w[0]); + + /* set the PC map variable */ + expc = (desc->flags & OPFLAG_IN_DELAY_SLOT) ? desc->pc - 1 : desc->pc; + UML_MAPVAR(block, MAPVAR_PC, expc); // mapvar PC,expc + + /* accumulate total cycles */ + compiler->cycles += desc->cycles; + + /* update the icount map variable */ + UML_MAPVAR(block, MAPVAR_CYCLES, compiler->cycles); // mapvar CYCLES,compiler->cycles + + /* if we want a probe, add it here */ + if (desc->pc == PROBE_ADDRESS) + { + UML_MOV(block, mem(&m_sh2_state->pc), desc->pc); // mov [pc],desc->pc + UML_CALLC(block, cfunc_printf_probe, this); // callc cfunc_printf_probe,sh2 + } + + /* if we are debugging, call the debugger */ + if ((machine().debug_flags & DEBUG_FLAG_ENABLED) != 0) + { + UML_MOV(block, mem(&m_sh2_state->pc), desc->pc); // mov [pc],desc->pc + save_fast_iregs(block); + UML_DEBUG(block, desc->pc); // debug desc->pc + } + else // not debug, see what other reasons there are for flushing the PC + { + if (m_drcoptions & SH2DRC_FLUSH_PC) // always flush? + { + UML_MOV(block, mem(&m_sh2_state->pc), desc->pc); // mov m_sh2_state->pc, desc->pc + } + else // check for driver-selected flushes + { + int pcflush; + + for (pcflush = 0; pcflush < m_pcfsel; pcflush++) + { + if (desc->pc == m_pcflushes[pcflush]) + { + UML_MOV(block, mem(&m_sh2_state->pc), desc->pc); // mov m_sh2_state->pc, desc->pc + } + } + } + } + + + /* if we hit an unmapped address, fatal error */ + if (desc->flags & OPFLAG_COMPILER_UNMAPPED) + { + UML_MOV(block, mem(&m_sh2_state->pc), desc->pc); // mov [pc],desc->pc + save_fast_iregs(block); + UML_EXIT(block, EXECUTE_UNMAPPED_CODE); // exit EXECUTE_UNMAPPED_CODE + } + + /* if this is an invalid opcode, die */ + if (desc->flags & OPFLAG_INVALID_OPCODE) + { + fatalerror("SH2DRC: invalid opcode!\n"); + } + + /* otherwise, unless this is a virtual no-op, it's a regular instruction */ + else if (!(desc->flags & OPFLAG_VIRTUAL_NOOP)) + { + /* compile the instruction */ + if (!generate_opcode(block, compiler, desc, ovrpc)) + { + // handle an illegal op + UML_MOV(block, mem(&m_sh2_state->pc), desc->pc); // mov [pc],desc->pc + UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr.w[0]); // mov [arg0],opcode + UML_CALLC(block, cfunc_unimplemented, this); // callc cfunc_unimplemented + } + } +} + +/*------------------------------------------------------------------ + generate_delay_slot +------------------------------------------------------------------*/ + +void sh2_device::generate_delay_slot(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint32_t ovrpc) +{ + compiler_state compiler_temp = *compiler; + + /* compile the delay slot using temporary compiler state */ + assert(desc->delay.first() != nullptr); + generate_sequence_instruction(block, &compiler_temp, desc->delay.first(), ovrpc); // + + /* update the label */ + compiler->labelnum = compiler_temp.labelnum; +} + +/*------------------------------------------------- + generate_opcode - generate code for a specific + opcode +-------------------------------------------------*/ + +bool sh2_device::generate_opcode(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint32_t ovrpc) +{ + uint32_t scratch, scratch2; + int32_t disp; + uint16_t opcode = desc->opptr.w[0]; + uint8_t opswitch = opcode >> 12; + int in_delay_slot = ((desc->flags & OPFLAG_IN_DELAY_SLOT) != 0); + + switch (opswitch) + { + case 0: + return generate_group_0(block, compiler, desc, opcode, in_delay_slot, ovrpc); + + case 1: // MOVLS4 + scratch = (opcode & 0x0f) * 4; + UML_ADD(block, I0, R32(Rn), scratch); // add r0, Rn, scratch + UML_MOV(block, I1, R32(Rm)); // mov r1, Rm + SETEA(0); // set ea for debug + UML_CALLH(block, *m_write32); + + if (!in_delay_slot) + generate_update_cycles(block, compiler, desc->pc + 2, true); + return true; + + case 2: + return generate_group_2(block, compiler, desc, opcode, in_delay_slot, ovrpc); + case 3: + return generate_group_3(block, compiler, desc, opcode, ovrpc); + case 4: + return generate_group_4(block, compiler, desc, opcode, in_delay_slot, ovrpc); + + case 5: // MOVLL4 + scratch = (opcode & 0x0f) * 4; + UML_ADD(block, I0, R32(Rm), scratch); // add r0, Rm, scratch + SETEA(0); // set ea for debug + UML_CALLH(block, *m_read32); // call read32 + UML_MOV(block, R32(Rn), I0); // mov Rn, r0 + + if (!in_delay_slot) + generate_update_cycles(block, compiler, desc->pc + 2, true); + return true; + + case 6: + return generate_group_6(block, compiler, desc, opcode, in_delay_slot, ovrpc); + + case 7: // ADDI + scratch = opcode & 0xff; + scratch2 = (uint32_t)(int32_t)(int16_t)(int8_t)scratch; + UML_ADD(block, R32(Rn), R32(Rn), scratch2); // add Rn, Rn, scratch2 + return true; + + case 8: + return generate_group_8(block, compiler, desc, opcode, in_delay_slot, ovrpc); + + case 9: // MOVWI + if (ovrpc == 0xffffffff) + { + scratch = (desc->pc + 2) + ((opcode & 0xff) * 2) + 2; + } + else + { + scratch = (ovrpc + 2) + ((opcode & 0xff) * 2) + 2; + } + + if (m_drcoptions & SH2DRC_STRICT_PCREL) + { + UML_MOV(block, I0, scratch); // mov r0, scratch + SETEA(0); // set ea for debug + UML_CALLH(block, *m_read16); // read16(r0, r1) + UML_SEXT(block, R32(Rn), I0, SIZE_WORD); // sext Rn, r0, WORD + } + else + { + scratch2 = (uint32_t)(int32_t)(int16_t) RW(scratch); + UML_MOV(block, R32(Rn), scratch2); // mov Rn, scratch2 + } + + if (!in_delay_slot) + generate_update_cycles(block, compiler, desc->pc + 2, true); + return true; + + case 10: // BRA + disp = ((int32_t)opcode << 20) >> 20; + m_sh2_state->ea = (desc->pc + 2) + disp * 2 + 2; // m_sh2_state->ea = pc+4 + disp*2 + 2 + + generate_delay_slot(block, compiler, desc, m_sh2_state->ea-2); + + generate_update_cycles(block, compiler, m_sh2_state->ea, true); // + UML_HASHJMP(block, 0, m_sh2_state->ea, *m_nocode); // hashjmp m_sh2_state->ea + return true; + + case 11: // BSR + // panicstr @ 403da22 relies on the delay slot clobbering the PR set by a BSR, so + // do this before running the delay slot + UML_ADD(block, mem(&m_sh2_state->pr), desc->pc, 4); // add m_pr, desc->pc, #4 (skip the current insn & delay slot) + + disp = ((int32_t)opcode << 20) >> 20; + m_sh2_state->ea = (desc->pc + 2) + disp * 2 + 2; // m_sh2_state->ea = pc+4 + disp*2 + 2 + + generate_delay_slot(block, compiler, desc, m_sh2_state->ea-2); + + generate_update_cycles(block, compiler, m_sh2_state->ea, true); // + UML_HASHJMP(block, 0, m_sh2_state->ea, *m_nocode); // hashjmp m_sh2_state->ea + return true; + + case 12: + return generate_group_12(block, compiler, desc, opcode, in_delay_slot, ovrpc); + + case 13: // MOVLI + if (ovrpc == 0xffffffff) + { + scratch = ((desc->pc + 4) & ~3) + ((opcode & 0xff) * 4); + } + else + { + scratch = ((ovrpc + 4) & ~3) + ((opcode & 0xff) * 4); + } + + if (m_drcoptions & SH2DRC_STRICT_PCREL) + { + UML_MOV(block, I0, scratch); // mov r0, scratch + UML_CALLH(block, *m_read32); // read32(r0, r1) + UML_MOV(block, R32(Rn), I0); // mov Rn, r0 + } + else + { + scratch2 = RL(scratch); + UML_MOV(block, R32(Rn), scratch2); // mov Rn, scratch2 + } + + if (!in_delay_slot) + generate_update_cycles(block, compiler, desc->pc + 2, true); + return true; + + case 14: // MOVI + scratch = opcode & 0xff; + scratch2 = (uint32_t)(int32_t)(int16_t)(int8_t)scratch; + UML_MOV(block, R32(Rn), scratch2); + return true; + + case 15: + return false; + } + + return false; +} + +bool sh2_device::generate_group_0(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc) +{ + switch (opcode & 0x3F) + { + case 0x00: // these are all illegal + case 0x01: + case 0x10: + case 0x11: + case 0x13: + case 0x20: + case 0x21: + case 0x30: + case 0x31: + case 0x32: + case 0x33: + case 0x38: + case 0x39: + case 0x3a: + case 0x3b: + return false; + + case 0x09: // NOP(); + return true; + + case 0x02: // STCSR(Rn); + UML_MOV(block, R32(Rn), mem(&m_sh2_state->sr)); + return true; + + case 0x03: // BSRF(Rn); + if (m_cpu_type > CPU_TYPE_SH1) + { + UML_ADD(block, mem(&m_sh2_state->target), R32(Rn), 4); // add target, Rm, #4 + UML_ADD(block, mem(&m_sh2_state->target), mem(&m_sh2_state->target), desc->pc); // add target, target, pc + + // 32x Cosmic Carnage @ 6002cb0 relies on the delay slot + // clobbering the calculated PR, so do it first + UML_ADD(block, mem(&m_sh2_state->pr), desc->pc, 4); // add m_pr, desc->pc, #4 (skip the current insn & delay slot) + + generate_delay_slot(block, compiler, desc, m_sh2_state->target); + + generate_update_cycles(block, compiler, mem(&m_sh2_state->target), true); // + UML_HASHJMP(block, 0, mem(&m_sh2_state->target), *m_nocode); // jmp target + return true; + } + break; + + case 0x04: // MOVBS0(Rm, Rn); + case 0x14: // MOVBS0(Rm, Rn); + case 0x24: // MOVBS0(Rm, Rn); + case 0x34: // MOVBS0(Rm, Rn); + UML_ADD(block, I0, R32(0), R32(Rn)); // add r0, R0, Rn + UML_AND(block, I1, R32(Rm), 0x000000ff); // and r1, Rm, 0xff + UML_CALLH(block, *m_write8); // call write8 + + if (!in_delay_slot) + generate_update_cycles(block, compiler, desc->pc + 2, true); + return true; + + case 0x05: // MOVWS0(Rm, Rn); + case 0x15: // MOVWS0(Rm, Rn); + case 0x25: // MOVWS0(Rm, Rn); + case 0x35: // MOVWS0(Rm, Rn); + UML_ADD(block, I0, R32(0), R32(Rn)); // add r0, R0, Rn + UML_AND(block, I1, R32(Rm), 0x0000ffff); // and r1, Rm, 0xffff + UML_CALLH(block, *m_write16); // call write16 + + if (!in_delay_slot) + generate_update_cycles(block, compiler, desc->pc + 2, true); + return true; + + case 0x06: // MOVLS0(Rm, Rn); + case 0x16: // MOVLS0(Rm, Rn); + case 0x26: // MOVLS0(Rm, Rn); + case 0x36: // MOVLS0(Rm, Rn); + UML_ADD(block, I0, R32(0), R32(Rn)); // add r0, R0, Rn + UML_MOV(block, I1, R32(Rm)); // mov r1, Rm + UML_CALLH(block, *m_write32); // call write32 + + if (!in_delay_slot) + generate_update_cycles(block, compiler, desc->pc + 2, true); + return true; + + case 0x07: // MULL(Rm, Rn); + case 0x17: // MULL(Rm, Rn); + case 0x27: // MULL(Rm, Rn); + case 0x37: // MULL(Rm, Rn); + if (m_cpu_type > CPU_TYPE_SH1) + { + UML_MULU(block, mem(&m_sh2_state->macl), mem(&m_sh2_state->ea), R32(Rn), R32(Rm)); // mulu macl, ea, Rn, Rm + return true; + } + break; + + case 0x08: // CLRT(); + UML_AND(block, mem(&m_sh2_state->sr), mem(&m_sh2_state->sr), ~T); // and r0, sr, ~T (clear the T bit) + return true; + + case 0x0a: // STSMACH(Rn); + UML_MOV(block, R32(Rn), mem(&m_sh2_state->mach)); // mov Rn, mach + return true; + + case 0x0b: // RTS(); + UML_MOV(block, mem(&m_sh2_state->target), mem(&m_sh2_state->pr)); // mov target, pr (in case of d-slot shenanigans) + + generate_delay_slot(block, compiler, desc, m_sh2_state->target); + + generate_update_cycles(block, compiler, mem(&m_sh2_state->target), true); // + UML_HASHJMP(block, 0, mem(&m_sh2_state->target), *m_nocode); + return true; + + case 0x0c: // MOVBL0(Rm, Rn); + case 0x1c: // MOVBL0(Rm, Rn); + case 0x2c: // MOVBL0(Rm, Rn); + case 0x3c: // MOVBL0(Rm, Rn); + UML_ADD(block, I0, R32(0), R32(Rm)); // add r0, R0, Rm + UML_CALLH(block, *m_read8); // call read8 + UML_SEXT(block, R32(Rn), I0, SIZE_BYTE); // sext Rn, r0, BYTE + + if (!in_delay_slot) + generate_update_cycles(block, compiler, desc->pc + 2, true); + return true; + + case 0x0d: // MOVWL0(Rm, Rn); + case 0x1d: // MOVWL0(Rm, Rn); + case 0x2d: // MOVWL0(Rm, Rn); + case 0x3d: // MOVWL0(Rm, Rn); + UML_ADD(block, I0, R32(0), R32(Rm)); // add r0, R0, Rm + UML_CALLH(block, *m_read16); // call read16 + UML_SEXT(block, R32(Rn), I0, SIZE_WORD); // sext Rn, r0, WORD + + if (!in_delay_slot) + generate_update_cycles(block, compiler, desc->pc + 2, true); + return true; + + case 0x0e: // MOVLL0(Rm, Rn); + case 0x1e: // MOVLL0(Rm, Rn); + case 0x2e: // MOVLL0(Rm, Rn); + case 0x3e: // MOVLL0(Rm, Rn); + UML_ADD(block, I0, R32(0), R32(Rm)); // add r0, R0, Rm + UML_CALLH(block, *m_read32); // call read32 + UML_MOV(block, R32(Rn), I0); // mov Rn, r0 + + if (!in_delay_slot) + generate_update_cycles(block, compiler, desc->pc + 2, true); + return true; + + case 0x0f: // MAC_L(Rm, Rn); + case 0x1f: // MAC_L(Rm, Rn); + case 0x2f: // MAC_L(Rm, Rn); + case 0x3f: // MAC_L(Rm, Rn); + if (m_cpu_type > CPU_TYPE_SH1) + { + save_fast_iregs(block); + UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr.w[0]); + UML_CALLC(block, cfunc_MAC_L, this); + load_fast_iregs(block); + return true; + } + break; + + case 0x12: // STCGBR(Rn); + UML_MOV(block, R32(Rn), mem(&m_sh2_state->gbr)); // mov Rn, gbr + return true; + + case 0x18: // SETT(); + UML_OR(block, mem(&m_sh2_state->sr), mem(&m_sh2_state->sr), T); // or sr, sr, T + return true; + + case 0x19: // DIV0U(); + UML_AND(block, mem(&m_sh2_state->sr), mem(&m_sh2_state->sr), ~(M|Q|T)); // and sr, sr, ~(M|Q|T) + return true; + + case 0x1a: // STSMACL(Rn); + UML_MOV(block, R32(Rn), mem(&m_sh2_state->macl)); // mov Rn, macl + return true; + + case 0x1b: // SLEEP(); + UML_MOV(block, I0, mem(&m_sh2_state->sleep_mode)); // mov i0, sleep_mode + UML_CMP(block, I0, 0x2); // cmp i0, #2 + UML_JMPc(block, COND_E, compiler->labelnum); // beq labelnum + // sleep mode != 2 + UML_MOV(block, mem(&m_sh2_state->sleep_mode), 0x1); // mov sleep_mode, #1 + generate_update_cycles(block, compiler, desc->pc, true); // repeat this insn + UML_JMP(block, compiler->labelnum+1); // jmp labelnum+1 + + UML_LABEL(block, compiler->labelnum++); // labelnum: + // sleep_mode == 2 + UML_MOV(block, mem(&m_sh2_state->sleep_mode), 0x0); // sleep_mode = 0 + generate_update_cycles(block, compiler, desc->pc+2, true); // go to next insn + + UML_LABEL(block, compiler->labelnum++); // labelnum+1: + return true; + + case 0x22: // STCVBR(Rn); + UML_MOV(block, R32(Rn), mem(&m_sh2_state->vbr)); // mov Rn, vbr + return true; + + case 0x23: // BRAF(Rn); + if (m_cpu_type > CPU_TYPE_SH1) + { + UML_ADD(block, mem(&m_sh2_state->target), R32(Rn), desc->pc+4); // add target, Rn, pc+4 + + generate_delay_slot(block, compiler, desc, m_sh2_state->target); + + generate_update_cycles(block, compiler, mem(&m_sh2_state->target), true); // + UML_HASHJMP(block, 0, mem(&m_sh2_state->target), *m_nocode); // jmp target + return true; + } + break; + + case 0x28: // CLRMAC(); + UML_MOV(block, mem(&m_sh2_state->macl), 0); // mov macl, #0 + UML_MOV(block, mem(&m_sh2_state->mach), 0); // mov mach, #0 + return true; + + case 0x29: // MOVT(Rn); + UML_AND(block, R32(Rn), mem(&m_sh2_state->sr), T); // and Rn, sr, T + return true; + + case 0x2a: // STSPR(Rn); + UML_MOV(block, R32(Rn), mem(&m_sh2_state->pr)); // mov Rn, pr + return true; + + case 0x2b: // RTE(); + generate_delay_slot(block, compiler, desc, 0xffffffff); + + UML_MOV(block, I0, R32(15)); // mov r0, R15 + UML_CALLH(block, *m_read32); // call read32 + UML_MOV(block, mem(&m_sh2_state->pc), I0); // mov pc, r0 + UML_ADD(block, R32(15), R32(15), 4); // add R15, R15, #4 + + UML_MOV(block, I0, R32(15)); // mov r0, R15 + UML_CALLH(block, *m_read32); // call read32 + UML_MOV(block, mem(&m_sh2_state->sr), I0); // mov sr, r0 + UML_ADD(block, R32(15), R32(15), 4); // add R15, R15, #4 + + compiler->checkints = true; + UML_MOV(block, mem(&m_sh2_state->ea), mem(&m_sh2_state->pc)); // mov ea, pc + generate_update_cycles(block, compiler, mem(&m_sh2_state->ea), true); // + UML_HASHJMP(block, 0, mem(&m_sh2_state->pc), *m_nocode); // and jump to the "resume PC" + + return true; + } + + return false; +} + +bool sh2_device::generate_group_2(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc) +{ + switch (opcode & 15) + { + case 0: // MOVBS(Rm, Rn); + UML_MOV(block, I0, R32(Rn)); // mov r0, Rn + UML_AND(block, I1, R32(Rm), 0xff); // and r1, Rm, 0xff + UML_CALLH(block, *m_write8); + + if (!in_delay_slot) + generate_update_cycles(block, compiler, desc->pc + 2, true); + return true; + + case 1: // MOVWS(Rm, Rn); + UML_MOV(block, I0, R32(Rn)); // mov r0, Rn + UML_AND(block, I1, R32(Rm), 0xffff); // and r1, Rm, 0xffff + UML_CALLH(block, *m_write16); + + if (!in_delay_slot) + generate_update_cycles(block, compiler, desc->pc + 2, true); + return true; + + case 2: // MOVLS(Rm, Rn); + UML_MOV(block, I0, R32(Rn)); // mov r0, Rn + UML_MOV(block, I1, R32(Rm)); // mov r1, Rm + UML_CALLH(block, *m_write32); + + if (!in_delay_slot) + generate_update_cycles(block, compiler, desc->pc + 2, true); + return true; + + case 3: + return false; + + case 4: // MOVBM(Rm, Rn); + UML_MOV(block, I1, R32(Rm)); // mov r1, Rm + UML_SUB(block, R32(Rn), R32(Rn), 1); // sub Rn, Rn, 1 + UML_MOV(block, I0, R32(Rn)); // mov r0, Rn + UML_CALLH(block, *m_write8); // call write8 + + if (!in_delay_slot) + generate_update_cycles(block, compiler, desc->pc + 2, true); + return true; + + case 5: // MOVWM(Rm, Rn); + UML_MOV(block, I1, R32(Rm)); // mov r1, Rm + UML_SUB(block, R32(Rn), R32(Rn), 2); // sub Rn, Rn, 2 + UML_MOV(block, I0, R32(Rn)); // mov r0, Rn + UML_CALLH(block, *m_write16); // call write16 + + if (!in_delay_slot) + generate_update_cycles(block, compiler, desc->pc + 2, true); + return true; + + case 6: // MOVLM(Rm, Rn); + UML_MOV(block, I1, R32(Rm)); // mov r1, Rm + UML_SUB(block, R32(Rn), R32(Rn), 4); // sub Rn, Rn, 4 + UML_MOV(block, I0, R32(Rn)); // mov r0, Rn + UML_CALLH(block, *m_write32); // call write32 + + if (!in_delay_slot) + generate_update_cycles(block, compiler, desc->pc + 2, true); + return true; + + case 13: // XTRCT(Rm, Rn); + UML_SHL(block, I0, R32(Rm), 16); // shl r0, Rm, #16 + UML_AND(block, I0, I0, 0xffff0000); // and r0, r0, #0xffff0000 + + UML_SHR(block, I1, R32(Rn), 16); // shr, r1, Rn, #16 + UML_AND(block, I1, I1, 0xffff); // and r1, r1, #0x0000ffff + + UML_OR(block, R32(Rn), I0, I1); // or Rn, r0, r1 + return true; + + case 7: // DIV0S(Rm, Rn); + UML_MOV(block, I0, mem(&m_sh2_state->sr)); // move r0, sr + UML_AND(block, I0, I0, ~(Q|M|T)); // and r0, r0, ~(Q|M|T) (clear the Q,M, and T bits) + + UML_TEST(block, R32(Rn), 0x80000000); // test Rn, #0x80000000 + UML_JMPc(block, COND_Z, compiler->labelnum); // jz labelnum + + UML_OR(block, I0, I0, Q); // or r0, r0, Q + UML_LABEL(block, compiler->labelnum++); // labelnum: + + UML_TEST(block, R32(Rm), 0x80000000); // test Rm, #0x80000000 + UML_JMPc(block, COND_Z, compiler->labelnum); // jz labelnum + + UML_OR(block, I0, I0, M); // or r0, r0, M + UML_LABEL(block, compiler->labelnum++); // labelnum: + + UML_XOR(block, I1, R32(Rn), R32(Rm)); // xor r1, Rn, Rm + UML_TEST(block, I1, 0x80000000); // test r1, #0x80000000 + UML_JMPc(block, COND_Z, compiler->labelnum); // jz labelnum + + UML_OR(block, I0, I0, T); // or r0, r0, T + UML_LABEL(block, compiler->labelnum++); // labelnum: + UML_MOV(block, mem(&m_sh2_state->sr), I0); // mov sr, r0 + return true; + + case 8: // TST(Rm, Rn); + UML_AND(block, I0, mem(&m_sh2_state->sr), ~T); // and r0, sr, ~T (clear the T bit) + UML_TEST(block, R32(Rm), R32(Rn)); // test Rm, Rn + UML_JMPc(block, COND_NZ, compiler->labelnum); // jnz compiler->labelnum + + UML_OR(block, I0, I0, T); // or r0, r0, T + UML_LABEL(block, compiler->labelnum++); // desc->pc: + + UML_MOV(block, mem(&m_sh2_state->sr), I0); // mov m_sh2_state->sr, r0 + return true; + + case 12: // CMPSTR(Rm, Rn); + UML_XOR(block, I0, R32(Rn), R32(Rm)); // xor r0, Rn, Rm (temp) + + UML_SHR(block, I1, I0, 24); // shr r1, r0, #24 (HH) + UML_AND(block, I1, I1, 0xff); // and r1, r1, #0xff + + UML_SHR(block, I2, I0, 16); // shr r2, r0, #16 (HL) + UML_AND(block, I2, I2, 0xff); // and r2, r2, #0xff + + UML_SHR(block, I3, I0, 8); // shr r3, r0, #8 (LH) + UML_AND(block, I3, I3, 0xff); // and r3, r3, #0xff + + UML_AND(block, I7, I0, 0xff); // and r7, r0, #0xff (LL) + + UML_AND(block, mem(&m_sh2_state->sr), mem(&m_sh2_state->sr), ~T); // and sr, sr, ~T (clear the T bit) + + UML_CMP(block, I1, 0); // cmp r1, #0 + UML_JMPc(block, COND_Z, compiler->labelnum); // jnz labelnum + UML_CMP(block, I2, 0); // cmp r2, #0 + UML_JMPc(block, COND_Z, compiler->labelnum); // jnz labelnum + UML_CMP(block, I3, 0); // cmp r3, #0 + UML_JMPc(block, COND_Z, compiler->labelnum); // jnz labelnum + UML_CMP(block, I7, 0); // cmp r7, #0 + UML_JMPc(block, COND_NZ, compiler->labelnum+1); // jnz labelnum + + UML_LABEL(block, compiler->labelnum++); // labelnum: + UML_OR(block, mem(&m_sh2_state->sr), mem(&m_sh2_state->sr), T); // or sr, sr, T + + UML_LABEL(block, compiler->labelnum++); // labelnum+1: + return true; + + case 9: // AND(Rm, Rn); + UML_AND(block, R32(Rn), R32(Rn), R32(Rm)); // and Rn, Rn, Rm + return true; + + case 10: // XOR(Rm, Rn); + UML_XOR(block, R32(Rn), R32(Rn), R32(Rm)); // xor Rn, Rn, Rm + return true; + + case 11: // OR(Rm, Rn); + UML_OR(block, R32(Rn), R32(Rn), R32(Rm)); // or Rn, Rn, Rm + return true; + + case 14: // MULU(Rm, Rn); + UML_AND(block, I0, R32(Rm), 0xffff); // and r0, Rm, 0xffff + UML_AND(block, I1, R32(Rn), 0xffff); // and r1, Rn, 0xffff + UML_MULU(block, mem(&m_sh2_state->macl), mem(&m_sh2_state->ea), I0, I1); // mulu macl, ea, r0, r1 + return true; + + case 15: // MULS(Rm, Rn); + UML_SEXT(block, I0, R32(Rm), SIZE_WORD); // sext r0, Rm + UML_SEXT(block, I1, R32(Rn), SIZE_WORD); // sext r1, Rn + UML_MULS(block, mem(&m_sh2_state->macl), mem(&m_sh2_state->ea), I0, I1); // muls macl, ea, r0, r1 + return true; + } + + return false; +} + +bool sh2_device::generate_group_3(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, uint32_t ovrpc) +{ + switch (opcode & 15) + { + case 0: // CMPEQ(Rm, Rn); (equality) + UML_CMP(block, R32(Rn), R32(Rm)); // cmp Rn, Rm + UML_SETc(block, COND_E, I0); // set E, r0 + UML_ROLINS(block, mem(&m_sh2_state->sr), I0, 0, 1); // rolins sr, r0, 0, 1 + return true; + + case 2: // CMPHS(Rm, Rn); (unsigned greater than or equal) + UML_CMP(block, R32(Rn), R32(Rm)); // cmp Rn, Rm + UML_SETc(block, COND_AE, I0); // set AE, r0 + UML_ROLINS(block, mem(&m_sh2_state->sr), I0, 0, 1); // rolins sr, r0, 0, 1 + return true; + + case 3: // CMPGE(Rm, Rn); (signed greater than or equal) + UML_CMP(block, R32(Rn), R32(Rm)); // cmp Rn, Rm + UML_SETc(block, COND_GE, I0); // set GE, r0 + UML_ROLINS(block, mem(&m_sh2_state->sr), I0, 0, 1); // rolins sr, r0, 0, 1 + return true; + + case 6: // CMPHI(Rm, Rn); (unsigned greater than) + UML_CMP(block, R32(Rn), R32(Rm)); // cmp Rn, Rm + UML_SETc(block, COND_A, I0); // set A, r0 + UML_ROLINS(block, mem(&m_sh2_state->sr), I0, 0, 1); // rolins sr, r0, 0, 1 + return true; + + case 7: // CMPGT(Rm, Rn); (signed greater than) + UML_CMP(block, R32(Rn), R32(Rm)); // cmp Rn, Rm + UML_SETc(block, COND_G, I0); // set G, r0 + UML_ROLINS(block, mem(&m_sh2_state->sr), I0, 0, 1); // rolins sr, r0, 0, 1 + return true; + + case 1: + case 9: + return false; + + case 4: // DIV1(Rm, Rn); + save_fast_iregs(block); + UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr.w[0]); + UML_CALLC(block, cfunc_DIV1, this); + load_fast_iregs(block); + return true; + + case 5: // DMULU(Rm, Rn); + if (m_cpu_type > CPU_TYPE_SH1) + { + UML_MULU(block, mem(&m_sh2_state->macl), mem(&m_sh2_state->mach), R32(Rn), R32(Rm)); + return true; + } + break; + + case 13: // DMULS(Rm, Rn); + if (m_cpu_type > CPU_TYPE_SH1) + { + UML_MULS(block, mem(&m_sh2_state->macl), mem(&m_sh2_state->mach), R32(Rn), R32(Rm)); + return true; + } + break; + + case 8: // SUB(Rm, Rn); + UML_SUB(block, R32(Rn), R32(Rn), R32(Rm)); // sub Rn, Rn, Rm + return true; + + case 12: // ADD(Rm, Rn); + UML_ADD(block, R32(Rn), R32(Rn), R32(Rm)); // add Rn, Rn, Rm + return true; + + case 10: // SUBC(Rm, Rn); + UML_CARRY(block, mem(&m_sh2_state->sr), 0); // carry = T (T is bit 0 of SR) + UML_SUBB(block, R32(Rn), R32(Rn), R32(Rm)); // addc Rn, Rn, Rm + UML_SETc(block, COND_C, I0); // setc i0, C + UML_ROLINS(block, mem(&m_sh2_state->sr), I0, 0, T); // rolins sr,i0,0,T + return true; + + case 11: // SUBV(Rm, Rn); +#if ADDSUBV_DIRECT + UML_SUB(block, R32(Rn), R32(Rn), R32(Rm)); // sub Rn, Rn, Rm + UML_SETc(block, COND_V, I0); // setc i0, V + UML_ROLINS(block, mem(&m_sh2_state->sr), I0, 0, T); // rolins [sr],i0,0,T +#else + save_fast_iregs(block); + UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr.w[0]); + UML_CALLC(block, cfunc_SUBV, this); + load_fast_iregs(block); +#endif + return true; + + case 14: // ADDC(Rm, Rn); + UML_CARRY(block, mem(&m_sh2_state->sr), 0); // carry = T (T is bit 0 of SR) + UML_ADDC(block, R32(Rn), R32(Rn), R32(Rm)); // addc Rn, Rn, Rm + UML_SETc(block, COND_C, I0); // setc i0, C + UML_ROLINS(block, mem(&m_sh2_state->sr), I0, 0, T); // rolins sr,i0,0,T + return true; + + case 15: // ADDV(Rm, Rn); +#if ADDSUBV_DIRECT + UML_ADD(block, R32(Rn), R32(Rn), R32(Rm)); // add Rn, Rn, Rm + UML_SETc(block, COND_V, I0); // setc i0, V + UML_ROLINS(block, mem(&m_sh2_state->sr), I0, 0, T); // rolins [sr],i0,0,T +#else + save_fast_iregs(block); + UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr.w[0]); + UML_CALLC(block, cfunc_ADDV, this); + load_fast_iregs(block); +#endif + return true; + } + return false; +} + +bool sh2_device::generate_group_4(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc) +{ + switch (opcode & 0x3F) + { + case 0x00: // SHLL(Rn); + UML_SHL(block, R32(Rn), R32(Rn), 1); // shl Rn, Rn, 1 + UML_SETc(block, COND_C, I0); // set i0,C + UML_ROLINS(block, mem(&m_sh2_state->sr), I0, 0, T); // rolins [sr],i0,0,T + return true; + + case 0x01: // SHLR(Rn); + UML_SHR(block, R32(Rn), R32(Rn), 1); // shr Rn, Rn, 1 + UML_SETc(block, COND_C, I0); // set i0,C + UML_ROLINS(block, mem(&m_sh2_state->sr), I0, 0, T); // rolins [sr],i0,0,T + return true; + + case 0x04: // ROTL(Rn); + UML_ROL(block, R32(Rn), R32(Rn), 1); // rol Rn, Rn, 1 + UML_SETc(block, COND_C, I0); // set i0,C + UML_ROLINS(block, mem(&m_sh2_state->sr), I0, 0, T); // rolins [sr],i0,0,T + return true; + + case 0x05: // ROTR(Rn); + UML_ROR(block, R32(Rn), R32(Rn), 1); // ror Rn, Rn, 1 + UML_SETc(block, COND_C, I0); // set i0,C + UML_ROLINS(block, mem(&m_sh2_state->sr), I0, 0, T); // rolins [sr],i0,0,T + return true; + + case 0x02: // STSMMACH(Rn); + UML_SUB(block, R32(Rn), R32(Rn), 4); // sub Rn, Rn, #4 + UML_MOV(block, I0, R32(Rn)); // mov r0, Rn + UML_MOV(block, I1, mem(&m_sh2_state->mach)); // mov r1, mach + SETEA(0); // set ea for debug + UML_CALLH(block, *m_write32); // call write32 + + if (!in_delay_slot) + generate_update_cycles(block, compiler, desc->pc + 2, true); + return true; + + case 0x03: // STCMSR(Rn); + UML_SUB(block, R32(Rn), R32(Rn), 4); // sub Rn, Rn, #4 + UML_MOV(block, I0, R32(Rn)); // mov r0, Rn + UML_MOV(block, I1, mem(&m_sh2_state->sr)); // mov r1, sr + SETEA(0); // set ea for debug + UML_CALLH(block, *m_write32); // call write32 + + if (!in_delay_slot) + generate_update_cycles(block, compiler, desc->pc + 2, true); + return true; + + case 0x06: // LDSMMACH(Rn); + UML_MOV(block, I0, R32(Rn)); // mov r0, Rn + SETEA(0); + UML_CALLH(block, *m_read32); // call read32 + UML_ADD(block, R32(Rn), R32(Rn), 4); // add Rn, #4 + UML_MOV(block, mem(&m_sh2_state->mach), I0); // mov mach, r0 + + if (!in_delay_slot) + generate_update_cycles(block, compiler, desc->pc + 2, true); + return true; + + case 0x07: // LDCMSR(Rn); + UML_MOV(block, I0, R32(Rn)); // mov r0, Rn + SETEA(0); + UML_CALLH(block, *m_read32); // call read32 + UML_ADD(block, R32(Rn), R32(Rn), 4); // add Rn, #4 + UML_MOV(block, mem(&m_sh2_state->sr), I0); // mov sr, r0 + + compiler->checkints = true; + if (!in_delay_slot) + generate_update_cycles(block, compiler, desc->pc + 2, true); + return true; + + + case 0x08: // SHLL2(Rn); + UML_SHL(block, R32(Rn), R32(Rn), 2); + return true; + + case 0x09: // SHLR2(Rn); + UML_SHR(block, R32(Rn), R32(Rn), 2); + return true; + + case 0x18: // SHLL8(Rn); + UML_SHL(block, R32(Rn), R32(Rn), 8); + return true; + + case 0x19: // SHLR8(Rn); + UML_SHR(block, R32(Rn), R32(Rn), 8); + return true; + + case 0x28: // SHLL16(Rn); + UML_SHL(block, R32(Rn), R32(Rn), 16); + return true; + + case 0x29: // SHLR16(Rn); + UML_SHR(block, R32(Rn), R32(Rn), 16); + return true; + + case 0x0a: // LDSMACH(Rn); + UML_MOV(block, mem(&m_sh2_state->mach), R32(Rn)); // mov mach, Rn + return true; + + case 0x0b: // JSR(Rn); + UML_MOV(block, mem(&m_sh2_state->target), R32(Rn)); // mov target, Rn + + UML_ADD(block, mem(&m_sh2_state->pr), desc->pc, 4); // add m_pr, desc->pc, #4 (skip the current insn & delay slot) + + generate_delay_slot(block, compiler, desc, m_sh2_state->target-4); + + generate_update_cycles(block, compiler, mem(&m_sh2_state->target), true); // + UML_HASHJMP(block, 0, mem(&m_sh2_state->target), *m_nocode); // and do the jump + return true; + + case 0x0e: // LDCSR(Rn); + UML_MOV(block, I0, R32(Rn)); // mov r0, Rn + UML_AND(block, I0, I0, FLAGS); // and r0, r0, FLAGS + UML_MOV(block, mem(&m_sh2_state->sr), I0); + + compiler->checkints = true; + return true; + + case 0x0f: // MAC_W(Rm, Rn); + case 0x1f: // MAC_W(Rm, Rn); + case 0x2f: // MAC_W(Rm, Rn); + case 0x3f: // MAC_W(Rm, Rn); + save_fast_iregs(block); + UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr.w[0]); + UML_CALLC(block, cfunc_MAC_W, this); + load_fast_iregs(block); + return true; + + case 0x10: // DT(Rn); + if (m_cpu_type > CPU_TYPE_SH1) + { + UML_AND(block, I0, mem(&m_sh2_state->sr), ~T); // and r0, sr, ~T (clear the T bit) + UML_SUB(block, R32(Rn), R32(Rn), 1); // sub Rn, Rn, 1 + UML_JMPc(block, COND_NZ, compiler->labelnum); // jz compiler->labelnum + + UML_OR(block, I0, I0, T); // or r0, r0, T + UML_LABEL(block, compiler->labelnum++); // desc->pc: + + UML_MOV(block, mem(&m_sh2_state->sr), I0); // mov m_sh2_state->sr, r0 + return true; + } + break; + + case 0x11: // CMPPZ(Rn); + UML_AND(block, I0, mem(&m_sh2_state->sr), ~T); // and r0, sr, ~T (clear the T bit) + + UML_CMP(block, R32(Rn), 0); // cmp Rn, 0 + UML_JMPc(block, COND_S, compiler->labelnum); // js compiler->labelnum (if negative) + + UML_OR(block, I0, I0, T); // or r0, r0, T + UML_LABEL(block, compiler->labelnum++); // desc->pc: + + UML_MOV(block, mem(&m_sh2_state->sr), I0); // mov m_sh2_state->sr, r0 + return true; + + case 0x15: // CMPPL(Rn); + UML_AND(block, I0, mem(&m_sh2_state->sr), ~T); // and r0, sr, ~T (clear the T bit) + + UML_CMP(block, R32(Rn), 0); // cmp Rn, 0 + + UML_JMPc(block, COND_S, compiler->labelnum); // js compiler->labelnum (if negative) + UML_JMPc(block, COND_Z, compiler->labelnum); // jz compiler->labelnum (if zero) + + UML_OR(block, I0, I0, T); // or r0, r0, T + + UML_LABEL(block, compiler->labelnum++); // desc->pc: + UML_MOV(block, mem(&m_sh2_state->sr), I0); // mov m_sh2_state->sr, r0 + return true; + + case 0x12: // STSMMACL(Rn); + UML_SUB(block, R32(Rn), R32(Rn), 4); // sub Rn, Rn, #4 + UML_MOV(block, I0, R32(Rn)); // mov r0, Rn + UML_MOV(block, I1, mem(&m_sh2_state->macl)); // mov r1, macl + SETEA(0); // set ea for debug + UML_CALLH(block, *m_write32); // call write32 + + if (!in_delay_slot) + generate_update_cycles(block, compiler, desc->pc + 2, true); + return true; + + case 0x13: // STCMGBR(Rn); + UML_SUB(block, R32(Rn), R32(Rn), 4); // sub Rn, Rn, #4 + UML_MOV(block, I0, R32(Rn)); // mov r0, Rn + UML_MOV(block, I1, mem(&m_sh2_state->gbr)); // mov r1, gbr + SETEA(0); // set ea for debug + UML_CALLH(block, *m_write32); // call write32 + + if (!in_delay_slot) + generate_update_cycles(block, compiler, desc->pc + 2, true); + return true; + + case 0x16: // LDSMMACL(Rn); + UML_MOV(block, I0, R32(Rn)); // mov r0, Rn + SETEA(0); + UML_CALLH(block, *m_read32); // call read32 + UML_ADD(block, R32(Rn), R32(Rn), 4); // add Rn, #4 + UML_MOV(block, mem(&m_sh2_state->macl), I0); // mov macl, r0 + + if (!in_delay_slot) + generate_update_cycles(block, compiler, desc->pc + 2, true); + return true; + + case 0x17: // LDCMGBR(Rn); + UML_MOV(block, I0, R32(Rn)); // mov r0, Rn + SETEA(0); + UML_CALLH(block, *m_read32); // call read32 + UML_ADD(block, R32(Rn), R32(Rn), 4); // add Rn, #4 + UML_MOV(block, mem(&m_sh2_state->gbr), I0); // mov gbr, r0 + + if (!in_delay_slot) + generate_update_cycles(block, compiler, desc->pc + 2, true); + return true; + + case 0x1a: // LDSMACL(Rn); + UML_MOV(block, mem(&m_sh2_state->macl), R32(Rn)); // mov macl, Rn + return true; + + case 0x1b: // TAS(Rn); + UML_MOV(block, I0, R32(Rn)); // mov r0, Rn + SETEA(0); + UML_CALLH(block, *m_read8); // call read8 + + UML_AND(block, mem(&m_sh2_state->sr), mem(&m_sh2_state->sr), ~T); // and sr, sr, ~T + + UML_CMP(block, I0, 0); // cmp r0, #0 + UML_JMPc(block, COND_NZ, compiler->labelnum); // jnz labelnum + + UML_OR(block, mem(&m_sh2_state->sr), mem(&m_sh2_state->sr), T); // or sr, sr, T + + UML_LABEL(block, compiler->labelnum++); // labelnum: + + UML_OR(block, I1, I0, 0x80); // or r1, r0, #0x80 + + UML_MOV(block, I0, R32(Rn)); // mov r0, Rn + UML_CALLH(block, *m_write8); // write the value back + + if (!in_delay_slot) + generate_update_cycles(block, compiler, desc->pc + 2, true); + return true; + + case 0x1e: // LDCGBR(Rn); + UML_MOV(block, mem(&m_sh2_state->gbr), R32(Rn)); // mov gbr, Rn + return true; + + case 0x20: // SHAL(Rn); + UML_AND(block, mem(&m_sh2_state->sr), mem(&m_sh2_state->sr), ~T); // and sr, sr, ~T + UML_SHR(block, I0, R32(Rn), 31); // shr r0, Rn, 31 + UML_AND(block, I0, I0, T); // and r0, r0, T + UML_OR(block, mem(&m_sh2_state->sr), mem(&m_sh2_state->sr), I0); // or sr, sr, r0 + UML_SHL(block, R32(Rn), R32(Rn), 1); // shl Rn, Rn, 1 + return true; + + case 0x21: // SHAR(Rn); + UML_AND(block, mem(&m_sh2_state->sr), mem(&m_sh2_state->sr), ~T); // and sr, sr, ~T + UML_AND(block, I0, R32(Rn), T); // and r0, Rn, T + UML_OR(block, mem(&m_sh2_state->sr), mem(&m_sh2_state->sr), I0); // or sr, sr, r0 + UML_SAR(block, R32(Rn), R32(Rn), 1); // sar Rn, Rn, 1 + return true; + + case 0x22: // STSMPR(Rn); + UML_SUB(block, R32(Rn), R32(Rn), 4); // sub Rn, Rn, 4 + UML_MOV(block, I0, R32(Rn)); // mov r0, Rn + SETEA(0); + UML_MOV(block, I1, mem(&m_sh2_state->pr)); // mov r1, pr + UML_CALLH(block, *m_write32); // call write32 + + if (!in_delay_slot) + generate_update_cycles(block, compiler, desc->pc + 2, true); + return true; + + case 0x23: // STCMVBR(Rn); + UML_SUB(block, R32(Rn), R32(Rn), 4); // sub Rn, Rn, 4 + UML_MOV(block, I0, R32(Rn)); // mov r0, Rn + SETEA(0); + UML_MOV(block, I1, mem(&m_sh2_state->vbr)); // mov r1, vbr + UML_CALLH(block, *m_write32); // call write32 + + if (!in_delay_slot) + generate_update_cycles(block, compiler, desc->pc + 2, true); + return true; + + case 0x24: // ROTCL(Rn); + UML_CARRY(block, mem(&m_sh2_state->sr), 0); // carry sr,0 + UML_ROLC(block, R32(Rn), R32(Rn), 1); // rolc Rn,Rn,1 + UML_SETc(block, COND_C, I0); // set i0,C + UML_ROLINS(block, mem(&m_sh2_state->sr), I0, 0, T); // rolins sr,i0,0,T + return true; + + case 0x25: // ROTCR(Rn); + UML_CARRY(block, mem(&m_sh2_state->sr), 0); // carry sr,0 + UML_RORC(block, R32(Rn), R32(Rn), 1); // rorc Rn,Rn,1 + UML_SETc(block, COND_C, I0); // set i0,C + UML_ROLINS(block, mem(&m_sh2_state->sr), I0, 0, T); // rolins sr,i0,0,T + return true; + + case 0x26: // LDSMPR(Rn); + UML_MOV(block, I0, R32(Rn)); // mov r0, Rn + SETEA(0); + UML_CALLH(block, *m_read32); // call read32 + UML_MOV(block, mem(&m_sh2_state->pr), I0); // mov m_pr, r0 + UML_ADD(block, R32(Rn), R32(Rn), 4); // add Rn, Rn, #4 + + if (!in_delay_slot) + generate_update_cycles(block, compiler, desc->pc + 2, true); + return true; + + case 0x27: // LDCMVBR(Rn); + UML_MOV(block, I0, R32(Rn)); // mov r0, Rn + SETEA(0); + UML_CALLH(block, *m_read32); // call read32 + UML_MOV(block, mem(&m_sh2_state->vbr), I0); // mov m_sh2_state->vbr, r0 + UML_ADD(block, R32(Rn), R32(Rn), 4); // add Rn, Rn, #4 + + if (!in_delay_slot) + generate_update_cycles(block, compiler, desc->pc + 2, true); + return true; + + case 0x2a: // LDSPR(Rn); + UML_MOV(block, mem(&m_sh2_state->pr), R32(Rn)); // mov m_pr, Rn + return true; + + case 0x2b: // JMP(Rn); + UML_MOV(block, mem(&m_sh2_state->target), R32(Rn)); // mov target, Rn + + generate_delay_slot(block, compiler, desc, m_sh2_state->target); + + generate_update_cycles(block, compiler, mem(&m_sh2_state->target), true); // + UML_HASHJMP(block, 0, mem(&m_sh2_state->target), *m_nocode); // jmp (target) + return true; + + case 0x2e: // LDCVBR(Rn); + UML_MOV(block, mem(&m_sh2_state->vbr), R32(Rn)); // mov vbr, Rn + return true; + + case 0x0c: + case 0x0d: + case 0x14: + case 0x1c: + case 0x1d: + case 0x2c: + case 0x2d: + case 0x30: + case 0x31: + case 0x32: + case 0x33: + case 0x34: + case 0x35: + case 0x36: + case 0x37: + case 0x38: + case 0x39: + case 0x3a: + case 0x3b: + case 0x3c: + case 0x3d: + case 0x3e: + return false; + } + + return false; +} + +bool sh2_device::generate_group_6(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc) +{ + switch (opcode & 15) + { + case 0: // MOVBL(Rm, Rn); + UML_MOV(block, I0, R32(Rm)); // mov r0, Rm + SETEA(0); // debug: ea = r0 + UML_CALLH(block, *m_read8); // call read8 + UML_SEXT(block, R32(Rn), I0, SIZE_BYTE); // sext Rn, r0, BYTE + + if (!in_delay_slot) + generate_update_cycles(block, compiler, desc->pc + 2, true); + return true; + + case 1: // MOVWL(Rm, Rn); + UML_MOV(block, I0, R32(Rm)); // mov r0, Rm + SETEA(0); // debug: ea = r0 + UML_CALLH(block, *m_read16); // call read16 + UML_SEXT(block, R32(Rn), I0, SIZE_WORD); // sext Rn, r0, WORD + + if (!in_delay_slot) + generate_update_cycles(block, compiler, desc->pc + 2, true); + return true; + + case 2: // MOVLL(Rm, Rn); + UML_MOV(block, I0, R32(Rm)); // mov r0, Rm + SETEA(0); // debug: ea = r0 + UML_CALLH(block, *m_read32); // call read32 + UML_MOV(block, R32(Rn), I0); // mov Rn, r0 + + if (!in_delay_slot) + generate_update_cycles(block, compiler, desc->pc + 2, true); + return true; + + case 3: // MOV(Rm, Rn); + UML_MOV(block, R32(Rn), R32(Rm)); // mov Rn, Rm + return true; + + case 7: // NOT(Rm, Rn); + UML_XOR(block, R32(Rn), R32(Rm), 0xffffffff); // xor Rn, Rm, 0xffffffff + return true; + + case 9: // SWAPW(Rm, Rn); + UML_ROL(block, R32(Rn), R32(Rm), 16); // rol Rn, Rm, 16 + return true; + + case 11: // NEG(Rm, Rn); + UML_SUB(block, R32(Rn), 0, R32(Rm)); // sub Rn, 0, Rm + return true; + + case 12: // EXTUB(Rm, Rn); + UML_AND(block, R32(Rn), R32(Rm), 0x000000ff); // and Rn, Rm, 0xff + return true; + + case 13: // EXTUW(Rm, Rn); + UML_AND(block, R32(Rn), R32(Rm), 0x0000ffff); // and Rn, Rm, 0xffff + return true; + + case 14: // EXTSB(Rm, Rn); + UML_SEXT(block, R32(Rn), R32(Rm), SIZE_BYTE); // sext Rn, Rm, BYTE + return true; + + case 15: // EXTSW(Rm, Rn); + UML_SEXT(block, R32(Rn), R32(Rm), SIZE_WORD); // sext Rn, Rm, WORD + return true; + + case 4: // MOVBP(Rm, Rn); + UML_MOV(block, I0, R32(Rm)); // mov r0, Rm + UML_CALLH(block, *m_read8); // call read8 + UML_SEXT(block, R32(Rn), I0, SIZE_BYTE); // sext Rn, r0, BYTE + + if (Rm != Rn) + UML_ADD(block, R32(Rm), R32(Rm), 1); // add Rm, Rm, #1 + + if (!in_delay_slot) + generate_update_cycles(block, compiler, desc->pc + 2, true); + return true; + + case 5: // MOVWP(Rm, Rn); + UML_MOV(block, I0, R32(Rm)); // mov r0, Rm + UML_CALLH(block, *m_read16); // call read16 + UML_SEXT(block, R32(Rn), I0, SIZE_WORD); // sext Rn, r0, WORD + + if (Rm != Rn) + UML_ADD(block, R32(Rm), R32(Rm), 2); // add Rm, Rm, #2 + + if (!in_delay_slot) + generate_update_cycles(block, compiler, desc->pc + 2, true); + return true; + + case 6: // MOVLP(Rm, Rn); + UML_MOV(block, I0, R32(Rm)); // mov r0, Rm + UML_CALLH(block, *m_read32); // call read32 + UML_MOV(block, R32(Rn), I0); // mov Rn, r0 + + if (Rm != Rn) + UML_ADD(block, R32(Rm), R32(Rm), 4); // add Rm, Rm, #4 + + if (!in_delay_slot) + generate_update_cycles(block, compiler, desc->pc + 2, true); + return true; + + case 8: // SWAPB(Rm, Rn); + UML_AND(block, I0, R32(Rm), 0xffff0000); // and r0, Rm, #0xffff0000 + UML_AND(block, I1, R32(Rm), 0x000000ff); // and r0, Rm, #0x000000ff + UML_AND(block, I2, R32(Rm), 0x0000ff00); // and r0, Rm, #0x0000ff00 + UML_SHL(block, I1, I1, 8); // shl r1, r1, #8 + UML_SHR(block, I2, I2, 8); // shr r2, r2, #8 + UML_OR(block, I0, I0, I1); // or r0, r0, r1 + UML_OR(block, R32(Rn), I0, I2); // or Rn, r0, r2 + return true; + + case 10: // NEGC(Rm, Rn); + UML_MOV(block, I0, mem(&m_sh2_state->sr)); // mov r0, sr (save SR) + UML_AND(block, mem(&m_sh2_state->sr), mem(&m_sh2_state->sr), ~T); // and sr, sr, ~T (clear the T bit) + UML_CARRY(block, I0, 0); // carry = T (T is bit 0 of SR) + UML_SUBB(block, R32(Rn), 0, R32(Rm)); // subb Rn, #0, Rm + + UML_JMPc(block, COND_NC, compiler->labelnum); // jnc labelnum + + UML_OR(block, mem(&m_sh2_state->sr), mem(&m_sh2_state->sr), T); // or sr, sr, T + + UML_LABEL(block, compiler->labelnum++); // labelnum: + + return true; + } + + return false; +} + +bool sh2_device::generate_group_8(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc) +{ + int32_t disp; + uint32_t udisp; + code_label templabel; + + switch ( opcode & (15<<8) ) + { + case 0 << 8: // MOVBS4(opcode & 0x0f, Rm); + udisp = (opcode & 0x0f); + UML_ADD(block, I0, R32(Rm), udisp); // add r0, Rm, udisp + UML_MOV(block, I1, R32(0)); // mov r1, R0 + UML_CALLH(block, *m_write8); // call write8 + + if (!in_delay_slot) + generate_update_cycles(block, compiler, desc->pc + 2, true); + return true; + + case 1 << 8: // MOVWS4(opcode & 0x0f, Rm); + udisp = (opcode & 0x0f) * 2; + UML_ADD(block, I0, R32(Rm), udisp); // add r0, Rm, udisp + UML_MOV(block, I1, R32(0)); // mov r1, R0 + UML_CALLH(block, *m_write16); // call write16 + + if (!in_delay_slot) + generate_update_cycles(block, compiler, desc->pc + 2, true); + return true; + + case 2<< 8: + case 3<< 8: + case 6<< 8: + case 7<< 8: + case 10<< 8: + case 12<< 8: + case 14<< 8: + return false; + + case 4<< 8: // MOVBL4(Rm, opcode & 0x0f); + udisp = opcode & 0x0f; + UML_ADD(block, I0, R32(Rm), udisp); // add r0, Rm, udisp + SETEA(0); + UML_CALLH(block, *m_read8); // call read8 + UML_SEXT(block, R32(0), I0, SIZE_BYTE); // sext R0, r0, BYTE + + if (!in_delay_slot) + generate_update_cycles(block, compiler, desc->pc + 2, true); + return true; + + case 5<< 8: // MOVWL4(Rm, opcode & 0x0f); + udisp = (opcode & 0x0f)*2; + UML_ADD(block, I0, R32(Rm), udisp); // add r0, Rm, udisp + SETEA(0); + UML_CALLH(block, *m_read16); // call read16 + UML_SEXT(block, R32(0), I0, SIZE_WORD); // sext R0, r0, WORD + + if (!in_delay_slot) + generate_update_cycles(block, compiler, desc->pc + 2, true); + return true; + + case 8<< 8: // CMPIM(opcode & 0xff); + UML_AND(block, I0, mem(&m_sh2_state->sr), ~T); // and r0, sr, ~T (clear the T bit) + + UML_SEXT(block, I1, opcode&0xff, SIZE_BYTE); // sext r1, opcode&0xff, BYTE + UML_CMP(block, I1, R32(0)); // cmp r1, R0 + UML_JMPc(block, COND_NZ, compiler->labelnum); // jnz compiler->labelnum (if negative) + + UML_OR(block, I0, I0, T); // or r0, r0, T + + UML_LABEL(block, compiler->labelnum++); // labelnum: + UML_MOV(block, mem(&m_sh2_state->sr), I0); // mov m_sh2_state->sr, r0 + return true; + + case 9<< 8: // BT(opcode & 0xff); + UML_TEST(block, mem(&m_sh2_state->sr), T); // test m_sh2_state->sr, T + UML_JMPc(block, COND_Z, compiler->labelnum); // jz compiler->labelnum + + disp = ((int32_t)opcode << 24) >> 24; + m_sh2_state->ea = (desc->pc + 2) + disp * 2 + 2; // m_sh2_state->ea = destination + + generate_update_cycles(block, compiler, m_sh2_state->ea, true); // + UML_HASHJMP(block, 0, m_sh2_state->ea, *m_nocode); // jmp m_sh2_state->ea + + UML_LABEL(block, compiler->labelnum++); // labelnum: + return true; + + case 11<< 8: // BF(opcode & 0xff); + UML_TEST(block, mem(&m_sh2_state->sr), T); // test m_sh2_state->sr, T + UML_JMPc(block, COND_NZ, compiler->labelnum); // jnz compiler->labelnum + + disp = ((int32_t)opcode << 24) >> 24; + m_sh2_state->ea = (desc->pc + 2) + disp * 2 + 2; // m_sh2_state->ea = destination + + generate_update_cycles(block, compiler, m_sh2_state->ea, true); // + UML_HASHJMP(block, 0, m_sh2_state->ea, *m_nocode); // jmp m_sh2_state->ea + + UML_LABEL(block, compiler->labelnum++); // labelnum: + return true; + + case 13<< 8: // BTS(opcode & 0xff); + if (m_cpu_type > CPU_TYPE_SH1) + { + UML_TEST(block, mem(&m_sh2_state->sr), T); // test m_sh2_state->sr, T + UML_JMPc(block, COND_Z, compiler->labelnum); // jz compiler->labelnum + + disp = ((int32_t)opcode << 24) >> 24; + m_sh2_state->ea = (desc->pc + 2) + disp * 2 + 2; // m_sh2_state->ea = destination + + templabel = compiler->labelnum; // save our label + compiler->labelnum++; // make sure the delay slot doesn't use it + generate_delay_slot(block, compiler, desc, m_sh2_state->ea-2); + + generate_update_cycles(block, compiler, m_sh2_state->ea, true); // + UML_HASHJMP(block, 0, m_sh2_state->ea, *m_nocode); // jmp m_sh2_state->ea + + UML_LABEL(block, templabel); // labelnum: + return true; + } + break; + + case 15<< 8: // BFS(opcode & 0xff); + if (m_cpu_type > CPU_TYPE_SH1) + { + UML_TEST(block, mem(&m_sh2_state->sr), T); // test m_sh2_state->sr, T + UML_JMPc(block, COND_NZ, compiler->labelnum); // jnz compiler->labelnum + + disp = ((int32_t)opcode << 24) >> 24; + m_sh2_state->ea = (desc->pc + 2) + disp * 2 + 2; // m_sh2_state->ea = destination + + templabel = compiler->labelnum; // save our label + compiler->labelnum++; // make sure the delay slot doesn't use it + generate_delay_slot(block, compiler, desc, m_sh2_state->ea-2); // delay slot only if the branch is taken + + generate_update_cycles(block, compiler, m_sh2_state->ea, true); // + UML_HASHJMP(block, 0, m_sh2_state->ea, *m_nocode); // jmp m_sh2_state->ea + + UML_LABEL(block, templabel); // labelnum: + return true; + } + break; + } + + return false; +} + +bool sh2_device::generate_group_12(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc) +{ + uint32_t scratch; + + switch (opcode & (15<<8)) + { + case 0<<8: // MOVBSG(opcode & 0xff); + scratch = (opcode & 0xff); + UML_ADD(block, I0, mem(&m_sh2_state->gbr), scratch); // add r0, gbr, scratch + UML_AND(block, I1, R32(0), 0xff); // and r1, R0, 0xff + UML_CALLH(block, *m_write8); // call write8 + + if (!in_delay_slot) + generate_update_cycles(block, compiler, desc->pc + 2, true); + return true; + + case 1<<8: // MOVWSG(opcode & 0xff); + scratch = (opcode & 0xff) * 2; + UML_ADD(block, I0, mem(&m_sh2_state->gbr), scratch); // add r0, gbr, scratch + UML_AND(block, I1, R32(0), 0xffff); // and r1, R0, 0xffff + UML_CALLH(block, *m_write16); // call write16 + + if (!in_delay_slot) + generate_update_cycles(block, compiler, desc->pc + 2, true); + return true; + + case 2<<8: // MOVLSG(opcode & 0xff); + scratch = (opcode & 0xff) * 4; + UML_ADD(block, I0, mem(&m_sh2_state->gbr), scratch); // add r0, gbr, scratch + UML_MOV(block, I1, R32(0)); // mov r1, R0 + UML_CALLH(block, *m_write32); // call write32 + + if (!in_delay_slot) + generate_update_cycles(block, compiler, desc->pc + 2, true); + return true; + + case 3<<8: // TRAPA(opcode & 0xff); + scratch = (opcode & 0xff) * 4; + UML_ADD(block, mem(&m_sh2_state->ea), mem(&m_sh2_state->vbr), scratch); // add ea, vbr, scratch + + UML_SUB(block, R32(15), R32(15), 4); // sub R15, R15, #4 + UML_MOV(block, I0, R32(15)); // mov r0, R15 + UML_MOV(block, I1, mem(&m_sh2_state->sr)); // mov r1, sr + UML_CALLH(block, *m_write32); // write32 + + UML_SUB(block, R32(15), R32(15), 4); // sub R15, R15, #4 + UML_MOV(block, I0, R32(15)); // mov r0, R15 + UML_MOV(block, I1, desc->pc+2); // mov r1, pc+2 + UML_CALLH(block, *m_write32); // write32 + + UML_MOV(block, I0, mem(&m_sh2_state->ea)); // mov r0, ea + UML_CALLH(block, *m_read32); // read32 + UML_HASHJMP(block, 0, I0, *m_nocode); // jmp (r0) + + return true; + + case 4<<8: // MOVBLG(opcode & 0xff); + scratch = (opcode & 0xff); + UML_ADD(block, I0, mem(&m_sh2_state->gbr), scratch); // add r0, gbr, scratch + UML_CALLH(block, *m_read8); // call read16 + UML_SEXT(block, R32(0), I0, SIZE_BYTE); // sext R0, r0, BYTE + + if (!in_delay_slot) + generate_update_cycles(block, compiler, desc->pc + 2, true); + return true; + + case 5<<8: // MOVWLG(opcode & 0xff); + scratch = (opcode & 0xff) * 2; + UML_ADD(block, I0, mem(&m_sh2_state->gbr), scratch); // add r0, gbr, scratch + UML_CALLH(block, *m_read16); // call read16 + UML_SEXT(block, R32(0), I0, SIZE_WORD); // sext R0, r0, WORD + + if (!in_delay_slot) + generate_update_cycles(block, compiler, desc->pc + 2, true); + return true; + + case 6<<8: // MOVLLG(opcode & 0xff); + scratch = (opcode & 0xff) * 4; + UML_ADD(block, I0, mem(&m_sh2_state->gbr), scratch); // add r0, gbr, scratch + UML_CALLH(block, *m_read32); // call read32 + UML_MOV(block, R32(0), I0); // mov R0, r0 + + if (!in_delay_slot) + generate_update_cycles(block, compiler, desc->pc + 2, true); + return true; + + case 7<<8: // MOVA(opcode & 0xff); + scratch = (opcode & 0xff) * 4; + scratch += ((desc->pc + 4) & ~3); + + UML_MOV(block, R32(0), scratch); // mov R0, scratch + return true; + + case 8<<8: // TSTI(opcode & 0xff); + scratch = opcode & 0xff; + + UML_AND(block, mem(&m_sh2_state->sr), mem(&m_sh2_state->sr), ~T); // and sr, sr, ~T (clear the T bit) + UML_AND(block, I0, R32(0), scratch); // and r0, R0, scratch + UML_CMP(block, I0, 0); // cmp r0, #0 + UML_JMPc(block, COND_NZ, compiler->labelnum); // jnz labelnum + + UML_OR(block, mem(&m_sh2_state->sr), mem(&m_sh2_state->sr), T); // or sr, sr, T + + UML_LABEL(block, compiler->labelnum++); // labelnum: + return true; + + case 9<<8: // ANDI(opcode & 0xff); + UML_AND(block, R32(0), R32(0), opcode & 0xff); // and r0, r0, opcode & 0xff + return true; + + case 10<<8: // XORI(opcode & 0xff); + UML_XOR(block, R32(0), R32(0), opcode & 0xff); // xor r0, r0, opcode & 0xff + return true; + + case 11<<8: // ORI(opcode & 0xff); + UML_OR(block, R32(0), R32(0), opcode & 0xff); // or r0, r0, opcode & 0xff + return true; + + case 12<<8: // TSTM(opcode & 0xff); + UML_AND(block, mem(&m_sh2_state->sr), mem(&m_sh2_state->sr), ~T); // and sr, sr, ~T (clear the T bit) + UML_ADD(block, I0, R32(0), mem(&m_sh2_state->gbr)); // add r0, R0, gbr + UML_CALLH(block, *m_read8); // read8 + + UML_AND(block, I0, I0, opcode & 0xff); + UML_CMP(block, I0, 0); // cmp r0, #0 + UML_JMPc(block, COND_NZ, compiler->labelnum); // jnz labelnum + + UML_OR(block, mem(&m_sh2_state->sr), mem(&m_sh2_state->sr), T); // or sr, sr, T + + UML_LABEL(block, compiler->labelnum++); // labelnum: + return true; + + case 13<<8: // ANDM(opcode & 0xff); + UML_ADD(block, I0, R32(0), mem(&m_sh2_state->gbr)); // add r0, R0, gbr + UML_CALLH(block, *m_read8); // read8 + + UML_AND(block, I1, I0, opcode&0xff); // and r1, r0, #opcode&0xff + UML_ADD(block, I0, R32(0), mem(&m_sh2_state->gbr)); // add r0, R0, gbr + SETEA(0); + UML_CALLH(block, *m_write8); // write8 + return true; + + case 14<<8: // XORM(opcode & 0xff); + UML_ADD(block, I0, R32(0), mem(&m_sh2_state->gbr)); // add r0, R0, gbr + UML_CALLH(block, *m_read8); // read8 + + UML_XOR(block, I1, I0, opcode&0xff); // xor r1, r0, #opcode&0xff + UML_ADD(block, I0, R32(0), mem(&m_sh2_state->gbr)); // add r0, R0, gbr + SETEA(0); + UML_CALLH(block, *m_write8); // write8 + return true; + + case 15<<8: // ORM(opcode & 0xff); + UML_ADD(block, I0, R32(0), mem(&m_sh2_state->gbr)); // add r0, R0, gbr + UML_CALLH(block, *m_read8); // read8 + + UML_OR(block, I1, I0, opcode&0xff); // or r1, r0, #opcode&0xff + UML_ADD(block, I0, R32(0), mem(&m_sh2_state->gbr)); // add r0, R0, gbr + SETEA(0); + UML_CALLH(block, *m_write8); // write8 + return true; + } + + return false; +} + +/*************************************************************************** + CORE CALLBACKS +***************************************************************************/ + +/*------------------------------------------------- + sh2drc_set_options - configure DRC options +-------------------------------------------------*/ + +void sh2_device::sh2drc_set_options(uint32_t options) +{ + if (!allow_drc()) return; + m_drcoptions = options; +} + + +/*------------------------------------------------- + sh2drc_add_pcflush - add a new address where + the PC must be flushed for speedups to work +-------------------------------------------------*/ + +void sh2_device::sh2drc_add_pcflush(offs_t address) +{ + if (!allow_drc()) return; + + if (m_pcfsel < ARRAY_LENGTH(m_pcflushes)) + m_pcflushes[m_pcfsel++] = address; +} + + +/*------------------------------------------------- + sh2drc_add_fastram - add a new fastram + region +-------------------------------------------------*/ + +void sh2_device::sh2drc_add_fastram(offs_t start, offs_t end, uint8_t readonly, void *base) +{ + if (m_fastram_select < ARRAY_LENGTH(m_fastram)) + { + m_fastram[m_fastram_select].start = start; + m_fastram[m_fastram_select].end = end; + m_fastram[m_fastram_select].readonly = readonly; + m_fastram[m_fastram_select].base = base; + m_fastram_select++; + } +} diff --git a/src/devices/cpu/sh/sh2fe.cpp b/src/devices/cpu/sh/sh2fe.cpp new file mode 100644 index 00000000000..f6b409a0cd5 --- /dev/null +++ b/src/devices/cpu/sh/sh2fe.cpp @@ -0,0 +1,762 @@ +// license:BSD-3-Clause +// copyright-holders:R. Belmont +/*************************************************************************** + + sh2fe.c + + Front end for SH-2 recompiler + +***************************************************************************/ + +#include "emu.h" +#include "sh2.h" +#include "sh2comn.h" +#include "cpu/drcfe.h" + + +/*************************************************************************** + INSTRUCTION PARSERS +***************************************************************************/ + +sh2_frontend::sh2_frontend(sh2_device *device, uint32_t window_start, uint32_t window_end, uint32_t max_sequence) + : drc_frontend(*device, window_start, window_end, max_sequence) + , m_sh2(device) +{ +} + +/*------------------------------------------------- + describe_instruction - build a description + of a single instruction +-------------------------------------------------*/ + +bool sh2_frontend::describe(opcode_desc &desc, const opcode_desc *prev) +{ + uint16_t opcode; + + /* fetch the opcode */ + opcode = desc.opptr.w[0] = m_sh2->m_direct->read_word(desc.physpc, SH2_CODE_XOR(0)); + + /* all instructions are 2 bytes and most are a single cycle */ + desc.length = 2; + desc.cycles = 1; + + switch (opcode>>12) + { + case 0: + return describe_group_0(desc, prev, opcode); + + case 1: // MOVLS4 + desc.regin[0] |= REGFLAG_R(Rn) | REGFLAG_R(Rm); + desc.flags |= OPFLAG_WRITES_MEMORY; + return true; + + case 2: + return describe_group_2(desc, prev, opcode); + + case 3: + return describe_group_3(desc, prev, opcode); + + case 4: + return describe_group_4(desc, prev, opcode); + + case 5: // MOVLL4 + desc.regin[0] |= REGFLAG_R(Rm); + desc.regout[0] |= REGFLAG_R(Rn); + desc.flags |= OPFLAG_READS_MEMORY; + return true; + + case 6: + return describe_group_6(desc, prev, opcode); + + case 7: // ADDI + desc.regin[0] |= REGFLAG_R(Rn); + desc.regout[0] |= REGFLAG_R(Rn); + return true; + + case 8: + return describe_group_8(desc, prev, opcode); + + case 9: // MOVWI + desc.regout[0] |= REGFLAG_R(Rn); + desc.flags |= OPFLAG_READS_MEMORY; + return true; + + case 11: // BSR + desc.regout[1] |= REGFLAG_PR; + // (intentional fallthrough - BSR is BRA with the addition of PR = the return address) + case 10: // BRA + { + int32_t disp = ((int32_t)opcode << 20) >> 20; + + desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE; + desc.targetpc = (desc.pc + 2) + disp * 2 + 2; + desc.delayslots = 1; + desc.cycles = 2; + return true; + } + + case 12: + return describe_group_12(desc, prev, opcode); + + case 13: // MOVLI + desc.regout[0] |= REGFLAG_R(Rn); + desc.flags |= OPFLAG_READS_MEMORY; + return true; + + case 14: // MOVI + desc.regout[0] |= REGFLAG_R(Rn); + return true; + + case 15: // NOP + return true; + } + + return false; +} + +bool sh2_frontend::describe_group_0(opcode_desc &desc, const opcode_desc *prev, uint16_t opcode) +{ + switch (opcode & 0x3F) + { + case 0x00: // NOP(); + case 0x01: // NOP(); + case 0x09: // NOP(); + case 0x10: // NOP(); + case 0x11: // NOP(); + case 0x13: // NOP(); + case 0x20: // NOP(); + case 0x21: // NOP(); + case 0x30: // NOP(); + case 0x31: // NOP(); + case 0x32: // NOP(); + case 0x33: // NOP(); + case 0x38: // NOP(); + case 0x39: // NOP(); + case 0x3a: // NOP(); + case 0x3b: // NOP(); + return true; + + case 0x02: // STCSR(Rn); + desc.regout[0] |= REGFLAG_R(Rn); + return true; + + case 0x03: // BSRF(Rn); + desc.regout[1] |= REGFLAG_PR; + + desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE; + desc.targetpc = BRANCH_TARGET_DYNAMIC; + desc.delayslots = 1; + + return true; + + case 0x04: // MOVBS0(Rm, Rn); + case 0x05: // MOVWS0(Rm, Rn); + case 0x06: // MOVLS0(Rm, Rn); + case 0x14: // MOVBS0(Rm, Rn); + case 0x15: // MOVWS0(Rm, Rn); + case 0x16: // MOVLS0(Rm, Rn); + case 0x24: // MOVBS0(Rm, Rn); + case 0x25: // MOVWS0(Rm, Rn); + case 0x26: // MOVLS0(Rm, Rn); + case 0x34: // MOVBS0(Rm, Rn); + case 0x35: // MOVWS0(Rm, Rn); + case 0x36: // MOVLS0(Rm, Rn); + desc.regin[0] |= REGFLAG_R(Rm) | REGFLAG_R(Rn) | REGFLAG_R(0); + desc.flags |= OPFLAG_READS_MEMORY; + return true; + + case 0x07: // MULL(Rm, Rn); + case 0x17: // MULL(Rm, Rn); + case 0x27: // MULL(Rm, Rn); + case 0x37: // MULL(Rm, Rn); + desc.regin[0] |= REGFLAG_R(Rn) | REGFLAG_R(Rm); + desc.regout[1] |= REGFLAG_MACL; + desc.cycles = 2; + return true; + + case 0x08: // CLRT(); + desc.regout[1] |= REGFLAG_SR; + return true; + + case 0x0a: // STSMACH(Rn); + desc.regout[0] |= REGFLAG_R(Rn); + desc.regout[1] |= REGFLAG_MACH; + return true; + + case 0x0b: // RTS(); + desc.regin[1] |= REGFLAG_PR; + + desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE; + desc.targetpc = BRANCH_TARGET_DYNAMIC; + desc.delayslots = 1; + desc.cycles = 2; + + return true; + + case 0x0c: // MOVBL0(Rm, Rn); + case 0x0d: // MOVWL0(Rm, Rn); + case 0x0e: // MOVLL0(Rm, Rn); + case 0x1c: // MOVBL0(Rm, Rn); + case 0x1d: // MOVWL0(Rm, Rn); + case 0x1e: // MOVLL0(Rm, Rn); + case 0x2c: // MOVBL0(Rm, Rn); + case 0x2d: // MOVWL0(Rm, Rn); + case 0x2e: // MOVLL0(Rm, Rn); + case 0x3c: // MOVBL0(Rm, Rn); + case 0x3d: // MOVWL0(Rm, Rn); + case 0x3e: // MOVLL0(Rm, Rn); + desc.regin[0] |= REGFLAG_R(Rm) | REGFLAG_R(0); + desc.regout[0] |= REGFLAG_R(Rn); + desc.flags |= OPFLAG_READS_MEMORY; + return true; + + case 0x0f: // MAC_L(Rm, Rn); + case 0x1f: // MAC_L(Rm, Rn); + case 0x2f: // MAC_L(Rm, Rn); + case 0x3f: // MAC_L(Rm, Rn); + desc.regin[0] |= REGFLAG_R(Rm) | REGFLAG_R(Rn); + desc.regout[1] |= REGFLAG_MACL | REGFLAG_MACH; + desc.cycles = 3; + return true; + + case 0x12: // STCGBR(Rn); + desc.regout[0] |= REGFLAG_R(Rn); + desc.regin[1] |= REGFLAG_GBR; + return true; + + case 0x18: // SETT(); + desc.regout[1] |= REGFLAG_SR; + return true; + + case 0x19: // DIV0U(); + desc.regout[1] |= REGFLAG_SR; + return true; + + case 0x1a: // STSMACL(Rn); + desc.regin[1] |= REGFLAG_MACL; + desc.regout[0] |= REGFLAG_R(Rn); + return true; + + case 0x1b: // SLEEP(); + desc.cycles = 3; + return true; + + case 0x22: // STCVBR(Rn); + desc.regin[0] |= REGFLAG_R(Rn); + desc.regout[1] |= REGFLAG_VBR; + return true; + + case 0x23: // BRAF(Rn); + desc.regin[0] |= REGFLAG_R(Rm); + desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE; + desc.targetpc = BRANCH_TARGET_DYNAMIC; + desc.delayslots = 1; + desc.cycles = 2; + return true; + + case 0x28: // CLRMAC(); + desc.regout[1] |= REGFLAG_MACL | REGFLAG_MACH; + return true; + + case 0x29: // MOVT(Rn); + desc.regin[1] |= REGFLAG_SR; + desc.regout[0] |= REGFLAG_R(Rn); + return true; + + case 0x2a: // STSPR(Rn); + desc.regin[1] |= REGFLAG_PR; + desc.regout[0] |= REGFLAG_R(Rn); + return true; + + case 0x2b: // RTE(); + desc.regin[0] |= REGFLAG_R(15); + desc.regout[0] |= REGFLAG_R(15); + + desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE | OPFLAG_CAN_EXPOSE_EXTERNAL_INT; + desc.targetpc = BRANCH_TARGET_DYNAMIC; + desc.delayslots = 1; + desc.cycles = 4; + + return true; + } + + return false; +} + +bool sh2_frontend::describe_group_2(opcode_desc &desc, const opcode_desc *prev, uint16_t opcode) +{ + switch (opcode & 15) + { + case 0: // MOVBS(Rm, Rn); + case 1: // MOVWS(Rm, Rn); + case 2: // MOVLS(Rm, Rn); + desc.regin[0] |= REGFLAG_R(Rm) | REGFLAG_R(Rn); + desc.flags |= OPFLAG_WRITES_MEMORY; + return true; + + case 3: // NOP(); + return true; + + case 4: // MOVBM(Rm, Rn); + case 5: // MOVWM(Rm, Rn); + case 6: // MOVLM(Rm, Rn); + case 13: // XTRCT(Rm, Rn); + desc.regin[0] |= REGFLAG_R(Rm) | REGFLAG_R(Rn); + desc.regout[0] |= REGFLAG_R(Rn); + desc.flags |= OPFLAG_WRITES_MEMORY; + return true; + + case 7: // DIV0S(Rm, Rn); + case 8: // TST(Rm, Rn); + case 12: // CMPSTR(Rm, Rn); + desc.regin[0] |= REGFLAG_R(Rm) | REGFLAG_R(Rn); + desc.regout[1] |= REGFLAG_SR; + return true; + + case 9: // AND(Rm, Rn); + case 10: // XOR(Rm, Rn); + case 11: // OR(Rm, Rn); + desc.regin[0] |= REGFLAG_R(Rm) | REGFLAG_R(Rn); + desc.regout[0] |= REGFLAG_R(Rn); + return true; + + case 14: // MULU(Rm, Rn); + case 15: // MULS(Rm, Rn); + desc.regin[0] |= REGFLAG_R(Rm) | REGFLAG_R(Rn); + desc.regout[1] |= REGFLAG_MACL | REGFLAG_MACH; + desc.cycles = 2; + return true; + } + + return false; +} + +bool sh2_frontend::describe_group_3(opcode_desc &desc, const opcode_desc *prev, uint16_t opcode) +{ + switch (opcode & 15) + { + case 0: // CMPEQ(Rm, Rn); + case 2: // CMPHS(Rm, Rn); + case 3: // CMPGE(Rm, Rn); + case 6: // CMPHI(Rm, Rn); + case 7: // CMPGT(Rm, Rn); + desc.regin[0] |= REGFLAG_R(Rm) | REGFLAG_R(Rn); + desc.regout[1] |= REGFLAG_SR; + return true; + + case 1: // NOP(); + case 9: // NOP(); + return true; + + case 4: // DIV1(Rm, Rn); + desc.regin[0] |= REGFLAG_R(Rm) | REGFLAG_R(Rn); + desc.regout[0] |= REGFLAG_R(Rn); + desc.regout[1] |= REGFLAG_SR; + return true; + + case 5: // DMULU(Rm, Rn); + case 13: // DMULS(Rm, Rn); + desc.regin[0] |= REGFLAG_R(Rm) | REGFLAG_R(Rn); + desc.regout[1] |= REGFLAG_MACL | REGFLAG_MACH; + desc.cycles = 2; + return true; + + case 8: // SUB(Rm, Rn); + case 12: // ADD(Rm, Rn); + desc.regin[0] |= REGFLAG_R(Rm) | REGFLAG_R(Rn); + desc.regout[0] |= REGFLAG_R(Rn); + return true; + + case 10: // SUBC(Rm, Rn); + case 11: // SUBV(Rm, Rn); + case 14: // ADDC(Rm, Rn); + case 15: // ADDV(Rm, Rn); + desc.regin[0] |= REGFLAG_R(Rm) | REGFLAG_R(Rn); + desc.regin[1] |= REGFLAG_SR; + desc.regout[0] |= REGFLAG_R(Rn); + desc.regout[1] |= REGFLAG_SR; + return true; + } + return false; +} + +bool sh2_frontend::describe_group_4(opcode_desc &desc, const opcode_desc *prev, uint16_t opcode) +{ + switch (opcode & 0x3F) + { + case 0x00: // SHLL(Rn); + case 0x01: // SHLR(Rn); + case 0x04: // ROTL(Rn); + case 0x05: // ROTR(Rn); + desc.regin[0] |= REGFLAG_R(Rn); + desc.regout[0] |= REGFLAG_R(Rn); + desc.regout[1] |= REGFLAG_SR; + return true; + + case 0x02: // STSMMACH(Rn); + desc.regin[0] |= REGFLAG_R(Rn); + desc.regin[1] |= REGFLAG_MACH; + desc.regout[0] |= REGFLAG_R(Rn); + desc.flags |= OPFLAG_WRITES_MEMORY; + return true; + + case 0x03: // STCMSR(Rn); + desc.regin[0] |= REGFLAG_R(Rn); + desc.regout[0] |= REGFLAG_R(Rn); + desc.cycles = 2; + desc.flags |= OPFLAG_WRITES_MEMORY; + return true; + + case 0x06: // LDSMMACH(Rn); + desc.regin[0] |= REGFLAG_R(Rn); + desc.regout[0] |= REGFLAG_R(Rn); + desc.regout[1] |= REGFLAG_MACH; + desc.flags |= OPFLAG_READS_MEMORY; + return true; + + case 0x07: // LDCMSR(Rn); + desc.regin[0] |= REGFLAG_R(Rn); + desc.regout[0] |= REGFLAG_R(Rn); + desc.regout[1] |= REGFLAG_SR; + desc.cycles = 3; + desc.flags |= OPFLAG_READS_MEMORY | OPFLAG_CAN_EXPOSE_EXTERNAL_INT | OPFLAG_END_SEQUENCE; + return true; + + case 0x08: // SHLL2(Rn); + case 0x09: // SHLR2(Rn); + case 0x18: // SHLL8(Rn); + case 0x19: // SHLR8(Rn); + case 0x28: // SHLL16(Rn); + case 0x29: // SHLR16(Rn); + desc.regin[0] |= REGFLAG_R(Rn); + desc.regout[0] |= REGFLAG_R(Rn); + return true; + + case 0x0a: // LDSMACH(Rn); + desc.regin[0] |= REGFLAG_R(Rn); + desc.regout[1] |= REGFLAG_MACH; + return true; + + case 0x0b: // JSR(Rn); + desc.regin[0] |= REGFLAG_R(Rn); + desc.regout[1] |= REGFLAG_PR; + desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE; + desc.targetpc = BRANCH_TARGET_DYNAMIC; + desc.delayslots = 1; + return true; + + case 0x0e: // LDCSR(Rn); + desc.regin[0] |= REGFLAG_R(Rn); + desc.regout[1] |= REGFLAG_SR; + desc.flags |= OPFLAG_CAN_EXPOSE_EXTERNAL_INT | OPFLAG_END_SEQUENCE; + return true; + + case 0x0f: // MAC_W(Rm, Rn); + case 0x1f: // MAC_W(Rm, Rn); + case 0x2f: // MAC_W(Rm, Rn); + case 0x3f: // MAC_W(Rm, Rn); + desc.regin[0] |= REGFLAG_R(Rm) | REGFLAG_R(Rn); + desc.regin[1] |= REGFLAG_MACL | REGFLAG_MACH; + desc.regout[0] |= REGFLAG_R(Rm) | REGFLAG_R(Rn); + desc.regout[1] |= REGFLAG_MACL | REGFLAG_MACH; + desc.cycles = 3; + return true; + + case 0x10: // DT(Rn); + desc.regin[0] |= REGFLAG_R(Rn); + desc.regin[1] |= REGFLAG_SR; + desc.regout[0] |= REGFLAG_R(Rn); + desc.regout[1] |= REGFLAG_SR; + return true; + + case 0x11: // CMPPZ(Rn); + case 0x15: // CMPPL(Rn); + desc.regin[0] |= REGFLAG_R(Rn); + desc.regin[1] |= REGFLAG_SR; + desc.regout[1] |= REGFLAG_SR; + return true; + + case 0x12: // STSMMACL(Rn); + desc.regin[0] |= REGFLAG_R(Rn); + desc.regin[1] |= REGFLAG_MACL; + desc.regout[0] |= REGFLAG_R(Rn); + desc.flags |= OPFLAG_WRITES_MEMORY; + return true; + + case 0x13: // STCMGBR(Rn); + desc.regin[0] |= REGFLAG_R(Rn); + desc.regin[1] |= REGFLAG_GBR; + desc.regout[0] |= REGFLAG_R(Rn); + desc.flags |= OPFLAG_WRITES_MEMORY; + return true; + + case 0x16: // LDSMMACL(Rn); + desc.regin[0] |= REGFLAG_R(Rm) | REGFLAG_R(Rn); + desc.regout[0] |= REGFLAG_R(Rm) | REGFLAG_R(Rn); + desc.regout[1] |= REGFLAG_MACL; + desc.flags |= OPFLAG_READS_MEMORY; + return true; + + case 0x17: // LDCMGBR(Rn); + desc.regin[0] |= REGFLAG_R(Rn); + desc.regout[0] |= REGFLAG_R(Rn); + desc.regout[1] |= REGFLAG_GBR; + desc.flags |= OPFLAG_READS_MEMORY; + return true; + + case 0x1a: // LDSMACL(Rn); + desc.regin[0] |= REGFLAG_R(Rn); + desc.regout[1] |= REGFLAG_MACL; + return true; + + case 0x1b: // TAS(Rn); + desc.regin[0] |= REGFLAG_R(Rn); + desc.regin[1] |= REGFLAG_SR; + desc.regout[1] |= REGFLAG_SR; + desc.cycles = 4; + desc.flags |= OPFLAG_READS_MEMORY | OPFLAG_WRITES_MEMORY; + return true; + + case 0x1e: // LDCGBR(Rn); + desc.regin[0] |= REGFLAG_R(Rn); + desc.regout[1] |= REGFLAG_GBR; + return true; + + case 0x20: // SHAL(Rn); + case 0x21: // SHAR(Rn); + desc.regin[0] |= REGFLAG_R(Rn); + desc.regout[0] |= REGFLAG_R(Rn); + desc.regout[1] |= REGFLAG_SR; + return true; + + case 0x22: // STSMPR(Rn); + desc.regin[0] |= REGFLAG_R(Rn); + desc.regin[1] |= REGFLAG_PR; + desc.regout[0] |= REGFLAG_R(Rn); + desc.flags |= OPFLAG_WRITES_MEMORY; + return true; + + case 0x23: // STCMVBR(Rn); + desc.regin[0] |= REGFLAG_R(Rn); + desc.regin[1] |= REGFLAG_VBR; + desc.regout[0] |= REGFLAG_R(Rn); + desc.flags |= OPFLAG_WRITES_MEMORY; + return true; + + case 0x24: // ROTCL(Rn); + case 0x25: // ROTCR(Rn); + desc.regin[0] |= REGFLAG_R(Rn); + desc.regin[1] |= REGFLAG_SR; + desc.regout[0] |= REGFLAG_R(Rn); + desc.regout[1] |= REGFLAG_SR; + return true; + + case 0x26: // LDSMPR(Rn); + desc.regin[0] |= REGFLAG_R(Rn); + desc.regout[0] |= REGFLAG_R(Rn); + desc.regout[1] |= REGFLAG_PR; + desc.flags |= OPFLAG_READS_MEMORY; + return true; + + case 0x27: // LDCMVBR(Rn); + desc.regin[0] |= REGFLAG_R(Rn); + desc.regout[0] |= REGFLAG_R(Rn); + desc.regout[1] |= REGFLAG_VBR; + desc.flags |= OPFLAG_READS_MEMORY; + return true; + + case 0x2a: // LDSPR(Rn); + desc.regin[0] |= REGFLAG_R(Rn); + desc.regout[1] |= REGFLAG_PR; + return true; + + case 0x2b: // JMP(Rm); + desc.regin[0] |= REGFLAG_R(Rm); + desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE; + desc.targetpc = BRANCH_TARGET_DYNAMIC; + desc.delayslots = 1; + return true; + + case 0x2e: // LDCVBR(Rn); + desc.regin[0] |= REGFLAG_R(Rn); + desc.regout[1] |= REGFLAG_VBR; + return true; + + case 0x0c: // NOP(); + case 0x0d: // NOP(); + case 0x14: // NOP(); + case 0x1c: // NOP(); + case 0x1d: // NOP(); + case 0x2c: // NOP(); + case 0x2d: // NOP(); + case 0x30: // NOP(); + case 0x31: // NOP(); + case 0x32: // NOP(); + case 0x33: // NOP(); + case 0x34: // NOP(); + case 0x35: // NOP(); + case 0x36: // NOP(); + case 0x37: // NOP(); + case 0x38: // NOP(); + case 0x39: // NOP(); + case 0x3a: // NOP(); + case 0x3b: // NOP(); + case 0x3c: // NOP(); + case 0x3d: // NOP(); + case 0x3e: // NOP(); + return true; + } + + return false; +} + +bool sh2_frontend::describe_group_6(opcode_desc &desc, const opcode_desc *prev, uint16_t opcode) +{ + switch (opcode & 15) + { + case 0: // MOVBL(Rm, Rn); + case 1: // MOVWL(Rm, Rn); + case 2: // MOVLL(Rm, Rn); + case 3: // MOV(Rm, Rn); + case 7: // NOT(Rm, Rn); + case 9: // SWAPW(Rm, Rn); + case 11: // NEG(Rm, Rn); + case 12: // EXTUB(Rm, Rn); + case 13: // EXTUW(Rm, Rn); + case 14: // EXTSB(Rm, Rn); + case 15: // EXTSW(Rm, Rn); + desc.regin[0] |= REGFLAG_R(Rm); + desc.regout[0] |= REGFLAG_R(Rn); + return true; + + case 4: // MOVBP(Rm, Rn); + case 5: // MOVWP(Rm, Rn); + case 6: // MOVLP(Rm, Rn); + desc.regin[0] |= REGFLAG_R(Rm) | REGFLAG_R(Rn); + desc.regout[0] |= REGFLAG_R(Rn); + desc.flags |= OPFLAG_READS_MEMORY; + return true; + + case 8: // SWAPB(Rm, Rn); + desc.regin[0] |= REGFLAG_R(Rm) | REGFLAG_R(Rn); + desc.regout[0] |= REGFLAG_R(Rn); + return true; + + case 10: // NEGC(Rm, Rn); + desc.regin[0] |= REGFLAG_R(Rm); + desc.regout[0] |= REGFLAG_R(Rn); + desc.regout[1] |= REGFLAG_SR; + return true; + } + return false; +} + +bool sh2_frontend::describe_group_8(opcode_desc &desc, const opcode_desc *prev, uint16_t opcode) +{ + int32_t disp; + + switch ( opcode & (15<<8) ) + { + case 0 << 8: // MOVBS4(opcode & 0x0f, Rm); + case 1 << 8: // MOVWS4(opcode & 0x0f, Rm); + desc.regin[0] |= REGFLAG_R(Rm) | REGFLAG_R(0); + desc.flags |= OPFLAG_WRITES_MEMORY; + return true; + + case 2<< 8: // NOP(); + case 3<< 8: // NOP(); + case 6<< 8: // NOP(); + case 7<< 8: // NOP(); + case 10<< 8: // NOP(); + case 12<< 8: // NOP(); + case 14<< 8: // NOP(); + return true; + + case 4<< 8: // MOVBL4(Rm, opcode & 0x0f); + case 5<< 8: // MOVWL4(Rm, opcode & 0x0f); + desc.regin[0] |= REGFLAG_R(Rm); + desc.regout[0] |= REGFLAG_R(0); + desc.flags |= OPFLAG_READS_MEMORY; + return true; + + case 8<< 8: // CMPIM(opcode & 0xff); + desc.regin[0] |= REGFLAG_R(Rm); + desc.regin[1] |= REGFLAG_SR; + desc.regout[1] |= REGFLAG_SR; + return true; + + case 9<< 8: // BT(opcode & 0xff); + case 11<< 8: // BF(opcode & 0xff); + desc.flags |= OPFLAG_IS_CONDITIONAL_BRANCH; + desc.cycles = 3; + disp = ((int32_t)opcode << 24) >> 24; + desc.targetpc = (desc.pc + 2) + disp * 2 + 2; + return true; + + case 13<< 8: // BTS(opcode & 0xff); + case 15<< 8: // BFS(opcode & 0xff); + desc.flags |= OPFLAG_IS_CONDITIONAL_BRANCH; + desc.cycles = 2; + disp = ((int32_t)opcode << 24) >> 24; + desc.targetpc = (desc.pc + 2) + disp * 2 + 2; + desc.delayslots = 1; + return true; + } + + return false; +} + +bool sh2_frontend::describe_group_12(opcode_desc &desc, const opcode_desc *prev, uint16_t opcode) +{ + switch (opcode & (15<<8)) + { + case 0<<8: // MOVBSG(opcode & 0xff); + case 1<<8: // MOVWSG(opcode & 0xff); + case 2<<8: // MOVLSG(opcode & 0xff); + desc.regin[0] |= REGFLAG_R(0); + desc.flags |= OPFLAG_WRITES_MEMORY; + return true; + + case 3<<8: // TRAPA(opcode & 0xff); + desc.regin[0] |= REGFLAG_R(15); + desc.regin[1] |= REGFLAG_VBR; + desc.regout[0] |= REGFLAG_R(15); + desc.cycles = 8; + desc.targetpc = BRANCH_TARGET_DYNAMIC; + desc.flags |= OPFLAG_READS_MEMORY | OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE; + return true; + + case 4<<8: // MOVBLG(opcode & 0xff); + case 5<<8: // MOVWLG(opcode & 0xff); + case 6<<8: // MOVLLG(opcode & 0xff); + case 7<<8: // MOVA(opcode & 0xff); + desc.regout[0] |= REGFLAG_R(0); + desc.flags |= OPFLAG_READS_MEMORY; + return true; + + case 8<<8: // TSTI(opcode & 0xff); + desc.regin[0] |= REGFLAG_R(0); + desc.regin[1] |= REGFLAG_SR; + desc.regout[1] |= REGFLAG_SR; + return true; + + case 9<<8: // ANDI(opcode & 0xff); + case 10<<8: // XORI(opcode & 0xff); + case 11<<8: // ORI(opcode & 0xff); + desc.regin[0] |= REGFLAG_R(0); + desc.regout[0] |= REGFLAG_R(0); + return true; + + case 12<<8: // TSTM(opcode & 0xff); + case 13<<8: // ANDM(opcode & 0xff); + case 14<<8: // XORM(opcode & 0xff); + case 15<<8: // ORM(opcode & 0xff); + desc.regin[0] |= REGFLAG_R(0); + desc.regin[1] |= REGFLAG_SR | REGFLAG_GBR; + desc.regout[1] |= REGFLAG_SR; + desc.flags |= OPFLAG_READS_MEMORY; + return true; + } + + return false; +} diff --git a/src/devices/cpu/sh/sh3comn.cpp b/src/devices/cpu/sh/sh3comn.cpp new file mode 100644 index 00000000000..4a50e748eb9 --- /dev/null +++ b/src/devices/cpu/sh/sh3comn.cpp @@ -0,0 +1,681 @@ +// license:BSD-3-Clause +// copyright-holders:R. Belmont +/* Handlers for SH3 internals */ + +#include "emu.h" +#include "debugger.h" +#include "sh4.h" +#include "sh4comn.h" +#include "sh3comn.h" +#include "sh4tmu.h" +#include "sh4dmac.h" + +/* High internal area (ffffxxxx) */ + +WRITE32_MEMBER( sh3_base_device::sh3_internal_high_w ) +{ + COMBINE_DATA(&m_sh3internal_upper[offset]); + + switch (offset) + { + case SH3_ICR0_IPRA_ADDR: + if (mem_mask & 0xffff0000) + { + logerror("'%s' (%08x): INTC internal write to %08x = %08x & %08x (SH3_ICR0_IPRA_ADDR - ICR0)\n",tag(), m_pc & AM,(offset *4)+SH3_UPPER_REGBASE,data,mem_mask); + } + + if (mem_mask & 0x0000ffff) + { + logerror("'%s' (%08x): INTC internal write to %08x = %08x & %08x (SH3_ICR0_IPRA_ADDR - IPRA)\n",tag(), m_pc & AM,(offset *4)+SH3_UPPER_REGBASE,data,mem_mask); + sh4_handler_ipra_w(data&0xffff,mem_mask&0xffff); + } + + break; + + case SH3_IPRB_ADDR: + logerror("'%s' (%08x): INTC internal write to %08x = %08x & %08x (SH3_IPRB_ADDR)\n",tag(), m_pc & AM,(offset *4)+SH3_UPPER_REGBASE,data,mem_mask); + break; + + case SH3_TOCR_TSTR_ADDR: + logerror("'%s' (%08x): TMU internal write to %08x = %08x & %08x (SH3_TOCR_TSTR_ADDR)\n",tag(), m_pc & AM,(offset *4)+SH3_UPPER_REGBASE,data,mem_mask); + if (mem_mask&0xff000000) + { + sh4_handle_tocr_addr_w((data>>24)&0xffff, (mem_mask>>24)&0xff); + } + if (mem_mask&0x0000ff00) + { + sh4_handle_tstr_addr_w((data>>8)&0xff, (mem_mask>>8)&0xff); + } + if (mem_mask&0x00ff00ff) + { + fatalerror("SH3_TOCR_TSTR_ADDR unused bits accessed (write)\n"); + } + break; + case SH3_TCOR0_ADDR: sh4_handle_tcor0_addr_w(data, mem_mask);break; + case SH3_TCOR1_ADDR: sh4_handle_tcor1_addr_w(data, mem_mask);break; + case SH3_TCOR2_ADDR: sh4_handle_tcor2_addr_w(data, mem_mask);break; + case SH3_TCNT0_ADDR: sh4_handle_tcnt0_addr_w(data, mem_mask);break; + case SH3_TCNT1_ADDR: sh4_handle_tcnt1_addr_w(data, mem_mask);break; + case SH3_TCNT2_ADDR: sh4_handle_tcnt2_addr_w(data, mem_mask);break; + case SH3_TCR0_ADDR: sh4_handle_tcr0_addr_w(data>>16, mem_mask>>16);break; + case SH3_TCR1_ADDR: sh4_handle_tcr1_addr_w(data>>16, mem_mask>>16);break; + case SH3_TCR2_ADDR: sh4_handle_tcr2_addr_w(data>>16, mem_mask>>16);break; + case SH3_TCPR2_ADDR: sh4_handle_tcpr2_addr_w(data, mem_mask);break; + + default: + logerror("'%s' (%08x): unmapped internal write to %08x = %08x & %08x (unk)\n",tag(), m_pc & AM,(offset *4)+SH3_UPPER_REGBASE,data,mem_mask); + break; + + } + + + + +} + +READ32_MEMBER( sh3_base_device::sh3_internal_high_r ) +{ + uint32_t ret = 0; + + switch (offset) + { + case SH3_ICR0_IPRA_ADDR: + logerror("'%s' (%08x): INTC internal read from %08x mask %08x (SH3_ICR0_IPRA_ADDR - %08x)\n",tag(), m_pc & AM,(offset *4)+SH3_UPPER_REGBASE,mem_mask, m_sh3internal_upper[offset]); + return (m_sh3internal_upper[offset] & 0xffff0000) | (m_SH4_IPRA & 0xffff); + + case SH3_IPRB_ADDR: + logerror("'%s' (%08x): INTC internal read from %08x mask %08x (SH3_IPRB_ADDR - %08x)\n",tag(), m_pc & AM,(offset *4)+SH3_UPPER_REGBASE,mem_mask, m_sh3internal_upper[offset]); + return m_sh3internal_upper[offset]; + + case SH3_TOCR_TSTR_ADDR: + + if (mem_mask&0xff00000) + { + ret |= (sh4_handle_tocr_addr_r(mem_mask)&0xff)<<24; + } + if (mem_mask&0x0000ff00) + { + ret |= (sh4_handle_tstr_addr_r(mem_mask)&0xff)<<8; + } + if (mem_mask&0x00ff00ff) + { + fatalerror("SH3_TOCR_TSTR_ADDR unused bits accessed (read)\n"); + } + return ret; + case SH3_TCOR0_ADDR: return sh4_handle_tcor0_addr_r(mem_mask); + case SH3_TCOR1_ADDR: return sh4_handle_tcor1_addr_r(mem_mask); + case SH3_TCOR2_ADDR: return sh4_handle_tcor2_addr_r(mem_mask); + case SH3_TCNT0_ADDR: return sh4_handle_tcnt0_addr_r(mem_mask); + case SH3_TCNT1_ADDR: return sh4_handle_tcnt1_addr_r(mem_mask); + case SH3_TCNT2_ADDR: return sh4_handle_tcnt2_addr_r(mem_mask); + case SH3_TCR0_ADDR: return sh4_handle_tcr0_addr_r(mem_mask)<<16; + case SH3_TCR1_ADDR: return sh4_handle_tcr1_addr_r(mem_mask)<<16; + case SH3_TCR2_ADDR: return sh4_handle_tcr2_addr_r(mem_mask)<<16; + case SH3_TCPR2_ADDR: return sh4_handle_tcpr2_addr_r(mem_mask); + + + case SH3_TRA_ADDR: + logerror("'%s' (%08x): unmapped internal read from %08x mask %08x (SH3 TRA - %08x)\n",tag(), m_pc & AM,(offset *4)+SH3_UPPER_REGBASE,mem_mask, m_sh3internal_upper[offset]); + return m_sh3internal_upper[offset]; + + case SH3_EXPEVT_ADDR: + logerror("'%s' (%08x): unmapped internal read from %08x mask %08x (SH3 EXPEVT - %08x)\n",tag(), m_pc & AM,(offset *4)+SH3_UPPER_REGBASE,mem_mask, m_sh3internal_upper[offset]); + return m_sh3internal_upper[offset]; + + case SH3_INTEVT_ADDR: + logerror("'%s' (%08x): unmapped internal read from %08x mask %08x (SH3 INTEVT - %08x)\n",tag(), m_pc & AM,(offset *4)+SH3_UPPER_REGBASE,mem_mask, m_sh3internal_upper[offset]); + fatalerror("INTEVT unsupported on SH3\n"); + // never executed + //return m_sh3internal_upper[offset]; + + + default: + logerror("'%s' (%08x): unmapped internal read from %08x mask %08x\n",tag(), m_pc & AM,(offset *4)+SH3_UPPER_REGBASE,mem_mask); + return m_sh3internal_upper[offset]; + } +} + + +READ32_MEMBER( sh3_base_device::sh3_internal_r ) +{ + if (offset<0x1000) + { + switch (offset) + { + case SH3_SAR0_ADDR: return sh4_handle_sar0_addr_r(mem_mask); + case SH3_SAR1_ADDR: return sh4_handle_sar1_addr_r(mem_mask); + case SH3_SAR2_ADDR: return sh4_handle_sar2_addr_r(mem_mask); + case SH3_SAR3_ADDR: return sh4_handle_sar3_addr_r(mem_mask); + case SH3_DAR0_ADDR: return sh4_handle_dar0_addr_r(mem_mask); + case SH3_DAR1_ADDR: return sh4_handle_dar1_addr_r(mem_mask); + case SH3_DAR2_ADDR: return sh4_handle_dar2_addr_r(mem_mask); + case SH3_DAR3_ADDR: return sh4_handle_dar3_addr_r(mem_mask); + case SH3_DMATCR0_ADDR: return sh4_handle_dmatcr0_addr_r(mem_mask); + case SH3_DMATCR1_ADDR: return sh4_handle_dmatcr1_addr_r(mem_mask); + case SH3_DMATCR2_ADDR: return sh4_handle_dmatcr2_addr_r(mem_mask); + case SH3_DMATCR3_ADDR: return sh4_handle_dmatcr3_addr_r(mem_mask); + case SH3_CHCR0_ADDR: return sh4_handle_chcr0_addr_r(mem_mask); + case SH3_CHCR1_ADDR: return sh4_handle_chcr1_addr_r(mem_mask); + case SH3_CHCR2_ADDR: return sh4_handle_chcr2_addr_r(mem_mask); + case SH3_CHCR3_ADDR: return sh4_handle_chcr3_addr_r(mem_mask); + case SH3_DMAOR_ADDR: return sh4_handle_dmaor_addr_r(mem_mask)<<16; + + + case INTEVT2: + { + // logerror("'%s' (%08x): unmapped internal read from %08x mask %08x (INTEVT2)\n",tag(), m_pc & AM,(offset *4)+0x4000000,mem_mask); + return m_sh3internal_lower[offset]; + } + + + case IRR0_IRR1: + { + { + if (mem_mask & 0xff000000) + { + logerror("'%s' (%08x): unmapped internal read from %08x mask %08x (IRR0)\n",tag(), m_pc & AM,(offset *4)+0x4000000,mem_mask); + return m_sh3internal_lower[offset]; + } + + if (mem_mask & 0x0000ff00) + { + logerror("'%s' (%08x): unmapped internal read from %08x mask %08x (IRR1)\n",tag(), m_pc & AM,(offset *4)+0x4000000,mem_mask); + return m_sh3internal_lower[offset]; + } + + fatalerror("'%s' (%08x): unmapped internal read from %08x mask %08x (IRR0/1 unused bits)\n",tag(), m_pc & AM,(offset *4)+0x4000000,mem_mask); + } + } + + case PADR_PBDR: + { + if (mem_mask & 0xffff0000) + { + //logerror("'%s' (%08x): unmapped internal read from %08x mask %08x (PADR)\n",tag(), m_pc & AM,(offset *4)+0x4000000,mem_mask); + return m_io->read_qword(SH3_PORT_A)<<24; + } + + if (mem_mask & 0x0000ffff) + { + //logerror("'%s' (%08x): unmapped internal read from %08x mask %08x (PBDR)\n",tag(), m_pc & AM,(offset *4)+0x4000000,mem_mask); + return m_io->read_qword(SH3_PORT_B)<<8; + } + } + break; + + case PCDR_PDDR: + { + if (mem_mask & 0xffff0000) + { + //logerror("'%s' (%08x): unmapped internal read from %08x mask %08x (PCDR)\n",tag(), m_pc & AM,(offset *4)+0x4000000,mem_mask); + return m_io->read_qword(SH3_PORT_C)<<24; + } + + if (mem_mask & 0x0000ffff) + { + //logerror("'%s' (%08x): unmapped internal read from %08x mask %08x (PDDR)\n",tag(), m_pc & AM,(offset *4)+0x4000000,mem_mask); + return m_io->read_qword(SH3_PORT_D)<<8; + } + } + break; + + case PEDR_PFDR: + { + if (mem_mask & 0xffff0000) + { + //logerror("'%s' (%08x): unmapped internal read from %08x mask %08x (PEDR)\n",tag(), m_pc & AM,(offset *4)+0x4000000,mem_mask); + return m_io->read_qword(SH3_PORT_E)<<24; + } + + if (mem_mask & 0x0000ffff) + { + //logerror("'%s' (%08x): unmapped internal read from %08x mask %08x (PFDR)\n",tag(), m_pc & AM,(offset *4)+0x4000000,mem_mask); + return m_io->read_qword(SH3_PORT_F)<<8; + } + } + break; + + case PGDR_PHDR: + { + if (mem_mask & 0xffff0000) + { + //logerror("'%s' (%08x): unmapped internal read from %08x mask %08x (PGDR)\n",tag(), m_pc & AM,(offset *4)+0x4000000,mem_mask); + return m_io->read_qword(SH3_PORT_G)<<24; + } + + if (mem_mask & 0x0000ffff) + { + //logerror("'%s' (%08x): unmapped internal read from %08x mask %08x (PHDR)\n",tag(), m_pc & AM,(offset *4)+0x4000000,mem_mask); + return m_io->read_qword(SH3_PORT_H)<<8; + } + } + break; + + case PJDR_PKDR: + { + if (mem_mask & 0xffff0000) + { + //logerror("'%s' (%08x): unmapped internal read from %08x mask %08x (PJDR)\n",tag(), m_pc & AM,(offset *4)+0x4000000,mem_mask); + return m_io->read_qword(SH3_PORT_J)<<24; + } + + if (mem_mask & 0x0000ffff) + { + //logerror("'%s' (%08x): unmapped internal read from %08x mask %08x (PKDR)\n",tag(), m_pc & AM,(offset *4)+0x4000000,mem_mask); + return m_io->read_qword(SH3_PORT_K)<<8; + } + } + break; + + case PLDR_SCPDR: + { + if (mem_mask & 0xffff0000) + { + //logerror("'%s' (%08x): unmapped internal read from %08x mask %08x (PLDR)\n",tag(), m_pc & AM,(offset *4)+0x4000000,mem_mask); + return m_io->read_qword(SH3_PORT_L)<<24; + } + + if (mem_mask & 0x0000ffff) + { + logerror("'%s' (%08x): unmapped internal read from %08x mask %08x (SCPDR)\n",tag(), m_pc & AM,(offset *4)+0x4000000,mem_mask); + //return m_io->read_qword(SH3_PORT_K)<<8; + } + } + break; + + + case SCSMR2_SCBRR2: + { + if (mem_mask & 0xff000000) + { + logerror("'%s' (%08x): SCIF internal read from %08x mask %08x (SCSMR2 - Serial Mode Register 2)\n",tag(), m_pc & AM,(offset *4)+0x4000000,mem_mask); + return m_sh3internal_lower[offset]; + } + + if (mem_mask & 0x0000ff00) + { + logerror("'%s' (%08x): SCIF internal read from %08x mask %08x (SCBRR2 - Bit Rate Register 2)\n",tag(), m_pc & AM,(offset *4)+0x4000000,mem_mask); + return m_sh3internal_lower[offset]; + } + } + break; + + case SCSCR2_SCFTDR2: + { + if (mem_mask & 0xff000000) + { + logerror("'%s' (%08x): SCIF internal read from %08x mask %08x (SCSCR2 - Serial Control Register 2)\n",tag(), m_pc & AM,(offset *4)+0x4000000,mem_mask); + return m_sh3internal_lower[offset]; + } + + if (mem_mask & 0x0000ff00) + { + logerror("'%s' (%08x): SCIF internal read from %08x mask %08x (SCFTDR2 - Transmit FIFO Data Register 2)\n",tag(), m_pc & AM,(offset *4)+0x4000000,mem_mask); + return m_sh3internal_lower[offset]; + } + } + break; + + case SCSSR2_SCFRDR2: + { + if (mem_mask & 0xffff0000) + { + logerror("'%s' (%08x): SCIF internal read from %08x mask %08x (SCSSR2 - Serial Status Register 2)\n",tag(), m_pc & AM,(offset *4)+0x4000000,mem_mask); + return m_sh3internal_lower[offset]; + } + + if (mem_mask & 0x0000ff00) + { + logerror("'%s' (%08x): SCIF internal read from %08x mask %08x (SCFRDR2 - Receive FIFO Data Register 2)\n",tag(), m_pc & AM,(offset *4)+0x4000000,mem_mask); + return m_sh3internal_lower[offset]; + } + } + break; + + case SCFCR2_SCFDR2: + { + if (mem_mask & 0xff000000) + { + logerror("'%s' (%08x): SCIF internal read from %08x mask %08x (SCFCR2 - Fifo Control Register 2)\n",tag(), m_pc & AM,(offset *4)+0x4000000,mem_mask); + return m_sh3internal_lower[offset]; + } + + if (mem_mask & 0x0000ffff) + { + logerror("'%s' (%08x): SCIF internal read from %08x mask %08x (SCFDR2 - Fifo Data Count Register 2)\n",tag(), m_pc & AM,(offset *4)+0x4000000,mem_mask); + return m_sh3internal_lower[offset]; + } + } + break; + + + default: + { + logerror("'%s' (%08x): unmapped internal read from %08x mask %08x\n", + tag(), m_pc & AM, + (offset *4)+0x4000000, + mem_mask); + } + break; + + } + + } + else + { + logerror("'%s' (%08x): unmapped internal read from %08x mask %08x\n", + tag(), m_pc & AM, + (offset *4)+0x4000000, + mem_mask); + } + + return 0; +} + +/* Lower internal area */ + +WRITE32_MEMBER( sh3_base_device::sh3_internal_w ) +{ + if (offset<0x1000) + { + //uint32_t old = m_sh3internal_lower[offset]; + COMBINE_DATA(&m_sh3internal_lower[offset]); + + switch (offset) + { + case SH3_SAR0_ADDR: sh4_handle_sar0_addr_w(data,mem_mask); break; + case SH3_SAR1_ADDR: sh4_handle_sar1_addr_w(data,mem_mask); break; + case SH3_SAR2_ADDR: sh4_handle_sar2_addr_w(data,mem_mask); break; + case SH3_SAR3_ADDR: sh4_handle_sar3_addr_w(data,mem_mask); break; + case SH3_DAR0_ADDR: sh4_handle_dar0_addr_w(data,mem_mask); break; + case SH3_DAR1_ADDR: sh4_handle_dar1_addr_w(data,mem_mask); break; + case SH3_DAR2_ADDR: sh4_handle_dar2_addr_w(data,mem_mask); break; + case SH3_DAR3_ADDR: sh4_handle_dar3_addr_w(data,mem_mask); break; + case SH3_DMATCR0_ADDR: sh4_handle_dmatcr0_addr_w(data,mem_mask); break; + case SH3_DMATCR1_ADDR: sh4_handle_dmatcr1_addr_w(data,mem_mask); break; + case SH3_DMATCR2_ADDR: sh4_handle_dmatcr2_addr_w(data,mem_mask); break; + case SH3_DMATCR3_ADDR: sh4_handle_dmatcr3_addr_w(data,mem_mask); break; + case SH3_CHCR0_ADDR: sh4_handle_chcr0_addr_w(data,mem_mask); break; + case SH3_CHCR1_ADDR: sh4_handle_chcr1_addr_w(data,mem_mask); break; + case SH3_CHCR2_ADDR: sh4_handle_chcr2_addr_w(data,mem_mask); break; + case SH3_CHCR3_ADDR: sh4_handle_chcr3_addr_w(data,mem_mask); break; + case SH3_DMAOR_ADDR: sh4_handle_dmaor_addr_w(data>>16,mem_mask>>16); break; + + + case IRR0_IRR1: + { + { + if (mem_mask & 0xff000000) + { + logerror("'%s' (%08x): unmapped internal write to %08x = %08x & %08x (IRR0)\n",tag(), m_pc & AM,(offset *4)+0x4000000,data,mem_mask); + // not sure if this is how we should clear lines in this core... + if (!(data & 0x01000000)) execute_set_input(0, CLEAR_LINE); + if (!(data & 0x02000000)) execute_set_input(1, CLEAR_LINE); + if (!(data & 0x04000000)) execute_set_input(2, CLEAR_LINE); + if (!(data & 0x08000000)) execute_set_input(3, CLEAR_LINE); + + } + if (mem_mask & 0x0000ff00) + { + logerror("'%s' (%08x): unmapped internal write to %08x = %08x & %08x (IRR1)\n",tag(), m_pc & AM,(offset *4)+0x4000000,data,mem_mask); + } + if (mem_mask & 0x00ff00ff) + { + fatalerror("'%s' (%08x): unmapped internal write to %08x = %08x & %08x (IRR0/1 unused bits)\n",tag(), m_pc & AM,(offset *4)+0x4000000,data,mem_mask); + } + } + } + break; + + case PINTER_IPRC: + { + if (mem_mask & 0xffff0000) + { + logerror("'%s' (%08x): unmapped internal write to %08x = %08x & %08x (PINTER)\n",tag(), m_pc & AM,(offset *4)+0x4000000,data,mem_mask); + } + + if (mem_mask & 0x0000ffff) + { + data &= 0xffff; mem_mask &= 0xffff; + COMBINE_DATA(&m_SH4_IPRC); + logerror("'%s' (%08x): INTC internal write to %08x = %08x & %08x (IPRC)\n",tag(), m_pc & AM,(offset *4)+0x4000000,data,mem_mask); + m_exception_priority[SH4_INTC_IRL0] = INTPRI((m_SH4_IPRC & 0x000f)>>0, SH4_INTC_IRL0); + m_exception_priority[SH4_INTC_IRL1] = INTPRI((m_SH4_IPRC & 0x00f0)>>4, SH4_INTC_IRL1); + m_exception_priority[SH4_INTC_IRL2] = INTPRI((m_SH4_IPRC & 0x0f00)>>8, SH4_INTC_IRL2); + m_exception_priority[SH4_INTC_IRL3] = INTPRI((m_SH4_IPRC & 0xf000)>>12,SH4_INTC_IRL3); + sh4_exception_recompute(); + } + } + break; + + case PCCR_PDCR: + { + if (mem_mask & 0xffff0000) + { + logerror("'%s' (%08x): unmapped internal write to %08x = %08x & %08x (PCCR)\n",tag(), m_pc & AM,(offset *4)+0x4000000,data,mem_mask); + } + + if (mem_mask & 0x0000ffff) + { + logerror("'%s' (%08x): unmapped internal write to %08x = %08x & %08x (PDCR)\n",tag(), m_pc & AM,(offset *4)+0x4000000,data,mem_mask); + } + } + break; + + case PECR_PFCR: + { + if (mem_mask & 0xffff0000) + { + logerror("'%s' (%08x): unmapped internal write to %08x = %08x & %08x (PECR)\n",tag(), m_pc & AM,(offset *4)+0x4000000,data,mem_mask); + } + + if (mem_mask & 0x0000ffff) + { + logerror("'%s' (%08x): unmapped internal write to %08x = %08x & %08x (PFCR)\n",tag(), m_pc & AM,(offset *4)+0x4000000,data,mem_mask); + } + } + break; + + + case PGCR_PHCR: + { + if (mem_mask & 0xffff0000) + { + logerror("'%s' (%08x): unmapped internal write to %08x = %08x & %08x (PGCR)\n",tag(), m_pc & AM,(offset *4)+0x4000000,data,mem_mask); + } + + if (mem_mask & 0x0000ffff) + { + logerror("'%s' (%08x): unmapped internal write to %08x = %08x & %08x (PHCR)\n",tag(), m_pc & AM,(offset *4)+0x4000000,data,mem_mask); + } + } + break; + + + case PJCR_PKCR: + { + if (mem_mask & 0xffff0000) + { + logerror("'%s' (%08x): unmapped internal write to %08x = %08x & %08x (PJCR)\n",tag(), m_pc & AM,(offset *4)+0x4000000,data,mem_mask); + } + + if (mem_mask & 0x0000ffff) + { + logerror("'%s' (%08x): unmapped internal write to %08x = %08x & %08x (PKCR)\n",tag(), m_pc & AM,(offset *4)+0x4000000,data,mem_mask); + } + } + break; + + + case PLCR_SCPCR: + { + if (mem_mask & 0xffff0000) + { + logerror("'%s' (%08x): unmapped internal write to %08x = %08x & %08x (PLCR)\n",tag(), m_pc & AM,(offset *4)+0x4000000,data,mem_mask); + } + + if (mem_mask & 0x0000ffff) + { + logerror("'%s' (%08x): unmapped internal write to %08x = %08x & %08x (SCPCR)\n",tag(), m_pc & AM,(offset *4)+0x4000000,data,mem_mask); + } + } + break; + + case PADR_PBDR: + { + if (mem_mask & 0xffff0000) + { + m_io->write_qword(SH3_PORT_A, (data>>24)&0xff); + // logerror("'%s' (%08x): unmapped internal write to %08x = %08x & %08x (PADR)\n",tag(), m_pc & AM,(offset *4)+0x4000000,data,mem_mask); + } + + if (mem_mask & 0x0000ffff) + { + m_io->write_qword(SH3_PORT_B, (data>>8)&0xff); + // logerror("'%s' (%08x): unmapped internal write to %08x = %08x & %08x (PBDR)\n",tag(), m_pc & AM,(offset *4)+0x4000000,data,mem_mask); + } + } + break; + + case PCDR_PDDR: + { + if (mem_mask & 0xffff0000) + { + m_io->write_qword(SH3_PORT_C, (data>>24)&0xff); + // logerror("'%s' (%08x): unmapped internal write to %08x = %08x & %08x (PADR)\n",tag(), m_pc & AM,(offset *4)+0x4000000,data,mem_mask); + } + + if (mem_mask & 0x0000ffff) + { + m_io->write_qword(SH3_PORT_D, (data>>8)&0xff); + // logerror("'%s' (%08x): unmapped internal write to %08x = %08x & %08x (PBDR)\n",tag(), m_pc & AM,(offset *4)+0x4000000,data,mem_mask); + } + } + break; + case PEDR_PFDR: + { + if (mem_mask & 0xffff0000) + { + m_io->write_qword(SH3_PORT_E, (data>>24)&0xff); + // logerror("'%s' (%08x): unmapped internal write to %08x = %08x & %08x (PEDR)\n",tag(), m_pc & AM,(offset *4)+0x4000000,data,mem_mask); + } + + if (mem_mask & 0x0000ffff) + { + m_io->write_qword(SH3_PORT_F, (data>>8)&0xff); + // logerror("'%s' (%08x): unmapped internal write to %08x = %08x & %08x (PFDR)\n",tag(), m_pc & AM,(offset *4)+0x4000000,data,mem_mask); + } + } + break; + + case PGDR_PHDR: + { + if (mem_mask & 0xffff0000) + { + m_io->write_qword(SH3_PORT_G, (data>>24)&0xff); + // logerror("'%s' (%08x): unmapped internal write to %08x = %08x & %08x (PGDR)\n",tag(), m_pc & AM,(offset *4)+0x4000000,data,mem_mask); + } + + if (mem_mask & 0x0000ffff) + { + m_io->write_qword(SH3_PORT_H, (data>>8)&0xff); + // logerror("'%s' (%08x): unmapped internal write to %08x = %08x & %08x (PHDR)\n",tag(), m_pc & AM,(offset *4)+0x4000000,data,mem_mask); + } + } + break; + + + case PJDR_PKDR: + { + if (mem_mask & 0xffff0000) + { + m_io->write_qword(SH3_PORT_J, (data>>24)&0xff); + // logerror("'%s' (%08x): unmapped internal write to %08x = %08x & %08x (PJDR)\n",tag(), m_pc & AM,(offset *4)+0x4000000,data,mem_mask); + } + + if (mem_mask & 0x0000ffff) + { + m_io->write_qword(SH3_PORT_K, (data>>8)&0xff); + //logerror("'%s' (%08x): unmapped internal write to %08x = %08x & %08x (PKDR)\n",tag(), m_pc & AM,(offset *4)+0x4000000,data,mem_mask); + } + } + break; + + case SCSMR2_SCBRR2: + { + if (mem_mask & 0xff000000) + { + logerror("'%s' (%08x): SCIF internal write to %08x = %08x & %08x (SCSMR2 - Serial Mode Register 2)\n",tag(), m_pc & AM,(offset *4)+0x4000000,data,mem_mask); + } + + if (mem_mask & 0x0000ff00) + { + logerror("'%s' (%08x): SCIF internal write to %08x = %08x & %08x (SCBRR2 - Bit Rate Register 2)\n",tag(), m_pc & AM,(offset *4)+0x4000000,data,mem_mask); + } + } + break; + + case SCSCR2_SCFTDR2: + { + if (mem_mask & 0xff000000) + { + logerror("'%s' (%08x): SCIF internal write to %08x = %08x & %08x (SCSCR2 - Serial Control Register 2)\n",tag(), m_pc & AM,(offset *4)+0x4000000,data,mem_mask); + } + + if (mem_mask & 0x0000ff00) + { + logerror("'%s' (%08x): SCIF internal write to %08x = %08x & %08x (SCFTDR2 - Transmit FIFO Data Register 2)\n",tag(), m_pc & AM,(offset *4)+0x4000000,data,mem_mask); + } + } + break; + + case SCSSR2_SCFRDR2: + { + if (mem_mask & 0xffff0000) + { + logerror("'%s' (%08x): SCIF internal write to %08x = %08x & %08x (SCSSR2 - Serial Status Register 2)\n",tag(), m_pc & AM,(offset *4)+0x4000000,data,mem_mask); + } + + if (mem_mask & 0x0000ff00) + { + logerror("'%s' (%08x): SCIF internal write to %08x = %08x & %08x (SCFRDR2 - Receive FIFO Data Register 2)\n",tag(), m_pc & AM,(offset *4)+0x4000000,data,mem_mask); + } + } + break; + + case SCFCR2_SCFDR2: + { + if (mem_mask & 0xff000000) + { + logerror("'%s' (%08x): SCIF internal write to %08x = %08x & %08x (SCFCR2 - Fifo Control Register 2)\n",tag(), m_pc & AM,(offset *4)+0x4000000,data,mem_mask); + } + + if (mem_mask & 0x0000ffff) + { + logerror("'%s' (%08x): SCIF internal write to %08x = %08x & %08x (SCFDR2 - Fifo Data Count Register 2)\n",tag(), m_pc & AM,(offset *4)+0x4000000,data,mem_mask); + } + } + break; + + default: + { + logerror("'%s' (%08x): unmapped internal write to %08x = %08x & %08x\n", + tag(), m_pc & AM, + (offset *4)+0x4000000, + data, + mem_mask); + } + break; + } + + } + else + { + logerror("'%s' (%08x): unmapped internal write to %08x = %08x & %08x\n", + tag(), m_pc & AM, + (offset *4)+0x4000000, + data, + mem_mask); + } + +} diff --git a/src/devices/cpu/sh/sh3comn.h b/src/devices/cpu/sh/sh3comn.h new file mode 100644 index 00000000000..241035b993e --- /dev/null +++ b/src/devices/cpu/sh/sh3comn.h @@ -0,0 +1,96 @@ +// license:BSD-3-Clause +// copyright-holders:R. Belmont +#pragma once + +#ifndef __SH3COMN_H__ +#define __SH3COMN_H__ + + +// actual port handling is more complex than this +// which should be considered a temporary solution +// just used some arbitrary port numbers +#define SH3_PORT_A (0x10*8) +#define SH3_PORT_B (0x11*8) +#define SH3_PORT_C (0x12*8) +#define SH3_PORT_D (0x13*8) +#define SH3_PORT_E (0x14*8) +#define SH3_PORT_F (0x15*8) +#define SH3_PORT_G (0x16*8) +#define SH3_PORT_H (0x17*8) +/* no I */ +#define SH3_PORT_J (0x18*8) +#define SH3_PORT_K (0x19*8) +#define SH3_PORT_L (0x1a*8) + +/* SH3 lower area regs */ + +#define SH3_LOWER_REGBASE (0x04000000) +#define SH3_LOWER_REGEND (0x07ffffff) + +#define INTEVT2 ((0x4000000 - SH3_LOWER_REGBASE)/4) +#define IRR0_IRR1 ((0x4000004 - SH3_LOWER_REGBASE)/4) +#define PINTER_IPRC ((0x4000014 - SH3_LOWER_REGBASE)/4) + +#define SH3_SAR0_ADDR ((0x4000020 - SH3_LOWER_REGBASE)/4) +#define SH3_DAR0_ADDR ((0x4000024 - SH3_LOWER_REGBASE)/4) +#define SH3_DMATCR0_ADDR ((0x4000028 - SH3_LOWER_REGBASE)/4) +#define SH3_CHCR0_ADDR ((0x400002c - SH3_LOWER_REGBASE)/4) +#define SH3_SAR1_ADDR ((0x4000030 - SH3_LOWER_REGBASE)/4) +#define SH3_DAR1_ADDR ((0x4000034 - SH3_LOWER_REGBASE)/4) +#define SH3_DMATCR1_ADDR ((0x4000038 - SH3_LOWER_REGBASE)/4) +#define SH3_CHCR1_ADDR ((0x400003c - SH3_LOWER_REGBASE)/4) +#define SH3_SAR2_ADDR ((0x4000040 - SH3_LOWER_REGBASE)/4) +#define SH3_DAR2_ADDR ((0x4000044 - SH3_LOWER_REGBASE)/4) +#define SH3_DMATCR2_ADDR ((0x4000048 - SH3_LOWER_REGBASE)/4) +#define SH3_CHCR2_ADDR ((0x400004c - SH3_LOWER_REGBASE)/4) +#define SH3_SAR3_ADDR ((0x4000050 - SH3_LOWER_REGBASE)/4) +#define SH3_DAR3_ADDR ((0x4000054 - SH3_LOWER_REGBASE)/4) +#define SH3_DMATCR3_ADDR ((0x4000058 - SH3_LOWER_REGBASE)/4) +#define SH3_CHCR3_ADDR ((0x400005c - SH3_LOWER_REGBASE)/4) +#define SH3_DMAOR_ADDR ((0x4000060 - SH3_LOWER_REGBASE)/4) + + +#define PCCR_PDCR ((0x4000104 - SH3_LOWER_REGBASE)/4) +#define PECR_PFCR ((0x4000108 - SH3_LOWER_REGBASE)/4) +#define PGCR_PHCR ((0x400010c - SH3_LOWER_REGBASE)/4) +#define PJCR_PKCR ((0x4000110 - SH3_LOWER_REGBASE)/4) +#define PLCR_SCPCR ((0x4000114 - SH3_LOWER_REGBASE)/4) + +#define PADR_PBDR ((0x4000120 - SH3_LOWER_REGBASE)/4) +#define PCDR_PDDR ((0x4000124 - SH3_LOWER_REGBASE)/4) +#define PEDR_PFDR ((0x4000128 - SH3_LOWER_REGBASE)/4) +#define PGDR_PHDR ((0x400012c - SH3_LOWER_REGBASE)/4) +#define PJDR_PKDR ((0x4000130 - SH3_LOWER_REGBASE)/4) +#define PLDR_SCPDR ((0x4000134 - SH3_LOWER_REGBASE)/4) + +#define SCSMR2_SCBRR2 ((0x4000150 - SH3_LOWER_REGBASE)/4) +#define SCSCR2_SCFTDR2 ((0x4000154 - SH3_LOWER_REGBASE)/4) +#define SCSSR2_SCFRDR2 ((0x4000158 - SH3_LOWER_REGBASE)/4) +#define SCFCR2_SCFDR2 ((0x400015c - SH3_LOWER_REGBASE)/4) + + +/* SH3 upper area */ + + +#define SH3_UPPER_REGBASE (0xffffd000) +#define SH3_UPPER_REGEND (0xffffffff) + +#define SH3_ICR0_IPRA_ADDR ((0xfffffee0 - SH3_UPPER_REGBASE)/4) +#define SH3_IPRB_ADDR ((0xfffffee4 - SH3_UPPER_REGBASE)/4) + +#define SH3_TOCR_TSTR_ADDR ((0xfffffe90 - SH3_UPPER_REGBASE)/4) +#define SH3_TCOR0_ADDR ((0xfffffe94 - SH3_UPPER_REGBASE)/4) +#define SH3_TCNT0_ADDR ((0xfffffe98 - SH3_UPPER_REGBASE)/4) +#define SH3_TCR0_ADDR ((0xfffffe9c - SH3_UPPER_REGBASE)/4) +#define SH3_TCOR1_ADDR ((0xfffffea0 - SH3_UPPER_REGBASE)/4) +#define SH3_TCNT1_ADDR ((0xfffffea4 - SH3_UPPER_REGBASE)/4) +#define SH3_TCR1_ADDR ((0xfffffea8 - SH3_UPPER_REGBASE)/4) +#define SH3_TCOR2_ADDR ((0xfffffeac - SH3_UPPER_REGBASE)/4) +#define SH3_TCNT2_ADDR ((0xfffffeb0 - SH3_UPPER_REGBASE)/4) +#define SH3_TCR2_ADDR ((0xfffffeb4 - SH3_UPPER_REGBASE)/4) +#define SH3_TCPR2_ADDR ((0xfffffeb8 - SH3_UPPER_REGBASE)/4) +#define SH3_TRA_ADDR ((0xffffffd0 - SH3_UPPER_REGBASE)/4) +#define SH3_EXPEVT_ADDR ((0xffffffd4 - SH3_UPPER_REGBASE)/4) +#define SH3_INTEVT_ADDR ((0xffffffd8 - SH3_UPPER_REGBASE)/4) + +#endif /* __SH3COMN_H__ */ diff --git a/src/devices/cpu/sh/sh4.cpp b/src/devices/cpu/sh/sh4.cpp new file mode 100644 index 00000000000..cc7c333d9cc --- /dev/null +++ b/src/devices/cpu/sh/sh4.cpp @@ -0,0 +1,4743 @@ +// license:BSD-3-Clause +// copyright-holders:R. Belmont +/***************************************************************************** + * + * sh4.c + * Portable Hitachi SH-4 (SH7750 family) emulator + * + * By R. Belmont, based on sh2.c by Juergen Buchmueller, Mariusz Wojcieszek, + * Olivier Galibert, Sylvain Glaize, and James Forshaw. + * + * + * TODO: FPU + * DMA + * on-board peripherals + * + * DONE: boot/reset setup + * 64-bit data bus + * banked registers + * additional registers for supervisor mode + * FPU status and data registers + * state save for the new registers + * interrupts + * store queues + * + *****************************************************************************/ + +#include "emu.h" +#include "sh4.h" +#include "sh4regs.h" +#include "sh4comn.h" +#include "sh3comn.h" +#include "sh4tmu.h" + +#include "debugger.h" + + +#if SH4_USE_FASTRAM_OPTIMIZATION +void sh34_base_device::add_fastram(offs_t start, offs_t end, uint8_t readonly, void *base) +{ + if (m_fastram_select < ARRAY_LENGTH(m_fastram)) + { + m_fastram[m_fastram_select].start = start; + m_fastram[m_fastram_select].end = end; + m_fastram[m_fastram_select].readonly = readonly; + m_fastram[m_fastram_select].base = base; + m_fastram_select++; + } +} +#else +void sh34_base_device::add_fastram(offs_t start, offs_t end, uint8_t readonly, void *base) +{ +} +#endif + + +CPU_DISASSEMBLE( sh4 ); +CPU_DISASSEMBLE( sh4be ); + + +DEFINE_DEVICE_TYPE(SH3LE, sh3_device, "sh3le", "SH-3 (little)") +DEFINE_DEVICE_TYPE(SH3BE, sh3be_device, "sh3be", "SH-3 (big)") +DEFINE_DEVICE_TYPE(SH4LE, sh4_device, "sh4le", "SH-4 (little)") +DEFINE_DEVICE_TYPE(SH4BE, sh4be_device, "sh4be", "SH-4 (big)") + + +#if 0 +/*When OC index mode is off (CCR.OIX = 0)*/ +static ADDRESS_MAP_START( sh4_internal_map, AS_PROGRAM, 64, sh4_base_device ) + AM_RANGE(0x1C000000, 0x1C000FFF) AM_RAM AM_MIRROR(0x03FFD000) + AM_RANGE(0x1C002000, 0x1C002FFF) AM_RAM AM_MIRROR(0x03FFD000) + AM_RANGE(0xE0000000, 0xE000003F) AM_RAM AM_MIRROR(0x03FFFFC0) +ADDRESS_MAP_END +#endif + +/*When OC index mode is on (CCR.OIX = 1)*/ +static ADDRESS_MAP_START( sh4_internal_map, AS_PROGRAM, 64, sh4_base_device ) + AM_RANGE(0x1C000000, 0x1C000FFF) AM_RAM AM_MIRROR(0x01FFF000) + AM_RANGE(0x1E000000, 0x1E000FFF) AM_RAM AM_MIRROR(0x01FFF000) + AM_RANGE(0xE0000000, 0xE000003F) AM_RAM AM_MIRROR(0x03FFFFC0) // todo: store queues should be write only on DC's SH4, executing PREFM shouldn't cause an actual memory read access! + + AM_RANGE(0xF6000000, 0xF6FFFFFF) AM_READWRITE(sh4_utlb_address_array_r,sh4_utlb_address_array_w) + AM_RANGE(0xF7000000, 0xF77FFFFF) AM_READWRITE(sh4_utlb_data_array1_r,sh4_utlb_data_array1_w) + AM_RANGE(0xF7800000, 0xF7FFFFFF) AM_READWRITE(sh4_utlb_data_array2_r,sh4_utlb_data_array2_w) + + AM_RANGE(0xFE000000, 0xFFFFFFFF) AM_READWRITE32(sh4_internal_r, sh4_internal_w, 0xffffffffffffffffU) +ADDRESS_MAP_END + +static ADDRESS_MAP_START( sh3_internal_map, AS_PROGRAM, 64, sh3_base_device ) + AM_RANGE(SH3_LOWER_REGBASE, SH3_LOWER_REGEND) AM_READWRITE32(sh3_internal_r, sh3_internal_w, 0xffffffffffffffffU) + AM_RANGE(SH3_UPPER_REGBASE, SH3_UPPER_REGEND) AM_READWRITE32(sh3_internal_high_r, sh3_internal_high_w, 0xffffffffffffffffU) +ADDRESS_MAP_END + + +sh34_base_device::sh34_base_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, endianness_t endianness, address_map_constructor internal) + : cpu_device(mconfig, type, tag, owner, clock) + , m_program_config("program", endianness, 64, 32, 0, internal) + , m_io_config("io", endianness, 64, 8) + , c_md2(0) + , c_md1(0) + , c_md0(0) + , c_md6(0) + , c_md4(0) + , c_md3(0) + , c_md5(0) + , c_md7(0) + , c_md8(0) + , c_clock(0) + , m_mmuhack(1) +#if SH4_USE_FASTRAM_OPTIMIZATION + , m_bigendian(endianness == ENDIANNESS_BIG) + , m_byte_xor(m_bigendian ? BYTE8_XOR_BE(0) : BYTE8_XOR_LE(0)) + , m_word_xor(m_bigendian ? WORD2_XOR_BE(0) : WORD2_XOR_LE(0)) + , m_dword_xor(m_bigendian ? DWORD_XOR_BE(0) : DWORD_XOR_LE(0)) + , m_fastram_select(0) +#endif +{ +#if SH4_USE_FASTRAM_OPTIMIZATION + memset(m_fastram, 0, sizeof(m_fastram)); +#endif +} + +device_memory_interface::space_config_vector sh34_base_device::memory_space_config() const +{ + return space_config_vector { + std::make_pair(AS_PROGRAM, &m_program_config), + std::make_pair(AS_IO, &m_io_config) + }; +} + + +sh3_base_device::sh3_base_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, endianness_t endianness) + : sh34_base_device(mconfig, type, tag, owner, clock, endianness, ADDRESS_MAP_NAME(sh3_internal_map)) +{ + m_cpu_type = CPU_TYPE_SH3; +} + + +sh4_base_device::sh4_base_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, endianness_t endianness) + : sh34_base_device(mconfig, type, tag, owner, clock, endianness, ADDRESS_MAP_NAME(sh4_internal_map)) +{ + m_cpu_type = CPU_TYPE_SH4; +} + + +sh3_device::sh3_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : sh3_base_device(mconfig, SH3LE, tag, owner, clock, ENDIANNESS_LITTLE) +{ +} + + +sh3be_device::sh3be_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : sh3_base_device(mconfig, SH3BE, tag, owner, clock, ENDIANNESS_BIG) +{ +} + + +sh4_device::sh4_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : sh4_base_device(mconfig, SH4LE, tag, owner, clock, ENDIANNESS_LITTLE) +{ +} + + +sh4be_device::sh4be_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : sh4_base_device(mconfig, SH4BE, tag, owner, clock, ENDIANNESS_BIG) +{ +} + + +offs_t sh34_base_device::disasm_disassemble(std::ostream &stream, offs_t pc, const uint8_t *oprom, const uint8_t *opram, uint32_t options) +{ + extern CPU_DISASSEMBLE( sh4 ); + + return CPU_DISASSEMBLE_NAME(sh4)(this, stream, pc, oprom, opram, options); +} + + +offs_t sh3be_device::disasm_disassemble(std::ostream &stream, offs_t pc, const uint8_t *oprom, const uint8_t *opram, uint32_t options) +{ + extern CPU_DISASSEMBLE( sh4be ); + + return CPU_DISASSEMBLE_NAME(sh4be)(this, stream, pc, oprom, opram, options); +} + + +offs_t sh4be_device::disasm_disassemble(std::ostream &stream, offs_t pc, const uint8_t *oprom, const uint8_t *opram, uint32_t options) +{ + extern CPU_DISASSEMBLE( sh4be ); + + return CPU_DISASSEMBLE_NAME(sh4be)(this, stream, pc, oprom, opram, options); +} + + +/* Called for unimplemented opcodes */ +void sh34_base_device::TODO(const uint16_t opcode) +{ +} + +void sh34_base_device::LDTLB(const uint16_t opcode) +{ + logerror("unhandled LDTLB for this CPU type\n"); +} + +void sh4_base_device::LDTLB(const uint16_t opcode) +{ + int replace = (m_m[MMUCR] & 0x0000fc00) >> 10; + + logerror("using LDTLB to replace UTLB entry %02x\n", replace); + + // these come from PTEH + m_utlb[replace].VPN = (m_m[PTEH] & 0xfffffc00) >> 10; +// m_utlb[replace].D = (m_m[PTEH] & 0x00000200) >> 9; // from PTEL +// m_utlb[replace].V = (m_m[PTEH] & 0x00000100) >> 8; // from PTEL + m_utlb[replace].ASID = (m_m[PTEH] & 0x000000ff) >> 0; + // these come from PTEL + m_utlb[replace].PPN = (m_m[PTEL] & 0x1ffffc00) >> 10; + m_utlb[replace].V = (m_m[PTEL] & 0x00000100) >> 8; + m_utlb[replace].PSZ = (m_m[PTEL] & 0x00000080) >> 6; + m_utlb[replace].PSZ |=(m_m[PTEL] & 0x00000010) >> 4; + m_utlb[replace].PPR= (m_m[PTEL] & 0x00000060) >> 5; + m_utlb[replace].C = (m_m[PTEL] & 0x00000008) >> 3; + m_utlb[replace].D = (m_m[PTEL] & 0x00000004) >> 2; + m_utlb[replace].SH = (m_m[PTEL] & 0x00000002) >> 1; + m_utlb[replace].WT = (m_m[PTEL] & 0x00000001) >> 0; + // these come from PTEA + m_utlb[replace].TC = (m_m[PTEA] & 0x00000008) >> 3; + m_utlb[replace].SA = (m_m[PTEA] & 0x00000007) >> 0; +} + +#if 0 +int sign_of(int n) +{ + return(m_fr[n]>>31); +} + +void zero(int n,int sign) +{ +if (sign == 0) + m_fr[n] = 0x00000000; +else + m_fr[n] = 0x80000000; +if ((m_fpscr & PR) == 1) + m_fr[n+1] = 0x00000000; +} + +int data_type_of(int n) +{ +uint32_t abs; + + abs = m_fr[n] & 0x7fffffff; + if ((m_fpscr & PR) == 0) { /* Single-precision */ + if (abs < 0x00800000) { + if (((m_fpscr & DN) == 1) || (abs == 0x00000000)) { + if (sign_of(n) == 0) { + zero(n, 0); + return(SH4_FPU_PZERO); + } else { + zero(n, 1); + return(SH4_FPU_NZERO); + } + } else + return(SH4_FPU_DENORM); + } else + if (abs < 0x7f800000) + return(SH4_FPU_NORM); + else + if (abs == 0x7f800000) { + if (sign_of(n) == 0) + return(SH4_FPU_PINF); + else + return(SH4_FPU_NINF); + } else + if (abs < 0x7fc00000) + return(SH4_FPU_qNaN); + else + return(SH4_FPU_sNaN); + } else { /* Double-precision */ + if (abs < 0x00100000) { + if (((m_fpscr & DN) == 1) || ((abs == 0x00000000) && (m_fr[n+1] == 0x00000000))) { + if(sign_of(n) == 0) { + zero(n, 0); + return(SH4_FPU_PZERO); + } else { + zero(n, 1); + return(SH4_FPU_NZERO); + } + } else + return(SH4_FPU_DENORM); + } else + if (abs < 0x7ff00000) + return(SH4_FPU_NORM); + else + if ((abs == 0x7ff00000) && (m_fr[n+1] == 0x00000000)) { + if (sign_of(n) == 0) + return(SH4_FPU_PINF); + else + return(SH4_FPU_NINF); + } else + if (abs < 0x7ff80000) + return(SH4_FPU_qNaN); + else + return(SH4_FPU_sNaN); + } + return(SH4_FPU_NORM); +} +#endif + +inline uint8_t sh34_base_device::RB(offs_t A) +{ + if (A >= 0xe0000000) + return m_program->read_byte(A); + + if (A >= 0x80000000) // P1/P2/P3 region + { +#if SH4_USE_FASTRAM_OPTIMIZATION + const offs_t _A = A & AM; + for (int ramnum = 0; ramnum < m_fastram_select; ramnum++) + { + if (_A < m_fastram[ramnum].start || _A > m_fastram[ramnum].end) + { + continue; + } + uint8_t *fastbase = (uint8_t*)m_fastram[ramnum].base - m_fastram[ramnum].start; + return fastbase[_A ^ m_byte_xor]; + } + return m_program->read_byte(_A); +#else + return m_program->read_byte(A & AM); +#endif + } + else // P0 region + { + if (!m_sh4_mmu_enabled) + { + return m_program->read_byte(A & AM); + } + else + { + A = get_remap(A & AM); + return m_program->read_byte(A); + } + } + +} + +inline uint16_t sh34_base_device::RW(offs_t A) +{ + if (A >= 0xe0000000) + return m_program->read_word(A); + + if (A >= 0x80000000) // P1/P2/P3 region + { +#if SH4_USE_FASTRAM_OPTIMIZATION + const offs_t _A = A & AM; + for (int ramnum = 0; ramnum < m_fastram_select; ramnum++) + { + if (_A < m_fastram[ramnum].start || _A > m_fastram[ramnum].end) + { + continue; + } + uint8_t *fastbase = (uint8_t*)m_fastram[ramnum].base - m_fastram[ramnum].start; + return ((uint16_t*)fastbase)[(_A ^ m_word_xor) >> 1]; + } + return m_program->read_word(_A); +#else + return m_program->read_word(A & AM); +#endif + } + else + { + if (!m_sh4_mmu_enabled) + { + return m_program->read_word(A & AM); + } + else + { + A = get_remap(A & AM); + return m_program->read_word(A); + } + } + +} + +inline uint32_t sh34_base_device::RL(offs_t A) +{ + if (A >= 0xe0000000) + return m_program->read_dword(A); + + if (A >= 0x80000000) // P1/P2/P3 region + { +#if SH4_USE_FASTRAM_OPTIMIZATION + const offs_t _A = A & AM; + for (int ramnum = 0; ramnum < m_fastram_select; ramnum++) + { + if (_A < m_fastram[ramnum].start || _A > m_fastram[ramnum].end) + { + continue; + } + uint8_t *fastbase = (uint8_t*)m_fastram[ramnum].base - m_fastram[ramnum].start; + return ((uint32_t*)fastbase)[(_A^m_dword_xor) >> 2]; + } + return m_program->read_dword(_A); +#else + return m_program->read_dword(A & AM); +#endif + } + else + { + if (!m_sh4_mmu_enabled) + { + return m_program->read_dword(A & AM); + } + else + { + A = get_remap(A & AM); + return m_program->read_dword(A); + } + } + +} + +inline void sh34_base_device::WB(offs_t A, uint8_t V) +{ + if (A >= 0xe0000000) + { + m_program->write_byte(A,V); + return; + } + + if (A >= 0x80000000) // P1/P2/P3 region + { +#if SH4_USE_FASTRAM_OPTIMIZATION + const offs_t _A = A & AM; + for (int ramnum = 0; ramnum < m_fastram_select; ramnum++) + { + if (m_fastram[ramnum].readonly == true || _A < m_fastram[ramnum].start || _A > m_fastram[ramnum].end) + { + continue; + } + uint8_t *fastbase = (uint8_t*)m_fastram[ramnum].base - m_fastram[ramnum].start; + fastbase[_A ^ m_byte_xor] = V; + return; + } + m_program->write_byte(_A, V); +#else + m_program->write_byte(A & AM, V); +#endif + } + else + { + if (!m_sh4_mmu_enabled) + { + m_program->write_byte(A & AM, V); + } + else + { + A = get_remap(A & AM); + m_program->write_byte(A, V); + } + } + +} + +inline void sh34_base_device::WW(offs_t A, uint16_t V) +{ + if (A >= 0xe0000000) + { + m_program->write_word(A,V); + return; + } + + if (A >= 0x80000000) // P1/P2/P3 region + { +#if SH4_USE_FASTRAM_OPTIMIZATION + const offs_t _A = A & AM; + for (int ramnum = 0; ramnum < m_fastram_select; ramnum++) + { + if (m_fastram[ramnum].readonly == true || _A < m_fastram[ramnum].start || _A > m_fastram[ramnum].end) + { + continue; + } + void *fastbase = (uint8_t*)m_fastram[ramnum].base - m_fastram[ramnum].start; + ((uint16_t*)fastbase)[(_A ^ m_word_xor) >> 1] = V; + return; + } + m_program->write_word(_A, V); +#else + m_program->write_word(A & AM, V); +#endif + } + else + { + if (!m_sh4_mmu_enabled) + { + m_program->write_word(A & AM, V); + } + else + { + A = get_remap(A & AM); + m_program->write_word(A, V); + } + } + +} + +inline void sh34_base_device::WL(offs_t A, uint32_t V) +{ + if (A >= 0xe0000000) + { + m_program->write_dword(A,V); + return; + } + + if (A >= 0x80000000) // P1/P2/P3 region + { +#if SH4_USE_FASTRAM_OPTIMIZATION + const offs_t _A = A & AM; + for (int ramnum = 0; ramnum < m_fastram_select; ramnum++) + { + if (m_fastram[ramnum].readonly == true || _A < m_fastram[ramnum].start || _A > m_fastram[ramnum].end) + { + continue; + } + void *fastbase = (uint8_t*)m_fastram[ramnum].base - m_fastram[ramnum].start; + ((uint32_t*)fastbase)[(_A ^ m_dword_xor) >> 2] = V; + return; + } + m_program->write_dword(_A, V); +#else + m_program->write_dword(A & AM, V); +#endif + } + else + { + if (!m_sh4_mmu_enabled) + { + m_program->write_dword(A & AM, V); + } + else + { + A = get_remap(A & AM); + m_program->write_dword(A, V); + } + } + +} + +/* code cycles t-bit + * 0011 nnnn mmmm 1100 1 - + * ADD Rm,Rn + */ +inline void sh34_base_device::ADD(const uint16_t opcode) +{ + m_r[Rn] += m_r[Rm]; +} + +/* code cycles t-bit + * 0111 nnnn iiii iiii 1 - + * ADD #imm,Rn + */ +inline void sh34_base_device::ADDI(const uint16_t opcode) +{ + m_r[Rn] += (int32_t)(int16_t)(int8_t)(opcode&0xff); +} + +/* code cycles t-bit + * 0011 nnnn mmmm 1110 1 carry + * ADDC Rm,Rn + */ +inline void sh34_base_device::ADDC(const uint16_t opcode) +{ + uint32_t m = Rm; uint32_t n = Rn; + uint32_t tmp0, tmp1; + + tmp1 = m_r[n] + m_r[m]; + tmp0 = m_r[n]; + m_r[n] = tmp1 + (m_sr & T); + if (tmp0 > tmp1) + m_sr |= T; + else + m_sr &= ~T; + if (tmp1 > m_r[n]) + m_sr |= T; +} + +/* code cycles t-bit + * 0011 nnnn mmmm 1111 1 overflow + * ADDV Rm,Rn + */ +inline void sh34_base_device::ADDV(const uint16_t opcode) +{ + uint32_t m = Rm; uint32_t n = Rn; + int32_t dest, src, ans; + + if ((int32_t) m_r[n] >= 0) + dest = 0; + else + dest = 1; + if ((int32_t) m_r[m] >= 0) + src = 0; + else + src = 1; + src += dest; + m_r[n] += m_r[m]; + if ((int32_t) m_r[n] >= 0) + ans = 0; + else + ans = 1; + ans += dest; + if (src == 0 || src == 2) + { + if (ans == 1) + m_sr |= T; + else + m_sr &= ~T; + } + else + m_sr &= ~T; +} + +/* code cycles t-bit + * 0010 nnnn mmmm 1001 1 - + * AND Rm,Rn + */ +inline void sh34_base_device::AND(const uint16_t opcode) +{ + m_r[Rn] &= m_r[Rm]; +} + + +/* code cycles t-bit + * 1100 1001 iiii iiii 1 - + * AND #imm,R0 + */ +inline void sh34_base_device::ANDI(const uint16_t opcode) +{ + m_r[0] &= (opcode&0xff); +} + +/* code cycles t-bit + * 1100 1101 iiii iiii 1 - + * AND.B #imm,@(R0,GBR) + */ +inline void sh34_base_device::ANDM(const uint16_t opcode) +{ + uint32_t temp; + + m_ea = m_gbr + m_r[0]; + temp = (opcode&0xff) & RB( m_ea ); + WB(m_ea, temp ); + m_sh4_icount -= 2; +} + +/* code cycles t-bit + * 1000 1011 dddd dddd 3/1 - + * BF disp8 + */ +inline void sh34_base_device::BF(const uint16_t opcode) +{ + if ((m_sr & T) == 0) + { + int32_t disp = ((int32_t)(opcode&0xff) << 24) >> 24; + m_pc = m_ea = m_pc + disp * 2 + 2; + m_sh4_icount -= 2; + } +} + +/* code cycles t-bit + * 1000 1111 dddd dddd 3/1 - + * BFS disp8 + */ +inline void sh34_base_device::BFS(const uint16_t opcode) +{ + if ((m_sr & T) == 0) + { + int32_t disp = ((int32_t)(opcode&0xff) << 24) >> 24; + m_delay = m_ea = m_pc + disp * 2 + 2; + m_sh4_icount--; + } +} + +/* code cycles t-bit + * 1010 dddd dddd dddd 2 - + * BRA disp12 + */ +inline void sh34_base_device::BRA(const uint16_t opcode) +{ + int32_t disp = ((int32_t)(opcode&0xfff) << 20) >> 20; + +#if BUSY_LOOP_HACKS + if (disp == -2) + { + uint32_t next_opcode = RW(m_pc & AM); + /* BRA $ + * NOP + */ + if (next_opcode == 0x0009) + m_sh4_icount %= 3; /* cycles for BRA $ and NOP taken (3) */ + } +#endif + m_delay = m_ea = m_pc + disp * 2 + 2; + m_sh4_icount--; +} + +/* code cycles t-bit + * 0000 mmmm 0010 0011 2 - + * BRAF Rm + */ +inline void sh34_base_device::BRAF(const uint16_t opcode) +{ + m_delay = m_pc + m_r[Rn] + 2; + m_sh4_icount--; +} + +/* code cycles t-bit + * 1011 dddd dddd dddd 2 - + * BSR disp12 + */ +inline void sh34_base_device::BSR(const uint16_t opcode) +{ + int32_t disp = ((int32_t)(opcode&0xfff) << 20) >> 20; + + m_pr = m_pc + 2; + m_delay = m_ea = m_pc + disp * 2 + 2; + m_sh4_icount--; +} + +/* code cycles t-bit + * 0000 mmmm 0000 0011 2 - + * BSRF Rm + */ +inline void sh34_base_device::BSRF(const uint16_t opcode) +{ + m_pr = m_pc + 2; + m_delay = m_pc + m_r[Rn] + 2; + m_sh4_icount--; +} + +/* code cycles t-bit + * 1000 1001 dddd dddd 3/1 - + * BT disp8 + */ +inline void sh34_base_device::BT(const uint16_t opcode) +{ + if ((m_sr & T) != 0) + { + int32_t disp = ((int32_t)(opcode&0xff) << 24) >> 24; + m_pc = m_ea = m_pc + disp * 2 + 2; + m_sh4_icount -= 2; + } +} + +/* code cycles t-bit + * 1000 1101 dddd dddd 2/1 - + * BTS disp8 + */ +inline void sh34_base_device::BTS(const uint16_t opcode) +{ + if ((m_sr & T) != 0) + { + int32_t disp = ((int32_t)(opcode&0xff) << 24) >> 24; + m_delay = m_ea = m_pc + disp * 2 + 2; + m_sh4_icount--; + } +} + +/* code cycles t-bit + * 0000 0000 0010 1000 1 - + * CLRMAC + */ +inline void sh34_base_device::CLRMAC(const uint16_t opcode) +{ + m_mach = 0; + m_macl = 0; +} + +/* code cycles t-bit + * 0000 0000 0000 1000 1 - + * CLRT + */ +inline void sh34_base_device::CLRT(const uint16_t opcode) +{ + m_sr &= ~T; +} + +/* code cycles t-bit + * 0011 nnnn mmmm 0000 1 comparison result + * CMP_EQ Rm,Rn + */ +inline void sh34_base_device::CMPEQ(const uint16_t opcode) +{ + if (m_r[Rn] == m_r[Rm]) + m_sr |= T; + else + m_sr &= ~T; +} + +/* code cycles t-bit + * 0011 nnnn mmmm 0011 1 comparison result + * CMP_GE Rm,Rn + */ +inline void sh34_base_device::CMPGE(const uint16_t opcode) +{ + if ((int32_t) m_r[Rn] >= (int32_t) m_r[Rm]) + m_sr |= T; + else + m_sr &= ~T; +} + +/* code cycles t-bit + * 0011 nnnn mmmm 0111 1 comparison result + * CMP_GT Rm,Rn + */ +inline void sh34_base_device::CMPGT(const uint16_t opcode) +{ + if ((int32_t) m_r[Rn] > (int32_t) m_r[Rm]) + m_sr |= T; + else + m_sr &= ~T; +} + +/* code cycles t-bit + * 0011 nnnn mmmm 0110 1 comparison result + * CMP_HI Rm,Rn + */ +inline void sh34_base_device::CMPHI(const uint16_t opcode) +{ + if ((uint32_t) m_r[Rn] > (uint32_t) m_r[Rm]) + m_sr |= T; + else + m_sr &= ~T; +} + +/* code cycles t-bit + * 0011 nnnn mmmm 0010 1 comparison result + * CMP_HS Rm,Rn + */ +inline void sh34_base_device::CMPHS(const uint16_t opcode) +{ + if ((uint32_t) m_r[Rn] >= (uint32_t) m_r[Rm]) + m_sr |= T; + else + m_sr &= ~T; +} + + +/* code cycles t-bit + * 0100 nnnn 0001 0101 1 comparison result + * CMP_PL Rn + */ +inline void sh34_base_device::CMPPL(const uint16_t opcode) +{ + if ((int32_t) m_r[Rn] > 0) + m_sr |= T; + else + m_sr &= ~T; +} + +/* code cycles t-bit + * 0100 nnnn 0001 0001 1 comparison result + * CMP_PZ Rn + */ +inline void sh34_base_device::CMPPZ(const uint16_t opcode) +{ + if ((int32_t) m_r[Rn] >= 0) + m_sr |= T; + else + m_sr &= ~T; +} + +/* code cycles t-bit + * 0010 nnnn mmmm 1100 1 comparison result + * CMP_STR Rm,Rn + */ +inline void sh34_base_device::CMPSTR(const uint16_t opcode) +{ + uint32_t temp; + int32_t HH, HL, LH, LL; + temp = m_r[Rn] ^ m_r[Rm]; + HH = (temp >> 24) & 0xff; + HL = (temp >> 16) & 0xff; + LH = (temp >> 8) & 0xff; + LL = temp & 0xff; + if (HH && HL && LH && LL) + m_sr &= ~T; + else + m_sr |= T; + } + + +/* code cycles t-bit + * 1000 1000 iiii iiii 1 comparison result + * CMP/EQ #imm,R0 + */ +inline void sh34_base_device::CMPIM(const uint16_t opcode) +{ + uint32_t imm = (uint32_t)(int32_t)(int16_t)(int8_t)(opcode&0xff); + + if (m_r[0] == imm) + m_sr |= T; + else + m_sr &= ~T; +} + +/* code cycles t-bit + * 0010 nnnn mmmm 0111 1 calculation result + * DIV0S Rm,Rn + */ +inline void sh34_base_device::DIV0S(const uint16_t opcode) +{ + uint32_t m = Rm; uint32_t n = Rn; + + if ((m_r[n] & 0x80000000) == 0) + m_sr &= ~Q; + else + m_sr |= Q; + if ((m_r[m] & 0x80000000) == 0) + m_sr &= ~M; + else + m_sr |= M; + if ((m_r[m] ^ m_r[n]) & 0x80000000) + m_sr |= T; + else + m_sr &= ~T; +} + +/* code cycles t-bit + * 0000 0000 0001 1001 1 0 + * DIV0U + */ +inline void sh34_base_device::DIV0U(const uint16_t opcode) +{ + m_sr &= ~(M | Q | T); +} + +/* code cycles t-bit + * 0011 nnnn mmmm 0100 1 calculation result + * DIV1 Rm,Rn + */ +inline void sh34_base_device::DIV1(const uint16_t opcode) +{ + uint32_t m = Rm; uint32_t n = Rn; + + uint32_t tmp0; + uint32_t old_q; + + old_q = m_sr & Q; + if (0x80000000 & m_r[n]) + m_sr |= Q; + else + m_sr &= ~Q; + + m_r[n] = (m_r[n] << 1) | (m_sr & T); + + if (!old_q) + { + if (!(m_sr & M)) + { + tmp0 = m_r[n]; + m_r[n] -= m_r[m]; + if(!(m_sr & Q)) + if(m_r[n] > tmp0) + m_sr |= Q; + else + m_sr &= ~Q; + else + if(m_r[n] > tmp0) + m_sr &= ~Q; + else + m_sr |= Q; + } + else + { + tmp0 = m_r[n]; + m_r[n] += m_r[m]; + if(!(m_sr & Q)) + { + if(m_r[n] < tmp0) + m_sr &= ~Q; + else + m_sr |= Q; + } + else + { + if(m_r[n] < tmp0) + m_sr |= Q; + else + m_sr &= ~Q; + } + } + } + else + { + if (!(m_sr & M)) + { + tmp0 = m_r[n]; + m_r[n] += m_r[m]; + if(!(m_sr & Q)) + if(m_r[n] < tmp0) + m_sr |= Q; + else + m_sr &= ~Q; + else + if(m_r[n] < tmp0) + m_sr &= ~Q; + else + m_sr |= Q; + } + else + { + tmp0 = m_r[n]; + m_r[n] -= m_r[m]; + if(!(m_sr & Q)) + if(m_r[n] > tmp0) + m_sr &= ~Q; + else + m_sr |= Q; + else + if(m_r[n] > tmp0) + m_sr |= Q; + else + m_sr &= ~Q; + } + } + + tmp0 = (m_sr & (Q | M)); + if((!tmp0) || (tmp0 == 0x300)) /* if Q == M set T else clear T */ + m_sr |= T; + else + m_sr &= ~T; +} + +/* DMULS.L Rm,Rn */ +inline void sh34_base_device::DMULS(const uint16_t opcode) +{ + uint32_t m = Rm; uint32_t n = Rn; + + uint32_t RnL, RnH, RmL, RmH, Res0, Res1, Res2; + uint32_t temp0, temp1, temp2, temp3; + int32_t tempm, tempn, fnLmL; + + tempn = (int32_t) m_r[n]; + tempm = (int32_t) m_r[m]; + if (tempn < 0) + tempn = 0 - tempn; + if (tempm < 0) + tempm = 0 - tempm; + if ((int32_t) (m_r[n] ^ m_r[m]) < 0) + fnLmL = -1; + else + fnLmL = 0; + temp1 = (uint32_t) tempn; + temp2 = (uint32_t) tempm; + RnL = temp1 & 0x0000ffff; + RnH = (temp1 >> 16) & 0x0000ffff; + RmL = temp2 & 0x0000ffff; + RmH = (temp2 >> 16) & 0x0000ffff; + temp0 = RmL * RnL; + temp1 = RmH * RnL; + temp2 = RmL * RnH; + temp3 = RmH * RnH; + Res2 = 0; + Res1 = temp1 + temp2; + if (Res1 < temp1) + Res2 += 0x00010000; + temp1 = (Res1 << 16) & 0xffff0000; + Res0 = temp0 + temp1; + if (Res0 < temp0) + Res2++; + Res2 = Res2 + ((Res1 >> 16) & 0x0000ffff) + temp3; + if (fnLmL < 0) + { + Res2 = ~Res2; + if (Res0 == 0) + Res2++; + else + Res0 = (~Res0) + 1; + } + m_mach = Res2; + m_macl = Res0; + m_sh4_icount--; +} + +/* DMULU.L Rm,Rn */ +inline void sh34_base_device::DMULU(const uint16_t opcode) +{ + uint32_t m = Rm; uint32_t n = Rn; + + uint32_t RnL, RnH, RmL, RmH, Res0, Res1, Res2; + uint32_t temp0, temp1, temp2, temp3; + + RnL = m_r[n] & 0x0000ffff; + RnH = (m_r[n] >> 16) & 0x0000ffff; + RmL = m_r[m] & 0x0000ffff; + RmH = (m_r[m] >> 16) & 0x0000ffff; + temp0 = RmL * RnL; + temp1 = RmH * RnL; + temp2 = RmL * RnH; + temp3 = RmH * RnH; + Res2 = 0; + Res1 = temp1 + temp2; + if (Res1 < temp1) + Res2 += 0x00010000; + temp1 = (Res1 << 16) & 0xffff0000; + Res0 = temp0 + temp1; + if (Res0 < temp0) + Res2++; + Res2 = Res2 + ((Res1 >> 16) & 0x0000ffff) + temp3; + m_mach = Res2; + m_macl = Res0; + m_sh4_icount--; +} + +/* DT Rn */ +inline void sh34_base_device::DT(const uint16_t opcode) +{ + uint32_t n = Rn; + + m_r[n]--; + if (m_r[n] == 0) + m_sr |= T; + else + m_sr &= ~T; +#if BUSY_LOOP_HACKS + { + uint32_t next_opcode = RW(m_pc & AM); + /* DT Rn + * BF $-2 + */ + if (next_opcode == 0x8bfd) + { + while (m_r[n] > 1 && m_sh4_icount > 4) + { + m_r[n]--; + m_sh4_icount -= 4; /* cycles for DT (1) and BF taken (3) */ + } + } + } +#endif +} + +/* EXTS.B Rm,Rn */ +inline void sh34_base_device::EXTSB(const uint16_t opcode) +{ + m_r[Rn] = ((int32_t)m_r[Rm] << 24) >> 24; +} + +/* EXTS.W Rm,Rn */ +inline void sh34_base_device::EXTSW(const uint16_t opcode) +{ + m_r[Rn] = ((int32_t)m_r[Rm] << 16) >> 16; +} + +/* EXTU.B Rm,Rn */ +inline void sh34_base_device::EXTUB(const uint16_t opcode) +{ + m_r[Rn] = m_r[Rm] & 0x000000ff; +} + +/* EXTU.W Rm,Rn */ +inline void sh34_base_device::EXTUW(const uint16_t opcode) +{ + m_r[Rn] = m_r[Rm] & 0x0000ffff; +} + +/* JMP @Rm */ +inline void sh34_base_device::JMP(const uint16_t opcode) +{ + m_delay = m_ea = m_r[Rn]; +} + +/* JSR @Rm */ +inline void sh34_base_device::JSR(const uint16_t opcode) +{ + m_pr = m_pc + 2; + m_delay = m_ea = m_r[Rn]; + m_sh4_icount--; +} + + +/* LDC Rm,SR */ +inline void sh34_base_device::LDCSR(const uint16_t opcode) +{ + uint32_t reg; + + reg = m_r[Rn]; + if ((machine().debug_flags & DEBUG_FLAG_ENABLED) != 0) + sh4_syncronize_register_bank((m_sr & sRB) >> 29); + if ((m_r[Rn] & sRB) != (m_sr & sRB)) + sh4_change_register_bank(m_r[Rn] & sRB ? 1 : 0); + m_sr = reg & FLAGS; + sh4_exception_recompute(); +} + +/* LDC Rm,GBR */ +inline void sh34_base_device::LDCGBR(const uint16_t opcode) +{ + m_gbr = m_r[Rn]; +} + +/* LDC Rm,VBR */ +inline void sh34_base_device::LDCVBR(const uint16_t opcode) +{ + m_vbr = m_r[Rn]; +} + +/* LDC.L @Rm+,SR */ +inline void sh34_base_device::LDCMSR(const uint16_t opcode) +{ + uint32_t old; + + old = m_sr; + m_ea = m_r[Rn]; + m_sr = RL(m_ea ) & FLAGS; + if ((machine().debug_flags & DEBUG_FLAG_ENABLED) != 0) + sh4_syncronize_register_bank((old & sRB) >> 29); + if ((old & sRB) != (m_sr & sRB)) + sh4_change_register_bank(m_sr & sRB ? 1 : 0); + m_r[Rn] += 4; + m_sh4_icount -= 2; + sh4_exception_recompute(); +} + +/* LDC.L @Rm+,GBR */ +inline void sh34_base_device::LDCMGBR(const uint16_t opcode) +{ + m_ea = m_r[Rn]; + m_gbr = RL(m_ea ); + m_r[Rn] += 4; + m_sh4_icount -= 2; +} + +/* LDC.L @Rm+,VBR */ +inline void sh34_base_device::LDCMVBR(const uint16_t opcode) +{ + m_ea = m_r[Rn]; + m_vbr = RL(m_ea ); + m_r[Rn] += 4; + m_sh4_icount -= 2; +} + +/* LDS Rm,MACH */ +inline void sh34_base_device::LDSMACH(const uint16_t opcode) +{ + m_mach = m_r[Rn]; +} + +/* LDS Rm,MACL */ +inline void sh34_base_device::LDSMACL(const uint16_t opcode) +{ + m_macl = m_r[Rn]; +} + +/* LDS Rm,PR */ +inline void sh34_base_device::LDSPR(const uint16_t opcode) +{ + m_pr = m_r[Rn]; +} + +/* LDS.L @Rm+,MACH */ +inline void sh34_base_device::LDSMMACH(const uint16_t opcode) +{ + m_ea = m_r[Rn]; + m_mach = RL(m_ea ); + m_r[Rn] += 4; +} + +/* LDS.L @Rm+,MACL */ +inline void sh34_base_device::LDSMMACL(const uint16_t opcode) +{ + m_ea = m_r[Rn]; + m_macl = RL(m_ea ); + m_r[Rn] += 4; +} + +/* LDS.L @Rm+,PR */ +inline void sh34_base_device::LDSMPR(const uint16_t opcode) +{ + m_ea = m_r[Rn]; + m_pr = RL(m_ea ); + m_r[Rn] += 4; +} + +/* MAC.L @Rm+,@Rn+ */ +inline void sh34_base_device::MAC_L(const uint16_t opcode) +{ + uint32_t m = Rm; uint32_t n = Rn; + + uint32_t RnL, RnH, RmL, RmH, Res0, Res1, Res2; + uint32_t temp0, temp1, temp2, temp3; + int32_t tempm, tempn, fnLmL; + + tempn = (int32_t) RL(m_r[n] ); + m_r[n] += 4; + tempm = (int32_t) RL(m_r[m] ); + m_r[m] += 4; + if ((int32_t) (tempn ^ tempm) < 0) + fnLmL = -1; + else + fnLmL = 0; + if (tempn < 0) + tempn = 0 - tempn; + if (tempm < 0) + tempm = 0 - tempm; + temp1 = (uint32_t) tempn; + temp2 = (uint32_t) tempm; + RnL = temp1 & 0x0000ffff; + RnH = (temp1 >> 16) & 0x0000ffff; + RmL = temp2 & 0x0000ffff; + RmH = (temp2 >> 16) & 0x0000ffff; + temp0 = RmL * RnL; + temp1 = RmH * RnL; + temp2 = RmL * RnH; + temp3 = RmH * RnH; + Res2 = 0; + Res1 = temp1 + temp2; + if (Res1 < temp1) + Res2 += 0x00010000; + temp1 = (Res1 << 16) & 0xffff0000; + Res0 = temp0 + temp1; + if (Res0 < temp0) + Res2++; + Res2 = Res2 + ((Res1 >> 16) & 0x0000ffff) + temp3; + if (fnLmL < 0) + { + Res2 = ~Res2; + if (Res0 == 0) + Res2++; + else + Res0 = (~Res0) + 1; + } + if (m_sr & S) + { + Res0 = m_macl + Res0; + if (m_macl > Res0) + Res2++; + Res2 += (m_mach & 0x0000ffff); + if (((int32_t) Res2 < 0) && (Res2 < 0xffff8000)) + { + Res2 = 0x00008000; + Res0 = 0x00000000; + } + else if (((int32_t) Res2 > 0) && (Res2 > 0x00007fff)) + { + Res2 = 0x00007fff; + Res0 = 0xffffffff; + } + m_mach = Res2; + m_macl = Res0; + } + else + { + Res0 = m_macl + Res0; + if (m_macl > Res0) + Res2++; + Res2 += m_mach; + m_mach = Res2; + m_macl = Res0; + } + m_sh4_icount -= 2; +} + +/* MAC.W @Rm+,@Rn+ */ +inline void sh34_base_device::MAC_W(const uint16_t opcode) +{ + uint32_t m = Rm; uint32_t n = Rn; + + int32_t tempm, tempn, dest, src, ans; + uint32_t templ; + + tempn = (int32_t) RW(m_r[n] ); + m_r[n] += 2; + tempm = (int32_t) RW(m_r[m] ); + m_r[m] += 2; + templ = m_macl; + tempm = ((int32_t) (short) tempn * (int32_t) (short) tempm); + if ((int32_t) m_macl >= 0) + dest = 0; + else + dest = 1; + if ((int32_t) tempm >= 0) + { + src = 0; + tempn = 0; + } + else + { + src = 1; + tempn = 0xffffffff; + } + src += dest; + m_macl += tempm; + if ((int32_t) m_macl >= 0) + ans = 0; + else + ans = 1; + ans += dest; + if (m_sr & S) + { + if (ans == 1) + { + if (src == 0) + m_macl = 0x7fffffff; + if (src == 2) + m_macl = 0x80000000; + } + } + else + { + m_mach += tempn; + if (templ > m_macl) + m_mach += 1; + } + m_sh4_icount -= 2; +} + +/* MOV Rm,Rn */ +inline void sh34_base_device::MOV(const uint16_t opcode) +{ + m_r[Rn] = m_r[Rm]; +} + +/* MOV.B Rm,@Rn */ +inline void sh34_base_device::MOVBS(const uint16_t opcode) +{ + m_ea = m_r[Rn]; + WB(m_ea, m_r[Rm] & 0x000000ff); +} + +/* MOV.W Rm,@Rn */ +inline void sh34_base_device::MOVWS(const uint16_t opcode) +{ + m_ea = m_r[Rn]; + WW(m_ea, m_r[Rm] & 0x0000ffff); +} + +/* MOV.L Rm,@Rn */ +inline void sh34_base_device::MOVLS(const uint16_t opcode) +{ + m_ea = m_r[Rn]; + WL(m_ea, m_r[Rm] ); +} + +/* MOV.B @Rm,Rn */ +inline void sh34_base_device::MOVBL(const uint16_t opcode) +{ + m_ea = m_r[Rm]; + m_r[Rn] = (uint32_t)(int32_t)(int16_t)(int8_t) RB( m_ea ); +} + +/* MOV.W @Rm,Rn */ +inline void sh34_base_device::MOVWL(const uint16_t opcode) +{ + m_ea = m_r[Rm]; + m_r[Rn] = (uint32_t)(int32_t)(int16_t) RW(m_ea ); +} + +/* MOV.L @Rm,Rn */ +inline void sh34_base_device::MOVLL(const uint16_t opcode) +{ + m_ea = m_r[Rm]; + m_r[Rn] = RL(m_ea ); +} + +/* MOV.B Rm,@-Rn */ +inline void sh34_base_device::MOVBM(const uint16_t opcode) +{ + uint32_t data = m_r[Rm] & 0x000000ff; + + m_r[Rn] -= 1; + WB(m_r[Rn], data ); +} + +/* MOV.W Rm,@-Rn */ +inline void sh34_base_device::MOVWM(const uint16_t opcode) +{ + uint32_t data = m_r[Rm] & 0x0000ffff; + + m_r[Rn] -= 2; + WW(m_r[Rn], data ); +} + +/* MOV.L Rm,@-Rn */ +inline void sh34_base_device::MOVLM(const uint16_t opcode) +{ + uint32_t data = m_r[Rm]; + + m_r[Rn] -= 4; + WL(m_r[Rn], data ); +} + +/* MOV.B @Rm+,Rn */ +inline void sh34_base_device::MOVBP(const uint16_t opcode) +{ + uint32_t m = Rm; uint32_t n = Rn; + + m_r[n] = (uint32_t)(int32_t)(int16_t)(int8_t) RB( m_r[m] ); + if (n != m) + m_r[m] += 1; +} + +/* MOV.W @Rm+,Rn */ +inline void sh34_base_device::MOVWP(const uint16_t opcode) +{ + uint32_t m = Rm; uint32_t n = Rn; + + m_r[n] = (uint32_t)(int32_t)(int16_t) RW(m_r[m] ); + if (n != m) + m_r[m] += 2; +} + +/* MOV.L @Rm+,Rn */ +inline void sh34_base_device::MOVLP(const uint16_t opcode) +{ + uint32_t m = Rm; uint32_t n = Rn; + + m_r[n] = RL(m_r[m] ); + if (n != m) + m_r[m] += 4; +} + +/* MOV.B Rm,@(R0,Rn) */ +inline void sh34_base_device::MOVBS0(const uint16_t opcode) +{ + m_ea = m_r[Rn] + m_r[0]; + WB(m_ea, m_r[Rm] & 0x000000ff ); +} + +/* MOV.W Rm,@(R0,Rn) */ +inline void sh34_base_device::MOVWS0(const uint16_t opcode) +{ + m_ea = m_r[Rn] + m_r[0]; + WW(m_ea, m_r[Rm] & 0x0000ffff ); +} + +/* MOV.L Rm,@(R0,Rn) */ +inline void sh34_base_device::MOVLS0(const uint16_t opcode) +{ + m_ea = m_r[Rn] + m_r[0]; + WL(m_ea, m_r[Rm] ); +} + +/* MOV.B @(R0,Rm),Rn */ +inline void sh34_base_device::MOVBL0(const uint16_t opcode) +{ + m_ea = m_r[Rm] + m_r[0]; + m_r[Rn] = (uint32_t)(int32_t)(int16_t)(int8_t) RB( m_ea ); +} + +/* MOV.W @(R0,Rm),Rn */ +inline void sh34_base_device::MOVWL0(const uint16_t opcode) +{ + m_ea = m_r[Rm] + m_r[0]; + m_r[Rn] = (uint32_t)(int32_t)(int16_t) RW(m_ea ); +} + +/* MOV.L @(R0,Rm),Rn */ +inline void sh34_base_device::MOVLL0(const uint16_t opcode) +{ + m_ea = m_r[Rm] + m_r[0]; + m_r[Rn] = RL(m_ea ); +} + +/* MOV #imm,Rn */ +inline void sh34_base_device::MOVI(const uint16_t opcode) +{ + m_r[Rn] = (uint32_t)(int32_t)(int16_t)(int8_t)(opcode&0xff); +} + +/* MOV.W @(disp8,PC),Rn */ +inline void sh34_base_device::MOVWI(const uint16_t opcode) +{ + uint32_t disp = opcode & 0xff; + m_ea = m_pc + disp * 2 + 2; + m_r[Rn] = (uint32_t)(int32_t)(int16_t) RW(m_ea ); +} + +/* MOV.L @(disp8,PC),Rn */ +inline void sh34_base_device::MOVLI(const uint16_t opcode) +{ + uint32_t disp = opcode & 0xff; + m_ea = ((m_pc + 2) & ~3) + disp * 4; + m_r[Rn] = RL(m_ea ); +} + +/* MOV.B @(disp8,GBR),R0 */ +inline void sh34_base_device::MOVBLG(const uint16_t opcode) +{ + uint32_t disp = opcode & 0xff; + m_ea = m_gbr + disp; + m_r[0] = (uint32_t)(int32_t)(int16_t)(int8_t) RB( m_ea ); +} + +/* MOV.W @(disp8,GBR),R0 */ +inline void sh34_base_device::MOVWLG(const uint16_t opcode) +{ + uint32_t disp = opcode & 0xff; + m_ea = m_gbr + disp * 2; + m_r[0] = (int32_t)(int16_t) RW(m_ea ); +} + +/* MOV.L @(disp8,GBR),R0 */ +inline void sh34_base_device::MOVLLG(const uint16_t opcode) +{ + uint32_t disp = opcode & 0xff; + m_ea = m_gbr + disp * 4; + m_r[0] = RL(m_ea ); +} + +/* MOV.B R0,@(disp8,GBR) */ +inline void sh34_base_device::MOVBSG(const uint16_t opcode) +{ + uint32_t disp = opcode & 0xff; + m_ea = m_gbr + disp; + WB(m_ea, m_r[0] & 0x000000ff ); +} + +/* MOV.W R0,@(disp8,GBR) */ +inline void sh34_base_device::MOVWSG(const uint16_t opcode) +{ + uint32_t disp = opcode & 0xff; + m_ea = m_gbr + disp * 2; + WW(m_ea, m_r[0] & 0x0000ffff ); +} + +/* MOV.L R0,@(disp8,GBR) */ +inline void sh34_base_device::MOVLSG(const uint16_t opcode) +{ + uint32_t disp = opcode & 0xff; + m_ea = m_gbr + disp * 4; + WL(m_ea, m_r[0] ); +} + +/* MOV.B R0,@(disp4,Rm) */ +inline void sh34_base_device::MOVBS4(const uint16_t opcode) +{ + uint32_t disp = opcode & 0x0f; + m_ea = m_r[Rm] + disp; + WB(m_ea, m_r[0] & 0x000000ff ); +} + +/* MOV.W R0,@(disp4,Rm) */ +inline void sh34_base_device::MOVWS4(const uint16_t opcode) +{ + uint32_t disp = opcode & 0x0f; + m_ea = m_r[Rm] + disp * 2; + WW(m_ea, m_r[0] & 0x0000ffff ); +} + +/* MOV.L Rm,@(disp4,Rn) */ +inline void sh34_base_device::MOVLS4(const uint16_t opcode) +{ + uint32_t disp = opcode & 0x0f; + m_ea = m_r[Rn] + disp * 4; + WL(m_ea, m_r[Rm] ); +} + +/* MOV.B @(disp4,Rm),R0 */ +inline void sh34_base_device::MOVBL4(const uint16_t opcode) +{ + uint32_t disp = opcode & 0x0f; + m_ea = m_r[Rm] + disp; + m_r[0] = (uint32_t)(int32_t)(int16_t)(int8_t) RB( m_ea ); +} + +/* MOV.W @(disp4,Rm),R0 */ +inline void sh34_base_device::MOVWL4(const uint16_t opcode) +{ + uint32_t disp = opcode & 0x0f; + m_ea = m_r[Rm] + disp * 2; + m_r[0] = (uint32_t)(int32_t)(int16_t) RW(m_ea ); +} + +/* MOV.L @(disp4,Rm),Rn */ +inline void sh34_base_device::MOVLL4(const uint16_t opcode) +{ + uint32_t disp = opcode & 0x0f; + m_ea = m_r[Rm] + disp * 4; + m_r[Rn] = RL(m_ea ); +} + +/* MOVA @(disp8,PC),R0 */ +inline void sh34_base_device::MOVA(const uint16_t opcode) +{ + uint32_t disp = opcode & 0xff; + m_ea = ((m_pc + 2) & ~3) + disp * 4; + m_r[0] = m_ea; +} + +/* MOVT Rn */ +void sh34_base_device::MOVT(const uint16_t opcode) +{ + m_r[Rn] = m_sr & T; +} + +/* MUL.L Rm,Rn */ +inline void sh34_base_device::MULL(const uint16_t opcode) +{ + m_macl = m_r[Rn] * m_r[Rm]; + m_sh4_icount--; +} + +/* MULS Rm,Rn */ +inline void sh34_base_device::MULS(const uint16_t opcode) +{ + m_macl = (int16_t) m_r[Rn] * (int16_t) m_r[Rm]; +} + +/* MULU Rm,Rn */ +inline void sh34_base_device::MULU(const uint16_t opcode) +{ + m_macl = (uint16_t) m_r[Rn] * (uint16_t) m_r[Rm]; +} + +/* NEG Rm,Rn */ +inline void sh34_base_device::NEG(const uint16_t opcode) +{ + m_r[Rn] = 0 - m_r[Rm]; +} + +/* NEGC Rm,Rn */ +inline void sh34_base_device::NEGC(const uint16_t opcode) +{ + uint32_t temp; + + temp = m_r[Rm]; + m_r[Rn] = -temp - (m_sr & T); + if (temp || (m_sr & T)) + m_sr |= T; + else + m_sr &= ~T; +} + +/* NOP */ +inline void sh34_base_device::NOP(const uint16_t opcode) +{ +} + +/* NOT Rm,Rn */ +inline void sh34_base_device::NOT(const uint16_t opcode) +{ + m_r[Rn] = ~m_r[Rm]; +} + +/* OR Rm,Rn */ +inline void sh34_base_device::OR(const uint16_t opcode) +{ + m_r[Rn] |= m_r[Rm]; +} + +/* OR #imm,R0 */ +inline void sh34_base_device::ORI(const uint16_t opcode) +{ + m_r[0] |= (opcode&0xff); + m_sh4_icount -= 2; +} + +/* OR.B #imm,@(R0,GBR) */ +inline void sh34_base_device::ORM(const uint16_t opcode) +{ + uint32_t temp; + + m_ea = m_gbr + m_r[0]; + temp = RB( m_ea ); + temp |= (opcode&0xff); + WB(m_ea, temp ); +} + +/* ROTCL Rn */ +inline void sh34_base_device::ROTCL(const uint16_t opcode) +{ + uint32_t n = Rn; + + uint32_t temp; + + temp = (m_r[n] >> 31) & T; + m_r[n] = (m_r[n] << 1) | (m_sr & T); + m_sr = (m_sr & ~T) | temp; +} + +/* ROTCR Rn */ +inline void sh34_base_device::ROTCR(const uint16_t opcode) +{ + uint32_t n = Rn; + + uint32_t temp; + temp = (m_sr & T) << 31; + if (m_r[n] & T) + m_sr |= T; + else + m_sr &= ~T; + m_r[n] = (m_r[n] >> 1) | temp; +} + +/* ROTL Rn */ +inline void sh34_base_device::ROTL(const uint16_t opcode) +{ + uint32_t n = Rn; + + m_sr = (m_sr & ~T) | ((m_r[n] >> 31) & T); + m_r[n] = (m_r[n] << 1) | (m_r[n] >> 31); +} + +/* ROTR Rn */ +inline void sh34_base_device::ROTR(const uint16_t opcode) +{ + uint32_t n = Rn; + + m_sr = (m_sr & ~T) | (m_r[n] & T); + m_r[n] = (m_r[n] >> 1) | (m_r[n] << 31); +} + +/* RTE */ +inline void sh34_base_device::RTE(const uint16_t opcode) +{ + m_delay = m_ea = m_spc; + if ((machine().debug_flags & DEBUG_FLAG_ENABLED) != 0) + sh4_syncronize_register_bank((m_sr & sRB) >> 29); + if ((m_ssr & sRB) != (m_sr & sRB)) + sh4_change_register_bank(m_ssr & sRB ? 1 : 0); + m_sr = m_ssr; + m_sh4_icount--; + sh4_exception_recompute(); +} + +/* RTS */ +inline void sh34_base_device::RTS(const uint16_t opcode) +{ + m_delay = m_ea = m_pr; + m_sh4_icount--; +} + +/* SETT */ +inline void sh34_base_device::SETT(const uint16_t opcode) +{ + m_sr |= T; +} + +/* SHAL Rn (same as SHLL) */ +inline void sh34_base_device::SHAL(const uint16_t opcode) +{ + uint32_t n = Rn; + + m_sr = (m_sr & ~T) | ((m_r[n] >> 31) & T); + m_r[n] <<= 1; +} + +/* SHAR Rn */ +inline void sh34_base_device::SHAR(const uint16_t opcode) +{ + uint32_t n = Rn; + + m_sr = (m_sr & ~T) | (m_r[n] & T); + m_r[n] = (uint32_t)((int32_t)m_r[n] >> 1); +} + +/* SHLL Rn (same as SHAL) */ +inline void sh34_base_device::SHLL(const uint16_t opcode) +{ + uint32_t n = Rn; + + m_sr = (m_sr & ~T) | ((m_r[n] >> 31) & T); + m_r[n] <<= 1; +} + +/* SHLL2 Rn */ +inline void sh34_base_device::SHLL2(const uint16_t opcode) +{ + m_r[Rn] <<= 2; +} + +/* SHLL8 Rn */ +inline void sh34_base_device::SHLL8(const uint16_t opcode) +{ + m_r[Rn] <<= 8; +} + +/* SHLL16 Rn */ +inline void sh34_base_device::SHLL16(const uint16_t opcode) +{ + m_r[Rn] <<= 16; +} + +/* SHLR Rn */ +inline void sh34_base_device::SHLR(const uint16_t opcode) +{ + uint32_t n = Rn; + + m_sr = (m_sr & ~T) | (m_r[n] & T); + m_r[n] >>= 1; +} + +/* SHLR2 Rn */ +inline void sh34_base_device::SHLR2(const uint16_t opcode) +{ + m_r[Rn] >>= 2; +} + +/* SHLR8 Rn */ +inline void sh34_base_device::SHLR8(const uint16_t opcode) +{ + m_r[Rn] >>= 8; +} + +/* SHLR16 Rn */ +inline void sh34_base_device::SHLR16(const uint16_t opcode) +{ + m_r[Rn] >>= 16; +} + +/* SLEEP */ +inline void sh34_base_device::SLEEP(const uint16_t opcode) +{ + /* 0 = normal mode */ + /* 1 = enters into power-down mode */ + /* 2 = go out the power-down mode after an exception */ + if(m_sleep_mode != 2) + m_pc -= 2; + m_sh4_icount -= 2; + /* Wait_for_exception; */ + if(m_sleep_mode == 0) + m_sleep_mode = 1; + else if(m_sleep_mode == 2) + m_sleep_mode = 0; +} + +/* STC SR,Rn */ +inline void sh34_base_device::STCSR(const uint16_t opcode) +{ + m_r[Rn] = m_sr; +} + +/* STC GBR,Rn */ +inline void sh34_base_device::STCGBR(const uint16_t opcode) +{ + m_r[Rn] = m_gbr; +} + +/* STC VBR,Rn */ +inline void sh34_base_device::STCVBR(const uint16_t opcode) +{ + m_r[Rn] = m_vbr; +} + +/* STC.L SR,@-Rn */ +inline void sh34_base_device::STCMSR(const uint16_t opcode) +{ + uint32_t n = Rn; + + m_r[n] -= 4; + m_ea = m_r[n]; + WL(m_ea, m_sr ); + m_sh4_icount--; +} + +/* STC.L GBR,@-Rn */ +inline void sh34_base_device::STCMGBR(const uint16_t opcode) +{ + uint32_t n = Rn; + + m_r[n] -= 4; + m_ea = m_r[n]; + WL(m_ea, m_gbr ); + m_sh4_icount--; +} + +/* STC.L VBR,@-Rn */ +inline void sh34_base_device::STCMVBR(const uint16_t opcode) +{ + uint32_t n = Rn; + + m_r[n] -= 4; + m_ea = m_r[n]; + WL(m_ea, m_vbr ); + m_sh4_icount--; +} + +/* STS MACH,Rn */ +inline void sh34_base_device::STSMACH(const uint16_t opcode) +{ + m_r[Rn] = m_mach; +} + +/* STS MACL,Rn */ +inline void sh34_base_device::STSMACL(const uint16_t opcode) +{ + m_r[Rn] = m_macl; +} + +/* STS PR,Rn */ +inline void sh34_base_device::STSPR(const uint16_t opcode) +{ + m_r[Rn] = m_pr; +} + +/* STS.L MACH,@-Rn */ +inline void sh34_base_device::STSMMACH(const uint16_t opcode) +{ + uint32_t n = Rn; + + m_r[n] -= 4; + m_ea = m_r[n]; + WL(m_ea, m_mach ); +} + +/* STS.L MACL,@-Rn */ +inline void sh34_base_device::STSMMACL(const uint16_t opcode) +{ + uint32_t n = Rn; + + m_r[n] -= 4; + m_ea = m_r[n]; + WL(m_ea, m_macl ); +} + +/* STS.L PR,@-Rn */ +inline void sh34_base_device::STSMPR(const uint16_t opcode) +{ + uint32_t n = Rn; + + m_r[n] -= 4; + m_ea = m_r[n]; + WL(m_ea, m_pr ); +} + +/* SUB Rm,Rn */ +inline void sh34_base_device::SUB(const uint16_t opcode) +{ + m_r[Rn] -= m_r[Rm]; +} + +/* SUBC Rm,Rn */ +inline void sh34_base_device::SUBC(const uint16_t opcode) +{ + uint32_t m = Rm; uint32_t n = Rn; + + uint32_t tmp0, tmp1; + + tmp1 = m_r[n] - m_r[m]; + tmp0 = m_r[n]; + m_r[n] = tmp1 - (m_sr & T); + if (tmp0 < tmp1) + m_sr |= T; + else + m_sr &= ~T; + if (tmp1 < m_r[n]) + m_sr |= T; +} + +/* SUBV Rm,Rn */ +inline void sh34_base_device::SUBV(const uint16_t opcode) +{ + uint32_t m = Rm; uint32_t n = Rn; + + int32_t dest, src, ans; + + if ((int32_t) m_r[n] >= 0) + dest = 0; + else + dest = 1; + if ((int32_t) m_r[m] >= 0) + src = 0; + else + src = 1; + src += dest; + m_r[n] -= m_r[m]; + if ((int32_t) m_r[n] >= 0) + ans = 0; + else + ans = 1; + ans += dest; + if (src == 1) + { + if (ans == 1) + m_sr |= T; + else + m_sr &= ~T; + } + else + m_sr &= ~T; +} + +/* SWAP.B Rm,Rn */ +inline void sh34_base_device::SWAPB(const uint16_t opcode) +{ + uint32_t m = Rm; uint32_t n = Rn; + + uint32_t temp0, temp1; + + temp0 = m_r[m] & 0xffff0000; + temp1 = (m_r[m] & 0x000000ff) << 8; + m_r[n] = (m_r[m] >> 8) & 0x000000ff; + m_r[n] = m_r[n] | temp1 | temp0; +} + +/* SWAP.W Rm,Rn */ +inline void sh34_base_device::SWAPW(const uint16_t opcode) +{ + uint32_t m = Rm; uint32_t n = Rn; + + uint32_t temp; + + temp = (m_r[m] >> 16) & 0x0000ffff; + m_r[n] = (m_r[m] << 16) | temp; +} + +/* TAS.B @Rn */ +inline void sh34_base_device::TAS(const uint16_t opcode) +{ + uint32_t n = Rn; + + uint32_t temp; + m_ea = m_r[n]; + /* Bus Lock enable */ + temp = RB( m_ea ); + if (temp == 0) + m_sr |= T; + else + m_sr &= ~T; + temp |= 0x80; + /* Bus Lock disable */ + WB(m_ea, temp ); + m_sh4_icount -= 3; +} + +/* TRAPA #imm */ +inline void sh34_base_device::TRAPA(const uint16_t opcode) +{ + uint32_t imm = opcode & 0xff; + + if (m_cpu_type == CPU_TYPE_SH4) + { + m_m[TRA] = imm << 2; + } + else /* SH3 */ + { + m_sh3internal_upper[SH3_TRA_ADDR] = imm << 2; + } + + + m_ssr = m_sr; + m_spc = m_pc; + m_sgr = m_r[15]; + + m_sr |= MD; + if ((machine().debug_flags & DEBUG_FLAG_ENABLED) != 0) + sh4_syncronize_register_bank((m_sr & sRB) >> 29); + if (!(m_sr & sRB)) + sh4_change_register_bank(1); + m_sr |= sRB; + m_sr |= BL; + sh4_exception_recompute(); + + if (m_cpu_type == CPU_TYPE_SH4) + { + m_m[EXPEVT] = 0x00000160; + } + else /* SH3 */ + { + m_sh3internal_upper[SH3_EXPEVT_ADDR] = 0x00000160; + } + + m_pc = m_vbr + 0x00000100; + + m_sh4_icount -= 7; +} + +/* TST Rm,Rn */ +inline void sh34_base_device::TST(const uint16_t opcode) +{ + if ((m_r[Rn] & m_r[Rm]) == 0) + m_sr |= T; + else + m_sr &= ~T; +} + +/* TST #imm,R0 */ +inline void sh34_base_device::TSTI(const uint16_t opcode) +{ + uint32_t imm = opcode & 0xff; + + if ((imm & m_r[0]) == 0) + m_sr |= T; + else + m_sr &= ~T; +} + +/* TST.B #imm,@(R0,GBR) */ +inline void sh34_base_device::TSTM(const uint16_t opcode) +{ + uint32_t imm = opcode & 0xff; + + m_ea = m_gbr + m_r[0]; + if ((imm & RB( m_ea )) == 0) + m_sr |= T; + else + m_sr &= ~T; + m_sh4_icount -= 2; +} + +/* XOR Rm,Rn */ +inline void sh34_base_device::XOR(const uint16_t opcode) +{ + m_r[Rn] ^= m_r[Rm]; +} + +/* XOR #imm,R0 */ +inline void sh34_base_device::XORI(const uint16_t opcode) +{ + uint32_t imm = opcode & 0xff; + m_r[0] ^= imm; +} + +/* XOR.B #imm,@(R0,GBR) */ +inline void sh34_base_device::XORM(const uint16_t opcode) +{ + uint32_t imm = opcode & 0xff; + uint32_t temp; + + m_ea = m_gbr + m_r[0]; + temp = RB( m_ea ); + temp ^= imm; + WB(m_ea, temp ); + m_sh4_icount -= 2; +} + +/* XTRCT Rm,Rn */ +inline void sh34_base_device::XTRCT(const uint16_t opcode) +{ + uint32_t m = Rm; uint32_t n = Rn; + + uint32_t temp; + + temp = (m_r[m] << 16) & 0xffff0000; + m_r[n] = (m_r[n] >> 16) & 0x0000ffff; + m_r[n] |= temp; +} + +/* STC SSR,Rn */ +inline void sh34_base_device::STCSSR(const uint16_t opcode) +{ + m_r[Rn] = m_ssr; +} + +/* STC SPC,Rn */ +inline void sh34_base_device::STCSPC(const uint16_t opcode) +{ + m_r[Rn] = m_spc; +} + +/* STC SGR,Rn */ +inline void sh34_base_device::STCSGR(const uint16_t opcode) +{ + m_r[Rn] = m_sgr; +} + +/* STS FPUL,Rn */ +inline void sh34_base_device::STSFPUL(const uint16_t opcode) +{ + m_r[Rn] = m_fpul; +} + +/* STS FPSCR,Rn */ +inline void sh34_base_device::STSFPSCR(const uint16_t opcode) +{ + m_r[Rn] = m_fpscr & 0x003FFFFF; +} + +/* STC DBR,Rn */ +inline void sh34_base_device::STCDBR(const uint16_t opcode) +{ + m_r[Rn] = m_dbr; +} + +/* STCRBANK Rm_BANK,Rn */ +inline void sh34_base_device::STCRBANK(const uint16_t opcode) +{ + uint32_t m = Rm; + + m_r[Rn] = m_rbnk[m_sr&sRB ? 0 : 1][m & 7]; +} + +/* STCMRBANK Rm_BANK,@-Rn */ +inline void sh34_base_device::STCMRBANK(const uint16_t opcode) +{ + uint32_t m = Rm; uint32_t n = Rn; + + m_r[n] -= 4; + m_ea = m_r[n]; + WL(m_ea, m_rbnk[m_sr&sRB ? 0 : 1][m & 7]); + m_sh4_icount--; +} + +/* MOVCA.L R0,@Rn */ +inline void sh34_base_device::MOVCAL(const uint16_t opcode) +{ + m_ea = m_r[Rn]; + WL(m_ea, m_r[0] ); +} + +inline void sh34_base_device::CLRS(const uint16_t opcode) +{ + m_sr &= ~S; +} + +inline void sh34_base_device::SETS(const uint16_t opcode) +{ + m_sr |= S; +} + +/* STS.L SGR,@-Rn */ +inline void sh34_base_device::STCMSGR(const uint16_t opcode) +{ + uint32_t n = Rn; + + m_r[n] -= 4; + m_ea = m_r[n]; + WL(m_ea, m_sgr ); +} + +/* STS.L FPUL,@-Rn */ +inline void sh34_base_device::STSMFPUL(const uint16_t opcode) +{ + uint32_t n = Rn; + + m_r[n] -= 4; + m_ea = m_r[n]; + WL(m_ea, m_fpul ); +} + +/* STS.L FPSCR,@-Rn */ +inline void sh34_base_device::STSMFPSCR(const uint16_t opcode) +{ + uint32_t n = Rn; + + m_r[n] -= 4; + m_ea = m_r[n]; + WL(m_ea, m_fpscr & 0x003FFFFF); +} + +/* STC.L DBR,@-Rn */ +inline void sh34_base_device::STCMDBR(const uint16_t opcode) +{ + uint32_t n = Rn; + + m_r[n] -= 4; + m_ea = m_r[n]; + WL(m_ea, m_dbr ); +} + +/* STC.L SSR,@-Rn */ +inline void sh34_base_device::STCMSSR(const uint16_t opcode) +{ + uint32_t n = Rn; + + m_r[n] -= 4; + m_ea = m_r[n]; + WL(m_ea, m_ssr ); +} + +/* STC.L SPC,@-Rn */ +inline void sh34_base_device::STCMSPC(const uint16_t opcode) +{ + uint32_t n = Rn; + + m_r[n] -= 4; + m_ea = m_r[n]; + WL(m_ea, m_spc ); +} + +/* LDS.L @Rm+,FPUL */ +inline void sh34_base_device::LDSMFPUL(const uint16_t opcode) +{ + m_ea = m_r[Rn]; + m_fpul = RL(m_ea ); + m_r[Rn] += 4; +} + +/* LDS.L @Rm+,FPSCR */ +inline void sh34_base_device::LDSMFPSCR(const uint16_t opcode) +{ + uint32_t s; + + s = m_fpscr; + m_ea = m_r[Rn]; + m_fpscr = RL(m_ea ); + m_fpscr &= 0x003FFFFF; + m_r[Rn] += 4; + if ((s & FR) != (m_fpscr & FR)) + sh4_swap_fp_registers(); +#ifdef LSB_FIRST + if ((s & PR) != (m_fpscr & PR)) + sh4_swap_fp_couples(); +#endif + m_fpu_sz = (m_fpscr & SZ) ? 1 : 0; + m_fpu_pr = (m_fpscr & PR) ? 1 : 0; +} + +/* LDC.L @Rm+,DBR */ +inline void sh34_base_device::LDCMDBR(const uint16_t opcode) +{ + m_ea = m_r[Rn]; + m_dbr = RL(m_ea ); + m_r[Rn] += 4; +} + +/* LDC.L @Rn+,Rm_BANK */ +inline void sh34_base_device::LDCMRBANK(const uint16_t opcode) +{ + uint32_t m = Rm; uint32_t n = Rn; + + m_ea = m_r[n]; + m_rbnk[m_sr&sRB ? 0 : 1][m & 7] = RL(m_ea ); + m_r[n] += 4; +} + +/* LDC.L @Rm+,SSR */ +inline void sh34_base_device::LDCMSSR(const uint16_t opcode) +{ + m_ea = m_r[Rn]; + m_ssr = RL(m_ea ); + m_r[Rn] += 4; +} + +/* LDC.L @Rm+,SPC */ +inline void sh34_base_device::LDCMSPC(const uint16_t opcode) +{ + m_ea = m_r[Rn]; + m_spc = RL(m_ea ); + m_r[Rn] += 4; +} + +/* LDS Rm,FPUL */ +inline void sh34_base_device::LDSFPUL(const uint16_t opcode) +{ + m_fpul = m_r[Rn]; +} + +/* LDS Rm,FPSCR */ +inline void sh34_base_device::LDSFPSCR(const uint16_t opcode) +{ + uint32_t s; + + s = m_fpscr; + m_fpscr = m_r[Rn] & 0x003FFFFF; + if ((s & FR) != (m_fpscr & FR)) + sh4_swap_fp_registers(); +#ifdef LSB_FIRST + if ((s & PR) != (m_fpscr & PR)) + sh4_swap_fp_couples(); +#endif + m_fpu_sz = (m_fpscr & SZ) ? 1 : 0; + m_fpu_pr = (m_fpscr & PR) ? 1 : 0; +} + +/* LDC Rm,DBR */ +inline void sh34_base_device::LDCDBR(const uint16_t opcode) +{ + m_dbr = m_r[Rn]; +} + +/* SHAD Rm,Rn */ +inline void sh34_base_device::SHAD(const uint16_t opcode) +{ + uint32_t m = Rm; uint32_t n = Rn; + + if ((m_r[m] & 0x80000000) == 0) + m_r[n] = m_r[n] << (m_r[m] & 0x1F); + else if ((m_r[m] & 0x1F) == 0) { + if ((m_r[n] & 0x80000000) == 0) + m_r[n] = 0; + else + m_r[n] = 0xFFFFFFFF; + } else + m_r[n]=(int32_t)m_r[n] >> ((~m_r[m] & 0x1F)+1); +} + +/* SHLD Rm,Rn */ +inline void sh34_base_device::SHLD(const uint16_t opcode) +{ + uint32_t m = Rm; uint32_t n = Rn; + + if ((m_r[m] & 0x80000000) == 0) + m_r[n] = m_r[n] << (m_r[m] & 0x1F); + else if ((m_r[m] & 0x1F) == 0) + m_r[n] = 0; + else + m_r[n] = m_r[n] >> ((~m_r[m] & 0x1F)+1); +} + +/* LDCRBANK Rn,Rm_BANK */ +inline void sh34_base_device::LDCRBANK(const uint16_t opcode) +{ + uint32_t m = Rm; + + m_rbnk[m_sr&sRB ? 0 : 1][m & 7] = m_r[Rn]; +} + +/* LDC Rm,SSR */ +inline void sh34_base_device::LDCSSR(const uint16_t opcode) +{ + m_ssr = m_r[Rn]; +} + +/* LDC Rm,SPC */ +inline void sh34_base_device::LDCSPC(const uint16_t opcode) +{ + m_spc = m_r[Rn]; +} + +/* PREF @Rn */ +inline void sh34_base_device::PREFM(const uint16_t opcode) +{ + int a; + uint32_t addr,dest,sq; + + addr = m_r[Rn]; // address + if ((addr >= 0xE0000000) && (addr <= 0xE3FFFFFF)) + { + if (m_sh4_mmu_enabled) + { + addr = addr & 0xFFFFFFE0; + dest = sh4_getsqremap(addr); // good enough for naomi-gd rom, probably not much else + + } + else + { + sq = (addr & 0x20) >> 5; + dest = addr & 0x03FFFFE0; + if (sq == 0) + { + if (m_cpu_type == CPU_TYPE_SH4) + { + dest |= (m_m[QACR0] & 0x1C) << 24; + } + else + { + fatalerror("m_cpu_type != CPU_TYPE_SH4 but access internal regs\n"); + } + } + else + { + if (m_cpu_type == CPU_TYPE_SH4) + { + dest |= (m_m[QACR1] & 0x1C) << 24; + } + else + { + fatalerror("m_cpu_type != CPU_TYPE_SH4 but access internal regs\n"); + } + + } + addr = addr & 0xFFFFFFE0; + } + + for (a = 0;a < 4;a++) + { + // shouldn't be causing a memory read, should store sq writes in registers. + m_program->write_qword(dest, m_program->read_qword(addr)); + addr += 8; + dest += 8; + } + } +} + +/***************************************************************************** + * OPCODE DISPATCHERS + *****************************************************************************/ + +// TODO: current SZ=1(64bit) FMOVs correct for SH4 in LE mode only + +/* FMOV.S @Rm+,FRn PR=0 SZ=0 1111nnnnmmmm1001 */ +/* FMOV @Rm+,DRn PR=0 SZ=1 1111nnn0mmmm1001 */ +/* FMOV @Rm+,XDn PR=0 SZ=1 1111nnn1mmmm1001 */ +/* FMOV @Rm+,XDn PR=1 1111nnn1mmmm1001 */ +inline void sh34_base_device::FMOVMRIFR(const uint16_t opcode) +{ + uint32_t m = Rm; uint32_t n = Rn; + + if (m_fpu_sz) { /* SZ = 1 */ + if (n & 1) { + n &= 14; +#ifdef LSB_FIRST + n ^= m_fpu_pr; +#endif + m_ea = m_r[m]; + m_xf[n] = RL(m_ea ); + m_r[m] += 4; + m_xf[n^1] = RL(m_ea+4 ); + m_r[m] += 4; + } else { +#ifdef LSB_FIRST + n ^= m_fpu_pr; +#endif + m_ea = m_r[m]; + m_fr[n] = RL(m_ea ); + m_r[m] += 4; + m_fr[n^1] = RL(m_ea+4 ); + m_r[m] += 4; + } + } else { /* SZ = 0 */ + m_ea = m_r[m]; +#ifdef LSB_FIRST + n ^= m_fpu_pr; +#endif + m_fr[n] = RL(m_ea ); + m_r[m] += 4; + } +} + +/* FMOV.S FRm,@Rn PR=0 SZ=0 1111nnnnmmmm1010 */ +/* FMOV DRm,@Rn PR=0 SZ=1 1111nnnnmmm01010 */ +/* FMOV XDm,@Rn PR=0 SZ=1 1111nnnnmmm11010 */ +/* FMOV XDm,@Rn PR=1 1111nnnnmmm11010 */ +inline void sh34_base_device::FMOVFRMR(const uint16_t opcode) +{ + uint32_t m = Rm; uint32_t n = Rn; + + if (m_fpu_sz) { /* SZ = 1 */ + if (m & 1) { + m &= 14; +#ifdef LSB_FIRST + m ^= m_fpu_pr; +#endif + m_ea = m_r[n]; + WL(m_ea,m_xf[m] ); + WL(m_ea+4,m_xf[m^1] ); + } else { +#ifdef LSB_FIRST + m ^= m_fpu_pr; +#endif + m_ea = m_r[n]; + WL(m_ea,m_fr[m] ); + WL(m_ea+4,m_fr[m^1] ); + } + } else { /* SZ = 0 */ + m_ea = m_r[n]; +#ifdef LSB_FIRST + m ^= m_fpu_pr; +#endif + WL(m_ea,m_fr[m] ); + } +} + +/* FMOV.S FRm,@-Rn PR=0 SZ=0 1111nnnnmmmm1011 */ +/* FMOV DRm,@-Rn PR=0 SZ=1 1111nnnnmmm01011 */ +/* FMOV XDm,@-Rn PR=0 SZ=1 1111nnnnmmm11011 */ +/* FMOV XDm,@-Rn PR=1 1111nnnnmmm11011 */ +inline void sh34_base_device::FMOVFRMDR(const uint16_t opcode) +{ + uint32_t m = Rm; uint32_t n = Rn; + + if (m_fpu_sz) { /* SZ = 1 */ + if (m & 1) { + m &= 14; +#ifdef LSB_FIRST + m ^= m_fpu_pr; +#endif + m_r[n] -= 8; + m_ea = m_r[n]; + WL(m_ea,m_xf[m] ); + WL(m_ea+4,m_xf[m^1] ); + } else { +#ifdef LSB_FIRST + m ^= m_fpu_pr; +#endif + m_r[n] -= 8; + m_ea = m_r[n]; + WL(m_ea,m_fr[m] ); + WL(m_ea+4,m_fr[m^1] ); + } + } else { /* SZ = 0 */ + m_r[n] -= 4; + m_ea = m_r[n]; +#ifdef LSB_FIRST + m ^= m_fpu_pr; +#endif + WL(m_ea,m_fr[m] ); + } +} + +/* FMOV.S FRm,@(R0,Rn) PR=0 SZ=0 1111nnnnmmmm0111 */ +/* FMOV DRm,@(R0,Rn) PR=0 SZ=1 1111nnnnmmm00111 */ +/* FMOV XDm,@(R0,Rn) PR=0 SZ=1 1111nnnnmmm10111 */ +/* FMOV XDm,@(R0,Rn) PR=1 1111nnnnmmm10111 */ +inline void sh34_base_device::FMOVFRS0(const uint16_t opcode) +{ + uint32_t m = Rm; uint32_t n = Rn; + + if (m_fpu_sz) { /* SZ = 1 */ + if (m & 1) { + m &= 14; +#ifdef LSB_FIRST + m ^= m_fpu_pr; +#endif + m_ea = m_r[0] + m_r[n]; + WL(m_ea,m_xf[m] ); + WL(m_ea+4,m_xf[m^1] ); + } else { +#ifdef LSB_FIRST + m ^= m_fpu_pr; +#endif + m_ea = m_r[0] + m_r[n]; + WL(m_ea,m_fr[m] ); + WL(m_ea+4,m_fr[m^1] ); + } + } else { /* SZ = 0 */ + m_ea = m_r[0] + m_r[n]; +#ifdef LSB_FIRST + m ^= m_fpu_pr; +#endif + WL(m_ea,m_fr[m] ); + } +} + +/* FMOV.S @(R0,Rm),FRn PR=0 SZ=0 1111nnnnmmmm0110 */ +/* FMOV @(R0,Rm),DRn PR=0 SZ=1 1111nnn0mmmm0110 */ +/* FMOV @(R0,Rm),XDn PR=0 SZ=1 1111nnn1mmmm0110 */ +/* FMOV @(R0,Rm),XDn PR=1 1111nnn1mmmm0110 */ +inline void sh34_base_device::FMOVS0FR(const uint16_t opcode) +{ + uint32_t m = Rm; uint32_t n = Rn; + + if (m_fpu_sz) { /* SZ = 1 */ + if (n & 1) { + n &= 14; +#ifdef LSB_FIRST + n ^= m_fpu_pr; +#endif + m_ea = m_r[0] + m_r[m]; + m_xf[n] = RL(m_ea ); + m_xf[n^1] = RL(m_ea+4 ); + } else { +#ifdef LSB_FIRST + n ^= m_fpu_pr; +#endif + m_ea = m_r[0] + m_r[m]; + m_fr[n] = RL(m_ea ); + m_fr[n^1] = RL(m_ea+4 ); + } + } else { /* SZ = 0 */ + m_ea = m_r[0] + m_r[m]; +#ifdef LSB_FIRST + n ^= m_fpu_pr; +#endif + m_fr[n] = RL(m_ea ); + } +} + +/* FMOV.S @Rm,FRn PR=0 SZ=0 1111nnnnmmmm1000 */ +/* FMOV @Rm,DRn PR=0 SZ=1 1111nnn0mmmm1000 */ +/* FMOV @Rm,XDn PR=0 SZ=1 1111nnn1mmmm1000 */ +/* FMOV @Rm,XDn PR=1 1111nnn1mmmm1000 */ +/* FMOV @Rm,DRn PR=1 1111nnn0mmmm1000 */ +inline void sh34_base_device::FMOVMRFR(const uint16_t opcode) +{ + uint32_t m = Rm; uint32_t n = Rn; + + if (m_fpu_sz) { /* SZ = 1 */ + if (n & 1) { + n &= 14; +#ifdef LSB_FIRST + n ^= m_fpu_pr; +#endif + m_ea = m_r[m]; + m_xf[n] = RL(m_ea ); + m_xf[n^1] = RL(m_ea+4 ); + } else { +#ifdef LSB_FIRST + n ^= m_fpu_pr; +#endif + m_ea = m_r[m]; + m_fr[n] = RL(m_ea ); + m_fr[n^1] = RL(m_ea+4 ); + } + } else { /* SZ = 0 */ + m_ea = m_r[m]; +#ifdef LSB_FIRST + n ^= m_fpu_pr; +#endif + m_fr[n] = RL(m_ea ); + } +} + +/* FMOV FRm,FRn PR=0 SZ=0 FRm -> FRn 1111nnnnmmmm1100 */ +/* FMOV DRm,DRn PR=0 SZ=1 DRm -> DRn 1111nnn0mmm01100 */ +/* FMOV XDm,DRn PR=1 XDm -> DRn 1111nnn0mmm11100 */ +/* FMOV DRm,XDn PR=1 DRm -> XDn 1111nnn1mmm01100 */ +/* FMOV XDm,XDn PR=1 XDm -> XDn 1111nnn1mmm11100 */ +inline void sh34_base_device::FMOVFR(const uint16_t opcode) +{ + uint32_t m = Rm; uint32_t n = Rn; + + if (m_fpu_sz == 0) { /* SZ = 0 */ +#ifdef LSB_FIRST + n ^= m_fpu_pr; + m ^= m_fpu_pr; +#endif + m_fr[n] = m_fr[m]; + } + else { /* SZ = 1 */ + if (m & 1) { + if (n & 1) { + m_xf[n & 14] = m_xf[m & 14]; + m_xf[n | 1] = m_xf[m | 1]; + } else { + m_fr[n] = m_xf[m & 14]; + m_fr[n | 1] = m_xf[m | 1]; + } + } else { + if (n & 1) { + m_xf[n & 14] = m_fr[m]; + m_xf[n | 1] = m_fr[m | 1]; // (a&14)+1 -> a|1 + } else { + m_fr[n] = m_fr[m]; + m_fr[n | 1] = m_fr[m | 1]; + } + } + } +} + +/* FLDI1 FRn 1111nnnn10011101 */ +inline void sh34_base_device::FLDI1(const uint16_t opcode) +{ +#ifdef LSB_FIRST + m_fr[Rn ^ m_fpu_pr] = 0x3F800000; +#else + m_fr[Rn] = 0x3F800000; +#endif +} + +/* FLDI0 FRn 1111nnnn10001101 */ +inline void sh34_base_device::FLDI0(const uint16_t opcode) +{ +#ifdef LSB_FIRST + m_fr[Rn ^ m_fpu_pr] = 0; +#else + m_fr[Rn] = 0; +#endif +} + +/* FLDS FRm,FPUL 1111mmmm00011101 */ +inline void sh34_base_device:: FLDS(const uint16_t opcode) +{ +#ifdef LSB_FIRST + m_fpul = m_fr[Rn ^ m_fpu_pr]; +#else + m_fpul = m_fr[Rn]; +#endif +} + +/* FSTS FPUL,FRn 1111nnnn00001101 */ +inline void sh34_base_device:: FSTS(const uint16_t opcode) +{ +#ifdef LSB_FIRST + m_fr[Rn ^ m_fpu_pr] = m_fpul; +#else + m_fr[Rn] = m_fpul; +#endif +} + +/* FRCHG 1111101111111101 */ +void sh34_base_device::FRCHG() +{ + m_fpscr ^= FR; + sh4_swap_fp_registers(); +} + +/* FSCHG 1111001111111101 */ +void sh34_base_device::FSCHG() +{ + m_fpscr ^= SZ; + m_fpu_sz = (m_fpscr & SZ) ? 1 : 0; +} + +/* FTRC FRm,FPUL PR=0 1111mmmm00111101 */ +/* FTRC DRm,FPUL PR=1 1111mmm000111101 */ +inline void sh34_base_device::FTRC(const uint16_t opcode) +{ + uint32_t n = Rn; + + if (m_fpu_pr) { /* PR = 1 */ + if(n & 1) + fatalerror("SH-4: FTRC opcode used with n %d",n); + + n = n & 14; + *((int32_t *)&m_fpul) = (int32_t)FP_RFD(n); + } else { /* PR = 0 */ + /* read m_fr[n] as float -> truncate -> fpul(32) */ + *((int32_t *)&m_fpul) = (int32_t)FP_RFS(n); + } +} + +/* FLOAT FPUL,FRn PR=0 1111nnnn00101101 */ +/* FLOAT FPUL,DRn PR=1 1111nnn000101101 */ +inline void sh34_base_device::FLOAT(const uint16_t opcode) +{ + uint32_t n = Rn; + + if (m_fpu_pr) { /* PR = 1 */ + if(n & 1) + fatalerror("SH-4: FLOAT opcode used with n %d",n); + + n = n & 14; + FP_RFD(n) = (double)*((int32_t *)&m_fpul); + } else { /* PR = 0 */ + FP_RFS(n) = (float)*((int32_t *)&m_fpul); + } +} + +/* FNEG FRn PR=0 1111nnnn01001101 */ +/* FNEG DRn PR=1 1111nnn001001101 */ +inline void sh34_base_device::FNEG(const uint16_t opcode) +{ + uint32_t n = Rn; + + if (m_fpu_pr) { /* PR = 1 */ + FP_RFD(n) = -FP_RFD(n); + } else { /* PR = 0 */ + FP_RFS(n) = -FP_RFS(n); + } +} + +/* FABS FRn PR=0 1111nnnn01011101 */ +/* FABS DRn PR=1 1111nnn001011101 */ +inline void sh34_base_device::FABS(const uint16_t opcode) +{ + uint32_t n = Rn; + + if (m_fpu_pr) { /* PR = 1 */ +#ifdef LSB_FIRST + n = n | 1; // n & 14 + 1 + m_fr[n] = m_fr[n] & 0x7fffffff; +#else + n = n & 14; + m_fr[n] = m_fr[n] & 0x7fffffff; +#endif + } else { /* PR = 0 */ + m_fr[n] = m_fr[n] & 0x7fffffff; + } +} + +/* FCMP/EQ FRm,FRn PR=0 1111nnnnmmmm0100 */ +/* FCMP/EQ DRm,DRn PR=1 1111nnn0mmm00100 */ +inline void sh34_base_device::FCMP_EQ(const uint16_t opcode) +{ + uint32_t m = Rm; uint32_t n = Rn; + + if (m_fpu_pr) { /* PR = 1 */ + n = n & 14; + m = m & 14; + if (FP_RFD(n) == FP_RFD(m)) + m_sr |= T; + else + m_sr &= ~T; + } else { /* PR = 0 */ + if (FP_RFS(n) == FP_RFS(m)) + m_sr |= T; + else + m_sr &= ~T; + } +} + +/* FCMP/GT FRm,FRn PR=0 1111nnnnmmmm0101 */ +/* FCMP/GT DRm,DRn PR=1 1111nnn0mmm00101 */ +inline void sh34_base_device::FCMP_GT(const uint16_t opcode) +{ + uint32_t m = Rm; uint32_t n = Rn; + + if (m_fpu_pr) { /* PR = 1 */ + n = n & 14; + m = m & 14; + if (FP_RFD(n) > FP_RFD(m)) + m_sr |= T; + else + m_sr &= ~T; + } else { /* PR = 0 */ + if (FP_RFS(n) > FP_RFS(m)) + m_sr |= T; + else + m_sr &= ~T; + } +} + +/* FCNVDS DRm,FPUL PR=1 1111mmm010111101 */ +inline void sh34_base_device::FCNVDS(const uint16_t opcode) +{ + uint32_t n = Rn; + + if (m_fpu_pr) { /* PR = 1 */ + n = n & 14; + if (m_fpscr & RM) + m_fr[n | NATIVE_ENDIAN_VALUE_LE_BE(0,1)] &= 0xe0000000; /* round toward zero*/ + *((float *)&m_fpul) = (float)FP_RFD(n); + } +} + +/* FCNVSD FPUL, DRn PR=1 1111nnn010101101 */ +inline void sh34_base_device::FCNVSD(const uint16_t opcode) +{ + uint32_t n = Rn; + + if (m_fpu_pr) { /* PR = 1 */ + n = n & 14; + FP_RFD(n) = (double)*((float *)&m_fpul); + } +} + +/* FADD FRm,FRn PR=0 1111nnnnmmmm0000 */ +/* FADD DRm,DRn PR=1 1111nnn0mmm00000 */ +inline void sh34_base_device::FADD(const uint16_t opcode) +{ + uint32_t m = Rm; uint32_t n = Rn; + + if (m_fpu_pr) { /* PR = 1 */ + n = n & 14; + m = m & 14; + FP_RFD(n) = FP_RFD(n) + FP_RFD(m); + } else { /* PR = 0 */ + FP_RFS(n) = FP_RFS(n) + FP_RFS(m); + } +} + +/* FSUB FRm,FRn PR=0 1111nnnnmmmm0001 */ +/* FSUB DRm,DRn PR=1 1111nnn0mmm00001 */ +inline void sh34_base_device::FSUB(const uint16_t opcode) +{ + uint32_t m = Rm; uint32_t n = Rn; + + if (m_fpu_pr) { /* PR = 1 */ + n = n & 14; + m = m & 14; + FP_RFD(n) = FP_RFD(n) - FP_RFD(m); + } else { /* PR = 0 */ + FP_RFS(n) = FP_RFS(n) - FP_RFS(m); + } +} + + +/* FMUL FRm,FRn PR=0 1111nnnnmmmm0010 */ +/* FMUL DRm,DRn PR=1 1111nnn0mmm00010 */ +inline void sh34_base_device::FMUL(const uint16_t opcode) +{ + uint32_t m = Rm; uint32_t n = Rn; + + if (m_fpu_pr) { /* PR = 1 */ + n = n & 14; + m = m & 14; + FP_RFD(n) = FP_RFD(n) * FP_RFD(m); + } else { /* PR = 0 */ + FP_RFS(n) = FP_RFS(n) * FP_RFS(m); + } +} + +/* FDIV FRm,FRn PR=0 1111nnnnmmmm0011 */ +/* FDIV DRm,DRn PR=1 1111nnn0mmm00011 */ +inline void sh34_base_device::FDIV(const uint16_t opcode) +{ + uint32_t m = Rm; uint32_t n = Rn; + + if (m_fpu_pr) { /* PR = 1 */ + n = n & 14; + m = m & 14; + if (FP_RFD(m) == 0) + return; + FP_RFD(n) = FP_RFD(n) / FP_RFD(m); + } else { /* PR = 0 */ + if (FP_RFS(m) == 0) + return; + FP_RFS(n) = FP_RFS(n) / FP_RFS(m); + } +} + +/* FMAC FR0,FRm,FRn PR=0 1111nnnnmmmm1110 */ +inline void sh34_base_device::FMAC(const uint16_t opcode) +{ + uint32_t m = Rm; uint32_t n = Rn; + + if (m_fpu_pr == 0) { /* PR = 0 */ + FP_RFS(n) = (FP_RFS(0) * FP_RFS(m)) + FP_RFS(n); + } +} + +/* FSQRT FRn PR=0 1111nnnn01101101 */ +/* FSQRT DRn PR=1 1111nnnn01101101 */ +inline void sh34_base_device::FSQRT(const uint16_t opcode) +{ + uint32_t n = Rn; + + if (m_fpu_pr) { /* PR = 1 */ + n = n & 14; + if (FP_RFD(n) < 0) + return; + FP_RFD(n) = sqrtf(FP_RFD(n)); + } else { /* PR = 0 */ + if (FP_RFS(n) < 0) + return; + FP_RFS(n) = sqrtf(FP_RFS(n)); + } +} + +/* FSRRA FRn PR=0 1111nnnn01111101 */ +inline void sh34_base_device::FSRRA(const uint16_t opcode) +{ + uint32_t n = Rn; + + if (FP_RFS(n) < 0) + return; + FP_RFS(n) = 1.0f / sqrtf(FP_RFS(n)); +} + +/* FSSCA FPUL,FRn PR=0 1111nnn011111101 */ +void sh34_base_device::FSSCA(const uint16_t opcode) +{ + uint32_t n = Rn; + + float angle; + + angle = (((float)(m_fpul & 0xFFFF)) / 65536.0f) * 2.0f * (float) M_PI; + FP_RFS(n) = sinf(angle); + FP_RFS(n+1) = cosf(angle); +} + +/* FIPR FVm,FVn PR=0 1111nnmm11101101 */ +inline void sh34_base_device::FIPR(const uint16_t opcode) +{ + uint32_t n = Rn; + +uint32_t m; +float ml[4]; +int a; + + m = (n & 3) << 2; + n = n & 12; + for (a = 0;a < 4;a++) + ml[a] = FP_RFS(n+a) * FP_RFS(m+a); + FP_RFS(n+3) = ml[0] + ml[1] + ml[2] + ml[3]; +} + +/* FTRV XMTRX,FVn PR=0 1111nn0111111101 */ +void sh34_base_device::FTRV(const uint16_t opcode) +{ + uint32_t n = Rn; + +int i,j; +float sum[4]; + + n = n & 12; + for (i = 0;i < 4;i++) { + sum[i] = 0; + for (j=0;j < 4;j++) + sum[i] += FP_XFS((j << 2) + i)*FP_RFS(n + j); + } + for (i = 0;i < 4;i++) + FP_RFS(n + i) = sum[i]; +} + +inline void sh34_base_device::op1111_0xf13(const uint16_t opcode) +{ + if (opcode & 0x100) { + if (opcode & 0x200) { + switch (opcode & 0xC00) + { + case 0x000: + FSCHG(); + break; + case 0x800: + FRCHG(); + break; + default: + machine().debug_break(); + break; + } + } else { + FTRV(opcode); + } + } else { + FSSCA(opcode); + } +} + +void sh34_base_device::dbreak(const uint16_t opcode) +{ + machine().debug_break(); +} + + +inline void sh34_base_device::op1111_0x13(uint16_t opcode) +{ + switch((opcode >> 4) & 0x0f) + { + case 0x00: FSTS(opcode); break; + case 0x01: FLDS(opcode); break; + case 0x02: FLOAT(opcode); break; + case 0x03: FTRC(opcode); break; + case 0x04: FNEG(opcode); break; + case 0x05: FABS(opcode); break; + case 0x06: FSQRT(opcode); break; + case 0x07: FSRRA(opcode); break; + case 0x08: FLDI0(opcode); break; + case 0x09: FLDI1(opcode); break; + case 0x0a: FCNVSD(opcode); break; + case 0x0b: FCNVDS(opcode); break; + case 0x0c: dbreak(opcode); break; + case 0x0d: dbreak(opcode); break; + case 0x0e: FIPR(opcode); break; + case 0x0f: op1111_0xf13(opcode); break; + } +} + + +/***************************************************************************** + * MAME CPU INTERFACE + *****************************************************************************/ + +void sh34_base_device::device_reset() +{ + m_spc = 0; + m_pr = 0; + m_sr = 0; + m_ssr = 0; + m_gbr = 0; + m_vbr = 0; + m_mach = 0; + m_macl = 0; + memset(m_r, 0, sizeof(m_r)); + memset(m_rbnk, 0, sizeof(m_rbnk)); + m_sgr = 0; + memset(m_fr, 0, sizeof(m_fr)); + memset(m_xf, 0, sizeof(m_xf)); + m_ea = 0; + m_delay = 0; + m_cpu_off = 0; + m_pending_irq = 0; + m_test_irq = 0; + memset(m_exception_priority, 0, sizeof(m_exception_priority)); + memset(m_exception_requesting, 0, sizeof(m_exception_requesting)); + memset(m_m, 0, sizeof(m_m)); + memset(m_sh3internal_upper, 0, sizeof(m_sh3internal_upper)); + memset(m_sh3internal_lower, 0, sizeof(m_sh3internal_lower)); + memset(m_irq_line_state, 0, sizeof(m_irq_line_state)); + m_SH4_TSTR = 0; + m_SH4_TCNT0 = 0; + m_SH4_TCNT1 = 0; + m_SH4_TCNT2 = 0; + m_SH4_TCR0 = 0; + m_SH4_TCR1 = 0; + m_SH4_TCR2 = 0; + m_SH4_TCOR0 = 0; + m_SH4_TCOR1 = 0; + m_SH4_TCOR2 = 0; + m_SH4_TOCR = 0; + m_SH4_TCPR2 = 0; + m_SH4_IPRA = 0; + m_SH4_IPRC = 0; + m_SH4_SAR0 = 0; + m_SH4_SAR1 = 0; + m_SH4_SAR2 = 0; + m_SH4_SAR3 = 0; + m_SH4_DAR0 = 0; + m_SH4_DAR1 = 0; + m_SH4_DAR2 = 0; + m_SH4_DAR3 = 0; + m_SH4_CHCR0 = 0; + m_SH4_CHCR1 = 0; + m_SH4_CHCR2 = 0; + m_SH4_CHCR3 = 0; + m_SH4_DMATCR0 = 0; + m_SH4_DMATCR1 = 0; + m_SH4_DMATCR2 = 0; + m_SH4_DMATCR3 = 0; + m_SH4_DMAOR = 0; + m_nmi_line_state = 0; + m_frt_input = 0; + m_internal_irq_vector = 0; + m_refresh_timer_base = 0; + memset(m_dma_timer_active, 0, sizeof(m_dma_timer_active)); + memset(m_dma_source, 0, sizeof(m_dma_source)); + memset(m_dma_destination, 0, sizeof(m_dma_destination)); + memset(m_dma_count, 0, sizeof(m_dma_count)); + memset(m_dma_wordsize, 0, sizeof(m_dma_wordsize)); + memset(m_dma_source_increment, 0, sizeof(m_dma_source_increment)); + memset(m_dma_destination_increment, 0, sizeof(m_dma_destination_increment)); + memset(m_dma_mode, 0, sizeof(m_dma_mode)); + m_ioport16_pullup = 0; + m_ioport16_direction = 0; + m_ioport4_pullup = 0; + m_ioport4_direction = 0; + + sh4_default_exception_priorities(); + + m_rtc_timer->adjust(attotime::from_hz(128)); + + m_pc = 0xa0000000; + m_ppc = m_pc & AM; + m_r[15] = RL(4); + m_sr = 0x700000f0; + m_fpscr = 0x00040001; + m_fpu_sz = (m_fpscr & SZ) ? 1 : 0; + m_fpu_pr = (m_fpscr & PR) ? 1 : 0; + m_fpul = 0; + m_dbr = 0; + + m_internal_irq_level = -1; + m_irln = 15; + m_sleep_mode = 0; + + m_sh4_mmu_enabled = 0; +} + +/*------------------------------------------------- + sh3_reset - reset the processor +-------------------------------------------------*/ + +void sh3_base_device::device_reset() +{ + sh34_base_device::device_reset(); + + m_SH4_TCOR0 = 0xffffffff; + m_SH4_TCNT0 = 0xffffffff; + m_SH4_TCOR1 = 0xffffffff; + m_SH4_TCNT1 = 0xffffffff; + m_SH4_TCOR2 = 0xffffffff; + m_SH4_TCNT2 = 0xffffffff; +} + +void sh4_base_device::device_reset() +{ + sh34_base_device::device_reset(); + + m_m[RCR2] = 0x09; + m_SH4_TCOR0 = 0xffffffff; + m_SH4_TCNT0 = 0xffffffff; + m_SH4_TCOR1 = 0xffffffff; + m_SH4_TCNT1 = 0xffffffff; + m_SH4_TCOR2 = 0xffffffff; + m_SH4_TCNT2 = 0xffffffff; +} + +inline void sh34_base_device::execute_one_0000(const uint16_t opcode) +{ + switch(opcode & 0xff) + { + // 0x00 + case 0x00: NOP(opcode); break; + case 0x10: NOP(opcode); break; + case 0x20: NOP(opcode); break; + case 0x30: NOP(opcode); break; + case 0x40: NOP(opcode); break; + case 0x50: NOP(opcode); break; + case 0x60: NOP(opcode); break; + case 0x70: NOP(opcode); break; + case 0x80: NOP(opcode); break; + case 0x90: NOP(opcode); break; + case 0xa0: NOP(opcode); break; + case 0xb0: NOP(opcode); break; + case 0xc0: NOP(opcode); break; + case 0xd0: NOP(opcode); break; + case 0xe0: NOP(opcode); break; + case 0xf0: NOP(opcode); break; + // 0x10 + case 0x01: NOP(opcode); break; + case 0x11: NOP(opcode); break; + case 0x21: NOP(opcode); break; + case 0x31: NOP(opcode); break; + case 0x41: NOP(opcode); break; + case 0x51: NOP(opcode); break; + case 0x61: NOP(opcode); break; + case 0x71: NOP(opcode); break; + case 0x81: NOP(opcode); break; + case 0x91: NOP(opcode); break; + case 0xa1: NOP(opcode); break; + case 0xb1: NOP(opcode); break; + case 0xc1: NOP(opcode); break; + case 0xd1: NOP(opcode); break; + case 0xe1: NOP(opcode); break; + case 0xf1: NOP(opcode); break; + // 0x20 + case 0x02: STCSR(opcode); break; + case 0x12: STCGBR(opcode); break; + case 0x22: STCVBR(opcode); break; + case 0x32: STCSSR(opcode); break; + case 0x42: STCSPC(opcode); break; + case 0x52: NOP(opcode); break; + case 0x62: NOP(opcode); break; + case 0x72: NOP(opcode); break; + case 0x82: STCRBANK(opcode); break; + case 0x92: STCRBANK(opcode); break; + case 0xa2: STCRBANK(opcode); break; + case 0xb2: STCRBANK(opcode); break; + case 0xc2: STCRBANK(opcode); break; + case 0xd2: STCRBANK(opcode); break; + case 0xe2: STCRBANK(opcode); break; + case 0xf2: STCRBANK(opcode); break; + // 0x30 + case 0x03: BSRF(opcode); break; + case 0x13: NOP(opcode); break; + case 0x23: BRAF(opcode); break; + case 0x33: NOP(opcode); break; + case 0x43: NOP(opcode); break; + case 0x53: NOP(opcode); break; + case 0x63: NOP(opcode); break; + case 0x73: NOP(opcode); break; + case 0x83: PREFM(opcode); break; + case 0x93: TODO(opcode); break; + case 0xa3: TODO(opcode); break; + case 0xb3: TODO(opcode); break; + case 0xc3: MOVCAL(opcode); break; + case 0xd3: NOP(opcode); break; + case 0xe3: NOP(opcode); break; + case 0xf3: NOP(opcode); break; + // 0x40 + case 0x04: MOVBS0(opcode); break; + case 0x14: MOVBS0(opcode); break; + case 0x24: MOVBS0(opcode); break; + case 0x34: MOVBS0(opcode); break; + case 0x44: MOVBS0(opcode); break; + case 0x54: MOVBS0(opcode); break; + case 0x64: MOVBS0(opcode); break; + case 0x74: MOVBS0(opcode); break; + case 0x84: MOVBS0(opcode); break; + case 0x94: MOVBS0(opcode); break; + case 0xa4: MOVBS0(opcode); break; + case 0xb4: MOVBS0(opcode); break; + case 0xc4: MOVBS0(opcode); break; + case 0xd4: MOVBS0(opcode); break; + case 0xe4: MOVBS0(opcode); break; + case 0xf4: MOVBS0(opcode); break; + // 0x50 + case 0x05: MOVWS0(opcode); break; + case 0x15: MOVWS0(opcode); break; + case 0x25: MOVWS0(opcode); break; + case 0x35: MOVWS0(opcode); break; + case 0x45: MOVWS0(opcode); break; + case 0x55: MOVWS0(opcode); break; + case 0x65: MOVWS0(opcode); break; + case 0x75: MOVWS0(opcode); break; + case 0x85: MOVWS0(opcode); break; + case 0x95: MOVWS0(opcode); break; + case 0xa5: MOVWS0(opcode); break; + case 0xb5: MOVWS0(opcode); break; + case 0xc5: MOVWS0(opcode); break; + case 0xd5: MOVWS0(opcode); break; + case 0xe5: MOVWS0(opcode); break; + case 0xf5: MOVWS0(opcode); break; + // 0x60 + case 0x06: MOVLS0(opcode); break; + case 0x16: MOVLS0(opcode); break; + case 0x26: MOVLS0(opcode); break; + case 0x36: MOVLS0(opcode); break; + case 0x46: MOVLS0(opcode); break; + case 0x56: MOVLS0(opcode); break; + case 0x66: MOVLS0(opcode); break; + case 0x76: MOVLS0(opcode); break; + case 0x86: MOVLS0(opcode); break; + case 0x96: MOVLS0(opcode); break; + case 0xa6: MOVLS0(opcode); break; + case 0xb6: MOVLS0(opcode); break; + case 0xc6: MOVLS0(opcode); break; + case 0xd6: MOVLS0(opcode); break; + case 0xe6: MOVLS0(opcode); break; + case 0xf6: MOVLS0(opcode); break; + // 0x70 + case 0x07: MULL(opcode); break; + case 0x17: MULL(opcode); break; + case 0x27: MULL(opcode); break; + case 0x37: MULL(opcode); break; + case 0x47: MULL(opcode); break; + case 0x57: MULL(opcode); break; + case 0x67: MULL(opcode); break; + case 0x77: MULL(opcode); break; + case 0x87: MULL(opcode); break; + case 0x97: MULL(opcode); break; + case 0xa7: MULL(opcode); break; + case 0xb7: MULL(opcode); break; + case 0xc7: MULL(opcode); break; + case 0xd7: MULL(opcode); break; + case 0xe7: MULL(opcode); break; + case 0xf7: MULL(opcode); break; + // 0x80 + case 0x08: CLRT(opcode); break; + case 0x18: SETT(opcode); break; + case 0x28: CLRMAC(opcode); break; + case 0x38: LDTLB(opcode); break; + case 0x48: CLRS(opcode); break; + case 0x58: SETS(opcode); break; + case 0x68: NOP(opcode); break; + case 0x78: NOP(opcode); break; + case 0x88: CLRT(opcode); break; + case 0x98: SETT(opcode); break; + case 0xa8: CLRMAC(opcode); break; + case 0xb8: LDTLB(opcode); break; + case 0xc8: CLRS(opcode); break; + case 0xd8: SETS(opcode); break; + case 0xe8: NOP(opcode); break; + case 0xf8: NOP(opcode); break; + // 0x90 + case 0x09: NOP(opcode); break; + case 0x19: DIV0U(opcode); break; + case 0x29: MOVT(opcode); break; + case 0x39: NOP(opcode); break; + case 0x49: NOP(opcode); break; + case 0x59: DIV0U(opcode); break; + case 0x69: MOVT(opcode); break; + case 0x79: NOP(opcode); break; + case 0x89: NOP(opcode); break; + case 0x99: DIV0U(opcode); break; + case 0xa9: MOVT(opcode); break; + case 0xb9: NOP(opcode); break; + case 0xc9: NOP(opcode); break; + case 0xd9: DIV0U(opcode); break; + case 0xe9: MOVT(opcode); break; + case 0xf9: NOP(opcode); break; + // 0xa0 + case 0x0a: STSMACH(opcode); break; + case 0x1a: STSMACL(opcode); break; + case 0x2a: STSPR(opcode); break; + case 0x3a: STCSGR(opcode); break; + case 0x4a: NOP(opcode); break; + case 0x5a: STSFPUL(opcode); break; + case 0x6a: STSFPSCR(opcode); break; + case 0x7a: STCDBR(opcode); break; + case 0x8a: STSMACH(opcode); break; + case 0x9a: STSMACL(opcode); break; + case 0xaa: STSPR(opcode); break; + case 0xba: STCSGR(opcode); break; + case 0xca: NOP(opcode); break; + case 0xda: STSFPUL(opcode); break; + case 0xea: STSFPSCR(opcode); break; + case 0xfa: STCDBR(opcode); break; + // 0xb0 + case 0x0b: RTS(opcode); break; + case 0x1b: SLEEP(opcode); break; + case 0x2b: RTE(opcode); break; + case 0x3b: NOP(opcode); break; + case 0x4b: RTS(opcode); break; + case 0x5b: SLEEP(opcode); break; + case 0x6b: RTE(opcode); break; + case 0x7b: NOP(opcode); break; + case 0x8b: RTS(opcode); break; + case 0x9b: SLEEP(opcode); break; + case 0xab: RTE(opcode); break; + case 0xbb: NOP(opcode); break; + case 0xcb: RTS(opcode); break; + case 0xdb: SLEEP(opcode); break; + case 0xeb: RTE(opcode); break; + case 0xfb: NOP(opcode); break; + // 0xc0 + case 0x0c: MOVBL0(opcode); break; + case 0x1c: MOVBL0(opcode); break; + case 0x2c: MOVBL0(opcode); break; + case 0x3c: MOVBL0(opcode); break; + case 0x4c: MOVBL0(opcode); break; + case 0x5c: MOVBL0(opcode); break; + case 0x6c: MOVBL0(opcode); break; + case 0x7c: MOVBL0(opcode); break; + case 0x8c: MOVBL0(opcode); break; + case 0x9c: MOVBL0(opcode); break; + case 0xac: MOVBL0(opcode); break; + case 0xbc: MOVBL0(opcode); break; + case 0xcc: MOVBL0(opcode); break; + case 0xdc: MOVBL0(opcode); break; + case 0xec: MOVBL0(opcode); break; + case 0xfc: MOVBL0(opcode); break; + // 0xd0 + case 0x0d: MOVWL0(opcode); break; + case 0x1d: MOVWL0(opcode); break; + case 0x2d: MOVWL0(opcode); break; + case 0x3d: MOVWL0(opcode); break; + case 0x4d: MOVWL0(opcode); break; + case 0x5d: MOVWL0(opcode); break; + case 0x6d: MOVWL0(opcode); break; + case 0x7d: MOVWL0(opcode); break; + case 0x8d: MOVWL0(opcode); break; + case 0x9d: MOVWL0(opcode); break; + case 0xad: MOVWL0(opcode); break; + case 0xbd: MOVWL0(opcode); break; + case 0xcd: MOVWL0(opcode); break; + case 0xdd: MOVWL0(opcode); break; + case 0xed: MOVWL0(opcode); break; + case 0xfd: MOVWL0(opcode); break; + // 0xe0 + case 0x0e: MOVLL0(opcode); break; + case 0x1e: MOVLL0(opcode); break; + case 0x2e: MOVLL0(opcode); break; + case 0x3e: MOVLL0(opcode); break; + case 0x4e: MOVLL0(opcode); break; + case 0x5e: MOVLL0(opcode); break; + case 0x6e: MOVLL0(opcode); break; + case 0x7e: MOVLL0(opcode); break; + case 0x8e: MOVLL0(opcode); break; + case 0x9e: MOVLL0(opcode); break; + case 0xae: MOVLL0(opcode); break; + case 0xbe: MOVLL0(opcode); break; + case 0xce: MOVLL0(opcode); break; + case 0xde: MOVLL0(opcode); break; + case 0xee: MOVLL0(opcode); break; + case 0xfe: MOVLL0(opcode); break; + // 0xf0 + case 0x0f: MAC_L(opcode); break; + case 0x1f: MAC_L(opcode); break; + case 0x2f: MAC_L(opcode); break; + case 0x3f: MAC_L(opcode); break; + case 0x4f: MAC_L(opcode); break; + case 0x5f: MAC_L(opcode); break; + case 0x6f: MAC_L(opcode); break; + case 0x7f: MAC_L(opcode); break; + case 0x8f: MAC_L(opcode); break; + case 0x9f: MAC_L(opcode); break; + case 0xaf: MAC_L(opcode); break; + case 0xbf: MAC_L(opcode); break; + case 0xcf: MAC_L(opcode); break; + case 0xdf: MAC_L(opcode); break; + case 0xef: MAC_L(opcode); break; + case 0xff: MAC_L(opcode); break; + } +} + +inline void sh34_base_device::execute_one_4000(const uint16_t opcode) +{ + switch(opcode & 0xff) + { + // 0x00 + case 0x00: SHLL(opcode); break; + case 0x10: DT(opcode); break; + case 0x20: SHAL(opcode); break; + case 0x30: NOP(opcode); break; + case 0x40: SHLL(opcode); break; + case 0x50: DT(opcode); break; + case 0x60: SHAL(opcode); break; + case 0x70: NOP(opcode); break; + case 0x80: SHLL(opcode); break; + case 0x90: DT(opcode); break; + case 0xa0: SHAL(opcode); break; + case 0xb0: NOP(opcode); break; + case 0xc0: SHLL(opcode); break; + case 0xd0: DT(opcode); break; + case 0xe0: SHAL(opcode); break; + case 0xf0: NOP(opcode); break; + // 0x10 + case 0x01: SHLR(opcode); break; + case 0x11: CMPPZ(opcode); break; + case 0x21: SHAR(opcode); break; + case 0x31: NOP(opcode); break; + case 0x41: SHLR(opcode); break; + case 0x51: CMPPZ(opcode); break; + case 0x61: SHAR(opcode); break; + case 0x71: NOP(opcode); break; + case 0x81: SHLR(opcode); break; + case 0x91: CMPPZ(opcode); break; + case 0xa1: SHAR(opcode); break; + case 0xb1: NOP(opcode); break; + case 0xc1: SHLR(opcode); break; + case 0xd1: CMPPZ(opcode); break; + case 0xe1: SHAR(opcode); break; + case 0xf1: NOP(opcode); break; + // 0x20 + case 0x02: STSMMACH(opcode); break; + case 0x12: STSMMACL(opcode); break; + case 0x22: STSMPR(opcode); break; + case 0x32: STCMSGR(opcode); break; + case 0x42: NOP(opcode); break; + case 0x52: STSMFPUL(opcode); break; + case 0x62: STSMFPSCR(opcode); break; + case 0x72: NOP(opcode); break; + case 0x82: NOP(opcode); break; + case 0x92: NOP(opcode); break; + case 0xa2: NOP(opcode); break; + case 0xb2: NOP(opcode); break; + case 0xc2: NOP(opcode); break; + case 0xd2: NOP(opcode); break; + case 0xe2: NOP(opcode); break; + case 0xf2: STCMDBR(opcode); break; + // 0x30 + case 0x03: STCMSR(opcode); break; + case 0x13: STCMGBR(opcode); break; + case 0x23: STCMVBR(opcode); break; + case 0x33: STCMSSR(opcode); break; + case 0x43: STCMSPC(opcode); break; + case 0x53: NOP(opcode); break; + case 0x63: NOP(opcode); break; + case 0x73: NOP(opcode); break; + case 0x83: STCMRBANK(opcode); break; + case 0x93: STCMRBANK(opcode); break; + case 0xa3: STCMRBANK(opcode); break; + case 0xb3: STCMRBANK(opcode); break; + case 0xc3: STCMRBANK(opcode); break; + case 0xd3: STCMRBANK(opcode); break; + case 0xe3: STCMRBANK(opcode); break; + case 0xf3: STCMRBANK(opcode); break; + // 0x40 + case 0x04: ROTL(opcode); break; + case 0x14: NOP(opcode); break; + case 0x24: ROTCL(opcode); break; + case 0x34: NOP(opcode); break; + case 0x44: ROTL(opcode); break; + case 0x54: NOP(opcode); break; + case 0x64: ROTCL(opcode); break; + case 0x74: NOP(opcode); break; + case 0x84: ROTL(opcode); break; + case 0x94: NOP(opcode); break; + case 0xa4: ROTCL(opcode); break; + case 0xb4: NOP(opcode); break; + case 0xc4: ROTL(opcode); break; + case 0xd4: NOP(opcode); break; + case 0xe4: ROTCL(opcode); break; + case 0xf4: NOP(opcode); break; + // 0x50 + case 0x05: ROTR(opcode); break; + case 0x15: CMPPL(opcode); break; + case 0x25: ROTCR(opcode); break; + case 0x35: NOP(opcode); break; + case 0x45: ROTR(opcode); break; + case 0x55: CMPPL(opcode); break; + case 0x65: ROTCR(opcode); break; + case 0x75: NOP(opcode); break; + case 0x85: ROTR(opcode); break; + case 0x95: CMPPL(opcode); break; + case 0xa5: ROTCR(opcode); break; + case 0xb5: NOP(opcode); break; + case 0xc5: ROTR(opcode); break; + case 0xd5: CMPPL(opcode); break; + case 0xe5: ROTCR(opcode); break; + case 0xf5: NOP(opcode); break; + // 0x60 + case 0x06: LDSMMACH(opcode); break; + case 0x16: LDSMMACL(opcode); break; + case 0x26: LDSMPR(opcode); break; + case 0x36: NOP(opcode); break; + case 0x46: NOP(opcode); break; + case 0x56: LDSMFPUL(opcode); break; + case 0x66: LDSMFPSCR(opcode); break; + case 0x76: NOP(opcode); break; + case 0x86: NOP(opcode); break; + case 0x96: NOP(opcode); break; + case 0xa6: NOP(opcode); break; + case 0xb6: NOP(opcode); break; + case 0xc6: NOP(opcode); break; + case 0xd6: NOP(opcode); break; + case 0xe6: NOP(opcode); break; + case 0xf6: LDCMDBR(opcode); break; + // 0x70 + case 0x07: LDCMSR(opcode); break; + case 0x17: LDCMGBR(opcode); break; + case 0x27: LDCMVBR(opcode); break; + case 0x37: LDCMSSR(opcode); break; + case 0x47: LDCMSPC(opcode); break; + case 0x57: NOP(opcode); break; + case 0x67: NOP(opcode); break; + case 0x77: NOP(opcode); break; + case 0x87: LDCMRBANK(opcode); break; + case 0x97: LDCMRBANK(opcode); break; + case 0xa7: LDCMRBANK(opcode); break; + case 0xb7: LDCMRBANK(opcode); break; + case 0xc7: LDCMRBANK(opcode); break; + case 0xd7: LDCMRBANK(opcode); break; + case 0xe7: LDCMRBANK(opcode); break; + case 0xf7: LDCMRBANK(opcode); break; + // 0x80 + case 0x08: SHLL2(opcode); break; + case 0x18: SHLL8(opcode); break; + case 0x28: SHLL16(opcode); break; + case 0x38: NOP(opcode); break; + case 0x48: SHLL2(opcode); break; + case 0x58: SHLL8(opcode); break; + case 0x68: SHLL16(opcode); break; + case 0x78: NOP(opcode); break; + case 0x88: SHLL2(opcode); break; + case 0x98: SHLL8(opcode); break; + case 0xa8: SHLL16(opcode); break; + case 0xb8: NOP(opcode); break; + case 0xc8: SHLL2(opcode); break; + case 0xd8: SHLL8(opcode); break; + case 0xe8: SHLL16(opcode); break; + case 0xf8: NOP(opcode); break; + // 0x90 + case 0x09: SHLR2(opcode); break; + case 0x19: SHLR8(opcode); break; + case 0x29: SHLR16(opcode); break; + case 0x39: NOP(opcode); break; + case 0x49: SHLR2(opcode); break; + case 0x59: SHLR8(opcode); break; + case 0x69: SHLR16(opcode); break; + case 0x79: NOP(opcode); break; + case 0x89: SHLR2(opcode); break; + case 0x99: SHLR8(opcode); break; + case 0xa9: SHLR16(opcode); break; + case 0xb9: NOP(opcode); break; + case 0xc9: SHLR2(opcode); break; + case 0xd9: SHLR8(opcode); break; + case 0xe9: SHLR16(opcode); break; + case 0xf9: NOP(opcode); break; + // 0xa0 + case 0x0a: LDSMACH(opcode); break; + case 0x1a: LDSMACL(opcode); break; + case 0x2a: LDSPR(opcode); break; + case 0x3a: NOP(opcode); break; + case 0x4a: NOP(opcode); break; + case 0x5a: LDSFPUL(opcode); break; + case 0x6a: LDSFPSCR(opcode); break; + case 0x7a: NOP(opcode); break; + case 0x8a: NOP(opcode); break; + case 0x9a: NOP(opcode); break; + case 0xaa: NOP(opcode); break; + case 0xba: NOP(opcode); break; + case 0xca: NOP(opcode); break; + case 0xda: NOP(opcode); break; + case 0xea: NOP(opcode); break; + case 0xfa: LDCDBR(opcode); break; + // 0xb0 + case 0x0b: JSR(opcode); break; + case 0x1b: TAS(opcode); break; + case 0x2b: JMP(opcode); break; + case 0x3b: NOP(opcode); break; + case 0x4b: JSR(opcode); break; + case 0x5b: TAS(opcode); break; + case 0x6b: JMP(opcode); break; + case 0x7b: NOP(opcode); break; + case 0x8b: JSR(opcode); break; + case 0x9b: TAS(opcode); break; + case 0xab: JMP(opcode); break; + case 0xbb: NOP(opcode); break; + case 0xcb: JSR(opcode); break; + case 0xdb: TAS(opcode); break; + case 0xeb: JMP(opcode); break; + case 0xfb: NOP(opcode); break; + // 0xc0 + case 0x0c: SHAD(opcode); break; + case 0x1c: SHAD(opcode); break; + case 0x2c: SHAD(opcode); break; + case 0x3c: SHAD(opcode); break; + case 0x4c: SHAD(opcode); break; + case 0x5c: SHAD(opcode); break; + case 0x6c: SHAD(opcode); break; + case 0x7c: SHAD(opcode); break; + case 0x8c: SHAD(opcode); break; + case 0x9c: SHAD(opcode); break; + case 0xac: SHAD(opcode); break; + case 0xbc: SHAD(opcode); break; + case 0xcc: SHAD(opcode); break; + case 0xdc: SHAD(opcode); break; + case 0xec: SHAD(opcode); break; + case 0xfc: SHAD(opcode); break; + // 0xd0 + case 0x0d: SHLD(opcode); break; + case 0x1d: SHLD(opcode); break; + case 0x2d: SHLD(opcode); break; + case 0x3d: SHLD(opcode); break; + case 0x4d: SHLD(opcode); break; + case 0x5d: SHLD(opcode); break; + case 0x6d: SHLD(opcode); break; + case 0x7d: SHLD(opcode); break; + case 0x8d: SHLD(opcode); break; + case 0x9d: SHLD(opcode); break; + case 0xad: SHLD(opcode); break; + case 0xbd: SHLD(opcode); break; + case 0xcd: SHLD(opcode); break; + case 0xdd: SHLD(opcode); break; + case 0xed: SHLD(opcode); break; + case 0xfd: SHLD(opcode); break; + // 0xe0 + case 0x0e: LDCSR(opcode); break; + case 0x1e: LDCGBR(opcode); break; + case 0x2e: LDCVBR(opcode); break; + case 0x3e: LDCSSR(opcode); break; + case 0x4e: LDCSPC(opcode); break; + case 0x5e: NOP(opcode); break; + case 0x6e: NOP(opcode); break; + case 0x7e: NOP(opcode); break; + case 0x8e: LDCRBANK(opcode); break; + case 0x9e: LDCRBANK(opcode); break; + case 0xae: LDCRBANK(opcode); break; + case 0xbe: LDCRBANK(opcode); break; + case 0xce: LDCRBANK(opcode); break; + case 0xde: LDCRBANK(opcode); break; + case 0xee: LDCRBANK(opcode); break; + case 0xfe: LDCRBANK(opcode); break; + // 0xf0 + case 0x0f: MAC_W(opcode); break; + case 0x1f: MAC_W(opcode); break; + case 0x2f: MAC_W(opcode); break; + case 0x3f: MAC_W(opcode); break; + case 0x4f: MAC_W(opcode); break; + case 0x5f: MAC_W(opcode); break; + case 0x6f: MAC_W(opcode); break; + case 0x7f: MAC_W(opcode); break; + case 0x8f: MAC_W(opcode); break; + case 0x9f: MAC_W(opcode); break; + case 0xaf: MAC_W(opcode); break; + case 0xbf: MAC_W(opcode); break; + case 0xcf: MAC_W(opcode); break; + case 0xdf: MAC_W(opcode); break; + case 0xef: MAC_W(opcode); break; + case 0xff: MAC_W(opcode); break; + } +} + + +inline void sh34_base_device::execute_one(const uint16_t opcode) +{ + switch(opcode & 0xf000) + { + case 0x0000: + execute_one_0000(opcode); + break; + + case 0x1000: + MOVLS4(opcode); + break; + + case 0x2000: + switch(opcode & 0x0f) + { + case 0x00: MOVBS(opcode); break; + case 0x01: MOVWS(opcode); break; + case 0x02: MOVLS(opcode); break; + case 0x03: NOP(opcode); break; + case 0x04: MOVBM(opcode); break; + case 0x05: MOVWM(opcode); break; + case 0x06: MOVLM(opcode); break; + case 0x07: DIV0S(opcode); break; + case 0x08: TST(opcode); break; + case 0x09: AND(opcode); break; + case 0x0a: XOR(opcode); break; + case 0x0b: OR(opcode); break; + case 0x0c: CMPSTR(opcode); break; + case 0x0d: XTRCT(opcode); break; + case 0x0e: MULU(opcode); break; + case 0x0f: MULS(opcode); break; + } + break; + + case 0x3000: + switch(opcode & 0x0f) + { + case 0x00: CMPEQ(opcode); break; + case 0x01: NOP(opcode); break; + case 0x02: CMPHS(opcode); break; + case 0x03: CMPGE(opcode); break; + case 0x04: DIV1(opcode); break; + case 0x05: DMULU(opcode); break; + case 0x06: CMPHI(opcode); break; + case 0x07: CMPGT(opcode); break; + case 0x08: SUB(opcode); break; + case 0x09: NOP(opcode); break; + case 0x0a: SUBC(opcode); break; + case 0x0b: SUBV(opcode); break; + case 0x0c: ADD(opcode); break; + case 0x0d: DMULS(opcode); break; + case 0x0e: ADDC(opcode); break; + case 0x0f: ADDV(opcode); break; + } + break; + + case 0x4000: + execute_one_4000(opcode); + break; + + case 0x5000: + MOVLL4(opcode); + break; + + case 0x6000: + switch(opcode & 0x0f) + { + case 0x00: MOVBL(opcode); break; + case 0x01: MOVWL(opcode); break; + case 0x02: MOVLL(opcode); break; + case 0x03: MOV(opcode); break; + case 0x04: MOVBP(opcode); break; + case 0x05: MOVWP(opcode); break; + case 0x06: MOVLP(opcode); break; + case 0x07: NOT(opcode); break; + case 0x08: SWAPB(opcode); break; + case 0x09: SWAPW(opcode); break; + case 0x0a: NEGC(opcode); break; + case 0x0b: NEG(opcode); break; + case 0x0c: EXTUB(opcode); break; + case 0x0d: EXTUW(opcode); break; + case 0x0e: EXTSB(opcode); break; + case 0x0f: EXTSW(opcode); break; + } + break; + + case 0x7000: + ADDI(opcode); + break; + + case 0x8000: + switch((opcode >> 8) & 0x0f) + { + case 0x00: MOVBS4(opcode); break; + case 0x01: MOVWS4(opcode); break; + case 0x02: NOP(opcode); break; + case 0x03: NOP(opcode); break; + case 0x04: MOVBL4(opcode); break; + case 0x05: MOVWL4(opcode); break; + case 0x06: NOP(opcode); break; + case 0x07: NOP(opcode); break; + case 0x08: CMPIM(opcode); break; + case 0x09: BT(opcode); break; + case 0x0a: NOP(opcode); break; + case 0x0b: BF(opcode); break; + case 0x0c: NOP(opcode); break; + case 0x0d: BTS(opcode); break; + case 0x0e: NOP(opcode); break; + case 0x0f: BFS(opcode); break; + } + break; + + case 0x9000: + MOVWI(opcode); + break; + + case 0xa000: + BRA(opcode); + break; + + case 0xb000: + BSR(opcode); + break; + + case 0xc000: + switch((opcode >> 8) & 0x0f) + { + case 0x00: MOVBSG(opcode); break; + case 0x01: MOVWSG(opcode); break; + case 0x02: MOVLSG(opcode); break; + case 0x03: TRAPA(opcode); break; + case 0x04: MOVBLG(opcode); break; + case 0x05: MOVWLG(opcode); break; + case 0x06: MOVLLG(opcode); break; + case 0x07: MOVA(opcode); break; + case 0x08: TSTI(opcode); break; + case 0x09: ANDI(opcode); break; + case 0x0a: XORI(opcode); break; + case 0x0b: ORI(opcode); break; + case 0x0c: TSTM(opcode); break; + case 0x0d: ANDM(opcode); break; + case 0x0e: XORM(opcode); break; + case 0x0f: ORM(opcode); break; + } + break; + + case 0xd000: + MOVLI(opcode); + break; + + case 0xe000: + MOVI(opcode); + break; + + case 0xf000: + switch(opcode & 0x0f) + { + case 0x00: FADD(opcode); break; + case 0x01: FSUB(opcode); break; + case 0x02: FMUL(opcode); break; + case 0x03: FDIV(opcode); break; + case 0x04: FCMP_EQ(opcode); break; + case 0x05: FCMP_GT(opcode); break; + case 0x06: FMOVS0FR(opcode); break; + case 0x07: FMOVFRS0(opcode); break; + case 0x08: FMOVMRFR(opcode); break; + case 0x09: FMOVMRIFR(opcode); break; + case 0x0a: FMOVFRMR(opcode); break; + case 0x0b: FMOVFRMDR(opcode); break; + case 0x0c: FMOVFR(opcode); break; + case 0x0d: op1111_0x13(opcode); break; + case 0x0e: FMAC(opcode); break; + case 0x0f: dbreak(opcode); break; + } + break; + } +} + + +/* Execute cycles - returns number of cycles actually run */ +void sh34_base_device::execute_run() +{ + if (m_cpu_off) + { + m_sh4_icount = 0; + return; + } + + do + { + m_ppc = m_pc & AM; + debugger_instruction_hook(this, m_pc & AM); + + uint16_t opcode; + + if (!m_sh4_mmu_enabled) opcode = m_direct->read_word(m_pc & AM, WORD2_XOR_LE(0)); + else opcode = RW(m_pc); // should probably use a different function as this needs to go through the ITLB + + if (m_delay) + { + m_pc = m_delay; + m_delay = 0; + } + else + m_pc += 2; + + execute_one(opcode); + + if (m_test_irq && !m_delay) + { + sh4_check_pending_irq("mame_sh4_execute"); + } + + m_sh4_icount--; + } while( m_sh4_icount > 0 ); +} + +void sh3be_device::execute_run() +{ + if (m_cpu_off) + { + m_sh4_icount = 0; + return; + } + + do + { + m_ppc = m_pc & AM; + debugger_instruction_hook(this, m_pc & AM); + + const uint16_t opcode = m_direct->read_word(m_pc & AM, WORD_XOR_LE(6)); + + if (m_delay) + { + m_pc = m_delay; + m_delay = 0; + } + else + m_pc += 2; + + execute_one(opcode); + + if (m_test_irq && !m_delay) + { + sh4_check_pending_irq("mame_sh4_execute"); + } + + m_sh4_icount--; + } while( m_sh4_icount > 0 ); +} + +void sh4be_device::execute_run() +{ + if (m_cpu_off) + { + m_sh4_icount = 0; + return; + } + + do + { + m_ppc = m_pc & AM; + debugger_instruction_hook(this, m_pc & AM); + + const uint16_t opcode = m_direct->read_word(m_pc & AM, WORD_XOR_LE(6)); + + if (m_delay) + { + m_pc = m_delay; + m_delay = 0; + } + else + m_pc += 2; + + execute_one(opcode); + + if (m_test_irq && !m_delay) + { + sh4_check_pending_irq("mame_sh4_execute"); + } + + m_sh4_icount--; + } while( m_sh4_icount > 0 ); +} + +void sh4_base_device::device_start() +{ + sh34_base_device::device_start(); + + int i; + for (i=0;i<64;i++) + { + m_utlb[i].ASID = 0; + m_utlb[i].VPN = 0; + m_utlb[i].V = 0; + m_utlb[i].PPN = 0; + m_utlb[i].PSZ = 0; + m_utlb[i].SH = 0; + m_utlb[i].C = 0; + m_utlb[i].PPR = 0; + m_utlb[i].D = 0; + m_utlb[i].WT = 0; + m_utlb[i].SA = 0; + m_utlb[i].TC = 0; + } + + for (i=0;i<64;i++) + { + save_item(NAME(m_utlb[i].ASID), i); + save_item(NAME(m_utlb[i].VPN), i); + save_item(NAME(m_utlb[i].V), i); + save_item(NAME(m_utlb[i].PPN), i); + save_item(NAME(m_utlb[i].PSZ), i); + save_item(NAME(m_utlb[i].SH), i); + save_item(NAME(m_utlb[i].C), i); + save_item(NAME(m_utlb[i].PPR), i); + save_item(NAME(m_utlb[i].D), i); + save_item(NAME(m_utlb[i].WT), i); + save_item(NAME(m_utlb[i].SA), i); + save_item(NAME(m_utlb[i].TC), i); + } + +} + + + +void sh34_base_device::device_start() +{ + for (int i=0; i<3; i++) + { + m_timer[i] = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(sh34_base_device::sh4_timer_callback), this)); + m_timer[i]->adjust(attotime::never, i); + } + + for (int i=0; i<4; i++) + { + m_dma_timer[i] = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(sh34_base_device::sh4_dmac_callback), this)); + m_dma_timer[i]->adjust(attotime::never, i); + } + + m_refresh_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(sh34_base_device::sh4_refresh_timer_callback), this)); + m_refresh_timer->adjust(attotime::never); + m_refresh_timer_base = 0; + + m_rtc_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(sh34_base_device::sh4_rtc_timer_callback), this)); + m_rtc_timer->adjust(attotime::never); + + sh4_parse_configuration(); + + m_internal = &space(AS_PROGRAM); + m_program = &space(AS_PROGRAM); + m_io = &space(AS_IO); + m_direct = &m_program->direct(); + sh4_default_exception_priorities(); + m_irln = 15; + m_test_irq = 0; + + save_item(NAME(m_pc)); + save_item(NAME(m_r)); + save_item(NAME(m_sr)); + save_item(NAME(m_pr)); + save_item(NAME(m_gbr)); + save_item(NAME(m_vbr)); + save_item(NAME(m_mach)); + save_item(NAME(m_macl)); + save_item(NAME(m_spc)); + save_item(NAME(m_ssr)); + save_item(NAME(m_sgr)); + save_item(NAME(m_fpscr)); + save_item(NAME(m_rbnk)); + save_item(NAME(m_fr)); + save_item(NAME(m_xf)); + save_item(NAME(m_ea)); + save_item(NAME(m_delay)); + save_item(NAME(m_cpu_off)); + save_item(NAME(m_pending_irq)); + save_item(NAME(m_test_irq)); + save_item(NAME(m_fpul)); + save_item(NAME(m_dbr)); + save_item(NAME(m_exception_priority)); + save_item(NAME(m_exception_requesting)); + save_item(NAME(m_irq_line_state)); + save_item(NAME(m_m)); + save_item(NAME(m_SH4_TSTR)); + save_item(NAME(m_SH4_TCNT0)); + save_item(NAME(m_SH4_TCNT1)); + save_item(NAME(m_SH4_TCNT2)); + save_item(NAME(m_SH4_TCR0)); + save_item(NAME(m_SH4_TCR1)); + save_item(NAME(m_SH4_TCR2)); + save_item(NAME(m_SH4_TCOR0)); + save_item(NAME(m_SH4_TCOR1)); + save_item(NAME(m_SH4_TCOR2)); + save_item(NAME(m_SH4_TOCR)); + save_item(NAME(m_SH4_TCPR2)); + save_item(NAME(m_SH4_IPRA)); + save_item(NAME(m_SH4_IPRC)); + save_item(NAME(m_SH4_DAR0)); + save_item(NAME(m_SH4_DAR1)); + save_item(NAME(m_SH4_DAR2)); + save_item(NAME(m_SH4_DAR3)); + save_item(NAME(m_SH4_CHCR0)); + save_item(NAME(m_SH4_CHCR1)); + save_item(NAME(m_SH4_CHCR2)); + save_item(NAME(m_SH4_CHCR3)); + save_item(NAME(m_SH4_DMATCR0)); + save_item(NAME(m_SH4_DMATCR1)); + save_item(NAME(m_SH4_DMATCR2)); + save_item(NAME(m_SH4_DMATCR3)); + save_item(NAME(m_SH4_DMAOR)); + save_item(NAME(m_nmi_line_state)); + save_item(NAME(m_sleep_mode)); + save_item(NAME(m_frt_input)); + save_item(NAME(m_irln)); + save_item(NAME(m_internal_irq_level)); + save_item(NAME(m_internal_irq_vector)); + save_item(NAME(m_refresh_timer_base)); + save_item(NAME(m_dma_timer_active)); + save_item(NAME(m_dma_source)); + save_item(NAME(m_dma_destination)); + save_item(NAME(m_dma_count)); + save_item(NAME(m_dma_wordsize)); + save_item(NAME(m_dma_source_increment)); + save_item(NAME(m_dma_destination_increment)); + save_item(NAME(m_dma_mode)); + save_item(NAME(m_sh4_icount)); + save_item(NAME(m_fpu_sz)); + save_item(NAME(m_fpu_pr)); + save_item(NAME(m_ioport16_pullup)); + save_item(NAME( m_ioport16_direction)); + save_item(NAME(m_ioport4_pullup)); + save_item(NAME(m_ioport4_direction)); + save_item(NAME(m_sh4_mmu_enabled)); + save_item(NAME(m_sh3internal_upper)); + save_item(NAME(m_sh3internal_lower)); + + // Debugger state + + state_add(SH4_PC, "PC", m_pc).formatstr("%08X").callimport(); + state_add(SH4_SR, "SR", m_sr).formatstr("%08X").callimport(); + state_add(SH4_PR, "PR", m_pr).formatstr("%08X"); + state_add(SH4_GBR, "GBR", m_gbr).formatstr("%08X"); + state_add(SH4_VBR, "VBR", m_vbr).formatstr("%08X"); + state_add(SH4_DBR, "DBR", m_dbr).formatstr("%08X"); + state_add(SH4_MACH, "MACH", m_mach).formatstr("%08X"); + state_add(SH4_MACL, "MACL", m_macl).formatstr("%08X"); + state_add(SH4_R0, "R0", m_r[ 0]).formatstr("%08X"); + state_add(SH4_R1, "R1", m_r[ 1]).formatstr("%08X"); + state_add(SH4_R2, "R2", m_r[ 2]).formatstr("%08X"); + state_add(SH4_R3, "R3", m_r[ 3]).formatstr("%08X"); + state_add(SH4_R4, "R4", m_r[ 4]).formatstr("%08X"); + state_add(SH4_R5, "R5", m_r[ 5]).formatstr("%08X"); + state_add(SH4_R6, "R6", m_r[ 6]).formatstr("%08X"); + state_add(SH4_R7, "R7", m_r[ 7]).formatstr("%08X"); + state_add(SH4_R8, "R8", m_r[ 8]).formatstr("%08X"); + state_add(SH4_R9, "R9", m_r[ 9]).formatstr("%08X"); + state_add(SH4_R10, "R10", m_r[10]).formatstr("%08X"); + state_add(SH4_R11, "R11", m_r[11]).formatstr("%08X"); + state_add(SH4_R12, "R12", m_r[12]).formatstr("%08X"); + state_add(SH4_R13, "R13", m_r[13]).formatstr("%08X"); + state_add(SH4_R14, "R14", m_r[14]).formatstr("%08X"); + state_add(SH4_R15, "R15", m_r[15]).formatstr("%08X"); + state_add(SH4_EA, "EA", m_ea).formatstr("%08X"); + state_add(SH4_R0_BK0, "R0 BK 0", m_rbnk[0][0]).formatstr("%08X"); + state_add(SH4_R1_BK0, "R1 BK 0", m_rbnk[0][1]).formatstr("%08X"); + state_add(SH4_R2_BK0, "R2 BK 0", m_rbnk[0][2]).formatstr("%08X"); + state_add(SH4_R3_BK0, "R3 BK 0", m_rbnk[0][3]).formatstr("%08X"); + state_add(SH4_R4_BK0, "R4 BK 0", m_rbnk[0][4]).formatstr("%08X"); + state_add(SH4_R5_BK0, "R5 BK 0", m_rbnk[0][5]).formatstr("%08X"); + state_add(SH4_R6_BK0, "R6 BK 0", m_rbnk[0][6]).formatstr("%08X"); + state_add(SH4_R7_BK0, "R7 BK 0", m_rbnk[0][7]).formatstr("%08X"); + state_add(SH4_R0_BK1, "R0 BK 1", m_rbnk[1][0]).formatstr("%08X"); + state_add(SH4_R1_BK1, "R1 BK 1", m_rbnk[1][1]).formatstr("%08X"); + state_add(SH4_R2_BK1, "R2 BK 1", m_rbnk[1][2]).formatstr("%08X"); + state_add(SH4_R3_BK1, "R3 BK 1", m_rbnk[1][3]).formatstr("%08X"); + state_add(SH4_R4_BK1, "R4 BK 1", m_rbnk[1][4]).formatstr("%08X"); + state_add(SH4_R5_BK1, "R5 BK 1", m_rbnk[1][5]).formatstr("%08X"); + state_add(SH4_R6_BK1, "R6 BK 1", m_rbnk[1][6]).formatstr("%08X"); + state_add(SH4_R7_BK1, "R7 BK 1", m_rbnk[1][7]).formatstr("%08X"); + state_add(SH4_SPC, "SPC", m_spc).formatstr("%08X"); + state_add(SH4_SSR, "SSR", m_ssr).formatstr("%08X"); + state_add(SH4_SGR, "SGR", m_sgr).formatstr("%08X"); + state_add(SH4_FPSCR, "FPSCR", m_fpscr).formatstr("%08X"); + state_add(SH4_FPUL, "FPUL", m_fpul).formatstr("%08X"); + + state_add(SH4_FR0, "FR0", m_debugger_temp).callimport().formatstr("%25s"); + state_add(SH4_FR1, "FR1", m_debugger_temp).callimport().formatstr("%25s"); + state_add(SH4_FR2, "FR2", m_debugger_temp).callimport().formatstr("%25s"); + state_add(SH4_FR3, "FR3", m_debugger_temp).callimport().formatstr("%25s"); + state_add(SH4_FR4, "FR4", m_debugger_temp).callimport().formatstr("%25s"); + state_add(SH4_FR5, "FR5", m_debugger_temp).callimport().formatstr("%25s"); + state_add(SH4_FR6, "FR6", m_debugger_temp).callimport().formatstr("%25s"); + state_add(SH4_FR7, "FR7", m_debugger_temp).callimport().formatstr("%25s"); + state_add(SH4_FR8, "FR8", m_debugger_temp).callimport().formatstr("%25s"); + state_add(SH4_FR9, "FR9", m_debugger_temp).callimport().formatstr("%25s"); + state_add(SH4_FR10, "FR10", m_debugger_temp).callimport().formatstr("%25s"); + state_add(SH4_FR11, "FR11", m_debugger_temp).callimport().formatstr("%25s"); + state_add(SH4_FR12, "FR12", m_debugger_temp).callimport().formatstr("%25s"); + state_add(SH4_FR13, "FR13", m_debugger_temp).callimport().formatstr("%25s"); + state_add(SH4_FR14, "FR14", m_debugger_temp).callimport().formatstr("%25s"); + state_add(SH4_FR15, "FR15", m_debugger_temp).callimport().formatstr("%25s"); + state_add(SH4_XF0, "XF0", m_debugger_temp).callimport().formatstr("%25s"); + state_add(SH4_XF1, "XF1", m_debugger_temp).callimport().formatstr("%25s"); + state_add(SH4_XF2, "XF2", m_debugger_temp).callimport().formatstr("%25s"); + state_add(SH4_XF3, "XF3", m_debugger_temp).callimport().formatstr("%25s"); + state_add(SH4_XF4, "XF4", m_debugger_temp).callimport().formatstr("%25s"); + state_add(SH4_XF5, "XF5", m_debugger_temp).callimport().formatstr("%25s"); + state_add(SH4_XF6, "XF6", m_debugger_temp).callimport().formatstr("%25s"); + state_add(SH4_XF7, "XF7", m_debugger_temp).callimport().formatstr("%25s"); + state_add(SH4_XF8, "XF8", m_debugger_temp).callimport().formatstr("%25s"); + state_add(SH4_XF9, "XF9", m_debugger_temp).callimport().formatstr("%25s"); + state_add(SH4_XF10, "XF10", m_debugger_temp).callimport().formatstr("%25s"); + state_add(SH4_XF11, "XF11", m_debugger_temp).callimport().formatstr("%25s"); + state_add(SH4_XF12, "XF12", m_debugger_temp).callimport().formatstr("%25s"); + state_add(SH4_XF13, "XF13", m_debugger_temp).callimport().formatstr("%25s"); + state_add(SH4_XF14, "XF14", m_debugger_temp).callimport().formatstr("%25s"); + state_add(SH4_XF15, "XF15", m_debugger_temp).callimport().formatstr("%25s"); + + state_add(STATE_GENPC, "GENPC", m_debugger_temp).callimport().callexport().noshow(); + state_add(STATE_GENPCBASE, "CURPC", m_ppc).noshow(); + state_add(STATE_GENSP, "GENSP", m_r[15]).noshow(); + state_add(STATE_GENFLAGS, "GENFLAGS", m_sr).formatstr("%20s").noshow(); + + m_icountptr = &m_sh4_icount; +} + +void sh34_base_device::state_import(const device_state_entry &entry) +{ +#ifdef LSB_FIRST + uint8_t fpu_xor = m_fpu_pr; +#else + uint8_t fpu_xor = 0; +#endif + + switch (entry.index()) + { + case STATE_GENPC: + m_pc = m_debugger_temp; + case SH4_PC: + m_delay = 0; + break; + + case SH4_SR: + sh4_exception_recompute(); + sh4_check_pending_irq("sh4_set_info"); + break; + + case SH4_FR0: + m_fr[0 ^ fpu_xor] = m_debugger_temp; + break; + + case SH4_FR1: + m_fr[1 ^ fpu_xor] = m_debugger_temp; + break; + + case SH4_FR2: + m_fr[2 ^ fpu_xor] = m_debugger_temp; + break; + + case SH4_FR3: + m_fr[3 ^ fpu_xor] = m_debugger_temp; + break; + + case SH4_FR4: + m_fr[4 ^ fpu_xor] = m_debugger_temp; + break; + + case SH4_FR5: + m_fr[5 ^ fpu_xor] = m_debugger_temp; + break; + + case SH4_FR6: + m_fr[6 ^ fpu_xor] = m_debugger_temp; + break; + + case SH4_FR7: + m_fr[7 ^ fpu_xor] = m_debugger_temp; + break; + + case SH4_FR8: + m_fr[8 ^ fpu_xor] = m_debugger_temp; + break; + + case SH4_FR9: + m_fr[9 ^ fpu_xor] = m_debugger_temp; + break; + + case SH4_FR10: + m_fr[10 ^ fpu_xor] = m_debugger_temp; + break; + + case SH4_FR11: + m_fr[11 ^ fpu_xor] = m_debugger_temp; + break; + + case SH4_FR12: + m_fr[12 ^ fpu_xor] = m_debugger_temp; + break; + + case SH4_FR13: + m_fr[13 ^ fpu_xor] = m_debugger_temp; + break; + + case SH4_FR14: + m_fr[14 ^ fpu_xor] = m_debugger_temp; + break; + + case SH4_FR15: + m_fr[15 ^ fpu_xor] = m_debugger_temp; + break; + + case SH4_XF0: + m_xf[0 ^ fpu_xor] = m_debugger_temp; + break; + + case SH4_XF1: + m_xf[1 ^ fpu_xor] = m_debugger_temp; + break; + + case SH4_XF2: + m_xf[2 ^ fpu_xor] = m_debugger_temp; + break; + + case SH4_XF3: + m_xf[3 ^ fpu_xor] = m_debugger_temp; + break; + + case SH4_XF4: + m_xf[4 ^ fpu_xor] = m_debugger_temp; + break; + + case SH4_XF5: + m_xf[5 ^ fpu_xor] = m_debugger_temp; + break; + + case SH4_XF6: + m_xf[6 ^ fpu_xor] = m_debugger_temp; + break; + + case SH4_XF7: + m_xf[7 ^ fpu_xor] = m_debugger_temp; + break; + + case SH4_XF8: + m_xf[8 ^ fpu_xor] = m_debugger_temp; + break; + + case SH4_XF9: + m_xf[9 ^ fpu_xor] = m_debugger_temp; + break; + + case SH4_XF10: + m_xf[10 ^ fpu_xor] = m_debugger_temp; + break; + + case SH4_XF11: + m_xf[11 ^ fpu_xor] = m_debugger_temp; + break; + + case SH4_XF12: + m_xf[12 ^ fpu_xor] = m_debugger_temp; + break; + + case SH4_XF13: + m_xf[13 ^ fpu_xor] = m_debugger_temp; + break; + + case SH4_XF14: + m_xf[14 ^ fpu_xor] = m_debugger_temp; + break; + + case SH4_XF15: + m_xf[15 ^ fpu_xor] = m_debugger_temp; + break; + } +} + +void sh34_base_device::state_export(const device_state_entry &entry) +{ + switch (entry.index()) + { + case STATE_GENPC: + m_debugger_temp = (m_pc & AM); + break; + } +} + +void sh34_base_device::state_string_export(const device_state_entry &entry, std::string &str) const +{ +#ifdef LSB_FIRST + uint8_t fpu_xor = m_fpu_pr; +#else + uint8_t fpu_xor = 0; +#endif + + switch (entry.index()) + { + case STATE_GENFLAGS: + str = string_format("%s%s%s%s%c%c%d%c%c", + m_sr & MD ? "MD ":" ", + m_sr & sRB ? "RB ":" ", + m_sr & BL ? "BL ":" ", + m_sr & FD ? "FD ":" ", + m_sr & M ? 'M':'.', + m_sr & Q ? 'Q':'.', + (m_sr & I) >> 4, + m_sr & S ? 'S':'.', + m_sr & T ? 'T':'.'); + break; + + case SH4_FR0: + str = string_format("%08X %f", m_fr[0 ^ fpu_xor], (double)FP_RFS(0 ^ fpu_xor)); + break; + + case SH4_FR1: + str = string_format("%08X %f", m_fr[1 ^ fpu_xor], (double)FP_RFS(1 ^ fpu_xor)); + break; + + case SH4_FR2: + str = string_format("%08X %f", m_fr[2 ^ fpu_xor], (double)FP_RFS(2 ^ fpu_xor)); + break; + + case SH4_FR3: + str = string_format("%08X %f", m_fr[3 ^ fpu_xor], (double)FP_RFS(3 ^ fpu_xor)); + break; + + case SH4_FR4: + str = string_format("%08X %f", m_fr[4 ^ fpu_xor], (double)FP_RFS(4 ^ fpu_xor)); + break; + + case SH4_FR5: + str = string_format("%08X %f", m_fr[5 ^ fpu_xor], (double)FP_RFS(5 ^ fpu_xor)); + break; + + case SH4_FR6: + str = string_format("%08X %f", m_fr[6 ^ fpu_xor], (double)FP_RFS(6 ^ fpu_xor)); + break; + + case SH4_FR7: + str = string_format("%08X %f", m_fr[7 ^ fpu_xor], (double)FP_RFS(7 ^ fpu_xor)); + break; + + case SH4_FR8: + str = string_format("%08X %f", m_fr[8 ^ fpu_xor], (double)FP_RFS(8 ^ fpu_xor)); + break; + + case SH4_FR9: + str = string_format("%08X %f", m_fr[9 ^ fpu_xor], (double)FP_RFS(9 ^ fpu_xor)); + break; + + case SH4_FR10: + str = string_format("%08X %f", m_fr[10 ^ fpu_xor], (double)FP_RFS(10 ^ fpu_xor)); + break; + + case SH4_FR11: + str = string_format("%08X %f", m_fr[11 ^ fpu_xor], (double)FP_RFS(11 ^ fpu_xor)); + break; + + case SH4_FR12: + str = string_format("%08X %f", m_fr[12 ^ fpu_xor], (double)FP_RFS(12 ^ fpu_xor)); + break; + + case SH4_FR13: + str = string_format("%08X %f", m_fr[13 ^ fpu_xor], (double)FP_RFS(13 ^ fpu_xor)); + break; + + case SH4_FR14: + str = string_format("%08X %f", m_fr[14 ^ fpu_xor], (double)FP_RFS(14 ^ fpu_xor)); + break; + + case SH4_FR15: + str = string_format("%08X %f", m_fr[15 ^ fpu_xor], (double)FP_RFS(15 ^ fpu_xor)); + break; + + case SH4_XF0: + str = string_format("%08X %f", m_xf[0 ^ fpu_xor], (double)FP_XFS(0 ^ fpu_xor)); + break; + + case SH4_XF1: + str = string_format("%08X %f", m_xf[1 ^ fpu_xor], (double)FP_XFS(1 ^ fpu_xor)); + break; + + case SH4_XF2: + str = string_format("%08X %f", m_xf[2 ^ fpu_xor], (double)FP_XFS(2 ^ fpu_xor)); + break; + + case SH4_XF3: + str = string_format("%08X %f", m_xf[3 ^ fpu_xor], (double)FP_XFS(3 ^ fpu_xor)); + break; + + case SH4_XF4: + str = string_format("%08X %f", m_xf[4 ^ fpu_xor], (double)FP_XFS(4 ^ fpu_xor)); + break; + + case SH4_XF5: + str = string_format("%08X %f", m_xf[5 ^ fpu_xor], (double)FP_XFS(5 ^ fpu_xor)); + break; + + case SH4_XF6: + str = string_format("%08X %f", m_xf[6 ^ fpu_xor], (double)FP_XFS(6 ^ fpu_xor)); + break; + + case SH4_XF7: + str = string_format("%08X %f", m_xf[7 ^ fpu_xor], (double)FP_XFS(7 ^ fpu_xor)); + break; + + case SH4_XF8: + str = string_format("%08X %f", m_xf[8 ^ fpu_xor], (double)FP_XFS(8 ^ fpu_xor)); + break; + + case SH4_XF9: + str = string_format("%08X %f", m_xf[9 ^ fpu_xor], (double)FP_XFS(9 ^ fpu_xor)); + break; + + case SH4_XF10: + str = string_format("%08X %f", m_xf[10 ^ fpu_xor], (double)FP_XFS(10 ^ fpu_xor)); + break; + + case SH4_XF11: + str = string_format("%08X %f", m_xf[11 ^ fpu_xor], (double)FP_XFS(11 ^ fpu_xor)); + break; + + case SH4_XF12: + str = string_format("%08X %f", m_xf[12 ^ fpu_xor], (double)FP_XFS(12 ^ fpu_xor)); + break; + + case SH4_XF13: + str = string_format("%08X %f", m_xf[13 ^ fpu_xor], (double)FP_XFS(13 ^ fpu_xor)); + break; + + case SH4_XF14: + str = string_format("%08X %f", m_xf[14 ^ fpu_xor], (double)FP_XFS(14 ^ fpu_xor)); + break; + + case SH4_XF15: + str = string_format("%08X %f", m_xf[15 ^ fpu_xor], (double)FP_XFS(15 ^ fpu_xor)); + break; + + } +} + + +void sh34_base_device::sh4_set_ftcsr_callback(sh4_ftcsr_callback callback) +{ + m_ftcsr_read_callback = callback; +} diff --git a/src/devices/cpu/sh/sh4.h b/src/devices/cpu/sh/sh4.h new file mode 100644 index 00000000000..fad1d326750 --- /dev/null +++ b/src/devices/cpu/sh/sh4.h @@ -0,0 +1,844 @@ +// license:BSD-3-Clause +// copyright-holders:R. Belmont +/***************************************************************************** + * + * sh4->h + * Portable Hitachi SH-4 (SH7750 family) emulator interface + * + * By R. Belmont, based on sh2.c by Juergen Buchmueller, Mariusz Wojcieszek, + * Olivier Galibert, Sylvain Glaize, and James Forshaw. + * + *****************************************************************************/ + +#ifndef MAME_CPU_SH4_SH4_H +#define MAME_CPU_SH4_SH4_H + +#pragma once + +// doesn't actually seem to improve performance at all +#define SH4_USE_FASTRAM_OPTIMIZATION 0 +#define SH4_MAX_FASTRAM 3 + +#define SH4_INT_NONE -1 +enum +{ + SH4_IRL0=0, SH4_IRL1, SH4_IRL2, SH4_IRL3, SH4_IRLn +}; + +enum +{ + SH4_PC=1, SH4_SR, SH4_PR, SH4_GBR, SH4_VBR, SH4_DBR, SH4_MACH, SH4_MACL, + SH4_R0, SH4_R1, SH4_R2, SH4_R3, SH4_R4, SH4_R5, SH4_R6, SH4_R7, + SH4_R8, SH4_R9, SH4_R10, SH4_R11, SH4_R12, SH4_R13, SH4_R14, SH4_R15, SH4_EA, + SH4_R0_BK0, SH4_R1_BK0, SH4_R2_BK0, SH4_R3_BK0, SH4_R4_BK0, SH4_R5_BK0, SH4_R6_BK0, SH4_R7_BK0, + SH4_R0_BK1, SH4_R1_BK1, SH4_R2_BK1, SH4_R3_BK1, SH4_R4_BK1, SH4_R5_BK1, SH4_R6_BK1, SH4_R7_BK1, + SH4_SPC, SH4_SSR, SH4_SGR, SH4_FPSCR, SH4_FPUL, SH4_FR0, SH4_FR1, SH4_FR2, SH4_FR3, SH4_FR4, SH4_FR5, + SH4_FR6, SH4_FR7, SH4_FR8, SH4_FR9, SH4_FR10, SH4_FR11, SH4_FR12, SH4_FR13, SH4_FR14, SH4_FR15, + SH4_XF0, SH4_XF1, SH4_XF2, SH4_XF3, SH4_XF4, SH4_XF5, SH4_XF6, SH4_XF7, + SH4_XF8, SH4_XF9, SH4_XF10, SH4_XF11, SH4_XF12, SH4_XF13, SH4_XF14, SH4_XF15 +}; + +enum +{ + SH4_INTC_NMI=23, + SH4_INTC_IRLn0, + SH4_INTC_IRLn1, + SH4_INTC_IRLn2, + SH4_INTC_IRLn3, + SH4_INTC_IRLn4, + SH4_INTC_IRLn5, + SH4_INTC_IRLn6, + SH4_INTC_IRLn7, + SH4_INTC_IRLn8, + SH4_INTC_IRLn9, + SH4_INTC_IRLnA, + SH4_INTC_IRLnB, + SH4_INTC_IRLnC, + SH4_INTC_IRLnD, + SH4_INTC_IRLnE, + + SH4_INTC_IRL0, + SH4_INTC_IRL1, + SH4_INTC_IRL2, + SH4_INTC_IRL3, + + SH4_INTC_HUDI, + SH4_INTC_GPOI, + + SH4_INTC_DMTE0, + SH4_INTC_DMTE1, + SH4_INTC_DMTE2, + SH4_INTC_DMTE3, + SH4_INTC_DMTE4, + SH4_INTC_DMTE5, + SH4_INTC_DMTE6, + SH4_INTC_DMTE7, + + SH4_INTC_DMAE, + + SH4_INTC_TUNI3, + SH4_INTC_TUNI4, + SH4_INTC_TUNI0, + SH4_INTC_TUNI1, + SH4_INTC_TUNI2, + SH4_INTC_TICPI2, + SH4_INTC_ATI, + SH4_INTC_PRI, + SH4_INTC_CUI, + SH4_INTC_SCI1ERI, + SH4_INTC_SCI1RXI, + + SH4_INTC_SCI1TXI, + SH4_INTC_SCI1TEI, + SH4_INTC_SCIFERI, + SH4_INTC_SCIFRXI, + SH4_INTC_SCIFBRI, + SH4_INTC_SCIFTXI, + SH4_INTC_ITI, + SH4_INTC_RCMI, + SH4_INTC_ROVI +}; + +#define SH4_FPU_PZERO 0 +#define SH4_FPU_NZERO 1 +#define SH4_FPU_DENORM 2 +#define SH4_FPU_NORM 3 +#define SH4_FPU_PINF 4 +#define SH4_FPU_NINF 5 +#define SH4_FPU_qNaN 6 +#define SH4_FPU_sNaN 7 + +enum +{ + SH4_IOPORT_16=8*0, + SH4_IOPORT_4=8*1, + SH4_IOPORT_DMA=8*2, + // future use + SH4_IOPORT_SCI=8*3, + SH4_IOPORT_SCIF=8*4 +}; + +struct sh4_device_dma +{ + uint32_t length; + uint32_t size; + void *buffer; + int channel; +}; + +struct sh4_ddt_dma +{ + uint32_t source; + uint32_t length; + uint32_t size; + uint32_t destination; + void *buffer; + int direction; + int channel; + int mode; +}; + + +// ASID [7:0] | VPN [31:10] | V | | PPN [28:10] | SZ[1:0] | SH | C | PR[1:0] | D | WT | SA[2:0] | TC + +struct sh4_utlb +{ + uint8_t ASID; + uint32_t VPN; + uint8_t V; + uint32_t PPN; + uint8_t PSZ; + uint8_t SH; + uint8_t C; + uint8_t PPR; + uint8_t D; + uint8_t WT; + uint8_t SA; + uint8_t TC; +}; + + +typedef void (*sh4_ftcsr_callback)(uint32_t); + + +#define MCFG_SH4_MD0(_md0) \ + sh34_base_device::set_md0(*device, _md0); + +#define MCFG_SH4_MD1(_md1) \ + sh34_base_device::set_md1(*device, _md1); + +#define MCFG_SH4_MD2(_md2) \ + sh34_base_device::set_md2(*device, _md2); + +#define MCFG_SH4_MD3(_md3) \ + sh34_base_device::set_md3(*device, _md3); + +#define MCFG_SH4_MD4(_md4) \ + sh34_base_device::set_md4(*device, _md4); + +#define MCFG_SH4_MD5(_md5) \ + sh34_base_device::set_md5(*device, _md5); + +#define MCFG_SH4_MD6(_md6) \ + sh34_base_device::set_md6(*device, _md6); + +#define MCFG_SH4_MD7(_md7) \ + sh34_base_device::set_md7(*device, _md7); + +#define MCFG_SH4_MD8(_md8) \ + sh34_base_device::set_md8(*device, _md8); + +#define MCFG_SH4_CLOCK(_clock) \ + sh34_base_device::set_sh4_clock(*device, _clock); + + +#define MCFG_MMU_HACK_TYPE(_hacktype) \ + sh34_base_device::set_mmu_hacktype(*device, _hacktype); + + +class sh34_base_device : public cpu_device +{ +public: +//#if SH4_USE_FASTRAM_OPTIMIZATION + void add_fastram(offs_t start, offs_t end, uint8_t readonly, void *base); +//#endif + + static void set_md0(device_t &device, int md0) { downcast(device).c_md0 = md0; } + static void set_md1(device_t &device, int md0) { downcast(device).c_md1 = md0; } + static void set_md2(device_t &device, int md0) { downcast(device).c_md2 = md0; } + static void set_md3(device_t &device, int md0) { downcast(device).c_md3 = md0; } + static void set_md4(device_t &device, int md0) { downcast(device).c_md4 = md0; } + static void set_md5(device_t &device, int md0) { downcast(device).c_md5 = md0; } + static void set_md6(device_t &device, int md0) { downcast(device).c_md6 = md0; } + static void set_md7(device_t &device, int md0) { downcast(device).c_md7 = md0; } + static void set_md8(device_t &device, int md0) { downcast(device).c_md8 = md0; } + static void set_sh4_clock(device_t &device, int clock) { downcast(device).c_clock = clock; } + + static void set_mmu_hacktype(device_t &device, int hacktype) { downcast(device).m_mmuhack = hacktype; } + + TIMER_CALLBACK_MEMBER( sh4_refresh_timer_callback ); + TIMER_CALLBACK_MEMBER( sh4_rtc_timer_callback ); + TIMER_CALLBACK_MEMBER( sh4_timer_callback ); + TIMER_CALLBACK_MEMBER( sh4_dmac_callback ); + + void sh4_set_frt_input(int state); + void sh4_set_irln_input(int value); + void sh4_set_ftcsr_callback(sh4_ftcsr_callback callback); + int sh4_dma_data(struct sh4_device_dma *s); + void sh4_dma_ddt(struct sh4_ddt_dma *s); + +protected: + // construction/destruction + sh34_base_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, endianness_t endianness, address_map_constructor internal); + + // device-level overrides + virtual void device_start() override; + virtual void device_reset() override; + + // device_execute_interface overrides + virtual uint32_t execute_min_cycles() const override { return 1; } + virtual uint32_t execute_max_cycles() const override { return 4; } + virtual uint32_t execute_input_lines() const override { return 5; } + virtual void execute_run() override; + virtual void execute_set_input(int inputnum, int state) override; + + // device_memory_interface overrides + virtual space_config_vector memory_space_config() const override; + + // device_state_interface overrides + virtual void state_import(const device_state_entry &entry) override; + virtual void state_export(const device_state_entry &entry) override; + virtual void state_string_export(const device_state_entry &entry, std::string &str) const override; + + // device_disasm_interface overrides + virtual uint32_t disasm_min_opcode_bytes() const override { return 2; } + virtual uint32_t disasm_max_opcode_bytes() const override { return 2; } + virtual offs_t disasm_disassemble(std::ostream &stream, offs_t pc, const uint8_t *oprom, const uint8_t *opram, uint32_t options) override; + + address_space_config m_program_config; + address_space_config m_io_config; + + int c_md2; + int c_md1; + int c_md0; + int c_md6; + int c_md4; + int c_md3; + int c_md5; + int c_md7; + int c_md8; + int c_clock; + + // hack 1 = Naomi hack, hack 2 = Work in Progress implementation + int m_mmuhack; + + uint32_t m_ppc; + uint32_t m_pc; + uint32_t m_spc; + uint32_t m_pr; + uint32_t m_sr; + uint32_t m_ssr; + uint32_t m_gbr; + uint32_t m_vbr; + uint32_t m_mach; + uint32_t m_macl; + uint32_t m_r[16]; + uint32_t m_rbnk[2][8]; + uint32_t m_sgr; + uint32_t m_fr[16]; + uint32_t m_xf[16]; + uint32_t m_ea; + uint32_t m_delay; + uint32_t m_cpu_off; + uint32_t m_pending_irq; + uint32_t m_test_irq; + uint32_t m_fpscr; + uint32_t m_fpul; + uint32_t m_dbr; + + uint32_t m_exception_priority[128]; + int m_exception_requesting[128]; + + int8_t m_irq_line_state[17]; + address_space *m_internal; + address_space *m_program; + direct_read_data *m_direct; + address_space *m_io; + + // sh4 internal + uint32_t m_m[16384]; + + // timer regs handled manually for reuse + uint32_t m_SH4_TSTR; + uint32_t m_SH4_TCNT0; + uint32_t m_SH4_TCNT1; + uint32_t m_SH4_TCNT2; + uint32_t m_SH4_TCR0; + uint32_t m_SH4_TCR1; + uint32_t m_SH4_TCR2; + uint32_t m_SH4_TCOR0; + uint32_t m_SH4_TCOR1; + uint32_t m_SH4_TCOR2; + uint32_t m_SH4_TOCR; + uint32_t m_SH4_TCPR2; + + // INTC regs + uint32_t m_SH4_IPRA; + + uint32_t m_SH4_IPRC; + + // DMAC regs + uint32_t m_SH4_SAR0; + uint32_t m_SH4_SAR1; + uint32_t m_SH4_SAR2; + uint32_t m_SH4_SAR3; + + uint32_t m_SH4_DAR0; + uint32_t m_SH4_DAR1; + uint32_t m_SH4_DAR2; + uint32_t m_SH4_DAR3; + + uint32_t m_SH4_CHCR0; + uint32_t m_SH4_CHCR1; + uint32_t m_SH4_CHCR2; + uint32_t m_SH4_CHCR3; + + uint32_t m_SH4_DMATCR0; + uint32_t m_SH4_DMATCR1; + uint32_t m_SH4_DMATCR2; + uint32_t m_SH4_DMATCR3; + + uint32_t m_SH4_DMAOR; + + int8_t m_nmi_line_state; + + uint8_t m_sleep_mode; + + int m_frt_input; + int m_irln; + int m_internal_irq_level; + int m_internal_irq_vector; + + emu_timer *m_dma_timer[4]; + emu_timer *m_refresh_timer; + emu_timer *m_rtc_timer; + emu_timer *m_timer[3]; + uint32_t m_refresh_timer_base; + int m_dma_timer_active[4]; + uint32_t m_dma_source[4]; + uint32_t m_dma_destination[4]; + uint32_t m_dma_count[4]; + int m_dma_wordsize[4]; + int m_dma_source_increment[4]; + int m_dma_destination_increment[4]; + int m_dma_mode[4]; + + int m_sh4_icount; + int m_is_slave; + int m_cpu_clock; + int m_bus_clock; + int m_pm_clock; + int m_fpu_sz; + int m_fpu_pr; + int m_ioport16_pullup; + int m_ioport16_direction; + int m_ioport4_pullup; + int m_ioport4_direction; + + void (*m_ftcsr_read_callback)(uint32_t data); + + /* This MMU simulation is good for the simple remap used on Naomi GD-ROM SQ access *ONLY* */ + uint8_t m_sh4_mmu_enabled; + + int m_cpu_type; + + // sh3 internal + uint32_t m_sh3internal_upper[0x3000/4]; + uint32_t m_sh3internal_lower[0x1000]; + + uint64_t m_debugger_temp; + + + void execute_one_0000(const uint16_t opcode); + void execute_one_4000(const uint16_t opcode); + void execute_one(const uint16_t opcode); + inline void sh4_check_pending_irq(const char *message) // look for highest priority active exception and handle it + { + int a,irq,z; + + irq = 0; + z = -1; + for (a=0;a <= SH4_INTC_ROVI;a++) + { + if (m_exception_requesting[a]) + { + if ((int)m_exception_priority[a] > z) + { + z = m_exception_priority[a]; + irq = a; + } + } + } + if (z >= 0) + { + sh4_exception(message, irq); + } + } + + void TODO(const uint16_t opcode); + void WB(offs_t A, uint8_t V); + void WW(offs_t A, uint16_t V); + void WL(offs_t A, uint32_t V); + void ADD(const uint16_t opcode); + void ADDI(const uint16_t opcode); + void ADDC(const uint16_t opcode); + void ADDV(const uint16_t opcode); + void AND(const uint16_t opcode); + void ANDI(const uint16_t opcode); + void ANDM(const uint16_t opcode); + void BF(const uint16_t opcode); + void BFS(const uint16_t opcode); + void BRA(const uint16_t opcode); + void BRAF(const uint16_t opcode); + void BSR(const uint16_t opcode); + void BSRF(const uint16_t opcode); + void BT(const uint16_t opcode); + void BTS(const uint16_t opcode); + void CLRMAC(const uint16_t opcode); + void CLRT(const uint16_t opcode); + void CMPEQ(const uint16_t opcode); + void CMPGE(const uint16_t opcode); + void CMPGT(const uint16_t opcode); + void CMPHI(const uint16_t opcode); + void CMPHS(const uint16_t opcode); + void CMPPL(const uint16_t opcode); + void CMPPZ(const uint16_t opcode); + void CMPSTR(const uint16_t opcode); + void CMPIM(const uint16_t opcode); + void DIV0S(const uint16_t opcode); + void DIV0U(const uint16_t opcode); + void DIV1(const uint16_t opcode); + void DMULS(const uint16_t opcode); + void DMULU(const uint16_t opcode); + void DT(const uint16_t opcode); + void EXTSB(const uint16_t opcode); + void EXTSW(const uint16_t opcode); + void EXTUB(const uint16_t opcode); + void EXTUW(const uint16_t opcode); + void JMP(const uint16_t opcode); + void JSR(const uint16_t opcode); + void LDCSR(const uint16_t opcode); + void LDCGBR(const uint16_t opcode); + void LDCVBR(const uint16_t opcode); + void LDCMSR(const uint16_t opcode); + void LDCMGBR(const uint16_t opcode); + void LDCMVBR(const uint16_t opcode); + void LDSMACH(const uint16_t opcode); + void LDSMACL(const uint16_t opcode); + void LDSPR(const uint16_t opcode); + void LDSMMACH(const uint16_t opcode); + void LDSMMACL(const uint16_t opcode); + void LDSMPR(const uint16_t opcode); + virtual void LDTLB(const uint16_t opcode); + void MAC_L(const uint16_t opcode); + void MAC_W(const uint16_t opcode); + void MOV(const uint16_t opcode); + void MOVBS(const uint16_t opcode); + void MOVWS(const uint16_t opcode); + void MOVLS(const uint16_t opcode); + void MOVBL(const uint16_t opcode); + void MOVWL(const uint16_t opcode); + void MOVLL(const uint16_t opcode); + void MOVBM(const uint16_t opcode); + void MOVWM(const uint16_t opcode); + void MOVLM(const uint16_t opcode); + void MOVBP(const uint16_t opcode); + void MOVWP(const uint16_t opcode); + void MOVLP(const uint16_t opcode); + void MOVBS0(const uint16_t opcode); + void MOVWS0(const uint16_t opcode); + void MOVLS0(const uint16_t opcode); + void MOVBL0(const uint16_t opcode); + void MOVWL0(const uint16_t opcode); + void MOVLL0(const uint16_t opcode); + void MOVI(const uint16_t opcode); + void MOVWI(const uint16_t opcode); + void MOVLI(const uint16_t opcode); + void MOVBLG(const uint16_t opcode); + void MOVWLG(const uint16_t opcode); + void MOVLLG(const uint16_t opcode); + void MOVBSG(const uint16_t opcode); + void MOVWSG(const uint16_t opcode); + void MOVLSG(const uint16_t opcode); + void MOVBS4(const uint16_t opcode); + void MOVWS4(const uint16_t opcode); + void MOVLS4(const uint16_t opcode); + void MOVBL4(const uint16_t opcode); + void MOVWL4(const uint16_t opcode); + void MOVLL4(const uint16_t opcode); + void MOVA(const uint16_t opcode); + void MOVT(const uint16_t opcode); + void MULL(const uint16_t opcode); + void MULS(const uint16_t opcode); + void MULU(const uint16_t opcode); + void NEG(const uint16_t opcode); + void NEGC(const uint16_t opcode); + void NOP(const uint16_t opcode); + void NOT(const uint16_t opcode); + void OR(const uint16_t opcode); + void ORI(const uint16_t opcode); + void ORM(const uint16_t opcode); + void ROTCL(const uint16_t opcode); + void ROTCR(const uint16_t opcode); + void ROTL(const uint16_t opcode); + void ROTR(const uint16_t opcode); + void RTE(const uint16_t opcode); + void RTS(const uint16_t opcode); + void SETT(const uint16_t opcode); + void SHAL(const uint16_t opcode); + void SHAR(const uint16_t opcode); + void SHLL(const uint16_t opcode); + void SHLL2(const uint16_t opcode); + void SHLL8(const uint16_t opcode); + void SHLL16(const uint16_t opcode); + void SHLR(const uint16_t opcode); + void SHLR2(const uint16_t opcode); + void SHLR8(const uint16_t opcode); + void SHLR16(const uint16_t opcode); + void SLEEP(const uint16_t opcode); + void STCSR(const uint16_t opcode); + void STCGBR(const uint16_t opcode); + void STCVBR(const uint16_t opcode); + void STCMSR(const uint16_t opcode); + void STCMGBR(const uint16_t opcode); + void STCMVBR(const uint16_t opcode); + void STSMACH(const uint16_t opcode); + void STSMACL(const uint16_t opcode); + void STSPR(const uint16_t opcode); + void STSMMACH(const uint16_t opcode); + void STSMMACL(const uint16_t opcode); + void STSMPR(const uint16_t opcode); + void SUB(const uint16_t opcode); + void SUBC(const uint16_t opcode); + void SUBV(const uint16_t opcode); + void SWAPB(const uint16_t opcode); + void SWAPW(const uint16_t opcode); + void TAS(const uint16_t opcode); + void TRAPA(const uint16_t opcode); + void TST(const uint16_t opcode); + void TSTI(const uint16_t opcode); + void TSTM(const uint16_t opcode); + void XOR(const uint16_t opcode); + void XORI(const uint16_t opcode); + void XORM(const uint16_t opcode); + void XTRCT(const uint16_t opcode); + void STCSSR(const uint16_t opcode); + void STCSPC(const uint16_t opcode); + void STCSGR(const uint16_t opcode); + void STSFPUL(const uint16_t opcode); + void STSFPSCR(const uint16_t opcode); + void STCDBR(const uint16_t opcode); + void STCRBANK(const uint16_t opcode); + void STCMRBANK(const uint16_t opcode); + void MOVCAL(const uint16_t opcode); + void CLRS(const uint16_t opcode); + void SETS(const uint16_t opcode); + void STCMSGR(const uint16_t opcode); + void STSMFPUL(const uint16_t opcode); + void STSMFPSCR(const uint16_t opcode); + void STCMDBR(const uint16_t opcode); + void STCMSSR(const uint16_t opcode); + void STCMSPC(const uint16_t opcode); + void LDSMFPUL(const uint16_t opcode); + void LDSMFPSCR(const uint16_t opcode); + void LDCMDBR(const uint16_t opcode); + void LDCMRBANK(const uint16_t opcode); + void LDCMSSR(const uint16_t opcode); + void LDCMSPC(const uint16_t opcode); + void LDSFPUL(const uint16_t opcode); + void LDSFPSCR(const uint16_t opcode); + void LDCDBR(const uint16_t opcode); + void SHAD(const uint16_t opcode); + void SHLD(const uint16_t opcode); + void LDCRBANK(const uint16_t opcode); + void LDCSSR(const uint16_t opcode); + void LDCSPC(const uint16_t opcode); + void PREFM(const uint16_t opcode); + void FMOVMRIFR(const uint16_t opcode); + void FMOVFRMR(const uint16_t opcode); + void FMOVFRMDR(const uint16_t opcode); + void FMOVFRS0(const uint16_t opcode); + void FMOVS0FR(const uint16_t opcode); + void FMOVMRFR(const uint16_t opcode); + void FMOVFR(const uint16_t opcode); + void FLDI1(const uint16_t opcode); + void FLDI0(const uint16_t opcode); + void FLDS(const uint16_t opcode); + void FSTS(const uint16_t opcode); + void FRCHG(); + void FSCHG(); + void FTRC(const uint16_t opcode); + void FLOAT(const uint16_t opcode); + void FNEG(const uint16_t opcode); + void FABS(const uint16_t opcode); + void FCMP_EQ(const uint16_t opcode); + void FCMP_GT(const uint16_t opcode); + void FCNVDS(const uint16_t opcode); + void FCNVSD(const uint16_t opcode); + void FADD(const uint16_t opcode); + void FSUB(const uint16_t opcode); + void FMUL(const uint16_t opcode); + void FDIV(const uint16_t opcode); + void FMAC(const uint16_t opcode); + void FSQRT(const uint16_t opcode); + void FSRRA(const uint16_t opcode); + void FSSCA(const uint16_t opcode); + void FIPR(const uint16_t opcode); + void FTRV(const uint16_t opcode); + void op1111_0xf13(const uint16_t opcode); + void dbreak(const uint16_t opcode); + void op1111_0x13(uint16_t opcode); + uint8_t RB(offs_t A); + uint16_t RW(offs_t A); + uint32_t RL(offs_t A); + void sh4_change_register_bank(int to); + void sh4_swap_fp_registers(); + void sh4_swap_fp_couples(); + void sh4_syncronize_register_bank(int to); + void sh4_default_exception_priorities(); + void sh4_exception_recompute(); + void sh4_exception_request(int exception); + void sh4_exception_unrequest(int exception); + void sh4_exception_checkunrequest(int exception); + void sh4_exception(const char *message, int exception); + uint32_t compute_ticks_refresh_timer(emu_timer *timer, int hertz, int base, int divisor); + void sh4_refresh_timer_recompute(); + void increment_rtc_time(int mode); + void sh4_dmac_nmi(); + void sh4_handler_ipra_w(uint32_t data, uint32_t mem_mask); + virtual uint32_t get_remap(uint32_t address); + virtual uint32_t sh4_getsqremap(uint32_t address); + void sh4_parse_configuration(); + void sh4_timer_recompute(int which); + uint32_t sh4_handle_tcnt0_addr_r(uint32_t mem_mask); + uint32_t sh4_handle_tcnt1_addr_r(uint32_t mem_mask); + uint32_t sh4_handle_tcnt2_addr_r(uint32_t mem_mask); + uint32_t sh4_handle_tcor0_addr_r(uint32_t mem_mask); + uint32_t sh4_handle_tcor1_addr_r(uint32_t mem_mask); + uint32_t sh4_handle_tcor2_addr_r(uint32_t mem_mask); + uint32_t sh4_handle_tcr0_addr_r(uint32_t mem_mask); + uint32_t sh4_handle_tcr1_addr_r(uint32_t mem_mask); + uint32_t sh4_handle_tcr2_addr_r(uint32_t mem_mask); + uint32_t sh4_handle_tstr_addr_r(uint32_t mem_mask); + uint32_t sh4_handle_tocr_addr_r(uint32_t mem_mask); + uint32_t sh4_handle_tcpr2_addr_r(uint32_t mem_mask); + void sh4_handle_tstr_addr_w(uint32_t data, uint32_t mem_mask); + void sh4_handle_tcr0_addr_w(uint32_t data, uint32_t mem_mask); + void sh4_handle_tcr1_addr_w(uint32_t data, uint32_t mem_mask); + void sh4_handle_tcr2_addr_w(uint32_t data, uint32_t mem_mask); + void sh4_handle_tcor0_addr_w(uint32_t data, uint32_t mem_mask); + void sh4_handle_tcor1_addr_w(uint32_t data, uint32_t mem_mask); + void sh4_handle_tcor2_addr_w(uint32_t data, uint32_t mem_mask); + void sh4_handle_tcnt0_addr_w(uint32_t data, uint32_t mem_mask); + void sh4_handle_tcnt1_addr_w(uint32_t data, uint32_t mem_mask); + void sh4_handle_tcnt2_addr_w(uint32_t data, uint32_t mem_mask); + void sh4_handle_tocr_addr_w(uint32_t data, uint32_t mem_mask); + void sh4_handle_tcpr2_addr_w(uint32_t data, uint32_t mem_mask); + int sh4_dma_transfer(int channel, int timermode, uint32_t chcr, uint32_t *sar, uint32_t *dar, uint32_t *dmatcr); + int sh4_dma_transfer_device(int channel, uint32_t chcr, uint32_t *sar, uint32_t *dar, uint32_t *dmatcr); + void sh4_dmac_check(int channel); + void sh4_handle_sar0_addr_w(uint32_t data, uint32_t mem_mask); + void sh4_handle_sar1_addr_w(uint32_t data, uint32_t mem_mask); + void sh4_handle_sar2_addr_w(uint32_t data, uint32_t mem_mask); + void sh4_handle_sar3_addr_w(uint32_t data, uint32_t mem_mask); + void sh4_handle_dar0_addr_w(uint32_t data, uint32_t mem_mask); + void sh4_handle_dar1_addr_w(uint32_t data, uint32_t mem_mask); + void sh4_handle_dar2_addr_w(uint32_t data, uint32_t mem_mask); + void sh4_handle_dar3_addr_w(uint32_t data, uint32_t mem_mask); + void sh4_handle_dmatcr0_addr_w(uint32_t data, uint32_t mem_mask); + void sh4_handle_dmatcr1_addr_w(uint32_t data, uint32_t mem_mask); + void sh4_handle_dmatcr2_addr_w(uint32_t data, uint32_t mem_mask); + void sh4_handle_dmatcr3_addr_w(uint32_t data, uint32_t mem_mask); + void sh4_handle_chcr0_addr_w(uint32_t data, uint32_t mem_mask); + void sh4_handle_chcr1_addr_w(uint32_t data, uint32_t mem_mask); + void sh4_handle_chcr2_addr_w(uint32_t data, uint32_t mem_mask); + void sh4_handle_chcr3_addr_w(uint32_t data, uint32_t mem_mask); + void sh4_handle_dmaor_addr_w(uint32_t data, uint32_t mem_mask); + uint32_t sh4_handle_sar0_addr_r(uint32_t mem_mask) { return m_SH4_SAR0; } + uint32_t sh4_handle_sar1_addr_r(uint32_t mem_mask) { return m_SH4_SAR1; } + uint32_t sh4_handle_sar2_addr_r(uint32_t mem_mask) { return m_SH4_SAR2; } + uint32_t sh4_handle_sar3_addr_r(uint32_t mem_mask) { return m_SH4_SAR3; } + uint32_t sh4_handle_dar0_addr_r(uint32_t mem_mask) { return m_SH4_DAR0; } + uint32_t sh4_handle_dar1_addr_r(uint32_t mem_mask) { return m_SH4_DAR1; } + uint32_t sh4_handle_dar2_addr_r(uint32_t mem_mask) { return m_SH4_DAR2; } + uint32_t sh4_handle_dar3_addr_r(uint32_t mem_mask) { return m_SH4_DAR3; } + uint32_t sh4_handle_dmatcr0_addr_r(uint32_t mem_mask) { return m_SH4_DMATCR0; } + uint32_t sh4_handle_dmatcr1_addr_r(uint32_t mem_mask) { return m_SH4_DMATCR1; } + uint32_t sh4_handle_dmatcr2_addr_r(uint32_t mem_mask) { return m_SH4_DMATCR2; } + uint32_t sh4_handle_dmatcr3_addr_r(uint32_t mem_mask) { return m_SH4_DMATCR3; } + uint32_t sh4_handle_chcr0_addr_r(uint32_t mem_mask) { return m_SH4_CHCR0; } + uint32_t sh4_handle_chcr1_addr_r(uint32_t mem_mask) { return m_SH4_CHCR1; } + uint32_t sh4_handle_chcr2_addr_r(uint32_t mem_mask) { return m_SH4_CHCR2; } + uint32_t sh4_handle_chcr3_addr_r(uint32_t mem_mask) { return m_SH4_CHCR3; } + uint32_t sh4_handle_dmaor_addr_r(uint32_t mem_mask) { return m_SH4_DMAOR; } + +#if SH4_USE_FASTRAM_OPTIMIZATION + /* fast RAM */ + bool m_bigendian; + uint32_t m_byte_xor; + uint32_t m_word_xor; + uint32_t m_dword_xor; + uint32_t m_fastram_select; + struct + { + offs_t start; /* start of the RAM block */ + offs_t end; /* end of the RAM block */ + bool readonly; /* true if read-only */ + void * base; /* base in memory where the RAM lives */ + } m_fastram[SH4_MAX_FASTRAM]; +#endif +}; + + +class sh3_base_device : public sh34_base_device +{ +public: + DECLARE_WRITE32_MEMBER( sh3_internal_w ); + DECLARE_READ32_MEMBER( sh3_internal_r ); + + DECLARE_WRITE32_MEMBER( sh3_internal_high_w ); + DECLARE_READ32_MEMBER( sh3_internal_high_r ); + +protected: + // construction/destruction + sh3_base_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, endianness_t endianness); + + virtual void device_reset() override; +}; + + +class sh4_base_device : public sh34_base_device +{ +public: + DECLARE_WRITE32_MEMBER( sh4_internal_w ); + DECLARE_READ32_MEMBER( sh4_internal_r ); + + DECLARE_READ64_MEMBER( sh4_utlb_address_array_r ); + DECLARE_WRITE64_MEMBER( sh4_utlb_address_array_w ); + DECLARE_READ64_MEMBER( sh4_utlb_data_array1_r ); + DECLARE_WRITE64_MEMBER( sh4_utlb_data_array1_w ); + DECLARE_READ64_MEMBER( sh4_utlb_data_array2_r ); + DECLARE_WRITE64_MEMBER( sh4_utlb_data_array2_w ); + + virtual void LDTLB(const uint16_t opcode) override; + + virtual uint32_t get_remap(uint32_t address) override; + virtual uint32_t sh4_getsqremap(uint32_t address) override; + sh4_utlb m_utlb[64]; + +protected: + // construction/destruction + sh4_base_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, endianness_t endianness); + + virtual void device_start() override; + virtual void device_reset() override; +}; + + +class sh3_device : public sh3_base_device +{ +public: + sh3_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); +}; + + +class sh3be_device : public sh3_base_device +{ +public: + sh3be_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + +protected: + virtual void execute_run() override; + virtual offs_t disasm_disassemble(std::ostream &stream, offs_t pc, const uint8_t *oprom, const uint8_t *opram, uint32_t options) override; +}; + + +class sh4_device : public sh4_base_device +{ +public: + sh4_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); +}; + + +class sh4be_device : public sh4_base_device +{ +public: + sh4be_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + +protected: + virtual void execute_run() override; + virtual offs_t disasm_disassemble(std::ostream &stream, offs_t pc, const uint8_t *oprom, const uint8_t *opram, uint32_t options) override; +}; + + +DECLARE_DEVICE_TYPE(SH3LE, sh3_device) +DECLARE_DEVICE_TYPE(SH3BE, sh3be_device) +DECLARE_DEVICE_TYPE(SH4LE, sh4_device) +DECLARE_DEVICE_TYPE(SH4BE, sh4be_device) + + +/*************************************************************************** + COMPILER-SPECIFIC OPTIONS +***************************************************************************/ + +#define SH4DRC_STRICT_VERIFY 0x0001 /* verify all instructions */ +#define SH4DRC_FLUSH_PC 0x0002 /* flush the PC value before each memory access */ +#define SH4DRC_STRICT_PCREL 0x0004 /* do actual loads on MOVLI/MOVWI instead of collapsing to immediates */ + +#define SH4DRC_COMPATIBLE_OPTIONS (SH4DRC_STRICT_VERIFY | SH4DRC_FLUSH_PC | SH4DRC_STRICT_PCREL) +#define SH4DRC_FASTEST_OPTIONS (0) + +void sh4drc_set_options(device_t *device, uint32_t options); +void sh4drc_add_pcflush(device_t *device, offs_t address); + +#endif // MAME_CPU_SH4_SH4_H diff --git a/src/devices/cpu/sh/sh4comn.cpp b/src/devices/cpu/sh/sh4comn.cpp new file mode 100644 index 00000000000..4f7ae411e7d --- /dev/null +++ b/src/devices/cpu/sh/sh4comn.cpp @@ -0,0 +1,1465 @@ +// license:BSD-3-Clause +// copyright-holders:R. Belmont +/***************************************************************************** + * + * sh4comn.c + * + * SH-4 non-specific components + * + *****************************************************************************/ + +#include "emu.h" +#include "debugger.h" +#include "sh4.h" +#include "sh4regs.h" +#include "sh4comn.h" +#include "sh3comn.h" +#include "sh4tmu.h" +#include "sh4dmac.h" + +static const int rtcnt_div[8] = { 0, 4, 16, 64, 256, 1024, 2048, 4096 }; +static const int daysmonth[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; + + + +static const uint32_t exception_priority_default[] = { + EXPPRI(1,1,0,0), /* Power-on Reset */ + EXPPRI(1,2,0,1), /* Manual Reset */ + EXPPRI(1,1,0,2), /* H-UDI Reset */ + EXPPRI(1,3,0,3), /* Inst TLB Multiple Hit */ + EXPPRI(1,4,0,4), /* Data TLB Multiple Hit */ + + EXPPRI(2,0,0,5), /* User break Before Instruction */ + EXPPRI(2,1,0,6), /* Inst Address Error */ + EXPPRI(2,2,0,7), /* Inst TLB Miss */ + EXPPRI(2,3,0,8), /* Inst TLB Protection Violation */ + EXPPRI(2,4,0,9), /* Illegal Instruction */ + EXPPRI(2,4,0,10), /* Slot Illegal Instruction */ + EXPPRI(2,4,0,11), /* FPU Disable */ + EXPPRI(2,4,0,12), /* Slot FPU Disable */ + EXPPRI(2,5,0,13), /* Data Address Error (Read) */ + EXPPRI(2,5,0,14), /* Data Address Error (Write) */ + EXPPRI(2,6,0,15), /* Data TBL Miss Read */ + EXPPRI(2,6,0,16), /* Data TBL Miss Write */ + EXPPRI(2,7,0,17), /* Data TBL Protection Violation Read */ + EXPPRI(2,7,0,18), /* Data TBL Protection Violation Write */ + EXPPRI(2,8,0,19), /* FPU Exception */ + EXPPRI(2,9,0,20), /* Initial Page Write exception */ + + EXPPRI(2,4,0,21), /* Unconditional TRAP */ + EXPPRI(2,10,0,22), /* User break After Instruction */ + + EXPPRI(3,0,16,SH4_INTC_NMI) /* NMI */ + /* This is copied to a table, and the IRQ priorities filled in later */ +}; + +static const int exception_codes[] = + +{ 0x000, /* Power-on Reset */ + 0x020, /* Manual Reset */ + 0x000, /* H-UDI Reset */ + 0x140, /* Inst TLB Multiple Hit */ + 0x140, /* Data TLB Multiple Hit */ + + 0x1E0, /* User break Before Instruction */ + 0x0E0, /* Inst Address Error */ + 0x040, /* Inst TLB Miss */ + 0x0A0, /* Inst TLB Protection Violation */ + 0x180, /* Illegal Instruction */ + 0x1A0, /* Slot Illegal Instruction */ + 0x800, /* FPU Disable */ + 0x820, /* Slot FPU Disable */ + 0x0E0, /* Data Address Error (Read) */ + 0x100, /* Data Address Error (Write) */ + 0x040, /* Data TBL Miss Read */ + 0x060, /* Data TBL Miss Write */ + 0x0A0, /* Data TBL Protection Violation Read */ + 0x0C0, /* Data TBL Protection Violation Write */ + 0x120, /* FPU Exception */ + 0x080, /* Initial Page Write exception */ + + 0x160, /* Unconditional TRAP */ + 0x1E0, /* User break After Instruction */ + + 0x1C0, /* NMI */ /* SH4_INTC_NMI=23 represents this location in this list.. */ + + 0x200, /* EX Irq 0 */ + 0x220, /* 1 */ + 0x240, /* 2 */ + 0x260, /* 3 */ + 0x280, /* 4 */ + 0x2A0, /* 5 */ + 0x2C0, /* 6 */ + 0x2E0, /* 7 */ + 0x300, /* 8 */ + 0x320, /* 9 */ + 0x340, /* A */ + 0x360, /* B */ + 0x380, /* C */ + 0x3A0, /* D */ + 0x3C0, /* E */ + + 0x240, /* SH4_INTC_IRL0 */ + 0x2A0, /* SH4_INTC_IRL1 */ + 0x300, /* SH4_INTC_IRL2 */ + 0x360, /* SH4_INTC_IRL3 */ + + 0x600, /* HUDI */ + 0x620, /* SH4_INTC_GPOI */ + 0x640, /* SH4_INTC_DMTE0 */ + 0x660, /* SH4_INTC_DMTE1 */ + 0x680, /* SH4_INTC_DMTE2 */ + 0x6A0, /* SH4_INTC_DMTE3 */ + + 0x780, /* SH4_INTC_DMTE4 */ + 0x7A0, /* SH4_INTC_DMTE5 */ + 0x7C0, /* SH4_INTC_DMTE6 */ + 0x7E0, /* SH4_INTC_DMTE7 */ + + 0x6C0, /* SH4_INTC_DMAE */ + + 0xB00, /* SH4_INTC_TUNI3 */ + 0xB80, /* SH4_INTC_TUNI4 */ + 0x400, /* SH4_INTC_TUNI0 */ + 0x420, /* SH4_INTC_TUNI1 */ + 0x440, /* SH4_INTC_TUNI2 */ + 0x460, /* SH4_INTC_TICPI2 */ + 0x480, /* SH4_INTC_ATI */ + 0x4A0, /* SH4_INTC_PRI */ + 0x4C0, /* SH4_INTC_CUI */ + 0x4E0, /* SH4_INTC_SCI1ERI */ + 0x500, /* SH4_INTC_SCI1RXI */ + 0x520, /* SH4_INTC_SCI1TXI */ + 0x540, /* SH4_INTC_SCI1TEI */ + + 0x700, /* SH4_INTC_SCIFERI */ + 0x720, /* SH4_INTC_SCIFRXI */ + 0x740, /* SH4_INTC_SCIFBRI */ + 0x760, /* SH4_INTC_SCIFTXI */ + 0x560, /* SH4_INTC_ITI */ + 0x580, /* SH4_INTC_RCMI */ + 0x5A0 /* SH4_INTC_ROVI */ +}; + +/* SH3 INTEVT2 uses a different table - values of -1 aren't filled in yet, some may not exist on the sh3. */ +/* The above table should differ too, some things depend on the interrupt level rather than beign fixed values */ + +static const int sh3_intevt2_exception_codes[] = + +{ 0x000, /* Power-on Reset */ + -1, /* Manual Reset */ + -1, /* H-UDI Reset */ + -1, /* Inst TLB Multiple Hit */ + -1, /* Data TLB Multiple Hit */ + + -1, /* User break Before Instruction */ + -1, /* Inst Address Error */ + -1, /* Inst TLB Miss */ + -1, /* Inst TLB Protection Violation */ + -1, /* Illegal Instruction */ + -1, /* Slot Illegal Instruction */ + -1, /* FPU Disable */ + -1, /* Slot FPU Disable */ + -1, /* Data Address Error (Read) */ + -1, /* Data Address Error (Write) */ + -1, /* Data TBL Miss Read */ + -1, /* Data TBL Miss Write */ + -1, /* Data TBL Protection Violation Read */ + -1, /* Data TBL Protection Violation Write */ + -1, /* FPU Exception */ + -1, /* Initial Page Write exception */ + + -1, /* Unconditional TRAP */ + -1, /* User break After Instruction */ + + -1, /* NMI */ /* SH4_INTC_NMI=23 represents this location in this list.. */ + + -1, /* EX Irq 0 */ + -1, /* 1 */ + -1, /* 2 */ + -1, /* 3 */ + -1, /* 4 */ + -1, /* 5 */ + -1, /* 6 */ + -1, /* 7 */ + -1, /* 8 */ + -1, /* 9 */ + -1, /* A */ + -1, /* B */ + -1, /* C */ + -1, /* D */ + -1, /* E */ + + 0x600, /* SH4_INTC_IRL0 */ + 0x620, /* SH4_INTC_IRL1 */ + 0x640, /* SH4_INTC_IRL2 */ + 0x660, /* SH4_INTC_IRL3 */ + /* todo: SH3 should have lines 4+5 too? */ + + -1, /* HUDI */ + -1, /* SH4_INTC_GPOI */ + -1, /* SH4_INTC_DMTE0 */ + -1, /* SH4_INTC_DMTE1 */ + -1, /* SH4_INTC_DMTE2 */ + -1, /* SH4_INTC_DMTE3 */ + + -1, /* SH4_INTC_DMTE4 */ + -1, /* SH4_INTC_DMTE5 */ + -1, /* SH4_INTC_DMTE6 */ + -1, /* SH4_INTC_DMTE7 */ + + -1, /* SH4_INTC_DMAE */ + + -1, /* SH4_INTC_TUNI3 */ + -1, /* SH4_INTC_TUNI4 */ + 0x400, /* SH4_INTC_TUNI0 */ + 0x420, /* SH4_INTC_TUNI1 */ + 0x440, /* SH4_INTC_TUNI2 */ + 0x460, /* SH4_INTC_TICPI2 */ + -1, /* SH4_INTC_ATI */ + -1, /* SH4_INTC_PRI */ + -1, /* SH4_INTC_CUI */ + -1, /* SH4_INTC_SCI1ERI */ + -1, /* SH4_INTC_SCI1RXI */ + -1, /* SH4_INTC_SCI1TXI */ + -1, /* SH4_INTC_SCI1TEI */ + + -1, /* SH4_INTC_SCIFERI */ + -1, /* SH4_INTC_SCIFRXI */ + -1, /* SH4_INTC_SCIFBRI */ + -1, /* SH4_INTC_SCIFTXI */ + -1, /* SH4_INTC_ITI */ + -1, /* SH4_INTC_RCMI */ + -1 /* SH4_INTC_ROVI */ +}; + + + +void sh34_base_device::sh4_change_register_bank(int to) +{ + int s; + + if (to) // 0 -> 1 + { + for (s = 0;s < 8;s++) + { + m_rbnk[0][s] = m_r[s]; + m_r[s] = m_rbnk[1][s]; + } + } + else // 1 -> 0 + { + for (s = 0;s < 8;s++) + { + m_rbnk[1][s] = m_r[s]; + m_r[s] = m_rbnk[0][s]; + } + } +} + +void sh34_base_device::sh4_swap_fp_registers() +{ + int s; + uint32_t z; + + for (s = 0;s <= 15;s++) + { + z = m_fr[s]; + m_fr[s] = m_xf[s]; + m_xf[s] = z; + } +} + +void sh34_base_device::sh4_swap_fp_couples() +{ + int s; + uint32_t z; + + for (s = 0;s <= 15;s = s+2) + { + z = m_fr[s]; + m_fr[s] = m_fr[s + 1]; + m_fr[s + 1] = z; + z = m_xf[s]; + m_xf[s] = m_xf[s + 1]; + m_xf[s + 1] = z; + } +} + +void sh34_base_device::sh4_syncronize_register_bank(int to) +{ + int s; + + for (s = 0;s < 8;s++) + { + m_rbnk[to][s] = m_r[s]; + } +} + +void sh34_base_device::sh4_default_exception_priorities() // setup default priorities for exceptions +{ + int a; + + for (a=0;a <= SH4_INTC_NMI;a++) + m_exception_priority[a] = exception_priority_default[a]; + for (a=SH4_INTC_IRLn0;a <= SH4_INTC_IRLnE;a++) + m_exception_priority[a] = INTPRI(15-(a-SH4_INTC_IRLn0), a); + m_exception_priority[SH4_INTC_IRL0] = INTPRI(13, SH4_INTC_IRL0); + m_exception_priority[SH4_INTC_IRL1] = INTPRI(10, SH4_INTC_IRL1); + m_exception_priority[SH4_INTC_IRL2] = INTPRI(7, SH4_INTC_IRL2); + m_exception_priority[SH4_INTC_IRL3] = INTPRI(4, SH4_INTC_IRL3); + for (a=SH4_INTC_HUDI;a <= SH4_INTC_ROVI;a++) + m_exception_priority[a] = INTPRI(0, a); +} + +void sh34_base_device::sh4_exception_recompute() // checks if there is any interrupt with high enough priority +{ + int a,z; + + m_test_irq = 0; + if ((!m_pending_irq) || ((m_sr & BL) && (m_exception_requesting[SH4_INTC_NMI] == 0))) + return; + z = (m_sr >> 4) & 15; + for (a=0;a <= SH4_INTC_ROVI;a++) + { + if (m_exception_requesting[a]) + { + int pri = (((int)m_exception_priority[a] >> 8) & 255); + //logerror("pri is %02x z is %02x\n",pri,z); + if (pri > z) + { + //logerror("will test\n"); + m_test_irq = 1; // will check for exception at end of instructions + break; + } + } + } +} + +void sh34_base_device::sh4_exception_request(int exception) // start requesting an exception +{ + //logerror("sh4_exception_request a\n"); + if (!m_exception_requesting[exception]) + { + //logerror("sh4_exception_request b\n"); + m_exception_requesting[exception] = 1; + m_pending_irq++; + sh4_exception_recompute(); + } +} + +void sh34_base_device::sh4_exception_unrequest(int exception) // stop requesting an exception +{ + if (m_exception_requesting[exception]) + { + m_exception_requesting[exception] = 0; + m_pending_irq--; + sh4_exception_recompute(); + } +} + +void sh34_base_device::sh4_exception_checkunrequest(int exception) +{ + if (exception == SH4_INTC_NMI) + sh4_exception_unrequest(exception); + if ((exception == SH4_INTC_DMTE0) || (exception == SH4_INTC_DMTE1) || + (exception == SH4_INTC_DMTE2) || (exception == SH4_INTC_DMTE3)) + sh4_exception_unrequest(exception); +} + +void sh34_base_device::sh4_exception(const char *message, int exception) // handle exception +{ + uint32_t vector; + + + if (m_cpu_type == CPU_TYPE_SH4) + { + if (exception < SH4_INTC_NMI) + return; // Not yet supported + if (exception == SH4_INTC_NMI) { + if ((m_sr & BL) && (!(m_m[ICR] & 0x200))) + return; + + m_m[ICR] &= ~0x200; + m_m[INTEVT] = 0x1c0; + + + vector = 0x600; + standard_irq_callback(INPUT_LINE_NMI); + LOG(("SH-4 '%s' nmi exception after [%s]\n", tag(), message)); + } else { + // if ((m_m[ICR] & 0x4000) && (m_nmi_line_state == ASSERT_LINE)) + // return; + if (m_sr & BL) + return; + if (((m_exception_priority[exception] >> 8) & 255) <= ((m_sr >> 4) & 15)) + return; + m_m[INTEVT] = exception_codes[exception]; + vector = 0x600; + if ((exception >= SH4_INTC_IRL0) && (exception <= SH4_INTC_IRL3)) + standard_irq_callback((exception-SH4_INTC_IRL0)+SH4_IRL0); + else + standard_irq_callback(SH4_IRL3+1); + LOG(("SH-4 '%s' interrupt exception #%d after [%s]\n", tag(), exception, message)); + } + } + else /* SH3 exceptions */ + { + /***** ASSUME THIS TO BE WRONG FOR NOW *****/ + + if (exception < SH4_INTC_NMI) + return; // Not yet supported + if (exception == SH4_INTC_NMI) + { + return; + } + else + { + if (m_sr & BL) + return; + if (((m_exception_priority[exception] >> 8) & 255) <= ((m_sr >> 4) & 15)) + return; + + + vector = 0x600; + + if ((exception >= SH4_INTC_IRL0) && (exception <= SH4_INTC_IRL3)) + standard_irq_callback((exception-SH4_INTC_IRL0)+SH4_IRL0); + else + standard_irq_callback(SH4_IRL3+1); + + if (sh3_intevt2_exception_codes[exception]==-1) + fatalerror("sh3_intevt2_exception_codes unpopulated for exception %02x\n", exception); + + m_sh3internal_lower[INTEVT2] = sh3_intevt2_exception_codes[exception]; + m_sh3internal_upper[SH3_EXPEVT_ADDR] = exception_codes[exception]; + + + LOG(("SH-3 '%s' interrupt exception #%d after [%s]\n", tag(), exception, message)); + } + + /***** END ASSUME THIS TO BE WRONG FOR NOW *****/ + } + sh4_exception_checkunrequest(exception); + + m_spc = m_pc; + m_ssr = m_sr; + m_sgr = m_r[15]; + + m_sr |= MD; + if ((machine().debug_flags & DEBUG_FLAG_ENABLED) != 0) + sh4_syncronize_register_bank((m_sr & sRB) >> 29); + if (!(m_sr & sRB)) + sh4_change_register_bank(1); + m_sr |= sRB; + m_sr |= BL; + sh4_exception_recompute(); + + /* fetch PC */ + m_pc = m_vbr + vector; + /* wake up if a sleep opcode is triggered */ + if(m_sleep_mode == 1) { m_sleep_mode = 2; } +} + + +uint32_t sh34_base_device::compute_ticks_refresh_timer(emu_timer *timer, int hertz, int base, int divisor) +{ + // elapsed:total = x : ticks + // x=elapsed*tics/total -> x=elapsed*(double)100000000/rtcnt_div[(m_m[RTCSR] >> 3) & 7] + // ticks/total=ticks / ((rtcnt_div[(m_m[RTCSR] >> 3) & 7] * ticks) / 100000000)=1/((rtcnt_div[(m_m[RTCSR] >> 3) & 7] / 100000000)=100000000/rtcnt_div[(m_m[RTCSR] >> 3) & 7] + return base + (uint32_t)((timer->elapsed().as_double() * (double)hertz) / (double)divisor); +} + +void sh34_base_device::sh4_refresh_timer_recompute() +{ + uint32_t ticks; + + if (m_cpu_type != CPU_TYPE_SH4) + fatalerror("sh4_refresh_timer_recompute uses m_m[] with SH3\n"); + + + //if rtcnt < rtcor then rtcor-rtcnt + //if rtcnt >= rtcor then 256-rtcnt+rtcor=256+rtcor-rtcnt + ticks = m_m[RTCOR]-m_m[RTCNT]; + if (ticks <= 0) + ticks = 256 + ticks; + m_refresh_timer->adjust(attotime::from_hz(m_bus_clock) * rtcnt_div[(m_m[RTCSR] >> 3) & 7] * ticks); + m_refresh_timer_base = m_m[RTCNT]; +} + + +TIMER_CALLBACK_MEMBER( sh34_base_device::sh4_refresh_timer_callback ) +{ + if (m_cpu_type != CPU_TYPE_SH4) + fatalerror("sh4_refresh_timer_callback uses m_m[] with SH3\n"); + + m_m[RTCNT] = 0; + sh4_refresh_timer_recompute(); + m_m[RTCSR] |= 128; + if ((m_m[MCR] & 4) && !(m_m[MCR] & 2)) + { + m_m[RFCR] = (m_m[RFCR] + 1) & 1023; + if (((m_m[RTCSR] & 1) && (m_m[RFCR] == 512)) || (m_m[RFCR] == 0)) + { + m_m[RFCR] = 0; + m_m[RTCSR] |= 4; + } + } +} + +void sh34_base_device::increment_rtc_time(int mode) +{ + int carry, year, leap, days; + + if (m_cpu_type != CPU_TYPE_SH4) + fatalerror("increment_rtc_time uses m_m[] with SH3\n"); + + if (mode == 0) + { + carry = 0; + m_m[RSECCNT] = m_m[RSECCNT] + 1; + if ((m_m[RSECCNT] & 0xf) == 0xa) + m_m[RSECCNT] = m_m[RSECCNT] + 6; + if (m_m[RSECCNT] == 0x60) + { + m_m[RSECCNT] = 0; + carry=1; + } + else + return; + } + else + carry = 1; + + m_m[RMINCNT] = m_m[RMINCNT] + carry; + if ((m_m[RMINCNT] & 0xf) == 0xa) + m_m[RMINCNT] = m_m[RMINCNT] + 6; + carry=0; + if (m_m[RMINCNT] == 0x60) + { + m_m[RMINCNT] = 0; + carry = 1; + } + + m_m[RHRCNT] = m_m[RHRCNT] + carry; + if ((m_m[RHRCNT] & 0xf) == 0xa) + m_m[RHRCNT] = m_m[RHRCNT] + 6; + carry = 0; + if (m_m[RHRCNT] == 0x24) + { + m_m[RHRCNT] = 0; + carry = 1; + } + + m_m[RWKCNT] = m_m[RWKCNT] + carry; + if (m_m[RWKCNT] == 0x7) + { + m_m[RWKCNT] = 0; + } + + days = 0; + year = (m_m[RYRCNT] & 0xf) + ((m_m[RYRCNT] & 0xf0) >> 4)*10 + ((m_m[RYRCNT] & 0xf00) >> 8)*100 + ((m_m[RYRCNT] & 0xf000) >> 12)*1000; + leap = 0; + if (!(year%100)) + { + if (!(year%400)) + leap = 1; + } + else if (!(year%4)) + leap = 1; + if (m_m[RMONCNT] != 2) + leap = 0; + if (m_m[RMONCNT]) + days = daysmonth[(m_m[RMONCNT] & 0xf) + ((m_m[RMONCNT] & 0xf0) >> 4)*10 - 1]; + + m_m[RDAYCNT] = m_m[RDAYCNT] + carry; + if ((m_m[RDAYCNT] & 0xf) == 0xa) + m_m[RDAYCNT] = m_m[RDAYCNT] + 6; + carry = 0; + if (m_m[RDAYCNT] > (days+leap)) + { + m_m[RDAYCNT] = 1; + carry = 1; + } + + m_m[RMONCNT] = m_m[RMONCNT] + carry; + if ((m_m[RMONCNT] & 0xf) == 0xa) + m_m[RMONCNT] = m_m[RMONCNT] + 6; + carry=0; + if (m_m[RMONCNT] == 0x13) + { + m_m[RMONCNT] = 1; + carry = 1; + } + + m_m[RYRCNT] = m_m[RYRCNT] + carry; + if ((m_m[RYRCNT] & 0xf) >= 0xa) + m_m[RYRCNT] = m_m[RYRCNT] + 6; + if ((m_m[RYRCNT] & 0xf0) >= 0xa0) + m_m[RYRCNT] = m_m[RYRCNT] + 0x60; + if ((m_m[RYRCNT] & 0xf00) >= 0xa00) + m_m[RYRCNT] = m_m[RYRCNT] + 0x600; + if ((m_m[RYRCNT] & 0xf000) >= 0xa000) + m_m[RYRCNT] = 0; +} + +TIMER_CALLBACK_MEMBER( sh34_base_device::sh4_rtc_timer_callback ) +{ + if (m_cpu_type != CPU_TYPE_SH4) + { + logerror("sh4_rtc_timer_callback uses m_m[] with SH3\n"); + return; + } + + m_rtc_timer->adjust(attotime::from_hz(128)); + m_m[R64CNT] = (m_m[R64CNT]+1) & 0x7f; + if (m_m[R64CNT] == 64) + { + m_m[RCR1] |= 0x80; + increment_rtc_time(0); + //sh4_exception_request(SH4_INTC_NMI); // TEST + } +} + + +void sh34_base_device::sh4_dmac_nmi() // manage dma when nmi gets asserted +{ + int s; + + m_SH4_DMAOR |= DMAOR_NMIF; + for (s = 0;s < 4;s++) + { + if (m_dma_timer_active[s]) + { + logerror("SH4: DMA %d cancelled due to NMI but all data transferred", s); + m_dma_timer[s]->adjust(attotime::never, s); + m_dma_timer_active[s] = 0; + } + } +} + +void sh34_base_device::sh4_handler_ipra_w(uint32_t data, uint32_t mem_mask) +{ + COMBINE_DATA(&m_SH4_IPRA); + /* 15 - 12 TMU0 */ + /* 11 - 8 TMU1 */ + /* 7 - 4 TMU2 */ + /* 3 - 0 RTC */ + m_exception_priority[SH4_INTC_ATI] = INTPRI(m_SH4_IPRA & 0x000f, SH4_INTC_ATI); + m_exception_priority[SH4_INTC_PRI] = INTPRI(m_SH4_IPRA & 0x000f, SH4_INTC_PRI); + m_exception_priority[SH4_INTC_CUI] = INTPRI(m_SH4_IPRA & 0x000f, SH4_INTC_CUI); + + m_exception_priority[SH4_INTC_TUNI2] = INTPRI((m_SH4_IPRA & 0x00f0) >> 4, SH4_INTC_TUNI2); + m_exception_priority[SH4_INTC_TICPI2] = INTPRI((m_SH4_IPRA & 0x00f0) >> 4, SH4_INTC_TICPI2); + + m_exception_priority[SH4_INTC_TUNI1] = INTPRI((m_SH4_IPRA & 0x0f00) >> 8, SH4_INTC_TUNI1); + + m_exception_priority[SH4_INTC_TUNI0] = INTPRI((m_SH4_IPRA & 0xf000) >> 12, SH4_INTC_TUNI0); + + logerror("setting priorities TMU0 %01x TMU1 %01x TMU2 %01x RTC %01x\n", (m_SH4_IPRA & 0xf000)>>12, (m_SH4_IPRA & 0x0f00)>>8, (m_SH4_IPRA & 0x00f0)>>4, (m_SH4_IPRA & 0x000f)>>0); + + sh4_exception_recompute(); +} + + +WRITE32_MEMBER( sh4_base_device::sh4_internal_w ) +{ + int a; + uint32_t addr = (offset << 2) + 0xfe000000; + offset = ((addr & 0xfc) >> 2) | ((addr & 0x1fe0000) >> 11); + + if (m_cpu_type != CPU_TYPE_SH4) + fatalerror("sh4_internal_w uses m_m[] with SH3\n"); + + uint32_t old = m_m[offset]; + COMBINE_DATA(m_m+offset); + +// printf("sh4_internal_w: Write %08x (%x), %08x @ %08x\n", 0xfe000000+((offset & 0x3fc0) << 11)+((offset & 0x3f) << 2), offset, data, mem_mask); + + switch( offset ) + { + case PTEH: // for use with LDTLB opcode + m_m[PTEH] &= 0xffffffff; + /* + NNNN NNNN NNNN NNNN NNNN NN-- AAAA AAAA + + N = VPM = Virtual Page Number + A = ASID = Address Space Identifier + + same as the address table part of the utlb but with 2 unused bits (these are sourced from PTEL instead when LDTLB is called) + */ + + + break; + + case PTEL: + m_m[PTEL] &= 0xffffffff; + /* + ---P PPPP PPPP PPPP PPPP PP-V zRRz CDHW + + same format as data array 1 of the utlb + */ + break; + + case PTEA: + m_m[PTEA] &= 0xffffffff; + /* + ---- ---- ---- ---- ---- ---- ---- TSSS + + same format as data array 2 of the utlb + */ + break; + + case TTB: + m_m[TTB] &= 0xffffffff; + logerror("TTB set to %08x\n", data); + break; + + case TEA: + m_m[TEA] &= 0xffffffff; + logerror("TEA set to %08x\n", data); + break; + + + case MMUCR: // MMU Control + logerror("%s: MMUCR %08x\n", machine().describe_context(), data); + m_m[MMUCR] &= 0xffffffff; + /* + LLLL LL-- BBBB BB-- CCCC CCQV ---- -T-A + + L = LRUI = Least recently used ITLB + B = URB = UTLB replace boundary + C = URC = UTLB replace counter + Q = SQMD = Store Queue Mode Bit + V = SV = Single Virtual Mode Bit + T = TI = TLB invaldiate + A = AT = Address translation bit (enable) + */ + + + + if (data & MMUCR_AT) + { + m_sh4_mmu_enabled = 1; + + + if (m_mmuhack == 1) + { + printf("SH4 MMU Enabled\n"); + printf("If you're seeing this, but running something other than a Naomi GD-ROM game then chances are it won't work\n"); + printf("The MMU emulation is a hack specific to that system\n"); + } + + + if (m_mmuhack == 2) + { + for (int i = 0;i < 64;i++) + { + if (m_utlb[i].V) + { + printf("(entry %02x | ASID: %02x VPN: %08x V: %02x PPN: %08x SZ: %02x SH: %02x C: %02x PPR: %02x D: %02x WT %02x: SA: %02x TC: %02x)\n", + i, + m_utlb[i].ASID, + m_utlb[i].VPN << 10, + m_utlb[i].V, + m_utlb[i].PPN << 10, + m_utlb[i].PSZ, + m_utlb[i].SH, + m_utlb[i].C, + m_utlb[i].PPR, + m_utlb[i].D, + m_utlb[i].WT, + m_utlb[i].SA, + m_utlb[i].TC); + } + } + } + + + } + else + { + m_sh4_mmu_enabled = 0; + } + + break; + + // Memory refresh + case RTCSR: + m_m[RTCSR] &= 255; + if ((old >> 3) & 7) + m_m[RTCNT] = compute_ticks_refresh_timer(m_refresh_timer, m_bus_clock, m_refresh_timer_base, rtcnt_div[(old >> 3) & 7]) & 0xff; + if ((m_m[RTCSR] >> 3) & 7) + { // activated + sh4_refresh_timer_recompute(); + } + else + { + m_refresh_timer->adjust(attotime::never); + } + break; + + case RTCNT: + m_m[RTCNT] &= 255; + if ((m_m[RTCSR] >> 3) & 7) + { // active + sh4_refresh_timer_recompute(); + } + break; + + case RTCOR: + m_m[RTCOR] &= 255; + if ((m_m[RTCSR] >> 3) & 7) + { // active + m_m[RTCNT] = compute_ticks_refresh_timer(m_refresh_timer, m_bus_clock, m_refresh_timer_base, rtcnt_div[(m_m[RTCSR] >> 3) & 7]) & 0xff; + sh4_refresh_timer_recompute(); + } + break; + + case RFCR: + m_m[RFCR] &= 1023; + break; + + // RTC + case RCR1: + if ((m_m[RCR1] & 8) && (~old & 8)) // 0 -> 1 + m_m[RCR1] ^= 1; + break; + + case RCR2: + if (m_m[RCR2] & 2) + { + m_m[R64CNT] = 0; + m_m[RCR2] ^= 2; + } + if (m_m[RCR2] & 4) + { + m_m[R64CNT] = 0; + if (m_m[RSECCNT] >= 30) + increment_rtc_time(1); + m_m[RSECCNT] = 0; + } + if ((m_m[RCR2] & 8) && (~old & 8)) + { // 0 -> 1 + m_rtc_timer->adjust(attotime::from_hz(128)); + } + else if (~(m_m[RCR2]) & 8) + { // 0 + m_rtc_timer->adjust(attotime::never); + } + break; + +/********************************************************************************************************************* + TMU (Timer Unit) +*********************************************************************************************************************/ + case SH4_TSTR_ADDR: sh4_handle_tstr_addr_w(data,mem_mask); break; + case SH4_TCR0_ADDR: sh4_handle_tcr0_addr_w(data,mem_mask); break; + case SH4_TCR1_ADDR: sh4_handle_tcr1_addr_w(data,mem_mask); break; + case SH4_TCR2_ADDR: sh4_handle_tcr2_addr_w(data,mem_mask); break; + case SH4_TCOR0_ADDR: sh4_handle_tcor0_addr_w(data,mem_mask); break; + case SH4_TCNT0_ADDR: sh4_handle_tcnt0_addr_w(data,mem_mask); break; + case SH4_TCOR1_ADDR: sh4_handle_tcor1_addr_w(data,mem_mask); break; + case SH4_TCNT1_ADDR: sh4_handle_tcnt1_addr_w(data,mem_mask); break; + case SH4_TCOR2_ADDR: sh4_handle_tcor2_addr_w(data,mem_mask); break; + case SH4_TCNT2_ADDR: sh4_handle_tcnt2_addr_w(data,mem_mask); break; + case SH4_TOCR_ADDR: sh4_handle_tocr_addr_w(data,mem_mask); break; // not supported + case SH4_TCPR2_ADDR: sh4_handle_tcpr2_addr_w(data,mem_mask); break; // not supported +/********************************************************************************************************************* + INTC (Interrupt Controller) +*********************************************************************************************************************/ + case ICR: + m_m[ICR] = (m_m[ICR] & 0x7fff) | (old & 0x8000); + break; + case IPRA: sh4_handler_ipra_w(data, mem_mask); break; + case IPRB: + m_exception_priority[SH4_INTC_SCI1ERI] = INTPRI((m_m[IPRB] & 0x00f0) >> 4, SH4_INTC_SCI1ERI); + m_exception_priority[SH4_INTC_SCI1RXI] = INTPRI((m_m[IPRB] & 0x00f0) >> 4, SH4_INTC_SCI1RXI); + m_exception_priority[SH4_INTC_SCI1TXI] = INTPRI((m_m[IPRB] & 0x00f0) >> 4, SH4_INTC_SCI1TXI); + m_exception_priority[SH4_INTC_SCI1TEI] = INTPRI((m_m[IPRB] & 0x00f0) >> 4, SH4_INTC_SCI1TEI); + m_exception_priority[SH4_INTC_RCMI] = INTPRI((m_m[IPRB] & 0x0f00) >> 8, SH4_INTC_RCMI); + m_exception_priority[SH4_INTC_ROVI] = INTPRI((m_m[IPRB] & 0x0f00) >> 8, SH4_INTC_ROVI); + m_exception_priority[SH4_INTC_ITI] = INTPRI((m_m[IPRB] & 0xf000) >> 12, SH4_INTC_ITI); + sh4_exception_recompute(); + break; + case IPRC: + m_exception_priority[SH4_INTC_HUDI] = INTPRI(m_m[IPRC] & 0x000f, SH4_INTC_HUDI); + m_exception_priority[SH4_INTC_SCIFERI] = INTPRI((m_m[IPRC] & 0x00f0) >> 4, SH4_INTC_SCIFERI); + m_exception_priority[SH4_INTC_SCIFRXI] = INTPRI((m_m[IPRC] & 0x00f0) >> 4, SH4_INTC_SCIFRXI); + m_exception_priority[SH4_INTC_SCIFBRI] = INTPRI((m_m[IPRC] & 0x00f0) >> 4, SH4_INTC_SCIFBRI); + m_exception_priority[SH4_INTC_SCIFTXI] = INTPRI((m_m[IPRC] & 0x00f0) >> 4, SH4_INTC_SCIFTXI); + m_exception_priority[SH4_INTC_DMTE0] = INTPRI((m_m[IPRC] & 0x0f00) >> 8, SH4_INTC_DMTE0); + m_exception_priority[SH4_INTC_DMTE1] = INTPRI((m_m[IPRC] & 0x0f00) >> 8, SH4_INTC_DMTE1); + m_exception_priority[SH4_INTC_DMTE2] = INTPRI((m_m[IPRC] & 0x0f00) >> 8, SH4_INTC_DMTE2); + m_exception_priority[SH4_INTC_DMTE3] = INTPRI((m_m[IPRC] & 0x0f00) >> 8, SH4_INTC_DMTE3); + m_exception_priority[SH4_INTC_DMAE] = INTPRI((m_m[IPRC] & 0x0f00) >> 8, SH4_INTC_DMAE); + m_exception_priority[SH4_INTC_GPOI] = INTPRI((m_m[IPRC] & 0xf000) >> 12, SH4_INTC_GPOI); + sh4_exception_recompute(); + break; +/********************************************************************************************************************* + DMAC (DMA Controller) +*********************************************************************************************************************/ + case SH4_SAR0_ADDR: sh4_handle_sar0_addr_w(data,mem_mask); break; + case SH4_SAR1_ADDR: sh4_handle_sar1_addr_w(data,mem_mask); break; + case SH4_SAR2_ADDR: sh4_handle_sar2_addr_w(data,mem_mask); break; + case SH4_SAR3_ADDR: sh4_handle_sar3_addr_w(data,mem_mask); break; + case SH4_DAR0_ADDR: sh4_handle_dar0_addr_w(data,mem_mask); break; + case SH4_DAR1_ADDR: sh4_handle_dar1_addr_w(data,mem_mask); break; + case SH4_DAR2_ADDR: sh4_handle_dar2_addr_w(data,mem_mask); break; + case SH4_DAR3_ADDR: sh4_handle_dar3_addr_w(data,mem_mask); break; + case SH4_DMATCR0_ADDR: sh4_handle_dmatcr0_addr_w(data,mem_mask); break; + case SH4_DMATCR1_ADDR: sh4_handle_dmatcr1_addr_w(data,mem_mask); break; + case SH4_DMATCR2_ADDR: sh4_handle_dmatcr2_addr_w(data,mem_mask); break; + case SH4_DMATCR3_ADDR: sh4_handle_dmatcr3_addr_w(data,mem_mask); break; + case SH4_CHCR0_ADDR: sh4_handle_chcr0_addr_w(data,mem_mask); break; + case SH4_CHCR1_ADDR: sh4_handle_chcr1_addr_w(data,mem_mask); break; + case SH4_CHCR2_ADDR: sh4_handle_chcr2_addr_w(data,mem_mask); break; + case SH4_CHCR3_ADDR: sh4_handle_chcr3_addr_w(data,mem_mask); break; + case SH4_DMAOR_ADDR: sh4_handle_dmaor_addr_w(data,mem_mask); break; +/********************************************************************************************************************* + Store Queues +*********************************************************************************************************************/ + case QACR0: + case QACR1: + break; +/********************************************************************************************************************* + I/O +*********************************************************************************************************************/ + case PCTRA: + m_ioport16_pullup = 0; + m_ioport16_direction = 0; + for (a=0;a < 16;a++) { + m_ioport16_direction |= (m_m[PCTRA] & (1 << (a*2))) >> a; + m_ioport16_pullup |= (m_m[PCTRA] & (1 << (a*2+1))) >> (a+1); + } + m_ioport16_direction &= 0xffff; + m_ioport16_pullup = (m_ioport16_pullup | m_ioport16_direction) ^ 0xffff; + if (m_m[BCR2] & 1) + m_io->write_dword(SH4_IOPORT_16, (uint64_t)(m_m[PDTRA] & m_ioport16_direction) | ((uint64_t)m_m[PCTRA] << 16)); + break; + case PDTRA: + if (m_m[BCR2] & 1) + m_io->write_dword(SH4_IOPORT_16, (uint64_t)(m_m[PDTRA] & m_ioport16_direction) | ((uint64_t)m_m[PCTRA] << 16)); + break; + case PCTRB: + m_ioport4_pullup = 0; + m_ioport4_direction = 0; + for (a=0;a < 4;a++) { + m_ioport4_direction |= (m_m[PCTRB] & (1 << (a*2))) >> a; + m_ioport4_pullup |= (m_m[PCTRB] & (1 << (a*2+1))) >> (a+1); + } + m_ioport4_direction &= 0xf; + m_ioport4_pullup = (m_ioport4_pullup | m_ioport4_direction) ^ 0xf; + if (m_m[BCR2] & 1) + m_io->write_dword(SH4_IOPORT_4, (m_m[PDTRB] & m_ioport4_direction) | (m_m[PCTRB] << 16)); + break; + case PDTRB: + if (m_m[BCR2] & 1) + m_io->write_dword(SH4_IOPORT_4, (m_m[PDTRB] & m_ioport4_direction) | (m_m[PCTRB] << 16)); + break; + + case SCBRR2: + break; + + case SCSPTR2: //trips often in aristocrat mk-6 + break; + + default: + logerror("sh4_internal_w: Unmapped write %08x, %08x @ %08x\n", 0xfe000000+((offset & 0x3fc0) << 11)+((offset & 0x3f) << 2), data, mem_mask); + break; + } +} + +READ32_MEMBER( sh4_base_device::sh4_internal_r ) +{ + if (m_cpu_type != CPU_TYPE_SH4) + fatalerror("sh4_internal_r uses m_m[] with SH3\n"); + + uint32_t addr = (offset << 2) + 0xfe000000; + offset = ((addr & 0xfc) >> 2) | ((addr & 0x1fe0000) >> 11); + +// printf("sh4_internal_r: Read %08x (%x) @ %08x\n", 0xfe000000+((offset & 0x3fc0) << 11)+((offset & 0x3f) << 2), offset, mem_mask); + + switch( offset ) + { + case VERSION: + return PVR_SH7091; // 0x040205c1, this is what a real SH7091 in a Dreamcast returns - the later Naomi BIOSes check and care! + case PRR: + return 0; + case IPRD: + return 0x00000000; // SH7750 ignores writes here and always returns zero + case RTCNT: + if ((m_m[RTCSR] >> 3) & 7) + { // activated + //((double)rtcnt_div[(m_m[RTCSR] >> 3) & 7] / (double)100000000) + //return (refresh_timer_base + (m_refresh_timer->elapsed() * (double)100000000) / (double)rtcnt_div[(m_m[RTCSR] >> 3) & 7]) & 0xff; + return compute_ticks_refresh_timer(m_refresh_timer, m_bus_clock, m_refresh_timer_base, rtcnt_div[(m_m[RTCSR] >> 3) & 7]) & 0xff; + } + else + return m_m[RTCNT]; + +/********************************************************************************************************************* + INTC (Interrupt Controller) +*********************************************************************************************************************/ + + case IPRA: + return m_SH4_IPRA; + +/********************************************************************************************************************* + TMU (Timer Unit) +*********************************************************************************************************************/ + case SH4_TSTR_ADDR: return sh4_handle_tstr_addr_r(mem_mask); + case SH4_TCR0_ADDR: return sh4_handle_tcr0_addr_r(mem_mask); + case SH4_TCR1_ADDR: return sh4_handle_tcr1_addr_r(mem_mask); + case SH4_TCR2_ADDR: return sh4_handle_tcr2_addr_r(mem_mask); + case SH4_TCNT0_ADDR: return sh4_handle_tcnt0_addr_r(mem_mask); + case SH4_TCNT1_ADDR: return sh4_handle_tcnt1_addr_r(mem_mask); + case SH4_TCNT2_ADDR: return sh4_handle_tcnt2_addr_r(mem_mask); + case SH4_TCOR0_ADDR: return sh4_handle_tcor0_addr_r(mem_mask); + case SH4_TCOR1_ADDR: return sh4_handle_tcor1_addr_r(mem_mask); + case SH4_TCOR2_ADDR: return sh4_handle_tcor2_addr_r(mem_mask); + case SH4_TOCR_ADDR: return sh4_handle_tocr_addr_r(mem_mask); // not supported + case SH4_TCPR2_ADDR: return sh4_handle_tcpr2_addr_r(mem_mask); // not supported +/********************************************************************************************************************* + DMAC (DMA Controller) +*********************************************************************************************************************/ + case SH4_SAR0_ADDR: return sh4_handle_sar0_addr_r(mem_mask); + case SH4_SAR1_ADDR: return sh4_handle_sar1_addr_r(mem_mask); + case SH4_SAR2_ADDR: return sh4_handle_sar2_addr_r(mem_mask); + case SH4_SAR3_ADDR: return sh4_handle_sar3_addr_r(mem_mask); + case SH4_DAR0_ADDR: return sh4_handle_dar0_addr_r(mem_mask); + case SH4_DAR1_ADDR: return sh4_handle_dar1_addr_r(mem_mask); + case SH4_DAR2_ADDR: return sh4_handle_dar2_addr_r(mem_mask); + case SH4_DAR3_ADDR: return sh4_handle_dar3_addr_r(mem_mask); + case SH4_DMATCR0_ADDR: return sh4_handle_dmatcr0_addr_r(mem_mask); + case SH4_DMATCR1_ADDR: return sh4_handle_dmatcr1_addr_r(mem_mask); + case SH4_DMATCR2_ADDR: return sh4_handle_dmatcr2_addr_r(mem_mask); + case SH4_DMATCR3_ADDR: return sh4_handle_dmatcr3_addr_r(mem_mask); + case SH4_CHCR0_ADDR: return sh4_handle_chcr0_addr_r(mem_mask); + case SH4_CHCR1_ADDR: return sh4_handle_chcr1_addr_r(mem_mask); + case SH4_CHCR2_ADDR: return sh4_handle_chcr2_addr_r(mem_mask); + case SH4_CHCR3_ADDR: return sh4_handle_chcr3_addr_r(mem_mask); + case SH4_DMAOR_ADDR: return sh4_handle_dmaor_addr_r(mem_mask); +/********************************************************************************************************************* + I/O Ports +*********************************************************************************************************************/ + + case PDTRA: + if (m_m[BCR2] & 1) + return (m_io->read_dword(SH4_IOPORT_16) & ~m_ioport16_direction) | (m_m[PDTRA] & m_ioport16_direction); + break; + case PDTRB: + if (m_m[BCR2] & 1) + return (m_io->read_dword(SH4_IOPORT_4) & ~m_ioport4_direction) | (m_m[PDTRB] & m_ioport4_direction); + break; + + // SCIF (UART with FIFO) + case SCFSR2: + return 0x60; //read-only status register + } + return m_m[offset]; +} + +void sh34_base_device::sh4_set_frt_input(int state) +{ + if (m_cpu_type != CPU_TYPE_SH4) + fatalerror("sh4_set_frt_input uses m_m[] with SH3\n"); + + if(state == PULSE_LINE) + { + sh4_set_frt_input(ASSERT_LINE); + sh4_set_frt_input(CLEAR_LINE); + return; + } + + if(m_frt_input == state) { + return; + } + + m_frt_input = state; + + if (m_cpu_type == CPU_TYPE_SH4) + { + if(m_m[5] & 0x8000) { + if(state == CLEAR_LINE) { + return; + } + } else { + if(state == ASSERT_LINE) { + return; + } + } + } + else + { + fatalerror("sh4_set_frt_input uses m_m[] with SH3\n"); + } + +#if 0 + sh4_timer_resync(); + m_icr = m_frc; + m_m[4] |= ICF; + logerror("SH4 '%s': ICF activated (%x)\n", tag(), m_pc & AM); + sh4_recalc_irq(); +#endif +} + +void sh34_base_device::sh4_set_irln_input(int value) +{ + if (m_irln == value) + return; + m_irln = value; + set_input_line(SH4_IRLn, ASSERT_LINE); + set_input_line(SH4_IRLn, CLEAR_LINE); +} + +void sh34_base_device::execute_set_input(int irqline, int state) // set state of external interrupt line +{ + if (m_cpu_type == CPU_TYPE_SH3) + { + /***** ASSUME THIS TO BE WRONG FOR NOW *****/ + + if (irqline == INPUT_LINE_NMI) + { + fatalerror("SH3 NMI Unimplemented\n"); + } + else + { + //if (irqline > SH4_IRL3) + // return; + if (m_irq_line_state[irqline] == state) + return; + m_irq_line_state[irqline] = state; + + if( state == CLEAR_LINE ) + { + LOG(("SH-4 '%s' cleared external irq IRL%d\n", tag(), irqline)); + sh4_exception_unrequest(SH4_INTC_IRL0+irqline-SH4_IRL0); + } + else + { + LOG(("SH-4 '%s' assert external irq IRL%d\n", tag(), irqline)); + sh4_exception_request(SH4_INTC_IRL0+irqline-SH4_IRL0); + } + + } + + /***** END ASSUME THIS TO BE WRONG FOR NOW *****/ + } + else + { + int s; + + if (irqline == INPUT_LINE_NMI) + { + if (m_nmi_line_state == state) + return; + if (m_m[ICR] & 0x100) + { + if ((state == CLEAR_LINE) && (m_nmi_line_state == ASSERT_LINE)) // rising + { + LOG(("SH-4 '%s' assert nmi\n", tag())); + sh4_exception_request(SH4_INTC_NMI); + sh4_dmac_nmi(); + } + } + else + { + if ((state == ASSERT_LINE) && (m_nmi_line_state == CLEAR_LINE)) // falling + { + LOG(("SH-4 '%s' assert nmi\n", tag())); + sh4_exception_request(SH4_INTC_NMI); + sh4_dmac_nmi(); + } + } + if (state == CLEAR_LINE) + m_m[ICR] ^= 0x8000; + else + m_m[ICR] |= 0x8000; + m_nmi_line_state = state; + } + else + { + if (m_m[ICR] & 0x80) // four independent external interrupt sources + { + if (irqline > SH4_IRL3) + return; + if (m_irq_line_state[irqline] == state) + return; + m_irq_line_state[irqline] = state; + + if( state == CLEAR_LINE ) + { + LOG(("SH-4 '%s' cleared external irq IRL%d\n", tag(), irqline)); + sh4_exception_unrequest(SH4_INTC_IRL0+irqline-SH4_IRL0); + } + else + { + LOG(("SH-4 '%s' assert external irq IRL%d\n", tag(), irqline)); + sh4_exception_request(SH4_INTC_IRL0+irqline-SH4_IRL0); + } + } + else // level-encoded interrupt + { + if (irqline != SH4_IRLn) + return; + if ((m_irln > 15) || (m_irln < 0)) + return; + for (s = 0; s < 15; s++) + sh4_exception_unrequest(SH4_INTC_IRLn0+s); + if (m_irln < 15) + sh4_exception_request(SH4_INTC_IRLn0+m_irln); + LOG(("SH-4 '%s' IRLn0-IRLn3 level #%d\n", tag(), m_irln)); + } + } + if (m_test_irq && (!m_delay)) + sh4_check_pending_irq("sh4_set_irq_line"); + } +} + +void sh34_base_device::sh4_parse_configuration() +{ + if(c_clock > 0) + { + switch((c_md2 << 2) | (c_md1 << 1) | (c_md0)) + { + case 0: + m_cpu_clock = c_clock; + m_bus_clock = c_clock / 4; + m_pm_clock = c_clock / 4; + break; + case 1: + m_cpu_clock = c_clock; + m_bus_clock = c_clock / 6; + m_pm_clock = c_clock / 6; + break; + case 2: + m_cpu_clock = c_clock; + m_bus_clock = c_clock / 3; + m_pm_clock = c_clock / 6; + break; + case 3: + m_cpu_clock = c_clock; + m_bus_clock = c_clock / 3; + m_pm_clock = c_clock / 6; + break; + case 4: + m_cpu_clock = c_clock; + m_bus_clock = c_clock / 2; + m_pm_clock = c_clock / 4; + break; + case 5: + m_cpu_clock = c_clock; + m_bus_clock = c_clock / 2; + m_pm_clock = c_clock / 4; + break; + } + m_is_slave = (~(c_md7)) & 1; + } + else + { + m_cpu_clock = 200000000; + m_bus_clock = 100000000; + m_pm_clock = 50000000; + m_is_slave = 0; + } +} + +uint32_t sh34_base_device::get_remap(uint32_t address) +{ + return address; +} + +uint32_t sh4_base_device::get_remap(uint32_t address) +{ + if (m_mmuhack != 2) + return address; + + // is this the correct way around? + int i; + uint32_t topaddr = address&0xfff00000; + + for (i=0;i<64;i++) + { + if (m_utlb[i].V) + { + uint32_t topcmp = (m_utlb[i].PPN << 10) & 0xfff00000; + if (topcmp == topaddr) + return (address & 0x000fffff) | ((m_utlb[i].VPN << 10) & 0xfff00000); + } + } + + //printf("address not in UTLB? %08x\n", address); + + + return address; +} + +uint32_t sh34_base_device::sh4_getsqremap(uint32_t address) +{ + return address; +} + +uint32_t sh4_base_device::sh4_getsqremap(uint32_t address) +{ + if (!m_sh4_mmu_enabled || (m_mmuhack != 1)) + return address; + else + { + int i; + uint32_t topaddr = address&0xfff00000; + + for (i=0;i<64;i++) + { + uint32_t topcmp = (m_utlb[i].VPN<<10)&0xfff00000; + if (topcmp==topaddr) + return (address&0x000fffff) | ((m_utlb[i].PPN<<10)&0xfff00000); + } + } + + return address; +} + + +WRITE64_MEMBER( sh4_base_device::sh4_utlb_address_array_w ) +{ +/* uses bits 13:8 of address to select which UTLB entry we're addressing + bit 7 of the address enables 'associative' mode, causing a search + operation rather than a direct write. + + NNNN NNNN NNNN NNNN NNNN NNDV AAAA AAAA + + N = VPN = Virtual Page Number + D = Dirty Bit + V = Validity Bit + A = ASID = Address Space Identifier +*/ + + logerror("sh4_utlb_address_array_w %08x %08x\n", offset, data); + int offs = offset << 3; + + uint8_t associative = (offs >> 7) & 1; + + if (!associative) + { + // non-associative mode + uint8_t i = (offs >> 8) & 63; + + m_utlb[i].VPN = (data & 0xfffffc00) >> 10; + m_utlb[i].D = (data & 0x00000200) >> 9; + m_utlb[i].V = (data & 0x00000100) >> 8; + m_utlb[i].ASID = (data & 0x000000ff) >> 0; + } + else + { + // associative mode + fatalerror("SH4MMU: associative mode writes unsupported\n"); + } +} + +READ64_MEMBER( sh4_base_device::sh4_utlb_address_array_r ) +{ + // associative bit is ignored for reads + int offs = offset*8; + + uint32_t ret = 0; + + uint8_t i = (offs >> 8) & 63; + + ret |= m_utlb[i].VPN << 10; + ret |= m_utlb[i].D << 9; + ret |= m_utlb[i].V << 8; + ret |= m_utlb[i].ASID << 0; + + return ret; +} + + +WRITE64_MEMBER( sh4_base_device::sh4_utlb_data_array1_w ) +{ +/* uses bits 13:8 of address to select which UTLB entry we're addressing + + ---P PPPP PPPP PPPP PPPP PP-V zRRz CDHW + + P = PPN = Physical page number + V = Validity bit + z = SZ = Page Size (2 bits, split) + D = Dirty Bit + R = PR = Protection Key Data + C = Cacheable bit + H = Share status + W = Write through + - = unused (should be 0) +*/ + logerror("sh4_utlb_data_array1_w %08x %08x\n", offset, data); + int offs = offset*8; + + uint8_t i = (offs>>8)&63; + + m_utlb[i].PPN = (data & 0x1ffffc00) >> 10; + m_utlb[i].V = (data & 0x00000100) >> 8; + m_utlb[i].PSZ = (data & 0x00000080) >> 6; + m_utlb[i].PSZ |=(data & 0x00000010) >> 4; + m_utlb[i].PPR= (data & 0x00000060) >> 5; + m_utlb[i].C = (data & 0x00000008) >> 3; + m_utlb[i].D = (data & 0x00000004) >> 2; + m_utlb[i].SH = (data & 0x00000002) >> 1; + m_utlb[i].WT = (data & 0x00000001) >> 0; +} + + +READ64_MEMBER(sh4_base_device::sh4_utlb_data_array1_r) +{ + uint32_t ret = 0; + int offs = offset*8; + + uint8_t i = (offs>>8)&63; + + ret |= m_utlb[i].PPN << 10; + ret |= m_utlb[i].V << 8; + ret |= (m_utlb[i].PSZ & 2) << 6; + ret |= (m_utlb[i].PSZ & 1) << 4; + ret |= m_utlb[i].PPR << 5; + ret |= m_utlb[i].C << 3; + ret |= m_utlb[i].D << 2; + ret |= m_utlb[i].SH << 1; + ret |= m_utlb[i].WT << 0; + + return ret; +} + + + +WRITE64_MEMBER( sh4_base_device::sh4_utlb_data_array2_w ) +{ +/* uses bits 13:8 of address to select which UTLB entry we're addressing + + ---- ---- ---- ---- ---- ---- ---- TSSS + + T = TC = Timing Control + S = SA = Space attributes + - = unused (should be 0) + +*/ + + logerror("sh4_utlb_data_array2_w %08x %08x\n", offset, data); + int offs = offset*8; + + uint8_t i = (offs>>8)&63; + + m_utlb[i].TC = (data & 0x00000008) >> 3; + m_utlb[i].SA = (data & 0x00000007) >> 0; +} + + +READ64_MEMBER(sh4_base_device::sh4_utlb_data_array2_r) +{ + uint32_t ret = 0; + int offs = offset*8; + + uint8_t i = (offs>>8)&63; + + ret |= m_utlb[i].TC << 3; + ret |= m_utlb[i].SA << 0; + + return ret; +} diff --git a/src/devices/cpu/sh/sh4comn.h b/src/devices/cpu/sh/sh4comn.h new file mode 100644 index 00000000000..230207652d6 --- /dev/null +++ b/src/devices/cpu/sh/sh4comn.h @@ -0,0 +1,174 @@ +// license:BSD-3-Clause +// copyright-holders:R. Belmont +/***************************************************************************** + * + * sh4comn.h + * + * SH-4 non-specific components + * + *****************************************************************************/ + +#pragma once + +#ifndef __SH4COMN_H__ +#define __SH4COMN_H__ + +//#define USE_SH4DRC + +/* speed up delay loops, bail out of tight loops */ +#define BUSY_LOOP_HACKS 0 + +#define VERBOSE 0 + +#ifdef USE_SH4DRC +#include "cpu/drcfe.h" +#include "cpu/drcuml.h" +#include "cpu/drcumlsh.h" + +class sh4_frontend; +#endif + +#define CPU_TYPE_SH3 (2) +#define CPU_TYPE_SH4 (3) + +#define LOG(x) do { if (VERBOSE) logerror x; } while (0) + +#define EXPPRI(pl,po,p,n) (((4-(pl)) << 24) | ((15-(po)) << 16) | ((p) << 8) | (255-(n))) +#define NMIPRI() EXPPRI(3,0,16,SH4_INTC_NMI) +#define INTPRI(p,n) EXPPRI(4,2,p,n) + +#define FP_RS(r) m_fr[(r)] // binary representation of single precision floating point register r +#define FP_RFS(r) *( (float *)(m_fr+(r)) ) // single precision floating point register r +#define FP_RFD(r) *( (double *)(m_fr+(r)) ) // double precision floating point register r +#define FP_XS(r) m_xf[(r)] // binary representation of extended single precision floating point register r +#define FP_XFS(r) *( (float *)(m_xf+(r)) ) // single precision extended floating point register r +#define FP_XFD(r) *( (double *)(m_xf+(r)) ) // double precision extended floating point register r +#ifdef LSB_FIRST +#define FP_RS2(r) m_fr[(r) ^ m_fpu_pr] +#define FP_RFS2(r) *( (float *)(m_fr+((r) ^ m_fpu_pr)) ) +#define FP_XS2(r) m_xf[(r) ^ m_fpu_pr] +#define FP_XFS2(r) *( (float *)(m_xf+((r) ^ m_fpu_pr)) ) +#endif + + +#ifdef USE_SH4DRC +struct sh4_state +{ + int icount; + + int pcfsel; // last pcflush entry set + int maxpcfsel; // highest valid pcflush entry + uint32_t pcflushes[16]; // pcflush entries + + drc_cache * cache; /* pointer to the DRC code cache */ + drcuml_state * drcuml; /* DRC UML generator state */ + sh4_frontend * drcfe; /* pointer to the DRC front-end class */ + uint32_t drcoptions; /* configurable DRC options */ + + /* internal stuff */ + uint8_t cache_dirty; /* true if we need to flush the cache */ + + /* parameters for subroutines */ + uint64_t numcycles; /* return value from gettotalcycles */ + uint32_t arg0; /* print_debug argument 1 */ + uint32_t arg1; /* print_debug argument 2 */ + uint32_t irq; /* irq we're taking */ + + /* register mappings */ + uml::parameter regmap[16]; /* parameter to register mappings for all 16 integer registers */ + + uml::code_handle * entry; /* entry point */ + uml::code_handle * read8; /* read byte */ + uml::code_handle * write8; /* write byte */ + uml::code_handle * read16; /* read half */ + uml::code_handle * write16; /* write half */ + uml::code_handle * read32; /* read word */ + uml::code_handle * write32; /* write word */ + + uml::code_handle * interrupt; /* interrupt */ + uml::code_handle * nocode; /* nocode */ + uml::code_handle * out_of_cycles; /* out of cycles exception handler */ + + uint32_t prefadr; + uint32_t target; +}; +#endif + +#ifdef USE_SH4DRC +class sh4_frontend : public drc_frontend +{ +public: + sh4_frontend(sh4_state &state, uint32_t window_start, uint32_t window_end, uint32_t max_sequence); + +protected: + virtual bool describe(opcode_desc &desc, const opcode_desc *prev); + +private: + bool describe_group_0(opcode_desc &desc, const opcode_desc *prev, uint16_t opcode); + bool describe_group_2(opcode_desc &desc, const opcode_desc *prev, uint16_t opcode); + bool describe_group_3(opcode_desc &desc, const opcode_desc *prev, uint16_t opcode); + bool describe_group_4(opcode_desc &desc, const opcode_desc *prev, uint16_t opcode); + bool describe_group_6(opcode_desc &desc, const opcode_desc *prev, uint16_t opcode); + bool describe_group_8(opcode_desc &desc, const opcode_desc *prev, uint16_t opcode); + bool describe_group_12(opcode_desc &desc, const opcode_desc *prev, uint16_t opcode); + bool describe_group_15(opcode_desc &desc, const opcode_desc *prev, uint16_t opcode); + + sh4_state &m_context; +}; +#endif + + +enum +{ + ICF = 0x00800000, + OCFA = 0x00080000, + OCFB = 0x00040000, + OVF = 0x00020000 +}; + +/* Bits in SR */ +#define T 0x00000001 +#define S 0x00000002 +#define I 0x000000f0 +#define Q 0x00000100 +#define M 0x00000200 +#define FD 0x00008000 +#define BL 0x10000000 +#define sRB 0x20000000 +#define MD 0x40000000 + +/* 29 bits */ +#define AM 0x1fffffff + +#define FLAGS (MD|sRB|BL|FD|M|Q|I|S|T) + +/* Bits in FPSCR */ +#define RM 0x00000003 +#define DN 0x00040000 +#define PR 0x00080000 +#define SZ 0x00100000 +#define FR 0x00200000 + +#define Rn ((opcode>>8)&15) +#define Rm ((opcode>>4)&15) + +#define REGFLAG_R(n) (1 << (n)) +#define REGFLAG_FR(n) (1 << (n)) +#define REGFLAG_XR(n) (1 << (n)) + +/* register flags 1 */ +#define REGFLAG_PR (1 << 0) +#define REGFLAG_MACL (1 << 1) +#define REGFLAG_MACH (1 << 2) +#define REGFLAG_GBR (1 << 3) +#define REGFLAG_VBR (1 << 4) +#define REGFLAG_SR (1 << 5) +#define REGFLAG_SGR (1 << 6) +#define REGFLAG_FPUL (1 << 7) +#define REGFLAG_FPSCR (1 << 8) +#define REGFLAG_DBR (1 << 9) +#define REGFLAG_SSR (1 << 10) +#define REGFLAG_SPC (1 << 11) + + +#endif /* __SH4COMN_H__ */ diff --git a/src/devices/cpu/sh/sh4dasm.cpp b/src/devices/cpu/sh/sh4dasm.cpp new file mode 100644 index 00000000000..faff895f3a5 --- /dev/null +++ b/src/devices/cpu/sh/sh4dasm.cpp @@ -0,0 +1,905 @@ +// license:BSD-3-Clause +// copyright-holders:R. Belmont +#include "emu.h" +#include "debugger.h" +#include "sh4.h" + +#define SIGNX8(x) (((int32_t)(x) << 24) >> 24) +#define SIGNX12(x) (((int32_t)(x) << 20) >> 20) + +#define Rn ((opcode >> 8) & 15) +#define Rm ((opcode >> 4) & 15) + +static const char *const regname[16] = { + "R0", "R1", "R2", "R3", "R4", "R5", "R6", "R7", + "R8", "R9", "R10","R11","R12","R13","R14","R15" +}; + +static uint32_t op0000(std::ostream &stream, uint32_t pc, uint16_t opcode) +{ + uint32_t flags = 0; + switch (opcode & 0xF) + { + case 0x0: + case 0x1: + util::stream_format(stream, "?????? $%04X", opcode); + break; + case 0x2: + if (opcode & 0x80) { + util::stream_format(stream, "STC %s_BANK,%s", regname[(Rm) & 7], regname[Rn]); + return flags; + } + switch (opcode & 0x70) + { + case 0x00: + util::stream_format(stream, "STC SR,%s", regname[Rn]); + break; + case 0x10: + util::stream_format(stream, "STC GBR,%s", regname[Rn]); + break; + case 0x20: + util::stream_format(stream, "STC VBR,%s", regname[Rn]); + break; + case 0x30: + util::stream_format(stream, "STC SSR,%s", regname[Rn]); + break; + case 0x40: + util::stream_format(stream, "STC SPC,%s", regname[Rn]); + break; + } + break; + case 0x3: + switch (opcode & 0xF0) + { + case 0x00: + util::stream_format(stream, "BSRF %s", regname[Rn]); + break; + case 0x20: + util::stream_format(stream, "BRAF %s", regname[Rn]); + break; + case 0x80: + util::stream_format(stream, "PREF @%s", regname[Rn]); + break; + case 0x90: + util::stream_format(stream, "OCBI @%s", regname[Rn]); + break; + case 0xA0: + util::stream_format(stream, "OCBP @%s", regname[Rn]); + break; + case 0xB0: + util::stream_format(stream, "OCBWB @%s", regname[Rn]); + break; + case 0xC0: + util::stream_format(stream, "MOVCA.L R0,@%s", regname[Rn]); + break; + } + break; + case 0x4: + util::stream_format(stream, "MOV.B %s,@(R0,%s)", regname[Rm], regname[Rn]); + break; + case 0x5: + util::stream_format(stream, "MOV.W %s,@(R0,%s)", regname[Rm], regname[Rn]); + break; + case 0x6: + util::stream_format(stream, "MOV.L %s,@(R0,%s)", regname[Rm], regname[Rn]); + break; + case 0x7: + util::stream_format(stream, "MUL.L %s,%s", regname[Rm], regname[Rn]); + break; + case 0x8: + switch (opcode & 0x70) + { + case 0x00: stream << "CLRT"; break; + case 0x10: stream << "SETT"; break; + case 0x20: stream << "CLRMAC"; break; + case 0x30: stream << "LDTLB"; break; + case 0x40: stream << "CLRS"; break; + case 0x50: stream << "SETS"; break; + } + break; + case 0x9: + switch (opcode & 0x30) + { + case 0x00: + stream << "NOP"; + break; + case 0x10: + stream << "DIV0U"; + break; + case 0x20: + util::stream_format(stream, "MOVT %s", regname[Rn]); + break; + } + break; + case 0xA: + switch (opcode & 0x70) + { + case 0x00: + util::stream_format(stream, "STS MACH,%s", regname[Rn]); + break; + case 0x10: + util::stream_format(stream, "STS MACL,%s", regname[Rn]); + break; + case 0x20: + util::stream_format(stream, "STS PR,%s", regname[Rn]); + break; + case 0x30: + util::stream_format(stream, "STC SGR,%s", regname[Rn]); + break; + case 0x50: + util::stream_format(stream, "STS FPUL,%s", regname[Rn]); + break; + case 0x60: + util::stream_format(stream, "STS FPSCR,%s", regname[Rn]); + break; + case 0x70: + util::stream_format(stream, "STC DBR,%s", regname[Rn]); + break; + } + break; + case 0xB: + switch (opcode & 0x30) + { + case 0x00: + stream << "RTS"; + flags = DASMFLAG_STEP_OUT; + break; + case 0x10: + stream << "SLEEP"; + break; + case 0x20: + stream << "RTE"; + flags = DASMFLAG_STEP_OUT; + break; + } + break; + case 0xC: + util::stream_format(stream, "MOV.B @(R0,%s),%s", regname[Rm], regname[Rn]); + break; + case 0xD: + util::stream_format(stream, "MOV.W @(R0,%s),%s", regname[Rm], regname[Rn]); + break; + case 0xE: + util::stream_format(stream, "MOV.L @(R0,%s),%s", regname[Rm], regname[Rn]); + break; + case 0xF: + util::stream_format(stream, "MAC.L @%s+,@%s+", regname[Rn], regname[Rm]); + break; + } + return flags; +} + +static uint32_t op0001(std::ostream &stream, uint32_t pc, uint16_t opcode) +{ + util::stream_format(stream, "MOV.L %s,@($%02X,%s)", regname[Rm], (opcode & 15) * 4, regname[Rn]); + return 0; +} + +static uint32_t op0010(std::ostream &stream, uint32_t pc, uint16_t opcode) +{ + switch (opcode & 15) + { + case 0: + util::stream_format(stream, "MOV.B %s,@%s", regname[Rm], regname[Rn]); + break; + case 1: + util::stream_format(stream, "MOV.W %s,@%s", regname[Rm], regname[Rn]); + break; + case 2: + util::stream_format(stream, "MOV.L %s,@%s", regname[Rm], regname[Rn]); + break; + case 3: + util::stream_format(stream, "?????? $%04X", opcode); + break; + case 4: + util::stream_format(stream, "MOV.B %s,@-%s", regname[Rm], regname[Rn]); + break; + case 5: + util::stream_format(stream, "MOV.W %s,@-%s", regname[Rm], regname[Rn]); + break; + case 6: + util::stream_format(stream, "MOV.L %s,@-%s", regname[Rm], regname[Rn]); + break; + case 7: + util::stream_format(stream, "DIV0S %s,%s", regname[Rm], regname[Rn]); + break; + case 8: + util::stream_format(stream, "TST %s,%s", regname[Rm], regname[Rn]); + break; + case 9: + util::stream_format(stream, "AND %s,%s", regname[Rm], regname[Rn]); + break; + case 10: + util::stream_format(stream, "XOR %s,%s", regname[Rm], regname[Rn]); + break; + case 11: + util::stream_format(stream, "OR %s,%s", regname[Rm], regname[Rn]); + break; + case 12: + util::stream_format(stream, "CMP/STR %s,%s", regname[Rm], regname[Rn]); + break; + case 13: + util::stream_format(stream, "XTRCT %s,%s", regname[Rm], regname[Rn]); + break; + case 14: + util::stream_format(stream, "MULU.W %s,%s", regname[Rm], regname[Rn]); + break; + case 15: + util::stream_format(stream, "MULS.W %s,%s", regname[Rm], regname[Rn]); + break; + } + return 0; +} + +static uint32_t op0011(std::ostream &stream, uint32_t pc, uint16_t opcode) +{ + switch (opcode & 15) + { + case 0: + util::stream_format(stream, "CMP/EQ %s,%s", regname[Rm], regname[Rn]); + break; + case 1: + util::stream_format(stream, "?????? %s,%s", regname[Rm], regname[Rn]); + break; + case 2: + util::stream_format(stream, "CMP/HS %s,%s", regname[Rm], regname[Rn]); + break; + case 3: + util::stream_format(stream, "CMP/GE %s,%s", regname[Rm], regname[Rn]); + break; + case 4: + util::stream_format(stream, "DIV1 %s,%s", regname[Rm], regname[Rn]); + break; + case 5: + util::stream_format(stream, "DMULU.L %s,%s", regname[Rm], regname[Rn]); + break; + case 6: + util::stream_format(stream, "CMP/HI %s,%s", regname[Rm], regname[Rn]); + break; + case 7: + util::stream_format(stream, "CMP/GT %s,%s", regname[Rm], regname[Rn]); + break; + case 8: + util::stream_format(stream, "SUB %s,%s", regname[Rm], regname[Rn]); + break; + case 9: + util::stream_format(stream, "?????? %s,%s", regname[Rm], regname[Rn]); + break; + case 10: + util::stream_format(stream, "SUBC %s,%s", regname[Rm], regname[Rn]); + break; + case 11: + util::stream_format(stream, "SUBV %s,%s", regname[Rm], regname[Rn]); + break; + case 12: + util::stream_format(stream, "ADD %s,%s", regname[Rm], regname[Rn]); + break; + case 13: + util::stream_format(stream, "DMULS.L %s,%s", regname[Rm], regname[Rn]); + break; + case 14: + util::stream_format(stream, "ADDC %s,%s", regname[Rm], regname[Rn]); + break; + case 15: + util::stream_format(stream, "ADDV %s,%s", regname[Rm], regname[Rn]); + break; + } + return 0; +} + +static uint32_t op0100(std::ostream &stream, uint32_t pc, uint16_t opcode) +{ + uint32_t flags = 0; + switch (opcode & 0xF) + { + case 0x0: + switch (opcode & 0x30) + { + case 0x00: + util::stream_format(stream, "SHLL %s", regname[Rn]); + break; + case 0x10: + util::stream_format(stream, "DT %s", regname[Rn]); + break; + case 0x20: + util::stream_format(stream, "SHAL %s", regname[Rn]); + break; + } + break; + case 0x1: + switch (opcode & 0x30) + { + case 0x00: + util::stream_format(stream, "SHLR %s", regname[Rn]); + break; + case 0x10: + util::stream_format(stream, "CMP/PZ %s", regname[Rn]); + break; + case 0x20: + util::stream_format(stream, "SHAR %s", regname[Rn]); + break; + } + break; + case 0x2: + switch (opcode & 0xF0) + { + case 0x00: + util::stream_format(stream, "STS.L MACH,@-%s", regname[Rn]); + break; + case 0x10: + util::stream_format(stream, "STS.L MACL,@-%s", regname[Rn]); + break; + case 0x20: + util::stream_format(stream, "STS.L PR,@-%s", regname[Rn]); + break; + case 0x30: + util::stream_format(stream, "STC.L SGR,@-%s", regname[Rn]); + break; + case 0x50: + util::stream_format(stream, "STS.L FPUL,@-%s", regname[Rn]); + break; + case 0x60: + util::stream_format(stream, "STS.L FPSCR,@-%s", regname[Rn]); + break; + case 0xF0: + util::stream_format(stream, "STC.L DBR,@-%s", regname[Rn]); + break; + } + break; + case 0x3: + if (opcode & 0x80) { + util::stream_format(stream, "STC.L %s_BANK,@-%s", regname[(Rm) & 7],regname[Rn]); + return flags; + } + switch (opcode & 0x70) + { + case 0x00: + util::stream_format(stream, "STC.L SR,@-%s", regname[Rn]); + break; + case 0x10: + util::stream_format(stream, "STC.L GBR,@-%s", regname[Rn]); + break; + case 0x20: + util::stream_format(stream, "STC.L VBR,@-%s", regname[Rn]); + break; + case 0x30: + util::stream_format(stream, "STC.L SSR,@-%s", regname[Rn]); + break; + case 0x40: + util::stream_format(stream, "STC.L SPC,@-%s", regname[Rn]); + break; + } + break; + case 0x4: + switch (opcode & 0x30) + { + case 0x00: + util::stream_format(stream, "ROTL %s", regname[Rn]); + break; + case 0x20: + util::stream_format(stream, "ROTCL %s", regname[Rn]); + break; + } + break; + case 0x5: + switch (opcode & 0x30) + { + case 0x00: + util::stream_format(stream, "ROTR %s", regname[Rn]); + break; + case 0x10: + util::stream_format(stream, "CMP/PL %s", regname[Rn]); + break; + case 0x20: + util::stream_format(stream, "ROTCR %s", regname[Rn]); + break; + } + break; + case 0x6: + switch (opcode & 0xF0) + { + case 0x00: + util::stream_format(stream, "LDS.L @%s+,MACH", regname[Rn]); + break; + case 0x10: + util::stream_format(stream, "LDS.L @%s+,MACL", regname[Rn]); + break; + case 0x20: + util::stream_format(stream, "LDS.L @%s+,PR", regname[Rn]); + break; + case 0x50: + util::stream_format(stream, "LDS.L @%s+,FPUL", regname[Rn]); + break; + case 0x60: + util::stream_format(stream, "LDS.L @%s+,FPSCR", regname[Rn]); + break; + case 0xF0: + util::stream_format(stream, "LDC.L @%s+,DBR", regname[Rn]); + break; + } + break; + case 0x7: + if (opcode & 0x80) { + util::stream_format(stream, "LDC.L @%s+,%s_BANK", regname[Rn],regname[(Rm) & 7]); + return flags; + } + switch (opcode & 0x70) + { + case 0x00: + util::stream_format(stream, "LDC.L @%s+,SR", regname[Rn]); + break; + case 0x10: + util::stream_format(stream, "LDC.L @%s+,GBR", regname[Rn]); + break; + case 0x20: + util::stream_format(stream, "LDC.L @%s+,VBR", regname[Rn]); + break; + case 0x30: + util::stream_format(stream, "LDC.L @%s+,SSR", regname[Rn]); + break; + case 0x40: + util::stream_format(stream, "LDC.L @%s+,SPC", regname[Rn]); + break; + } + break; + case 0x8: + switch (opcode & 0x30) + { + case 0x00: + util::stream_format(stream, "SHLL2 %s", regname[Rn]); + break; + case 0x10: + util::stream_format(stream, "SHLL8 %s", regname[Rn]); + break; + case 0x20: + util::stream_format(stream, "SHLL16 %s", regname[Rn]); + break; + } + break; + case 0x9: + switch (opcode & 0x30) + { + case 0x00: + util::stream_format(stream, "SHLR2 %s", regname[Rn]); + break; + case 0x10: + util::stream_format(stream, "SHLR8 %s", regname[Rn]); + break; + case 0x20: + util::stream_format(stream, "SHLR16 %s", regname[Rn]); + break; + } + break; + case 0xA: + switch (opcode & 0xF0) + { + case 0x00: + util::stream_format(stream, "LDS %s,MACH", regname[Rn]); + break; + case 0x10: + util::stream_format(stream, "LDS %s,MACL", regname[Rn]); + break; + case 0x20: + util::stream_format(stream, "LDS %s,PR", regname[Rn]); + break; + case 0x50: + util::stream_format(stream, "LDS %s,FPUL", regname[Rn]); + break; + case 0x60: + util::stream_format(stream, "LDS %s,FPSCR", regname[Rn]); + break; + case 0xF0: + util::stream_format(stream, "LDC %s,DBR", regname[Rn]); + break; + } + break; + case 0xB: + switch (opcode & 0x30) + { + case 0x00: + util::stream_format(stream, "JSR %s", regname[Rn]); + flags = DASMFLAG_STEP_OVER | DASMFLAG_STEP_OVER_EXTRA(1); + break; + case 0x10: + util::stream_format(stream, "TAS %s", regname[Rn]); + break; + case 0x20: + util::stream_format(stream, "JMP %s", regname[Rn]); + break; + } + break; + case 0xC: + util::stream_format(stream, "SHAD %s,%s", regname[Rm], regname[Rn]); + break; + case 0xD: + util::stream_format(stream, "SHLD %s,%s", regname[Rm], regname[Rn]); + break; + case 0xE: + if (opcode & 0x80) { + util::stream_format(stream, "LDC %s,%s_BANK", regname[Rn],regname[(Rm) & 7]); + return flags; + } + switch (opcode & 0x70) + { + case 0x00: + util::stream_format(stream, "LDC %s,SR", regname[Rn]); + break; + case 0x10: + util::stream_format(stream, "LDC %s,GBR", regname[Rn]); + break; + case 0x20: + util::stream_format(stream, "LDC %s,VBR", regname[Rn]); + break; + case 0x30: + util::stream_format(stream, "LDC %s,SSR", regname[Rn]); + break; + case 0x40: + util::stream_format(stream, "LDC %s,SPC", regname[Rn]); + break; + } + break; + case 0xF: + util::stream_format(stream, "MAC.W @%s+,@%s+", regname[Rm], regname[Rn]); + break; + } + return flags; +} + +static uint32_t op0101(std::ostream &stream, uint32_t pc, uint16_t opcode) +{ + util::stream_format(stream, "MOV.L @($%02X,%s),%s", (opcode & 15) * 4, regname[Rm], regname[Rn]); + return 0; +} + +static uint32_t op0110(std::ostream &stream, uint32_t pc, uint16_t opcode) + +{ + switch(opcode & 0xF) + { + case 0x00: + util::stream_format(stream, "MOV.B @%s,%s", regname[Rm], regname[Rn]); + break; + case 0x01: + util::stream_format(stream, "MOV.W @%s,%s", regname[Rm], regname[Rn]); + break; + case 0x02: + util::stream_format(stream, "MOV.L @%s,%s", regname[Rm], regname[Rn]); + break; + case 0x03: + util::stream_format(stream, "MOV %s,%s", regname[Rm], regname[Rn]); + break; + case 0x04: + util::stream_format(stream, "MOV.B @%s+,%s", regname[Rm], regname[Rn]); + break; + case 0x05: + util::stream_format(stream, "MOV.W @%s+,%s", regname[Rm], regname[Rn]); + break; + case 0x06: + util::stream_format(stream, "MOV.L @%s+,%s", regname[Rm], regname[Rn]); + break; + case 0x07: + util::stream_format(stream, "NOT %s,%s", regname[Rm], regname[Rn]); + break; + case 0x08: + util::stream_format(stream, "SWAP.B %s,%s", regname[Rm], regname[Rn]); + break; + case 0x09: + util::stream_format(stream, "SWAP.W %s,%s", regname[Rm], regname[Rn]); + break; + case 0x0a: + util::stream_format(stream, "NEGC %s,%s", regname[Rm], regname[Rn]); + break; + case 0x0b: + util::stream_format(stream, "NEG %s,%s", regname[Rm], regname[Rn]); + break; + case 0x0c: + util::stream_format(stream, "EXTU.B %s,%s", regname[Rm], regname[Rn]); + break; + case 0x0d: + util::stream_format(stream, "EXTU.W %s,%s", regname[Rm], regname[Rn]); + break; + case 0x0e: + util::stream_format(stream, "EXTS.B %s,%s", regname[Rm], regname[Rn]); + break; + case 0x0f: + util::stream_format(stream, "EXTS.W %s,%s", regname[Rm], regname[Rn]); + break; + } + return 0; +} + +static uint32_t op0111(std::ostream &stream, uint32_t pc, uint16_t opcode) +{ + util::stream_format(stream, "ADD #$%02X,%s", opcode & 0xff, regname[Rn]); + return 0; +} + +static uint32_t op1000(std::ostream &stream, uint32_t pc, uint16_t opcode) +{ + switch((opcode >> 8) & 15) + { + case 0: + util::stream_format(stream, "MOV.B R0,@($%02X,%s)", (opcode & 15), regname[Rm]); + break; + case 1: + util::stream_format(stream, "MOV.W R0,@($%02X,%s)", (opcode & 15) * 2, regname[Rm]); + break; + case 4: + util::stream_format(stream, "MOV.B @($%02X,%s),R0", (opcode & 15), regname[Rm]); + break; + case 5: + util::stream_format(stream, "MOV.W @($%02X,%s),R0", (opcode & 15) * 2, regname[Rm]); + break; + case 8: + util::stream_format(stream, "CMP/EQ #$%02X,R0", (opcode & 0xff)); + break; + case 9: + util::stream_format(stream, "BT $%08X", pc + SIGNX8(opcode & 0xff) * 2 + 2); + break; + case 11: + util::stream_format(stream, "BF $%08X", pc + SIGNX8(opcode & 0xff) * 2 + 2); + break; + case 13: + util::stream_format(stream, "BTS $%08X", pc + SIGNX8(opcode & 0xff) * 2 + 2); + break; + case 15: + util::stream_format(stream, "BFS $%08X", pc + SIGNX8(opcode & 0xff) * 2 + 2); + break; + default : + util::stream_format(stream, "invalid $%04X", opcode); + } + return 0; +} + +static uint32_t op1001(std::ostream &stream, uint32_t pc, uint16_t opcode) +{ +uint32_t ea=(pc+((opcode & 0xff) * 2)+2); + + util::stream_format(stream, "MOV.W @($%04X,PC),%s [%08X]", (opcode & 0xff) * 2, regname[Rn], ea); + return 0; +} + +static uint32_t op1010(std::ostream &stream, uint32_t pc, uint16_t opcode) +{ + util::stream_format(stream, "BRA $%08X", SIGNX12(opcode & 0xfff) * 2 + pc + 2); + return 0; +} + +static uint32_t op1011(std::ostream &stream, uint32_t pc, uint16_t opcode) +{ + util::stream_format(stream, "BSR $%08X", SIGNX12(opcode & 0xfff) * 2 + pc + 2); + return DASMFLAG_STEP_OVER | DASMFLAG_STEP_OVER_EXTRA(1); +} + +static uint32_t op1100(std::ostream &stream, uint32_t pc, uint16_t opcode) +{ + uint32_t flags = 0; + switch((opcode >> 8) & 15) + { + case 0: + util::stream_format(stream, "MOV.B R0,@($%02X,GBR)", opcode & 0xff); + break; + case 1: + util::stream_format(stream, "MOV.W R0,@($%04X,GBR)", (opcode & 0xff) * 2); + break; + case 2: + util::stream_format(stream, "MOV.L R0,@($%04X,GBR)", (opcode & 0xff) * 4); + break; + case 3: + util::stream_format(stream, "TRAPA #$%02X", opcode & 0xff); + flags = DASMFLAG_STEP_OVER; + break; + case 4: + util::stream_format(stream, "MOV.B @($%02X,GBR),R0", opcode & 0xff); + break; + case 5: + util::stream_format(stream, "MOV.W @($%04X,GBR),R0", (opcode & 0xff) * 2); + break; + case 6: + util::stream_format(stream, "MOV.L @($%04X,GBR),R0", (opcode & 0xff) * 4); + break; + case 7: + util::stream_format(stream, "MOVA @($%04X,PC),R0 [%08X]", (opcode & 0xff) * 4, ((pc + 2) & ~3) + (opcode & 0xff) * 4); + break; + case 8: + util::stream_format(stream, "TST #$%02X,R0", opcode & 0xff); + break; + case 9: + util::stream_format(stream, "AND #$%02X,R0", opcode & 0xff); + break; + case 10: + util::stream_format(stream, "XOR #$%02X,R0", opcode & 0xff); + break; + case 11: + util::stream_format(stream, "OR #$%02X,R0", opcode & 0xff); + break; + case 12: + util::stream_format(stream, "TST.B #$%02X,@(R0,GBR)", opcode & 0xff); + break; + case 13: + util::stream_format(stream, "AND.B #$%02X,@(R0,GBR)", opcode & 0xff); + break; + case 14: + util::stream_format(stream, "XOR.B #$%02X,@(R0,GBR)", opcode & 0xff); + break; + case 15: + util::stream_format(stream, "OR.B #$%02X,@(R0,GBR)", opcode & 0xff); + break; + } + return flags; +} + +static uint32_t op1101(std::ostream &stream, uint32_t pc, uint16_t opcode) +{ +uint32_t ea=((pc + 2) & ~3) + (opcode & 0xff) * 4; + + util::stream_format(stream, "MOV.L @($%04X,PC),%s [%08X]", (opcode & 0xff) * 4, regname[Rn], ea); + return 0; +} + +static uint32_t op1110(std::ostream &stream, uint32_t pc, uint16_t opcode) +{ + util::stream_format(stream, "MOV #$%02X,%s", (opcode & 0xff), regname[Rn]); + return 0; +} + +static uint32_t op1111(std::ostream &stream, uint32_t pc, uint16_t opcode) +{ + switch (opcode & 0xf) + { + case 0: + util::stream_format(stream, "FADD F%s, F%s", regname[Rm], regname[Rn]); + break; + case 1: + util::stream_format(stream, "FSUB F%s, F%s", regname[Rm], regname[Rn]); + break; + case 2: + util::stream_format(stream, "FMUL F%s, F%s", regname[Rm], regname[Rn]); + break; + case 3: + util::stream_format(stream, "FDIV F%s, F%s", regname[Rm], regname[Rn]); + break; + case 4: + util::stream_format(stream, "FCMP/EQ F%s, F%s", regname[Rm], regname[Rn]); + break; + case 5: + util::stream_format(stream, "FCMP/GT F%s, F%s", regname[Rm], regname[Rn]); + break; + case 6: + util::stream_format(stream, "FMOV.S @(R0,%s),F%s", regname[Rm], regname[Rn]); + break; + case 7: + util::stream_format(stream, "FMOV.S F%s, @(R0,%s)", regname[Rm], regname[Rn]); + break; + case 8: + util::stream_format(stream, "FMOV.S @%s, F%s", regname[Rm], regname[Rn]); + break; + case 9: + util::stream_format(stream, "FMOV.S @%s+, F%s", regname[Rm], regname[Rn]); + break; + case 10: + util::stream_format(stream, "FMOV.S F%s, @%s", regname[Rm], regname[Rn]); + break; + case 11: + util::stream_format(stream, "FMOV.S F%s, @-%s", regname[Rm], regname[Rn]); + break; + case 12: + util::stream_format(stream, "FMOV.S F%s, F%s", regname[Rm], regname[Rn]); + break; + case 13: + switch (opcode & 0xF0) + { + case 0x00: + util::stream_format(stream, "FSTS FPUL, F%s", regname[Rn]); + break; + case 0x10: + util::stream_format(stream, "FLDS F%s, FPUL", regname[Rn]); + break; + case 0x20: + util::stream_format(stream, "FLOAT FPUL, F%s", regname[Rn]); + break; + case 0x30: + util::stream_format(stream, "FTRC F%s, FPUL", regname[Rn]); + break; + case 0x40: + util::stream_format(stream, "FNEG F%s", regname[Rn]); + break; + case 0x50: + util::stream_format(stream, "FABS F%s", regname[Rn]); + break; + case 0x60: + util::stream_format(stream, "FSQRT F%s", regname[Rn]); + break; + case 0x70: + util::stream_format(stream, "FSRRA F%s", regname[Rn]); + break; + case 0x80: + util::stream_format(stream, "FLDI0 F%s", regname[Rn]); + break; + case 0x90: + util::stream_format(stream, "FLDI1 F%s", regname[Rn]); + break; + case 0xA0: + util::stream_format(stream, "FCNVSD FPUL, D%s", regname[Rn]); + break; + case 0xB0: + util::stream_format(stream, "FCNVDS D%s, FPUL", regname[Rn]); + break; + case 0xE0: + util::stream_format(stream, "FIPR FV%d, FV%d", (Rn & 3) << 2, Rn & 12); + break; + case 0xF0: + if (opcode & 0x100) { + if (opcode & 0x200) { + switch (opcode & 0xC00) + { + case 0x000: + stream << "FSCHG"; + break; + case 0x800: + stream << "FRCHG"; + break; + default: + util::stream_format(stream, "Funknown $%04X", opcode); + break; + } + } else { + util::stream_format(stream, "FTRV XMTRX, FV%d", Rn & 12); + } + } else { + util::stream_format(stream, "FSCA FPUL, F%s", regname[Rn & 14]); + } + break; + default: + util::stream_format(stream, "Funknown $%04X", opcode); + break; + } + break; + case 14: + util::stream_format(stream, "FMAC FR0, F%s,F%s", regname[Rm], regname[Rn]); + break; + default: + util::stream_format(stream, "Funknown $%04X", opcode); + break; + } + + return 0; +} + +unsigned DasmSH4(std::ostream &stream, unsigned pc, uint16_t opcode) +{ + uint32_t flags; + + pc += 2; + + switch ((opcode >> 12) & 15) + { + case 0: flags = op0000(stream, pc, opcode); break; + case 1: flags = op0001(stream, pc, opcode); break; + case 2: flags = op0010(stream, pc, opcode); break; + case 3: flags = op0011(stream, pc, opcode); break; + case 4: flags = op0100(stream, pc, opcode); break; + case 5: flags = op0101(stream, pc, opcode); break; + case 6: flags = op0110(stream, pc, opcode); break; + case 7: flags = op0111(stream, pc, opcode); break; + case 8: flags = op1000(stream, pc, opcode); break; + case 9: flags = op1001(stream, pc, opcode); break; + case 10: flags = op1010(stream, pc, opcode); break; + case 11: flags = op1011(stream, pc, opcode); break; + case 12: flags = op1100(stream, pc, opcode); break; + case 13: flags = op1101(stream, pc, opcode); break; + case 14: flags = op1110(stream, pc, opcode); break; + default: flags = op1111(stream, pc, opcode); break; + } + return 2 | flags | DASMFLAG_SUPPORTED; +} + +CPU_DISASSEMBLE(sh4) +{ + return DasmSH4(stream, pc, (oprom[1] << 8) | oprom[0]); +} + +CPU_DISASSEMBLE(sh4be) +{ + return DasmSH4(stream, pc, (oprom[0] << 8) | oprom[1]); +} diff --git a/src/devices/cpu/sh/sh4dmac.cpp b/src/devices/cpu/sh/sh4dmac.cpp new file mode 100644 index 00000000000..c06ffb034dd --- /dev/null +++ b/src/devices/cpu/sh/sh4dmac.cpp @@ -0,0 +1,666 @@ +// license:BSD-3-Clause +// copyright-holders:R. Belmont +/* SHA3/4 DMA Controller */ + +#include "emu.h" +#include "debugger.h" +#include "sh4.h" +#include "sh4comn.h" +#include "sh3comn.h" +#include "sh4dmac.h" + +static const int dmasize[8] = { 8, 1, 2, 4, 32, 0, 0, 0 }; + +static const int sh3_dmasize[4] = { 1, 2, 4, 16 }; + +TIMER_CALLBACK_MEMBER( sh34_base_device::sh4_dmac_callback ) +{ + int channel = param; + + LOG(("SH4 '%s': DMA %d complete\n", tag(), channel)); + m_dma_timer_active[channel] = 0; + switch (channel) + { + case 0: + m_SH4_DMATCR0 = 0; + m_SH4_CHCR0 |= CHCR_TE; + if (m_SH4_CHCR0 & CHCR_IE) + sh4_exception_request(SH4_INTC_DMTE0); + break; + case 1: + m_SH4_DMATCR1 = 0; + m_SH4_CHCR1 |= CHCR_TE; + if (m_SH4_CHCR1 & CHCR_IE) + sh4_exception_request(SH4_INTC_DMTE1); + break; + case 2: + m_SH4_DMATCR2 = 0; + m_SH4_CHCR2 |= CHCR_TE; + if (m_SH4_CHCR2 & CHCR_IE) + sh4_exception_request(SH4_INTC_DMTE2); + break; + case 3: + m_SH4_DMATCR3 = 0; + m_SH4_CHCR3 |= CHCR_TE; + if (m_SH4_CHCR3 & CHCR_IE) + sh4_exception_request(SH4_INTC_DMTE3); + break; + } +} + +int sh34_base_device::sh4_dma_transfer(int channel, int timermode, uint32_t chcr, uint32_t *sar, uint32_t *dar, uint32_t *dmatcr) +{ + int incs, incd, size; + uint32_t src, dst, count; + + incd = (chcr & CHCR_DM) >> 14; + incs = (chcr & CHCR_SM) >> 12; + + if (m_cpu_type == CPU_TYPE_SH4) + { + size = dmasize[(chcr & CHCR_TS) >> 4]; + } + else + { + size = sh3_dmasize[(chcr >> 3) & 3]; + } + + if(incd == 3 || incs == 3) + { + logerror("SH4: DMA: bad increment values (%d, %d, %d, %04x)\n", incd, incs, size, chcr); + return 0; + } + src = *sar; + dst = *dar; + count = *dmatcr; + if (!count) + count = 0x1000000; + + LOG(("SH4: DMA %d start %x, %x, %x, %04x, %d, %d, %d\n", channel, src, dst, count, chcr, incs, incd, size)); + + if (timermode == 1) // timer actvated after a time based on the number of words to transfer + { + m_dma_timer_active[channel] = 1; + m_dma_timer[channel]->adjust(cycles_to_attotime(2*count+1), channel); + } + else if (timermode == 2) // timer activated immediately + { + m_dma_timer_active[channel] = 1; + m_dma_timer[channel]->adjust(attotime::zero, channel); + } + + src &= AM; + dst &= AM; + + switch(size) + { + case 1: // 8 bit + for(;count > 0; count --) + { + if(incs == 2) + src --; + if(incd == 2) + dst --; + m_program->write_byte(dst, m_program->read_byte(src)); + if(incs == 1) + src ++; + if(incd == 1) + dst ++; + } + break; + case 2: // 16 bit + src &= ~1; + dst &= ~1; + for(;count > 0; count --) + { + if(incs == 2) + src -= 2; + if(incd == 2) + dst -= 2; + m_program->write_word(dst, m_program->read_word(src)); + if(incs == 1) + src += 2; + if(incd == 1) + dst += 2; + } + break; + case 8: // 64 bit + src &= ~7; + dst &= ~7; + for(;count > 0; count --) + { + if(incs == 2) + src -= 8; + if(incd == 2) + dst -= 8; + m_program->write_qword(dst, m_program->read_qword(src)); + if(incs == 1) + src += 8; + if(incd == 1) + dst += 8; + + } + break; + case 4: // 32 bit + src &= ~3; + dst &= ~3; + for(;count > 0; count --) + { + if(incs == 2) + src -= 4; + if(incd == 2) + dst -= 4; + m_program->write_dword(dst, m_program->read_dword(src)); + if(incs == 1) + src += 4; + if(incd == 1) + dst += 4; + + } + break; + case 32: + src &= ~31; + dst &= ~31; + for(;count > 0; count --) + { + if(incs == 2) + src -= 32; + if(incd == 2) + dst -= 32; + m_program->write_qword(dst, m_program->read_qword(src)); + m_program->write_qword(dst+8, m_program->read_qword(src+8)); + m_program->write_qword(dst+16, m_program->read_qword(src+16)); + m_program->write_qword(dst+24, m_program->read_qword(src+24)); + if(incs == 1) + src += 32; + if(incd == 1) + dst += 32; + } + break; + } + *sar = (*sar & ~AM) | src; + *dar = (*dar & ~AM) | dst; + *dmatcr = count; + return 1; +} + +int sh34_base_device::sh4_dma_transfer_device(int channel, uint32_t chcr, uint32_t *sar, uint32_t *dar, uint32_t *dmatcr) +{ + int incs, incd, size, mod; + uint32_t src, dst, count; + + incd = (chcr & CHCR_DM) >> 14; + incs = (chcr & CHCR_SM) >> 12; + + + if (m_cpu_type == CPU_TYPE_SH4) + { + size = dmasize[(chcr & CHCR_TS) >> 4]; + } + else + { + size = sh3_dmasize[(chcr >> 3) & 3]; + } + + mod = ((chcr & CHCR_RS) >> 8); + if (incd == 3 || incs == 3) + { + logerror("SH4: DMA: bad increment values (%d, %d, %d, %04x)\n", incd, incs, size, chcr); + return 0; + } + src = *sar; + dst = *dar; + count = *dmatcr; + if (!count) + count = 0x1000000; + + LOG(("SH4: DMA %d start device<->memory %x, %x, %x, %04x, %d, %d, %d\n", channel, src, dst, count, chcr, incs, incd, size)); + + m_dma_timer_active[channel] = 1; + + src &= AM; + dst &= AM; + + // remember parameters + m_dma_source[channel]=src; + m_dma_destination[channel]=dst; + m_dma_count[channel]=count; + m_dma_wordsize[channel]=size; + m_dma_source_increment[channel]=incs; + m_dma_destination_increment[channel]=incd; + m_dma_mode[channel]=mod; + + // inform device its ready to transfer + m_io->write_dword(SH4_IOPORT_DMA, channel | (mod << 16)); + return 1; +} + +void sh34_base_device::sh4_dmac_check(int channel) +{ + uint32_t dmatcr, chcr, sar, dar; + + switch (channel) + { + case 0: + sar = m_SH4_SAR0; + dar = m_SH4_DAR0; + chcr = m_SH4_CHCR0; + dmatcr = m_SH4_DMATCR0; + break; + case 1: + sar = m_SH4_SAR1; + dar = m_SH4_DAR1; + chcr = m_SH4_CHCR1; + dmatcr = m_SH4_DMATCR1; + break; + case 2: + sar = m_SH4_SAR2; + dar = m_SH4_DAR2; + chcr = m_SH4_CHCR2; + dmatcr = m_SH4_DMATCR2; + break; + case 3: + sar = m_SH4_SAR3; + dar = m_SH4_DAR3; + chcr = m_SH4_CHCR3; + dmatcr = m_SH4_DMATCR3; + break; + default: + return; + } + if (chcr & m_SH4_DMAOR & DMAOR_DME) + { + if ((((chcr & CHCR_RS) >> 8) < 2) || (((chcr & CHCR_RS) >> 8) > 6)) + return; + if (!m_dma_timer_active[channel] && !(chcr & CHCR_TE) && !(m_SH4_DMAOR & (DMAOR_AE | DMAOR_NMIF))) + { + if (((chcr & CHCR_RS) >> 8) > 3) + sh4_dma_transfer(channel, 1, chcr, &sar, &dar, &dmatcr); + else if ((m_SH4_DMAOR & DMAOR_DDT) == 0) + sh4_dma_transfer_device(channel, chcr, &sar, &dar, &dmatcr); // tell device we are ready to transfer + } + } + else + { + if (m_dma_timer_active[channel]) + { + logerror("SH4: DMA %d cancelled in-flight but all data transferred", channel); + m_dma_timer[channel]->adjust(attotime::never, channel); + m_dma_timer_active[channel] = 0; + } + } +} + + +// called by drivers to transfer data in a cpu<->device dma. 'device' must be a SH4 cpu +int sh34_base_device::sh4_dma_data(struct sh4_device_dma *s) +{ + uint32_t pos, len, siz; + int channel = s->channel; + void *data = s->buffer; + + if (!m_dma_timer_active[channel]) + return 0; + + if (m_dma_mode[channel] == 2) + { + // device receives data + len = m_dma_count[channel]; + if (s->length < len) + len = s->length; + siz = m_dma_wordsize[channel]; + for (pos = 0;pos < len;pos++) { + switch (siz) + { + case 8: + if (m_dma_source_increment[channel] == 2) + m_dma_source[channel] -= 8; + *(uint64_t *)data = m_program->read_qword(m_dma_source[channel] & ~7); + if (m_dma_source_increment[channel] == 1) + m_dma_source[channel] += 8; + break; + case 1: + if (m_dma_source_increment[channel] == 2) + m_dma_source[channel]--; + *(uint8_t *)data = m_program->read_byte(m_dma_source[channel]); + if (m_dma_source_increment[channel] == 1) + m_dma_source[channel]++; + break; + case 2: + if (m_dma_source_increment[channel] == 2) + m_dma_source[channel] -= 2; + *(uint16_t *)data = m_program->read_word(m_dma_source[channel] & ~1); + if (m_dma_source_increment[channel] == 1) + m_dma_source[channel] += 2; + break; + case 4: + if (m_dma_source_increment[channel] == 2) + m_dma_source[channel] -= 4; + *(uint32_t *)data = m_program->read_dword(m_dma_source[channel] & ~3); + if (m_dma_source_increment[channel] == 1) + m_dma_source[channel] += 4; + break; + case 32: + if (m_dma_source_increment[channel] == 2) + m_dma_source[channel] -= 32; + *(uint64_t *)data = m_program->read_qword(m_dma_source[channel] & ~31); + *((uint64_t *)data+1) = m_program->read_qword((m_dma_source[channel] & ~31)+8); + *((uint64_t *)data+2) = m_program->read_qword((m_dma_source[channel] & ~31)+16); + *((uint64_t *)data+3) = m_program->read_qword((m_dma_source[channel] & ~31)+24); + if (m_dma_source_increment[channel] == 1) + m_dma_source[channel] += 32; + break; + } + m_dma_count[channel]--; + } + if (m_dma_count[channel] == 0) // all data transferred ? + { + m_dma_timer[channel]->adjust(attotime::zero, channel); + return 2; + } + return 1; + } + else if (m_dma_mode[channel] == 3) + { + // device sends data + len = m_dma_count[channel]; + if (s->length < len) + len = s->length; + siz = m_dma_wordsize[channel]; + for (pos = 0;pos < len;pos++) { + switch (siz) + { + case 8: + if (m_dma_destination_increment[channel] == 2) + m_dma_destination[channel]-=8; + m_program->write_qword(m_dma_destination[channel] & ~7, *(uint64_t *)data); + if (m_dma_destination_increment[channel] == 1) + m_dma_destination[channel]+=8; + break; + case 1: + if (m_dma_destination_increment[channel] == 2) + m_dma_destination[channel]--; + m_program->write_byte(m_dma_destination[channel], *(uint8_t *)data); + if (m_dma_destination_increment[channel] == 1) + m_dma_destination[channel]++; + break; + case 2: + if (m_dma_destination_increment[channel] == 2) + m_dma_destination[channel]-=2; + m_program->write_word(m_dma_destination[channel] & ~1, *(uint16_t *)data); + if (m_dma_destination_increment[channel] == 1) + m_dma_destination[channel]+=2; + break; + case 4: + if (m_dma_destination_increment[channel] == 2) + m_dma_destination[channel]-=4; + m_program->write_dword(m_dma_destination[channel] & ~3, *(uint32_t *)data); + if (m_dma_destination_increment[channel] == 1) + m_dma_destination[channel]+=4; + break; + case 32: + if (m_dma_destination_increment[channel] == 2) + m_dma_destination[channel]-=32; + m_program->write_qword(m_dma_destination[channel] & ~31, *(uint64_t *)data); + m_program->write_qword((m_dma_destination[channel] & ~31)+8, *((uint64_t *)data+1)); + m_program->write_qword((m_dma_destination[channel] & ~31)+16, *((uint64_t *)data+2)); + m_program->write_qword((m_dma_destination[channel] & ~31)+24, *((uint64_t *)data+3)); + if (m_dma_destination_increment[channel] == 1) + m_dma_destination[channel]+=32; + break; + } + m_dma_count[channel]--; + } + + if (m_dma_count[channel] == 0) // all data transferred ? + { + m_dma_timer[channel]->adjust(attotime::zero, channel); + return 2; + } + return 1; + } + else + return 0; +} + +// called by drivers to transfer data in a DDT dma. +void sh34_base_device::sh4_dma_ddt(struct sh4_ddt_dma *s) +{ + uint32_t chcr; + uint32_t *p32bits; + uint64_t *p32bytes; + uint32_t pos,len,siz; + + if (m_cpu_type != CPU_TYPE_SH4) + fatalerror("sh4_dma_ddt uses m_m[] with SH3\n"); + + if (m_dma_timer_active[s->channel]) + return; + if (s->mode >= 0) { + switch (s->channel) + { + case 0: + if (s->mode & 1) + s->source = m_SH4_SAR0; + if (s->mode & 2) + m_SH4_SAR0 = s->source; + if (s->mode & 4) + s->destination = m_SH4_DAR0; + if (s->mode & 8) + m_SH4_DAR0 = s->destination; + break; + case 1: + if (s->mode & 1) + s->source = m_SH4_SAR1; + if (s->mode & 2) + m_SH4_SAR1 = s->source; + if (s->mode & 4) + s->destination = m_SH4_DAR1; + if (s->mode & 8) + m_SH4_DAR1 = s->destination; + break; + case 2: + if (s->mode & 1) + s->source = m_SH4_SAR2; + if (s->mode & 2) + m_SH4_SAR2 = s->source; + if (s->mode & 4) + s->destination = m_SH4_DAR2; + if (s->mode & 8) + m_SH4_DAR2 = s->destination; + break; + case 3: + default: + if (s->mode & 1) + s->source = m_SH4_SAR3; + if (s->mode & 2) + m_SH4_SAR3 = s->source; + if (s->mode & 4) + s->destination = m_SH4_DAR3; + if (s->mode & 8) + m_SH4_DAR3 = s->destination; + break; + } + switch (s->channel) + { + case 0: + chcr = m_SH4_CHCR0; + len = m_SH4_DMATCR0; + break; + case 1: + chcr = m_SH4_CHCR1; + len = m_SH4_DMATCR1; + break; + case 2: + chcr = m_SH4_CHCR2; + len = m_SH4_DMATCR2; + break; + case 3: + default: + chcr = m_SH4_CHCR3; + len = m_SH4_DMATCR3; + break; + } + if ((s->direction) == 0) { + chcr = (chcr & 0xffff3fff) | ((s->mode & 0x30) << 10); + } else { + chcr = (chcr & 0xffffcfff) | ((s->mode & 0x30) << 8); + } + + + if (m_cpu_type == CPU_TYPE_SH4) + { + //siz = dmasize[(chcr & CHCR_TS) >> 4]; + siz = dmasize[(chcr >> 4) & 7]; + } + else + { + siz = sh3_dmasize[(chcr >> 3) & 3]; + } + + + if (siz && (s->size)) + if ((len * siz) != (s->length * s->size)) + return; + sh4_dma_transfer(s->channel, 0, chcr, &s->source, &s->destination, &len); + } else { + if (s->size == 4) { + if ((s->direction) == 0) { + len = s->length; + p32bits = (uint32_t *)(s->buffer); + for (pos = 0;pos < len;pos++) { + *p32bits = m_program->read_dword(s->source); + p32bits++; + s->source = s->source + 4; + } + } else { + len = s->length; + p32bits = (uint32_t *)(s->buffer); + for (pos = 0;pos < len;pos++) { + m_program->write_dword(s->destination, *p32bits); + p32bits++; + s->destination = s->destination + 4; + } + } + } + if (s->size == 32) { + if ((s->direction) == 0) { + len = s->length * 4; + p32bytes = (uint64_t *)(s->buffer); + for (pos = 0;pos < len;pos++) { + *p32bytes = m_program->read_qword(s->source); + p32bytes++; + s->destination = s->destination + 8; + } + } else { + len = s->length * 4; + p32bytes = (uint64_t *)(s->buffer); + for (pos = 0;pos < len;pos++) { + m_program->write_qword(s->destination, *p32bytes); + p32bytes++; + s->destination = s->destination + 8; + } + } + } + } +} + + + void sh34_base_device::sh4_handle_sar0_addr_w(uint32_t data, uint32_t mem_mask) +{ + COMBINE_DATA(&m_SH4_SAR0); +} + + void sh34_base_device::sh4_handle_sar1_addr_w(uint32_t data, uint32_t mem_mask) +{ + COMBINE_DATA(&m_SH4_SAR1); +} + + void sh34_base_device::sh4_handle_sar2_addr_w(uint32_t data, uint32_t mem_mask) +{ + COMBINE_DATA(&m_SH4_SAR2); +} + + void sh34_base_device::sh4_handle_sar3_addr_w(uint32_t data, uint32_t mem_mask) +{ + COMBINE_DATA(&m_SH4_SAR3); +} + + void sh34_base_device::sh4_handle_dar0_addr_w(uint32_t data, uint32_t mem_mask) +{ + COMBINE_DATA(&m_SH4_DAR0); +} + + void sh34_base_device::sh4_handle_dar1_addr_w(uint32_t data, uint32_t mem_mask) +{ + COMBINE_DATA(&m_SH4_DAR1); +} + + void sh34_base_device::sh4_handle_dar2_addr_w(uint32_t data, uint32_t mem_mask) +{ + COMBINE_DATA(&m_SH4_DAR2); +} + + void sh34_base_device::sh4_handle_dar3_addr_w(uint32_t data, uint32_t mem_mask) +{ + COMBINE_DATA(&m_SH4_DAR3); +} + + void sh34_base_device::sh4_handle_dmatcr0_addr_w(uint32_t data, uint32_t mem_mask) +{ + COMBINE_DATA(&m_SH4_DMATCR0); +} + + void sh34_base_device::sh4_handle_dmatcr1_addr_w(uint32_t data, uint32_t mem_mask) +{ + COMBINE_DATA(&m_SH4_DMATCR1); +} + + void sh34_base_device::sh4_handle_dmatcr2_addr_w(uint32_t data, uint32_t mem_mask) +{ + COMBINE_DATA(&m_SH4_DMATCR2); +} + + void sh34_base_device::sh4_handle_dmatcr3_addr_w(uint32_t data, uint32_t mem_mask) +{ + COMBINE_DATA(&m_SH4_DMATCR3); +} + + void sh34_base_device::sh4_handle_chcr0_addr_w(uint32_t data, uint32_t mem_mask) +{ + COMBINE_DATA(&m_SH4_CHCR0); + sh4_dmac_check(0); +} + + void sh34_base_device::sh4_handle_chcr1_addr_w(uint32_t data, uint32_t mem_mask) +{ + COMBINE_DATA(&m_SH4_CHCR1); + sh4_dmac_check(1); +} + + void sh34_base_device::sh4_handle_chcr2_addr_w(uint32_t data, uint32_t mem_mask) +{ + COMBINE_DATA(&m_SH4_CHCR2); + sh4_dmac_check(2); +} + + void sh34_base_device::sh4_handle_chcr3_addr_w(uint32_t data, uint32_t mem_mask) +{ + COMBINE_DATA(&m_SH4_CHCR3); + sh4_dmac_check(3); +} + + void sh34_base_device::sh4_handle_dmaor_addr_w(uint32_t data, uint32_t mem_mask) +{ + uint32_t old = m_SH4_DMAOR; + COMBINE_DATA(&m_SH4_DMAOR); + + if ((m_SH4_DMAOR & DMAOR_AE) && (~old & DMAOR_AE)) + m_SH4_DMAOR &= ~DMAOR_AE; + if ((m_SH4_DMAOR & DMAOR_NMIF) && (~old & DMAOR_NMIF)) + m_SH4_DMAOR &= ~DMAOR_NMIF; + sh4_dmac_check(0); + sh4_dmac_check(1); + sh4_dmac_check(2); + sh4_dmac_check(3); +} diff --git a/src/devices/cpu/sh/sh4dmac.h b/src/devices/cpu/sh/sh4dmac.h new file mode 100644 index 00000000000..b7918fac997 --- /dev/null +++ b/src/devices/cpu/sh/sh4dmac.h @@ -0,0 +1,63 @@ +// license:BSD-3-Clause +// copyright-holders:R. Belmont +/* SHA3/4 DMA Controller */ + +/* bit definitions */ +#define CHCR_SSA 0xe0000000 +#define CHCR_STC 0x10000000 +#define CHCR_DSA 0x0e000000 +#define CHCR_DTC 0x01000000 +#define CHCR_DS 0x00080000 +#define CHCR_RL 0x00040000 +#define CHCR_AM 0x00020000 +#define CHCR_AL 0x00010000 +#define CHCR_DM 0x0000c000 +#define CHCR_SM 0x00003000 +#define CHCR_RS 0x00000f00 +#define CHCR_TM 0x00000080 +#define CHCR_TS 0x00000070 +#define CHCR_IE 0x00000004 +#define CHCR_TE 0x00000002 +#define CHCR_DE 0x00000001 + +#define DMAOR_DDT 0x8000 +#define DMAOR_PR 0x0300 +#define DMAOR_COD 0x0010 +#define DMAOR_AE 0x0004 +#define DMAOR_NMIF 0x0002 +#define DMAOR_DME 0x0001 + +void sh4_handle_sar0_addr_w(uint32_t data, uint32_t mem_mask); +void sh4_handle_sar1_addr_w(uint32_t data, uint32_t mem_mask); +void sh4_handle_sar2_addr_w(uint32_t data, uint32_t mem_mask); +void sh4_handle_sar3_addr_w(uint32_t data, uint32_t mem_mask); +void sh4_handle_dar0_addr_w(uint32_t data, uint32_t mem_mask); +void sh4_handle_dar1_addr_w(uint32_t data, uint32_t mem_mask); +void sh4_handle_dar2_addr_w(uint32_t data, uint32_t mem_mask); +void sh4_handle_dar3_addr_w(uint32_t data, uint32_t mem_mask); +void sh4_handle_dmatcr0_addr_w(uint32_t data, uint32_t mem_mask); +void sh4_handle_dmatcr1_addr_w(uint32_t data, uint32_t mem_mask); +void sh4_handle_dmatcr2_addr_w(uint32_t data, uint32_t mem_mask); +void sh4_handle_dmatcr3_addr_w(uint32_t data, uint32_t mem_mask); +void sh4_handle_chcr0_addr_w(uint32_t data, uint32_t mem_mask); +void sh4_handle_chcr1_addr_w(uint32_t data, uint32_t mem_mask); +void sh4_handle_chcr2_addr_w(uint32_t data, uint32_t mem_mask); +void sh4_handle_chcr3_addr_w(uint32_t data, uint32_t mem_mask); +void sh4_handle_dmaor_addr_w(uint32_t data, uint32_t mem_mask); +uint32_t sh4_handle_sar0_addr_r(uint32_t mem_mask); +uint32_t sh4_handle_sar1_addr_r(uint32_t mem_mask); +uint32_t sh4_handle_sar2_addr_r(uint32_t mem_mask); +uint32_t sh4_handle_sar3_addr_r(uint32_t mem_mask); +uint32_t sh4_handle_dar0_addr_r(uint32_t mem_mask); +uint32_t sh4_handle_dar1_addr_r(uint32_t mem_mask); +uint32_t sh4_handle_dar2_addr_r(uint32_t mem_mask); +uint32_t sh4_handle_dar3_addr_r(uint32_t mem_mask); +uint32_t sh4_handle_dmatcr0_addr_r(uint32_t mem_mask); +uint32_t sh4_handle_dmatcr1_addr_r(uint32_t mem_mask); +uint32_t sh4_handle_dmatcr2_addr_r(uint32_t mem_mask); +uint32_t sh4_handle_dmatcr3_addr_r(uint32_t mem_mask); +uint32_t sh4_handle_chcr0_addr_r(uint32_t mem_mask); +uint32_t sh4_handle_chcr1_addr_r(uint32_t mem_mask); +uint32_t sh4_handle_chcr2_addr_r(uint32_t mem_mask); +uint32_t sh4_handle_chcr3_addr_r(uint32_t mem_mask); +uint32_t sh4_handle_dmaor_addr_r(uint32_t mem_mask); diff --git a/src/devices/cpu/sh/sh4regs.h b/src/devices/cpu/sh/sh4regs.h new file mode 100644 index 00000000000..384f062858e --- /dev/null +++ b/src/devices/cpu/sh/sh4regs.h @@ -0,0 +1,183 @@ +// license:BSD-3-Clause +// copyright-holders:R. Belmont +#pragma once + +#ifndef __SH4REGS_H__ +#define __SH4REGS_H__ + +/* 00000001111111100000000011111100 */ +#define PTEH 0x2000 /* FF000000 */ +#define PTEL 0x2001 /* FF000004 */ +#define TTB 0x2002 /* FF000008 */ +#define TEA 0x2003 /* FF00000C */ +#define MMUCR 0x2004 /* FF000010 */ +#define BASRA 0x2005 /* FF000014 */ +#define BASRB 0x2006 /* FF000018 */ +#define CCR 0x2007 /* FF00001C */ +#define TRA 0x2008 /* FF000020 */ +#define EXPEVT 0x2009 /* FF000024 */ +#define INTEVT 0x200A /* FF000028 */ +#define VERSION 0x200C /* FF000030 */ +#define PTEA 0x200D /* FF000034 */ +#define QACR0 0x200E /* FF000038 */ +#define QACR1 0x200F /* FF00003C */ +#define PRR 0x2011 /* FF000044 */ +#define BARA 0x2400 /* FF200000 */ +#define BAMRA 0x2401 /* FF200004 */ +#define BBRA 0x2402 /* FF200008 */ +#define BARB 0x2403 /* FF20000C */ +#define BAMRB 0x2404 /* FF200010 */ +#define BBRB 0x2405 /* FF200014 */ +#define BDRB 0x2406 /* FF200018 */ +#define BDMRB 0x2407 /* FF20001C */ +#define BRCR 0x2408 /* FF200020 */ +#define BCR1 0x3000 /* FF800000 */ +#define BCR2 0x3001 /* FF800004 */ +#define BCR3 0x3014 /* FF800050 */ +#define BCR4 0x17C /* FE0A00F0 */ +#define WCR1 0x3002 /* FF800008 */ +#define WCR2 0x3003 /* FF80000C */ +#define WCR3 0x3004 /* FF800010 */ +#define MCR 0x3005 /* FF800014 */ +#define PCR 0x3006 /* FF800018 */ +#define RTCSR 0x3007 /* FF80001C */ +#define RTCNT 0x3008 /* FF800020 */ +#define RTCOR 0x3009 /* FF800024 */ +#define RFCR 0x300A /* FF800028 */ +#define PCTRA 0x300B /* FF80002C */ +#define PDTRA 0x300C /* FF800030 */ +#define PCTRB 0x3010 /* FF800040 */ +#define PDTRB 0x3011 /* FF800044 */ +#define GPIOIC 0x3012 /* FF800048 */ +#define SDMR2 0x3200 /* FF900000 */ +#define SDMR3 0x3280 /* FF940000 */ +#define SH4_SAR0_ADDR 0x3400 /* FFA00000 */ +#define SH4_DAR0_ADDR 0x3401 /* FFA00004 */ +#define SH4_DMATCR0_ADDR 0x3402 /* FFA00008 */ +#define SH4_CHCR0_ADDR 0x3403 /* FFA0000C */ +#define SH4_SAR1_ADDR 0x3404 /* FFA00010 */ +#define SH4_DAR1_ADDR 0x3405 /* FFA00014 */ +#define SH4_DMATCR1_ADDR 0x3406 /* FFA00018 */ +#define SH4_CHCR1_ADDR 0x3407 /* FFA0001C */ +#define SH4_SAR2_ADDR 0x3408 /* FFA00020 */ +#define SH4_DAR2_ADDR 0x3409 /* FFA00024 */ +#define SH4_DMATCR2_ADDR 0x340A /* FFA00028 */ +#define SH4_CHCR2_ADDR 0x340B /* FFA0002C */ +#define SH4_SAR3_ADDR 0x340C /* FFA00030 */ +#define SH4_DAR3_ADDR 0x340D /* FFA00034 */ +#define SH4_DMATCR3_ADDR 0x340E /* FFA00038 */ +#define SH4_CHCR3_ADDR 0x340F /* FFA0003C */ +#define SH4_DMAOR_ADDR 0x3410 /* FFA00040 */ +#define SAR4 0x3414 /* FFA00050 */ +#define DAR4 0x3415 /* FFA00054 */ +#define DMATCR4 0x3416 /* FFA00058 */ +#define CHCR4 0x3417 /* FFA0005C */ +#define SAR5 0x3418 /* FFA00060 */ +#define DAR5 0x3419 /* FFA00064 */ +#define DMATCR5 0x341A /* FFA00068 */ +#define CHCR5 0x341B /* FFA0006C */ +#define SAR6 0x341C /* FFA00070 */ +#define DAR6 0x341D /* FFA00074 */ +#define DMATCR6 0x341E /* FFA00078 */ +#define CHCR6 0x341F /* FFA0007C */ +#define SAR7 0x3420 /* FFA00080 */ +#define DAR7 0x3421 /* FFA00084 */ +#define DMATCR7 0x3422 /* FFA00088 */ +#define CHCR7 0x3423 /* FFA0008C */ +#define FRQCR 0x3800 /* FFC00000 */ +#define STBCR 0x3801 /* FFC00004 */ +#define WTCNT 0x3802 /* FFC00008 */ +#define WTCSR 0x3803 /* FFC0000C */ +#define STBCR2 0x3804 /* FFC00010 */ +#define R64CNT 0x3900 /* FFC80000 */ +#define RSECCNT 0x3901 /* FFC80004 */ +#define RMINCNT 0x3902 /* FFC80008 */ +#define RHRCNT 0x3903 /* FFC8000C */ +#define RWKCNT 0x3904 /* FFC80010 */ +#define RDAYCNT 0x3905 /* FFC80014 */ +#define RMONCNT 0x3906 /* FFC80018 */ +#define RYRCNT 0x3907 /* FFC8001C */ +#define RSECAR 0x3908 /* FFC80020 */ +#define RMINAR 0x3909 /* FFC80024 */ +#define RHRAR 0x390A /* FFC80028 */ +#define RWKAR 0x390B /* FFC8002C */ +#define RDAYAR 0x390C /* FFC80030 */ +#define RMONAR 0x390D /* FFC80034 */ +#define RCR1 0x390E /* FFC80038 */ +#define RCR2 0x390F /* FFC8003C */ +#define RCR3 0x3914 /* FFC80050 */ +#define RYRAR 0x3915 /* FFC80054 */ +#define ICR 0x3A00 /* FFD00000 */ +#define IPRA 0x3A01 /* FFD00004 */ +#define IPRB 0x3A02 /* FFD00008 */ +#define IPRC 0x3A03 /* FFD0000C */ +#define IPRD 0x3A04 /* FFD00010 */ +#define INTPRI00 0x100 /* FE080000 */ +#define INTREQ00 0x108 /* FE080020 */ +#define INTMSK00 0x110 /* FE080040 */ +#define INTMSKCLR00 0x118 /* FE080060 */ +#define CLKSTP00 0x140 /* FE0A0000 */ +#define CLKSTPCLR00 0x142 /* FE0A0008 */ +#define TSTR2 0x201 /* FE100004 */ +#define TCOR3 0x202 /* FE100008 */ +#define TCNT3 0x203 /* FE10000C */ +#define TCR3 0x204 /* FE100010 */ +#define TCOR4 0x205 /* FE100014 */ +#define TCNT4 0x206 /* FE100018 */ +#define TCR4 0x207 /* FE10001C */ +#define SH4_TOCR_ADDR 0x3B00 /* FFD80000 */ +#define SH4_TSTR_ADDR 0x3B01 /* FFD80004 */ +#define SH4_TCOR0_ADDR 0x3B02 /* FFD80008 */ +#define SH4_TCNT0_ADDR 0x3B03 /* FFD8000C */ +#define SH4_TCR0_ADDR 0x3B04 /* FFD80010 */ +#define SH4_TCOR1_ADDR 0x3B05 /* FFD80014 */ +#define SH4_TCNT1_ADDR 0x3B06 /* FFD80018 */ +#define SH4_TCR1_ADDR 0x3B07 /* FFD8001C */ +#define SH4_TCOR2_ADDR 0x3B08 /* FFD80020 */ +#define SH4_TCNT2_ADDR 0x3B09 /* FFD80024 */ +#define SH4_TCR2_ADDR 0x3B0A /* FFD80028 */ +#define SH4_TCPR2_ADDR 0x3B0B /* FFD8002C */ +#define SCSMR1 0x3C00 /* FFE00000 */ +#define SCBRR1 0x3C01 /* FFE00004 */ +#define SCSCR1 0x3C02 /* FFE00008 */ +#define SCTDR1 0x3C03 /* FFE0000C */ +#define SCSSR1 0x3C04 /* FFE00010 */ +#define SCRDR1 0x3C05 /* FFE00014 */ +#define SCSCMR1 0x3C06 /* FFE00018 */ +#define SCSPTR1 0x3C07 /* FFE0001C */ +#define SCSMR2 0x3D00 /* FFE80000 */ +#define SCBRR2 0x3D01 /* FFE80004 */ +#define SCSCR2 0x3D02 /* FFE80008 */ +#define SCFTDR2 0x3D03 /* FFE8000C */ +#define SCFSR2 0x3D04 /* FFE80010 */ +#define SCFRDR2 0x3D05 /* FFE80014 */ +#define SCFCR2 0x3D06 /* FFE80018 */ +#define SCFDR2 0x3D07 /* FFE8001C */ +#define SCSPTR2 0x3D08 /* FFE80020 */ +#define SCLSR2 0x3D09 /* FFE80024 */ +#define SDIR 0x3E00 /* FFF00000 */ +#define SDDR 0x3E02 /* FFF00008 */ +#define SDINT 0x3E05 /* FFF00014 */ +#define SIZEREGS 15878 + + + +#define MMUCR_LRUI 0xfc000000 +#define MMUCR_URB 0x00fc0000 +#define MMUCR_URC 0x0000fc00 +#define MMUCR_SQMD 0x00000200 +#define MMUCR_SV 0x00000100 +#define MMUCR_TI 0x00000004 +#define MMUCR_AT 0x00000001 + +/* constants */ +#define PVR_SH7091 0x040205c1 +#define PVR_SH7750 0x04020500 // from TN-SH7-361B/E +#define PVR_SH7750S 0x04020600 +#define PVR_SH7750R 0x04050000 +#define PRR_SH7750R 0x00000100 +#define PVR_SH7751 0x04110000 +#define PVR_SH7751R 0x04050000 +#define PRR_SH7751R 0x00000110 + +#endif /* __SH4REGS_H__ */ diff --git a/src/devices/cpu/sh/sh4tmu.cpp b/src/devices/cpu/sh/sh4tmu.cpp new file mode 100644 index 00000000000..4735b8bba67 --- /dev/null +++ b/src/devices/cpu/sh/sh4tmu.cpp @@ -0,0 +1,324 @@ +// license:BSD-3-Clause +// copyright-holders:R. Belmont +/* SH3/4 Timer Unit */ + +#include "emu.h" +#include "debugger.h" +#include "sh4.h" +#include "sh4comn.h" +#include "sh3comn.h" +#include "sh4tmu.h" + +static const int tcnt_div[8] = { 4, 16, 64, 256, 1024, 1, 1, 1 }; + +/*------------------------------------------------- + sh4_scale_up_mame_time - multiply a attotime by + a (constant+1) where 0 <= constant < 2^32 +-------------------------------------------------*/ + +static inline attotime sh4_scale_up_mame_time(const attotime &_time1, uint32_t factor1) +{ + return _time1 * factor1 + _time1; +} + +static uint32_t compute_ticks_timer(emu_timer *timer, int hertz, int divisor) +{ + double ret; + + ret=((timer->remaining().as_double() * (double)hertz) / (double)divisor) - 1; + return (uint32_t)ret; +} + +void sh34_base_device::sh4_timer_recompute(int which) +{ + double ticks; + + uint32_t tcnt = 0; + uint32_t tcr = 0; + switch (which) + { + case 0: + tcr = m_SH4_TCR0; + tcnt = m_SH4_TCNT0; + break; + + case 1: + tcr = m_SH4_TCR1; + tcnt = m_SH4_TCNT1; + break; + + case 2: + tcr = m_SH4_TCR2; + tcnt = m_SH4_TCNT2; + break; + } + + ticks = tcnt; + m_timer[which]->adjust(sh4_scale_up_mame_time(attotime::from_hz(m_pm_clock) * tcnt_div[tcr & 7], ticks), which); +} + + +TIMER_CALLBACK_MEMBER( sh34_base_device::sh4_timer_callback ) +{ + int which = param; + + switch (which) + { + case 0: + m_SH4_TCNT0 = m_SH4_TCOR0; + break; + + case 1: + m_SH4_TCNT1 = m_SH4_TCOR1; + break; + + case 2: + m_SH4_TCNT2 = m_SH4_TCOR2; + break; + + } + + sh4_timer_recompute(which); + + switch (which) + { + case 0: + m_SH4_TCR0 |= 0x100; + break; + + case 1: + m_SH4_TCR1 |= 0x100; + break; + + case 2: + m_SH4_TCR2 |= 0x100; + break; + + } + + switch (which) + { + case 0: + if (m_SH4_TCR0 & 0x20) + { + sh4_exception_request(SH4_INTC_TUNI0); + // logerror("SH4_INTC_TUNI0 requested\n"); + } + break; + + case 1: + if (m_SH4_TCR1 & 0x20) + { + sh4_exception_request(SH4_INTC_TUNI1); + // logerror("SH4_INTC_TUNI1 requested\n"); + } + break; + + case 2: + if (m_SH4_TCR2 & 0x20) + { + sh4_exception_request(SH4_INTC_TUNI2); + // logerror("SH4_INTC_TUNI2 requested\n"); + } + break; + + } +} + + +uint32_t sh34_base_device::sh4_handle_tcnt0_addr_r(uint32_t mem_mask) +{ + if (m_SH4_TSTR & 1) + return compute_ticks_timer(m_timer[0], m_pm_clock, tcnt_div[m_SH4_TCR0 & 7]); + else + return m_SH4_TCNT0; +} + +uint32_t sh34_base_device::sh4_handle_tcnt1_addr_r(uint32_t mem_mask) +{ + if (m_SH4_TSTR & 2) + return compute_ticks_timer(m_timer[1], m_pm_clock, tcnt_div[m_SH4_TCR1 & 7]); + else + return m_SH4_TCNT1; +} + +uint32_t sh34_base_device::sh4_handle_tcnt2_addr_r(uint32_t mem_mask) +{ + if (m_SH4_TSTR & 4) + return compute_ticks_timer(m_timer[2], m_pm_clock, tcnt_div[m_SH4_TCR2 & 7]); + else + return m_SH4_TCNT2; +} + +uint32_t sh34_base_device::sh4_handle_tcor0_addr_r(uint32_t mem_mask) +{ + return m_SH4_TCOR0; +} + +uint32_t sh34_base_device::sh4_handle_tcor1_addr_r(uint32_t mem_mask) +{ + return m_SH4_TCOR1; +} + +uint32_t sh34_base_device::sh4_handle_tcor2_addr_r(uint32_t mem_mask) +{ + return m_SH4_TCOR2; +} + +uint32_t sh34_base_device::sh4_handle_tcr0_addr_r(uint32_t mem_mask) +{ + return m_SH4_TCR0; +} + +uint32_t sh34_base_device::sh4_handle_tcr1_addr_r(uint32_t mem_mask) +{ + return m_SH4_TCR1; +} + +uint32_t sh34_base_device::sh4_handle_tcr2_addr_r(uint32_t mem_mask) +{ + return m_SH4_TCR2; +} + +uint32_t sh34_base_device::sh4_handle_tstr_addr_r(uint32_t mem_mask) +{ + return m_SH4_TSTR; +} + +uint32_t sh34_base_device::sh4_handle_tocr_addr_r(uint32_t mem_mask) +{ + return m_SH4_TOCR; +} + +uint32_t sh34_base_device::sh4_handle_tcpr2_addr_r(uint32_t mem_mask) +{ + return m_SH4_TCPR2; +} + + +void sh34_base_device::sh4_handle_tstr_addr_w(uint32_t data, uint32_t mem_mask) +{ + uint32_t old2 = m_SH4_TSTR; + COMBINE_DATA(&m_SH4_TSTR); + + if (old2 & 1) + m_SH4_TCNT0 = compute_ticks_timer(m_timer[0], m_pm_clock, tcnt_div[m_SH4_TCR0 & 7]); + if ((m_SH4_TSTR & 1) == 0) { + m_timer[0]->adjust(attotime::never); + } else + sh4_timer_recompute(0); + + if (old2 & 2) + m_SH4_TCNT1 = compute_ticks_timer(m_timer[1], m_pm_clock, tcnt_div[m_SH4_TCR1 & 7]); + if ((m_SH4_TSTR & 2) == 0) { + m_timer[1]->adjust(attotime::never); + } else + sh4_timer_recompute(1); + + if (old2 & 4) + m_SH4_TCNT2 = compute_ticks_timer(m_timer[2], m_pm_clock, tcnt_div[m_SH4_TCR2 & 7]); + if ((m_SH4_TSTR & 4) == 0) { + m_timer[2]->adjust(attotime::never); + } else + sh4_timer_recompute(2); +} + +void sh34_base_device::sh4_handle_tcr0_addr_w(uint32_t data, uint32_t mem_mask) +{ + uint32_t old2 = m_SH4_TCR0; + COMBINE_DATA(&m_SH4_TCR0); + if (m_SH4_TSTR & 1) + { + m_SH4_TCNT0 = compute_ticks_timer(m_timer[0], m_pm_clock, tcnt_div[old2 & 7]); + sh4_timer_recompute(0); + } + if (!(m_SH4_TCR0 & 0x20) || !(m_SH4_TCR0 & 0x100)) + sh4_exception_unrequest(SH4_INTC_TUNI0); +} + +void sh34_base_device::sh4_handle_tcr1_addr_w(uint32_t data, uint32_t mem_mask) +{ + uint32_t old2 = m_SH4_TCR1; + COMBINE_DATA(&m_SH4_TCR1); + if (m_SH4_TSTR & 2) + { + m_SH4_TCNT1 = compute_ticks_timer(m_timer[1], m_pm_clock, tcnt_div[old2 & 7]); + sh4_timer_recompute(1); + } + if (!(m_SH4_TCR1 & 0x20) || !(m_SH4_TCR1 & 0x100)) + sh4_exception_unrequest(SH4_INTC_TUNI1); +} + +void sh34_base_device::sh4_handle_tcr2_addr_w(uint32_t data, uint32_t mem_mask) +{ + uint32_t old2 = m_SH4_TCR2; + COMBINE_DATA(&m_SH4_TCR2); + if (m_SH4_TSTR & 4) + { + m_SH4_TCNT2 = compute_ticks_timer(m_timer[2], m_pm_clock, tcnt_div[old2 & 7]); + sh4_timer_recompute(2); + } + if (!(m_SH4_TCR2 & 0x20) || !(m_SH4_TCR2 & 0x100)) + sh4_exception_unrequest(SH4_INTC_TUNI2); +} + +void sh34_base_device::sh4_handle_tcor0_addr_w(uint32_t data, uint32_t mem_mask) +{ + COMBINE_DATA(&m_SH4_TCOR0); + if (m_SH4_TSTR & 1) + { + m_SH4_TCNT0 = compute_ticks_timer(m_timer[0], m_pm_clock, tcnt_div[m_SH4_TCR0 & 7]); + sh4_timer_recompute(0); + } +} + +void sh34_base_device::sh4_handle_tcor1_addr_w(uint32_t data, uint32_t mem_mask) +{ + COMBINE_DATA(&m_SH4_TCOR1); + if (m_SH4_TSTR & 2) + { + m_SH4_TCNT1 = compute_ticks_timer(m_timer[1], m_pm_clock, tcnt_div[m_SH4_TCR1 & 7]); + sh4_timer_recompute(1); + } +} + +void sh34_base_device::sh4_handle_tcor2_addr_w(uint32_t data, uint32_t mem_mask) +{ + COMBINE_DATA(&m_SH4_TCOR2); + if (m_SH4_TSTR & 4) + { + m_SH4_TCNT2 = compute_ticks_timer(m_timer[2], m_pm_clock, tcnt_div[m_SH4_TCR2 & 7]); + sh4_timer_recompute(2); + } +} + +void sh34_base_device::sh4_handle_tcnt0_addr_w(uint32_t data, uint32_t mem_mask) +{ + COMBINE_DATA(&m_SH4_TCNT0); + if (m_SH4_TSTR & 1) + sh4_timer_recompute(0); +} + +void sh34_base_device::sh4_handle_tcnt1_addr_w(uint32_t data, uint32_t mem_mask) +{ + COMBINE_DATA(&m_SH4_TCNT1); + if (m_SH4_TSTR & 2) + sh4_timer_recompute(1); +} + +void sh34_base_device::sh4_handle_tcnt2_addr_w(uint32_t data, uint32_t mem_mask) +{ + COMBINE_DATA(&m_SH4_TCNT2); + if (m_SH4_TSTR & 4) + sh4_timer_recompute(2); +} + +void sh34_base_device::sh4_handle_tocr_addr_w(uint32_t data, uint32_t mem_mask) +{ + COMBINE_DATA(&m_SH4_TOCR); +} + +void sh34_base_device::sh4_handle_tcpr2_addr_w(uint32_t data, uint32_t mem_mask) +{ + COMBINE_DATA(&m_SH4_TCPR2); +} diff --git a/src/devices/cpu/sh/sh4tmu.h b/src/devices/cpu/sh/sh4tmu.h new file mode 100644 index 00000000000..7bbad37a0c1 --- /dev/null +++ b/src/devices/cpu/sh/sh4tmu.h @@ -0,0 +1,3 @@ +// license:BSD-3-Clause +// copyright-holders:R. Belmont +/* SH3/4 Timer Unit */ diff --git a/src/devices/cpu/sh/sh7604_bus.cpp b/src/devices/cpu/sh/sh7604_bus.cpp new file mode 100644 index 00000000000..f4000a46300 --- /dev/null +++ b/src/devices/cpu/sh/sh7604_bus.cpp @@ -0,0 +1,162 @@ +// license:BSD-3-Clause +// copyright-holders:Angelo Salese +/*************************************************************************** + + SH7604 BUS Controller + + Lies at 0xffffffe0-0xffffffff + + + TODO: + - Host CPU setter (is_slave and clock are needed); + - timer clock emulation; + - fix fatalerrors; + - bus control stuff, someday; + +***************************************************************************/ + +#include "emu.h" +#include "sh7604_bus.h" + +//************************************************************************** +// GLOBAL VARIABLES +//************************************************************************** + +// device type definition +DEFINE_DEVICE_TYPE(SH7604_BUS, sh7604_bus_device, "sh7604bus", "SH7604 BUS Controller") + + +//************************************************************************** +// LIVE DEVICE +//************************************************************************** + +READ16_MEMBER(sh7604_bus_device::bus_control_1_r) +{ + return (m_bcr1 & 0x1ff7) | (m_is_slave == true ? 0x8000 : 0); +} + +WRITE16_MEMBER(sh7604_bus_device::bus_control_1_w) +{ + COMBINE_DATA(&m_bcr1); + if(m_bcr1 & 0x1000) // ENDIAN + throw emu_fatalerror("%s: enabled little endian for Area 2\n", tag()); + if(m_bcr1 & 0x0800) // PSHR + throw emu_fatalerror("%s: enabled partial space share mode\n", tag()); +} + +READ16_MEMBER(sh7604_bus_device::bus_control_2_r) { return m_bcr2 & 0x00fc; } +WRITE16_MEMBER(sh7604_bus_device::bus_control_2_w) +{ + COMBINE_DATA(&m_bcr2); + if(m_bcr2 != 0x00fc) + throw emu_fatalerror("%s: unexpected bus size register set %04x\n", tag(),data); +} + +READ16_MEMBER(sh7604_bus_device::wait_control_r) { return m_wcr; } +WRITE16_MEMBER(sh7604_bus_device::wait_control_w) { COMBINE_DATA(&m_wcr); } + +READ16_MEMBER(sh7604_bus_device::memory_control_r) { return m_mcr & 0xfefc; } +WRITE16_MEMBER(sh7604_bus_device::memory_control_w) { COMBINE_DATA(&m_mcr); } + +READ16_MEMBER(sh7604_bus_device::refresh_timer_status_r) +{ + return m_rtcsr & 0x00f8; +} + +WRITE16_MEMBER(sh7604_bus_device::refresh_timer_control_w) +{ + COMBINE_DATA(&m_rtcsr); + + if(m_rtcsr & 0x40) + throw emu_fatalerror("%s: enabled timer irq register with clock setting = %02x\n",tag(),data & 0x38); +} + +READ16_MEMBER(sh7604_bus_device::refresh_timer_counter_r) +{ + throw emu_fatalerror("%s: reading timer counter!\n",tag()); + return 0; +} + +WRITE16_MEMBER(sh7604_bus_device::refresh_timer_counter_w) +{ + throw emu_fatalerror("%s: writing timer counter %04x\n",tag(),data); + //COMBINE_DATA(&m_rtcnt); +} + +READ16_MEMBER(sh7604_bus_device::refresh_timer_constant_r) +{ + return m_rtcor & 0xff; +} + +WRITE16_MEMBER(sh7604_bus_device::refresh_timer_constant_w) +{ + COMBINE_DATA(&m_rtcor); +} + +DEVICE_ADDRESS_MAP_START( bus_regs, 16, sh7604_bus_device ) + AM_RANGE(0x00, 0x01) AM_READWRITE(bus_control_1_r, bus_control_1_w) + AM_RANGE(0x02, 0x03) AM_READWRITE(bus_control_2_r, bus_control_2_w) + AM_RANGE(0x04, 0x05) AM_READWRITE(wait_control_r, wait_control_w) + AM_RANGE(0x06, 0x07) AM_READWRITE(memory_control_r, memory_control_w) + AM_RANGE(0x08, 0x09) AM_READWRITE(refresh_timer_status_r, refresh_timer_control_w) + AM_RANGE(0x0a, 0x0b) AM_READWRITE(refresh_timer_counter_r, refresh_timer_counter_w) + AM_RANGE(0x0c, 0x0d) AM_READWRITE(refresh_timer_constant_r, refresh_timer_constant_w) +// AM_RANGE(0x0e, 0x0f) unmapped, mirror? +ADDRESS_MAP_END + +//------------------------------------------------- +// sh7604_bus_device - constructor +//------------------------------------------------- + +sh7604_bus_device::sh7604_bus_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : device_t(mconfig, SH7604_BUS, tag, owner, clock) +{ +} + +//------------------------------------------------- +// device_start - device-specific startup +//------------------------------------------------- + +void sh7604_bus_device::device_start() +{ +} + + +//------------------------------------------------- +// device_reset - device-specific reset +//------------------------------------------------- + +void sh7604_bus_device::device_reset() +{ + m_bcr1 = 0x03f0; + m_bcr2 = 0x00fc; + m_wcr = 0xaaff; + m_mcr = 0x0000; + m_rtcsr = 0x0000; + m_rtcor = 0x0000; +} + + +//************************************************************************** +// READ/WRITE HANDLERS +//************************************************************************** + +READ32_MEMBER( sh7604_bus_device::read ) +{ + // 16 bit access only, TODO + return space.read_word(offset) & 0xffff; +} + +WRITE32_MEMBER( sh7604_bus_device::write ) +{ + // TODO: 8 bit access is invalid + // if accessing bits 16-31, one must write ID = 0xa55a + if(ACCESSING_BITS_16_31) + { + // throw fatalerror if something trips it, presumably the write is going to be ignored + if((data & 0xffff0000) != 0xa55a0000) + throw emu_fatalerror("%s: making bus write with ID signature = %04x!\n", tag(),data >> 16); + } + + space.write_word(offset,data & 0xffff); +} diff --git a/src/devices/cpu/sh/sh7604_bus.h b/src/devices/cpu/sh/sh7604_bus.h new file mode 100644 index 00000000000..486ff93558f --- /dev/null +++ b/src/devices/cpu/sh/sh7604_bus.h @@ -0,0 +1,77 @@ +// license:BSD-3-Clause +// copyright-holders:Angelo Salese +/*************************************************************************** + + SH7604 BUS Controller + +***************************************************************************/ + +#ifndef MAME_CPU_SH2_SH7604_BUS_H +#define MAME_CPU_SH2_SH7604_BUS_H + +#pragma once + + + +//************************************************************************** +// INTERFACE CONFIGURATION MACROS +//************************************************************************** + +#define MCFG_SH7604_BUS_ADD(_tag,_freq) \ + MCFG_DEVICE_ADD(_tag, SH7604_BUS, _freq) + +//************************************************************************** +// TYPE DEFINITIONS +//************************************************************************** + +// ======================> sh7604_bus_device + +class sh7604_bus_device : public device_t +{ +public: + // construction/destruction + sh7604_bus_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + + // I/O operations + DECLARE_ADDRESS_MAP( bus_regs, 16 ); + + DECLARE_WRITE32_MEMBER( write ); + DECLARE_READ32_MEMBER( read ); + DECLARE_READ16_MEMBER( bus_control_1_r ); + DECLARE_WRITE16_MEMBER( bus_control_1_w ); + DECLARE_READ16_MEMBER( bus_control_2_r ); + DECLARE_WRITE16_MEMBER( bus_control_2_w ); + DECLARE_READ16_MEMBER( wait_control_r ); + DECLARE_WRITE16_MEMBER( wait_control_w ); + DECLARE_READ16_MEMBER( memory_control_r ); + DECLARE_WRITE16_MEMBER( memory_control_w ); + DECLARE_READ16_MEMBER( refresh_timer_status_r ); + DECLARE_WRITE16_MEMBER( refresh_timer_control_w ); + DECLARE_READ16_MEMBER( refresh_timer_counter_r ); + DECLARE_WRITE16_MEMBER( refresh_timer_counter_w ); + DECLARE_READ16_MEMBER( refresh_timer_constant_r ); + DECLARE_WRITE16_MEMBER( refresh_timer_constant_w ); + +protected: + // device-level overrides + //virtual void device_validity_check(validity_checker &valid) const; + virtual void device_start() override; + virtual void device_reset() override; + +private: + bool m_is_slave; + const address_space_config m_space_config; + + uint16_t m_bcr1; + uint16_t m_bcr2; + uint16_t m_wcr; + uint16_t m_mcr; + uint16_t m_rtcsr; + uint16_t m_rtcor; +}; + + +// device type definition +DECLARE_DEVICE_TYPE(SH7604_BUS, sh7604_bus_device) + +#endif // MAME_CPU_SH2_SH7604_BUS_H diff --git a/src/devices/cpu/sh/sh7604_sci.cpp b/src/devices/cpu/sh/sh7604_sci.cpp new file mode 100644 index 00000000000..248e0112622 --- /dev/null +++ b/src/devices/cpu/sh/sh7604_sci.cpp @@ -0,0 +1,156 @@ +// license:BSD-3-Clause +// copyright-holders:Angelo Salese +/*************************************************************************** + + SH7604 SCI Controller + + Lies at 0xfffffe00-0xfffffe0f + + TODO: + - diserial; + - CPU callbacks for RX and TX; + +***************************************************************************/ + +#include "emu.h" +#include "sh7604_sci.h" + + + +//************************************************************************** +// GLOBAL VARIABLES +//************************************************************************** + +// device type definition +DEFINE_DEVICE_TYPE(SH7604_SCI, sh7604_sci_device, "sh7604sci", "SH7604 SCI Controller") + + +//************************************************************************** +// LIVE DEVICE +//************************************************************************** + +READ8_MEMBER(sh7604_sci_device::serial_mode_r) +{ + return m_smr; +} + +WRITE8_MEMBER(sh7604_sci_device::serial_mode_w) +{ + m_smr = data; + + logerror("%s: serial mode set:\n",tag()); + logerror("\tCommunication Mode: %s mode\n",data & 0x80 ? "clocked synchronous" : "asynchronous"); + logerror("\tCharacter Length: %s mode\n",data & 0x40 ? "7-bit" : "8-bit"); + logerror("\tParity Enable: %s\n",data & 0x20 ? "yes" : "no"); + logerror("\tParity Mode: %s\n",data & 0x10 ? "Odd" : "Even"); + logerror("\tStop bits: %s\n",data & 0x08 ? "2" : "1"); + logerror("\tMultiprocessor mode: %s\n",data & 0x04 ? "yes" : "no"); + logerror("\tClock select: clock/%d\n",4 << ((data & 0x03)*2)); +} + +READ8_MEMBER(sh7604_sci_device::serial_control_r) +{ + return m_scr; +} + +WRITE8_MEMBER(sh7604_sci_device::serial_control_w) +{ + m_scr = data; + + if(data & 0x30) + throw emu_fatalerror("%s: enabled serial control %02x\n", tag(),data); +} + +READ8_MEMBER(sh7604_sci_device::serial_status_r) +{ + return m_ssr; +} + +WRITE8_MEMBER(sh7604_sci_device::serial_ack_w) +{ + // TODO: verify this + m_ssr = (m_ssr & 0x06) | (m_ssr & data & 0xf9); +} + +READ8_MEMBER(sh7604_sci_device::bitrate_r ) +{ + return m_brr; +} + +WRITE8_MEMBER(sh7604_sci_device::bitrate_w ) +{ + m_brr = data; +} + +READ8_MEMBER(sh7604_sci_device::transmit_data_r) +{ + // ... + return 0; +} + +WRITE8_MEMBER(sh7604_sci_device::transmit_data_w) +{ + // ... +} + +READ8_MEMBER(sh7604_sci_device::receive_data_r) +{ + // ... + return 0; +} + +DEVICE_ADDRESS_MAP_START( sci_regs, 8, sh7604_sci_device ) + AM_RANGE(0x00, 0x00) AM_READWRITE(serial_mode_r, serial_mode_w) + AM_RANGE(0x01, 0x01) AM_READWRITE(bitrate_r, bitrate_w) + AM_RANGE(0x02, 0x02) AM_READWRITE(serial_control_r,serial_control_w) + AM_RANGE(0x03, 0x03) AM_READWRITE(transmit_data_r, transmit_data_w) + AM_RANGE(0x04, 0x04) AM_READWRITE(serial_status_r, serial_ack_w) + AM_RANGE(0x05, 0x05) AM_READ(receive_data_r) +ADDRESS_MAP_END + +//------------------------------------------------- +// sh7604_sci_device - constructor +//------------------------------------------------- + +sh7604_sci_device::sh7604_sci_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : device_t(mconfig, SH7604_SCI, tag, owner, clock) + +{ +} + + +//------------------------------------------------- +// device_start - device-specific startup +//------------------------------------------------- + +void sh7604_sci_device::device_start() +{ +} + + +//------------------------------------------------- +// device_reset - device-specific reset +//------------------------------------------------- + +void sh7604_sci_device::device_reset() +{ + m_smr = 0; + m_scr = 0; + m_ssr = STATUS_TDRE|STATUS_TEND; //0x84; + m_brr = 0xff; +} + + +//************************************************************************** +// READ/WRITE HANDLERS +//************************************************************************** + +READ8_MEMBER( sh7604_sci_device::read ) +{ + return space.read_byte(offset); +} + +WRITE8_MEMBER( sh7604_sci_device::write ) +{ + space.write_byte(offset,data); +} diff --git a/src/devices/cpu/sh/sh7604_sci.h b/src/devices/cpu/sh/sh7604_sci.h new file mode 100644 index 00000000000..d7a290f6946 --- /dev/null +++ b/src/devices/cpu/sh/sh7604_sci.h @@ -0,0 +1,83 @@ +// license:BSD-3-Clause +// copyright-holders:Angelo Salese +/*************************************************************************** + + SH7604 SCI Controller + +***************************************************************************/ + +#ifndef MAME_CPU_SH2_SH7604_SCI_H +#define MAME_CPU_SH2_SH7604_SCI_H + +#pragma once + + + +//************************************************************************** +// INTERFACE CONFIGURATION MACROS +//************************************************************************** + +#define MCFG_SH7604_SCI_ADD(_tag,_freq) \ + MCFG_DEVICE_ADD(_tag, SH7604_SCI, _freq) + +//************************************************************************** +// TYPE DEFINITIONS +//************************************************************************** + +// ======================> sh7604_sci_device + +class sh7604_sci_device : public device_t +{ +public: + // construction/destruction + sh7604_sci_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + + // I/O operations + DECLARE_ADDRESS_MAP( sci_regs, 8 ); + + DECLARE_WRITE8_MEMBER( write ); + DECLARE_READ8_MEMBER( read ); + + DECLARE_READ8_MEMBER( serial_mode_r ); + DECLARE_WRITE8_MEMBER( serial_mode_w ); + DECLARE_READ8_MEMBER( bitrate_r ); + DECLARE_WRITE8_MEMBER( bitrate_w ); + DECLARE_READ8_MEMBER( serial_control_r ); + DECLARE_WRITE8_MEMBER( serial_control_w ); + + DECLARE_READ8_MEMBER( transmit_data_r ); + DECLARE_WRITE8_MEMBER( transmit_data_w ); + DECLARE_READ8_MEMBER( serial_status_r ); + DECLARE_WRITE8_MEMBER( serial_ack_w ); + DECLARE_READ8_MEMBER( receive_data_r ); + +protected: + enum { + STATUS_MPBT = 1 << 0, + STATUS_MPB = 1 << 1, + STATUS_TEND = 1 << 2, + STATUS_PER = 1 << 3, + STATUS_FER = 1 << 4, + STATUS_ORER = 1 << 5, + STATUS_RDRF = 1 << 6, + STATUS_TDRE = 1 << 7 + }; + + // device-level overrides +// virtual void device_validity_check(validity_checker &valid) const; + virtual void device_start() override; + virtual void device_reset() override; + +private: + const address_space_config m_space_config; + uint8_t m_smr; + uint8_t m_scr; + uint8_t m_ssr; + uint8_t m_brr; +}; + + +// device type definition +DECLARE_DEVICE_TYPE(SH7604_SCI, sh7604_sci_device) + +#endif // MAME_CPU_SH2_SH7604_SCI_H diff --git a/src/devices/cpu/sh/sh7604_wdt.cpp b/src/devices/cpu/sh/sh7604_wdt.cpp new file mode 100644 index 00000000000..16b40f30768 --- /dev/null +++ b/src/devices/cpu/sh/sh7604_wdt.cpp @@ -0,0 +1,83 @@ +// license:BSD-3-Clause +// copyright-holders:Angelo Salese +/*************************************************************************** + + SH7604 Watchdog Timer Controller + + TODO: + - Host CPU setter (clock and callback for irq and reset lines); + - memory map (needs to verify if ID write is ok); + +***************************************************************************/ + +#include "emu.h" +#include "sh7604_wdt.h" + + + +//************************************************************************** +// GLOBAL VARIABLES +//************************************************************************** + +// device type definition +DEFINE_DEVICE_TYPE(SH7604_WDT, sh7604_wdt_device, "sh7604wdt", "SH7604 Watchdog Timer") + + +//************************************************************************** +// LIVE DEVICE +//************************************************************************** + +DEVICE_ADDRESS_MAP_START( wdt_regs, 8, sh7604_wdt_device ) +// AM_RANGE(0x00, 0x00) timer control/status +// AM_RANGE(0x01, 0x01) timer counter +// AM_RANGE(0x02, 0x02) write only, reset control register +// AM_RANGE(0x03, 0x03) read status register, write reset status register +ADDRESS_MAP_END + +//------------------------------------------------- +// sh7604_wdt_device - constructor +//------------------------------------------------- + +sh7604_wdt_device::sh7604_wdt_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : device_t(mconfig, SH7604_WDT, tag, owner, clock) +{ +} + + +//------------------------------------------------- +// device_start - device-specific startup +//------------------------------------------------- + +void sh7604_wdt_device::device_start() +{ +} + + +//------------------------------------------------- +// device_reset - device-specific reset +//------------------------------------------------- + +void sh7604_wdt_device::device_reset() +{ +} + + +//************************************************************************** +// READ/WRITE HANDLERS +//************************************************************************** + +READ8_MEMBER( sh7604_wdt_device::read ) +{ + return space.read_byte(offset); +} + +WRITE16_MEMBER( sh7604_wdt_device::write ) +{ + uint8_t id_param = data >> 8; + switch(id_param) + { + case 0xa5: space.write_byte(offset*2+0,data & 0xff); break; + case 0x5a: space.write_byte(offset*2+1,data & 0xff); break; + default: throw emu_fatalerror("%s: invalid id param write = %02x\n",tag(),id_param); + } +} diff --git a/src/devices/cpu/sh/sh7604_wdt.h b/src/devices/cpu/sh/sh7604_wdt.h new file mode 100644 index 00000000000..7e014745f19 --- /dev/null +++ b/src/devices/cpu/sh/sh7604_wdt.h @@ -0,0 +1,54 @@ +// license:BSD-3-Clause +// copyright-holders:Angelo Salese +/*************************************************************************** + + SH7604 Watchdog Timer Controller + +***************************************************************************/ + +#ifndef MAME_CPU_SH7604_WDT_H +#define MAME_CPU_SH7604_WDT_H + +#pragma once + + + +//************************************************************************** +// INTERFACE CONFIGURATION MACROS +//************************************************************************** + +#define MCFG_SH7604_WDT_ADD(_tag,_freq) \ + MCFG_DEVICE_ADD(_tag, SH7604_WDT, _freq) + +//************************************************************************** +// TYPE DEFINITIONS +//************************************************************************** + +// ======================> sh7604_wdt_device + +class sh7604_wdt_device : public device_t +{ +public: + // construction/destruction + sh7604_wdt_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + + // I/O operations + DECLARE_ADDRESS_MAP( wdt_regs, 8 ); + + DECLARE_WRITE16_MEMBER( write ); + DECLARE_READ8_MEMBER( read ); + +protected: + // device-level overrides +// virtual void device_validity_check(validity_checker &valid) const; + virtual void device_start() override; + virtual void device_reset() override; +private: + const address_space_config m_space_config; +}; + + +// device type definition +DECLARE_DEVICE_TYPE(SH7604_WDT, sh7604_wdt_device) + +#endif // MAME_CPU_SH7604_WDT_H diff --git a/src/devices/cpu/superh/sh2.cpp b/src/devices/cpu/superh/sh2.cpp deleted file mode 100644 index 9b1cf8dcbbf..00000000000 --- a/src/devices/cpu/superh/sh2.cpp +++ /dev/null @@ -1,2704 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Juergen Buchmueller -/***************************************************************************** - * - * sh2.c - * Portable Hitachi SH-2 (SH7600 family) emulator - * - * This work is based on C/C++ implementation of - * the SH-2 CPU core and was adapted to the MAME CPU core requirements. - * Thanks also go to Chuck Mason and Olivier Galibert - * for letting me peek into their SEMU code :-) - * - *****************************************************************************/ - -/***************************************************************************** - 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 "debugger.h" - -//#define VERBOSE 1 -#include "logmacro.h" - - -/*************************************************************************** - DEBUGGING -***************************************************************************/ - -#define DISABLE_FAST_REGISTERS (0) // set to 1 to turn off usage of register caching -#define SINGLE_INSTRUCTION_MODE (0) - - -/*************************************************************************** - CONSTANTS -***************************************************************************/ - -/* size of the execution code cache */ -#define CACHE_SIZE (32 * 1024 * 1024) - -/* compilation boundaries -- how far back/forward does the analysis extend? */ -#define COMPILE_BACKWARDS_BYTES 64 -#define COMPILE_FORWARDS_BYTES 256 -#define COMPILE_MAX_INSTRUCTIONS ((COMPILE_BACKWARDS_BYTES/2) + (COMPILE_FORWARDS_BYTES/2)) -#define COMPILE_MAX_SEQUENCE 64 - - -DEFINE_DEVICE_TYPE(SH1, sh1_device, "sh1", "SH-1") -DEFINE_DEVICE_TYPE(SH2, sh2_device, "sh2", "SH-2") -DEFINE_DEVICE_TYPE(SH2A, sh2a_device, "sh21", "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 --------------------------------------------------*/ - -static ADDRESS_MAP_START( sh7604_map, AS_PROGRAM, 32, sh2_device ) - AM_RANGE(0x40000000, 0xbfffffff) AM_READ(sh2_internal_a5) -/*! - @todo: cps3boot breaks with this enabled. Needs customization ... - */ -// AM_RANGE(0xc0000000, 0xc0000fff) AM_RAM // cache data array -// AM_RANGE(0xffffff88, 0xffffff8b) AM_READWRITE(dma_dtcr0_r,dma_dtcr0_w) - AM_RANGE(0xe0000000, 0xe00001ff) AM_MIRROR(0x1ffffe00) AM_READWRITE(sh7604_r, sh7604_w) -ADDRESS_MAP_END - -static ADDRESS_MAP_START( sh7021_map, AS_PROGRAM, 32, sh2a_device ) -// overrides - AM_RANGE(0x05ffff40, 0x05ffff43) AM_READWRITE(dma_sar0_r, dma_sar0_w) - AM_RANGE(0x05ffff44, 0x05ffff47) AM_READWRITE(dma_dar0_r, dma_dar0_w) - AM_RANGE(0x05ffff48, 0x05ffff4b) AM_READWRITE16(dmaor_r, dmaor_w,0xffff0000) - AM_RANGE(0x05ffff48, 0x05ffff4b) AM_READWRITE16(dma_tcr0_r, dma_tcr0_w,0x0000ffff) - AM_RANGE(0x05ffff4c, 0x05ffff4f) AM_READWRITE16(dma_chcr0_r, dma_chcr0_w, 0x0000ffff) -// fall-back - AM_RANGE(0x05fffe00, 0x05ffffff) AM_READWRITE16(sh7021_r,sh7021_w,0xffffffff) // SH-7032H internal i/o -// 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) -ADDRESS_MAP_END - -static ADDRESS_MAP_START( sh7032_map, AS_PROGRAM, 32, sh1_device ) -// fall-back - AM_RANGE(0x05fffe00, 0x05ffffff) AM_READWRITE16(sh7032_r,sh7032_w,0xffffffff) // SH-7032H internal i/o -ADDRESS_MAP_END - -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_NAME(sh7604_map), 32) -{ -} - - -void sh2_device::device_stop() -{ -} - - -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) - : cpu_device(mconfig, type, tag, owner, clock) - , 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_cpu_type(cpu_type) - , m_cache(CACHE_SIZE + sizeof(internal_sh2_state)) - , m_drcuml(nullptr) -// , m_drcuml(*this, m_cache, 0, 1, 32, 1) - , m_drcfe(nullptr) - , m_drcoptions(0) - , m_sh2_state(nullptr) - , m_entry(nullptr) - , m_read8(nullptr) - , m_write8(nullptr) - , m_read16(nullptr) - , m_write16(nullptr) - , m_read32(nullptr) - , m_write32(nullptr) - , m_interrupt(nullptr) - , m_nocode(nullptr) - , m_out_of_cycles(nullptr) - , m_debugger_temp(0) -{ - m_isdrc = allow_drc(); -} - -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_NAME(sh7021_map), 28) -{ -} - -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_NAME(sh7032_map), 28) -{ -} - -device_memory_interface::space_config_vector sh2_device::memory_space_config() const -{ - 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 { - std::make_pair(AS_PROGRAM, &m_program_config) - }; -} - -offs_t sh2_device::disasm_disassemble(std::ostream &stream, offs_t pc, const uint8_t *oprom, const uint8_t *opram, uint32_t options) -{ - extern CPU_DISASSEMBLE( sh2 ); - return CPU_DISASSEMBLE_NAME( sh2 )(this, stream, pc, oprom, opram, options); -} - - -/* speed up delay loops, bail out of tight loops */ -#define BUSY_LOOP_HACKS 1 - -uint8_t sh2_device::RB(offs_t A) -{ - if((A & 0xf0000000) == 0 || (A & 0xf0000000) == 0x20000000) - return m_program->read_byte(A & AM); - - return m_program->read_byte(A); -} - -uint16_t sh2_device::RW(offs_t A) -{ - if((A & 0xf0000000) == 0 || (A & 0xf0000000) == 0x20000000) - return m_program->read_word(A & AM); - - return m_program->read_word(A); -} - -uint32_t sh2_device::RL(offs_t A) -{ - /* 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 & AM); - - return m_program->read_dword(A); -} - -void sh2_device::WB(offs_t A, uint8_t V) -{ - if((A & 0xf0000000) == 0 || (A & 0xf0000000) == 0x20000000) - { - m_program->write_byte(A & AM,V); - return; - } - - m_program->write_byte(A,V); -} - -void sh2_device::WW(offs_t A, uint16_t V) -{ - if((A & 0xf0000000) == 0 || (A & 0xf0000000) == 0x20000000) - { - m_program->write_word(A & AM,V); - return; - } - - m_program->write_word(A,V); -} - -void sh2_device::WL(offs_t A, uint32_t V) -{ - if((A & 0xf0000000) == 0 || (A & 0xf0000000) == 0x20000000) - { - m_program->write_dword(A & AM,V); - return; - } - - /* 0x20000000 no Cache */ - /* 0x00000000 read thru Cache if CE bit is 1 */ - m_program->write_dword(A,V); -} - -/* code cycles t-bit - * 0011 nnnn mmmm 1100 1 - - * ADD Rm,Rn - */ -void sh2_device::ADD(uint32_t m, uint32_t n) -{ - m_sh2_state->r[n] += m_sh2_state->r[m]; -} - -/* code cycles t-bit - * 0111 nnnn iiii iiii 1 - - * ADD #imm,Rn - */ -void sh2_device::ADDI(uint32_t i, uint32_t n) -{ - m_sh2_state->r[n] += (int32_t)(int16_t)(int8_t)i; -} - -/* code cycles t-bit - * 0011 nnnn mmmm 1110 1 carry - * ADDC Rm,Rn - */ -void sh2_device::ADDC(uint32_t m, uint32_t n) -{ - uint32_t tmp0, tmp1; - - tmp1 = m_sh2_state->r[n] + m_sh2_state->r[m]; - tmp0 = m_sh2_state->r[n]; - m_sh2_state->r[n] = tmp1 + (m_sh2_state->sr & T); - if (tmp0 > tmp1) - m_sh2_state->sr |= T; - else - m_sh2_state->sr &= ~T; - if (tmp1 > m_sh2_state->r[n]) - m_sh2_state->sr |= T; -} - -/* code cycles t-bit - * 0011 nnnn mmmm 1111 1 overflow - * ADDV Rm,Rn - */ -void sh2_device::ADDV(uint32_t m, uint32_t n) -{ - int32_t dest, src, ans; - - if ((int32_t) m_sh2_state->r[n] >= 0) - dest = 0; - else - dest = 1; - if ((int32_t) m_sh2_state->r[m] >= 0) - src = 0; - else - src = 1; - src += dest; - m_sh2_state->r[n] += m_sh2_state->r[m]; - if ((int32_t) m_sh2_state->r[n] >= 0) - ans = 0; - else - ans = 1; - ans += dest; - if (src == 0 || src == 2) - { - if (ans == 1) - m_sh2_state->sr |= T; - else - m_sh2_state->sr &= ~T; - } - else - m_sh2_state->sr &= ~T; -} - -/* code cycles t-bit - * 0010 nnnn mmmm 1001 1 - - * AND Rm,Rn - */ -void sh2_device::AND(uint32_t m, uint32_t n) -{ - m_sh2_state->r[n] &= m_sh2_state->r[m]; -} - - -/* code cycles t-bit - * 1100 1001 iiii iiii 1 - - * AND #imm,R0 - */ -void sh2_device::ANDI(uint32_t i) -{ - m_sh2_state->r[0] &= i; -} - -/* code cycles t-bit - * 1100 1101 iiii iiii 1 - - * AND.B #imm,@(R0,GBR) - */ -void sh2_device::ANDM(uint32_t i) -{ - uint32_t temp; - - m_sh2_state->ea = m_sh2_state->gbr + m_sh2_state->r[0]; - temp = i & RB( m_sh2_state->ea ); - WB( m_sh2_state->ea, temp ); - m_sh2_state->icount -= 2; -} - -/* code cycles t-bit - * 1000 1011 dddd dddd 3/1 - - * BF disp8 - */ -void sh2_device::BF(uint32_t d) -{ - if ((m_sh2_state->sr & T) == 0) - { - int32_t disp = ((int32_t)d << 24) >> 24; - m_sh2_state->pc = m_sh2_state->ea = m_sh2_state->pc + disp * 2 + 2; - m_sh2_state->icount -= 2; - } -} - -/* code cycles t-bit - * 1000 1111 dddd dddd 3/1 - - * BFS disp8 - */ -void sh2_device::BFS(uint32_t d) -{ - if ((m_sh2_state->sr & T) == 0) - { - int32_t disp = ((int32_t)d << 24) >> 24; - m_delay = m_sh2_state->ea = m_sh2_state->pc + disp * 2 + 2; - m_sh2_state->icount--; - } -} - -/* code cycles t-bit - * 1010 dddd dddd dddd 2 - - * BRA disp12 - */ -void sh2_device::BRA(uint32_t d) -{ - int32_t disp = ((int32_t)d << 20) >> 20; - -#if BUSY_LOOP_HACKS - if (disp == -2) - { - uint32_t next_opcode = RW(m_sh2_state->pc & AM); - /* BRA $ - * NOP - */ - if (next_opcode == 0x0009) - m_sh2_state->icount %= 3; /* cycles for BRA $ and NOP taken (3) */ - } -#endif - m_delay = m_sh2_state->ea = m_sh2_state->pc + disp * 2 + 2; - m_sh2_state->icount--; -} - -/* code cycles t-bit - * 0000 mmmm 0010 0011 2 - - * BRAF Rm - */ -void sh2_device::BRAF(uint32_t m) -{ - m_delay = m_sh2_state->pc + m_sh2_state->r[m] + 2; - m_sh2_state->icount--; -} - -/* code cycles t-bit - * 1011 dddd dddd dddd 2 - - * BSR disp12 - */ -void sh2_device::BSR(uint32_t d) -{ - int32_t disp = ((int32_t)d << 20) >> 20; - - m_sh2_state->pr = m_sh2_state->pc + 2; - m_delay = m_sh2_state->ea = m_sh2_state->pc + disp * 2 + 2; - m_sh2_state->icount--; -} - -/* code cycles t-bit - * 0000 mmmm 0000 0011 2 - - * BSRF Rm - */ -void sh2_device::BSRF(uint32_t m) -{ - m_sh2_state->pr = m_sh2_state->pc + 2; - m_delay = m_sh2_state->pc + m_sh2_state->r[m] + 2; - m_sh2_state->icount--; -} - -/* code cycles t-bit - * 1000 1001 dddd dddd 3/1 - - * BT disp8 - */ -void sh2_device::BT(uint32_t d) -{ - if ((m_sh2_state->sr & T) != 0) - { - int32_t disp = ((int32_t)d << 24) >> 24; - m_sh2_state->pc = m_sh2_state->ea = m_sh2_state->pc + disp * 2 + 2; - m_sh2_state->icount -= 2; - } -} - -/* code cycles t-bit - * 1000 1101 dddd dddd 2/1 - - * BTS disp8 - */ -void sh2_device::BTS(uint32_t d) -{ - if ((m_sh2_state->sr & T) != 0) - { - int32_t disp = ((int32_t)d << 24) >> 24; - m_delay = m_sh2_state->ea = m_sh2_state->pc + disp * 2 + 2; - m_sh2_state->icount--; - } -} - -/* code cycles t-bit - * 0000 0000 0010 1000 1 - - * CLRMAC - */ -void sh2_device::CLRMAC() -{ - m_sh2_state->mach = 0; - m_sh2_state->macl = 0; -} - -/* code cycles t-bit - * 0000 0000 0000 1000 1 - - * CLRT - */ -void sh2_device::CLRT() -{ - m_sh2_state->sr &= ~T; -} - -/* code cycles t-bit - * 0011 nnnn mmmm 0000 1 comparison result - * CMP_EQ Rm,Rn - */ -void sh2_device::CMPEQ(uint32_t m, uint32_t n) -{ - if (m_sh2_state->r[n] == m_sh2_state->r[m]) - m_sh2_state->sr |= T; - else - m_sh2_state->sr &= ~T; -} - -/* code cycles t-bit - * 0011 nnnn mmmm 0011 1 comparison result - * CMP_GE Rm,Rn - */ -void sh2_device::CMPGE(uint32_t m, uint32_t n) -{ - if ((int32_t) m_sh2_state->r[n] >= (int32_t) m_sh2_state->r[m]) - m_sh2_state->sr |= T; - else - m_sh2_state->sr &= ~T; -} - -/* code cycles t-bit - * 0011 nnnn mmmm 0111 1 comparison result - * CMP_GT Rm,Rn - */ -void sh2_device::CMPGT(uint32_t m, uint32_t n) -{ - if ((int32_t) m_sh2_state->r[n] > (int32_t) m_sh2_state->r[m]) - m_sh2_state->sr |= T; - else - m_sh2_state->sr &= ~T; -} - -/* code cycles t-bit - * 0011 nnnn mmmm 0110 1 comparison result - * CMP_HI Rm,Rn - */ -void sh2_device::CMPHI(uint32_t m, uint32_t n) -{ - if ((uint32_t) m_sh2_state->r[n] > (uint32_t) m_sh2_state->r[m]) - m_sh2_state->sr |= T; - else - m_sh2_state->sr &= ~T; -} - -/* code cycles t-bit - * 0011 nnnn mmmm 0010 1 comparison result - * CMP_HS Rm,Rn - */ -void sh2_device::CMPHS(uint32_t m, uint32_t n) -{ - if ((uint32_t) m_sh2_state->r[n] >= (uint32_t) m_sh2_state->r[m]) - m_sh2_state->sr |= T; - else - m_sh2_state->sr &= ~T; -} - - -/* code cycles t-bit - * 0100 nnnn 0001 0101 1 comparison result - * CMP_PL Rn - */ -void sh2_device::CMPPL(uint32_t n) -{ - if ((int32_t) m_sh2_state->r[n] > 0) - m_sh2_state->sr |= T; - else - m_sh2_state->sr &= ~T; -} - -/* code cycles t-bit - * 0100 nnnn 0001 0001 1 comparison result - * CMP_PZ Rn - */ -void sh2_device::CMPPZ(uint32_t n) -{ - if ((int32_t) m_sh2_state->r[n] >= 0) - m_sh2_state->sr |= T; - else - m_sh2_state->sr &= ~T; -} - -/* code cycles t-bit - * 0010 nnnn mmmm 1100 1 comparison result - * CMP_STR Rm,Rn - */ -void sh2_device::CMPSTR(uint32_t m, uint32_t n) - { - uint32_t temp; - int32_t HH, HL, LH, LL; - temp = m_sh2_state->r[n] ^ m_sh2_state->r[m]; - HH = (temp >> 24) & 0xff; - HL = (temp >> 16) & 0xff; - LH = (temp >> 8) & 0xff; - LL = temp & 0xff; - if (HH && HL && LH && LL) - m_sh2_state->sr &= ~T; - else - m_sh2_state->sr |= T; - } - - -/* code cycles t-bit - * 1000 1000 iiii iiii 1 comparison result - * CMP/EQ #imm,R0 - */ -void sh2_device::CMPIM(uint32_t i) -{ - uint32_t imm = (uint32_t)(int32_t)(int16_t)(int8_t)i; - - if (m_sh2_state->r[0] == imm) - m_sh2_state->sr |= T; - else - m_sh2_state->sr &= ~T; -} - -/* code cycles t-bit - * 0010 nnnn mmmm 0111 1 calculation result - * DIV0S Rm,Rn - */ -void sh2_device::DIV0S(uint32_t m, uint32_t n) -{ - if ((m_sh2_state->r[n] & 0x80000000) == 0) - m_sh2_state->sr &= ~Q; - else - m_sh2_state->sr |= Q; - if ((m_sh2_state->r[m] & 0x80000000) == 0) - m_sh2_state->sr &= ~M; - else - m_sh2_state->sr |= M; - if ((m_sh2_state->r[m] ^ m_sh2_state->r[n]) & 0x80000000) - m_sh2_state->sr |= T; - else - m_sh2_state->sr &= ~T; -} - -/* code cycles t-bit - * 0000 0000 0001 1001 1 0 - * DIV0U - */ -void sh2_device::DIV0U() -{ - m_sh2_state->sr &= ~(M | Q | T); -} - -/* code cycles t-bit - * 0011 nnnn mmmm 0100 1 calculation result - * DIV1 Rm,Rn - */ -void sh2_device::DIV1(uint32_t m, uint32_t n) -{ - uint32_t tmp0; - uint32_t old_q; - - old_q = m_sh2_state->sr & Q; - if (0x80000000 & m_sh2_state->r[n]) - m_sh2_state->sr |= Q; - else - m_sh2_state->sr &= ~Q; - - m_sh2_state->r[n] = (m_sh2_state->r[n] << 1) | (m_sh2_state->sr & T); - - if (!old_q) - { - if (!(m_sh2_state->sr & M)) - { - tmp0 = m_sh2_state->r[n]; - m_sh2_state->r[n] -= m_sh2_state->r[m]; - if(!(m_sh2_state->sr & Q)) - if(m_sh2_state->r[n] > tmp0) - m_sh2_state->sr |= Q; - else - m_sh2_state->sr &= ~Q; - else - if(m_sh2_state->r[n] > tmp0) - m_sh2_state->sr &= ~Q; - else - m_sh2_state->sr |= Q; - } - else - { - tmp0 = m_sh2_state->r[n]; - m_sh2_state->r[n] += m_sh2_state->r[m]; - if(!(m_sh2_state->sr & Q)) - { - if(m_sh2_state->r[n] < tmp0) - m_sh2_state->sr &= ~Q; - else - m_sh2_state->sr |= Q; - } - else - { - if(m_sh2_state->r[n] < tmp0) - m_sh2_state->sr |= Q; - else - m_sh2_state->sr &= ~Q; - } - } - } - else - { - if (!(m_sh2_state->sr & M)) - { - tmp0 = m_sh2_state->r[n]; - m_sh2_state->r[n] += m_sh2_state->r[m]; - if(!(m_sh2_state->sr & Q)) - if(m_sh2_state->r[n] < tmp0) - m_sh2_state->sr |= Q; - else - m_sh2_state->sr &= ~Q; - else - if(m_sh2_state->r[n] < tmp0) - m_sh2_state->sr &= ~Q; - else - m_sh2_state->sr |= Q; - } - else - { - tmp0 = m_sh2_state->r[n]; - m_sh2_state->r[n] -= m_sh2_state->r[m]; - if(!(m_sh2_state->sr & Q)) - if(m_sh2_state->r[n] > tmp0) - m_sh2_state->sr &= ~Q; - else - m_sh2_state->sr |= Q; - else - if(m_sh2_state->r[n] > tmp0) - m_sh2_state->sr |= Q; - else - m_sh2_state->sr &= ~Q; - } - } - - tmp0 = (m_sh2_state->sr & (Q | M)); - if((!tmp0) || (tmp0 == 0x300)) /* if Q == M set T else clear T */ - m_sh2_state->sr |= T; - else - m_sh2_state->sr &= ~T; -} - -/* DMULS.L Rm,Rn */ -void sh2_device::DMULS(uint32_t m, uint32_t n) -{ - uint32_t RnL, RnH, RmL, RmH, Res0, Res1, Res2; - uint32_t temp0, temp1, temp2, temp3; - int32_t tempm, tempn, fnLmL; - - tempn = (int32_t) m_sh2_state->r[n]; - tempm = (int32_t) m_sh2_state->r[m]; - if (tempn < 0) - tempn = 0 - tempn; - if (tempm < 0) - tempm = 0 - tempm; - if ((int32_t) (m_sh2_state->r[n] ^ m_sh2_state->r[m]) < 0) - fnLmL = -1; - else - fnLmL = 0; - temp1 = (uint32_t) tempn; - temp2 = (uint32_t) tempm; - RnL = temp1 & 0x0000ffff; - RnH = (temp1 >> 16) & 0x0000ffff; - RmL = temp2 & 0x0000ffff; - RmH = (temp2 >> 16) & 0x0000ffff; - temp0 = RmL * RnL; - temp1 = RmH * RnL; - temp2 = RmL * RnH; - temp3 = RmH * RnH; - Res2 = 0; - Res1 = temp1 + temp2; - if (Res1 < temp1) - Res2 += 0x00010000; - temp1 = (Res1 << 16) & 0xffff0000; - Res0 = temp0 + temp1; - if (Res0 < temp0) - Res2++; - Res2 = Res2 + ((Res1 >> 16) & 0x0000ffff) + temp3; - if (fnLmL < 0) - { - Res2 = ~Res2; - if (Res0 == 0) - Res2++; - else - Res0 = (~Res0) + 1; - } - m_sh2_state->mach = Res2; - m_sh2_state->macl = Res0; - m_sh2_state->icount--; -} - -/* DMULU.L Rm,Rn */ -void sh2_device::DMULU(uint32_t m, uint32_t n) -{ - uint32_t RnL, RnH, RmL, RmH, Res0, Res1, Res2; - uint32_t temp0, temp1, temp2, temp3; - - RnL = m_sh2_state->r[n] & 0x0000ffff; - RnH = (m_sh2_state->r[n] >> 16) & 0x0000ffff; - RmL = m_sh2_state->r[m] & 0x0000ffff; - RmH = (m_sh2_state->r[m] >> 16) & 0x0000ffff; - temp0 = RmL * RnL; - temp1 = RmH * RnL; - temp2 = RmL * RnH; - temp3 = RmH * RnH; - Res2 = 0; - Res1 = temp1 + temp2; - if (Res1 < temp1) - Res2 += 0x00010000; - temp1 = (Res1 << 16) & 0xffff0000; - Res0 = temp0 + temp1; - if (Res0 < temp0) - Res2++; - Res2 = Res2 + ((Res1 >> 16) & 0x0000ffff) + temp3; - m_sh2_state->mach = Res2; - m_sh2_state->macl = Res0; - m_sh2_state->icount--; -} - -/* DT Rn */ -void sh2_device::DT(uint32_t n) -{ - m_sh2_state->r[n]--; - if (m_sh2_state->r[n] == 0) - m_sh2_state->sr |= T; - else - m_sh2_state->sr &= ~T; -#if BUSY_LOOP_HACKS - { - uint32_t next_opcode = RW(m_sh2_state->pc & AM); - /* DT Rn - * BF $-2 - */ - if (next_opcode == 0x8bfd) - { - while (m_sh2_state->r[n] > 1 && m_sh2_state->icount > 4) - { - m_sh2_state->r[n]--; - m_sh2_state->icount -= 4; /* cycles for DT (1) and BF taken (3) */ - } - } - } -#endif -} - -/* EXTS.B Rm,Rn */ -void sh2_device::EXTSB(uint32_t m, uint32_t n) -{ - m_sh2_state->r[n] = ((int32_t)m_sh2_state->r[m] << 24) >> 24; -} - -/* EXTS.W Rm,Rn */ -void sh2_device::EXTSW(uint32_t m, uint32_t n) -{ - m_sh2_state->r[n] = ((int32_t)m_sh2_state->r[m] << 16) >> 16; -} - -/* EXTU.B Rm,Rn */ -void sh2_device::EXTUB(uint32_t m, uint32_t n) -{ - m_sh2_state->r[n] = m_sh2_state->r[m] & 0x000000ff; -} - -/* EXTU.W Rm,Rn */ -void sh2_device::EXTUW(uint32_t m, uint32_t n) -{ - m_sh2_state->r[n] = m_sh2_state->r[m] & 0x0000ffff; -} - -/* ILLEGAL */ -void sh2_device::ILLEGAL() -{ - logerror("SH2.%s: Illegal opcode at %08x\n", tag(), m_sh2_state->pc - 2); - m_sh2_state->r[15] -= 4; - WL( 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 */ - - /* fetch PC */ - m_sh2_state->pc = RL( m_sh2_state->vbr + 4 * 4 ); - - /* TODO: timing is a guess */ - m_sh2_state->icount -= 5; -} - - -/* JMP @Rm */ -void sh2_device::JMP(uint32_t m) -{ - m_delay = m_sh2_state->ea = m_sh2_state->r[m]; - m_sh2_state->icount--; -} - -/* JSR @Rm */ -void sh2_device::JSR(uint32_t m) -{ - m_sh2_state->pr = m_sh2_state->pc + 2; - m_delay = m_sh2_state->ea = m_sh2_state->r[m]; - m_sh2_state->icount--; -} - - -/* LDC Rm,SR */ -void sh2_device::LDCSR(uint32_t m) -{ - m_sh2_state->sr = m_sh2_state->r[m] & FLAGS; - m_test_irq = 1; -} - -/* LDC Rm,GBR */ -void sh2_device::LDCGBR(uint32_t m) -{ - m_sh2_state->gbr = m_sh2_state->r[m]; -} - -/* LDC Rm,VBR */ -void sh2_device::LDCVBR(uint32_t m) -{ - m_sh2_state->vbr = m_sh2_state->r[m]; -} - -/* LDC.L @Rm+,SR */ -void sh2_device::LDCMSR(uint32_t m) -{ - m_sh2_state->ea = m_sh2_state->r[m]; - m_sh2_state->sr = RL( m_sh2_state->ea ) & FLAGS; - m_sh2_state->r[m] += 4; - m_sh2_state->icount -= 2; - m_test_irq = 1; -} - -/* LDC.L @Rm+,GBR */ -void sh2_device::LDCMGBR(uint32_t m) -{ - m_sh2_state->ea = m_sh2_state->r[m]; - m_sh2_state->gbr = RL( m_sh2_state->ea ); - m_sh2_state->r[m] += 4; - m_sh2_state->icount -= 2; -} - -/* LDC.L @Rm+,VBR */ -void sh2_device::LDCMVBR(uint32_t m) -{ - m_sh2_state->ea = m_sh2_state->r[m]; - m_sh2_state->vbr = RL( m_sh2_state->ea ); - m_sh2_state->r[m] += 4; - m_sh2_state->icount -= 2; -} - -/* LDS Rm,MACH */ -void sh2_device::LDSMACH(uint32_t m) -{ - m_sh2_state->mach = m_sh2_state->r[m]; -} - -/* LDS Rm,MACL */ -void sh2_device::LDSMACL(uint32_t m) -{ - m_sh2_state->macl = m_sh2_state->r[m]; -} - -/* LDS Rm,PR */ -void sh2_device::LDSPR(uint32_t m) -{ - m_sh2_state->pr = m_sh2_state->r[m]; -} - -/* LDS.L @Rm+,MACH */ -void sh2_device::LDSMMACH(uint32_t m) -{ - m_sh2_state->ea = m_sh2_state->r[m]; - m_sh2_state->mach = RL( m_sh2_state->ea ); - m_sh2_state->r[m] += 4; -} - -/* LDS.L @Rm+,MACL */ -void sh2_device::LDSMMACL(uint32_t m) -{ - m_sh2_state->ea = m_sh2_state->r[m]; - m_sh2_state->macl = RL( m_sh2_state->ea ); - m_sh2_state->r[m] += 4; -} - -/* LDS.L @Rm+,PR */ -void sh2_device::LDSMPR(uint32_t m) -{ - m_sh2_state->ea = m_sh2_state->r[m]; - m_sh2_state->pr = RL( m_sh2_state->ea ); - m_sh2_state->r[m] += 4; -} - -/* MAC.L @Rm+,@Rn+ */ -void sh2_device::MAC_L(uint32_t m, uint32_t n) -{ - uint32_t RnL, RnH, RmL, RmH, Res0, Res1, Res2; - uint32_t temp0, temp1, temp2, temp3; - int32_t tempm, tempn, fnLmL; - - tempn = (int32_t) RL( m_sh2_state->r[n] ); - m_sh2_state->r[n] += 4; - tempm = (int32_t) RL( m_sh2_state->r[m] ); - m_sh2_state->r[m] += 4; - if ((int32_t) (tempn ^ tempm) < 0) - fnLmL = -1; - else - fnLmL = 0; - if (tempn < 0) - tempn = 0 - tempn; - if (tempm < 0) - tempm = 0 - tempm; - temp1 = (uint32_t) tempn; - temp2 = (uint32_t) tempm; - RnL = temp1 & 0x0000ffff; - RnH = (temp1 >> 16) & 0x0000ffff; - RmL = temp2 & 0x0000ffff; - RmH = (temp2 >> 16) & 0x0000ffff; - temp0 = RmL * RnL; - temp1 = RmH * RnL; - temp2 = RmL * RnH; - temp3 = RmH * RnH; - Res2 = 0; - Res1 = temp1 + temp2; - if (Res1 < temp1) - Res2 += 0x00010000; - temp1 = (Res1 << 16) & 0xffff0000; - Res0 = temp0 + temp1; - if (Res0 < temp0) - Res2++; - Res2 = Res2 + ((Res1 >> 16) & 0x0000ffff) + temp3; - if (fnLmL < 0) - { - Res2 = ~Res2; - if (Res0 == 0) - Res2++; - else - Res0 = (~Res0) + 1; - } - if (m_sh2_state->sr & S) - { - Res0 = m_sh2_state->macl + Res0; - if (m_sh2_state->macl > Res0) - Res2++; - Res2 += (m_sh2_state->mach & 0x0000ffff); - if (((int32_t) Res2 < 0) && (Res2 < 0xffff8000)) - { - Res2 = 0x00008000; - Res0 = 0x00000000; - } - else if (((int32_t) Res2 > 0) && (Res2 > 0x00007fff)) - { - Res2 = 0x00007fff; - Res0 = 0xffffffff; - } - m_sh2_state->mach = Res2; - m_sh2_state->macl = Res0; - } - else - { - Res0 = m_sh2_state->macl + Res0; - if (m_sh2_state->macl > Res0) - Res2++; - Res2 += m_sh2_state->mach; - m_sh2_state->mach = Res2; - m_sh2_state->macl = Res0; - } - m_sh2_state->icount -= 2; -} - -/* MAC.W @Rm+,@Rn+ */ -void sh2_device::MAC_W(uint32_t m, uint32_t n) -{ - int32_t tempm, tempn, dest, src, ans; - uint32_t templ; - - tempn = (int32_t) RW( m_sh2_state->r[n] ); - m_sh2_state->r[n] += 2; - tempm = (int32_t) RW( m_sh2_state->r[m] ); - m_sh2_state->r[m] += 2; - templ = m_sh2_state->macl; - tempm = ((int32_t) (short) tempn * (int32_t) (short) tempm); - if ((int32_t) m_sh2_state->macl >= 0) - dest = 0; - else - dest = 1; - if ((int32_t) tempm >= 0) - { - src = 0; - tempn = 0; - } - else - { - src = 1; - tempn = 0xffffffff; - } - src += dest; - m_sh2_state->macl += tempm; - if ((int32_t) m_sh2_state->macl >= 0) - ans = 0; - else - ans = 1; - ans += dest; - if (m_sh2_state->sr & S) - { - if (ans == 1) - { - if (src == 0) - m_sh2_state->macl = 0x7fffffff; - if (src == 2) - m_sh2_state->macl = 0x80000000; - } - } - else - { - m_sh2_state->mach += tempn; - if (templ > m_sh2_state->macl) - m_sh2_state->mach += 1; - } - m_sh2_state->icount -= 2; -} - -/* MOV Rm,Rn */ -void sh2_device::MOV(uint32_t m, uint32_t n) -{ - m_sh2_state->r[n] = m_sh2_state->r[m]; -} - -/* MOV.B Rm,@Rn */ -void sh2_device::MOVBS(uint32_t m, uint32_t n) -{ - m_sh2_state->ea = m_sh2_state->r[n]; - WB( m_sh2_state->ea, m_sh2_state->r[m] & 0x000000ff); -} - -/* MOV.W Rm,@Rn */ -void sh2_device::MOVWS(uint32_t m, uint32_t n) -{ - m_sh2_state->ea = m_sh2_state->r[n]; - WW( m_sh2_state->ea, m_sh2_state->r[m] & 0x0000ffff); -} - -/* MOV.L Rm,@Rn */ -void sh2_device::MOVLS(uint32_t m, uint32_t n) -{ - m_sh2_state->ea = m_sh2_state->r[n]; - WL( m_sh2_state->ea, m_sh2_state->r[m] ); -} - -/* MOV.B @Rm,Rn */ -void sh2_device::MOVBL(uint32_t m, uint32_t n) -{ - m_sh2_state->ea = m_sh2_state->r[m]; - m_sh2_state->r[n] = (uint32_t)(int32_t)(int16_t)(int8_t) RB( m_sh2_state->ea ); -} - -/* MOV.W @Rm,Rn */ -void sh2_device::MOVWL(uint32_t m, uint32_t n) -{ - m_sh2_state->ea = m_sh2_state->r[m]; - m_sh2_state->r[n] = (uint32_t)(int32_t)(int16_t) RW( m_sh2_state->ea ); -} - -/* MOV.L @Rm,Rn */ -void sh2_device::MOVLL(uint32_t m, uint32_t n) -{ - m_sh2_state->ea = m_sh2_state->r[m]; - m_sh2_state->r[n] = RL( m_sh2_state->ea ); -} - -/* MOV.B Rm,@-Rn */ -void sh2_device::MOVBM(uint32_t m, uint32_t n) -{ - /* SMG : bug fix, was reading m_sh2_state->r[n] */ - uint32_t data = m_sh2_state->r[m] & 0x000000ff; - - m_sh2_state->r[n] -= 1; - WB( m_sh2_state->r[n], data ); -} - -/* MOV.W Rm,@-Rn */ -void sh2_device::MOVWM(uint32_t m, uint32_t n) -{ - uint32_t data = m_sh2_state->r[m] & 0x0000ffff; - - m_sh2_state->r[n] -= 2; - WW( m_sh2_state->r[n], data ); -} - -/* MOV.L Rm,@-Rn */ -void sh2_device::MOVLM(uint32_t m, uint32_t n) -{ - uint32_t data = m_sh2_state->r[m]; - - m_sh2_state->r[n] -= 4; - WL( m_sh2_state->r[n], data ); -} - -/* MOV.B @Rm+,Rn */ -void sh2_device::MOVBP(uint32_t m, uint32_t n) -{ - m_sh2_state->r[n] = (uint32_t)(int32_t)(int16_t)(int8_t) RB( m_sh2_state->r[m] ); - if (n != m) - m_sh2_state->r[m] += 1; -} - -/* MOV.W @Rm+,Rn */ -void sh2_device::MOVWP(uint32_t m, uint32_t n) -{ - m_sh2_state->r[n] = (uint32_t)(int32_t)(int16_t) RW( m_sh2_state->r[m] ); - if (n != m) - m_sh2_state->r[m] += 2; -} - -/* MOV.L @Rm+,Rn */ -void sh2_device::MOVLP(uint32_t m, uint32_t n) -{ - m_sh2_state->r[n] = RL( m_sh2_state->r[m] ); - if (n != m) - m_sh2_state->r[m] += 4; -} - -/* MOV.B Rm,@(R0,Rn) */ -void sh2_device::MOVBS0(uint32_t m, uint32_t n) -{ - m_sh2_state->ea = m_sh2_state->r[n] + m_sh2_state->r[0]; - WB( m_sh2_state->ea, m_sh2_state->r[m] & 0x000000ff ); -} - -/* MOV.W Rm,@(R0,Rn) */ -void sh2_device::MOVWS0(uint32_t m, uint32_t n) -{ - m_sh2_state->ea = m_sh2_state->r[n] + m_sh2_state->r[0]; - WW( m_sh2_state->ea, m_sh2_state->r[m] & 0x0000ffff ); -} - -/* MOV.L Rm,@(R0,Rn) */ -void sh2_device::MOVLS0(uint32_t m, uint32_t n) -{ - m_sh2_state->ea = m_sh2_state->r[n] + m_sh2_state->r[0]; - WL( m_sh2_state->ea, m_sh2_state->r[m] ); -} - -/* MOV.B @(R0,Rm),Rn */ -void sh2_device::MOVBL0(uint32_t m, uint32_t n) -{ - m_sh2_state->ea = m_sh2_state->r[m] + m_sh2_state->r[0]; - m_sh2_state->r[n] = (uint32_t)(int32_t)(int16_t)(int8_t) RB( m_sh2_state->ea ); -} - -/* MOV.W @(R0,Rm),Rn */ -void sh2_device::MOVWL0(uint32_t m, uint32_t n) -{ - m_sh2_state->ea = m_sh2_state->r[m] + m_sh2_state->r[0]; - m_sh2_state->r[n] = (uint32_t)(int32_t)(int16_t) RW( m_sh2_state->ea ); -} - -/* MOV.L @(R0,Rm),Rn */ -void sh2_device::MOVLL0(uint32_t m, uint32_t n) -{ - m_sh2_state->ea = m_sh2_state->r[m] + m_sh2_state->r[0]; - m_sh2_state->r[n] = RL( m_sh2_state->ea ); -} - -/* MOV #imm,Rn */ -void sh2_device::MOVI(uint32_t i, uint32_t n) -{ - m_sh2_state->r[n] = (uint32_t)(int32_t)(int16_t)(int8_t) i; -} - -/* MOV.W @(disp8,PC),Rn */ -void sh2_device::MOVWI(uint32_t d, uint32_t n) -{ - uint32_t disp = d & 0xff; - m_sh2_state->ea = m_sh2_state->pc + disp * 2 + 2; - m_sh2_state->r[n] = (uint32_t)(int32_t)(int16_t) RW( m_sh2_state->ea ); -} - -/* MOV.L @(disp8,PC),Rn */ -void sh2_device::MOVLI(uint32_t d, uint32_t n) -{ - uint32_t disp = d & 0xff; - m_sh2_state->ea = ((m_sh2_state->pc + 2) & ~3) + disp * 4; - m_sh2_state->r[n] = RL( m_sh2_state->ea ); -} - -/* MOV.B @(disp8,GBR),R0 */ -void sh2_device::MOVBLG(uint32_t d) -{ - uint32_t disp = d & 0xff; - m_sh2_state->ea = m_sh2_state->gbr + disp; - m_sh2_state->r[0] = (uint32_t)(int32_t)(int16_t)(int8_t) RB( m_sh2_state->ea ); -} - -/* MOV.W @(disp8,GBR),R0 */ -void sh2_device::MOVWLG(uint32_t d) -{ - uint32_t disp = d & 0xff; - m_sh2_state->ea = m_sh2_state->gbr + disp * 2; - m_sh2_state->r[0] = (int32_t)(int16_t) RW( m_sh2_state->ea ); -} - -/* MOV.L @(disp8,GBR),R0 */ -void sh2_device::MOVLLG(uint32_t d) -{ - uint32_t disp = d & 0xff; - m_sh2_state->ea = m_sh2_state->gbr + disp * 4; - m_sh2_state->r[0] = RL( m_sh2_state->ea ); -} - -/* MOV.B R0,@(disp8,GBR) */ -void sh2_device::MOVBSG(uint32_t d) -{ - uint32_t disp = d & 0xff; - m_sh2_state->ea = m_sh2_state->gbr + disp; - WB( m_sh2_state->ea, m_sh2_state->r[0] & 0x000000ff ); -} - -/* MOV.W R0,@(disp8,GBR) */ -void sh2_device::MOVWSG(uint32_t d) -{ - uint32_t disp = d & 0xff; - m_sh2_state->ea = m_sh2_state->gbr + disp * 2; - WW( m_sh2_state->ea, m_sh2_state->r[0] & 0x0000ffff ); -} - -/* MOV.L R0,@(disp8,GBR) */ -void sh2_device::MOVLSG(uint32_t d) -{ - uint32_t disp = d & 0xff; - m_sh2_state->ea = m_sh2_state->gbr + disp * 4; - WL( m_sh2_state->ea, m_sh2_state->r[0] ); -} - -/* MOV.B R0,@(disp4,Rn) */ -void sh2_device::MOVBS4(uint32_t d, uint32_t n) -{ - uint32_t disp = d & 0x0f; - m_sh2_state->ea = m_sh2_state->r[n] + disp; - WB( m_sh2_state->ea, m_sh2_state->r[0] & 0x000000ff ); -} - -/* MOV.W R0,@(disp4,Rn) */ -void sh2_device::MOVWS4(uint32_t d, uint32_t n) -{ - uint32_t disp = d & 0x0f; - m_sh2_state->ea = m_sh2_state->r[n] + disp * 2; - WW( m_sh2_state->ea, m_sh2_state->r[0] & 0x0000ffff ); -} - -/* MOV.L Rm,@(disp4,Rn) */ -void sh2_device::MOVLS4(uint32_t m, uint32_t d, uint32_t n) -{ - uint32_t disp = d & 0x0f; - m_sh2_state->ea = m_sh2_state->r[n] + disp * 4; - WL( m_sh2_state->ea, m_sh2_state->r[m] ); -} - -/* MOV.B @(disp4,Rm),R0 */ -void sh2_device::MOVBL4(uint32_t m, uint32_t d) -{ - uint32_t disp = d & 0x0f; - m_sh2_state->ea = m_sh2_state->r[m] + disp; - m_sh2_state->r[0] = (uint32_t)(int32_t)(int16_t)(int8_t) RB( m_sh2_state->ea ); -} - -/* MOV.W @(disp4,Rm),R0 */ -void sh2_device::MOVWL4(uint32_t m, uint32_t d) -{ - uint32_t disp = d & 0x0f; - m_sh2_state->ea = m_sh2_state->r[m] + disp * 2; - m_sh2_state->r[0] = (uint32_t)(int32_t)(int16_t) RW( m_sh2_state->ea ); -} - -/* MOV.L @(disp4,Rm),Rn */ -void sh2_device::MOVLL4(uint32_t m, uint32_t d, uint32_t n) -{ - uint32_t disp = d & 0x0f; - m_sh2_state->ea = m_sh2_state->r[m] + disp * 4; - m_sh2_state->r[n] = RL( m_sh2_state->ea ); -} - -/* MOVA @(disp8,PC),R0 */ -void sh2_device::MOVA(uint32_t d) -{ - uint32_t disp = d & 0xff; - m_sh2_state->ea = ((m_sh2_state->pc + 2) & ~3) + disp * 4; - m_sh2_state->r[0] = m_sh2_state->ea; -} - -/* MOVT Rn */ -void sh2_device::MOVT(uint32_t n) -{ - m_sh2_state->r[n] = m_sh2_state->sr & T; -} - -/* MUL.L Rm,Rn */ -void sh2_device::MULL(uint32_t m, uint32_t n) -{ - m_sh2_state->macl = m_sh2_state->r[n] * m_sh2_state->r[m]; - m_sh2_state->icount--; -} - -/* MULS Rm,Rn */ -void sh2_device::MULS(uint32_t m, uint32_t n) -{ - m_sh2_state->macl = (int16_t) m_sh2_state->r[n] * (int16_t) m_sh2_state->r[m]; -} - -/* MULU Rm,Rn */ -void sh2_device::MULU(uint32_t m, uint32_t n) -{ - m_sh2_state->macl = (uint16_t) m_sh2_state->r[n] * (uint16_t) m_sh2_state->r[m]; -} - -/* NEG Rm,Rn */ -void sh2_device::NEG(uint32_t m, uint32_t n) -{ - m_sh2_state->r[n] = 0 - m_sh2_state->r[m]; -} - -/* NEGC Rm,Rn */ -void sh2_device::NEGC(uint32_t m, uint32_t n) -{ - uint32_t temp; - - temp = m_sh2_state->r[m]; - m_sh2_state->r[n] = -temp - (m_sh2_state->sr & T); - if (temp || (m_sh2_state->sr & T)) - m_sh2_state->sr |= T; - else - m_sh2_state->sr &= ~T; -} - -/* NOP */ -void sh2_device::NOP(void) -{ -} - -/* NOT Rm,Rn */ -void sh2_device::NOT(uint32_t m, uint32_t n) -{ - m_sh2_state->r[n] = ~m_sh2_state->r[m]; -} - -/* OR Rm,Rn */ -void sh2_device::OR(uint32_t m, uint32_t n) -{ - m_sh2_state->r[n] |= m_sh2_state->r[m]; -} - -/* OR #imm,R0 */ -void sh2_device::ORI(uint32_t i) -{ - m_sh2_state->r[0] |= i; -} - -/* OR.B #imm,@(R0,GBR) */ -void sh2_device::ORM(uint32_t i) -{ - uint32_t temp; - - m_sh2_state->ea = m_sh2_state->gbr + m_sh2_state->r[0]; - temp = RB( m_sh2_state->ea ); - temp |= i; - WB( m_sh2_state->ea, temp ); - m_sh2_state->icount -= 2; -} - -/* ROTCL Rn */ -void sh2_device::ROTCL(uint32_t n) -{ - uint32_t temp; - - temp = (m_sh2_state->r[n] >> 31) & T; - m_sh2_state->r[n] = (m_sh2_state->r[n] << 1) | (m_sh2_state->sr & T); - m_sh2_state->sr = (m_sh2_state->sr & ~T) | temp; -} - -/* ROTCR Rn */ -void sh2_device::ROTCR(uint32_t n) -{ - uint32_t temp; - temp = (m_sh2_state->sr & T) << 31; - if (m_sh2_state->r[n] & T) - m_sh2_state->sr |= T; - else - m_sh2_state->sr &= ~T; - m_sh2_state->r[n] = (m_sh2_state->r[n] >> 1) | temp; -} - -/* ROTL Rn */ -void sh2_device::ROTL(uint32_t n) -{ - m_sh2_state->sr = (m_sh2_state->sr & ~T) | ((m_sh2_state->r[n] >> 31) & T); - m_sh2_state->r[n] = (m_sh2_state->r[n] << 1) | (m_sh2_state->r[n] >> 31); -} - -/* ROTR Rn */ -void sh2_device::ROTR(uint32_t n) -{ - m_sh2_state->sr = (m_sh2_state->sr & ~T) | (m_sh2_state->r[n] & T); - m_sh2_state->r[n] = (m_sh2_state->r[n] >> 1) | (m_sh2_state->r[n] << 31); -} - -/* RTE */ -void sh2_device::RTE() -{ - m_sh2_state->ea = m_sh2_state->r[15]; - m_delay = RL( 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 ) & FLAGS; - m_sh2_state->r[15] += 4; - m_sh2_state->icount -= 3; - m_test_irq = 1; -} - -/* RTS */ -void sh2_device::RTS() -{ - m_delay = m_sh2_state->ea = m_sh2_state->pr; - m_sh2_state->icount--; -} - -/* SETT */ -void sh2_device::SETT() -{ - m_sh2_state->sr |= T; -} - -/* SHAL Rn (same as SHLL) */ -void sh2_device::SHAL(uint32_t n) -{ - m_sh2_state->sr = (m_sh2_state->sr & ~T) | ((m_sh2_state->r[n] >> 31) & T); - m_sh2_state->r[n] <<= 1; -} - -/* SHAR Rn */ -void sh2_device::SHAR(uint32_t n) -{ - m_sh2_state->sr = (m_sh2_state->sr & ~T) | (m_sh2_state->r[n] & T); - m_sh2_state->r[n] = (uint32_t)((int32_t)m_sh2_state->r[n] >> 1); -} - -/* SHLL Rn (same as SHAL) */ -void sh2_device::SHLL(uint32_t n) -{ - m_sh2_state->sr = (m_sh2_state->sr & ~T) | ((m_sh2_state->r[n] >> 31) & T); - m_sh2_state->r[n] <<= 1; -} - -/* SHLL2 Rn */ -void sh2_device::SHLL2(uint32_t n) -{ - m_sh2_state->r[n] <<= 2; -} - -/* SHLL8 Rn */ -void sh2_device::SHLL8(uint32_t n) -{ - m_sh2_state->r[n] <<= 8; -} - -/* SHLL16 Rn */ -void sh2_device::SHLL16(uint32_t n) -{ - m_sh2_state->r[n] <<= 16; -} - -/* SHLR Rn */ -void sh2_device::SHLR(uint32_t n) -{ - m_sh2_state->sr = (m_sh2_state->sr & ~T) | (m_sh2_state->r[n] & T); - m_sh2_state->r[n] >>= 1; -} - -/* SHLR2 Rn */ -void sh2_device::SHLR2(uint32_t n) -{ - m_sh2_state->r[n] >>= 2; -} - -/* SHLR8 Rn */ -void sh2_device::SHLR8(uint32_t n) -{ - m_sh2_state->r[n] >>= 8; -} - -/* SHLR16 Rn */ -void sh2_device::SHLR16(uint32_t n) -{ - m_sh2_state->r[n] >>= 16; -} - -/* SLEEP */ -void sh2_device::SLEEP() -{ - if(m_sh2_state->sleep_mode != 2) - m_sh2_state->pc -= 2; - m_sh2_state->icount -= 2; - /* Wait_for_exception; */ - if(m_sh2_state->sleep_mode == 0) - m_sh2_state->sleep_mode = 1; - else if(m_sh2_state->sleep_mode == 2) - m_sh2_state->sleep_mode = 0; -} - -/* STC SR,Rn */ -void sh2_device::STCSR(uint32_t n) -{ - m_sh2_state->r[n] = m_sh2_state->sr; -} - -/* STC GBR,Rn */ -void sh2_device::STCGBR(uint32_t n) -{ - m_sh2_state->r[n] = m_sh2_state->gbr; -} - -/* STC VBR,Rn */ -void sh2_device::STCVBR(uint32_t n) -{ - m_sh2_state->r[n] = m_sh2_state->vbr; -} - -/* STC.L SR,@-Rn */ -void sh2_device::STCMSR(uint32_t n) -{ - m_sh2_state->r[n] -= 4; - m_sh2_state->ea = m_sh2_state->r[n]; - WL( m_sh2_state->ea, m_sh2_state->sr ); - m_sh2_state->icount--; -} - -/* STC.L GBR,@-Rn */ -void sh2_device::STCMGBR(uint32_t n) -{ - m_sh2_state->r[n] -= 4; - m_sh2_state->ea = m_sh2_state->r[n]; - WL( m_sh2_state->ea, m_sh2_state->gbr ); - m_sh2_state->icount--; -} - -/* STC.L VBR,@-Rn */ -void sh2_device::STCMVBR(uint32_t n) -{ - m_sh2_state->r[n] -= 4; - m_sh2_state->ea = m_sh2_state->r[n]; - WL( m_sh2_state->ea, m_sh2_state->vbr ); - m_sh2_state->icount--; -} - -/* STS MACH,Rn */ -void sh2_device::STSMACH(uint32_t n) -{ - m_sh2_state->r[n] = m_sh2_state->mach; -} - -/* STS MACL,Rn */ -void sh2_device::STSMACL(uint32_t n) -{ - m_sh2_state->r[n] = m_sh2_state->macl; -} - -/* STS PR,Rn */ -void sh2_device::STSPR(uint32_t n) -{ - m_sh2_state->r[n] = m_sh2_state->pr; -} - -/* STS.L MACH,@-Rn */ -void sh2_device::STSMMACH(uint32_t n) -{ - m_sh2_state->r[n] -= 4; - m_sh2_state->ea = m_sh2_state->r[n]; - WL( m_sh2_state->ea, m_sh2_state->mach ); -} - -/* STS.L MACL,@-Rn */ -void sh2_device::STSMMACL(uint32_t n) -{ - m_sh2_state->r[n] -= 4; - m_sh2_state->ea = m_sh2_state->r[n]; - WL( m_sh2_state->ea, m_sh2_state->macl ); -} - -/* STS.L PR,@-Rn */ -void sh2_device::STSMPR(uint32_t n) -{ - m_sh2_state->r[n] -= 4; - m_sh2_state->ea = m_sh2_state->r[n]; - WL( m_sh2_state->ea, m_sh2_state->pr ); -} - -/* SUB Rm,Rn */ -void sh2_device::SUB(uint32_t m, uint32_t n) -{ - m_sh2_state->r[n] -= m_sh2_state->r[m]; -} - -/* SUBC Rm,Rn */ -void sh2_device::SUBC(uint32_t m, uint32_t n) -{ - uint32_t tmp0, tmp1; - - tmp1 = m_sh2_state->r[n] - m_sh2_state->r[m]; - tmp0 = m_sh2_state->r[n]; - m_sh2_state->r[n] = tmp1 - (m_sh2_state->sr & T); - if (tmp0 < tmp1) - m_sh2_state->sr |= T; - else - m_sh2_state->sr &= ~T; - if (tmp1 < m_sh2_state->r[n]) - m_sh2_state->sr |= T; -} - -/* SUBV Rm,Rn */ -void sh2_device::SUBV(uint32_t m, uint32_t n) -{ - int32_t dest, src, ans; - - if ((int32_t) m_sh2_state->r[n] >= 0) - dest = 0; - else - dest = 1; - if ((int32_t) m_sh2_state->r[m] >= 0) - src = 0; - else - src = 1; - src += dest; - m_sh2_state->r[n] -= m_sh2_state->r[m]; - if ((int32_t) m_sh2_state->r[n] >= 0) - ans = 0; - else - ans = 1; - ans += dest; - if (src == 1) - { - if (ans == 1) - m_sh2_state->sr |= T; - else - m_sh2_state->sr &= ~T; - } - else - m_sh2_state->sr &= ~T; -} - -/* SWAP.B Rm,Rn */ -void sh2_device::SWAPB(uint32_t m, uint32_t n) -{ - uint32_t temp0, temp1; - - temp0 = m_sh2_state->r[m] & 0xffff0000; - temp1 = (m_sh2_state->r[m] & 0x000000ff) << 8; - m_sh2_state->r[n] = (m_sh2_state->r[m] >> 8) & 0x000000ff; - m_sh2_state->r[n] = m_sh2_state->r[n] | temp1 | temp0; -} - -/* SWAP.W Rm,Rn */ -void sh2_device::SWAPW(uint32_t m, uint32_t n) -{ - uint32_t temp; - - temp = (m_sh2_state->r[m] >> 16) & 0x0000ffff; - m_sh2_state->r[n] = (m_sh2_state->r[m] << 16) | temp; -} - -/* TAS.B @Rn */ -void sh2_device::TAS(uint32_t n) -{ - uint32_t temp; - m_sh2_state->ea = m_sh2_state->r[n]; - /* Bus Lock enable */ - temp = RB( m_sh2_state->ea ); - if (temp == 0) - m_sh2_state->sr |= T; - else - m_sh2_state->sr &= ~T; - temp |= 0x80; - /* Bus Lock disable */ - WB( m_sh2_state->ea, temp ); - m_sh2_state->icount -= 3; -} - -/* TRAPA #imm */ -void sh2_device::TRAPA(uint32_t i) -{ - uint32_t imm = i & 0xff; - - 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 ); - m_sh2_state->r[15] -= 4; - WL( m_sh2_state->r[15], m_sh2_state->pc ); - - m_sh2_state->pc = RL( m_sh2_state->ea ); - - m_sh2_state->icount -= 7; -} - -/* TST Rm,Rn */ -void sh2_device::TST(uint32_t m, uint32_t n) -{ - if ((m_sh2_state->r[n] & m_sh2_state->r[m]) == 0) - m_sh2_state->sr |= T; - else - m_sh2_state->sr &= ~T; -} - -/* TST #imm,R0 */ -void sh2_device::TSTI(uint32_t i) -{ - uint32_t imm = i & 0xff; - - if ((imm & m_sh2_state->r[0]) == 0) - m_sh2_state->sr |= T; - else - m_sh2_state->sr &= ~T; -} - -/* TST.B #imm,@(R0,GBR) */ -void sh2_device::TSTM(uint32_t i) -{ - uint32_t imm = i & 0xff; - - m_sh2_state->ea = m_sh2_state->gbr + m_sh2_state->r[0]; - if ((imm & RB( m_sh2_state->ea )) == 0) - m_sh2_state->sr |= T; - else - m_sh2_state->sr &= ~T; - m_sh2_state->icount -= 2; -} - -/* XOR Rm,Rn */ -void sh2_device::XOR(uint32_t m, uint32_t n) -{ - m_sh2_state->r[n] ^= m_sh2_state->r[m]; -} - -/* XOR #imm,R0 */ -void sh2_device::XORI(uint32_t i) -{ - uint32_t imm = i & 0xff; - m_sh2_state->r[0] ^= imm; -} - -/* XOR.B #imm,@(R0,GBR) */ -void sh2_device::XORM(uint32_t i) -{ - uint32_t imm = i & 0xff; - uint32_t temp; - - m_sh2_state->ea = m_sh2_state->gbr + m_sh2_state->r[0]; - temp = RB( m_sh2_state->ea ); - temp ^= imm; - WB( m_sh2_state->ea, temp ); - m_sh2_state->icount -= 2; -} - -/* XTRCT Rm,Rn */ -void sh2_device::XTRCT(uint32_t m, uint32_t n) -{ - uint32_t temp; - - temp = (m_sh2_state->r[m] << 16) & 0xffff0000; - m_sh2_state->r[n] = (m_sh2_state->r[n] >> 16) & 0x0000ffff; - m_sh2_state->r[n] |= temp; -} - -/***************************************************************************** - * OPCODE DISPATCHERS - *****************************************************************************/ - -void sh2_device::op0000(uint16_t opcode) -{ - switch (opcode & 0x3F) - { - case 0x00: ILLEGAL(); break; - case 0x01: ILLEGAL(); break; - case 0x02: STCSR(Rn); break; - case 0x03: BSRF(Rn); break; - case 0x04: MOVBS0(Rm, Rn); break; - case 0x05: MOVWS0(Rm, Rn); break; - case 0x06: MOVLS0(Rm, Rn); break; - case 0x07: MULL(Rm, Rn); break; - case 0x08: CLRT(); break; - case 0x09: NOP(); break; - case 0x0a: STSMACH(Rn); break; - case 0x0b: RTS(); break; - case 0x0c: MOVBL0(Rm, Rn); break; - case 0x0d: MOVWL0(Rm, Rn); break; - case 0x0e: MOVLL0(Rm, Rn); break; - case 0x0f: MAC_L(Rm, Rn); break; - - case 0x10: ILLEGAL(); break; - case 0x11: ILLEGAL(); break; - case 0x12: STCGBR(Rn); break; - case 0x13: ILLEGAL(); break; - case 0x14: MOVBS0(Rm, Rn); break; - case 0x15: MOVWS0(Rm, Rn); break; - case 0x16: MOVLS0(Rm, Rn); break; - case 0x17: MULL(Rm, Rn); break; - case 0x18: SETT(); break; - case 0x19: DIV0U(); break; - case 0x1a: STSMACL(Rn); break; - case 0x1b: SLEEP(); break; - case 0x1c: MOVBL0(Rm, Rn); break; - case 0x1d: MOVWL0(Rm, Rn); break; - case 0x1e: MOVLL0(Rm, Rn); break; - case 0x1f: MAC_L(Rm, Rn); break; - - case 0x20: ILLEGAL(); break; - case 0x21: ILLEGAL(); break; - case 0x22: STCVBR(Rn); break; - case 0x23: BRAF(Rn); break; - case 0x24: MOVBS0(Rm, Rn); break; - case 0x25: MOVWS0(Rm, Rn); break; - case 0x26: MOVLS0(Rm, Rn); break; - case 0x27: MULL(Rm, Rn); break; - case 0x28: CLRMAC(); break; - case 0x29: MOVT(Rn); break; - case 0x2a: STSPR(Rn); break; - case 0x2b: RTE(); break; - case 0x2c: MOVBL0(Rm, Rn); break; - case 0x2d: MOVWL0(Rm, Rn); break; - case 0x2e: MOVLL0(Rm, Rn); break; - case 0x2f: MAC_L(Rm, Rn); break; - - case 0x30: ILLEGAL(); break; - case 0x31: ILLEGAL(); break; - case 0x32: ILLEGAL(); break; - case 0x33: ILLEGAL(); break; - case 0x34: MOVBS0(Rm, Rn); break; - case 0x35: MOVWS0(Rm, Rn); break; - case 0x36: MOVLS0(Rm, Rn); break; - case 0x37: MULL(Rm, Rn); break; - case 0x38: ILLEGAL(); break; - case 0x39: ILLEGAL(); break; - case 0x3c: MOVBL0(Rm, Rn); break; - case 0x3d: MOVWL0(Rm, Rn); break; - case 0x3e: MOVLL0(Rm, Rn); break; - case 0x3f: MAC_L(Rm, Rn); break; - case 0x3a: ILLEGAL(); break; - case 0x3b: ILLEGAL(); break; - - - - } -} - -void sh2_device::op0001(uint16_t opcode) -{ - MOVLS4(Rm, opcode & 0x0f, Rn); -} - -void sh2_device::op0010(uint16_t opcode) -{ - switch (opcode & 15) - { - case 0: MOVBS(Rm, Rn); break; - case 1: MOVWS(Rm, Rn); break; - case 2: MOVLS(Rm, Rn); break; - case 3: ILLEGAL(); break; - case 4: MOVBM(Rm, Rn); break; - case 5: MOVWM(Rm, Rn); break; - case 6: MOVLM(Rm, Rn); break; - case 7: DIV0S(Rm, Rn); break; - case 8: TST(Rm, Rn); break; - case 9: AND(Rm, Rn); break; - case 10: XOR(Rm, Rn); break; - case 11: OR(Rm, Rn); break; - case 12: CMPSTR(Rm, Rn); break; - case 13: XTRCT(Rm, Rn); break; - case 14: MULU(Rm, Rn); break; - case 15: MULS(Rm, Rn); break; - } -} - -void sh2_device::op0011(uint16_t opcode) -{ - switch (opcode & 15) - { - case 0: CMPEQ(Rm, Rn); break; - case 1: ILLEGAL(); break; - case 2: CMPHS(Rm, Rn); break; - case 3: CMPGE(Rm, Rn); break; - case 4: DIV1(Rm, Rn); break; - case 5: DMULU(Rm, Rn); break; - case 6: CMPHI(Rm, Rn); break; - case 7: CMPGT(Rm, Rn); break; - case 8: SUB(Rm, Rn); break; - case 9: ILLEGAL(); break; - case 10: SUBC(Rm, Rn); break; - case 11: SUBV(Rm, Rn); break; - case 12: ADD(Rm, Rn); break; - case 13: DMULS(Rm, Rn); break; - case 14: ADDC(Rm, Rn); break; - case 15: ADDV(Rm, Rn); break; - } -} - -void sh2_device::op0100(uint16_t opcode) -{ - switch (opcode & 0x3F) - { - case 0x00: SHLL(Rn); break; - case 0x01: SHLR(Rn); break; - case 0x02: STSMMACH(Rn); break; - case 0x03: STCMSR(Rn); break; - case 0x04: ROTL(Rn); break; - case 0x05: ROTR(Rn); break; - case 0x06: LDSMMACH(Rn); break; - case 0x07: LDCMSR(Rn); break; - case 0x08: SHLL2(Rn); break; - case 0x09: SHLR2(Rn); break; - case 0x0a: LDSMACH(Rn); break; - case 0x0b: JSR(Rn); break; - case 0x0c: ILLEGAL(); break; - case 0x0d: ILLEGAL(); break; - case 0x0e: LDCSR(Rn); break; - case 0x0f: MAC_W(Rm, Rn); break; - - case 0x10: DT(Rn); break; - case 0x11: CMPPZ(Rn); break; - case 0x12: STSMMACL(Rn); break; - case 0x13: STCMGBR(Rn); break; - case 0x14: ILLEGAL(); break; - case 0x15: CMPPL(Rn); break; - case 0x16: LDSMMACL(Rn); break; - case 0x17: LDCMGBR(Rn); break; - case 0x18: SHLL8(Rn); break; - case 0x19: SHLR8(Rn); break; - case 0x1a: LDSMACL(Rn); break; - case 0x1b: TAS(Rn); break; - case 0x1c: ILLEGAL(); break; - case 0x1d: ILLEGAL(); break; - case 0x1e: LDCGBR(Rn); break; - case 0x1f: MAC_W(Rm, Rn); break; - - case 0x20: SHAL(Rn); break; - case 0x21: SHAR(Rn); break; - case 0x22: STSMPR(Rn); break; - case 0x23: STCMVBR(Rn); break; - case 0x24: ROTCL(Rn); break; - case 0x25: ROTCR(Rn); break; - case 0x26: LDSMPR(Rn); break; - case 0x27: LDCMVBR(Rn); break; - case 0x28: SHLL16(Rn); break; - case 0x29: SHLR16(Rn); break; - case 0x2a: LDSPR(Rn); break; - case 0x2b: JMP(Rn); break; - case 0x2c: ILLEGAL(); break; - case 0x2d: ILLEGAL(); break; - case 0x2e: LDCVBR(Rn); break; - case 0x2f: MAC_W(Rm, Rn); break; - - case 0x30: ILLEGAL(); break; - case 0x31: ILLEGAL(); break; - case 0x32: ILLEGAL(); break; - case 0x33: ILLEGAL(); break; - case 0x34: ILLEGAL(); break; - case 0x35: ILLEGAL(); break; - case 0x36: ILLEGAL(); break; - case 0x37: ILLEGAL(); break; - case 0x38: ILLEGAL(); break; - case 0x39: ILLEGAL(); break; - case 0x3a: ILLEGAL(); break; - case 0x3b: ILLEGAL(); break; - case 0x3c: ILLEGAL(); break; - case 0x3d: ILLEGAL(); break; - case 0x3e: ILLEGAL(); break; - case 0x3f: MAC_W(Rm, Rn); break; - - } -} - -void sh2_device::op0101(uint16_t opcode) -{ - MOVLL4(Rm, opcode & 0x0f, Rn); -} - -void sh2_device::op0110(uint16_t opcode) -{ - switch (opcode & 15) - { - case 0: MOVBL(Rm, Rn); break; - case 1: MOVWL(Rm, Rn); break; - case 2: MOVLL(Rm, Rn); break; - case 3: MOV(Rm, Rn); break; - case 4: MOVBP(Rm, Rn); break; - case 5: MOVWP(Rm, Rn); break; - case 6: MOVLP(Rm, Rn); break; - case 7: NOT(Rm, Rn); break; - case 8: SWAPB(Rm, Rn); break; - case 9: SWAPW(Rm, Rn); break; - case 10: NEGC(Rm, Rn); break; - case 11: NEG(Rm, Rn); break; - case 12: EXTUB(Rm, Rn); break; - case 13: EXTUW(Rm, Rn); break; - case 14: EXTSB(Rm, Rn); break; - case 15: EXTSW(Rm, Rn); break; - } -} - -void sh2_device::op0111(uint16_t opcode) -{ - ADDI(opcode & 0xff, Rn); -} - -void sh2_device::op1000(uint16_t opcode) -{ - switch ( opcode & (15<<8) ) - { - case 0 << 8: MOVBS4(opcode & 0x0f, Rm); break; - case 1 << 8: MOVWS4(opcode & 0x0f, Rm); break; - case 2<< 8: ILLEGAL(); break; - case 3<< 8: ILLEGAL(); break; - case 4<< 8: MOVBL4(Rm, opcode & 0x0f); break; - case 5<< 8: MOVWL4(Rm, opcode & 0x0f); break; - case 6<< 8: ILLEGAL(); break; - case 7<< 8: ILLEGAL(); break; - case 8<< 8: CMPIM(opcode & 0xff); break; - case 9<< 8: BT(opcode & 0xff); break; - case 10<< 8: ILLEGAL(); break; - case 11<< 8: BF(opcode & 0xff); break; - case 12<< 8: ILLEGAL(); break; - case 13<< 8: BTS(opcode & 0xff); break; - case 14<< 8: ILLEGAL(); break; - case 15<< 8: BFS(opcode & 0xff); break; - } -} - - -void sh2_device::op1001(uint16_t opcode) -{ - MOVWI(opcode & 0xff, Rn); -} - -void sh2_device::op1010(uint16_t opcode) -{ - BRA(opcode & 0xfff); -} - -void sh2_device::op1011(uint16_t opcode) -{ - BSR(opcode & 0xfff); -} - -void sh2_device::op1100(uint16_t opcode) -{ - switch (opcode & (15<<8)) - { - case 0<<8: MOVBSG(opcode & 0xff); break; - case 1<<8: MOVWSG(opcode & 0xff); break; - case 2<<8: MOVLSG(opcode & 0xff); break; - case 3<<8: TRAPA(opcode & 0xff); break; - case 4<<8: MOVBLG(opcode & 0xff); break; - case 5<<8: MOVWLG(opcode & 0xff); break; - case 6<<8: MOVLLG(opcode & 0xff); break; - case 7<<8: MOVA(opcode & 0xff); break; - case 8<<8: TSTI(opcode & 0xff); break; - case 9<<8: ANDI(opcode & 0xff); break; - case 10<<8: XORI(opcode & 0xff); break; - case 11<<8: ORI(opcode & 0xff); break; - case 12<<8: TSTM(opcode & 0xff); break; - case 13<<8: ANDM(opcode & 0xff); break; - case 14<<8: XORM(opcode & 0xff); break; - case 15<<8: ORM(opcode & 0xff); break; - } -} - -void sh2_device::op1101(uint16_t opcode) -{ - MOVLI(opcode & 0xff, Rn); -} - -void sh2_device::op1110(uint16_t opcode) -{ - MOVI(opcode & 0xff, Rn); -} - -void sh2_device::op1111(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_delay = m_cpu_off = 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_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; - - memset(m_m, 0, 0x200); - - m_sh2_state->pc = RL(0); - m_sh2_state->r[15] = RL(4); - m_sh2_state->sr = 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 ) - { - execute_run_drc(); - return; - } - - if (m_cpu_off) - { - m_sh2_state->icount = 0; - return; - } - - // run any active DMAs now -#ifndef USE_TIMER_FOR_DMA - for ( int i = 0; i < m_sh2_state->icount ; i++) - { - for( int dma=0;dma<1;dma++) - { - if (m_dma_timer_active[dma]) - sh2_do_dma(dma); - } - } -#endif - - do - { - uint32_t opcode; - - debugger_instruction_hook(this, m_sh2_state->pc); - - opcode = m_program->read_word(m_sh2_state->pc & AM); - - if (m_delay) - { - m_sh2_state->pc = m_delay; - m_delay = 0; - } - else - m_sh2_state->pc += 2; - - switch (opcode & ( 15 << 12)) - { - case 0<<12: op0000(opcode); break; - case 1<<12: op0001(opcode); break; - case 2<<12: op0010(opcode); break; - case 3<<12: op0011(opcode); break; - case 4<<12: op0100(opcode); break; - case 5<<12: op0101(opcode); break; - case 6<<12: op0110(opcode); break; - case 7<<12: op0111(opcode); break; - case 8<<12: op1000(opcode); break; - case 9<<12: op1001(opcode); break; - case 10<<12: op1010(opcode); break; - case 11<<12: op1011(opcode); break; - case 12<<12: op1100(opcode); break; - case 13<<12: op1101(opcode); break; - case 14<<12: op1110(opcode); break; - default: op1111(opcode); break; - } - - if(m_test_irq && !m_delay) - { - CHECK_PENDING_IRQ("mame_sh2_execute"); - m_test_irq = 0; - } - m_sh2_state->icount--; - } while( m_sh2_state->icount > 0 ); -} - -void sh2_device::device_start() -{ - /* allocate the implementation-specific state from the full cache */ - m_sh2_state = (internal_sh2_state *)m_cache.alloc_near(sizeof(internal_sh2_state)); - - 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_program = &space(AS_PROGRAM); - m_decrypted_program = has_space(AS_OPCODES) ? &space(AS_OPCODES) : &space(AS_PROGRAM); - m_direct = &m_decrypted_program->direct(); - m_internal = &space(AS_PROGRAM); - - save_item(NAME(m_sh2_state->pc)); - save_item(NAME(m_sh2_state->sr)); - save_item(NAME(m_sh2_state->pr)); - save_item(NAME(m_sh2_state->gbr)); - save_item(NAME(m_sh2_state->vbr)); - save_item(NAME(m_sh2_state->mach)); - save_item(NAME(m_sh2_state->macl)); - save_item(NAME(m_sh2_state->r)); - save_item(NAME(m_sh2_state->ea)); - save_item(NAME(m_delay)); - save_item(NAME(m_cpu_off)); - save_item(NAME(m_dvsr)); - save_item(NAME(m_dvdnth)); - save_item(NAME(m_dvdntl)); - save_item(NAME(m_dvcr)); - save_item(NAME(m_sh2_state->pending_irq)); - save_item(NAME(m_test_irq)); - save_item(NAME(m_sh2_state->pending_nmi)); - save_item(NAME(m_sh2_state->irqline)); - save_item(NAME(m_sh2_state->evec)); - save_item(NAME(m_sh2_state->irqsr)); - save_item(NAME(m_sh2_state->target)); - 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); - } - save_item(NAME(m_pcfsel)); - save_item(NAME(m_maxpcfsel)); - save_item(NAME(m_pcflushes)); - save_item(NAME(m_irq_line_state)); - save_item(NAME(m_m)); - save_item(NAME(m_nmi_line_state)); - save_item(NAME(m_frc)); - save_item(NAME(m_ocra)); - save_item(NAME(m_ocrb)); - save_item(NAME(m_icr)); - save_item(NAME(m_frc_base)); - save_item(NAME(m_frt_input)); - save_item(NAME(m_sh2_state->internal_irq_level)); - save_item(NAME(m_internal_irq_vector)); - save_item(NAME(m_dma_timer_active)); - save_item(NAME(m_dma_irq)); - save_item(NAME(m_wtcnt)); - save_item(NAME(m_wtcsr)); - save_item(NAME(m_sh2_state->sleep_mode)); - - state_add( STATE_GENPC, "PC", m_sh2_state->pc).mask(AM).callimport(); - state_add( SH2_SR, "SR", m_sh2_state->sr).callimport().formatstr("%08X"); - state_add( SH2_PR, "PR", m_sh2_state->pr).formatstr("%08X"); - state_add( SH2_GBR, "GBR", m_sh2_state->gbr).formatstr("%08X"); - state_add( SH2_VBR, "VBR", m_sh2_state->vbr).formatstr("%08X"); - state_add( SH2_MACH, "MACH", m_sh2_state->mach).formatstr("%08X"); - state_add( SH2_MACL, "MACL", m_sh2_state->macl).formatstr("%08X"); - state_add( SH2_R0, "R0", m_sh2_state->r[ 0]).formatstr("%08X"); - state_add( SH2_R1, "R1", m_sh2_state->r[ 1]).formatstr("%08X"); - state_add( SH2_R2, "R2", m_sh2_state->r[ 2]).formatstr("%08X"); - state_add( SH2_R3, "R3", m_sh2_state->r[ 3]).formatstr("%08X"); - state_add( SH2_R4, "R4", m_sh2_state->r[ 4]).formatstr("%08X"); - state_add( SH2_R5, "R5", m_sh2_state->r[ 5]).formatstr("%08X"); - state_add( SH2_R6, "R6", m_sh2_state->r[ 6]).formatstr("%08X"); - state_add( SH2_R7, "R7", m_sh2_state->r[ 7]).formatstr("%08X"); - state_add( SH2_R8, "R8", m_sh2_state->r[ 8]).formatstr("%08X"); - state_add( SH2_R9, "R9", m_sh2_state->r[ 9]).formatstr("%08X"); - state_add( SH2_R10, "R10", m_sh2_state->r[10]).formatstr("%08X"); - state_add( SH2_R11, "R11", m_sh2_state->r[11]).formatstr("%08X"); - state_add( SH2_R12, "R12", m_sh2_state->r[12]).formatstr("%08X"); - state_add( SH2_R13, "R13", m_sh2_state->r[13]).formatstr("%08X"); - state_add( SH2_R14, "R14", m_sh2_state->r[14]).formatstr("%08X"); - state_add( SH2_R15, "R15", m_sh2_state->r[15]).formatstr("%08X"); - state_add( SH2_EA, "EA", m_sh2_state->ea).formatstr("%08X"); - - state_add( STATE_GENPCBASE, "CURPC", m_sh2_state->pc ).callimport().noshow(); - state_add( STATE_GENSP, "GENSP", m_sh2_state->r[15] ).noshow(); - state_add( STATE_GENFLAGS, "GENFLAGS", m_sh2_state->sr ).formatstr("%6s").noshow(); - - m_icountptr = &m_sh2_state->icount; - - // Clear state - m_sh2_state->pc = 0; - m_sh2_state->pr = 0; - m_sh2_state->sr = 0; - m_sh2_state->gbr = 0; - m_sh2_state->vbr = 0; - m_sh2_state->mach = 0; - m_sh2_state->macl = 0; - memset(m_sh2_state->r, 0, sizeof(m_sh2_state->r)); - m_sh2_state->ea = 0; - m_delay = 0; - m_cpu_off = 0; - m_dvsr = 0; - m_dvdnth = 0; - m_dvdntl = 0; - m_dvcr = 0; - m_sh2_state->pending_irq = 0; - m_test_irq = 0; - m_sh2_state->pending_nmi = 0; - m_sh2_state->irqline = 0; - m_sh2_state->evec = 0; - m_sh2_state->irqsr = 0; - m_sh2_state->target = 0; - memset(m_irq_queue, 0, sizeof(m_irq_queue)); - m_maxpcfsel = 0; - memset(m_pcflushes, 0, sizeof(m_pcflushes)); - memset(m_irq_line_state, 0, sizeof(m_irq_line_state)); - memset(m_m, 0, sizeof(m_m)); - m_nmi_line_state = 0; - m_frc = 0; - m_ocra = 0; - m_ocrb = 0; - m_icr = 0; - m_frc_base = 0; - m_frt_input = 0; - m_sh2_state->internal_irq_level = 0; - m_internal_irq_vector = 0; - m_sh2_state->icount = 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; - m_sh2_state->sleep_mode = 0; - m_numcycles = 0; - m_sh2_state->arg0 = 0; - m_arg1 = 0; - m_irq = 0; - m_fastram_select = 0; - memset(m_fastram, 0, sizeof(m_fastram)); - - /* reset per-driver pcflushes */ - m_pcfsel = 0; - - /* initialize the UML generator */ - uint32_t flags = 0; - m_drcuml = std::make_unique(*this, m_cache, flags, 1, 32, 1); - - /* add symbols for our stuff */ - m_drcuml->symbol_add(&m_sh2_state->pc, sizeof(m_sh2_state->pc), "pc"); - m_drcuml->symbol_add(&m_sh2_state->icount, sizeof(m_sh2_state->icount), "icount"); - for (int regnum = 0; regnum < 16; regnum++) - { - char buf[10]; - sprintf(buf, "r%d", regnum); - m_drcuml->symbol_add(&m_sh2_state->r[regnum], sizeof(m_sh2_state->r[regnum]), buf); - } - m_drcuml->symbol_add(&m_sh2_state->pr, sizeof(m_sh2_state->pr), "pr"); - m_drcuml->symbol_add(&m_sh2_state->sr, sizeof(m_sh2_state->sr), "sr"); - m_drcuml->symbol_add(&m_sh2_state->gbr, sizeof(m_sh2_state->gbr), "gbr"); - m_drcuml->symbol_add(&m_sh2_state->vbr, sizeof(m_sh2_state->vbr), "vbr"); - m_drcuml->symbol_add(&m_sh2_state->macl, sizeof(m_sh2_state->macl), "macl"); - m_drcuml->symbol_add(&m_sh2_state->mach, sizeof(m_sh2_state->macl), "mach"); - - /* initialize the front-end helper */ - m_drcfe = std::make_unique(this, COMPILE_BACKWARDS_BYTES, COMPILE_FORWARDS_BYTES, SINGLE_INSTRUCTION_MODE ? 1 : COMPILE_MAX_SEQUENCE); - - /* compute the register parameters */ - for (int regnum = 0; regnum < 16; regnum++) - { - m_regmap[regnum] = uml::mem(&m_sh2_state->r[regnum]); - } - - /* if we have registers to spare, assign r0, r1, r2 to leftovers */ - /* WARNING: do not use synthetic registers that are mapped here! */ - if (!DISABLE_FAST_REGISTERS) - { - drcbe_info beinfo; - m_drcuml->get_backend_info(beinfo); - if (beinfo.direct_iregs > 4) - { - m_regmap[0] = uml::I4; - } - if (beinfo.direct_iregs > 5) - { - m_regmap[1] = uml::I5; - } - if (beinfo.direct_iregs > 6) - { - m_regmap[2] = uml::I6; - } - } - - /* mark the cache dirty so it is updated on next execute */ - m_cache_dirty = true; -} - - -void sh2_device::state_string_export(const device_state_entry &entry, std::string &str) const -{ - switch (entry.index()) - { - case STATE_GENFLAGS: - str = string_format("%c%c%d%c%c", - m_sh2_state->sr & M ? 'M':'.', - m_sh2_state->sr & Q ? 'Q':'.', - (m_sh2_state->sr & I) >> 4, - m_sh2_state->sr & S ? 'S':'.', - m_sh2_state->sr & T ? 'T':'.'); - break; - } -} - - -void sh2_device::state_import(const device_state_entry &entry) -{ - switch (entry.index()) - { - case STATE_GENPC: - case STATE_GENPCBASE: - m_delay = 0; - break; - - case SH2_SR: - 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"); - } - else - { - LOG("SH-2 asserted nmi\n"); - - sh2_exception("Set IRQ line", 16); - - if (m_isdrc) - m_sh2_state->pending_nmi = 1; - } - } - else - { - if (m_irq_line_state[irqline] == state) - return; - m_irq_line_state[irqline] = state; - - if (state == CLEAR_LINE) - { - LOG("SH-2 cleared irq #%d\n", irqline); - m_sh2_state->pending_irq &= ~(1 << irqline); - } - else - { - 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_delay) - m_test_irq = 1; - else - CHECK_PENDING_IRQ("sh2_set_irq_line"); - } - } - } -} - -void sh2_device::sh2_exception(const char *message, int irqline) -{ - int vector; - - if (irqline != 16) - { - if (irqline <= ((m_sh2_state->sr >> 4) & 15)) /* If the cpu forbids this interrupt */ - return; - - // if this is an sh2 internal irq, use its vector - if (m_sh2_state->internal_irq_level == irqline) - { - vector = m_internal_irq_vector; - /* avoid spurious irqs with this (TODO: needs a better fix) */ - m_sh2_state->internal_irq_level = -1; - LOG("SH-2 exception #%d (internal vector: $%x) after [%s]\n", irqline, vector, message); - } - else - { - if(m_m[0x38] & 0x00010000) - { - 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); - } - } - } - else - { - vector = 11; - LOG("SH-2 nmi exception (autovector: $%x) after [%s]\n", vector, message); - } - - if (m_isdrc) - { - m_sh2_state->evec = RL( m_sh2_state->vbr + vector * 4 ); - m_sh2_state->evec &= AM; - m_sh2_state->irqsr = m_sh2_state->sr; - - /* set I flags in SR */ - if (irqline > SH2_INT_15) - m_sh2_state->sr = m_sh2_state->sr | I; - else - m_sh2_state->sr = (m_sh2_state->sr & ~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 { - m_sh2_state->r[15] -= 4; - WL( 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 */ - - /* set I flags in SR */ - if (irqline > SH2_INT_15) - m_sh2_state->sr = m_sh2_state->sr | I; - else - m_sh2_state->sr = (m_sh2_state->sr & ~I) | (irqline << 4); - - /* fetch PC */ - m_sh2_state->pc = RL( m_sh2_state->vbr + vector * 4 ); - } - - if(m_sh2_state->sleep_mode == 1) { m_sh2_state->sleep_mode = 2; } -} - -#include "sh2drc.cpp" diff --git a/src/devices/cpu/superh/sh2.h b/src/devices/cpu/superh/sh2.h deleted file mode 100644 index 50ecf680c88..00000000000 --- a/src/devices/cpu/superh/sh2.h +++ /dev/null @@ -1,557 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Juergen Buchmueller -/***************************************************************************** - * - * sh2.h - * Portable Hitachi SH-2 (SH7600 family) emulator interface - * - * This work is based on C/C++ implementation of - * the SH-2 CPU core and was heavily changed to the MAME CPU requirements. - * Thanks also go to Chuck Mason and Olivier Galibert - * for letting me peek into their SEMU code :-) - * - *****************************************************************************/ - -#ifndef MAME_CPU_SH2_SH2_H -#define MAME_CPU_SH2_SH2_H - -#pragma once - -#include "cpu/drcfe.h" -#include "cpu/drcuml.h" - - -#define SH2_INT_NONE -1 -#define SH2_INT_VBLIN 0 -#define SH2_INT_VBLOUT 1 -#define SH2_INT_HBLIN 2 -#define SH2_INT_TIMER0 3 -#define SH2_INT_TIMER1 4 -#define SH2_INT_DSP 5 -#define SH2_INT_SOUND 6 -#define SH2_INT_SMPC 7 -#define SH2_INT_PAD 8 -#define SH2_INT_DMA2 9 -#define SH2_INT_DMA1 10 -#define SH2_INT_DMA0 11 -#define SH2_INT_DMAILL 12 -#define SH2_INT_SPRITE 13 -#define SH2_INT_14 14 -#define SH2_INT_15 15 -#define SH2_INT_ABUS 16 - -enum -{ - SH2_PC = STATE_GENPC, SH2_SR=1, SH2_PR, SH2_GBR, SH2_VBR, SH2_MACH, SH2_MACL, - SH2_R0, SH2_R1, SH2_R2, SH2_R3, SH2_R4, SH2_R5, SH2_R6, SH2_R7, - SH2_R8, SH2_R9, SH2_R10, SH2_R11, SH2_R12, SH2_R13, SH2_R14, SH2_R15, SH2_EA -}; - - -#define SH2_DMA_KLUDGE_CB(name) int name(uint32_t src, uint32_t dst, uint32_t data, int size) - -#define SH2_DMA_FIFO_DATA_AVAILABLE_CB(name) int name(uint32_t src, uint32_t dst, uint32_t data, int size) - -#define SH2_FTCSR_READ_CB(name) void name(uint32_t data) - - -#define MCFG_SH2_IS_SLAVE(_slave) \ - sh2_device::set_is_slave(*device, _slave); - -#define MCFG_SH2_DMA_KLUDGE_CB(_class, _method) \ - sh2_device::set_dma_kludge_callback(*device, sh2_device::dma_kludge_delegate(&_class::_method, #_class "::" #_method, downcast<_class *>(owner))); - -#define MCFG_SH2_FIFO_DATA_AVAIL_CB(_class, _method) \ - sh2_device::set_dma_fifo_data_available_callback(*device, sh2_device::dma_fifo_data_available_delegate(&_class::_method, #_class "::" #_method, downcast<_class *>(owner))); - -#define MCFG_SH2_FTCSR_READ_CB(_class, _method) \ - sh2_device::set_ftcsr_read_callback(*device, sh2_device::ftcsr_read_delegate(&_class::_method, #_class "::" #_method, downcast<_class *>(owner))); - - -/*************************************************************************** - COMPILER-SPECIFIC OPTIONS -***************************************************************************/ - -#define SH2DRC_STRICT_VERIFY 0x0001 /* verify all instructions */ -#define SH2DRC_FLUSH_PC 0x0002 /* flush the PC value before each memory access */ -#define SH2DRC_STRICT_PCREL 0x0004 /* do actual loads on MOVLI/MOVWI instead of collapsing to immediates */ - -#define SH2DRC_COMPATIBLE_OPTIONS (SH2DRC_STRICT_VERIFY | SH2DRC_FLUSH_PC | SH2DRC_STRICT_PCREL) -#define SH2DRC_FASTEST_OPTIONS (0) - -#define SH2_MAX_FASTRAM 4 - -class sh2_frontend; - -class sh2_device : public cpu_device -{ - friend class sh2_frontend; - -public: - typedef device_delegate dma_kludge_delegate; - typedef device_delegate dma_fifo_data_available_delegate; - typedef device_delegate ftcsr_read_delegate; - - // construction/destruction - sh2_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); - - static void set_is_slave(device_t &device, int slave) { downcast(device).m_is_slave = slave; } - static void set_dma_kludge_callback(device_t &device, dma_kludge_delegate callback) { downcast(device).m_dma_kludge_cb = callback; } - static void set_dma_fifo_data_available_callback(device_t &device, dma_fifo_data_available_delegate callback) { downcast(device).m_dma_fifo_data_available_cb = callback; } - static void set_ftcsr_read_callback(device_t &device, ftcsr_read_delegate callback) { downcast(device).m_ftcsr_read_cb = callback; } - - DECLARE_WRITE32_MEMBER( sh7604_w ); - DECLARE_READ32_MEMBER( sh7604_r ); - DECLARE_READ32_MEMBER(sh2_internal_a5); - - void sh2_set_frt_input(int state); - void sh2drc_set_options(uint32_t options); - void sh2drc_add_pcflush(offs_t address); - void sh2drc_add_fastram(offs_t start, offs_t end, uint8_t readonly, void *base); - - void sh2_notify_dma_data_available(); - -protected: - 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); - - // device-level overrides - virtual void device_start() override; - virtual void device_reset() override; - virtual void device_stop() override; - - // device_execute_interface overrides - virtual uint32_t execute_min_cycles() const override { return 1; } - virtual uint32_t execute_max_cycles() const override { return 4; } - virtual uint32_t execute_input_lines() const override { return 16; } - virtual uint32_t execute_default_irq_vector() const override { return 0; } - virtual void execute_run() override; - virtual void execute_set_input(int inputnum, int state) override; - - // device_memory_interface overrides - virtual space_config_vector memory_space_config() const override; - - // device_state_interface overrides - virtual void state_import(const device_state_entry &entry) override; - virtual void state_string_export(const device_state_entry &entry, std::string &str) const override; - - // device_disasm_interface overrides - virtual uint32_t disasm_min_opcode_bytes() const override { return 2; } - virtual uint32_t disasm_max_opcode_bytes() const override { return 2; } - virtual offs_t disasm_disassemble(std::ostream &stream, offs_t pc, const uint8_t *oprom, const uint8_t *opram, uint32_t options) override; - address_space *m_program, *m_decrypted_program; - -private: - address_space_config m_program_config, m_decrypted_program_config; - - // Data that needs to be stored close to the generated DRC code - struct internal_sh2_state - { - uint32_t pc; - uint32_t pr; - uint32_t sr; - uint32_t gbr; - uint32_t vbr; - uint32_t mach; - uint32_t macl; - uint32_t r[16]; - uint32_t ea; - uint32_t pending_irq; - uint32_t pending_nmi; - int32_t irqline; - uint32_t evec; // exception vector for DRC - uint32_t irqsr; // IRQ-time old SR for DRC - uint32_t target; // target for jmp/jsr/etc so the delay slot can't kill it - int internal_irq_level; - int icount; - uint8_t sleep_mode; - uint32_t arg0; /* print_debug argument 1 */ - }; - - uint32_t m_delay; - uint32_t m_cpu_off; - uint32_t m_dvsr, m_dvdnth, m_dvdntl, m_dvcr; - uint32_t m_test_irq; - struct - { - int irq_vector; - int irq_priority; - } m_irq_queue[16]; - - bool m_isdrc; - - int m_pcfsel; // last pcflush entry set - int m_maxpcfsel; // highest valid pcflush entry - uint32_t m_pcflushes[16]; // pcflush entries - - int8_t m_irq_line_state[17]; -protected: - direct_read_data *m_direct; -private: - address_space *m_internal; - uint32_t m_m[0x200/4]; - int8_t m_nmi_line_state; - - uint16_t m_frc; - uint16_t m_ocra, m_ocrb, m_icr; - uint64_t m_frc_base; - - int m_frt_input; - int m_internal_irq_vector; - - emu_timer *m_timer; - emu_timer *m_dma_current_active_timer[2]; - int m_dma_timer_active[2]; - uint8_t m_dma_irq[2]; - - int m_active_dma_incs[2]; - int m_active_dma_incd[2]; - int m_active_dma_size[2]; - int m_active_dma_steal[2]; - uint32_t m_active_dma_src[2]; - uint32_t m_active_dma_dst[2]; - uint32_t m_active_dma_count[2]; - uint16_t m_wtcnt; - uint8_t m_wtcsr; - - int m_is_slave, m_cpu_type; - dma_kludge_delegate m_dma_kludge_cb; - dma_fifo_data_available_delegate m_dma_fifo_data_available_cb; - ftcsr_read_delegate m_ftcsr_read_cb; - - drc_cache m_cache; /* pointer to the DRC code cache */ - std::unique_ptr m_drcuml; /* DRC UML generator state */ - std::unique_ptr m_drcfe; /* pointer to the DRC front-end state */ - uint32_t m_drcoptions; /* configurable DRC options */ - - internal_sh2_state *m_sh2_state; - - /* internal stuff */ - uint8_t m_cache_dirty; /* true if we need to flush the cache */ - - /* parameters for subroutines */ - uint64_t m_numcycles; /* return value from gettotalcycles */ - uint32_t m_arg1; /* print_debug argument 2 */ - uint32_t m_irq; /* irq we're taking */ - - /* register mappings */ - uml::parameter m_regmap[16]; /* parameter to register mappings for all 16 integer registers */ - - uml::code_handle * m_entry; /* entry point */ - uml::code_handle * m_read8; /* read byte */ - uml::code_handle * m_write8; /* write byte */ - uml::code_handle * m_read16; /* read half */ - uml::code_handle * m_write16; /* write half */ - uml::code_handle * m_read32; /* read word */ - uml::code_handle * m_write32; /* write word */ - - uml::code_handle * m_interrupt; /* interrupt */ - uml::code_handle * m_nocode; /* nocode */ - uml::code_handle * m_out_of_cycles; /* out of cycles exception handler */ - - /* fast RAM */ - uint32_t m_fastram_select; - struct - { - offs_t start; /* start of the RAM block */ - offs_t end; /* end of the RAM block */ - bool readonly; /* true if read-only */ - void * base; /* base in memory where the RAM lives */ - } m_fastram[SH2_MAX_FASTRAM]; - - uint32_t m_debugger_temp; - - inline uint8_t RB(offs_t A); - inline uint16_t RW(offs_t A); - inline uint32_t RL(offs_t A); - inline void WB(offs_t A, uint8_t V); - inline void WW(offs_t A, uint16_t V); - inline void WL(offs_t A, uint32_t V); - inline void ADD(uint32_t m, uint32_t n); - inline void ADDI(uint32_t i, uint32_t n); - inline void ADDC(uint32_t m, uint32_t n); - inline void ADDV(uint32_t m, uint32_t n); - inline void AND(uint32_t m, uint32_t n); - inline void ANDI(uint32_t i); - inline void ANDM(uint32_t i); - inline void BF(uint32_t d); - inline void BFS(uint32_t d); - inline void BRA(uint32_t d); - inline void BRAF(uint32_t m); - inline void BSR(uint32_t d); - inline void BSRF(uint32_t m); - inline void BT(uint32_t d); - inline void BTS(uint32_t d); - inline void CLRMAC(); - inline void CLRT(); - inline void CMPEQ(uint32_t m, uint32_t n); - inline void CMPGE(uint32_t m, uint32_t n); - inline void CMPGT(uint32_t m, uint32_t n); - inline void CMPHI(uint32_t m, uint32_t n); - inline void CMPHS(uint32_t m, uint32_t n); - inline void CMPPL(uint32_t n); - inline void CMPPZ(uint32_t n); - inline void CMPSTR(uint32_t m, uint32_t n); - inline void CMPIM(uint32_t i); - inline void DIV0S(uint32_t m, uint32_t n); - inline void DIV0U(); - inline void DIV1(uint32_t m, uint32_t n); - inline void DMULS(uint32_t m, uint32_t n); - inline void DMULU(uint32_t m, uint32_t n); - inline void DT(uint32_t n); - inline void EXTSB(uint32_t m, uint32_t n); - inline void EXTSW(uint32_t m, uint32_t n); - inline void EXTUB(uint32_t m, uint32_t n); - inline void EXTUW(uint32_t m, uint32_t n); - inline void ILLEGAL(); - inline void JMP(uint32_t m); - inline void JSR(uint32_t m); - inline void LDCSR(uint32_t m); - inline void LDCGBR(uint32_t m); - inline void LDCVBR(uint32_t m); - inline void LDCMSR(uint32_t m); - inline void LDCMGBR(uint32_t m); - inline void LDCMVBR(uint32_t m); - inline void LDSMACH(uint32_t m); - inline void LDSMACL(uint32_t m); - inline void LDSPR(uint32_t m); - inline void LDSMMACH(uint32_t m); - inline void LDSMMACL(uint32_t m); - inline void LDSMPR(uint32_t m); - inline void MAC_L(uint32_t m, uint32_t n); - inline void MAC_W(uint32_t m, uint32_t n); - inline void MOV(uint32_t m, uint32_t n); - inline void MOVBS(uint32_t m, uint32_t n); - inline void MOVWS(uint32_t m, uint32_t n); - inline void MOVLS(uint32_t m, uint32_t n); - inline void MOVBL(uint32_t m, uint32_t n); - inline void MOVWL(uint32_t m, uint32_t n); - inline void MOVLL(uint32_t m, uint32_t n); - inline void MOVBM(uint32_t m, uint32_t n); - inline void MOVWM(uint32_t m, uint32_t n); - inline void MOVLM(uint32_t m, uint32_t n); - inline void MOVBP(uint32_t m, uint32_t n); - inline void MOVWP(uint32_t m, uint32_t n); - inline void MOVLP(uint32_t m, uint32_t n); - inline void MOVBS0(uint32_t m, uint32_t n); - inline void MOVWS0(uint32_t m, uint32_t n); - inline void MOVLS0(uint32_t m, uint32_t n); - inline void MOVBL0(uint32_t m, uint32_t n); - inline void MOVWL0(uint32_t m, uint32_t n); - inline void MOVLL0(uint32_t m, uint32_t n); - inline void MOVI(uint32_t i, uint32_t n); - inline void MOVWI(uint32_t d, uint32_t n); - inline void MOVLI(uint32_t d, uint32_t n); - inline void MOVBLG(uint32_t d); - inline void MOVWLG(uint32_t d); - inline void MOVLLG(uint32_t d); - inline void MOVBSG(uint32_t d); - inline void MOVWSG(uint32_t d); - inline void MOVLSG(uint32_t d); - inline void MOVBS4(uint32_t d, uint32_t n); - inline void MOVWS4(uint32_t d, uint32_t n); - inline void MOVLS4(uint32_t m, uint32_t d, uint32_t n); - inline void MOVBL4(uint32_t m, uint32_t d); - inline void MOVWL4(uint32_t m, uint32_t d); - inline void MOVLL4(uint32_t m, uint32_t d, uint32_t n); - inline void MOVA(uint32_t d); - inline void MOVT(uint32_t n); - inline void MULL(uint32_t m, uint32_t n); - inline void MULS(uint32_t m, uint32_t n); - inline void MULU(uint32_t m, uint32_t n); - inline void NEG(uint32_t m, uint32_t n); - inline void NEGC(uint32_t m, uint32_t n); - inline void NOP(void); - inline void NOT(uint32_t m, uint32_t n); - inline void OR(uint32_t m, uint32_t n); - inline void ORI(uint32_t i); - inline void ORM(uint32_t i); - inline void ROTCL(uint32_t n); - inline void ROTCR(uint32_t n); - inline void ROTL(uint32_t n); - inline void ROTR(uint32_t n); - inline void RTE(); - inline void RTS(); - inline void SETT(); - inline void SHAL(uint32_t n); - inline void SHAR(uint32_t n); - inline void SHLL(uint32_t n); - inline void SHLL2(uint32_t n); - inline void SHLL8(uint32_t n); - inline void SHLL16(uint32_t n); - inline void SHLR(uint32_t n); - inline void SHLR2(uint32_t n); - inline void SHLR8(uint32_t n); - inline void SHLR16(uint32_t n); - inline void SLEEP(); - inline void STCSR(uint32_t n); - inline void STCGBR(uint32_t n); - inline void STCVBR(uint32_t n); - inline void STCMSR(uint32_t n); - inline void STCMGBR(uint32_t n); - inline void STCMVBR(uint32_t n); - inline void STSMACH(uint32_t n); - inline void STSMACL(uint32_t n); - inline void STSPR(uint32_t n); - inline void STSMMACH(uint32_t n); - inline void STSMMACL(uint32_t n); - inline void STSMPR(uint32_t n); - inline void SUB(uint32_t m, uint32_t n); - inline void SUBC(uint32_t m, uint32_t n); - inline void SUBV(uint32_t m, uint32_t n); - inline void SWAPB(uint32_t m, uint32_t n); - inline void SWAPW(uint32_t m, uint32_t n); - inline void TAS(uint32_t n); - inline void TRAPA(uint32_t i); - inline void TST(uint32_t m, uint32_t n); - inline void TSTI(uint32_t i); - inline void TSTM(uint32_t i); - inline void XOR(uint32_t m, uint32_t n); - inline void XORI(uint32_t i); - inline void XORM(uint32_t i); - inline void XTRCT(uint32_t m, uint32_t n); - inline void op0000(uint16_t opcode); - inline void op0001(uint16_t opcode); - inline void op0010(uint16_t opcode); - inline void op0011(uint16_t opcode); - inline void op0100(uint16_t opcode); - inline void op0101(uint16_t opcode); - inline void op0110(uint16_t opcode); - inline void op0111(uint16_t opcode); - inline void op1000(uint16_t opcode); - inline void op1001(uint16_t opcode); - inline void op1010(uint16_t opcode); - inline void op1011(uint16_t opcode); - inline void op1100(uint16_t opcode); - inline void op1101(uint16_t opcode); - inline void op1110(uint16_t opcode); - inline void op1111(uint16_t opcode); - TIMER_CALLBACK_MEMBER( sh2_timer_callback ); - TIMER_CALLBACK_MEMBER( sh2_dma_current_active_callback ); - void sh2_timer_resync(); - void sh2_timer_activate(); - void sh2_do_dma(int dma); - void sh2_exception(const char *message, int irqline); - void sh2_dmac_check(int dma); - void sh2_recalc_irq(); - - /* internal compiler state */ - struct compiler_state - { - uint32_t cycles; /* accumulated cycles */ - uint8_t checkints; /* need to check interrupts before next instruction */ - uml::code_label labelnum; /* index for local labels */ - }; - - inline uint32_t epc(const opcode_desc *desc); - inline void alloc_handle(drcuml_state *drcuml, uml::code_handle **handleptr, const char *name); - inline void load_fast_iregs(drcuml_block *block); - inline void save_fast_iregs(drcuml_block *block); - - void code_flush_cache(); - void execute_run_drc(); - void code_compile_block(uint8_t mode, offs_t pc); - void static_generate_entry_point(); - void static_generate_nocode_handler(); - void static_generate_out_of_cycles(); - void static_generate_memory_accessor(int size, int iswrite, const char *name, uml::code_handle **handleptr); - const char *log_desc_flags_to_string(uint32_t flags); - void log_register_list(drcuml_state *drcuml, const char *string, const uint32_t *reglist, const uint32_t *regnostarlist); - void log_opcode_desc(drcuml_state *drcuml, const opcode_desc *desclist, int indent); - void log_add_disasm_comment(drcuml_block *block, uint32_t pc, uint32_t op); - void generate_update_cycles(drcuml_block *block, compiler_state *compiler, uml::parameter param, bool allow_exception); - void generate_checksum_block(drcuml_block *block, compiler_state *compiler, const opcode_desc *seqhead, const opcode_desc *seqlast); - void generate_sequence_instruction(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint32_t ovrpc); - void generate_delay_slot(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint32_t ovrpc); - bool generate_opcode(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint32_t ovrpc); - bool generate_group_0(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc); - bool generate_group_2(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc); - bool generate_group_3(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, uint32_t ovrpc); - bool generate_group_4(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc); - bool generate_group_6(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc); - bool generate_group_8(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc); - bool generate_group_12(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc); - -public: - void func_printf_probe(); - void func_unimplemented(); - void func_fastirq(); - void func_MAC_W(); - void func_MAC_L(); - void func_DIV1(); - void func_ADDV(); - void func_SUBV(); -}; - -class sh2a_device : public sh2_device -{ -public: - // construction/destruction - sh2a_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); - - DECLARE_READ32_MEMBER(dma_sar0_r); - DECLARE_WRITE32_MEMBER(dma_sar0_w); - DECLARE_READ32_MEMBER(dma_dar0_r); - DECLARE_WRITE32_MEMBER(dma_dar0_w); - DECLARE_READ16_MEMBER(dmaor_r); - DECLARE_WRITE16_MEMBER(dmaor_w); - DECLARE_READ16_MEMBER(dma_tcr0_r); - DECLARE_WRITE16_MEMBER(dma_tcr0_w); - DECLARE_READ16_MEMBER(dma_chcr0_r); - DECLARE_WRITE16_MEMBER(dma_chcr0_w); - DECLARE_READ16_MEMBER(sh7021_r); - DECLARE_WRITE16_MEMBER(sh7021_w); - void sh7032_dma_exec(int ch); - -private: - uint16_t m_sh7021_regs[0x200]; - struct - { - uint32_t sar; /**< Source Address Register */ - uint32_t dar; /**< Destination Address Register */ - uint16_t tcr; /**< Transfer Count Register */ - uint16_t chcr; /**< Channel Control Register */ - } m_dma[4]; - uint16_t m_dmaor; /**< DMA Operation Register (status flags) */ - -}; - -class sh1_device : public sh2_device -{ -public: - // construction/destruction - sh1_device(const machine_config &mconfig, const char *_tag, device_t *_owner, uint32_t _clock); - - DECLARE_READ16_MEMBER(sh7032_r); - DECLARE_WRITE16_MEMBER(sh7032_w); -private: - uint16_t m_sh7032_regs[0x200]; -}; - - -class sh2_frontend : public drc_frontend -{ -public: - sh2_frontend(sh2_device *device, uint32_t window_start, uint32_t window_end, uint32_t max_sequence); - -protected: - virtual bool describe(opcode_desc &desc, const opcode_desc *prev) override; - -private: - bool describe_group_0(opcode_desc &desc, const opcode_desc *prev, uint16_t opcode); - bool describe_group_2(opcode_desc &desc, const opcode_desc *prev, uint16_t opcode); - bool describe_group_3(opcode_desc &desc, const opcode_desc *prev, uint16_t opcode); - bool describe_group_4(opcode_desc &desc, const opcode_desc *prev, uint16_t opcode); - bool describe_group_6(opcode_desc &desc, const opcode_desc *prev, uint16_t opcode); - bool describe_group_8(opcode_desc &desc, const opcode_desc *prev, uint16_t opcode); - bool describe_group_12(opcode_desc &desc, const opcode_desc *prev, uint16_t opcode); - - sh2_device *m_sh2; -}; - - -DECLARE_DEVICE_TYPE(SH1, sh1_device) -DECLARE_DEVICE_TYPE(SH2, sh2_device) -DECLARE_DEVICE_TYPE(SH2A, sh2a_device) - - -#endif // MAME_CPU_SH2_SH2_H diff --git a/src/devices/cpu/superh/sh2comn.cpp b/src/devices/cpu/superh/sh2comn.cpp deleted file mode 100644 index b6ac0e1cc65..00000000000 --- a/src/devices/cpu/superh/sh2comn.cpp +++ /dev/null @@ -1,946 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:R. Belmont -/***************************************************************************** - * - * sh2common.c - * - * SH-2 non-specific components - * - *****************************************************************************/ - -#include "emu.h" -#include "sh2.h" -#include "sh2comn.h" - -#include "debugger.h" - -//#define VERBOSE 1 -#include "logmacro.h" - -static const int div_tab[4] = { 3, 5, 7, 0 }; - - -void sh2_device::sh2_timer_resync() -{ - int divider = div_tab[(m_m[5] >> 8) & 3]; - uint64_t cur_time = total_cycles(); - uint64_t add = (cur_time - m_frc_base) >> divider; - - if (add > 0) - { - if(divider) - m_frc += add; - - m_frc_base = cur_time; - } -} - -void sh2_device::sh2_timer_activate() -{ - int max_delta = 0xfffff; - uint16_t frc; - - m_timer->adjust(attotime::never); - - frc = m_frc; - if(!(m_m[4] & OCFA)) { - uint16_t delta = m_ocra - frc; - if(delta < max_delta) - max_delta = delta; - } - - if(!(m_m[4] & OCFB) && (m_ocra <= m_ocrb || !(m_m[4] & 0x010000))) { - uint16_t delta = m_ocrb - frc; - if(delta < max_delta) - max_delta = delta; - } - - if(!(m_m[4] & OVF) && !(m_m[4] & 0x010000)) { - int delta = 0x10000 - frc; - if(delta < max_delta) - max_delta = delta; - } - - if(max_delta != 0xfffff) { - int divider = div_tab[(m_m[5] >> 8) & 3]; - if(divider) { - max_delta <<= divider; - m_frc_base = total_cycles(); - m_timer->adjust(cycles_to_attotime(max_delta)); - } else { - logerror("SH2.%s: Timer event in %d cycles of external clock", tag(), max_delta); - } - } -} - -TIMER_CALLBACK_MEMBER( sh2_device::sh2_timer_callback ) -{ - uint16_t frc; - - sh2_timer_resync(); - - frc = m_frc; - - if(frc == m_ocrb) - m_m[4] |= OCFB; - - if(frc == 0x0000) - m_m[4] |= OVF; - - if(frc == m_ocra) - { - m_m[4] |= OCFA; - - if(m_m[4] & 0x010000) - m_frc = 0; - } - - sh2_recalc_irq(); - sh2_timer_activate(); -} - - -/* - We have to do DMA on a timer (or at least, in chunks) due to the way some systems use it. - The 32x is a difficult case, they set the SOURCE of the DMA to a FIFO buffer, which at most - can have 8 words in it. Attempting to do an 'instant DMA' in this scenario is impossible - because the game is expecting the 68k of the system to feed data into the FIFO at the same - time as the SH2 is transfering it out via DMA - - There are two ways we can do this - - a) with a high frequency timer (more accurate, but a large performance hit) - - or - - b) in the CPU_EXECUTE loop - - - we're currently doing a) - - b) causes problems with ST-V games - -*/ - - - -void sh2_device::sh2_notify_dma_data_available() -{ - //printf("call notify\n"); - - for (int dma=0;dma<2;dma++) - { - //printf("m_dma_timer_active[dma] %04x\n",m_dma_timer_active[dma]); - - if (m_dma_timer_active[dma]==2) // 2 = stalled - { - // printf("resuming stalled dma\n"); - m_dma_timer_active[dma]=1; - m_dma_current_active_timer[dma]->adjust(attotime::zero, dma); - } - } - -} - -void sh2_device::sh2_do_dma(int dma) -{ - uint32_t dmadata; - - uint32_t tempsrc, tempdst; - - if (m_active_dma_count[dma] > 0) - { - // process current DMA - switch(m_active_dma_size[dma]) - { - case 0: - { - // we need to know the src / dest ahead of time without changing them - // to allow for the callback to check if we can process the DMA at this - // time (we need to know where we're reading / writing to/from) - - if(m_active_dma_incs[dma] == 2) - tempsrc = m_active_dma_src[dma] - 1; - else - tempsrc = m_active_dma_src[dma]; - - if(m_active_dma_incd[dma] == 2) - tempdst = m_active_dma_dst[dma] - 1; - else - tempdst = m_active_dma_dst[dma]; - - if (!m_dma_fifo_data_available_cb.isnull()) - { - int available = m_dma_fifo_data_available_cb(tempsrc, tempdst, 0, m_active_dma_size[dma]); - - if (!available) - { - //printf("dma stalled\n"); - m_dma_timer_active[dma]=2;// mark as stalled - return; - } - } - - #ifdef USE_TIMER_FOR_DMA - //schedule next DMA callback - m_dma_current_active_timer[dma]->adjust(cycles_to_attotime(2), dma); - #endif - - - dmadata = m_program->read_byte(tempsrc); - if (!m_dma_kludge_cb.isnull()) dmadata = m_dma_kludge_cb(tempsrc, tempdst, dmadata, m_active_dma_size[dma]); - m_program->write_byte(tempdst, dmadata); - - if(m_active_dma_incs[dma] == 2) - m_active_dma_src[dma] --; - if(m_active_dma_incd[dma] == 2) - m_active_dma_dst[dma] --; - - - if(m_active_dma_incs[dma] == 1) - m_active_dma_src[dma] ++; - if(m_active_dma_incd[dma] == 1) - m_active_dma_dst[dma] ++; - - m_active_dma_count[dma] --; - } - break; - case 1: - { - if(m_active_dma_incs[dma] == 2) - tempsrc = m_active_dma_src[dma] - 2; - else - tempsrc = m_active_dma_src[dma]; - - if(m_active_dma_incd[dma] == 2) - tempdst = m_active_dma_dst[dma] - 2; - else - tempdst = m_active_dma_dst[dma]; - - if (!m_dma_fifo_data_available_cb.isnull()) - { - int available = m_dma_fifo_data_available_cb(tempsrc, tempdst, 0, m_active_dma_size[dma]); - - if (!available) - { - //printf("dma stalled\n"); - m_dma_timer_active[dma]=2;// mark as stalled - return; - } - } - - #ifdef USE_TIMER_FOR_DMA - //schedule next DMA callback - m_dma_current_active_timer[dma]->adjust(cycles_to_attotime(2), dma); - #endif - - // check: should this really be using read_word_32 / write_word_32? - dmadata = m_program->read_word(tempsrc); - if (!m_dma_kludge_cb.isnull()) dmadata = m_dma_kludge_cb(tempsrc, tempdst, dmadata, m_active_dma_size[dma]); - m_program->write_word(tempdst, dmadata); - - if(m_active_dma_incs[dma] == 2) - m_active_dma_src[dma] -= 2; - if(m_active_dma_incd[dma] == 2) - m_active_dma_dst[dma] -= 2; - - if(m_active_dma_incs[dma] == 1) - m_active_dma_src[dma] += 2; - if(m_active_dma_incd[dma] == 1) - m_active_dma_dst[dma] += 2; - - m_active_dma_count[dma] --; - } - break; - case 2: - { - if(m_active_dma_incs[dma] == 2) - tempsrc = m_active_dma_src[dma] - 4; - else - tempsrc = m_active_dma_src[dma]; - - if(m_active_dma_incd[dma] == 2) - tempdst = m_active_dma_dst[dma] - 4; - else - tempdst = m_active_dma_dst[dma]; - - if (!m_dma_fifo_data_available_cb.isnull()) - { - int available = m_dma_fifo_data_available_cb(tempsrc, tempdst, 0, m_active_dma_size[dma]); - - if (!available) - { - //printf("dma stalled\n"); - m_dma_timer_active[dma]=2;// mark as stalled - return; - } - } - - #ifdef USE_TIMER_FOR_DMA - //schedule next DMA callback - m_dma_current_active_timer[dma]->adjust(cycles_to_attotime(2), dma); - #endif - - dmadata = m_program->read_dword(tempsrc); - if (!m_dma_kludge_cb.isnull()) dmadata = m_dma_kludge_cb(tempsrc, tempdst, dmadata, m_active_dma_size[dma]); - m_program->write_dword(tempdst, dmadata); - - if(m_active_dma_incs[dma] == 2) - m_active_dma_src[dma] -= 4; - if(m_active_dma_incd[dma] == 2) - m_active_dma_dst[dma] -= 4; - - if(m_active_dma_incs[dma] == 1) - m_active_dma_src[dma] += 4; - if(m_active_dma_incd[dma] == 1) - m_active_dma_dst[dma] += 4; - - m_active_dma_count[dma] --; - } - break; - case 3: - { - // shouldn't this really be 4 calls here instead? - - tempsrc = m_active_dma_src[dma]; - - if(m_active_dma_incd[dma] == 2) - tempdst = m_active_dma_dst[dma] - 16; - else - tempdst = m_active_dma_dst[dma]; - - if (!m_dma_fifo_data_available_cb.isnull()) - { - int available = m_dma_fifo_data_available_cb(tempsrc, tempdst, 0, m_active_dma_size[dma]); - - if (!available) - { - //printf("dma stalled\n"); - m_dma_timer_active[dma]=2;// mark as stalled - fatalerror("SH2 dma_callback_fifo_data_available == 0 in unsupported mode\n"); - } - } - - #ifdef USE_TIMER_FOR_DMA - //schedule next DMA callback - m_dma_current_active_timer[dma]->adjust(cycles_to_attotime(2), dma); - #endif - - dmadata = m_program->read_dword(tempsrc); - if (!m_dma_kludge_cb.isnull()) dmadata = m_dma_kludge_cb(tempsrc, tempdst, dmadata, m_active_dma_size[dma]); - m_program->write_dword(tempdst, dmadata); - - dmadata = m_program->read_dword(tempsrc+4); - if (!m_dma_kludge_cb.isnull()) dmadata = m_dma_kludge_cb(tempsrc, tempdst, dmadata, m_active_dma_size[dma]); - m_program->write_dword(tempdst+4, dmadata); - - dmadata = m_program->read_dword(tempsrc+8); - if (!m_dma_kludge_cb.isnull()) dmadata = m_dma_kludge_cb(tempsrc, tempdst, dmadata, m_active_dma_size[dma]); - m_program->write_dword(tempdst+8, dmadata); - - dmadata = m_program->read_dword(tempsrc+12); - if (!m_dma_kludge_cb.isnull()) dmadata = m_dma_kludge_cb(tempsrc, tempdst, dmadata, m_active_dma_size[dma]); - m_program->write_dword(tempdst+12, dmadata); - - if(m_active_dma_incd[dma] == 2) - m_active_dma_dst[dma] -= 16; - - m_active_dma_src[dma] += 16; - if(m_active_dma_incd[dma] == 1) - m_active_dma_dst[dma] += 16; - - m_active_dma_count[dma]-=4; - } - break; - } - } - else // the dma is complete - { - // int dma = param & 1; - - // fever soccer uses cycle-stealing mode, resume the CPU now DMA has finished - if (m_active_dma_steal[dma]) - { - resume(SUSPEND_REASON_HALT ); - } - - - LOG("SH2: DMA %d complete\n", dma); - m_m[0x62+4*dma] = 0; - m_m[0x63+4*dma] |= 2; - m_dma_timer_active[dma] = 0; - m_dma_irq[dma] |= 1; - sh2_recalc_irq(); - - } -} - -TIMER_CALLBACK_MEMBER( sh2_device::sh2_dma_current_active_callback ) -{ - int dma = param & 1; - - sh2_do_dma(dma); -} - - -void sh2_device::sh2_dmac_check(int dma) -{ - if(m_m[0x63+4*dma] & m_m[0x6c] & 1) - { - if(!m_dma_timer_active[dma] && !(m_m[0x63+4*dma] & 2)) - { - m_active_dma_incd[dma] = (m_m[0x63+4*dma] >> 14) & 3; - m_active_dma_incs[dma] = (m_m[0x63+4*dma] >> 12) & 3; - m_active_dma_size[dma] = (m_m[0x63+4*dma] >> 10) & 3; - m_active_dma_steal[dma] = (m_m[0x63+4*dma] &0x10); - - if(m_active_dma_incd[dma] == 3 || m_active_dma_incs[dma] == 3) - { - logerror("SH2: DMA: bad increment values (%d, %d, %d, %04x)\n", m_active_dma_incd[dma], m_active_dma_incs[dma], m_active_dma_size[dma], m_m[0x63+4*dma]); - return; - } - m_active_dma_src[dma] = m_m[0x60+4*dma]; - m_active_dma_dst[dma] = m_m[0x61+4*dma]; - m_active_dma_count[dma] = m_m[0x62+4*dma]; - if(!m_active_dma_count[dma]) - m_active_dma_count[dma] = 0x1000000; - - LOG("SH2: DMA %d start %x, %x, %x, %04x, %d, %d, %d\n", dma, m_active_dma_src[dma], m_active_dma_dst[dma], m_active_dma_count[dma], m_m[0x63+4*dma], m_active_dma_incs[dma], m_active_dma_incd[dma], m_active_dma_size[dma]); - - m_dma_timer_active[dma] = 1; - - m_active_dma_src[dma] &= AM; - m_active_dma_dst[dma] &= AM; - - switch(m_active_dma_size[dma]) - { - case 0: - break; - case 1: - m_active_dma_src[dma] &= ~1; - m_active_dma_dst[dma] &= ~1; - break; - case 2: - m_active_dma_src[dma] &= ~3; - m_active_dma_dst[dma] &= ~3; - break; - case 3: - m_active_dma_src[dma] &= ~3; - m_active_dma_dst[dma] &= ~3; - m_active_dma_count[dma] &= ~3; - break; - } - - - - -#ifdef USE_TIMER_FOR_DMA - // start DMA timer - - // fever soccer uses cycle-stealing mode, requiring the CPU to be halted - if (m_active_dma_steal[dma]) - { - //printf("cycle stealing DMA\n"); - suspend(SUSPEND_REASON_HALT, 1 ); - } - - m_dma_current_active_timer[dma]->adjust(cycles_to_attotime(2), dma); -#endif - - } - } - else - { - if(m_dma_timer_active[dma]) - { - logerror("SH2: DMA %d cancelled in-flight\n", dma); - //m_dma_complete_timer[dma]->adjust(attotime::never); - m_dma_current_active_timer[dma]->adjust(attotime::never); - - m_dma_timer_active[dma] = 0; - } - } -} - - -WRITE32_MEMBER( sh2_device::sh7604_w ) -{ - uint32_t old; - - old = m_m[offset]; - COMBINE_DATA(m_m+offset); - - // if(offset != 0x20) - // logerror("sh2_internal_w: Write %08x (%x), %08x @ %08x\n", 0xfffffe00+offset*4, offset, data, mem_mask); - -// if(offset != 0x20) -// printf("sh2_internal_w: Write %08x (%x), %08x @ %08x (PC %x)\n", 0xfffffe00+offset*4, offset, data, mem_mask, space.device().safe_pc()); - - switch( offset ) - { - case 0x00: - //if(mem_mask == 0xff) - // printf("%c",data & 0xff); - break; - case 0x01: - //printf("%08x %02x %02x\n",mem_mask,offset,data); - break; - // Timers - case 0x04: // TIER, FTCSR, FRC - if((mem_mask & 0x00ffffff) != 0) - { - sh2_timer_resync(); - } -// printf("SH2.%s: TIER write %04x @ %04x\n", m_device->tag(), data >> 16, mem_mask>>16); - m_m[4] = (m_m[4] & ~(ICF|OCFA|OCFB|OVF)) | (old & m_m[4] & (ICF|OCFA|OCFB|OVF)); - COMBINE_DATA(&m_frc); - if((mem_mask & 0x00ffffff) != 0) - sh2_timer_activate(); - sh2_recalc_irq(); - break; - case 0x05: // OCRx, TCR, TOCR -// printf("SH2.%s: TCR write %08x @ %08x\n", m_device->tag(), data, mem_mask); - sh2_timer_resync(); - if(m_m[5] & 0x10) - m_ocrb = (m_ocrb & (~mem_mask >> 16)) | ((data & mem_mask) >> 16); - else - m_ocra = (m_ocra & (~mem_mask >> 16)) | ((data & mem_mask) >> 16); - sh2_timer_activate(); - break; - - case 0x06: // ICR - break; - - // Interrupt vectors - case 0x18: // IPRB, VCRA - case 0x19: // VCRB, VCRC - case 0x1a: // VCRD - sh2_recalc_irq(); - break; - - // DMA - case 0x1c: // DRCR0, DRCR1 - break; - - // Watchdog - case 0x20: // WTCNT, RSTCSR - if((m_m[0x20] & 0xff000000) == 0x5a000000) - m_wtcnt = (m_m[0x20] >> 16) & 0xff; - - if((m_m[0x20] & 0xff000000) == 0xa5000000) - { - /* - WTCSR - x--- ---- Overflow in IT mode - -x-- ---- Timer mode (0: IT 1: watchdog) - --x- ---- Timer enable - ---1 1--- - ---- -xxx Clock select - */ - - m_wtcsr = (m_m[0x20] >> 16) & 0xff; - } - - if((m_m[0x20] & 0x0000ff00) == 0x00005a00) - { - // -x-- ---- RSTE (1: resets wtcnt when overflows 0: no reset) - // --x- ---- RSTS (0: power-on reset 1: Manual reset) - // ... - } - - if((m_m[0x20] & 0x0000ff00) == 0x0000a500) - { - // clear WOVF - // ... - } - - - - break; - - // Standby and cache - case 0x24: // SBYCR, CCR - /* - CCR - xx-- ---- ---- ---- Way 0/1 - ---x ---- ---- ---- Cache Purge (CP) - ---- x--- ---- ---- Two-Way Mode (TW) - ---- -x-- ---- ---- Data Replacement Disable (OD) - ---- --x- ---- ---- Instruction Replacement Disable (ID) - ---- ---x ---- ---- Cache Enable (CE) - */ - break; - - // Interrupt vectors cont. - case 0x38: // ICR, IRPA - break; - case 0x39: // VCRWDT - break; - - // Division box - case 0x40: // DVSR - break; - case 0x41: // DVDNT - { - int32_t a = m_m[0x41]; - int32_t b = m_m[0x40]; - LOG("SH2 div+mod %d/%d\n", a, b); - if (b) - { - m_m[0x45] = a / b; - m_m[0x44] = a % b; - } - else - { - m_m[0x42] |= 0x00010000; - m_m[0x45] = 0x7fffffff; - m_m[0x44] = 0x7fffffff; - sh2_recalc_irq(); - } - break; - } - case 0x42: // DVCR - m_m[0x42] = (m_m[0x42] & ~0x00001000) | (old & m_m[0x42] & 0x00010000); - sh2_recalc_irq(); - break; - case 0x43: // VCRDIV - sh2_recalc_irq(); - break; - case 0x44: // DVDNTH - break; - case 0x45: // DVDNTL - { - int64_t a = m_m[0x45] | ((uint64_t)(m_m[0x44]) << 32); - int64_t b = (int32_t)m_m[0x40]; - LOG("SH2 div+mod %d/%d\n", a, b); - if (b) - { - int64_t q = a / b; - if (q != (int32_t)q) - { - m_m[0x42] |= 0x00010000; - m_m[0x45] = 0x7fffffff; - m_m[0x44] = 0x7fffffff; - sh2_recalc_irq(); - } - else - { - m_m[0x45] = q; - m_m[0x44] = a % b; - } - } - else - { - m_m[0x42] |= 0x00010000; - m_m[0x45] = 0x7fffffff; - m_m[0x44] = 0x7fffffff; - sh2_recalc_irq(); - } - break; - } - - // DMA controller - case 0x60: // SAR0 - case 0x61: // DAR0 - break; - case 0x62: // DTCR0 - m_m[0x62] &= 0xffffff; - break; - case 0x63: // CHCR0 - m_m[0x63] = (m_m[0x63] & ~2) | (old & m_m[0x63] & 2); - sh2_dmac_check(0); - break; - case 0x64: // SAR1 - case 0x65: // DAR1 - break; - case 0x66: // DTCR1 - m_m[0x66] &= 0xffffff; - break; - case 0x67: // CHCR1 - m_m[0x67] = (m_m[0x67] & ~2) | (old & m_m[0x67] & 2); - sh2_dmac_check(1); - break; - case 0x68: // VCRDMA0 - case 0x6a: // VCRDMA1 - sh2_recalc_irq(); - break; - case 0x6c: // DMAOR - m_m[0x6c] = (m_m[0x6c] & ~6) | (old & m_m[0x6c] & 6); - sh2_dmac_check(0); - sh2_dmac_check(1); - break; - - // Bus controller - case 0x78: // BCR1 - case 0x79: // BCR2 - case 0x7a: // WCR - case 0x7b: // MCR - case 0x7c: // RTCSR - case 0x7d: // RTCNT - case 0x7e: // RTCOR - break; - - default: - logerror("sh2_internal_w: Unmapped write %08x, %08x @ %08x\n", 0xfffffe00+offset*4, data, mem_mask); - break; - } -} - -READ32_MEMBER( sh2_device::sh7604_r ) -{ -// logerror("sh2_internal_r: Read %08x (%x) @ %08x\n", 0xfffffe00+offset*4, offset, mem_mask); - switch( offset ) - { - case 0x00: - break; - case 0x01: -// return m_m[1] | 0; // bit31 is TDRE: Trasmit Data Register Empty. Forcing it to be '1' breaks Saturn ... - return m_m[1] | (0x84 << 24); // ... but this is actually needed to make EGWord on SS to boot? - - case 0x04: // TIER, FTCSR, FRC - if ( mem_mask == 0x00ff0000 ) - { - if (!m_ftcsr_read_cb.isnull()) - { - m_ftcsr_read_cb((m_m[4] & 0xffff0000) | m_frc); - } - } - sh2_timer_resync(); - return (m_m[4] & 0xffff0000) | m_frc; - case 0x05: // OCRx, TCR, TOCR - if(m_m[5] & 0x10) - return (m_ocrb << 16) | (m_m[5] & 0xffff); - else - return (m_ocra << 16) | (m_m[5] & 0xffff); - case 0x06: // ICR - return m_icr << 16; - - case 0x20: - return (((m_wtcsr | 0x18) & 0xff) << 24) | ((m_wtcnt & 0xff) << 16); - - case 0x24: // SBYCR, CCR - return m_m[0x24] & ~0x3000; /* bit 4-5 of CCR are always zero */ - - case 0x38: // ICR, IPRA - return (m_m[0x38] & 0x7fffffff) | (m_nmi_line_state == ASSERT_LINE ? 0 : 0x80000000); - - case 0x78: // BCR1 - return (m_is_slave ? 0x00008000 : 0) | (m_m[0x78] & 0x7fff); - - case 0x41: // dvdntl mirrors - case 0x47: - return m_m[0x45]; - - case 0x46: // dvdnth mirror - return m_m[0x44]; - } - return m_m[offset]; -} - -void sh2_device::sh2_set_frt_input(int state) -{ - if(state == PULSE_LINE) - { - sh2_set_frt_input(ASSERT_LINE); - sh2_set_frt_input(CLEAR_LINE); - return; - } - - if(m_frt_input == state) { - return; - } - - m_frt_input = state; - - if(m_m[5] & 0x8000) { - if(state == CLEAR_LINE) { - return; - } - } else { - if(state == ASSERT_LINE) { - return; - } - } - - sh2_timer_resync(); - m_icr = m_frc; - m_m[4] |= ICF; - //logerror("SH2.%s: ICF activated (%x)\n", tag(), m_sh2_state->pc & AM); - sh2_recalc_irq(); -} - -void sh2_device::sh2_recalc_irq() -{ - int irq = 0, vector = -1; - int level; - - // Timer irqs - if((m_m[4]>>8) & m_m[4] & (ICF|OCFA|OCFB|OVF)) - { - level = (m_m[0x18] >> 24) & 15; - if(level > irq) - { - int mask = (m_m[4]>>8) & m_m[4]; - irq = level; - if(mask & ICF) - vector = (m_m[0x19] >> 8) & 0x7f; - else if(mask & (OCFA|OCFB)) - vector = m_m[0x19] & 0x7f; - else - vector = (m_m[0x1a] >> 24) & 0x7f; - } - } - - // DMA irqs - if((m_m[0x63] & 6) == 6 && m_dma_irq[0]) { - level = (m_m[0x38] >> 8) & 15; - if(level > irq) { - irq = level; - m_dma_irq[0] &= ~1; - vector = (m_m[0x68]) & 0x7f; - } - } - else if((m_m[0x67] & 6) == 6 && m_dma_irq[1]) { - level = (m_m[0x38] >> 8) & 15; - if(level > irq) { - irq = level; - m_dma_irq[1] &= ~1; - vector = (m_m[0x6a]) & 0x7f; - } - } - - m_sh2_state->internal_irq_level = irq; - m_internal_irq_vector = vector; - m_test_irq = 1; -} - -/* - SH-7021 on-chip device - */ - -void sh2a_device::sh7032_dma_exec(int ch) -{ - const short dma_word_size[4] = { 0, +1, -1, 0 }; - uint8_t rs = (m_dma[ch].chcr >> 8) & 0xf; /**< Resource Select bits */ - if(rs != 0xc) // Auto-Request - { - logerror("Warning: SH7032 DMA enables non auto-request transfer\n"); - return; - } - - // channel enable & master enable - if((m_dma[ch].chcr & 1) == 0 || (m_dmaor & 1) == 0) - return; - - printf("%08x %08x %04x\n",m_dma[ch].sar,m_dma[ch].dar,m_dma[ch].chcr); - uint8_t dm = (m_dma[ch].chcr >> 14) & 3; /**< Destination Address Mode bits */ - uint8_t sm = (m_dma[ch].chcr >> 12) & 3; /**< Source Address Mode bits */ - bool ts = (m_dma[ch].chcr & 8); /**< Transfer Size bit */ - int src_word_size = dma_word_size[sm] * ((ts == true) ? 2 : 1); - int dst_word_size = dma_word_size[dm] * ((ts == true) ? 2 : 1); - uint32_t src_addr = m_dma[ch].sar; - uint32_t dst_addr = m_dma[ch].dar; - uint32_t size_index = m_dma[ch].tcr; - if(size_index == 0) - size_index = 0x10000; - - if(ts == false) - logerror("SH7032: DMA byte mode check\n"); - - for(int index = size_index;index>-1;index--) - { - if(ts == true) - m_program->write_word(dst_addr,m_program->read_word(src_addr)); - else - m_program->write_byte(dst_addr,m_program->read_byte(src_addr)); - - src_addr += src_word_size; - dst_addr += dst_word_size; - } - - m_dma[ch].chcr &= ~1; /**< @todo non-instant DMA */ - printf("%02x %02x %02x %1d\n",sm,dm,rs,ts); -} - -READ32_MEMBER(sh2a_device::dma_sar0_r) -{ - return m_dma[0].sar; -} - -WRITE32_MEMBER(sh2a_device::dma_sar0_w) -{ - COMBINE_DATA(&m_dma[0].sar); -} - -READ32_MEMBER(sh2a_device::dma_dar0_r) -{ - return m_dma[0].dar; -} - -WRITE32_MEMBER(sh2a_device::dma_dar0_w) -{ - COMBINE_DATA(&m_dma[0].dar); -} - -READ16_MEMBER(sh2a_device::dma_tcr0_r) -{ - return m_dma[0].tcr; -} - -WRITE16_MEMBER(sh2a_device::dma_tcr0_w) -{ - //printf("%04x\n",data); - COMBINE_DATA(&m_dma[0].tcr); -} - -READ16_MEMBER(sh2a_device::dma_chcr0_r) -{ - return m_dma[0].chcr; -} - -WRITE16_MEMBER(sh2a_device::dma_chcr0_w) -{ - //printf("%04x CHCR0\n",data); - COMBINE_DATA(&m_dma[0].chcr); - sh7032_dma_exec(0); -} - -READ16_MEMBER(sh2a_device::dmaor_r) -{ - return m_dmaor; -} - -WRITE16_MEMBER(sh2a_device::dmaor_w) -{ - COMBINE_DATA(&m_dmaor); - sh7032_dma_exec(0); -} - -/*! - @brief Dummy debug interface - */ -READ16_MEMBER(sh1_device::sh7032_r) -{ - return m_sh7032_regs[offset]; -} - -/*! - @brief Dummy debug interface - */ -WRITE16_MEMBER(sh1_device::sh7032_w) -{ - COMBINE_DATA(&m_sh7032_regs[offset]); -} - -READ16_MEMBER(sh2a_device::sh7021_r) -{ - return m_sh7021_regs[offset]; -} - -/*! - @brief Dummy debug interface - */ -WRITE16_MEMBER(sh2a_device::sh7021_w) -{ - COMBINE_DATA(&m_sh7021_regs[offset]); -} diff --git a/src/devices/cpu/superh/sh2comn.h b/src/devices/cpu/superh/sh2comn.h deleted file mode 100644 index 1c859e227d6..00000000000 --- a/src/devices/cpu/superh/sh2comn.h +++ /dev/null @@ -1,85 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:R. Belmont -/***************************************************************************** - * - * sh2common.h - * - * SH-2 non-specific components - * - *****************************************************************************/ - -#ifndef MAME_CPU_SH2_SH2COMN_H -#define MAME_CPU_SH2_SH2COMN_H - -#pragma once - - - -// do we use a timer for the DMA, or have it in CPU_EXECUTE -#define USE_TIMER_FOR_DMA - -#include "cpu/drcuml.h" -#include "cpu/drcumlsh.h" - -#define SH2_CODE_XOR(a) ((a) ^ NATIVE_ENDIAN_VALUE_LE_BE(2,0)) - -enum -{ - ICF = 0x00800000, - OCFA = 0x00080000, - OCFB = 0x00040000, - OVF = 0x00020000 -}; - -#define T 0x00000001 -#define S 0x00000002 -#define I 0x000000f0 -#define Q 0x00000100 -#define M 0x00000200 - -#define AM 0xc7ffffff - -#define FLAGS (M|Q|I|S|T) - -#define Rn ((opcode>>8)&15) -#define Rm ((opcode>>4)&15) - -#define CPU_TYPE_SH1 (0) -#define CPU_TYPE_SH2 (1) - -#define REGFLAG_R(n) (1 << (n)) - -/* register flags 1 */ -#define REGFLAG_PR (1 << 0) -#define REGFLAG_MACL (1 << 1) -#define REGFLAG_MACH (1 << 2) -#define REGFLAG_GBR (1 << 3) -#define REGFLAG_VBR (1 << 4) -#define REGFLAG_SR (1 << 5) - -#define CHECK_PENDING_IRQ(message) \ -do { \ - int irq = -1; \ - if (m_sh2_state->pending_irq & (1 << 0)) irq = 0; \ - if (m_sh2_state->pending_irq & (1 << 1)) irq = 1; \ - if (m_sh2_state->pending_irq & (1 << 2)) irq = 2; \ - if (m_sh2_state->pending_irq & (1 << 3)) irq = 3; \ - if (m_sh2_state->pending_irq & (1 << 4)) irq = 4; \ - if (m_sh2_state->pending_irq & (1 << 5)) irq = 5; \ - if (m_sh2_state->pending_irq & (1 << 6)) irq = 6; \ - if (m_sh2_state->pending_irq & (1 << 7)) irq = 7; \ - if (m_sh2_state->pending_irq & (1 << 8)) irq = 8; \ - if (m_sh2_state->pending_irq & (1 << 9)) irq = 9; \ - if (m_sh2_state->pending_irq & (1 << 10)) irq = 10; \ - if (m_sh2_state->pending_irq & (1 << 11)) irq = 11; \ - if (m_sh2_state->pending_irq & (1 << 12)) irq = 12; \ - if (m_sh2_state->pending_irq & (1 << 13)) irq = 13; \ - if (m_sh2_state->pending_irq & (1 << 14)) irq = 14; \ - if (m_sh2_state->pending_irq & (1 << 15)) irq = 15; \ - if ((m_sh2_state->internal_irq_level != -1) && (m_sh2_state->internal_irq_level > irq)) irq = m_sh2_state->internal_irq_level; \ - if (irq >= 0) \ - sh2_exception(message,irq); \ -} while(0) - - -#endif // MAME_CPU_SH2_SH2COMN_H diff --git a/src/devices/cpu/superh/sh2dasm.cpp b/src/devices/cpu/superh/sh2dasm.cpp deleted file mode 100644 index ef823ee28a5..00000000000 --- a/src/devices/cpu/superh/sh2dasm.cpp +++ /dev/null @@ -1,610 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Juergen Buchmueller -#include "emu.h" -#include "debugger.h" -#include "sh2.h" - -#define SIGNX8(x) (((int32_t)(x) << 24) >> 24) -#define SIGNX12(x) (((int32_t)(x) << 20) >> 20) - -#define Rn ((opcode >> 8) & 15) -#define Rm ((opcode >> 4) & 15) - -static const char *const regname[16] = { - "R0", "R1", "R2", "R3", "R4", "R5", "R6", "R7", - "R8", "R9", "R10","R11","R12","R13","R14","SP" -}; - -static uint32_t op0000(std::ostream &stream, uint32_t pc, uint16_t opcode) -{ - uint32_t flags = 0; - switch(opcode & 0x3f) - { - case 0x02: - util::stream_format(stream, "STC SR,%s", regname[Rn]); - break; - case 0x03: - util::stream_format(stream, "BSRF %s", regname[Rn]); - break; - case 0x08: - stream << "CLRT"; - break; - case 0x09: - stream << "NOP"; - break; - case 0x0A: - util::stream_format(stream, "STS MACH,%s", regname[Rn]); - break; - case 0x0B: - stream << "RTS"; - flags = DASMFLAG_STEP_OUT; - break; - case 0x12: - util::stream_format(stream, "STS GBR,%s", regname[Rn]); - break; - case 0x18: - stream << "SETT"; - break; - case 0x19: - stream << "DIV0U"; - break; - case 0x1A: - util::stream_format(stream, "STS MACL,%s", regname[Rn]); - break; - case 0x1B: - stream << "SLEEP"; - break; - case 0x22: - util::stream_format(stream, "STC VBR,%s", regname[Rn]); - break; - case 0x23: - util::stream_format(stream, "BRAF %s", regname[Rn]); - break; - case 0x28: - stream << "CLRMAC"; - break; - case 0x29: - util::stream_format(stream, "MOVT %s", regname[Rn]); - break; - case 0x2A: - util::stream_format(stream, "STS PR,%s", regname[Rn]); - break; - case 0x2B: - stream << "RTE"; - flags = DASMFLAG_STEP_OUT; - break; - default: - switch(opcode & 15) - { - case 0: - util::stream_format(stream, "?????? $%04X", opcode); - break; - case 1: - util::stream_format(stream, "?????? $%04X", opcode); - break; - case 2: - util::stream_format(stream, "?????? $%04X", opcode); - break; - case 3: - util::stream_format(stream, "?????? $%04X", opcode); - break; - case 4: - util::stream_format(stream, "MOV.B %s,@(R0,%s)", regname[Rm], regname[Rn]); - break; - case 5: - util::stream_format(stream, "MOV.W %s,@(R0,%s)", regname[Rm], regname[Rn]); - break; - case 6: - util::stream_format(stream, "MOV.L %s,@(R0,%s)", regname[Rm], regname[Rn]); - break; - case 7: - util::stream_format(stream, "MUL.L %s,%s", regname[Rm], regname[Rn]); - break; - case 8: - util::stream_format(stream, "?????? $%04X", opcode); - break; - case 9: - util::stream_format(stream, "?????? $%04X", opcode); - break; - case 10: - util::stream_format(stream, "?????? $%04X", opcode); - break; - case 11: - util::stream_format(stream, "?????? $%04X", opcode); - break; - case 12: - util::stream_format(stream, "MOV.B @(R0,%s),%s", regname[Rm], regname[Rn]); - break; - case 13: - util::stream_format(stream, "MOV.W @(R0,%s),%s", regname[Rm], regname[Rn]); - break; - case 14: - util::stream_format(stream, "MOV.L @(R0,%s),%s", regname[Rm], regname[Rn]); - break; - case 15: - util::stream_format(stream, "MAC.L @%s+,@%s+", regname[Rn], regname[Rm]); - break; - } - } - return flags; -} - -static uint32_t op0001(std::ostream &stream, uint32_t pc, uint16_t opcode) -{ - util::stream_format(stream, "MOV.L %s,@($%02X,%s)", regname[Rm], (opcode & 15) * 4, regname[Rn]); - return 0; -} - -static uint32_t op0010(std::ostream &stream, uint32_t pc, uint16_t opcode) -{ - switch (opcode & 15) - { - case 0: - util::stream_format(stream, "MOV.B %s,@%s", regname[Rm], regname[Rn]); - break; - case 1: - util::stream_format(stream, "MOV.W %s,@%s", regname[Rm], regname[Rn]); - break; - case 2: - util::stream_format(stream, "MOV.L %s,@%s", regname[Rm], regname[Rn]); - break; - case 3: - util::stream_format(stream, "?????? $%04X", opcode); - break; - case 4: - util::stream_format(stream, "MOV.B %s,@-%s", regname[Rm], regname[Rn]); - break; - case 5: - util::stream_format(stream, "MOV.W %s,@-%s", regname[Rm], regname[Rn]); - break; - case 6: - util::stream_format(stream, "MOV.L %s,@-%s", regname[Rm], regname[Rn]); - break; - case 7: - util::stream_format(stream, "DIV0S %s,%s", regname[Rm], regname[Rn]); - break; - case 8: - util::stream_format(stream, "TST %s,%s", regname[Rm], regname[Rn]); - break; - case 9: - util::stream_format(stream, "AND %s,%s", regname[Rm], regname[Rn]); - break; - case 10: - util::stream_format(stream, "XOR %s,%s", regname[Rm], regname[Rn]); - break; - case 11: - util::stream_format(stream, "OR %s,%s", regname[Rm], regname[Rn]); - break; - case 12: - util::stream_format(stream, "CMP/STR %s,%s", regname[Rm], regname[Rn]); - break; - case 13: - util::stream_format(stream, "XTRCT %s,%s", regname[Rm], regname[Rn]); - break; - case 14: - util::stream_format(stream, "MULU.W %s,%s", regname[Rm], regname[Rn]); - break; - case 15: - util::stream_format(stream, "MULS.W %s,%s", regname[Rm], regname[Rn]); - break; - } - return 0; -} - -static uint32_t op0011(std::ostream &stream, uint32_t pc, uint16_t opcode) -{ - switch (opcode & 15) - { - case 0: - util::stream_format(stream, "CMP/EQ %s,%s", regname[Rm], regname[Rn]); - break; - case 1: - util::stream_format(stream, "?????? %s,%s", regname[Rm], regname[Rn]); - break; - case 2: - util::stream_format(stream, "CMP/HS %s,%s", regname[Rm], regname[Rn]); - break; - case 3: - util::stream_format(stream, "CMP/GE %s,%s", regname[Rm], regname[Rn]); - break; - case 4: - util::stream_format(stream, "DIV1 %s,%s", regname[Rm], regname[Rn]); - break; - case 5: - util::stream_format(stream, "DMULU.L %s,%s", regname[Rm], regname[Rn]); - break; - case 6: - util::stream_format(stream, "CMP/HI %s,%s", regname[Rm], regname[Rn]); - break; - case 7: - util::stream_format(stream, "CMP/GT %s,%s", regname[Rm], regname[Rn]); - break; - case 8: - util::stream_format(stream, "SUB %s,%s", regname[Rm], regname[Rn]); - break; - case 9: - util::stream_format(stream, "?????? %s,%s", regname[Rm], regname[Rn]); - break; - case 10: - util::stream_format(stream, "SUBC %s,%s", regname[Rm], regname[Rn]); - break; - case 11: - util::stream_format(stream, "SUBV %s,%s", regname[Rm], regname[Rn]); - break; - case 12: - util::stream_format(stream, "ADD %s,%s", regname[Rm], regname[Rn]); - break; - case 13: - util::stream_format(stream, "DMULS.L %s,%s", regname[Rm], regname[Rn]); - break; - case 14: - util::stream_format(stream, "ADDC %s,%s", regname[Rm], regname[Rn]); - break; - case 15: - util::stream_format(stream, "ADDV %s,%s", regname[Rm], regname[Rn]); - break; - } - return 0; -} - -static uint32_t op0100(std::ostream &stream, uint32_t pc, uint16_t opcode) -{ - uint32_t flags = 0; - switch(opcode & 0x3F) - { - case 0x00: - util::stream_format(stream, "SHLL %s", regname[Rn]); - break; - case 0x01: - util::stream_format(stream, "SHLR %s", regname[Rn]); - break; - case 0x02: - util::stream_format(stream, "STS.L MACH,@-%s", regname[Rn]); - break; - case 0x03: - util::stream_format(stream, "STC.L SR,@-%s", regname[Rn]); - break; - case 0x04: - util::stream_format(stream, "ROTL %s", regname[Rn]); - break; - case 0x05: - util::stream_format(stream, "ROTR %s", regname[Rn]); - break; - case 0x06: - util::stream_format(stream, "LDS.L @%s+,MACH", regname[Rn]); - break; - case 0x07: - util::stream_format(stream, "LDC.L @%s+,SR", regname[Rn]); - break; - case 0x08: - util::stream_format(stream, "SHLL2 %s", regname[Rn]); - break; - case 0x09: - util::stream_format(stream, "SHLR2 %s", regname[Rn]); - break; - case 0x0a: - util::stream_format(stream, "LDS %s,MACH", regname[Rn]); - break; - case 0x0b: - util::stream_format(stream, "JSR %s", regname[Rn]); - flags = DASMFLAG_STEP_OVER | DASMFLAG_STEP_OVER_EXTRA(1); - break; - case 0x0e: - util::stream_format(stream, "LDC %s,SR", regname[Rn]); - break; - case 0x10: - util::stream_format(stream, "DT %s", regname[Rn]); - break; - case 0x11: - util::stream_format(stream, "CMP/PZ %s", regname[Rn]); - break; - case 0x12: - util::stream_format(stream, "STS.L MACL,@-%s", regname[Rn]); - break; - case 0x13: - util::stream_format(stream, "STC.L GBR,@-%s", regname[Rn]); - break; - case 0x15: - util::stream_format(stream, "CMP/PL %s", regname[Rn]); - break; - case 0x16: - util::stream_format(stream, "LDS.L @%s+,MACL", regname[Rn]); - break; - case 0x17: - util::stream_format(stream, "LDC.L @%s+,GBR", regname[Rn]); - break; - case 0x18: - util::stream_format(stream, "SHLL8 %s", regname[Rn]); - break; - case 0x19: - util::stream_format(stream, "SHLR8 %s", regname[Rn]); - break; - case 0x1a: - util::stream_format(stream, "LDS %s,MACL", regname[Rn]); - break; - case 0x1b: - util::stream_format(stream, "TAS %s", regname[Rn]); - break; - case 0x1e: - util::stream_format(stream, "LDC %s,GBR", regname[Rn]); - break; - case 0x20: - util::stream_format(stream, "SHAL %s", regname[Rn]); - break; - case 0x21: - util::stream_format(stream, "SHAR %s", regname[Rn]); - break; - case 0x22: - util::stream_format(stream, "STS.L PR,@-%s", regname[Rn]); - break; - case 0x23: - util::stream_format(stream, "STC.L VBR,@-%s", regname[Rn]); - break; - case 0x24: - util::stream_format(stream, "ROTCL %s", regname[Rn]); - break; - case 0x25: - util::stream_format(stream, "ROTCR %s", regname[Rn]); - break; - case 0x26: - util::stream_format(stream, "LDS.L @%s+,PR", regname[Rn]); - break; - case 0x27: - util::stream_format(stream, "LDC.L @%s+,VBR", regname[Rn]); - break; - case 0x28: - util::stream_format(stream, "SHLL16 %s", regname[Rn]); - break; - case 0x29: - util::stream_format(stream, "SHLR16 %s", regname[Rn]); - break; - case 0x2a: - util::stream_format(stream, "LDS %s,PR", regname[Rn]); - break; - case 0x2b: - util::stream_format(stream, "JMP %s", regname[Rn]); - break; - case 0x2e: - util::stream_format(stream, "LDC %s,VBR", regname[Rn]); - break; - default: - if ((opcode & 15) == 15) - util::stream_format(stream, "MAC.W @%s+,@%s+", regname[Rm], regname[Rn]); - else - util::stream_format(stream, "?????? $%04X", opcode); - } - return flags; -} - -static uint32_t op0101(std::ostream &stream, uint32_t pc, uint16_t opcode) -{ - util::stream_format(stream, "MOV.L @($%02X,%s),%s", (opcode & 15) * 4, regname[Rm], regname[Rn]); - return 0; -} - -static uint32_t op0110(std::ostream &stream, uint32_t pc, uint16_t opcode) - -{ - switch(opcode & 0xF) - { - case 0x00: - util::stream_format(stream, "MOV.B @%s,%s", regname[Rm], regname[Rn]); - break; - case 0x01: - util::stream_format(stream, "MOV.W @%s,%s", regname[Rm], regname[Rn]); - break; - case 0x02: - util::stream_format(stream, "MOV.L @%s,%s", regname[Rm], regname[Rn]); - break; - case 0x03: - util::stream_format(stream, "MOV %s,%s", regname[Rm], regname[Rn]); - break; - case 0x04: - util::stream_format(stream, "MOV.B @%s+,%s", regname[Rm], regname[Rn]); - break; - case 0x05: - util::stream_format(stream, "MOV.W @%s+,%s", regname[Rm], regname[Rn]); - break; - case 0x06: - util::stream_format(stream, "MOV.L @%s+,%s", regname[Rm], regname[Rn]); - break; - case 0x07: - util::stream_format(stream, "NOT %s,%s", regname[Rm], regname[Rn]); - break; - case 0x08: - util::stream_format(stream, "SWAP.B %s,%s", regname[Rm], regname[Rn]); - break; - case 0x09: - util::stream_format(stream, "SWAP.W %s,%s", regname[Rm], regname[Rn]); - break; - case 0x0a: - util::stream_format(stream, "NEGC %s,%s", regname[Rm], regname[Rn]); - break; - case 0x0b: - util::stream_format(stream, "NEG %s,%s", regname[Rm], regname[Rn]); - break; - case 0x0c: - util::stream_format(stream, "EXTU.B %s,%s", regname[Rm], regname[Rn]); - break; - case 0x0d: - util::stream_format(stream, "EXTU.W %s,%s", regname[Rm], regname[Rn]); - break; - case 0x0e: - util::stream_format(stream, "EXTS.B %s,%s", regname[Rm], regname[Rn]); - break; - case 0x0f: - util::stream_format(stream, "EXTS.W %s,%s", regname[Rm], regname[Rn]); - break; - } - return 0; -} - -static uint32_t op0111(std::ostream &stream, uint32_t pc, uint16_t opcode) -{ - util::stream_format(stream, "ADD #$%02X,%s", opcode & 0xff, regname[Rn]); - return 0; -} - -static uint32_t op1000(std::ostream &stream, uint32_t pc, uint16_t opcode) -{ - switch((opcode >> 8) & 15) - { - case 0: - util::stream_format(stream, "MOV.B R0,@($%02X,%s)", (opcode & 15), regname[Rm]); - break; - case 1: - util::stream_format(stream, "MOV.W R0,@($%02X,%s)", (opcode & 15) * 2, regname[Rm]); - break; - case 4: - util::stream_format(stream, "MOV.B @($%02X,%s),R0", (opcode & 15), regname[Rm]); - break; - case 5: - util::stream_format(stream, "MOV.W @($%02X,%s),R0", (opcode & 15), regname[Rm]); - break; - case 8: - util::stream_format(stream, "CMP/EQ #$%02X,R0", (opcode & 0xff)); - break; - case 9: - util::stream_format(stream, "BT $%08X", pc + SIGNX8(opcode & 0xff) * 2 + 2); - break; - case 11: - util::stream_format(stream, "BF $%08X", pc + SIGNX8(opcode & 0xff) * 2 + 2); - break; - case 13: - util::stream_format(stream, "BTS $%08X", pc + SIGNX8(opcode & 0xff) * 2 + 2); - break; - case 15: - util::stream_format(stream, "BFS $%08X", pc + SIGNX8(opcode & 0xff) * 2 + 2); - break; - default : - util::stream_format(stream, "invalid $%04X", opcode); - } - return 0; -} - -static uint32_t op1001(std::ostream &stream, uint32_t pc, uint16_t opcode) -{ - util::stream_format(stream, "MOV.W @($%04X,PC),%s [%08X]", (opcode & 0xff) * 2, regname[Rn], pc+((opcode & 0xff) * 2)+2); - return 0; -} - -static uint32_t op1010(std::ostream &stream, uint32_t pc, uint16_t opcode) -{ - util::stream_format(stream, "BRA $%08X", SIGNX12(opcode & 0xfff) * 2 + pc + 2); - return 0; -} - -static uint32_t op1011(std::ostream &stream, uint32_t pc, uint16_t opcode) -{ - util::stream_format(stream, "BSR $%08X", SIGNX12(opcode & 0xfff) * 2 + pc + 2); - return DASMFLAG_STEP_OVER | DASMFLAG_STEP_OVER_EXTRA(1); -} - -static uint32_t op1100(std::ostream &stream, uint32_t pc, uint16_t opcode) -{ - uint32_t flags = 0; - switch((opcode >> 8) & 15) - { - case 0: - util::stream_format(stream, "MOV.B R0,@($%02X,GBR)", opcode & 0xff); - break; - case 1: - util::stream_format(stream, "MOV.W R0,@($%04X,GBR)", (opcode & 0xff) * 2); - break; - case 2: - util::stream_format(stream, "MOV.L R0,@($%04X,GBR)", (opcode & 0xff) * 4); - break; - case 3: - util::stream_format(stream, "TRAPA #$%02X", opcode & 0xff); - flags = DASMFLAG_STEP_OVER; - break; - case 4: - util::stream_format(stream, "MOV.B @($%02X,GBR),R0", opcode & 0xff); - break; - case 5: - util::stream_format(stream, "MOV.W @($%04X,GBR),R0", (opcode & 0xff) * 2); - break; - case 6: - util::stream_format(stream, "MOV.L @($%04X,GBR),R0", (opcode & 0xff) * 4); - break; - case 7: - util::stream_format(stream, "MOVA @($%04X,PC),R0 [%08X]", (opcode & 0xff) * 4, ((pc + 2) & ~3) + (opcode & 0xff) * 4); - break; - case 8: - util::stream_format(stream, "TST #$%02X,R0", opcode & 0xff); - break; - case 9: - util::stream_format(stream, "AND #$%02X,R0", opcode & 0xff); - break; - case 10: - util::stream_format(stream, "XOR #$%02X,R0", opcode & 0xff); - break; - case 11: - util::stream_format(stream, "OR #$%02X,R0", opcode & 0xff); - break; - case 12: - util::stream_format(stream, "TST.B #$%02X,@(R0,GBR)", opcode & 0xff); - break; - case 13: - util::stream_format(stream, "AND.B #$%02X,@(R0,GBR)", opcode & 0xff); - break; - case 14: - util::stream_format(stream, "XOR.B #$%02X,@(R0,GBR)", opcode & 0xff); - break; - case 15: - util::stream_format(stream, "OR.B #$%02X,@(R0,GBR)", opcode & 0xff); - break; - } - return flags; -} - -static uint32_t op1101(std::ostream &stream, uint32_t pc, uint16_t opcode) -{ - util::stream_format(stream, "MOV.L @($%02X,PC),%s [%08X]", (opcode * 4) & 0xff, regname[Rn], ((pc + 2) & ~3) + (opcode & 0xff) * 4); - return 0; -} - -static uint32_t op1110(std::ostream &stream, uint32_t pc, uint16_t opcode) -{ - util::stream_format(stream, "MOV #$%02X,%s", (opcode & 0xff), regname[Rn]); - return 0; -} - -static uint32_t op1111(std::ostream &stream, uint32_t pc, uint16_t opcode) -{ - util::stream_format(stream, "unknown $%04X", opcode); - return 0; -} - -unsigned DasmSH2(std::ostream &stream, unsigned pc, uint16_t opcode) -{ - uint32_t flags; - - pc += 2; - - switch ((opcode >> 12) & 15) - { - case 0: flags = op0000(stream, pc, opcode); break; - case 1: flags = op0001(stream, pc, opcode); break; - case 2: flags = op0010(stream, pc, opcode); break; - case 3: flags = op0011(stream, pc, opcode); break; - case 4: flags = op0100(stream, pc, opcode); break; - case 5: flags = op0101(stream, pc, opcode); break; - case 6: flags = op0110(stream, pc, opcode); break; - case 7: flags = op0111(stream, pc, opcode); break; - case 8: flags = op1000(stream, pc, opcode); break; - case 9: flags = op1001(stream, pc, opcode); break; - case 10: flags = op1010(stream, pc, opcode); break; - case 11: flags = op1011(stream, pc, opcode); break; - case 12: flags = op1100(stream, pc, opcode); break; - case 13: flags = op1101(stream, pc, opcode); break; - case 14: flags = op1110(stream, pc, opcode); break; - default: flags = op1111(stream, pc, opcode); break; - } - return 2 | flags | DASMFLAG_SUPPORTED; -} - -CPU_DISASSEMBLE(sh2) -{ - return DasmSH2(stream, pc, (oprom[0] << 8) | oprom[1]); -} diff --git a/src/devices/cpu/superh/sh2drc.cpp b/src/devices/cpu/superh/sh2drc.cpp deleted file mode 100644 index 1003463b97a..00000000000 --- a/src/devices/cpu/superh/sh2drc.cpp +++ /dev/null @@ -1,2982 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:R. Belmont -/*************************************************************************** - - sh2drc.c - Universal machine language-based SH-2 emulator. - -***************************************************************************/ - -#include "emu.h" -#include "debugger.h" -#include "sh2.h" -#include "sh2comn.h" - -extern unsigned DasmSH2(std::ostream &stream, unsigned pc, uint16_t opcode); - -using namespace uml; - -/*************************************************************************** - DEBUGGING -***************************************************************************/ - -#define SET_EA (0) // makes slower but "shows work" in the EA fake register like the interpreter - -#define ADDSUBV_DIRECT (0) - -#if SET_EA -#define SETEA(x) UML_MOV(block, mem(&m_sh2_state->ea), ireg(x)) -#else -#define SETEA(x) -#endif - -/*************************************************************************** - CONSTANTS -***************************************************************************/ - -/* map variables */ -#define MAPVAR_PC M0 -#define MAPVAR_CYCLES M1 - -/* exit codes */ -#define EXECUTE_OUT_OF_CYCLES 0 -#define EXECUTE_MISSING_CODE 1 -#define EXECUTE_UNMAPPED_CODE 2 -#define EXECUTE_RESET_CACHE 3 - -#define PROBE_ADDRESS ~0 - - -/*************************************************************************** - MACROS -***************************************************************************/ - -#define R32(reg) m_regmap[reg] - -/*************************************************************************** - INLINE FUNCTIONS -***************************************************************************/ - -/*------------------------------------------------- - epc - compute the exception PC from a - descriptor --------------------------------------------------*/ - -uint32_t sh2_device::epc(const opcode_desc *desc) -{ - return (desc->flags & OPFLAG_IN_DELAY_SLOT) ? (desc->pc - 1) : desc->pc; -} - -/*------------------------------------------------- - alloc_handle - allocate a handle if not - already allocated --------------------------------------------------*/ - -void sh2_device::alloc_handle(drcuml_state *drcuml, code_handle **handleptr, const char *name) -{ - if (*handleptr == nullptr) - *handleptr = drcuml->handle_alloc(name); -} - -/*------------------------------------------------- - load_fast_iregs - load any fast integer - registers --------------------------------------------------*/ - -void sh2_device::load_fast_iregs(drcuml_block *block) -{ - int regnum; - - for (regnum = 0; regnum < ARRAY_LENGTH(m_regmap); regnum++) - { - if (m_regmap[regnum].is_int_register()) - { - UML_MOV(block, uml::parameter::make_ireg(m_regmap[regnum].ireg()), mem(&m_sh2_state->r[regnum])); - } - } -} - - -/*------------------------------------------------- - save_fast_iregs - save any fast integer - registers --------------------------------------------------*/ - -void sh2_device::save_fast_iregs(drcuml_block *block) -{ - int regnum; - - for (regnum = 0; regnum < ARRAY_LENGTH(m_regmap); regnum++) - { - if (m_regmap[regnum].is_int_register()) - { - UML_MOV(block, mem(&m_sh2_state->r[regnum]), uml::parameter::make_ireg(m_regmap[regnum].ireg())); - } - } -} - -/*------------------------------------------------- - cfunc_printf_probe - print the current CPU - state and return --------------------------------------------------*/ - -static void cfunc_printf_probe(void *param) -{ - ((sh2_device *)param)->func_printf_probe(); -} - -void sh2_device::func_printf_probe() -{ - uint32_t pc = m_sh2_state->pc; - - printf(" PC=%08X r0=%08X r1=%08X r2=%08X\n", - pc, - (uint32_t)m_sh2_state->r[0], - (uint32_t)m_sh2_state->r[1], - (uint32_t)m_sh2_state->r[2]); - printf(" r3=%08X r4=%08X r5=%08X r6=%08X\n", - (uint32_t)m_sh2_state->r[3], - (uint32_t)m_sh2_state->r[4], - (uint32_t)m_sh2_state->r[5], - (uint32_t)m_sh2_state->r[6]); - printf(" r7=%08X r8=%08X r9=%08X r10=%08X\n", - (uint32_t)m_sh2_state->r[7], - (uint32_t)m_sh2_state->r[8], - (uint32_t)m_sh2_state->r[9], - (uint32_t)m_sh2_state->r[10]); - printf(" r11=%08X r12=%08X r13=%08X r14=%08X\n", - (uint32_t)m_sh2_state->r[11], - (uint32_t)m_sh2_state->r[12], - (uint32_t)m_sh2_state->r[13], - (uint32_t)m_sh2_state->r[14]); - printf(" r15=%08X macl=%08X mach=%08X gbr=%08X\n", - (uint32_t)m_sh2_state->r[15], - (uint32_t)m_sh2_state->macl, - (uint32_t)m_sh2_state->mach, - (uint32_t)m_sh2_state->gbr); - printf(" evec %x irqsr %x pc=%08x\n", - (uint32_t)m_sh2_state->evec, - (uint32_t)m_sh2_state->irqsr, (uint32_t)m_sh2_state->pc); -} - -/*------------------------------------------------- - cfunc_unimplemented - handler for - unimplemented opcdes --------------------------------------------------*/ - -static void cfunc_unimplemented(void *param) -{ - ((sh2_device *)param)->func_unimplemented(); -} - -void sh2_device::func_unimplemented() -{ - // set up an invalid opcode exception - m_sh2_state->evec = RL( m_sh2_state->vbr + 4 * 4 ); - m_sh2_state->evec &= AM; - m_sh2_state->irqsr = m_sh2_state->sr; - // claim it's an NMI, because it pretty much is - m_sh2_state->pending_nmi = 1; -} - -/*------------------------------------------------- - cfunc_fastirq - checks for pending IRQs --------------------------------------------------*/ -static void cfunc_fastirq(void *param) -{ - ((sh2_device *)param)->func_fastirq(); -} - -void sh2_device::func_fastirq() -{ - sh2_exception("fastirq",m_sh2_state->irqline); -} - -/*------------------------------------------------- - cfunc_MAC_W - implementation of MAC_W Rm,Rn --------------------------------------------------*/ -static void cfunc_MAC_W(void *param) -{ - ((sh2_device *)param)->func_MAC_W(); -} - -void sh2_device::func_MAC_W() -{ - int32_t tempm, tempn, dest, src, ans; - uint32_t templ; - uint16_t opcode; - int n, m; - - // recover the opcode - opcode = m_sh2_state->arg0; - - // extract the operands - n = Rn; - m = Rm; - - tempn = (int32_t) RW( m_sh2_state->r[n] ); - m_sh2_state->r[n] += 2; - tempm = (int32_t) RW( m_sh2_state->r[m] ); - m_sh2_state->r[m] += 2; - templ = m_sh2_state->macl; - tempm = ((int32_t) (short) tempn * (int32_t) (short) tempm); - if ((int32_t) m_sh2_state->macl >= 0) - dest = 0; - else - dest = 1; - if ((int32_t) tempm >= 0) - { - src = 0; - tempn = 0; - } - else - { - src = 1; - tempn = 0xffffffff; - } - src += dest; - m_sh2_state->macl += tempm; - if ((int32_t) m_sh2_state->macl >= 0) - ans = 0; - else - ans = 1; - ans += dest; - if (m_sh2_state->sr & S) - { - if (ans == 1) - { - if ((m_cpu_type == CPU_TYPE_SH1) && ((src == 0) || (src == 2))) - { - m_sh2_state->mach |= 0x00000001; - } - - if (src == 0) - m_sh2_state->macl = 0x7fffffff; - if (src == 2) - m_sh2_state->macl = 0x80000000; - } - } - else - { - m_sh2_state->mach += tempn; - if (templ > m_sh2_state->macl) - m_sh2_state->mach += 1; - - // SH-1 has limited precision - if (m_cpu_type == CPU_TYPE_SH1) - { - if ((m_sh2_state->mach & 0x200) == 0) - { - m_sh2_state->mach &= 0x3ff; - } - else - { - m_sh2_state->mach |= 0xfffffc00; - } - } - - - } -} - -/*------------------------------------------------- - cfunc_MAC_L - implementation of MAC_L Rm,Rn --------------------------------------------------*/ -static void cfunc_MAC_L(void *param) -{ - ((sh2_device *)param)->func_MAC_L(); -} - -void sh2_device::func_MAC_L() -{ - uint32_t RnL, RnH, RmL, RmH, Res0, Res1, Res2; - uint32_t temp0, temp1, temp2, temp3; - int32_t tempm, tempn, fnLmL; - uint16_t opcode; - int n, m; - - // recover the opcode - opcode = m_sh2_state->arg0; - - // extract the operands - n = Rn; - m = Rm; - - tempn = (int32_t) RL( m_sh2_state->r[n] ); - m_sh2_state->r[n] += 4; - tempm = (int32_t) RL( m_sh2_state->r[m] ); - m_sh2_state->r[m] += 4; - if ((int32_t) (tempn ^ tempm) < 0) - fnLmL = -1; - else - fnLmL = 0; - if (tempn < 0) - tempn = 0 - tempn; - if (tempm < 0) - tempm = 0 - tempm; - temp1 = (uint32_t) tempn; - temp2 = (uint32_t) tempm; - RnL = temp1 & 0x0000ffff; - RnH = (temp1 >> 16) & 0x0000ffff; - RmL = temp2 & 0x0000ffff; - RmH = (temp2 >> 16) & 0x0000ffff; - temp0 = RmL * RnL; - temp1 = RmH * RnL; - temp2 = RmL * RnH; - temp3 = RmH * RnH; - Res2 = 0; - Res1 = temp1 + temp2; - if (Res1 < temp1) - Res2 += 0x00010000; - temp1 = (Res1 << 16) & 0xffff0000; - Res0 = temp0 + temp1; - if (Res0 < temp0) - Res2++; - Res2 = Res2 + ((Res1 >> 16) & 0x0000ffff) + temp3; - if (fnLmL < 0) - { - Res2 = ~Res2; - if (Res0 == 0) - Res2++; - else - Res0 = (~Res0) + 1; - } - if (m_sh2_state->sr & S) - { - Res0 = m_sh2_state->macl + Res0; - if (m_sh2_state->macl > Res0) - Res2++; - Res2 += (m_sh2_state->mach & 0x0000ffff); - if (((int32_t) Res2 < 0) && (Res2 < 0xffff8000)) - { - Res2 = 0x00008000; - Res0 = 0x00000000; - } - else if (((int32_t) Res2 > 0) && (Res2 > 0x00007fff)) - { - Res2 = 0x00007fff; - Res0 = 0xffffffff; - } - m_sh2_state->mach = Res2; - m_sh2_state->macl = Res0; - } - else - { - Res0 = m_sh2_state->macl + Res0; - if (m_sh2_state->macl > Res0) - Res2++; - Res2 += m_sh2_state->mach; - m_sh2_state->mach = Res2; - m_sh2_state->macl = Res0; - } -} - -/*------------------------------------------------- - cfunc_DIV1 - implementation of DIV1 Rm,Rn --------------------------------------------------*/ -static void cfunc_DIV1(void *param) -{ - ((sh2_device *)param)->func_DIV1(); -} - -void sh2_device::func_DIV1() -{ - uint32_t tmp0; - uint32_t old_q; - uint16_t opcode; - int n, m; - - // recover the opcode - opcode = m_sh2_state->arg0; - - // extract the operands - n = Rn; - m = Rm; - - old_q = m_sh2_state->sr & Q; - if (0x80000000 & m_sh2_state->r[n]) - m_sh2_state->sr |= Q; - else - m_sh2_state->sr &= ~Q; - - m_sh2_state->r[n] = (m_sh2_state->r[n] << 1) | (m_sh2_state->sr & T); - - if (!old_q) - { - if (!(m_sh2_state->sr & M)) - { - tmp0 = m_sh2_state->r[n]; - m_sh2_state->r[n] -= m_sh2_state->r[m]; - if(!(m_sh2_state->sr & Q)) - if(m_sh2_state->r[n] > tmp0) - m_sh2_state->sr |= Q; - else - m_sh2_state->sr &= ~Q; - else - if(m_sh2_state->r[n] > tmp0) - m_sh2_state->sr &= ~Q; - else - m_sh2_state->sr |= Q; - } - else - { - tmp0 = m_sh2_state->r[n]; - m_sh2_state->r[n] += m_sh2_state->r[m]; - if(!(m_sh2_state->sr & Q)) - { - if(m_sh2_state->r[n] < tmp0) - m_sh2_state->sr &= ~Q; - else - m_sh2_state->sr |= Q; - } - else - { - if(m_sh2_state->r[n] < tmp0) - m_sh2_state->sr |= Q; - else - m_sh2_state->sr &= ~Q; - } - } - } - else - { - if (!(m_sh2_state->sr & M)) - { - tmp0 = m_sh2_state->r[n]; - m_sh2_state->r[n] += m_sh2_state->r[m]; - if(!(m_sh2_state->sr & Q)) - if(m_sh2_state->r[n] < tmp0) - m_sh2_state->sr |= Q; - else - m_sh2_state->sr &= ~Q; - else - if(m_sh2_state->r[n] < tmp0) - m_sh2_state->sr &= ~Q; - else - m_sh2_state->sr |= Q; - } - else - { - tmp0 = m_sh2_state->r[n]; - m_sh2_state->r[n] -= m_sh2_state->r[m]; - if(!(m_sh2_state->sr & Q)) - if(m_sh2_state->r[n] > tmp0) - m_sh2_state->sr &= ~Q; - else - m_sh2_state->sr |= Q; - else - if(m_sh2_state->r[n] > tmp0) - m_sh2_state->sr |= Q; - else - m_sh2_state->sr &= ~Q; - } - } - - tmp0 = (m_sh2_state->sr & (Q | M)); - if((!tmp0) || (tmp0 == 0x300)) /* if Q == M set T else clear T */ - m_sh2_state->sr |= T; - else - m_sh2_state->sr &= ~T; -} - -#if (!ADDSUBV_DIRECT) -/*------------------------------------------------- - cfunc_ADDV - implementation of ADDV Rm,Rn --------------------------------------------------*/ -static void cfunc_ADDV(void *param) -{ - ((sh2_device *)param)->func_ADDV(); -} - -void sh2_device::func_ADDV() -{ - int32_t dest, src, ans; - uint16_t opcode; - int n, m; - - // recover the opcode - opcode = m_sh2_state->arg0; - - // extract the operands - n = Rn; - m = Rm; - - if ((int32_t) m_sh2_state->r[n] >= 0) - dest = 0; - else - dest = 1; - if ((int32_t) m_sh2_state->r[m] >= 0) - src = 0; - else - src = 1; - src += dest; - m_sh2_state->r[n] += m_sh2_state->r[m]; - if ((int32_t) m_sh2_state->r[n] >= 0) - ans = 0; - else - ans = 1; - ans += dest; - if (src == 0 || src == 2) - { - if (ans == 1) - m_sh2_state->sr |= T; - else - m_sh2_state->sr &= ~T; - } - else - m_sh2_state->sr &= ~T; -} - -/*------------------------------------------------- - cfunc_SUBV - implementation of SUBV Rm,Rn --------------------------------------------------*/ -static void cfunc_SUBV(void *param) -{ - ((sh2_device *)param)->func_SUBV(); -} - -void sh2_device::func_SUBV() -{ - int32_t dest, src, ans; - uint16_t opcode; - int n, m; - - // recover the opcode - opcode = m_sh2_state->arg0; - - // extract the operands - n = Rn; - m = Rm; - - if ((int32_t) m_sh2_state->r[n] >= 0) - dest = 0; - else - dest = 1; - if ((int32_t) m_sh2_state->r[m] >= 0) - src = 0; - else - src = 1; - src += dest; - m_sh2_state->r[n] -= m_sh2_state->r[m]; - if ((int32_t) m_sh2_state->r[n] >= 0) - ans = 0; - else - ans = 1; - ans += dest; - if (src == 1) - { - if (ans == 1) - m_sh2_state->sr |= T; - else - m_sh2_state->sr &= ~T; - } - else - m_sh2_state->sr &= ~T; -} -#else -void sh2_device::func_ADDV() {} -void sh2_device::func_SUBV() {} -#endif - -/*------------------------------------------------- - code_flush_cache - flush the cache and - regenerate static code --------------------------------------------------*/ - -void sh2_device::code_flush_cache() -{ - drcuml_state *drcuml = m_drcuml.get(); - - /* empty the transient cache contents */ - drcuml->reset(); - - try - { - /* generate the entry point and out-of-cycles handlers */ - static_generate_nocode_handler(); - static_generate_out_of_cycles(); - static_generate_entry_point(); - - /* add subroutines for memory accesses */ - static_generate_memory_accessor(1, false, "read8", &m_read8); - static_generate_memory_accessor(1, true, "write8", &m_write8); - static_generate_memory_accessor(2, false, "read16", &m_read16); - static_generate_memory_accessor(2, true, "write16", &m_write16); - static_generate_memory_accessor(4, false, "read32", &m_read32); - static_generate_memory_accessor(4, true, "write32", &m_write32); - } - catch (drcuml_block::abort_compilation &) - { - fatalerror("Unable to generate SH2 static code\n"); - } - - m_cache_dirty = false; -} - -/* Execute cycles - returns number of cycles actually run */ -void sh2_device::execute_run_drc() -{ - drcuml_state *drcuml = m_drcuml.get(); - int execute_result; - - // run any active DMAs now -#ifndef USE_TIMER_FOR_DMA - for ( int i = 0; i < m_sh2_state->icount ; i++) - { - for( int dma=0;dma<1;dma++) - { - if (m_dma_timer_active[dma]) - sh2_do_dma(dma); - } - } -#endif - - /* reset the cache if dirty */ - if (m_cache_dirty) - code_flush_cache(); - - /* execute */ - do - { - /* run as much as we can */ - execute_result = drcuml->execute(*m_entry); - - /* if we need to recompile, do it */ - if (execute_result == EXECUTE_MISSING_CODE) - { - code_compile_block(0, m_sh2_state->pc); - } - else if (execute_result == EXECUTE_UNMAPPED_CODE) - { - fatalerror("Attempted to execute unmapped code at PC=%08X\n", m_sh2_state->pc); - } - else if (execute_result == EXECUTE_RESET_CACHE) - { - code_flush_cache(); - } - } while (execute_result != EXECUTE_OUT_OF_CYCLES); -} - -/*------------------------------------------------- - code_compile_block - compile a block of the - given mode at the specified pc --------------------------------------------------*/ - -void sh2_device::code_compile_block(uint8_t mode, offs_t pc) -{ - drcuml_state *drcuml = m_drcuml.get(); - compiler_state compiler = { 0 }; - const opcode_desc *seqhead, *seqlast; - const opcode_desc *desclist; - bool override = false; - drcuml_block *block; - - g_profiler.start(PROFILER_DRC_COMPILE); - - /* get a description of this sequence */ - desclist = m_drcfe->describe_code(pc); - if (drcuml->logging() || drcuml->logging_native()) - log_opcode_desc(drcuml, desclist, 0); - - bool succeeded = false; - while (!succeeded) - { - try - { - /* start the block */ - block = drcuml->begin_block(4096); - - /* loop until we get through all instruction sequences */ - for (seqhead = desclist; seqhead != nullptr; seqhead = seqlast->next()) - { - const opcode_desc *curdesc; - uint32_t nextpc; - - /* add a code log entry */ - if (drcuml->logging()) - block->append_comment("-------------------------"); // comment - - /* determine the last instruction in this sequence */ - for (seqlast = seqhead; seqlast != nullptr; seqlast = seqlast->next()) - if (seqlast->flags & OPFLAG_END_SEQUENCE) - break; - assert(seqlast != nullptr); - - /* if we don't have a hash for this mode/pc, or if we are overriding all, add one */ - if (override || !drcuml->hash_exists(mode, seqhead->pc)) - UML_HASH(block, mode, seqhead->pc); // hash mode,pc - - /* if we already have a hash, and this is the first sequence, assume that we */ - /* are recompiling due to being out of sync and allow future overrides */ - else if (seqhead == desclist) - { - override = true; - UML_HASH(block, mode, seqhead->pc); // hash mode,pc - } - - /* otherwise, redispatch to that fixed PC and skip the rest of the processing */ - else - { - UML_LABEL(block, seqhead->pc | 0x80000000); // label seqhead->pc | 0x80000000 - UML_HASHJMP(block, 0, seqhead->pc, *m_nocode); - // hashjmp ,seqhead->pc,nocode - continue; - } - - /* validate this code block if we're not pointing into ROM */ - if (m_program->get_write_ptr(seqhead->physpc) != nullptr) - generate_checksum_block(block, &compiler, seqhead, seqlast); - - /* label this instruction, if it may be jumped to locally */ - if (seqhead->flags & OPFLAG_IS_BRANCH_TARGET) - { - UML_LABEL(block, seqhead->pc | 0x80000000); // label seqhead->pc | 0x80000000 - } - - /* iterate over instructions in the sequence and compile them */ - for (curdesc = seqhead; curdesc != seqlast->next(); curdesc = curdesc->next()) - { - generate_sequence_instruction(block, &compiler, curdesc, 0xffffffff); - } - - /* if we need to return to the start, do it */ - if (seqlast->flags & OPFLAG_RETURN_TO_START) - { - nextpc = pc; - } - /* otherwise we just go to the next instruction */ - else - { - nextpc = seqlast->pc + (seqlast->skipslots + 1) * 2; - } - - /* count off cycles and go there */ - generate_update_cycles(block, &compiler, nextpc, true); // - - /* SH2 has no modes */ - if (seqlast->next() == nullptr || seqlast->next()->pc != nextpc) - { - UML_HASHJMP(block, 0, nextpc, *m_nocode); - } - // hashjmp ,nextpc,nocode - } - - /* end the sequence */ - block->end(); - g_profiler.stop(); - succeeded = true; - } - catch (drcuml_block::abort_compilation &) - { - code_flush_cache(); - } - } -} - -/*------------------------------------------------- - static_generate_entry_point - generate a - static entry point --------------------------------------------------*/ - -void sh2_device::static_generate_entry_point() -{ - drcuml_state *drcuml = m_drcuml.get(); - code_label skip = 1; - drcuml_block *block; - - /* begin generating */ - block = drcuml->begin_block(200); - - /* forward references */ - alloc_handle(drcuml, &m_nocode, "nocode"); - alloc_handle(drcuml, &m_write32, "write32"); // necessary? - alloc_handle(drcuml, &m_entry, "entry"); - UML_HANDLE(block, *m_entry); // handle entry - - /* load fast integer registers */ - load_fast_iregs(block); - - /* check for interrupts */ - UML_MOV(block, mem(&m_sh2_state->irqline), 0xffffffff); // mov irqline, #-1 - UML_CMP(block, mem(&m_sh2_state->pending_nmi), 0); // cmp pending_nmi, #0 - UML_JMPc(block, COND_Z, skip+2); // jz skip+2 - - UML_MOV(block, mem(&m_sh2_state->pending_nmi), 0); // zap pending_nmi - UML_JMP(block, skip+1); // and then go take it (evec is already set) - - UML_LABEL(block, skip+2); // skip+2: - UML_MOV(block, mem(&m_sh2_state->evec), 0xffffffff); // mov evec, -1 - UML_MOV(block, I0, 0xffffffff); // mov r0, -1 (r0 = irq) - UML_AND(block, I1, I0, 0xffff); // and r1, 0xffff - - UML_LZCNT(block, I1, mem(&m_sh2_state->pending_irq)); // lzcnt r1, r1 - UML_CMP(block, I1, 32); // cmp r1, #32 - UML_JMPc(block, COND_Z, skip+4); // jz skip+4 - - UML_SUB(block, mem(&m_sh2_state->irqline), 31, I1); // sub irqline, #31, r1 - - UML_LABEL(block, skip+4); // skip+4: - UML_CMP(block, mem(&m_sh2_state->internal_irq_level), 0xffffffff); // cmp internal_irq_level, #-1 - UML_JMPc(block, COND_Z, skip+3); // jz skip+3 - UML_CMP(block, mem(&m_sh2_state->internal_irq_level), mem(&m_sh2_state->irqline)); // cmp internal_irq_level, irqline - UML_JMPc(block, COND_LE, skip+3); // jle skip+3 - - UML_MOV(block, mem(&m_sh2_state->irqline), mem(&m_sh2_state->internal_irq_level)); // mov r0, internal_irq_level - - UML_LABEL(block, skip+3); // skip+3: - UML_CMP(block, mem(&m_sh2_state->irqline), 0xffffffff); // cmp irqline, #-1 - UML_JMPc(block, COND_Z, skip+1); // jz skip+1 - UML_CALLC(block, cfunc_fastirq, this); // callc fastirq - - UML_LABEL(block, skip+1); // skip+1: - - UML_CMP(block, mem(&m_sh2_state->evec), 0xffffffff); // cmp evec, 0xffffffff - UML_JMPc(block, COND_Z, skip); // jz skip - - UML_SUB(block, R32(15), R32(15), 4); // sub R15, R15, #4 - UML_MOV(block, I0, R32(15)); // mov r0, R15 - UML_MOV(block, I1, mem(&m_sh2_state->irqsr)); // mov r1, irqsr - UML_CALLH(block, *m_write32); // call write32 - - UML_SUB(block, R32(15), R32(15), 4); // sub R15, R15, #4 - UML_MOV(block, I0, R32(15)); // mov r0, R15 - UML_MOV(block, I1, mem(&m_sh2_state->pc)); // mov r1, pc - UML_CALLH(block, *m_write32); // call write32 - - UML_MOV(block, mem(&m_sh2_state->pc), mem(&m_sh2_state->evec)); // mov pc, evec - - UML_LABEL(block, skip); // skip: - - /* generate a hash jump via the current mode and PC */ - UML_HASHJMP(block, 0, mem(&m_sh2_state->pc), *m_nocode); // hashjmp ,,nocode - - block->end(); -} - -/*------------------------------------------------- - static_generate_nocode_handler - generate an - exception handler for "out of code" --------------------------------------------------*/ - -void sh2_device::static_generate_nocode_handler() -{ - drcuml_state *drcuml = m_drcuml.get(); - drcuml_block *block; - - /* begin generating */ - block = drcuml->begin_block(10); - - /* generate a hash jump via the current mode and PC */ - alloc_handle(drcuml, &m_nocode, "nocode"); - UML_HANDLE(block, *m_nocode); // handle nocode - UML_GETEXP(block, I0); // getexp i0 - UML_MOV(block, mem(&m_sh2_state->pc), I0); // mov [pc],i0 - save_fast_iregs(block); - UML_EXIT(block, EXECUTE_MISSING_CODE); // exit EXECUTE_MISSING_CODE - - block->end(); -} - - -/*------------------------------------------------- - static_generate_out_of_cycles - generate an - out of cycles exception handler --------------------------------------------------*/ - -void sh2_device::static_generate_out_of_cycles() -{ - drcuml_state *drcuml = m_drcuml.get(); - drcuml_block *block; - - /* begin generating */ - block = drcuml->begin_block(10); - - /* generate a hash jump via the current mode and PC */ - alloc_handle(drcuml, &m_out_of_cycles, "out_of_cycles"); - UML_HANDLE(block, *m_out_of_cycles); // handle out_of_cycles - UML_GETEXP(block, I0); // getexp i0 - UML_MOV(block, mem(&m_sh2_state->pc), I0); // mov ,i0 - save_fast_iregs(block); - UML_EXIT(block, EXECUTE_OUT_OF_CYCLES); // exit EXECUTE_OUT_OF_CYCLES - - block->end(); -} - -/*------------------------------------------------------------------ - static_generate_memory_accessor -------------------------------------------------------------------*/ - -void sh2_device::static_generate_memory_accessor(int size, int iswrite, const char *name, code_handle **handleptr) -{ - /* on entry, address is in I0; data for writes is in I1 */ - /* on exit, read result is in I0 */ - /* routine trashes I0 */ - drcuml_state *drcuml = m_drcuml.get(); - drcuml_block *block; - int label = 1; - - /* begin generating */ - block = drcuml->begin_block(1024); - - /* add a global entry for this */ - alloc_handle(drcuml, handleptr, name); - UML_HANDLE(block, **handleptr); // handle *handleptr - - // with internal handlers this becomes easier. - // if addr < 0x40000000 AND it with AM and do the read/write, else just do the read/write - UML_TEST(block, I0, 0x80000000); // test r0, #0x80000000 - UML_JMPc(block, COND_NZ, label); // if high bit is set, don't mask - - UML_CMP(block, I0, 0x40000000); // cmp #0x40000000, r0 - UML_JMPc(block, COND_AE, label); // bae label - - UML_AND(block, I0, I0, AM); // and r0, r0, #AM (0xc7ffffff) - - UML_LABEL(block, label++); // label: - - for (auto & elem : m_fastram) - { - if (elem.base != nullptr && (!iswrite || !elem.readonly)) - { - void *fastbase = (uint8_t *)elem.base - elem.start; - uint32_t skip = label++; - if (elem.end != 0xffffffff) - { - UML_CMP(block, I0, elem.end); // cmp i0,end - UML_JMPc(block, COND_A, skip); // ja skip - } - if (elem.start != 0x00000000) - { - UML_CMP(block, I0, elem.start);// cmp i0,fastram_start - UML_JMPc(block, COND_B, skip); // jb skip - } - - if (!iswrite) - { - if (size == 1) - { - UML_XOR(block, I0, I0, BYTE4_XOR_BE(0)); - UML_LOAD(block, I0, fastbase, I0, SIZE_BYTE, SCALE_x1); // load i0,fastbase,i0,byte - } - else if (size == 2) - { - UML_XOR(block, I0, I0, WORD_XOR_BE(0)); - UML_LOAD(block, I0, fastbase, I0, SIZE_WORD, SCALE_x1); // load i0,fastbase,i0,word_x1 - } - else if (size == 4) - { - UML_LOAD(block, I0, fastbase, I0, SIZE_DWORD, SCALE_x1); // load i0,fastbase,i0,dword_x1 - } - UML_RET(block); // ret - } - else - { - if (size == 1) - { - UML_XOR(block, I0, I0, BYTE4_XOR_BE(0)); - UML_STORE(block, fastbase, I0, I1, SIZE_BYTE, SCALE_x1);// store fastbase,i0,i1,byte - } - else if (size == 2) - { - UML_XOR(block, I0, I0, WORD_XOR_BE(0)); - UML_STORE(block, fastbase, I0, I1, SIZE_WORD, SCALE_x1);// store fastbase,i0,i1,word_x1 - } - else if (size == 4) - { - UML_STORE(block, fastbase, I0, I1, SIZE_DWORD, SCALE_x1); // store fastbase,i0,i1,dword_x1 - } - UML_RET(block); // ret - } - - UML_LABEL(block, skip); // skip: - } - } - - if (iswrite) - { - switch (size) - { - case 1: - UML_WRITE(block, I0, I1, SIZE_BYTE, SPACE_PROGRAM); // write r0, r1, program_byte - break; - - case 2: - UML_WRITE(block, I0, I1, SIZE_WORD, SPACE_PROGRAM); // write r0, r1, program_word - break; - - case 4: - UML_WRITE(block, I0, I1, SIZE_DWORD, SPACE_PROGRAM); // write r0, r1, program_dword - break; - } - } - else - { - switch (size) - { - case 1: - UML_READ(block, I0, I0, SIZE_BYTE, SPACE_PROGRAM); // read r0, program_byte - break; - - case 2: - UML_READ(block, I0, I0, SIZE_WORD, SPACE_PROGRAM); // read r0, program_word - break; - - case 4: - UML_READ(block, I0, I0, SIZE_DWORD, SPACE_PROGRAM); // read r0, program_dword - break; - } - } - - UML_RET(block); // ret - - block->end(); -} - -/*------------------------------------------------- - log_desc_flags_to_string - generate a string - representing the instruction description - flags --------------------------------------------------*/ - -const char *sh2_device::log_desc_flags_to_string(uint32_t flags) -{ - static char tempbuf[30]; - char *dest = tempbuf; - - /* branches */ - if (flags & OPFLAG_IS_UNCONDITIONAL_BRANCH) - *dest++ = 'U'; - else if (flags & OPFLAG_IS_CONDITIONAL_BRANCH) - *dest++ = 'C'; - else - *dest++ = '.'; - - /* intrablock branches */ - *dest++ = (flags & OPFLAG_INTRABLOCK_BRANCH) ? 'i' : '.'; - - /* branch targets */ - *dest++ = (flags & OPFLAG_IS_BRANCH_TARGET) ? 'B' : '.'; - - /* delay slots */ - *dest++ = (flags & OPFLAG_IN_DELAY_SLOT) ? 'D' : '.'; - - /* exceptions */ - if (flags & OPFLAG_WILL_CAUSE_EXCEPTION) - *dest++ = 'E'; - else if (flags & OPFLAG_CAN_CAUSE_EXCEPTION) - *dest++ = 'e'; - else - *dest++ = '.'; - - /* read/write */ - if (flags & OPFLAG_READS_MEMORY) - *dest++ = 'R'; - else if (flags & OPFLAG_WRITES_MEMORY) - *dest++ = 'W'; - else - *dest++ = '.'; - - /* TLB validation */ - *dest++ = (flags & OPFLAG_VALIDATE_TLB) ? 'V' : '.'; - - /* TLB modification */ - *dest++ = (flags & OPFLAG_MODIFIES_TRANSLATION) ? 'T' : '.'; - - /* redispatch */ - *dest++ = (flags & OPFLAG_REDISPATCH) ? 'R' : '.'; - return tempbuf; -} - - -/*------------------------------------------------- - log_register_list - log a list of GPR registers --------------------------------------------------*/ - -void sh2_device::log_register_list(drcuml_state *drcuml, const char *string, const uint32_t *reglist, const uint32_t *regnostarlist) -{ - int count = 0; - int regnum; - - /* skip if nothing */ - if (reglist[0] == 0 && reglist[1] == 0 && reglist[2] == 0) - return; - - drcuml->log_printf("[%s:", string); - - for (regnum = 0; regnum < 16; regnum++) - { - if (reglist[0] & REGFLAG_R(regnum)) - { - drcuml->log_printf("%sr%d", (count++ == 0) ? "" : ",", regnum); - if (regnostarlist != nullptr && !(regnostarlist[0] & REGFLAG_R(regnum))) - drcuml->log_printf("*"); - } - } - - if (reglist[1] & REGFLAG_PR) - { - drcuml->log_printf("%spr", (count++ == 0) ? "" : ","); - if (regnostarlist != nullptr && !(regnostarlist[1] & REGFLAG_PR)) - drcuml->log_printf("*"); - } - - if (reglist[1] & REGFLAG_SR) - { - drcuml->log_printf("%ssr", (count++ == 0) ? "" : ","); - if (regnostarlist != nullptr && !(regnostarlist[1] & REGFLAG_SR)) - drcuml->log_printf("*"); - } - - if (reglist[1] & REGFLAG_MACL) - { - drcuml->log_printf("%smacl", (count++ == 0) ? "" : ","); - if (regnostarlist != nullptr && !(regnostarlist[1] & REGFLAG_MACL)) - drcuml->log_printf("*"); - } - - if (reglist[1] & REGFLAG_MACH) - { - drcuml->log_printf("%smach", (count++ == 0) ? "" : ","); - if (regnostarlist != nullptr && !(regnostarlist[1] & REGFLAG_MACH)) - drcuml->log_printf("*"); - } - - if (reglist[1] & REGFLAG_GBR) - { - drcuml->log_printf("%sgbr", (count++ == 0) ? "" : ","); - if (regnostarlist != nullptr && !(regnostarlist[1] & REGFLAG_GBR)) - drcuml->log_printf("*"); - } - - if (reglist[1] & REGFLAG_VBR) - { - drcuml->log_printf("%svbr", (count++ == 0) ? "" : ","); - if (regnostarlist != nullptr && !(regnostarlist[1] & REGFLAG_VBR)) - drcuml->log_printf("*"); - } - - drcuml->log_printf("] "); -} - -/*------------------------------------------------- - log_opcode_desc - log a list of descriptions --------------------------------------------------*/ - -void sh2_device::log_opcode_desc(drcuml_state *drcuml, const opcode_desc *desclist, int indent) -{ - /* open the file, creating it if necessary */ - if (indent == 0) - drcuml->log_printf("\nDescriptor list @ %08X\n", desclist->pc); - - /* output each descriptor */ - for ( ; desclist != nullptr; desclist = desclist->next()) - { - std::ostringstream stream; - - /* disassemle the current instruction and output it to the log */ - if (drcuml->logging() || drcuml->logging_native()) - { - if (desclist->flags & OPFLAG_VIRTUAL_NOOP) - stream << ""; - else - DasmSH2(stream, desclist->pc, desclist->opptr.w[0]); - } - else - stream << "???"; - drcuml->log_printf("%08X [%08X] t:%08X f:%s: %-30s", desclist->pc, desclist->physpc, desclist->targetpc, log_desc_flags_to_string(desclist->flags), stream.str().c_str()); - - /* output register states */ - log_register_list(drcuml, "use", desclist->regin, nullptr); - log_register_list(drcuml, "mod", desclist->regout, desclist->regreq); - drcuml->log_printf("\n"); - - /* if we have a delay slot, output it recursively */ - if (desclist->delay.first() != nullptr) - log_opcode_desc(drcuml, desclist->delay.first(), indent + 1); - - /* at the end of a sequence add a dividing line */ - if (desclist->flags & OPFLAG_END_SEQUENCE) - drcuml->log_printf("-----\n"); - } -} - -/*------------------------------------------------- - log_add_disasm_comment - add a comment - including disassembly of an SH2 instruction --------------------------------------------------*/ - -void sh2_device::log_add_disasm_comment(drcuml_block *block, uint32_t pc, uint32_t op) -{ - if (m_drcuml->logging()) - { - std::ostringstream stream; - DasmSH2(stream, pc, op); - block->append_comment("%08X: %s", pc, stream.str().c_str()); - } -} - -/*------------------------------------------------- - generate_update_cycles - generate code to - subtract cycles from the icount and generate - an exception if out --------------------------------------------------*/ -void sh2_device::generate_update_cycles(drcuml_block *block, compiler_state *compiler, uml::parameter param, bool allow_exception) -{ - /* check full interrupts if pending */ - if (compiler->checkints) - { - code_label skip = compiler->labelnum++; - - compiler->checkints = false; - compiler->labelnum += 4; - - /* check for interrupts */ - UML_MOV(block, mem(&m_sh2_state->irqline), 0xffffffff); // mov irqline, #-1 - UML_CMP(block, mem(&m_sh2_state->pending_nmi), 0); // cmp pending_nmi, #0 - UML_JMPc(block, COND_Z, skip+2); // jz skip+2 - - UML_MOV(block, mem(&m_sh2_state->pending_nmi), 0); // zap pending_nmi - UML_JMP(block, skip+1); // and then go take it (evec is already set) - - UML_LABEL(block, skip+2); // skip+2: - UML_MOV(block, mem(&m_sh2_state->evec), 0xffffffff); // mov evec, -1 - UML_MOV(block, I0, 0xffffffff); // mov r0, -1 (r0 = irq) - UML_AND(block, I1, I0, 0xffff); // and r1, r0, 0xffff - - UML_LZCNT(block, I1, mem(&m_sh2_state->pending_irq)); // lzcnt r1, pending_irq - UML_CMP(block, I1, 32); // cmp r1, #32 - UML_JMPc(block, COND_Z, skip+4); // jz skip+4 - - UML_SUB(block, mem(&m_sh2_state->irqline), 31, I1); // sub irqline, #31, r1 - - UML_LABEL(block, skip+4); // skip+4: - UML_CMP(block, mem(&m_sh2_state->internal_irq_level), 0xffffffff); // cmp internal_irq_level, #-1 - UML_JMPc(block, COND_Z, skip+3); // jz skip+3 - UML_CMP(block, mem(&m_sh2_state->internal_irq_level), mem(&m_sh2_state->irqline)); // cmp internal_irq_level, irqline - UML_JMPc(block, COND_LE, skip+3); // jle skip+3 - - UML_MOV(block, mem(&m_sh2_state->irqline), mem(&m_sh2_state->internal_irq_level)); // mov r0, internal_irq_level - - UML_LABEL(block, skip+3); // skip+3: - UML_CMP(block, mem(&m_sh2_state->irqline), 0xffffffff); // cmp irqline, #-1 - UML_JMPc(block, COND_Z, skip+1); // jz skip+1 - UML_CALLC(block, cfunc_fastirq, this); // callc fastirq - - UML_LABEL(block, skip+1); // skip+1: - UML_CMP(block, mem(&m_sh2_state->evec), 0xffffffff); // cmp evec, 0xffffffff - UML_JMPc(block, COND_Z, skip); // jz skip - - UML_SUB(block, R32(15), R32(15), 4); // sub R15, R15, #4 - UML_MOV(block, I0, R32(15)); // mov r0, R15 - UML_MOV(block, I1, mem(&m_sh2_state->irqsr)); // mov r1, irqsr - UML_CALLH(block, *m_write32); // call write32 - - UML_SUB(block, R32(15), R32(15), 4); // sub R15, R15, #4 - UML_MOV(block, I0, R32(15)); // mov r0, R15 - UML_MOV(block, I1, param); // mov r1, nextpc - UML_CALLH(block, *m_write32); // call write32 - - UML_HASHJMP(block, 0, mem(&m_sh2_state->evec), *m_nocode); // hashjmp m_sh2_state->evec - - UML_LABEL(block, skip); // skip: - } - - /* account for cycles */ - if (compiler->cycles > 0) - { - UML_SUB(block, mem(&m_sh2_state->icount), mem(&m_sh2_state->icount), MAPVAR_CYCLES); // sub icount,icount,cycles - UML_MAPVAR(block, MAPVAR_CYCLES, 0); // mapvar cycles,0 - if (allow_exception) - UML_EXHc(block, COND_S, *m_out_of_cycles, param); - // exh out_of_cycles,nextpc - } - compiler->cycles = 0; -} - -/*------------------------------------------------- - generate_checksum_block - generate code to - validate a sequence of opcodes --------------------------------------------------*/ - -void sh2_device::generate_checksum_block(drcuml_block *block, compiler_state *compiler, const opcode_desc *seqhead, const opcode_desc *seqlast) -{ - const opcode_desc *curdesc; - if (m_drcuml->logging()) - block->append_comment("[Validation for %08X]", seqhead->pc); // comment - - /* loose verify or single instruction: just compare and fail */ - if (!(m_drcoptions & SH2DRC_STRICT_VERIFY) || seqhead->next() == nullptr) - { - if (!(seqhead->flags & OPFLAG_VIRTUAL_NOOP)) - { - void *base = m_direct->read_ptr(seqhead->physpc, SH2_CODE_XOR(0)); - UML_LOAD(block, I0, base, 0, SIZE_WORD, SCALE_x2); // load i0,base,word - UML_CMP(block, I0, seqhead->opptr.w[0]); // cmp i0,*opptr - UML_EXHc(block, COND_NE, *m_nocode, epc(seqhead)); // exne nocode,seqhead->pc - } - } - - /* full verification; sum up everything */ - else - { -#if 0 - for (curdesc = seqhead->next(); curdesc != seqlast->next(); curdesc = curdesc->next()) - if (!(curdesc->flags & OPFLAG_VIRTUAL_NOOP)) - { - base = m_direct->read_ptr(curdesc->physpc, SH2_CODE_XOR(0)); - UML_LOAD(block, I0, curdesc->opptr.w, 0, SIZE_WORD, SCALE_x2); // load i0,*opptr,0,word - UML_CMP(block, I0, curdesc->opptr.w[0]); // cmp i0,*opptr - UML_EXHc(block, COND_NE, *m_nocode, epc(seqhead)); // exne nocode,seqhead->pc - } -#else - uint32_t sum = 0; - void *base = m_direct->read_ptr(seqhead->physpc, SH2_CODE_XOR(0)); - UML_LOAD(block, I0, base, 0, SIZE_WORD, SCALE_x4); // load i0,base,word - sum += seqhead->opptr.w[0]; - for (curdesc = seqhead->next(); curdesc != seqlast->next(); curdesc = curdesc->next()) - if (!(curdesc->flags & OPFLAG_VIRTUAL_NOOP)) - { - base = m_direct->read_ptr(curdesc->physpc, SH2_CODE_XOR(0)); - UML_LOAD(block, I1, base, 0, SIZE_WORD, SCALE_x2); // load i1,*opptr,word - UML_ADD(block, I0, I0, I1); // add i0,i0,i1 - sum += curdesc->opptr.w[0]; - } - UML_CMP(block, I0, sum); // cmp i0,sum - UML_EXHc(block, COND_NE, *m_nocode, epc(seqhead)); // exne nocode,seqhead->pc -#endif - } -} - - -/*------------------------------------------------- - generate_sequence_instruction - generate code - for a single instruction in a sequence --------------------------------------------------*/ - -void sh2_device::generate_sequence_instruction(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint32_t ovrpc) -{ - offs_t expc; - - /* add an entry for the log */ - if (m_drcuml->logging() && !(desc->flags & OPFLAG_VIRTUAL_NOOP)) - log_add_disasm_comment(block, desc->pc, desc->opptr.w[0]); - - /* set the PC map variable */ - expc = (desc->flags & OPFLAG_IN_DELAY_SLOT) ? desc->pc - 1 : desc->pc; - UML_MAPVAR(block, MAPVAR_PC, expc); // mapvar PC,expc - - /* accumulate total cycles */ - compiler->cycles += desc->cycles; - - /* update the icount map variable */ - UML_MAPVAR(block, MAPVAR_CYCLES, compiler->cycles); // mapvar CYCLES,compiler->cycles - - /* if we want a probe, add it here */ - if (desc->pc == PROBE_ADDRESS) - { - UML_MOV(block, mem(&m_sh2_state->pc), desc->pc); // mov [pc],desc->pc - UML_CALLC(block, cfunc_printf_probe, this); // callc cfunc_printf_probe,sh2 - } - - /* if we are debugging, call the debugger */ - if ((machine().debug_flags & DEBUG_FLAG_ENABLED) != 0) - { - UML_MOV(block, mem(&m_sh2_state->pc), desc->pc); // mov [pc],desc->pc - save_fast_iregs(block); - UML_DEBUG(block, desc->pc); // debug desc->pc - } - else // not debug, see what other reasons there are for flushing the PC - { - if (m_drcoptions & SH2DRC_FLUSH_PC) // always flush? - { - UML_MOV(block, mem(&m_sh2_state->pc), desc->pc); // mov m_sh2_state->pc, desc->pc - } - else // check for driver-selected flushes - { - int pcflush; - - for (pcflush = 0; pcflush < m_pcfsel; pcflush++) - { - if (desc->pc == m_pcflushes[pcflush]) - { - UML_MOV(block, mem(&m_sh2_state->pc), desc->pc); // mov m_sh2_state->pc, desc->pc - } - } - } - } - - - /* if we hit an unmapped address, fatal error */ - if (desc->flags & OPFLAG_COMPILER_UNMAPPED) - { - UML_MOV(block, mem(&m_sh2_state->pc), desc->pc); // mov [pc],desc->pc - save_fast_iregs(block); - UML_EXIT(block, EXECUTE_UNMAPPED_CODE); // exit EXECUTE_UNMAPPED_CODE - } - - /* if this is an invalid opcode, die */ - if (desc->flags & OPFLAG_INVALID_OPCODE) - { - fatalerror("SH2DRC: invalid opcode!\n"); - } - - /* otherwise, unless this is a virtual no-op, it's a regular instruction */ - else if (!(desc->flags & OPFLAG_VIRTUAL_NOOP)) - { - /* compile the instruction */ - if (!generate_opcode(block, compiler, desc, ovrpc)) - { - // handle an illegal op - UML_MOV(block, mem(&m_sh2_state->pc), desc->pc); // mov [pc],desc->pc - UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr.w[0]); // mov [arg0],opcode - UML_CALLC(block, cfunc_unimplemented, this); // callc cfunc_unimplemented - } - } -} - -/*------------------------------------------------------------------ - generate_delay_slot -------------------------------------------------------------------*/ - -void sh2_device::generate_delay_slot(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint32_t ovrpc) -{ - compiler_state compiler_temp = *compiler; - - /* compile the delay slot using temporary compiler state */ - assert(desc->delay.first() != nullptr); - generate_sequence_instruction(block, &compiler_temp, desc->delay.first(), ovrpc); // - - /* update the label */ - compiler->labelnum = compiler_temp.labelnum; -} - -/*------------------------------------------------- - generate_opcode - generate code for a specific - opcode --------------------------------------------------*/ - -bool sh2_device::generate_opcode(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint32_t ovrpc) -{ - uint32_t scratch, scratch2; - int32_t disp; - uint16_t opcode = desc->opptr.w[0]; - uint8_t opswitch = opcode >> 12; - int in_delay_slot = ((desc->flags & OPFLAG_IN_DELAY_SLOT) != 0); - - switch (opswitch) - { - case 0: - return generate_group_0(block, compiler, desc, opcode, in_delay_slot, ovrpc); - - case 1: // MOVLS4 - scratch = (opcode & 0x0f) * 4; - UML_ADD(block, I0, R32(Rn), scratch); // add r0, Rn, scratch - UML_MOV(block, I1, R32(Rm)); // mov r1, Rm - SETEA(0); // set ea for debug - UML_CALLH(block, *m_write32); - - if (!in_delay_slot) - generate_update_cycles(block, compiler, desc->pc + 2, true); - return true; - - case 2: - return generate_group_2(block, compiler, desc, opcode, in_delay_slot, ovrpc); - case 3: - return generate_group_3(block, compiler, desc, opcode, ovrpc); - case 4: - return generate_group_4(block, compiler, desc, opcode, in_delay_slot, ovrpc); - - case 5: // MOVLL4 - scratch = (opcode & 0x0f) * 4; - UML_ADD(block, I0, R32(Rm), scratch); // add r0, Rm, scratch - SETEA(0); // set ea for debug - UML_CALLH(block, *m_read32); // call read32 - UML_MOV(block, R32(Rn), I0); // mov Rn, r0 - - if (!in_delay_slot) - generate_update_cycles(block, compiler, desc->pc + 2, true); - return true; - - case 6: - return generate_group_6(block, compiler, desc, opcode, in_delay_slot, ovrpc); - - case 7: // ADDI - scratch = opcode & 0xff; - scratch2 = (uint32_t)(int32_t)(int16_t)(int8_t)scratch; - UML_ADD(block, R32(Rn), R32(Rn), scratch2); // add Rn, Rn, scratch2 - return true; - - case 8: - return generate_group_8(block, compiler, desc, opcode, in_delay_slot, ovrpc); - - case 9: // MOVWI - if (ovrpc == 0xffffffff) - { - scratch = (desc->pc + 2) + ((opcode & 0xff) * 2) + 2; - } - else - { - scratch = (ovrpc + 2) + ((opcode & 0xff) * 2) + 2; - } - - if (m_drcoptions & SH2DRC_STRICT_PCREL) - { - UML_MOV(block, I0, scratch); // mov r0, scratch - SETEA(0); // set ea for debug - UML_CALLH(block, *m_read16); // read16(r0, r1) - UML_SEXT(block, R32(Rn), I0, SIZE_WORD); // sext Rn, r0, WORD - } - else - { - scratch2 = (uint32_t)(int32_t)(int16_t) RW(scratch); - UML_MOV(block, R32(Rn), scratch2); // mov Rn, scratch2 - } - - if (!in_delay_slot) - generate_update_cycles(block, compiler, desc->pc + 2, true); - return true; - - case 10: // BRA - disp = ((int32_t)opcode << 20) >> 20; - m_sh2_state->ea = (desc->pc + 2) + disp * 2 + 2; // m_sh2_state->ea = pc+4 + disp*2 + 2 - - generate_delay_slot(block, compiler, desc, m_sh2_state->ea-2); - - generate_update_cycles(block, compiler, m_sh2_state->ea, true); // - UML_HASHJMP(block, 0, m_sh2_state->ea, *m_nocode); // hashjmp m_sh2_state->ea - return true; - - case 11: // BSR - // panicstr @ 403da22 relies on the delay slot clobbering the PR set by a BSR, so - // do this before running the delay slot - UML_ADD(block, mem(&m_sh2_state->pr), desc->pc, 4); // add m_pr, desc->pc, #4 (skip the current insn & delay slot) - - disp = ((int32_t)opcode << 20) >> 20; - m_sh2_state->ea = (desc->pc + 2) + disp * 2 + 2; // m_sh2_state->ea = pc+4 + disp*2 + 2 - - generate_delay_slot(block, compiler, desc, m_sh2_state->ea-2); - - generate_update_cycles(block, compiler, m_sh2_state->ea, true); // - UML_HASHJMP(block, 0, m_sh2_state->ea, *m_nocode); // hashjmp m_sh2_state->ea - return true; - - case 12: - return generate_group_12(block, compiler, desc, opcode, in_delay_slot, ovrpc); - - case 13: // MOVLI - if (ovrpc == 0xffffffff) - { - scratch = ((desc->pc + 4) & ~3) + ((opcode & 0xff) * 4); - } - else - { - scratch = ((ovrpc + 4) & ~3) + ((opcode & 0xff) * 4); - } - - if (m_drcoptions & SH2DRC_STRICT_PCREL) - { - UML_MOV(block, I0, scratch); // mov r0, scratch - UML_CALLH(block, *m_read32); // read32(r0, r1) - UML_MOV(block, R32(Rn), I0); // mov Rn, r0 - } - else - { - scratch2 = RL(scratch); - UML_MOV(block, R32(Rn), scratch2); // mov Rn, scratch2 - } - - if (!in_delay_slot) - generate_update_cycles(block, compiler, desc->pc + 2, true); - return true; - - case 14: // MOVI - scratch = opcode & 0xff; - scratch2 = (uint32_t)(int32_t)(int16_t)(int8_t)scratch; - UML_MOV(block, R32(Rn), scratch2); - return true; - - case 15: - return false; - } - - return false; -} - -bool sh2_device::generate_group_0(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc) -{ - switch (opcode & 0x3F) - { - case 0x00: // these are all illegal - case 0x01: - case 0x10: - case 0x11: - case 0x13: - case 0x20: - case 0x21: - case 0x30: - case 0x31: - case 0x32: - case 0x33: - case 0x38: - case 0x39: - case 0x3a: - case 0x3b: - return false; - - case 0x09: // NOP(); - return true; - - case 0x02: // STCSR(Rn); - UML_MOV(block, R32(Rn), mem(&m_sh2_state->sr)); - return true; - - case 0x03: // BSRF(Rn); - if (m_cpu_type > CPU_TYPE_SH1) - { - UML_ADD(block, mem(&m_sh2_state->target), R32(Rn), 4); // add target, Rm, #4 - UML_ADD(block, mem(&m_sh2_state->target), mem(&m_sh2_state->target), desc->pc); // add target, target, pc - - // 32x Cosmic Carnage @ 6002cb0 relies on the delay slot - // clobbering the calculated PR, so do it first - UML_ADD(block, mem(&m_sh2_state->pr), desc->pc, 4); // add m_pr, desc->pc, #4 (skip the current insn & delay slot) - - generate_delay_slot(block, compiler, desc, m_sh2_state->target); - - generate_update_cycles(block, compiler, mem(&m_sh2_state->target), true); // - UML_HASHJMP(block, 0, mem(&m_sh2_state->target), *m_nocode); // jmp target - return true; - } - break; - - case 0x04: // MOVBS0(Rm, Rn); - case 0x14: // MOVBS0(Rm, Rn); - case 0x24: // MOVBS0(Rm, Rn); - case 0x34: // MOVBS0(Rm, Rn); - UML_ADD(block, I0, R32(0), R32(Rn)); // add r0, R0, Rn - UML_AND(block, I1, R32(Rm), 0x000000ff); // and r1, Rm, 0xff - UML_CALLH(block, *m_write8); // call write8 - - if (!in_delay_slot) - generate_update_cycles(block, compiler, desc->pc + 2, true); - return true; - - case 0x05: // MOVWS0(Rm, Rn); - case 0x15: // MOVWS0(Rm, Rn); - case 0x25: // MOVWS0(Rm, Rn); - case 0x35: // MOVWS0(Rm, Rn); - UML_ADD(block, I0, R32(0), R32(Rn)); // add r0, R0, Rn - UML_AND(block, I1, R32(Rm), 0x0000ffff); // and r1, Rm, 0xffff - UML_CALLH(block, *m_write16); // call write16 - - if (!in_delay_slot) - generate_update_cycles(block, compiler, desc->pc + 2, true); - return true; - - case 0x06: // MOVLS0(Rm, Rn); - case 0x16: // MOVLS0(Rm, Rn); - case 0x26: // MOVLS0(Rm, Rn); - case 0x36: // MOVLS0(Rm, Rn); - UML_ADD(block, I0, R32(0), R32(Rn)); // add r0, R0, Rn - UML_MOV(block, I1, R32(Rm)); // mov r1, Rm - UML_CALLH(block, *m_write32); // call write32 - - if (!in_delay_slot) - generate_update_cycles(block, compiler, desc->pc + 2, true); - return true; - - case 0x07: // MULL(Rm, Rn); - case 0x17: // MULL(Rm, Rn); - case 0x27: // MULL(Rm, Rn); - case 0x37: // MULL(Rm, Rn); - if (m_cpu_type > CPU_TYPE_SH1) - { - UML_MULU(block, mem(&m_sh2_state->macl), mem(&m_sh2_state->ea), R32(Rn), R32(Rm)); // mulu macl, ea, Rn, Rm - return true; - } - break; - - case 0x08: // CLRT(); - UML_AND(block, mem(&m_sh2_state->sr), mem(&m_sh2_state->sr), ~T); // and r0, sr, ~T (clear the T bit) - return true; - - case 0x0a: // STSMACH(Rn); - UML_MOV(block, R32(Rn), mem(&m_sh2_state->mach)); // mov Rn, mach - return true; - - case 0x0b: // RTS(); - UML_MOV(block, mem(&m_sh2_state->target), mem(&m_sh2_state->pr)); // mov target, pr (in case of d-slot shenanigans) - - generate_delay_slot(block, compiler, desc, m_sh2_state->target); - - generate_update_cycles(block, compiler, mem(&m_sh2_state->target), true); // - UML_HASHJMP(block, 0, mem(&m_sh2_state->target), *m_nocode); - return true; - - case 0x0c: // MOVBL0(Rm, Rn); - case 0x1c: // MOVBL0(Rm, Rn); - case 0x2c: // MOVBL0(Rm, Rn); - case 0x3c: // MOVBL0(Rm, Rn); - UML_ADD(block, I0, R32(0), R32(Rm)); // add r0, R0, Rm - UML_CALLH(block, *m_read8); // call read8 - UML_SEXT(block, R32(Rn), I0, SIZE_BYTE); // sext Rn, r0, BYTE - - if (!in_delay_slot) - generate_update_cycles(block, compiler, desc->pc + 2, true); - return true; - - case 0x0d: // MOVWL0(Rm, Rn); - case 0x1d: // MOVWL0(Rm, Rn); - case 0x2d: // MOVWL0(Rm, Rn); - case 0x3d: // MOVWL0(Rm, Rn); - UML_ADD(block, I0, R32(0), R32(Rm)); // add r0, R0, Rm - UML_CALLH(block, *m_read16); // call read16 - UML_SEXT(block, R32(Rn), I0, SIZE_WORD); // sext Rn, r0, WORD - - if (!in_delay_slot) - generate_update_cycles(block, compiler, desc->pc + 2, true); - return true; - - case 0x0e: // MOVLL0(Rm, Rn); - case 0x1e: // MOVLL0(Rm, Rn); - case 0x2e: // MOVLL0(Rm, Rn); - case 0x3e: // MOVLL0(Rm, Rn); - UML_ADD(block, I0, R32(0), R32(Rm)); // add r0, R0, Rm - UML_CALLH(block, *m_read32); // call read32 - UML_MOV(block, R32(Rn), I0); // mov Rn, r0 - - if (!in_delay_slot) - generate_update_cycles(block, compiler, desc->pc + 2, true); - return true; - - case 0x0f: // MAC_L(Rm, Rn); - case 0x1f: // MAC_L(Rm, Rn); - case 0x2f: // MAC_L(Rm, Rn); - case 0x3f: // MAC_L(Rm, Rn); - if (m_cpu_type > CPU_TYPE_SH1) - { - save_fast_iregs(block); - UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr.w[0]); - UML_CALLC(block, cfunc_MAC_L, this); - load_fast_iregs(block); - return true; - } - break; - - case 0x12: // STCGBR(Rn); - UML_MOV(block, R32(Rn), mem(&m_sh2_state->gbr)); // mov Rn, gbr - return true; - - case 0x18: // SETT(); - UML_OR(block, mem(&m_sh2_state->sr), mem(&m_sh2_state->sr), T); // or sr, sr, T - return true; - - case 0x19: // DIV0U(); - UML_AND(block, mem(&m_sh2_state->sr), mem(&m_sh2_state->sr), ~(M|Q|T)); // and sr, sr, ~(M|Q|T) - return true; - - case 0x1a: // STSMACL(Rn); - UML_MOV(block, R32(Rn), mem(&m_sh2_state->macl)); // mov Rn, macl - return true; - - case 0x1b: // SLEEP(); - UML_MOV(block, I0, mem(&m_sh2_state->sleep_mode)); // mov i0, sleep_mode - UML_CMP(block, I0, 0x2); // cmp i0, #2 - UML_JMPc(block, COND_E, compiler->labelnum); // beq labelnum - // sleep mode != 2 - UML_MOV(block, mem(&m_sh2_state->sleep_mode), 0x1); // mov sleep_mode, #1 - generate_update_cycles(block, compiler, desc->pc, true); // repeat this insn - UML_JMP(block, compiler->labelnum+1); // jmp labelnum+1 - - UML_LABEL(block, compiler->labelnum++); // labelnum: - // sleep_mode == 2 - UML_MOV(block, mem(&m_sh2_state->sleep_mode), 0x0); // sleep_mode = 0 - generate_update_cycles(block, compiler, desc->pc+2, true); // go to next insn - - UML_LABEL(block, compiler->labelnum++); // labelnum+1: - return true; - - case 0x22: // STCVBR(Rn); - UML_MOV(block, R32(Rn), mem(&m_sh2_state->vbr)); // mov Rn, vbr - return true; - - case 0x23: // BRAF(Rn); - if (m_cpu_type > CPU_TYPE_SH1) - { - UML_ADD(block, mem(&m_sh2_state->target), R32(Rn), desc->pc+4); // add target, Rn, pc+4 - - generate_delay_slot(block, compiler, desc, m_sh2_state->target); - - generate_update_cycles(block, compiler, mem(&m_sh2_state->target), true); // - UML_HASHJMP(block, 0, mem(&m_sh2_state->target), *m_nocode); // jmp target - return true; - } - break; - - case 0x28: // CLRMAC(); - UML_MOV(block, mem(&m_sh2_state->macl), 0); // mov macl, #0 - UML_MOV(block, mem(&m_sh2_state->mach), 0); // mov mach, #0 - return true; - - case 0x29: // MOVT(Rn); - UML_AND(block, R32(Rn), mem(&m_sh2_state->sr), T); // and Rn, sr, T - return true; - - case 0x2a: // STSPR(Rn); - UML_MOV(block, R32(Rn), mem(&m_sh2_state->pr)); // mov Rn, pr - return true; - - case 0x2b: // RTE(); - generate_delay_slot(block, compiler, desc, 0xffffffff); - - UML_MOV(block, I0, R32(15)); // mov r0, R15 - UML_CALLH(block, *m_read32); // call read32 - UML_MOV(block, mem(&m_sh2_state->pc), I0); // mov pc, r0 - UML_ADD(block, R32(15), R32(15), 4); // add R15, R15, #4 - - UML_MOV(block, I0, R32(15)); // mov r0, R15 - UML_CALLH(block, *m_read32); // call read32 - UML_MOV(block, mem(&m_sh2_state->sr), I0); // mov sr, r0 - UML_ADD(block, R32(15), R32(15), 4); // add R15, R15, #4 - - compiler->checkints = true; - UML_MOV(block, mem(&m_sh2_state->ea), mem(&m_sh2_state->pc)); // mov ea, pc - generate_update_cycles(block, compiler, mem(&m_sh2_state->ea), true); // - UML_HASHJMP(block, 0, mem(&m_sh2_state->pc), *m_nocode); // and jump to the "resume PC" - - return true; - } - - return false; -} - -bool sh2_device::generate_group_2(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc) -{ - switch (opcode & 15) - { - case 0: // MOVBS(Rm, Rn); - UML_MOV(block, I0, R32(Rn)); // mov r0, Rn - UML_AND(block, I1, R32(Rm), 0xff); // and r1, Rm, 0xff - UML_CALLH(block, *m_write8); - - if (!in_delay_slot) - generate_update_cycles(block, compiler, desc->pc + 2, true); - return true; - - case 1: // MOVWS(Rm, Rn); - UML_MOV(block, I0, R32(Rn)); // mov r0, Rn - UML_AND(block, I1, R32(Rm), 0xffff); // and r1, Rm, 0xffff - UML_CALLH(block, *m_write16); - - if (!in_delay_slot) - generate_update_cycles(block, compiler, desc->pc + 2, true); - return true; - - case 2: // MOVLS(Rm, Rn); - UML_MOV(block, I0, R32(Rn)); // mov r0, Rn - UML_MOV(block, I1, R32(Rm)); // mov r1, Rm - UML_CALLH(block, *m_write32); - - if (!in_delay_slot) - generate_update_cycles(block, compiler, desc->pc + 2, true); - return true; - - case 3: - return false; - - case 4: // MOVBM(Rm, Rn); - UML_MOV(block, I1, R32(Rm)); // mov r1, Rm - UML_SUB(block, R32(Rn), R32(Rn), 1); // sub Rn, Rn, 1 - UML_MOV(block, I0, R32(Rn)); // mov r0, Rn - UML_CALLH(block, *m_write8); // call write8 - - if (!in_delay_slot) - generate_update_cycles(block, compiler, desc->pc + 2, true); - return true; - - case 5: // MOVWM(Rm, Rn); - UML_MOV(block, I1, R32(Rm)); // mov r1, Rm - UML_SUB(block, R32(Rn), R32(Rn), 2); // sub Rn, Rn, 2 - UML_MOV(block, I0, R32(Rn)); // mov r0, Rn - UML_CALLH(block, *m_write16); // call write16 - - if (!in_delay_slot) - generate_update_cycles(block, compiler, desc->pc + 2, true); - return true; - - case 6: // MOVLM(Rm, Rn); - UML_MOV(block, I1, R32(Rm)); // mov r1, Rm - UML_SUB(block, R32(Rn), R32(Rn), 4); // sub Rn, Rn, 4 - UML_MOV(block, I0, R32(Rn)); // mov r0, Rn - UML_CALLH(block, *m_write32); // call write32 - - if (!in_delay_slot) - generate_update_cycles(block, compiler, desc->pc + 2, true); - return true; - - case 13: // XTRCT(Rm, Rn); - UML_SHL(block, I0, R32(Rm), 16); // shl r0, Rm, #16 - UML_AND(block, I0, I0, 0xffff0000); // and r0, r0, #0xffff0000 - - UML_SHR(block, I1, R32(Rn), 16); // shr, r1, Rn, #16 - UML_AND(block, I1, I1, 0xffff); // and r1, r1, #0x0000ffff - - UML_OR(block, R32(Rn), I0, I1); // or Rn, r0, r1 - return true; - - case 7: // DIV0S(Rm, Rn); - UML_MOV(block, I0, mem(&m_sh2_state->sr)); // move r0, sr - UML_AND(block, I0, I0, ~(Q|M|T)); // and r0, r0, ~(Q|M|T) (clear the Q,M, and T bits) - - UML_TEST(block, R32(Rn), 0x80000000); // test Rn, #0x80000000 - UML_JMPc(block, COND_Z, compiler->labelnum); // jz labelnum - - UML_OR(block, I0, I0, Q); // or r0, r0, Q - UML_LABEL(block, compiler->labelnum++); // labelnum: - - UML_TEST(block, R32(Rm), 0x80000000); // test Rm, #0x80000000 - UML_JMPc(block, COND_Z, compiler->labelnum); // jz labelnum - - UML_OR(block, I0, I0, M); // or r0, r0, M - UML_LABEL(block, compiler->labelnum++); // labelnum: - - UML_XOR(block, I1, R32(Rn), R32(Rm)); // xor r1, Rn, Rm - UML_TEST(block, I1, 0x80000000); // test r1, #0x80000000 - UML_JMPc(block, COND_Z, compiler->labelnum); // jz labelnum - - UML_OR(block, I0, I0, T); // or r0, r0, T - UML_LABEL(block, compiler->labelnum++); // labelnum: - UML_MOV(block, mem(&m_sh2_state->sr), I0); // mov sr, r0 - return true; - - case 8: // TST(Rm, Rn); - UML_AND(block, I0, mem(&m_sh2_state->sr), ~T); // and r0, sr, ~T (clear the T bit) - UML_TEST(block, R32(Rm), R32(Rn)); // test Rm, Rn - UML_JMPc(block, COND_NZ, compiler->labelnum); // jnz compiler->labelnum - - UML_OR(block, I0, I0, T); // or r0, r0, T - UML_LABEL(block, compiler->labelnum++); // desc->pc: - - UML_MOV(block, mem(&m_sh2_state->sr), I0); // mov m_sh2_state->sr, r0 - return true; - - case 12: // CMPSTR(Rm, Rn); - UML_XOR(block, I0, R32(Rn), R32(Rm)); // xor r0, Rn, Rm (temp) - - UML_SHR(block, I1, I0, 24); // shr r1, r0, #24 (HH) - UML_AND(block, I1, I1, 0xff); // and r1, r1, #0xff - - UML_SHR(block, I2, I0, 16); // shr r2, r0, #16 (HL) - UML_AND(block, I2, I2, 0xff); // and r2, r2, #0xff - - UML_SHR(block, I3, I0, 8); // shr r3, r0, #8 (LH) - UML_AND(block, I3, I3, 0xff); // and r3, r3, #0xff - - UML_AND(block, I7, I0, 0xff); // and r7, r0, #0xff (LL) - - UML_AND(block, mem(&m_sh2_state->sr), mem(&m_sh2_state->sr), ~T); // and sr, sr, ~T (clear the T bit) - - UML_CMP(block, I1, 0); // cmp r1, #0 - UML_JMPc(block, COND_Z, compiler->labelnum); // jnz labelnum - UML_CMP(block, I2, 0); // cmp r2, #0 - UML_JMPc(block, COND_Z, compiler->labelnum); // jnz labelnum - UML_CMP(block, I3, 0); // cmp r3, #0 - UML_JMPc(block, COND_Z, compiler->labelnum); // jnz labelnum - UML_CMP(block, I7, 0); // cmp r7, #0 - UML_JMPc(block, COND_NZ, compiler->labelnum+1); // jnz labelnum - - UML_LABEL(block, compiler->labelnum++); // labelnum: - UML_OR(block, mem(&m_sh2_state->sr), mem(&m_sh2_state->sr), T); // or sr, sr, T - - UML_LABEL(block, compiler->labelnum++); // labelnum+1: - return true; - - case 9: // AND(Rm, Rn); - UML_AND(block, R32(Rn), R32(Rn), R32(Rm)); // and Rn, Rn, Rm - return true; - - case 10: // XOR(Rm, Rn); - UML_XOR(block, R32(Rn), R32(Rn), R32(Rm)); // xor Rn, Rn, Rm - return true; - - case 11: // OR(Rm, Rn); - UML_OR(block, R32(Rn), R32(Rn), R32(Rm)); // or Rn, Rn, Rm - return true; - - case 14: // MULU(Rm, Rn); - UML_AND(block, I0, R32(Rm), 0xffff); // and r0, Rm, 0xffff - UML_AND(block, I1, R32(Rn), 0xffff); // and r1, Rn, 0xffff - UML_MULU(block, mem(&m_sh2_state->macl), mem(&m_sh2_state->ea), I0, I1); // mulu macl, ea, r0, r1 - return true; - - case 15: // MULS(Rm, Rn); - UML_SEXT(block, I0, R32(Rm), SIZE_WORD); // sext r0, Rm - UML_SEXT(block, I1, R32(Rn), SIZE_WORD); // sext r1, Rn - UML_MULS(block, mem(&m_sh2_state->macl), mem(&m_sh2_state->ea), I0, I1); // muls macl, ea, r0, r1 - return true; - } - - return false; -} - -bool sh2_device::generate_group_3(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, uint32_t ovrpc) -{ - switch (opcode & 15) - { - case 0: // CMPEQ(Rm, Rn); (equality) - UML_CMP(block, R32(Rn), R32(Rm)); // cmp Rn, Rm - UML_SETc(block, COND_E, I0); // set E, r0 - UML_ROLINS(block, mem(&m_sh2_state->sr), I0, 0, 1); // rolins sr, r0, 0, 1 - return true; - - case 2: // CMPHS(Rm, Rn); (unsigned greater than or equal) - UML_CMP(block, R32(Rn), R32(Rm)); // cmp Rn, Rm - UML_SETc(block, COND_AE, I0); // set AE, r0 - UML_ROLINS(block, mem(&m_sh2_state->sr), I0, 0, 1); // rolins sr, r0, 0, 1 - return true; - - case 3: // CMPGE(Rm, Rn); (signed greater than or equal) - UML_CMP(block, R32(Rn), R32(Rm)); // cmp Rn, Rm - UML_SETc(block, COND_GE, I0); // set GE, r0 - UML_ROLINS(block, mem(&m_sh2_state->sr), I0, 0, 1); // rolins sr, r0, 0, 1 - return true; - - case 6: // CMPHI(Rm, Rn); (unsigned greater than) - UML_CMP(block, R32(Rn), R32(Rm)); // cmp Rn, Rm - UML_SETc(block, COND_A, I0); // set A, r0 - UML_ROLINS(block, mem(&m_sh2_state->sr), I0, 0, 1); // rolins sr, r0, 0, 1 - return true; - - case 7: // CMPGT(Rm, Rn); (signed greater than) - UML_CMP(block, R32(Rn), R32(Rm)); // cmp Rn, Rm - UML_SETc(block, COND_G, I0); // set G, r0 - UML_ROLINS(block, mem(&m_sh2_state->sr), I0, 0, 1); // rolins sr, r0, 0, 1 - return true; - - case 1: - case 9: - return false; - - case 4: // DIV1(Rm, Rn); - save_fast_iregs(block); - UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr.w[0]); - UML_CALLC(block, cfunc_DIV1, this); - load_fast_iregs(block); - return true; - - case 5: // DMULU(Rm, Rn); - if (m_cpu_type > CPU_TYPE_SH1) - { - UML_MULU(block, mem(&m_sh2_state->macl), mem(&m_sh2_state->mach), R32(Rn), R32(Rm)); - return true; - } - break; - - case 13: // DMULS(Rm, Rn); - if (m_cpu_type > CPU_TYPE_SH1) - { - UML_MULS(block, mem(&m_sh2_state->macl), mem(&m_sh2_state->mach), R32(Rn), R32(Rm)); - return true; - } - break; - - case 8: // SUB(Rm, Rn); - UML_SUB(block, R32(Rn), R32(Rn), R32(Rm)); // sub Rn, Rn, Rm - return true; - - case 12: // ADD(Rm, Rn); - UML_ADD(block, R32(Rn), R32(Rn), R32(Rm)); // add Rn, Rn, Rm - return true; - - case 10: // SUBC(Rm, Rn); - UML_CARRY(block, mem(&m_sh2_state->sr), 0); // carry = T (T is bit 0 of SR) - UML_SUBB(block, R32(Rn), R32(Rn), R32(Rm)); // addc Rn, Rn, Rm - UML_SETc(block, COND_C, I0); // setc i0, C - UML_ROLINS(block, mem(&m_sh2_state->sr), I0, 0, T); // rolins sr,i0,0,T - return true; - - case 11: // SUBV(Rm, Rn); -#if ADDSUBV_DIRECT - UML_SUB(block, R32(Rn), R32(Rn), R32(Rm)); // sub Rn, Rn, Rm - UML_SETc(block, COND_V, I0); // setc i0, V - UML_ROLINS(block, mem(&m_sh2_state->sr), I0, 0, T); // rolins [sr],i0,0,T -#else - save_fast_iregs(block); - UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr.w[0]); - UML_CALLC(block, cfunc_SUBV, this); - load_fast_iregs(block); -#endif - return true; - - case 14: // ADDC(Rm, Rn); - UML_CARRY(block, mem(&m_sh2_state->sr), 0); // carry = T (T is bit 0 of SR) - UML_ADDC(block, R32(Rn), R32(Rn), R32(Rm)); // addc Rn, Rn, Rm - UML_SETc(block, COND_C, I0); // setc i0, C - UML_ROLINS(block, mem(&m_sh2_state->sr), I0, 0, T); // rolins sr,i0,0,T - return true; - - case 15: // ADDV(Rm, Rn); -#if ADDSUBV_DIRECT - UML_ADD(block, R32(Rn), R32(Rn), R32(Rm)); // add Rn, Rn, Rm - UML_SETc(block, COND_V, I0); // setc i0, V - UML_ROLINS(block, mem(&m_sh2_state->sr), I0, 0, T); // rolins [sr],i0,0,T -#else - save_fast_iregs(block); - UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr.w[0]); - UML_CALLC(block, cfunc_ADDV, this); - load_fast_iregs(block); -#endif - return true; - } - return false; -} - -bool sh2_device::generate_group_4(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc) -{ - switch (opcode & 0x3F) - { - case 0x00: // SHLL(Rn); - UML_SHL(block, R32(Rn), R32(Rn), 1); // shl Rn, Rn, 1 - UML_SETc(block, COND_C, I0); // set i0,C - UML_ROLINS(block, mem(&m_sh2_state->sr), I0, 0, T); // rolins [sr],i0,0,T - return true; - - case 0x01: // SHLR(Rn); - UML_SHR(block, R32(Rn), R32(Rn), 1); // shr Rn, Rn, 1 - UML_SETc(block, COND_C, I0); // set i0,C - UML_ROLINS(block, mem(&m_sh2_state->sr), I0, 0, T); // rolins [sr],i0,0,T - return true; - - case 0x04: // ROTL(Rn); - UML_ROL(block, R32(Rn), R32(Rn), 1); // rol Rn, Rn, 1 - UML_SETc(block, COND_C, I0); // set i0,C - UML_ROLINS(block, mem(&m_sh2_state->sr), I0, 0, T); // rolins [sr],i0,0,T - return true; - - case 0x05: // ROTR(Rn); - UML_ROR(block, R32(Rn), R32(Rn), 1); // ror Rn, Rn, 1 - UML_SETc(block, COND_C, I0); // set i0,C - UML_ROLINS(block, mem(&m_sh2_state->sr), I0, 0, T); // rolins [sr],i0,0,T - return true; - - case 0x02: // STSMMACH(Rn); - UML_SUB(block, R32(Rn), R32(Rn), 4); // sub Rn, Rn, #4 - UML_MOV(block, I0, R32(Rn)); // mov r0, Rn - UML_MOV(block, I1, mem(&m_sh2_state->mach)); // mov r1, mach - SETEA(0); // set ea for debug - UML_CALLH(block, *m_write32); // call write32 - - if (!in_delay_slot) - generate_update_cycles(block, compiler, desc->pc + 2, true); - return true; - - case 0x03: // STCMSR(Rn); - UML_SUB(block, R32(Rn), R32(Rn), 4); // sub Rn, Rn, #4 - UML_MOV(block, I0, R32(Rn)); // mov r0, Rn - UML_MOV(block, I1, mem(&m_sh2_state->sr)); // mov r1, sr - SETEA(0); // set ea for debug - UML_CALLH(block, *m_write32); // call write32 - - if (!in_delay_slot) - generate_update_cycles(block, compiler, desc->pc + 2, true); - return true; - - case 0x06: // LDSMMACH(Rn); - UML_MOV(block, I0, R32(Rn)); // mov r0, Rn - SETEA(0); - UML_CALLH(block, *m_read32); // call read32 - UML_ADD(block, R32(Rn), R32(Rn), 4); // add Rn, #4 - UML_MOV(block, mem(&m_sh2_state->mach), I0); // mov mach, r0 - - if (!in_delay_slot) - generate_update_cycles(block, compiler, desc->pc + 2, true); - return true; - - case 0x07: // LDCMSR(Rn); - UML_MOV(block, I0, R32(Rn)); // mov r0, Rn - SETEA(0); - UML_CALLH(block, *m_read32); // call read32 - UML_ADD(block, R32(Rn), R32(Rn), 4); // add Rn, #4 - UML_MOV(block, mem(&m_sh2_state->sr), I0); // mov sr, r0 - - compiler->checkints = true; - if (!in_delay_slot) - generate_update_cycles(block, compiler, desc->pc + 2, true); - return true; - - - case 0x08: // SHLL2(Rn); - UML_SHL(block, R32(Rn), R32(Rn), 2); - return true; - - case 0x09: // SHLR2(Rn); - UML_SHR(block, R32(Rn), R32(Rn), 2); - return true; - - case 0x18: // SHLL8(Rn); - UML_SHL(block, R32(Rn), R32(Rn), 8); - return true; - - case 0x19: // SHLR8(Rn); - UML_SHR(block, R32(Rn), R32(Rn), 8); - return true; - - case 0x28: // SHLL16(Rn); - UML_SHL(block, R32(Rn), R32(Rn), 16); - return true; - - case 0x29: // SHLR16(Rn); - UML_SHR(block, R32(Rn), R32(Rn), 16); - return true; - - case 0x0a: // LDSMACH(Rn); - UML_MOV(block, mem(&m_sh2_state->mach), R32(Rn)); // mov mach, Rn - return true; - - case 0x0b: // JSR(Rn); - UML_MOV(block, mem(&m_sh2_state->target), R32(Rn)); // mov target, Rn - - UML_ADD(block, mem(&m_sh2_state->pr), desc->pc, 4); // add m_pr, desc->pc, #4 (skip the current insn & delay slot) - - generate_delay_slot(block, compiler, desc, m_sh2_state->target-4); - - generate_update_cycles(block, compiler, mem(&m_sh2_state->target), true); // - UML_HASHJMP(block, 0, mem(&m_sh2_state->target), *m_nocode); // and do the jump - return true; - - case 0x0e: // LDCSR(Rn); - UML_MOV(block, I0, R32(Rn)); // mov r0, Rn - UML_AND(block, I0, I0, FLAGS); // and r0, r0, FLAGS - UML_MOV(block, mem(&m_sh2_state->sr), I0); - - compiler->checkints = true; - return true; - - case 0x0f: // MAC_W(Rm, Rn); - case 0x1f: // MAC_W(Rm, Rn); - case 0x2f: // MAC_W(Rm, Rn); - case 0x3f: // MAC_W(Rm, Rn); - save_fast_iregs(block); - UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr.w[0]); - UML_CALLC(block, cfunc_MAC_W, this); - load_fast_iregs(block); - return true; - - case 0x10: // DT(Rn); - if (m_cpu_type > CPU_TYPE_SH1) - { - UML_AND(block, I0, mem(&m_sh2_state->sr), ~T); // and r0, sr, ~T (clear the T bit) - UML_SUB(block, R32(Rn), R32(Rn), 1); // sub Rn, Rn, 1 - UML_JMPc(block, COND_NZ, compiler->labelnum); // jz compiler->labelnum - - UML_OR(block, I0, I0, T); // or r0, r0, T - UML_LABEL(block, compiler->labelnum++); // desc->pc: - - UML_MOV(block, mem(&m_sh2_state->sr), I0); // mov m_sh2_state->sr, r0 - return true; - } - break; - - case 0x11: // CMPPZ(Rn); - UML_AND(block, I0, mem(&m_sh2_state->sr), ~T); // and r0, sr, ~T (clear the T bit) - - UML_CMP(block, R32(Rn), 0); // cmp Rn, 0 - UML_JMPc(block, COND_S, compiler->labelnum); // js compiler->labelnum (if negative) - - UML_OR(block, I0, I0, T); // or r0, r0, T - UML_LABEL(block, compiler->labelnum++); // desc->pc: - - UML_MOV(block, mem(&m_sh2_state->sr), I0); // mov m_sh2_state->sr, r0 - return true; - - case 0x15: // CMPPL(Rn); - UML_AND(block, I0, mem(&m_sh2_state->sr), ~T); // and r0, sr, ~T (clear the T bit) - - UML_CMP(block, R32(Rn), 0); // cmp Rn, 0 - - UML_JMPc(block, COND_S, compiler->labelnum); // js compiler->labelnum (if negative) - UML_JMPc(block, COND_Z, compiler->labelnum); // jz compiler->labelnum (if zero) - - UML_OR(block, I0, I0, T); // or r0, r0, T - - UML_LABEL(block, compiler->labelnum++); // desc->pc: - UML_MOV(block, mem(&m_sh2_state->sr), I0); // mov m_sh2_state->sr, r0 - return true; - - case 0x12: // STSMMACL(Rn); - UML_SUB(block, R32(Rn), R32(Rn), 4); // sub Rn, Rn, #4 - UML_MOV(block, I0, R32(Rn)); // mov r0, Rn - UML_MOV(block, I1, mem(&m_sh2_state->macl)); // mov r1, macl - SETEA(0); // set ea for debug - UML_CALLH(block, *m_write32); // call write32 - - if (!in_delay_slot) - generate_update_cycles(block, compiler, desc->pc + 2, true); - return true; - - case 0x13: // STCMGBR(Rn); - UML_SUB(block, R32(Rn), R32(Rn), 4); // sub Rn, Rn, #4 - UML_MOV(block, I0, R32(Rn)); // mov r0, Rn - UML_MOV(block, I1, mem(&m_sh2_state->gbr)); // mov r1, gbr - SETEA(0); // set ea for debug - UML_CALLH(block, *m_write32); // call write32 - - if (!in_delay_slot) - generate_update_cycles(block, compiler, desc->pc + 2, true); - return true; - - case 0x16: // LDSMMACL(Rn); - UML_MOV(block, I0, R32(Rn)); // mov r0, Rn - SETEA(0); - UML_CALLH(block, *m_read32); // call read32 - UML_ADD(block, R32(Rn), R32(Rn), 4); // add Rn, #4 - UML_MOV(block, mem(&m_sh2_state->macl), I0); // mov macl, r0 - - if (!in_delay_slot) - generate_update_cycles(block, compiler, desc->pc + 2, true); - return true; - - case 0x17: // LDCMGBR(Rn); - UML_MOV(block, I0, R32(Rn)); // mov r0, Rn - SETEA(0); - UML_CALLH(block, *m_read32); // call read32 - UML_ADD(block, R32(Rn), R32(Rn), 4); // add Rn, #4 - UML_MOV(block, mem(&m_sh2_state->gbr), I0); // mov gbr, r0 - - if (!in_delay_slot) - generate_update_cycles(block, compiler, desc->pc + 2, true); - return true; - - case 0x1a: // LDSMACL(Rn); - UML_MOV(block, mem(&m_sh2_state->macl), R32(Rn)); // mov macl, Rn - return true; - - case 0x1b: // TAS(Rn); - UML_MOV(block, I0, R32(Rn)); // mov r0, Rn - SETEA(0); - UML_CALLH(block, *m_read8); // call read8 - - UML_AND(block, mem(&m_sh2_state->sr), mem(&m_sh2_state->sr), ~T); // and sr, sr, ~T - - UML_CMP(block, I0, 0); // cmp r0, #0 - UML_JMPc(block, COND_NZ, compiler->labelnum); // jnz labelnum - - UML_OR(block, mem(&m_sh2_state->sr), mem(&m_sh2_state->sr), T); // or sr, sr, T - - UML_LABEL(block, compiler->labelnum++); // labelnum: - - UML_OR(block, I1, I0, 0x80); // or r1, r0, #0x80 - - UML_MOV(block, I0, R32(Rn)); // mov r0, Rn - UML_CALLH(block, *m_write8); // write the value back - - if (!in_delay_slot) - generate_update_cycles(block, compiler, desc->pc + 2, true); - return true; - - case 0x1e: // LDCGBR(Rn); - UML_MOV(block, mem(&m_sh2_state->gbr), R32(Rn)); // mov gbr, Rn - return true; - - case 0x20: // SHAL(Rn); - UML_AND(block, mem(&m_sh2_state->sr), mem(&m_sh2_state->sr), ~T); // and sr, sr, ~T - UML_SHR(block, I0, R32(Rn), 31); // shr r0, Rn, 31 - UML_AND(block, I0, I0, T); // and r0, r0, T - UML_OR(block, mem(&m_sh2_state->sr), mem(&m_sh2_state->sr), I0); // or sr, sr, r0 - UML_SHL(block, R32(Rn), R32(Rn), 1); // shl Rn, Rn, 1 - return true; - - case 0x21: // SHAR(Rn); - UML_AND(block, mem(&m_sh2_state->sr), mem(&m_sh2_state->sr), ~T); // and sr, sr, ~T - UML_AND(block, I0, R32(Rn), T); // and r0, Rn, T - UML_OR(block, mem(&m_sh2_state->sr), mem(&m_sh2_state->sr), I0); // or sr, sr, r0 - UML_SAR(block, R32(Rn), R32(Rn), 1); // sar Rn, Rn, 1 - return true; - - case 0x22: // STSMPR(Rn); - UML_SUB(block, R32(Rn), R32(Rn), 4); // sub Rn, Rn, 4 - UML_MOV(block, I0, R32(Rn)); // mov r0, Rn - SETEA(0); - UML_MOV(block, I1, mem(&m_sh2_state->pr)); // mov r1, pr - UML_CALLH(block, *m_write32); // call write32 - - if (!in_delay_slot) - generate_update_cycles(block, compiler, desc->pc + 2, true); - return true; - - case 0x23: // STCMVBR(Rn); - UML_SUB(block, R32(Rn), R32(Rn), 4); // sub Rn, Rn, 4 - UML_MOV(block, I0, R32(Rn)); // mov r0, Rn - SETEA(0); - UML_MOV(block, I1, mem(&m_sh2_state->vbr)); // mov r1, vbr - UML_CALLH(block, *m_write32); // call write32 - - if (!in_delay_slot) - generate_update_cycles(block, compiler, desc->pc + 2, true); - return true; - - case 0x24: // ROTCL(Rn); - UML_CARRY(block, mem(&m_sh2_state->sr), 0); // carry sr,0 - UML_ROLC(block, R32(Rn), R32(Rn), 1); // rolc Rn,Rn,1 - UML_SETc(block, COND_C, I0); // set i0,C - UML_ROLINS(block, mem(&m_sh2_state->sr), I0, 0, T); // rolins sr,i0,0,T - return true; - - case 0x25: // ROTCR(Rn); - UML_CARRY(block, mem(&m_sh2_state->sr), 0); // carry sr,0 - UML_RORC(block, R32(Rn), R32(Rn), 1); // rorc Rn,Rn,1 - UML_SETc(block, COND_C, I0); // set i0,C - UML_ROLINS(block, mem(&m_sh2_state->sr), I0, 0, T); // rolins sr,i0,0,T - return true; - - case 0x26: // LDSMPR(Rn); - UML_MOV(block, I0, R32(Rn)); // mov r0, Rn - SETEA(0); - UML_CALLH(block, *m_read32); // call read32 - UML_MOV(block, mem(&m_sh2_state->pr), I0); // mov m_pr, r0 - UML_ADD(block, R32(Rn), R32(Rn), 4); // add Rn, Rn, #4 - - if (!in_delay_slot) - generate_update_cycles(block, compiler, desc->pc + 2, true); - return true; - - case 0x27: // LDCMVBR(Rn); - UML_MOV(block, I0, R32(Rn)); // mov r0, Rn - SETEA(0); - UML_CALLH(block, *m_read32); // call read32 - UML_MOV(block, mem(&m_sh2_state->vbr), I0); // mov m_sh2_state->vbr, r0 - UML_ADD(block, R32(Rn), R32(Rn), 4); // add Rn, Rn, #4 - - if (!in_delay_slot) - generate_update_cycles(block, compiler, desc->pc + 2, true); - return true; - - case 0x2a: // LDSPR(Rn); - UML_MOV(block, mem(&m_sh2_state->pr), R32(Rn)); // mov m_pr, Rn - return true; - - case 0x2b: // JMP(Rn); - UML_MOV(block, mem(&m_sh2_state->target), R32(Rn)); // mov target, Rn - - generate_delay_slot(block, compiler, desc, m_sh2_state->target); - - generate_update_cycles(block, compiler, mem(&m_sh2_state->target), true); // - UML_HASHJMP(block, 0, mem(&m_sh2_state->target), *m_nocode); // jmp (target) - return true; - - case 0x2e: // LDCVBR(Rn); - UML_MOV(block, mem(&m_sh2_state->vbr), R32(Rn)); // mov vbr, Rn - return true; - - case 0x0c: - case 0x0d: - case 0x14: - case 0x1c: - case 0x1d: - case 0x2c: - case 0x2d: - case 0x30: - case 0x31: - case 0x32: - case 0x33: - case 0x34: - case 0x35: - case 0x36: - case 0x37: - case 0x38: - case 0x39: - case 0x3a: - case 0x3b: - case 0x3c: - case 0x3d: - case 0x3e: - return false; - } - - return false; -} - -bool sh2_device::generate_group_6(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc) -{ - switch (opcode & 15) - { - case 0: // MOVBL(Rm, Rn); - UML_MOV(block, I0, R32(Rm)); // mov r0, Rm - SETEA(0); // debug: ea = r0 - UML_CALLH(block, *m_read8); // call read8 - UML_SEXT(block, R32(Rn), I0, SIZE_BYTE); // sext Rn, r0, BYTE - - if (!in_delay_slot) - generate_update_cycles(block, compiler, desc->pc + 2, true); - return true; - - case 1: // MOVWL(Rm, Rn); - UML_MOV(block, I0, R32(Rm)); // mov r0, Rm - SETEA(0); // debug: ea = r0 - UML_CALLH(block, *m_read16); // call read16 - UML_SEXT(block, R32(Rn), I0, SIZE_WORD); // sext Rn, r0, WORD - - if (!in_delay_slot) - generate_update_cycles(block, compiler, desc->pc + 2, true); - return true; - - case 2: // MOVLL(Rm, Rn); - UML_MOV(block, I0, R32(Rm)); // mov r0, Rm - SETEA(0); // debug: ea = r0 - UML_CALLH(block, *m_read32); // call read32 - UML_MOV(block, R32(Rn), I0); // mov Rn, r0 - - if (!in_delay_slot) - generate_update_cycles(block, compiler, desc->pc + 2, true); - return true; - - case 3: // MOV(Rm, Rn); - UML_MOV(block, R32(Rn), R32(Rm)); // mov Rn, Rm - return true; - - case 7: // NOT(Rm, Rn); - UML_XOR(block, R32(Rn), R32(Rm), 0xffffffff); // xor Rn, Rm, 0xffffffff - return true; - - case 9: // SWAPW(Rm, Rn); - UML_ROL(block, R32(Rn), R32(Rm), 16); // rol Rn, Rm, 16 - return true; - - case 11: // NEG(Rm, Rn); - UML_SUB(block, R32(Rn), 0, R32(Rm)); // sub Rn, 0, Rm - return true; - - case 12: // EXTUB(Rm, Rn); - UML_AND(block, R32(Rn), R32(Rm), 0x000000ff); // and Rn, Rm, 0xff - return true; - - case 13: // EXTUW(Rm, Rn); - UML_AND(block, R32(Rn), R32(Rm), 0x0000ffff); // and Rn, Rm, 0xffff - return true; - - case 14: // EXTSB(Rm, Rn); - UML_SEXT(block, R32(Rn), R32(Rm), SIZE_BYTE); // sext Rn, Rm, BYTE - return true; - - case 15: // EXTSW(Rm, Rn); - UML_SEXT(block, R32(Rn), R32(Rm), SIZE_WORD); // sext Rn, Rm, WORD - return true; - - case 4: // MOVBP(Rm, Rn); - UML_MOV(block, I0, R32(Rm)); // mov r0, Rm - UML_CALLH(block, *m_read8); // call read8 - UML_SEXT(block, R32(Rn), I0, SIZE_BYTE); // sext Rn, r0, BYTE - - if (Rm != Rn) - UML_ADD(block, R32(Rm), R32(Rm), 1); // add Rm, Rm, #1 - - if (!in_delay_slot) - generate_update_cycles(block, compiler, desc->pc + 2, true); - return true; - - case 5: // MOVWP(Rm, Rn); - UML_MOV(block, I0, R32(Rm)); // mov r0, Rm - UML_CALLH(block, *m_read16); // call read16 - UML_SEXT(block, R32(Rn), I0, SIZE_WORD); // sext Rn, r0, WORD - - if (Rm != Rn) - UML_ADD(block, R32(Rm), R32(Rm), 2); // add Rm, Rm, #2 - - if (!in_delay_slot) - generate_update_cycles(block, compiler, desc->pc + 2, true); - return true; - - case 6: // MOVLP(Rm, Rn); - UML_MOV(block, I0, R32(Rm)); // mov r0, Rm - UML_CALLH(block, *m_read32); // call read32 - UML_MOV(block, R32(Rn), I0); // mov Rn, r0 - - if (Rm != Rn) - UML_ADD(block, R32(Rm), R32(Rm), 4); // add Rm, Rm, #4 - - if (!in_delay_slot) - generate_update_cycles(block, compiler, desc->pc + 2, true); - return true; - - case 8: // SWAPB(Rm, Rn); - UML_AND(block, I0, R32(Rm), 0xffff0000); // and r0, Rm, #0xffff0000 - UML_AND(block, I1, R32(Rm), 0x000000ff); // and r0, Rm, #0x000000ff - UML_AND(block, I2, R32(Rm), 0x0000ff00); // and r0, Rm, #0x0000ff00 - UML_SHL(block, I1, I1, 8); // shl r1, r1, #8 - UML_SHR(block, I2, I2, 8); // shr r2, r2, #8 - UML_OR(block, I0, I0, I1); // or r0, r0, r1 - UML_OR(block, R32(Rn), I0, I2); // or Rn, r0, r2 - return true; - - case 10: // NEGC(Rm, Rn); - UML_MOV(block, I0, mem(&m_sh2_state->sr)); // mov r0, sr (save SR) - UML_AND(block, mem(&m_sh2_state->sr), mem(&m_sh2_state->sr), ~T); // and sr, sr, ~T (clear the T bit) - UML_CARRY(block, I0, 0); // carry = T (T is bit 0 of SR) - UML_SUBB(block, R32(Rn), 0, R32(Rm)); // subb Rn, #0, Rm - - UML_JMPc(block, COND_NC, compiler->labelnum); // jnc labelnum - - UML_OR(block, mem(&m_sh2_state->sr), mem(&m_sh2_state->sr), T); // or sr, sr, T - - UML_LABEL(block, compiler->labelnum++); // labelnum: - - return true; - } - - return false; -} - -bool sh2_device::generate_group_8(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc) -{ - int32_t disp; - uint32_t udisp; - code_label templabel; - - switch ( opcode & (15<<8) ) - { - case 0 << 8: // MOVBS4(opcode & 0x0f, Rm); - udisp = (opcode & 0x0f); - UML_ADD(block, I0, R32(Rm), udisp); // add r0, Rm, udisp - UML_MOV(block, I1, R32(0)); // mov r1, R0 - UML_CALLH(block, *m_write8); // call write8 - - if (!in_delay_slot) - generate_update_cycles(block, compiler, desc->pc + 2, true); - return true; - - case 1 << 8: // MOVWS4(opcode & 0x0f, Rm); - udisp = (opcode & 0x0f) * 2; - UML_ADD(block, I0, R32(Rm), udisp); // add r0, Rm, udisp - UML_MOV(block, I1, R32(0)); // mov r1, R0 - UML_CALLH(block, *m_write16); // call write16 - - if (!in_delay_slot) - generate_update_cycles(block, compiler, desc->pc + 2, true); - return true; - - case 2<< 8: - case 3<< 8: - case 6<< 8: - case 7<< 8: - case 10<< 8: - case 12<< 8: - case 14<< 8: - return false; - - case 4<< 8: // MOVBL4(Rm, opcode & 0x0f); - udisp = opcode & 0x0f; - UML_ADD(block, I0, R32(Rm), udisp); // add r0, Rm, udisp - SETEA(0); - UML_CALLH(block, *m_read8); // call read8 - UML_SEXT(block, R32(0), I0, SIZE_BYTE); // sext R0, r0, BYTE - - if (!in_delay_slot) - generate_update_cycles(block, compiler, desc->pc + 2, true); - return true; - - case 5<< 8: // MOVWL4(Rm, opcode & 0x0f); - udisp = (opcode & 0x0f)*2; - UML_ADD(block, I0, R32(Rm), udisp); // add r0, Rm, udisp - SETEA(0); - UML_CALLH(block, *m_read16); // call read16 - UML_SEXT(block, R32(0), I0, SIZE_WORD); // sext R0, r0, WORD - - if (!in_delay_slot) - generate_update_cycles(block, compiler, desc->pc + 2, true); - return true; - - case 8<< 8: // CMPIM(opcode & 0xff); - UML_AND(block, I0, mem(&m_sh2_state->sr), ~T); // and r0, sr, ~T (clear the T bit) - - UML_SEXT(block, I1, opcode&0xff, SIZE_BYTE); // sext r1, opcode&0xff, BYTE - UML_CMP(block, I1, R32(0)); // cmp r1, R0 - UML_JMPc(block, COND_NZ, compiler->labelnum); // jnz compiler->labelnum (if negative) - - UML_OR(block, I0, I0, T); // or r0, r0, T - - UML_LABEL(block, compiler->labelnum++); // labelnum: - UML_MOV(block, mem(&m_sh2_state->sr), I0); // mov m_sh2_state->sr, r0 - return true; - - case 9<< 8: // BT(opcode & 0xff); - UML_TEST(block, mem(&m_sh2_state->sr), T); // test m_sh2_state->sr, T - UML_JMPc(block, COND_Z, compiler->labelnum); // jz compiler->labelnum - - disp = ((int32_t)opcode << 24) >> 24; - m_sh2_state->ea = (desc->pc + 2) + disp * 2 + 2; // m_sh2_state->ea = destination - - generate_update_cycles(block, compiler, m_sh2_state->ea, true); // - UML_HASHJMP(block, 0, m_sh2_state->ea, *m_nocode); // jmp m_sh2_state->ea - - UML_LABEL(block, compiler->labelnum++); // labelnum: - return true; - - case 11<< 8: // BF(opcode & 0xff); - UML_TEST(block, mem(&m_sh2_state->sr), T); // test m_sh2_state->sr, T - UML_JMPc(block, COND_NZ, compiler->labelnum); // jnz compiler->labelnum - - disp = ((int32_t)opcode << 24) >> 24; - m_sh2_state->ea = (desc->pc + 2) + disp * 2 + 2; // m_sh2_state->ea = destination - - generate_update_cycles(block, compiler, m_sh2_state->ea, true); // - UML_HASHJMP(block, 0, m_sh2_state->ea, *m_nocode); // jmp m_sh2_state->ea - - UML_LABEL(block, compiler->labelnum++); // labelnum: - return true; - - case 13<< 8: // BTS(opcode & 0xff); - if (m_cpu_type > CPU_TYPE_SH1) - { - UML_TEST(block, mem(&m_sh2_state->sr), T); // test m_sh2_state->sr, T - UML_JMPc(block, COND_Z, compiler->labelnum); // jz compiler->labelnum - - disp = ((int32_t)opcode << 24) >> 24; - m_sh2_state->ea = (desc->pc + 2) + disp * 2 + 2; // m_sh2_state->ea = destination - - templabel = compiler->labelnum; // save our label - compiler->labelnum++; // make sure the delay slot doesn't use it - generate_delay_slot(block, compiler, desc, m_sh2_state->ea-2); - - generate_update_cycles(block, compiler, m_sh2_state->ea, true); // - UML_HASHJMP(block, 0, m_sh2_state->ea, *m_nocode); // jmp m_sh2_state->ea - - UML_LABEL(block, templabel); // labelnum: - return true; - } - break; - - case 15<< 8: // BFS(opcode & 0xff); - if (m_cpu_type > CPU_TYPE_SH1) - { - UML_TEST(block, mem(&m_sh2_state->sr), T); // test m_sh2_state->sr, T - UML_JMPc(block, COND_NZ, compiler->labelnum); // jnz compiler->labelnum - - disp = ((int32_t)opcode << 24) >> 24; - m_sh2_state->ea = (desc->pc + 2) + disp * 2 + 2; // m_sh2_state->ea = destination - - templabel = compiler->labelnum; // save our label - compiler->labelnum++; // make sure the delay slot doesn't use it - generate_delay_slot(block, compiler, desc, m_sh2_state->ea-2); // delay slot only if the branch is taken - - generate_update_cycles(block, compiler, m_sh2_state->ea, true); // - UML_HASHJMP(block, 0, m_sh2_state->ea, *m_nocode); // jmp m_sh2_state->ea - - UML_LABEL(block, templabel); // labelnum: - return true; - } - break; - } - - return false; -} - -bool sh2_device::generate_group_12(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc) -{ - uint32_t scratch; - - switch (opcode & (15<<8)) - { - case 0<<8: // MOVBSG(opcode & 0xff); - scratch = (opcode & 0xff); - UML_ADD(block, I0, mem(&m_sh2_state->gbr), scratch); // add r0, gbr, scratch - UML_AND(block, I1, R32(0), 0xff); // and r1, R0, 0xff - UML_CALLH(block, *m_write8); // call write8 - - if (!in_delay_slot) - generate_update_cycles(block, compiler, desc->pc + 2, true); - return true; - - case 1<<8: // MOVWSG(opcode & 0xff); - scratch = (opcode & 0xff) * 2; - UML_ADD(block, I0, mem(&m_sh2_state->gbr), scratch); // add r0, gbr, scratch - UML_AND(block, I1, R32(0), 0xffff); // and r1, R0, 0xffff - UML_CALLH(block, *m_write16); // call write16 - - if (!in_delay_slot) - generate_update_cycles(block, compiler, desc->pc + 2, true); - return true; - - case 2<<8: // MOVLSG(opcode & 0xff); - scratch = (opcode & 0xff) * 4; - UML_ADD(block, I0, mem(&m_sh2_state->gbr), scratch); // add r0, gbr, scratch - UML_MOV(block, I1, R32(0)); // mov r1, R0 - UML_CALLH(block, *m_write32); // call write32 - - if (!in_delay_slot) - generate_update_cycles(block, compiler, desc->pc + 2, true); - return true; - - case 3<<8: // TRAPA(opcode & 0xff); - scratch = (opcode & 0xff) * 4; - UML_ADD(block, mem(&m_sh2_state->ea), mem(&m_sh2_state->vbr), scratch); // add ea, vbr, scratch - - UML_SUB(block, R32(15), R32(15), 4); // sub R15, R15, #4 - UML_MOV(block, I0, R32(15)); // mov r0, R15 - UML_MOV(block, I1, mem(&m_sh2_state->sr)); // mov r1, sr - UML_CALLH(block, *m_write32); // write32 - - UML_SUB(block, R32(15), R32(15), 4); // sub R15, R15, #4 - UML_MOV(block, I0, R32(15)); // mov r0, R15 - UML_MOV(block, I1, desc->pc+2); // mov r1, pc+2 - UML_CALLH(block, *m_write32); // write32 - - UML_MOV(block, I0, mem(&m_sh2_state->ea)); // mov r0, ea - UML_CALLH(block, *m_read32); // read32 - UML_HASHJMP(block, 0, I0, *m_nocode); // jmp (r0) - - return true; - - case 4<<8: // MOVBLG(opcode & 0xff); - scratch = (opcode & 0xff); - UML_ADD(block, I0, mem(&m_sh2_state->gbr), scratch); // add r0, gbr, scratch - UML_CALLH(block, *m_read8); // call read16 - UML_SEXT(block, R32(0), I0, SIZE_BYTE); // sext R0, r0, BYTE - - if (!in_delay_slot) - generate_update_cycles(block, compiler, desc->pc + 2, true); - return true; - - case 5<<8: // MOVWLG(opcode & 0xff); - scratch = (opcode & 0xff) * 2; - UML_ADD(block, I0, mem(&m_sh2_state->gbr), scratch); // add r0, gbr, scratch - UML_CALLH(block, *m_read16); // call read16 - UML_SEXT(block, R32(0), I0, SIZE_WORD); // sext R0, r0, WORD - - if (!in_delay_slot) - generate_update_cycles(block, compiler, desc->pc + 2, true); - return true; - - case 6<<8: // MOVLLG(opcode & 0xff); - scratch = (opcode & 0xff) * 4; - UML_ADD(block, I0, mem(&m_sh2_state->gbr), scratch); // add r0, gbr, scratch - UML_CALLH(block, *m_read32); // call read32 - UML_MOV(block, R32(0), I0); // mov R0, r0 - - if (!in_delay_slot) - generate_update_cycles(block, compiler, desc->pc + 2, true); - return true; - - case 7<<8: // MOVA(opcode & 0xff); - scratch = (opcode & 0xff) * 4; - scratch += ((desc->pc + 4) & ~3); - - UML_MOV(block, R32(0), scratch); // mov R0, scratch - return true; - - case 8<<8: // TSTI(opcode & 0xff); - scratch = opcode & 0xff; - - UML_AND(block, mem(&m_sh2_state->sr), mem(&m_sh2_state->sr), ~T); // and sr, sr, ~T (clear the T bit) - UML_AND(block, I0, R32(0), scratch); // and r0, R0, scratch - UML_CMP(block, I0, 0); // cmp r0, #0 - UML_JMPc(block, COND_NZ, compiler->labelnum); // jnz labelnum - - UML_OR(block, mem(&m_sh2_state->sr), mem(&m_sh2_state->sr), T); // or sr, sr, T - - UML_LABEL(block, compiler->labelnum++); // labelnum: - return true; - - case 9<<8: // ANDI(opcode & 0xff); - UML_AND(block, R32(0), R32(0), opcode & 0xff); // and r0, r0, opcode & 0xff - return true; - - case 10<<8: // XORI(opcode & 0xff); - UML_XOR(block, R32(0), R32(0), opcode & 0xff); // xor r0, r0, opcode & 0xff - return true; - - case 11<<8: // ORI(opcode & 0xff); - UML_OR(block, R32(0), R32(0), opcode & 0xff); // or r0, r0, opcode & 0xff - return true; - - case 12<<8: // TSTM(opcode & 0xff); - UML_AND(block, mem(&m_sh2_state->sr), mem(&m_sh2_state->sr), ~T); // and sr, sr, ~T (clear the T bit) - UML_ADD(block, I0, R32(0), mem(&m_sh2_state->gbr)); // add r0, R0, gbr - UML_CALLH(block, *m_read8); // read8 - - UML_AND(block, I0, I0, opcode & 0xff); - UML_CMP(block, I0, 0); // cmp r0, #0 - UML_JMPc(block, COND_NZ, compiler->labelnum); // jnz labelnum - - UML_OR(block, mem(&m_sh2_state->sr), mem(&m_sh2_state->sr), T); // or sr, sr, T - - UML_LABEL(block, compiler->labelnum++); // labelnum: - return true; - - case 13<<8: // ANDM(opcode & 0xff); - UML_ADD(block, I0, R32(0), mem(&m_sh2_state->gbr)); // add r0, R0, gbr - UML_CALLH(block, *m_read8); // read8 - - UML_AND(block, I1, I0, opcode&0xff); // and r1, r0, #opcode&0xff - UML_ADD(block, I0, R32(0), mem(&m_sh2_state->gbr)); // add r0, R0, gbr - SETEA(0); - UML_CALLH(block, *m_write8); // write8 - return true; - - case 14<<8: // XORM(opcode & 0xff); - UML_ADD(block, I0, R32(0), mem(&m_sh2_state->gbr)); // add r0, R0, gbr - UML_CALLH(block, *m_read8); // read8 - - UML_XOR(block, I1, I0, opcode&0xff); // xor r1, r0, #opcode&0xff - UML_ADD(block, I0, R32(0), mem(&m_sh2_state->gbr)); // add r0, R0, gbr - SETEA(0); - UML_CALLH(block, *m_write8); // write8 - return true; - - case 15<<8: // ORM(opcode & 0xff); - UML_ADD(block, I0, R32(0), mem(&m_sh2_state->gbr)); // add r0, R0, gbr - UML_CALLH(block, *m_read8); // read8 - - UML_OR(block, I1, I0, opcode&0xff); // or r1, r0, #opcode&0xff - UML_ADD(block, I0, R32(0), mem(&m_sh2_state->gbr)); // add r0, R0, gbr - SETEA(0); - UML_CALLH(block, *m_write8); // write8 - return true; - } - - return false; -} - -/*************************************************************************** - CORE CALLBACKS -***************************************************************************/ - -/*------------------------------------------------- - sh2drc_set_options - configure DRC options --------------------------------------------------*/ - -void sh2_device::sh2drc_set_options(uint32_t options) -{ - if (!allow_drc()) return; - m_drcoptions = options; -} - - -/*------------------------------------------------- - sh2drc_add_pcflush - add a new address where - the PC must be flushed for speedups to work --------------------------------------------------*/ - -void sh2_device::sh2drc_add_pcflush(offs_t address) -{ - if (!allow_drc()) return; - - if (m_pcfsel < ARRAY_LENGTH(m_pcflushes)) - m_pcflushes[m_pcfsel++] = address; -} - - -/*------------------------------------------------- - sh2drc_add_fastram - add a new fastram - region --------------------------------------------------*/ - -void sh2_device::sh2drc_add_fastram(offs_t start, offs_t end, uint8_t readonly, void *base) -{ - if (m_fastram_select < ARRAY_LENGTH(m_fastram)) - { - m_fastram[m_fastram_select].start = start; - m_fastram[m_fastram_select].end = end; - m_fastram[m_fastram_select].readonly = readonly; - m_fastram[m_fastram_select].base = base; - m_fastram_select++; - } -} diff --git a/src/devices/cpu/superh/sh2fe.cpp b/src/devices/cpu/superh/sh2fe.cpp deleted file mode 100644 index f6b409a0cd5..00000000000 --- a/src/devices/cpu/superh/sh2fe.cpp +++ /dev/null @@ -1,762 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:R. Belmont -/*************************************************************************** - - sh2fe.c - - Front end for SH-2 recompiler - -***************************************************************************/ - -#include "emu.h" -#include "sh2.h" -#include "sh2comn.h" -#include "cpu/drcfe.h" - - -/*************************************************************************** - INSTRUCTION PARSERS -***************************************************************************/ - -sh2_frontend::sh2_frontend(sh2_device *device, uint32_t window_start, uint32_t window_end, uint32_t max_sequence) - : drc_frontend(*device, window_start, window_end, max_sequence) - , m_sh2(device) -{ -} - -/*------------------------------------------------- - describe_instruction - build a description - of a single instruction --------------------------------------------------*/ - -bool sh2_frontend::describe(opcode_desc &desc, const opcode_desc *prev) -{ - uint16_t opcode; - - /* fetch the opcode */ - opcode = desc.opptr.w[0] = m_sh2->m_direct->read_word(desc.physpc, SH2_CODE_XOR(0)); - - /* all instructions are 2 bytes and most are a single cycle */ - desc.length = 2; - desc.cycles = 1; - - switch (opcode>>12) - { - case 0: - return describe_group_0(desc, prev, opcode); - - case 1: // MOVLS4 - desc.regin[0] |= REGFLAG_R(Rn) | REGFLAG_R(Rm); - desc.flags |= OPFLAG_WRITES_MEMORY; - return true; - - case 2: - return describe_group_2(desc, prev, opcode); - - case 3: - return describe_group_3(desc, prev, opcode); - - case 4: - return describe_group_4(desc, prev, opcode); - - case 5: // MOVLL4 - desc.regin[0] |= REGFLAG_R(Rm); - desc.regout[0] |= REGFLAG_R(Rn); - desc.flags |= OPFLAG_READS_MEMORY; - return true; - - case 6: - return describe_group_6(desc, prev, opcode); - - case 7: // ADDI - desc.regin[0] |= REGFLAG_R(Rn); - desc.regout[0] |= REGFLAG_R(Rn); - return true; - - case 8: - return describe_group_8(desc, prev, opcode); - - case 9: // MOVWI - desc.regout[0] |= REGFLAG_R(Rn); - desc.flags |= OPFLAG_READS_MEMORY; - return true; - - case 11: // BSR - desc.regout[1] |= REGFLAG_PR; - // (intentional fallthrough - BSR is BRA with the addition of PR = the return address) - case 10: // BRA - { - int32_t disp = ((int32_t)opcode << 20) >> 20; - - desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE; - desc.targetpc = (desc.pc + 2) + disp * 2 + 2; - desc.delayslots = 1; - desc.cycles = 2; - return true; - } - - case 12: - return describe_group_12(desc, prev, opcode); - - case 13: // MOVLI - desc.regout[0] |= REGFLAG_R(Rn); - desc.flags |= OPFLAG_READS_MEMORY; - return true; - - case 14: // MOVI - desc.regout[0] |= REGFLAG_R(Rn); - return true; - - case 15: // NOP - return true; - } - - return false; -} - -bool sh2_frontend::describe_group_0(opcode_desc &desc, const opcode_desc *prev, uint16_t opcode) -{ - switch (opcode & 0x3F) - { - case 0x00: // NOP(); - case 0x01: // NOP(); - case 0x09: // NOP(); - case 0x10: // NOP(); - case 0x11: // NOP(); - case 0x13: // NOP(); - case 0x20: // NOP(); - case 0x21: // NOP(); - case 0x30: // NOP(); - case 0x31: // NOP(); - case 0x32: // NOP(); - case 0x33: // NOP(); - case 0x38: // NOP(); - case 0x39: // NOP(); - case 0x3a: // NOP(); - case 0x3b: // NOP(); - return true; - - case 0x02: // STCSR(Rn); - desc.regout[0] |= REGFLAG_R(Rn); - return true; - - case 0x03: // BSRF(Rn); - desc.regout[1] |= REGFLAG_PR; - - desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE; - desc.targetpc = BRANCH_TARGET_DYNAMIC; - desc.delayslots = 1; - - return true; - - case 0x04: // MOVBS0(Rm, Rn); - case 0x05: // MOVWS0(Rm, Rn); - case 0x06: // MOVLS0(Rm, Rn); - case 0x14: // MOVBS0(Rm, Rn); - case 0x15: // MOVWS0(Rm, Rn); - case 0x16: // MOVLS0(Rm, Rn); - case 0x24: // MOVBS0(Rm, Rn); - case 0x25: // MOVWS0(Rm, Rn); - case 0x26: // MOVLS0(Rm, Rn); - case 0x34: // MOVBS0(Rm, Rn); - case 0x35: // MOVWS0(Rm, Rn); - case 0x36: // MOVLS0(Rm, Rn); - desc.regin[0] |= REGFLAG_R(Rm) | REGFLAG_R(Rn) | REGFLAG_R(0); - desc.flags |= OPFLAG_READS_MEMORY; - return true; - - case 0x07: // MULL(Rm, Rn); - case 0x17: // MULL(Rm, Rn); - case 0x27: // MULL(Rm, Rn); - case 0x37: // MULL(Rm, Rn); - desc.regin[0] |= REGFLAG_R(Rn) | REGFLAG_R(Rm); - desc.regout[1] |= REGFLAG_MACL; - desc.cycles = 2; - return true; - - case 0x08: // CLRT(); - desc.regout[1] |= REGFLAG_SR; - return true; - - case 0x0a: // STSMACH(Rn); - desc.regout[0] |= REGFLAG_R(Rn); - desc.regout[1] |= REGFLAG_MACH; - return true; - - case 0x0b: // RTS(); - desc.regin[1] |= REGFLAG_PR; - - desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE; - desc.targetpc = BRANCH_TARGET_DYNAMIC; - desc.delayslots = 1; - desc.cycles = 2; - - return true; - - case 0x0c: // MOVBL0(Rm, Rn); - case 0x0d: // MOVWL0(Rm, Rn); - case 0x0e: // MOVLL0(Rm, Rn); - case 0x1c: // MOVBL0(Rm, Rn); - case 0x1d: // MOVWL0(Rm, Rn); - case 0x1e: // MOVLL0(Rm, Rn); - case 0x2c: // MOVBL0(Rm, Rn); - case 0x2d: // MOVWL0(Rm, Rn); - case 0x2e: // MOVLL0(Rm, Rn); - case 0x3c: // MOVBL0(Rm, Rn); - case 0x3d: // MOVWL0(Rm, Rn); - case 0x3e: // MOVLL0(Rm, Rn); - desc.regin[0] |= REGFLAG_R(Rm) | REGFLAG_R(0); - desc.regout[0] |= REGFLAG_R(Rn); - desc.flags |= OPFLAG_READS_MEMORY; - return true; - - case 0x0f: // MAC_L(Rm, Rn); - case 0x1f: // MAC_L(Rm, Rn); - case 0x2f: // MAC_L(Rm, Rn); - case 0x3f: // MAC_L(Rm, Rn); - desc.regin[0] |= REGFLAG_R(Rm) | REGFLAG_R(Rn); - desc.regout[1] |= REGFLAG_MACL | REGFLAG_MACH; - desc.cycles = 3; - return true; - - case 0x12: // STCGBR(Rn); - desc.regout[0] |= REGFLAG_R(Rn); - desc.regin[1] |= REGFLAG_GBR; - return true; - - case 0x18: // SETT(); - desc.regout[1] |= REGFLAG_SR; - return true; - - case 0x19: // DIV0U(); - desc.regout[1] |= REGFLAG_SR; - return true; - - case 0x1a: // STSMACL(Rn); - desc.regin[1] |= REGFLAG_MACL; - desc.regout[0] |= REGFLAG_R(Rn); - return true; - - case 0x1b: // SLEEP(); - desc.cycles = 3; - return true; - - case 0x22: // STCVBR(Rn); - desc.regin[0] |= REGFLAG_R(Rn); - desc.regout[1] |= REGFLAG_VBR; - return true; - - case 0x23: // BRAF(Rn); - desc.regin[0] |= REGFLAG_R(Rm); - desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE; - desc.targetpc = BRANCH_TARGET_DYNAMIC; - desc.delayslots = 1; - desc.cycles = 2; - return true; - - case 0x28: // CLRMAC(); - desc.regout[1] |= REGFLAG_MACL | REGFLAG_MACH; - return true; - - case 0x29: // MOVT(Rn); - desc.regin[1] |= REGFLAG_SR; - desc.regout[0] |= REGFLAG_R(Rn); - return true; - - case 0x2a: // STSPR(Rn); - desc.regin[1] |= REGFLAG_PR; - desc.regout[0] |= REGFLAG_R(Rn); - return true; - - case 0x2b: // RTE(); - desc.regin[0] |= REGFLAG_R(15); - desc.regout[0] |= REGFLAG_R(15); - - desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE | OPFLAG_CAN_EXPOSE_EXTERNAL_INT; - desc.targetpc = BRANCH_TARGET_DYNAMIC; - desc.delayslots = 1; - desc.cycles = 4; - - return true; - } - - return false; -} - -bool sh2_frontend::describe_group_2(opcode_desc &desc, const opcode_desc *prev, uint16_t opcode) -{ - switch (opcode & 15) - { - case 0: // MOVBS(Rm, Rn); - case 1: // MOVWS(Rm, Rn); - case 2: // MOVLS(Rm, Rn); - desc.regin[0] |= REGFLAG_R(Rm) | REGFLAG_R(Rn); - desc.flags |= OPFLAG_WRITES_MEMORY; - return true; - - case 3: // NOP(); - return true; - - case 4: // MOVBM(Rm, Rn); - case 5: // MOVWM(Rm, Rn); - case 6: // MOVLM(Rm, Rn); - case 13: // XTRCT(Rm, Rn); - desc.regin[0] |= REGFLAG_R(Rm) | REGFLAG_R(Rn); - desc.regout[0] |= REGFLAG_R(Rn); - desc.flags |= OPFLAG_WRITES_MEMORY; - return true; - - case 7: // DIV0S(Rm, Rn); - case 8: // TST(Rm, Rn); - case 12: // CMPSTR(Rm, Rn); - desc.regin[0] |= REGFLAG_R(Rm) | REGFLAG_R(Rn); - desc.regout[1] |= REGFLAG_SR; - return true; - - case 9: // AND(Rm, Rn); - case 10: // XOR(Rm, Rn); - case 11: // OR(Rm, Rn); - desc.regin[0] |= REGFLAG_R(Rm) | REGFLAG_R(Rn); - desc.regout[0] |= REGFLAG_R(Rn); - return true; - - case 14: // MULU(Rm, Rn); - case 15: // MULS(Rm, Rn); - desc.regin[0] |= REGFLAG_R(Rm) | REGFLAG_R(Rn); - desc.regout[1] |= REGFLAG_MACL | REGFLAG_MACH; - desc.cycles = 2; - return true; - } - - return false; -} - -bool sh2_frontend::describe_group_3(opcode_desc &desc, const opcode_desc *prev, uint16_t opcode) -{ - switch (opcode & 15) - { - case 0: // CMPEQ(Rm, Rn); - case 2: // CMPHS(Rm, Rn); - case 3: // CMPGE(Rm, Rn); - case 6: // CMPHI(Rm, Rn); - case 7: // CMPGT(Rm, Rn); - desc.regin[0] |= REGFLAG_R(Rm) | REGFLAG_R(Rn); - desc.regout[1] |= REGFLAG_SR; - return true; - - case 1: // NOP(); - case 9: // NOP(); - return true; - - case 4: // DIV1(Rm, Rn); - desc.regin[0] |= REGFLAG_R(Rm) | REGFLAG_R(Rn); - desc.regout[0] |= REGFLAG_R(Rn); - desc.regout[1] |= REGFLAG_SR; - return true; - - case 5: // DMULU(Rm, Rn); - case 13: // DMULS(Rm, Rn); - desc.regin[0] |= REGFLAG_R(Rm) | REGFLAG_R(Rn); - desc.regout[1] |= REGFLAG_MACL | REGFLAG_MACH; - desc.cycles = 2; - return true; - - case 8: // SUB(Rm, Rn); - case 12: // ADD(Rm, Rn); - desc.regin[0] |= REGFLAG_R(Rm) | REGFLAG_R(Rn); - desc.regout[0] |= REGFLAG_R(Rn); - return true; - - case 10: // SUBC(Rm, Rn); - case 11: // SUBV(Rm, Rn); - case 14: // ADDC(Rm, Rn); - case 15: // ADDV(Rm, Rn); - desc.regin[0] |= REGFLAG_R(Rm) | REGFLAG_R(Rn); - desc.regin[1] |= REGFLAG_SR; - desc.regout[0] |= REGFLAG_R(Rn); - desc.regout[1] |= REGFLAG_SR; - return true; - } - return false; -} - -bool sh2_frontend::describe_group_4(opcode_desc &desc, const opcode_desc *prev, uint16_t opcode) -{ - switch (opcode & 0x3F) - { - case 0x00: // SHLL(Rn); - case 0x01: // SHLR(Rn); - case 0x04: // ROTL(Rn); - case 0x05: // ROTR(Rn); - desc.regin[0] |= REGFLAG_R(Rn); - desc.regout[0] |= REGFLAG_R(Rn); - desc.regout[1] |= REGFLAG_SR; - return true; - - case 0x02: // STSMMACH(Rn); - desc.regin[0] |= REGFLAG_R(Rn); - desc.regin[1] |= REGFLAG_MACH; - desc.regout[0] |= REGFLAG_R(Rn); - desc.flags |= OPFLAG_WRITES_MEMORY; - return true; - - case 0x03: // STCMSR(Rn); - desc.regin[0] |= REGFLAG_R(Rn); - desc.regout[0] |= REGFLAG_R(Rn); - desc.cycles = 2; - desc.flags |= OPFLAG_WRITES_MEMORY; - return true; - - case 0x06: // LDSMMACH(Rn); - desc.regin[0] |= REGFLAG_R(Rn); - desc.regout[0] |= REGFLAG_R(Rn); - desc.regout[1] |= REGFLAG_MACH; - desc.flags |= OPFLAG_READS_MEMORY; - return true; - - case 0x07: // LDCMSR(Rn); - desc.regin[0] |= REGFLAG_R(Rn); - desc.regout[0] |= REGFLAG_R(Rn); - desc.regout[1] |= REGFLAG_SR; - desc.cycles = 3; - desc.flags |= OPFLAG_READS_MEMORY | OPFLAG_CAN_EXPOSE_EXTERNAL_INT | OPFLAG_END_SEQUENCE; - return true; - - case 0x08: // SHLL2(Rn); - case 0x09: // SHLR2(Rn); - case 0x18: // SHLL8(Rn); - case 0x19: // SHLR8(Rn); - case 0x28: // SHLL16(Rn); - case 0x29: // SHLR16(Rn); - desc.regin[0] |= REGFLAG_R(Rn); - desc.regout[0] |= REGFLAG_R(Rn); - return true; - - case 0x0a: // LDSMACH(Rn); - desc.regin[0] |= REGFLAG_R(Rn); - desc.regout[1] |= REGFLAG_MACH; - return true; - - case 0x0b: // JSR(Rn); - desc.regin[0] |= REGFLAG_R(Rn); - desc.regout[1] |= REGFLAG_PR; - desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE; - desc.targetpc = BRANCH_TARGET_DYNAMIC; - desc.delayslots = 1; - return true; - - case 0x0e: // LDCSR(Rn); - desc.regin[0] |= REGFLAG_R(Rn); - desc.regout[1] |= REGFLAG_SR; - desc.flags |= OPFLAG_CAN_EXPOSE_EXTERNAL_INT | OPFLAG_END_SEQUENCE; - return true; - - case 0x0f: // MAC_W(Rm, Rn); - case 0x1f: // MAC_W(Rm, Rn); - case 0x2f: // MAC_W(Rm, Rn); - case 0x3f: // MAC_W(Rm, Rn); - desc.regin[0] |= REGFLAG_R(Rm) | REGFLAG_R(Rn); - desc.regin[1] |= REGFLAG_MACL | REGFLAG_MACH; - desc.regout[0] |= REGFLAG_R(Rm) | REGFLAG_R(Rn); - desc.regout[1] |= REGFLAG_MACL | REGFLAG_MACH; - desc.cycles = 3; - return true; - - case 0x10: // DT(Rn); - desc.regin[0] |= REGFLAG_R(Rn); - desc.regin[1] |= REGFLAG_SR; - desc.regout[0] |= REGFLAG_R(Rn); - desc.regout[1] |= REGFLAG_SR; - return true; - - case 0x11: // CMPPZ(Rn); - case 0x15: // CMPPL(Rn); - desc.regin[0] |= REGFLAG_R(Rn); - desc.regin[1] |= REGFLAG_SR; - desc.regout[1] |= REGFLAG_SR; - return true; - - case 0x12: // STSMMACL(Rn); - desc.regin[0] |= REGFLAG_R(Rn); - desc.regin[1] |= REGFLAG_MACL; - desc.regout[0] |= REGFLAG_R(Rn); - desc.flags |= OPFLAG_WRITES_MEMORY; - return true; - - case 0x13: // STCMGBR(Rn); - desc.regin[0] |= REGFLAG_R(Rn); - desc.regin[1] |= REGFLAG_GBR; - desc.regout[0] |= REGFLAG_R(Rn); - desc.flags |= OPFLAG_WRITES_MEMORY; - return true; - - case 0x16: // LDSMMACL(Rn); - desc.regin[0] |= REGFLAG_R(Rm) | REGFLAG_R(Rn); - desc.regout[0] |= REGFLAG_R(Rm) | REGFLAG_R(Rn); - desc.regout[1] |= REGFLAG_MACL; - desc.flags |= OPFLAG_READS_MEMORY; - return true; - - case 0x17: // LDCMGBR(Rn); - desc.regin[0] |= REGFLAG_R(Rn); - desc.regout[0] |= REGFLAG_R(Rn); - desc.regout[1] |= REGFLAG_GBR; - desc.flags |= OPFLAG_READS_MEMORY; - return true; - - case 0x1a: // LDSMACL(Rn); - desc.regin[0] |= REGFLAG_R(Rn); - desc.regout[1] |= REGFLAG_MACL; - return true; - - case 0x1b: // TAS(Rn); - desc.regin[0] |= REGFLAG_R(Rn); - desc.regin[1] |= REGFLAG_SR; - desc.regout[1] |= REGFLAG_SR; - desc.cycles = 4; - desc.flags |= OPFLAG_READS_MEMORY | OPFLAG_WRITES_MEMORY; - return true; - - case 0x1e: // LDCGBR(Rn); - desc.regin[0] |= REGFLAG_R(Rn); - desc.regout[1] |= REGFLAG_GBR; - return true; - - case 0x20: // SHAL(Rn); - case 0x21: // SHAR(Rn); - desc.regin[0] |= REGFLAG_R(Rn); - desc.regout[0] |= REGFLAG_R(Rn); - desc.regout[1] |= REGFLAG_SR; - return true; - - case 0x22: // STSMPR(Rn); - desc.regin[0] |= REGFLAG_R(Rn); - desc.regin[1] |= REGFLAG_PR; - desc.regout[0] |= REGFLAG_R(Rn); - desc.flags |= OPFLAG_WRITES_MEMORY; - return true; - - case 0x23: // STCMVBR(Rn); - desc.regin[0] |= REGFLAG_R(Rn); - desc.regin[1] |= REGFLAG_VBR; - desc.regout[0] |= REGFLAG_R(Rn); - desc.flags |= OPFLAG_WRITES_MEMORY; - return true; - - case 0x24: // ROTCL(Rn); - case 0x25: // ROTCR(Rn); - desc.regin[0] |= REGFLAG_R(Rn); - desc.regin[1] |= REGFLAG_SR; - desc.regout[0] |= REGFLAG_R(Rn); - desc.regout[1] |= REGFLAG_SR; - return true; - - case 0x26: // LDSMPR(Rn); - desc.regin[0] |= REGFLAG_R(Rn); - desc.regout[0] |= REGFLAG_R(Rn); - desc.regout[1] |= REGFLAG_PR; - desc.flags |= OPFLAG_READS_MEMORY; - return true; - - case 0x27: // LDCMVBR(Rn); - desc.regin[0] |= REGFLAG_R(Rn); - desc.regout[0] |= REGFLAG_R(Rn); - desc.regout[1] |= REGFLAG_VBR; - desc.flags |= OPFLAG_READS_MEMORY; - return true; - - case 0x2a: // LDSPR(Rn); - desc.regin[0] |= REGFLAG_R(Rn); - desc.regout[1] |= REGFLAG_PR; - return true; - - case 0x2b: // JMP(Rm); - desc.regin[0] |= REGFLAG_R(Rm); - desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE; - desc.targetpc = BRANCH_TARGET_DYNAMIC; - desc.delayslots = 1; - return true; - - case 0x2e: // LDCVBR(Rn); - desc.regin[0] |= REGFLAG_R(Rn); - desc.regout[1] |= REGFLAG_VBR; - return true; - - case 0x0c: // NOP(); - case 0x0d: // NOP(); - case 0x14: // NOP(); - case 0x1c: // NOP(); - case 0x1d: // NOP(); - case 0x2c: // NOP(); - case 0x2d: // NOP(); - case 0x30: // NOP(); - case 0x31: // NOP(); - case 0x32: // NOP(); - case 0x33: // NOP(); - case 0x34: // NOP(); - case 0x35: // NOP(); - case 0x36: // NOP(); - case 0x37: // NOP(); - case 0x38: // NOP(); - case 0x39: // NOP(); - case 0x3a: // NOP(); - case 0x3b: // NOP(); - case 0x3c: // NOP(); - case 0x3d: // NOP(); - case 0x3e: // NOP(); - return true; - } - - return false; -} - -bool sh2_frontend::describe_group_6(opcode_desc &desc, const opcode_desc *prev, uint16_t opcode) -{ - switch (opcode & 15) - { - case 0: // MOVBL(Rm, Rn); - case 1: // MOVWL(Rm, Rn); - case 2: // MOVLL(Rm, Rn); - case 3: // MOV(Rm, Rn); - case 7: // NOT(Rm, Rn); - case 9: // SWAPW(Rm, Rn); - case 11: // NEG(Rm, Rn); - case 12: // EXTUB(Rm, Rn); - case 13: // EXTUW(Rm, Rn); - case 14: // EXTSB(Rm, Rn); - case 15: // EXTSW(Rm, Rn); - desc.regin[0] |= REGFLAG_R(Rm); - desc.regout[0] |= REGFLAG_R(Rn); - return true; - - case 4: // MOVBP(Rm, Rn); - case 5: // MOVWP(Rm, Rn); - case 6: // MOVLP(Rm, Rn); - desc.regin[0] |= REGFLAG_R(Rm) | REGFLAG_R(Rn); - desc.regout[0] |= REGFLAG_R(Rn); - desc.flags |= OPFLAG_READS_MEMORY; - return true; - - case 8: // SWAPB(Rm, Rn); - desc.regin[0] |= REGFLAG_R(Rm) | REGFLAG_R(Rn); - desc.regout[0] |= REGFLAG_R(Rn); - return true; - - case 10: // NEGC(Rm, Rn); - desc.regin[0] |= REGFLAG_R(Rm); - desc.regout[0] |= REGFLAG_R(Rn); - desc.regout[1] |= REGFLAG_SR; - return true; - } - return false; -} - -bool sh2_frontend::describe_group_8(opcode_desc &desc, const opcode_desc *prev, uint16_t opcode) -{ - int32_t disp; - - switch ( opcode & (15<<8) ) - { - case 0 << 8: // MOVBS4(opcode & 0x0f, Rm); - case 1 << 8: // MOVWS4(opcode & 0x0f, Rm); - desc.regin[0] |= REGFLAG_R(Rm) | REGFLAG_R(0); - desc.flags |= OPFLAG_WRITES_MEMORY; - return true; - - case 2<< 8: // NOP(); - case 3<< 8: // NOP(); - case 6<< 8: // NOP(); - case 7<< 8: // NOP(); - case 10<< 8: // NOP(); - case 12<< 8: // NOP(); - case 14<< 8: // NOP(); - return true; - - case 4<< 8: // MOVBL4(Rm, opcode & 0x0f); - case 5<< 8: // MOVWL4(Rm, opcode & 0x0f); - desc.regin[0] |= REGFLAG_R(Rm); - desc.regout[0] |= REGFLAG_R(0); - desc.flags |= OPFLAG_READS_MEMORY; - return true; - - case 8<< 8: // CMPIM(opcode & 0xff); - desc.regin[0] |= REGFLAG_R(Rm); - desc.regin[1] |= REGFLAG_SR; - desc.regout[1] |= REGFLAG_SR; - return true; - - case 9<< 8: // BT(opcode & 0xff); - case 11<< 8: // BF(opcode & 0xff); - desc.flags |= OPFLAG_IS_CONDITIONAL_BRANCH; - desc.cycles = 3; - disp = ((int32_t)opcode << 24) >> 24; - desc.targetpc = (desc.pc + 2) + disp * 2 + 2; - return true; - - case 13<< 8: // BTS(opcode & 0xff); - case 15<< 8: // BFS(opcode & 0xff); - desc.flags |= OPFLAG_IS_CONDITIONAL_BRANCH; - desc.cycles = 2; - disp = ((int32_t)opcode << 24) >> 24; - desc.targetpc = (desc.pc + 2) + disp * 2 + 2; - desc.delayslots = 1; - return true; - } - - return false; -} - -bool sh2_frontend::describe_group_12(opcode_desc &desc, const opcode_desc *prev, uint16_t opcode) -{ - switch (opcode & (15<<8)) - { - case 0<<8: // MOVBSG(opcode & 0xff); - case 1<<8: // MOVWSG(opcode & 0xff); - case 2<<8: // MOVLSG(opcode & 0xff); - desc.regin[0] |= REGFLAG_R(0); - desc.flags |= OPFLAG_WRITES_MEMORY; - return true; - - case 3<<8: // TRAPA(opcode & 0xff); - desc.regin[0] |= REGFLAG_R(15); - desc.regin[1] |= REGFLAG_VBR; - desc.regout[0] |= REGFLAG_R(15); - desc.cycles = 8; - desc.targetpc = BRANCH_TARGET_DYNAMIC; - desc.flags |= OPFLAG_READS_MEMORY | OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE; - return true; - - case 4<<8: // MOVBLG(opcode & 0xff); - case 5<<8: // MOVWLG(opcode & 0xff); - case 6<<8: // MOVLLG(opcode & 0xff); - case 7<<8: // MOVA(opcode & 0xff); - desc.regout[0] |= REGFLAG_R(0); - desc.flags |= OPFLAG_READS_MEMORY; - return true; - - case 8<<8: // TSTI(opcode & 0xff); - desc.regin[0] |= REGFLAG_R(0); - desc.regin[1] |= REGFLAG_SR; - desc.regout[1] |= REGFLAG_SR; - return true; - - case 9<<8: // ANDI(opcode & 0xff); - case 10<<8: // XORI(opcode & 0xff); - case 11<<8: // ORI(opcode & 0xff); - desc.regin[0] |= REGFLAG_R(0); - desc.regout[0] |= REGFLAG_R(0); - return true; - - case 12<<8: // TSTM(opcode & 0xff); - case 13<<8: // ANDM(opcode & 0xff); - case 14<<8: // XORM(opcode & 0xff); - case 15<<8: // ORM(opcode & 0xff); - desc.regin[0] |= REGFLAG_R(0); - desc.regin[1] |= REGFLAG_SR | REGFLAG_GBR; - desc.regout[1] |= REGFLAG_SR; - desc.flags |= OPFLAG_READS_MEMORY; - return true; - } - - return false; -} diff --git a/src/devices/cpu/superh/sh3comn.cpp b/src/devices/cpu/superh/sh3comn.cpp deleted file mode 100644 index 4a50e748eb9..00000000000 --- a/src/devices/cpu/superh/sh3comn.cpp +++ /dev/null @@ -1,681 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:R. Belmont -/* Handlers for SH3 internals */ - -#include "emu.h" -#include "debugger.h" -#include "sh4.h" -#include "sh4comn.h" -#include "sh3comn.h" -#include "sh4tmu.h" -#include "sh4dmac.h" - -/* High internal area (ffffxxxx) */ - -WRITE32_MEMBER( sh3_base_device::sh3_internal_high_w ) -{ - COMBINE_DATA(&m_sh3internal_upper[offset]); - - switch (offset) - { - case SH3_ICR0_IPRA_ADDR: - if (mem_mask & 0xffff0000) - { - logerror("'%s' (%08x): INTC internal write to %08x = %08x & %08x (SH3_ICR0_IPRA_ADDR - ICR0)\n",tag(), m_pc & AM,(offset *4)+SH3_UPPER_REGBASE,data,mem_mask); - } - - if (mem_mask & 0x0000ffff) - { - logerror("'%s' (%08x): INTC internal write to %08x = %08x & %08x (SH3_ICR0_IPRA_ADDR - IPRA)\n",tag(), m_pc & AM,(offset *4)+SH3_UPPER_REGBASE,data,mem_mask); - sh4_handler_ipra_w(data&0xffff,mem_mask&0xffff); - } - - break; - - case SH3_IPRB_ADDR: - logerror("'%s' (%08x): INTC internal write to %08x = %08x & %08x (SH3_IPRB_ADDR)\n",tag(), m_pc & AM,(offset *4)+SH3_UPPER_REGBASE,data,mem_mask); - break; - - case SH3_TOCR_TSTR_ADDR: - logerror("'%s' (%08x): TMU internal write to %08x = %08x & %08x (SH3_TOCR_TSTR_ADDR)\n",tag(), m_pc & AM,(offset *4)+SH3_UPPER_REGBASE,data,mem_mask); - if (mem_mask&0xff000000) - { - sh4_handle_tocr_addr_w((data>>24)&0xffff, (mem_mask>>24)&0xff); - } - if (mem_mask&0x0000ff00) - { - sh4_handle_tstr_addr_w((data>>8)&0xff, (mem_mask>>8)&0xff); - } - if (mem_mask&0x00ff00ff) - { - fatalerror("SH3_TOCR_TSTR_ADDR unused bits accessed (write)\n"); - } - break; - case SH3_TCOR0_ADDR: sh4_handle_tcor0_addr_w(data, mem_mask);break; - case SH3_TCOR1_ADDR: sh4_handle_tcor1_addr_w(data, mem_mask);break; - case SH3_TCOR2_ADDR: sh4_handle_tcor2_addr_w(data, mem_mask);break; - case SH3_TCNT0_ADDR: sh4_handle_tcnt0_addr_w(data, mem_mask);break; - case SH3_TCNT1_ADDR: sh4_handle_tcnt1_addr_w(data, mem_mask);break; - case SH3_TCNT2_ADDR: sh4_handle_tcnt2_addr_w(data, mem_mask);break; - case SH3_TCR0_ADDR: sh4_handle_tcr0_addr_w(data>>16, mem_mask>>16);break; - case SH3_TCR1_ADDR: sh4_handle_tcr1_addr_w(data>>16, mem_mask>>16);break; - case SH3_TCR2_ADDR: sh4_handle_tcr2_addr_w(data>>16, mem_mask>>16);break; - case SH3_TCPR2_ADDR: sh4_handle_tcpr2_addr_w(data, mem_mask);break; - - default: - logerror("'%s' (%08x): unmapped internal write to %08x = %08x & %08x (unk)\n",tag(), m_pc & AM,(offset *4)+SH3_UPPER_REGBASE,data,mem_mask); - break; - - } - - - - -} - -READ32_MEMBER( sh3_base_device::sh3_internal_high_r ) -{ - uint32_t ret = 0; - - switch (offset) - { - case SH3_ICR0_IPRA_ADDR: - logerror("'%s' (%08x): INTC internal read from %08x mask %08x (SH3_ICR0_IPRA_ADDR - %08x)\n",tag(), m_pc & AM,(offset *4)+SH3_UPPER_REGBASE,mem_mask, m_sh3internal_upper[offset]); - return (m_sh3internal_upper[offset] & 0xffff0000) | (m_SH4_IPRA & 0xffff); - - case SH3_IPRB_ADDR: - logerror("'%s' (%08x): INTC internal read from %08x mask %08x (SH3_IPRB_ADDR - %08x)\n",tag(), m_pc & AM,(offset *4)+SH3_UPPER_REGBASE,mem_mask, m_sh3internal_upper[offset]); - return m_sh3internal_upper[offset]; - - case SH3_TOCR_TSTR_ADDR: - - if (mem_mask&0xff00000) - { - ret |= (sh4_handle_tocr_addr_r(mem_mask)&0xff)<<24; - } - if (mem_mask&0x0000ff00) - { - ret |= (sh4_handle_tstr_addr_r(mem_mask)&0xff)<<8; - } - if (mem_mask&0x00ff00ff) - { - fatalerror("SH3_TOCR_TSTR_ADDR unused bits accessed (read)\n"); - } - return ret; - case SH3_TCOR0_ADDR: return sh4_handle_tcor0_addr_r(mem_mask); - case SH3_TCOR1_ADDR: return sh4_handle_tcor1_addr_r(mem_mask); - case SH3_TCOR2_ADDR: return sh4_handle_tcor2_addr_r(mem_mask); - case SH3_TCNT0_ADDR: return sh4_handle_tcnt0_addr_r(mem_mask); - case SH3_TCNT1_ADDR: return sh4_handle_tcnt1_addr_r(mem_mask); - case SH3_TCNT2_ADDR: return sh4_handle_tcnt2_addr_r(mem_mask); - case SH3_TCR0_ADDR: return sh4_handle_tcr0_addr_r(mem_mask)<<16; - case SH3_TCR1_ADDR: return sh4_handle_tcr1_addr_r(mem_mask)<<16; - case SH3_TCR2_ADDR: return sh4_handle_tcr2_addr_r(mem_mask)<<16; - case SH3_TCPR2_ADDR: return sh4_handle_tcpr2_addr_r(mem_mask); - - - case SH3_TRA_ADDR: - logerror("'%s' (%08x): unmapped internal read from %08x mask %08x (SH3 TRA - %08x)\n",tag(), m_pc & AM,(offset *4)+SH3_UPPER_REGBASE,mem_mask, m_sh3internal_upper[offset]); - return m_sh3internal_upper[offset]; - - case SH3_EXPEVT_ADDR: - logerror("'%s' (%08x): unmapped internal read from %08x mask %08x (SH3 EXPEVT - %08x)\n",tag(), m_pc & AM,(offset *4)+SH3_UPPER_REGBASE,mem_mask, m_sh3internal_upper[offset]); - return m_sh3internal_upper[offset]; - - case SH3_INTEVT_ADDR: - logerror("'%s' (%08x): unmapped internal read from %08x mask %08x (SH3 INTEVT - %08x)\n",tag(), m_pc & AM,(offset *4)+SH3_UPPER_REGBASE,mem_mask, m_sh3internal_upper[offset]); - fatalerror("INTEVT unsupported on SH3\n"); - // never executed - //return m_sh3internal_upper[offset]; - - - default: - logerror("'%s' (%08x): unmapped internal read from %08x mask %08x\n",tag(), m_pc & AM,(offset *4)+SH3_UPPER_REGBASE,mem_mask); - return m_sh3internal_upper[offset]; - } -} - - -READ32_MEMBER( sh3_base_device::sh3_internal_r ) -{ - if (offset<0x1000) - { - switch (offset) - { - case SH3_SAR0_ADDR: return sh4_handle_sar0_addr_r(mem_mask); - case SH3_SAR1_ADDR: return sh4_handle_sar1_addr_r(mem_mask); - case SH3_SAR2_ADDR: return sh4_handle_sar2_addr_r(mem_mask); - case SH3_SAR3_ADDR: return sh4_handle_sar3_addr_r(mem_mask); - case SH3_DAR0_ADDR: return sh4_handle_dar0_addr_r(mem_mask); - case SH3_DAR1_ADDR: return sh4_handle_dar1_addr_r(mem_mask); - case SH3_DAR2_ADDR: return sh4_handle_dar2_addr_r(mem_mask); - case SH3_DAR3_ADDR: return sh4_handle_dar3_addr_r(mem_mask); - case SH3_DMATCR0_ADDR: return sh4_handle_dmatcr0_addr_r(mem_mask); - case SH3_DMATCR1_ADDR: return sh4_handle_dmatcr1_addr_r(mem_mask); - case SH3_DMATCR2_ADDR: return sh4_handle_dmatcr2_addr_r(mem_mask); - case SH3_DMATCR3_ADDR: return sh4_handle_dmatcr3_addr_r(mem_mask); - case SH3_CHCR0_ADDR: return sh4_handle_chcr0_addr_r(mem_mask); - case SH3_CHCR1_ADDR: return sh4_handle_chcr1_addr_r(mem_mask); - case SH3_CHCR2_ADDR: return sh4_handle_chcr2_addr_r(mem_mask); - case SH3_CHCR3_ADDR: return sh4_handle_chcr3_addr_r(mem_mask); - case SH3_DMAOR_ADDR: return sh4_handle_dmaor_addr_r(mem_mask)<<16; - - - case INTEVT2: - { - // logerror("'%s' (%08x): unmapped internal read from %08x mask %08x (INTEVT2)\n",tag(), m_pc & AM,(offset *4)+0x4000000,mem_mask); - return m_sh3internal_lower[offset]; - } - - - case IRR0_IRR1: - { - { - if (mem_mask & 0xff000000) - { - logerror("'%s' (%08x): unmapped internal read from %08x mask %08x (IRR0)\n",tag(), m_pc & AM,(offset *4)+0x4000000,mem_mask); - return m_sh3internal_lower[offset]; - } - - if (mem_mask & 0x0000ff00) - { - logerror("'%s' (%08x): unmapped internal read from %08x mask %08x (IRR1)\n",tag(), m_pc & AM,(offset *4)+0x4000000,mem_mask); - return m_sh3internal_lower[offset]; - } - - fatalerror("'%s' (%08x): unmapped internal read from %08x mask %08x (IRR0/1 unused bits)\n",tag(), m_pc & AM,(offset *4)+0x4000000,mem_mask); - } - } - - case PADR_PBDR: - { - if (mem_mask & 0xffff0000) - { - //logerror("'%s' (%08x): unmapped internal read from %08x mask %08x (PADR)\n",tag(), m_pc & AM,(offset *4)+0x4000000,mem_mask); - return m_io->read_qword(SH3_PORT_A)<<24; - } - - if (mem_mask & 0x0000ffff) - { - //logerror("'%s' (%08x): unmapped internal read from %08x mask %08x (PBDR)\n",tag(), m_pc & AM,(offset *4)+0x4000000,mem_mask); - return m_io->read_qword(SH3_PORT_B)<<8; - } - } - break; - - case PCDR_PDDR: - { - if (mem_mask & 0xffff0000) - { - //logerror("'%s' (%08x): unmapped internal read from %08x mask %08x (PCDR)\n",tag(), m_pc & AM,(offset *4)+0x4000000,mem_mask); - return m_io->read_qword(SH3_PORT_C)<<24; - } - - if (mem_mask & 0x0000ffff) - { - //logerror("'%s' (%08x): unmapped internal read from %08x mask %08x (PDDR)\n",tag(), m_pc & AM,(offset *4)+0x4000000,mem_mask); - return m_io->read_qword(SH3_PORT_D)<<8; - } - } - break; - - case PEDR_PFDR: - { - if (mem_mask & 0xffff0000) - { - //logerror("'%s' (%08x): unmapped internal read from %08x mask %08x (PEDR)\n",tag(), m_pc & AM,(offset *4)+0x4000000,mem_mask); - return m_io->read_qword(SH3_PORT_E)<<24; - } - - if (mem_mask & 0x0000ffff) - { - //logerror("'%s' (%08x): unmapped internal read from %08x mask %08x (PFDR)\n",tag(), m_pc & AM,(offset *4)+0x4000000,mem_mask); - return m_io->read_qword(SH3_PORT_F)<<8; - } - } - break; - - case PGDR_PHDR: - { - if (mem_mask & 0xffff0000) - { - //logerror("'%s' (%08x): unmapped internal read from %08x mask %08x (PGDR)\n",tag(), m_pc & AM,(offset *4)+0x4000000,mem_mask); - return m_io->read_qword(SH3_PORT_G)<<24; - } - - if (mem_mask & 0x0000ffff) - { - //logerror("'%s' (%08x): unmapped internal read from %08x mask %08x (PHDR)\n",tag(), m_pc & AM,(offset *4)+0x4000000,mem_mask); - return m_io->read_qword(SH3_PORT_H)<<8; - } - } - break; - - case PJDR_PKDR: - { - if (mem_mask & 0xffff0000) - { - //logerror("'%s' (%08x): unmapped internal read from %08x mask %08x (PJDR)\n",tag(), m_pc & AM,(offset *4)+0x4000000,mem_mask); - return m_io->read_qword(SH3_PORT_J)<<24; - } - - if (mem_mask & 0x0000ffff) - { - //logerror("'%s' (%08x): unmapped internal read from %08x mask %08x (PKDR)\n",tag(), m_pc & AM,(offset *4)+0x4000000,mem_mask); - return m_io->read_qword(SH3_PORT_K)<<8; - } - } - break; - - case PLDR_SCPDR: - { - if (mem_mask & 0xffff0000) - { - //logerror("'%s' (%08x): unmapped internal read from %08x mask %08x (PLDR)\n",tag(), m_pc & AM,(offset *4)+0x4000000,mem_mask); - return m_io->read_qword(SH3_PORT_L)<<24; - } - - if (mem_mask & 0x0000ffff) - { - logerror("'%s' (%08x): unmapped internal read from %08x mask %08x (SCPDR)\n",tag(), m_pc & AM,(offset *4)+0x4000000,mem_mask); - //return m_io->read_qword(SH3_PORT_K)<<8; - } - } - break; - - - case SCSMR2_SCBRR2: - { - if (mem_mask & 0xff000000) - { - logerror("'%s' (%08x): SCIF internal read from %08x mask %08x (SCSMR2 - Serial Mode Register 2)\n",tag(), m_pc & AM,(offset *4)+0x4000000,mem_mask); - return m_sh3internal_lower[offset]; - } - - if (mem_mask & 0x0000ff00) - { - logerror("'%s' (%08x): SCIF internal read from %08x mask %08x (SCBRR2 - Bit Rate Register 2)\n",tag(), m_pc & AM,(offset *4)+0x4000000,mem_mask); - return m_sh3internal_lower[offset]; - } - } - break; - - case SCSCR2_SCFTDR2: - { - if (mem_mask & 0xff000000) - { - logerror("'%s' (%08x): SCIF internal read from %08x mask %08x (SCSCR2 - Serial Control Register 2)\n",tag(), m_pc & AM,(offset *4)+0x4000000,mem_mask); - return m_sh3internal_lower[offset]; - } - - if (mem_mask & 0x0000ff00) - { - logerror("'%s' (%08x): SCIF internal read from %08x mask %08x (SCFTDR2 - Transmit FIFO Data Register 2)\n",tag(), m_pc & AM,(offset *4)+0x4000000,mem_mask); - return m_sh3internal_lower[offset]; - } - } - break; - - case SCSSR2_SCFRDR2: - { - if (mem_mask & 0xffff0000) - { - logerror("'%s' (%08x): SCIF internal read from %08x mask %08x (SCSSR2 - Serial Status Register 2)\n",tag(), m_pc & AM,(offset *4)+0x4000000,mem_mask); - return m_sh3internal_lower[offset]; - } - - if (mem_mask & 0x0000ff00) - { - logerror("'%s' (%08x): SCIF internal read from %08x mask %08x (SCFRDR2 - Receive FIFO Data Register 2)\n",tag(), m_pc & AM,(offset *4)+0x4000000,mem_mask); - return m_sh3internal_lower[offset]; - } - } - break; - - case SCFCR2_SCFDR2: - { - if (mem_mask & 0xff000000) - { - logerror("'%s' (%08x): SCIF internal read from %08x mask %08x (SCFCR2 - Fifo Control Register 2)\n",tag(), m_pc & AM,(offset *4)+0x4000000,mem_mask); - return m_sh3internal_lower[offset]; - } - - if (mem_mask & 0x0000ffff) - { - logerror("'%s' (%08x): SCIF internal read from %08x mask %08x (SCFDR2 - Fifo Data Count Register 2)\n",tag(), m_pc & AM,(offset *4)+0x4000000,mem_mask); - return m_sh3internal_lower[offset]; - } - } - break; - - - default: - { - logerror("'%s' (%08x): unmapped internal read from %08x mask %08x\n", - tag(), m_pc & AM, - (offset *4)+0x4000000, - mem_mask); - } - break; - - } - - } - else - { - logerror("'%s' (%08x): unmapped internal read from %08x mask %08x\n", - tag(), m_pc & AM, - (offset *4)+0x4000000, - mem_mask); - } - - return 0; -} - -/* Lower internal area */ - -WRITE32_MEMBER( sh3_base_device::sh3_internal_w ) -{ - if (offset<0x1000) - { - //uint32_t old = m_sh3internal_lower[offset]; - COMBINE_DATA(&m_sh3internal_lower[offset]); - - switch (offset) - { - case SH3_SAR0_ADDR: sh4_handle_sar0_addr_w(data,mem_mask); break; - case SH3_SAR1_ADDR: sh4_handle_sar1_addr_w(data,mem_mask); break; - case SH3_SAR2_ADDR: sh4_handle_sar2_addr_w(data,mem_mask); break; - case SH3_SAR3_ADDR: sh4_handle_sar3_addr_w(data,mem_mask); break; - case SH3_DAR0_ADDR: sh4_handle_dar0_addr_w(data,mem_mask); break; - case SH3_DAR1_ADDR: sh4_handle_dar1_addr_w(data,mem_mask); break; - case SH3_DAR2_ADDR: sh4_handle_dar2_addr_w(data,mem_mask); break; - case SH3_DAR3_ADDR: sh4_handle_dar3_addr_w(data,mem_mask); break; - case SH3_DMATCR0_ADDR: sh4_handle_dmatcr0_addr_w(data,mem_mask); break; - case SH3_DMATCR1_ADDR: sh4_handle_dmatcr1_addr_w(data,mem_mask); break; - case SH3_DMATCR2_ADDR: sh4_handle_dmatcr2_addr_w(data,mem_mask); break; - case SH3_DMATCR3_ADDR: sh4_handle_dmatcr3_addr_w(data,mem_mask); break; - case SH3_CHCR0_ADDR: sh4_handle_chcr0_addr_w(data,mem_mask); break; - case SH3_CHCR1_ADDR: sh4_handle_chcr1_addr_w(data,mem_mask); break; - case SH3_CHCR2_ADDR: sh4_handle_chcr2_addr_w(data,mem_mask); break; - case SH3_CHCR3_ADDR: sh4_handle_chcr3_addr_w(data,mem_mask); break; - case SH3_DMAOR_ADDR: sh4_handle_dmaor_addr_w(data>>16,mem_mask>>16); break; - - - case IRR0_IRR1: - { - { - if (mem_mask & 0xff000000) - { - logerror("'%s' (%08x): unmapped internal write to %08x = %08x & %08x (IRR0)\n",tag(), m_pc & AM,(offset *4)+0x4000000,data,mem_mask); - // not sure if this is how we should clear lines in this core... - if (!(data & 0x01000000)) execute_set_input(0, CLEAR_LINE); - if (!(data & 0x02000000)) execute_set_input(1, CLEAR_LINE); - if (!(data & 0x04000000)) execute_set_input(2, CLEAR_LINE); - if (!(data & 0x08000000)) execute_set_input(3, CLEAR_LINE); - - } - if (mem_mask & 0x0000ff00) - { - logerror("'%s' (%08x): unmapped internal write to %08x = %08x & %08x (IRR1)\n",tag(), m_pc & AM,(offset *4)+0x4000000,data,mem_mask); - } - if (mem_mask & 0x00ff00ff) - { - fatalerror("'%s' (%08x): unmapped internal write to %08x = %08x & %08x (IRR0/1 unused bits)\n",tag(), m_pc & AM,(offset *4)+0x4000000,data,mem_mask); - } - } - } - break; - - case PINTER_IPRC: - { - if (mem_mask & 0xffff0000) - { - logerror("'%s' (%08x): unmapped internal write to %08x = %08x & %08x (PINTER)\n",tag(), m_pc & AM,(offset *4)+0x4000000,data,mem_mask); - } - - if (mem_mask & 0x0000ffff) - { - data &= 0xffff; mem_mask &= 0xffff; - COMBINE_DATA(&m_SH4_IPRC); - logerror("'%s' (%08x): INTC internal write to %08x = %08x & %08x (IPRC)\n",tag(), m_pc & AM,(offset *4)+0x4000000,data,mem_mask); - m_exception_priority[SH4_INTC_IRL0] = INTPRI((m_SH4_IPRC & 0x000f)>>0, SH4_INTC_IRL0); - m_exception_priority[SH4_INTC_IRL1] = INTPRI((m_SH4_IPRC & 0x00f0)>>4, SH4_INTC_IRL1); - m_exception_priority[SH4_INTC_IRL2] = INTPRI((m_SH4_IPRC & 0x0f00)>>8, SH4_INTC_IRL2); - m_exception_priority[SH4_INTC_IRL3] = INTPRI((m_SH4_IPRC & 0xf000)>>12,SH4_INTC_IRL3); - sh4_exception_recompute(); - } - } - break; - - case PCCR_PDCR: - { - if (mem_mask & 0xffff0000) - { - logerror("'%s' (%08x): unmapped internal write to %08x = %08x & %08x (PCCR)\n",tag(), m_pc & AM,(offset *4)+0x4000000,data,mem_mask); - } - - if (mem_mask & 0x0000ffff) - { - logerror("'%s' (%08x): unmapped internal write to %08x = %08x & %08x (PDCR)\n",tag(), m_pc & AM,(offset *4)+0x4000000,data,mem_mask); - } - } - break; - - case PECR_PFCR: - { - if (mem_mask & 0xffff0000) - { - logerror("'%s' (%08x): unmapped internal write to %08x = %08x & %08x (PECR)\n",tag(), m_pc & AM,(offset *4)+0x4000000,data,mem_mask); - } - - if (mem_mask & 0x0000ffff) - { - logerror("'%s' (%08x): unmapped internal write to %08x = %08x & %08x (PFCR)\n",tag(), m_pc & AM,(offset *4)+0x4000000,data,mem_mask); - } - } - break; - - - case PGCR_PHCR: - { - if (mem_mask & 0xffff0000) - { - logerror("'%s' (%08x): unmapped internal write to %08x = %08x & %08x (PGCR)\n",tag(), m_pc & AM,(offset *4)+0x4000000,data,mem_mask); - } - - if (mem_mask & 0x0000ffff) - { - logerror("'%s' (%08x): unmapped internal write to %08x = %08x & %08x (PHCR)\n",tag(), m_pc & AM,(offset *4)+0x4000000,data,mem_mask); - } - } - break; - - - case PJCR_PKCR: - { - if (mem_mask & 0xffff0000) - { - logerror("'%s' (%08x): unmapped internal write to %08x = %08x & %08x (PJCR)\n",tag(), m_pc & AM,(offset *4)+0x4000000,data,mem_mask); - } - - if (mem_mask & 0x0000ffff) - { - logerror("'%s' (%08x): unmapped internal write to %08x = %08x & %08x (PKCR)\n",tag(), m_pc & AM,(offset *4)+0x4000000,data,mem_mask); - } - } - break; - - - case PLCR_SCPCR: - { - if (mem_mask & 0xffff0000) - { - logerror("'%s' (%08x): unmapped internal write to %08x = %08x & %08x (PLCR)\n",tag(), m_pc & AM,(offset *4)+0x4000000,data,mem_mask); - } - - if (mem_mask & 0x0000ffff) - { - logerror("'%s' (%08x): unmapped internal write to %08x = %08x & %08x (SCPCR)\n",tag(), m_pc & AM,(offset *4)+0x4000000,data,mem_mask); - } - } - break; - - case PADR_PBDR: - { - if (mem_mask & 0xffff0000) - { - m_io->write_qword(SH3_PORT_A, (data>>24)&0xff); - // logerror("'%s' (%08x): unmapped internal write to %08x = %08x & %08x (PADR)\n",tag(), m_pc & AM,(offset *4)+0x4000000,data,mem_mask); - } - - if (mem_mask & 0x0000ffff) - { - m_io->write_qword(SH3_PORT_B, (data>>8)&0xff); - // logerror("'%s' (%08x): unmapped internal write to %08x = %08x & %08x (PBDR)\n",tag(), m_pc & AM,(offset *4)+0x4000000,data,mem_mask); - } - } - break; - - case PCDR_PDDR: - { - if (mem_mask & 0xffff0000) - { - m_io->write_qword(SH3_PORT_C, (data>>24)&0xff); - // logerror("'%s' (%08x): unmapped internal write to %08x = %08x & %08x (PADR)\n",tag(), m_pc & AM,(offset *4)+0x4000000,data,mem_mask); - } - - if (mem_mask & 0x0000ffff) - { - m_io->write_qword(SH3_PORT_D, (data>>8)&0xff); - // logerror("'%s' (%08x): unmapped internal write to %08x = %08x & %08x (PBDR)\n",tag(), m_pc & AM,(offset *4)+0x4000000,data,mem_mask); - } - } - break; - case PEDR_PFDR: - { - if (mem_mask & 0xffff0000) - { - m_io->write_qword(SH3_PORT_E, (data>>24)&0xff); - // logerror("'%s' (%08x): unmapped internal write to %08x = %08x & %08x (PEDR)\n",tag(), m_pc & AM,(offset *4)+0x4000000,data,mem_mask); - } - - if (mem_mask & 0x0000ffff) - { - m_io->write_qword(SH3_PORT_F, (data>>8)&0xff); - // logerror("'%s' (%08x): unmapped internal write to %08x = %08x & %08x (PFDR)\n",tag(), m_pc & AM,(offset *4)+0x4000000,data,mem_mask); - } - } - break; - - case PGDR_PHDR: - { - if (mem_mask & 0xffff0000) - { - m_io->write_qword(SH3_PORT_G, (data>>24)&0xff); - // logerror("'%s' (%08x): unmapped internal write to %08x = %08x & %08x (PGDR)\n",tag(), m_pc & AM,(offset *4)+0x4000000,data,mem_mask); - } - - if (mem_mask & 0x0000ffff) - { - m_io->write_qword(SH3_PORT_H, (data>>8)&0xff); - // logerror("'%s' (%08x): unmapped internal write to %08x = %08x & %08x (PHDR)\n",tag(), m_pc & AM,(offset *4)+0x4000000,data,mem_mask); - } - } - break; - - - case PJDR_PKDR: - { - if (mem_mask & 0xffff0000) - { - m_io->write_qword(SH3_PORT_J, (data>>24)&0xff); - // logerror("'%s' (%08x): unmapped internal write to %08x = %08x & %08x (PJDR)\n",tag(), m_pc & AM,(offset *4)+0x4000000,data,mem_mask); - } - - if (mem_mask & 0x0000ffff) - { - m_io->write_qword(SH3_PORT_K, (data>>8)&0xff); - //logerror("'%s' (%08x): unmapped internal write to %08x = %08x & %08x (PKDR)\n",tag(), m_pc & AM,(offset *4)+0x4000000,data,mem_mask); - } - } - break; - - case SCSMR2_SCBRR2: - { - if (mem_mask & 0xff000000) - { - logerror("'%s' (%08x): SCIF internal write to %08x = %08x & %08x (SCSMR2 - Serial Mode Register 2)\n",tag(), m_pc & AM,(offset *4)+0x4000000,data,mem_mask); - } - - if (mem_mask & 0x0000ff00) - { - logerror("'%s' (%08x): SCIF internal write to %08x = %08x & %08x (SCBRR2 - Bit Rate Register 2)\n",tag(), m_pc & AM,(offset *4)+0x4000000,data,mem_mask); - } - } - break; - - case SCSCR2_SCFTDR2: - { - if (mem_mask & 0xff000000) - { - logerror("'%s' (%08x): SCIF internal write to %08x = %08x & %08x (SCSCR2 - Serial Control Register 2)\n",tag(), m_pc & AM,(offset *4)+0x4000000,data,mem_mask); - } - - if (mem_mask & 0x0000ff00) - { - logerror("'%s' (%08x): SCIF internal write to %08x = %08x & %08x (SCFTDR2 - Transmit FIFO Data Register 2)\n",tag(), m_pc & AM,(offset *4)+0x4000000,data,mem_mask); - } - } - break; - - case SCSSR2_SCFRDR2: - { - if (mem_mask & 0xffff0000) - { - logerror("'%s' (%08x): SCIF internal write to %08x = %08x & %08x (SCSSR2 - Serial Status Register 2)\n",tag(), m_pc & AM,(offset *4)+0x4000000,data,mem_mask); - } - - if (mem_mask & 0x0000ff00) - { - logerror("'%s' (%08x): SCIF internal write to %08x = %08x & %08x (SCFRDR2 - Receive FIFO Data Register 2)\n",tag(), m_pc & AM,(offset *4)+0x4000000,data,mem_mask); - } - } - break; - - case SCFCR2_SCFDR2: - { - if (mem_mask & 0xff000000) - { - logerror("'%s' (%08x): SCIF internal write to %08x = %08x & %08x (SCFCR2 - Fifo Control Register 2)\n",tag(), m_pc & AM,(offset *4)+0x4000000,data,mem_mask); - } - - if (mem_mask & 0x0000ffff) - { - logerror("'%s' (%08x): SCIF internal write to %08x = %08x & %08x (SCFDR2 - Fifo Data Count Register 2)\n",tag(), m_pc & AM,(offset *4)+0x4000000,data,mem_mask); - } - } - break; - - default: - { - logerror("'%s' (%08x): unmapped internal write to %08x = %08x & %08x\n", - tag(), m_pc & AM, - (offset *4)+0x4000000, - data, - mem_mask); - } - break; - } - - } - else - { - logerror("'%s' (%08x): unmapped internal write to %08x = %08x & %08x\n", - tag(), m_pc & AM, - (offset *4)+0x4000000, - data, - mem_mask); - } - -} diff --git a/src/devices/cpu/superh/sh3comn.h b/src/devices/cpu/superh/sh3comn.h deleted file mode 100644 index 241035b993e..00000000000 --- a/src/devices/cpu/superh/sh3comn.h +++ /dev/null @@ -1,96 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:R. Belmont -#pragma once - -#ifndef __SH3COMN_H__ -#define __SH3COMN_H__ - - -// actual port handling is more complex than this -// which should be considered a temporary solution -// just used some arbitrary port numbers -#define SH3_PORT_A (0x10*8) -#define SH3_PORT_B (0x11*8) -#define SH3_PORT_C (0x12*8) -#define SH3_PORT_D (0x13*8) -#define SH3_PORT_E (0x14*8) -#define SH3_PORT_F (0x15*8) -#define SH3_PORT_G (0x16*8) -#define SH3_PORT_H (0x17*8) -/* no I */ -#define SH3_PORT_J (0x18*8) -#define SH3_PORT_K (0x19*8) -#define SH3_PORT_L (0x1a*8) - -/* SH3 lower area regs */ - -#define SH3_LOWER_REGBASE (0x04000000) -#define SH3_LOWER_REGEND (0x07ffffff) - -#define INTEVT2 ((0x4000000 - SH3_LOWER_REGBASE)/4) -#define IRR0_IRR1 ((0x4000004 - SH3_LOWER_REGBASE)/4) -#define PINTER_IPRC ((0x4000014 - SH3_LOWER_REGBASE)/4) - -#define SH3_SAR0_ADDR ((0x4000020 - SH3_LOWER_REGBASE)/4) -#define SH3_DAR0_ADDR ((0x4000024 - SH3_LOWER_REGBASE)/4) -#define SH3_DMATCR0_ADDR ((0x4000028 - SH3_LOWER_REGBASE)/4) -#define SH3_CHCR0_ADDR ((0x400002c - SH3_LOWER_REGBASE)/4) -#define SH3_SAR1_ADDR ((0x4000030 - SH3_LOWER_REGBASE)/4) -#define SH3_DAR1_ADDR ((0x4000034 - SH3_LOWER_REGBASE)/4) -#define SH3_DMATCR1_ADDR ((0x4000038 - SH3_LOWER_REGBASE)/4) -#define SH3_CHCR1_ADDR ((0x400003c - SH3_LOWER_REGBASE)/4) -#define SH3_SAR2_ADDR ((0x4000040 - SH3_LOWER_REGBASE)/4) -#define SH3_DAR2_ADDR ((0x4000044 - SH3_LOWER_REGBASE)/4) -#define SH3_DMATCR2_ADDR ((0x4000048 - SH3_LOWER_REGBASE)/4) -#define SH3_CHCR2_ADDR ((0x400004c - SH3_LOWER_REGBASE)/4) -#define SH3_SAR3_ADDR ((0x4000050 - SH3_LOWER_REGBASE)/4) -#define SH3_DAR3_ADDR ((0x4000054 - SH3_LOWER_REGBASE)/4) -#define SH3_DMATCR3_ADDR ((0x4000058 - SH3_LOWER_REGBASE)/4) -#define SH3_CHCR3_ADDR ((0x400005c - SH3_LOWER_REGBASE)/4) -#define SH3_DMAOR_ADDR ((0x4000060 - SH3_LOWER_REGBASE)/4) - - -#define PCCR_PDCR ((0x4000104 - SH3_LOWER_REGBASE)/4) -#define PECR_PFCR ((0x4000108 - SH3_LOWER_REGBASE)/4) -#define PGCR_PHCR ((0x400010c - SH3_LOWER_REGBASE)/4) -#define PJCR_PKCR ((0x4000110 - SH3_LOWER_REGBASE)/4) -#define PLCR_SCPCR ((0x4000114 - SH3_LOWER_REGBASE)/4) - -#define PADR_PBDR ((0x4000120 - SH3_LOWER_REGBASE)/4) -#define PCDR_PDDR ((0x4000124 - SH3_LOWER_REGBASE)/4) -#define PEDR_PFDR ((0x4000128 - SH3_LOWER_REGBASE)/4) -#define PGDR_PHDR ((0x400012c - SH3_LOWER_REGBASE)/4) -#define PJDR_PKDR ((0x4000130 - SH3_LOWER_REGBASE)/4) -#define PLDR_SCPDR ((0x4000134 - SH3_LOWER_REGBASE)/4) - -#define SCSMR2_SCBRR2 ((0x4000150 - SH3_LOWER_REGBASE)/4) -#define SCSCR2_SCFTDR2 ((0x4000154 - SH3_LOWER_REGBASE)/4) -#define SCSSR2_SCFRDR2 ((0x4000158 - SH3_LOWER_REGBASE)/4) -#define SCFCR2_SCFDR2 ((0x400015c - SH3_LOWER_REGBASE)/4) - - -/* SH3 upper area */ - - -#define SH3_UPPER_REGBASE (0xffffd000) -#define SH3_UPPER_REGEND (0xffffffff) - -#define SH3_ICR0_IPRA_ADDR ((0xfffffee0 - SH3_UPPER_REGBASE)/4) -#define SH3_IPRB_ADDR ((0xfffffee4 - SH3_UPPER_REGBASE)/4) - -#define SH3_TOCR_TSTR_ADDR ((0xfffffe90 - SH3_UPPER_REGBASE)/4) -#define SH3_TCOR0_ADDR ((0xfffffe94 - SH3_UPPER_REGBASE)/4) -#define SH3_TCNT0_ADDR ((0xfffffe98 - SH3_UPPER_REGBASE)/4) -#define SH3_TCR0_ADDR ((0xfffffe9c - SH3_UPPER_REGBASE)/4) -#define SH3_TCOR1_ADDR ((0xfffffea0 - SH3_UPPER_REGBASE)/4) -#define SH3_TCNT1_ADDR ((0xfffffea4 - SH3_UPPER_REGBASE)/4) -#define SH3_TCR1_ADDR ((0xfffffea8 - SH3_UPPER_REGBASE)/4) -#define SH3_TCOR2_ADDR ((0xfffffeac - SH3_UPPER_REGBASE)/4) -#define SH3_TCNT2_ADDR ((0xfffffeb0 - SH3_UPPER_REGBASE)/4) -#define SH3_TCR2_ADDR ((0xfffffeb4 - SH3_UPPER_REGBASE)/4) -#define SH3_TCPR2_ADDR ((0xfffffeb8 - SH3_UPPER_REGBASE)/4) -#define SH3_TRA_ADDR ((0xffffffd0 - SH3_UPPER_REGBASE)/4) -#define SH3_EXPEVT_ADDR ((0xffffffd4 - SH3_UPPER_REGBASE)/4) -#define SH3_INTEVT_ADDR ((0xffffffd8 - SH3_UPPER_REGBASE)/4) - -#endif /* __SH3COMN_H__ */ diff --git a/src/devices/cpu/superh/sh4.cpp b/src/devices/cpu/superh/sh4.cpp deleted file mode 100644 index cc7c333d9cc..00000000000 --- a/src/devices/cpu/superh/sh4.cpp +++ /dev/null @@ -1,4743 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:R. Belmont -/***************************************************************************** - * - * sh4.c - * Portable Hitachi SH-4 (SH7750 family) emulator - * - * By R. Belmont, based on sh2.c by Juergen Buchmueller, Mariusz Wojcieszek, - * Olivier Galibert, Sylvain Glaize, and James Forshaw. - * - * - * TODO: FPU - * DMA - * on-board peripherals - * - * DONE: boot/reset setup - * 64-bit data bus - * banked registers - * additional registers for supervisor mode - * FPU status and data registers - * state save for the new registers - * interrupts - * store queues - * - *****************************************************************************/ - -#include "emu.h" -#include "sh4.h" -#include "sh4regs.h" -#include "sh4comn.h" -#include "sh3comn.h" -#include "sh4tmu.h" - -#include "debugger.h" - - -#if SH4_USE_FASTRAM_OPTIMIZATION -void sh34_base_device::add_fastram(offs_t start, offs_t end, uint8_t readonly, void *base) -{ - if (m_fastram_select < ARRAY_LENGTH(m_fastram)) - { - m_fastram[m_fastram_select].start = start; - m_fastram[m_fastram_select].end = end; - m_fastram[m_fastram_select].readonly = readonly; - m_fastram[m_fastram_select].base = base; - m_fastram_select++; - } -} -#else -void sh34_base_device::add_fastram(offs_t start, offs_t end, uint8_t readonly, void *base) -{ -} -#endif - - -CPU_DISASSEMBLE( sh4 ); -CPU_DISASSEMBLE( sh4be ); - - -DEFINE_DEVICE_TYPE(SH3LE, sh3_device, "sh3le", "SH-3 (little)") -DEFINE_DEVICE_TYPE(SH3BE, sh3be_device, "sh3be", "SH-3 (big)") -DEFINE_DEVICE_TYPE(SH4LE, sh4_device, "sh4le", "SH-4 (little)") -DEFINE_DEVICE_TYPE(SH4BE, sh4be_device, "sh4be", "SH-4 (big)") - - -#if 0 -/*When OC index mode is off (CCR.OIX = 0)*/ -static ADDRESS_MAP_START( sh4_internal_map, AS_PROGRAM, 64, sh4_base_device ) - AM_RANGE(0x1C000000, 0x1C000FFF) AM_RAM AM_MIRROR(0x03FFD000) - AM_RANGE(0x1C002000, 0x1C002FFF) AM_RAM AM_MIRROR(0x03FFD000) - AM_RANGE(0xE0000000, 0xE000003F) AM_RAM AM_MIRROR(0x03FFFFC0) -ADDRESS_MAP_END -#endif - -/*When OC index mode is on (CCR.OIX = 1)*/ -static ADDRESS_MAP_START( sh4_internal_map, AS_PROGRAM, 64, sh4_base_device ) - AM_RANGE(0x1C000000, 0x1C000FFF) AM_RAM AM_MIRROR(0x01FFF000) - AM_RANGE(0x1E000000, 0x1E000FFF) AM_RAM AM_MIRROR(0x01FFF000) - AM_RANGE(0xE0000000, 0xE000003F) AM_RAM AM_MIRROR(0x03FFFFC0) // todo: store queues should be write only on DC's SH4, executing PREFM shouldn't cause an actual memory read access! - - AM_RANGE(0xF6000000, 0xF6FFFFFF) AM_READWRITE(sh4_utlb_address_array_r,sh4_utlb_address_array_w) - AM_RANGE(0xF7000000, 0xF77FFFFF) AM_READWRITE(sh4_utlb_data_array1_r,sh4_utlb_data_array1_w) - AM_RANGE(0xF7800000, 0xF7FFFFFF) AM_READWRITE(sh4_utlb_data_array2_r,sh4_utlb_data_array2_w) - - AM_RANGE(0xFE000000, 0xFFFFFFFF) AM_READWRITE32(sh4_internal_r, sh4_internal_w, 0xffffffffffffffffU) -ADDRESS_MAP_END - -static ADDRESS_MAP_START( sh3_internal_map, AS_PROGRAM, 64, sh3_base_device ) - AM_RANGE(SH3_LOWER_REGBASE, SH3_LOWER_REGEND) AM_READWRITE32(sh3_internal_r, sh3_internal_w, 0xffffffffffffffffU) - AM_RANGE(SH3_UPPER_REGBASE, SH3_UPPER_REGEND) AM_READWRITE32(sh3_internal_high_r, sh3_internal_high_w, 0xffffffffffffffffU) -ADDRESS_MAP_END - - -sh34_base_device::sh34_base_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, endianness_t endianness, address_map_constructor internal) - : cpu_device(mconfig, type, tag, owner, clock) - , m_program_config("program", endianness, 64, 32, 0, internal) - , m_io_config("io", endianness, 64, 8) - , c_md2(0) - , c_md1(0) - , c_md0(0) - , c_md6(0) - , c_md4(0) - , c_md3(0) - , c_md5(0) - , c_md7(0) - , c_md8(0) - , c_clock(0) - , m_mmuhack(1) -#if SH4_USE_FASTRAM_OPTIMIZATION - , m_bigendian(endianness == ENDIANNESS_BIG) - , m_byte_xor(m_bigendian ? BYTE8_XOR_BE(0) : BYTE8_XOR_LE(0)) - , m_word_xor(m_bigendian ? WORD2_XOR_BE(0) : WORD2_XOR_LE(0)) - , m_dword_xor(m_bigendian ? DWORD_XOR_BE(0) : DWORD_XOR_LE(0)) - , m_fastram_select(0) -#endif -{ -#if SH4_USE_FASTRAM_OPTIMIZATION - memset(m_fastram, 0, sizeof(m_fastram)); -#endif -} - -device_memory_interface::space_config_vector sh34_base_device::memory_space_config() const -{ - return space_config_vector { - std::make_pair(AS_PROGRAM, &m_program_config), - std::make_pair(AS_IO, &m_io_config) - }; -} - - -sh3_base_device::sh3_base_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, endianness_t endianness) - : sh34_base_device(mconfig, type, tag, owner, clock, endianness, ADDRESS_MAP_NAME(sh3_internal_map)) -{ - m_cpu_type = CPU_TYPE_SH3; -} - - -sh4_base_device::sh4_base_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, endianness_t endianness) - : sh34_base_device(mconfig, type, tag, owner, clock, endianness, ADDRESS_MAP_NAME(sh4_internal_map)) -{ - m_cpu_type = CPU_TYPE_SH4; -} - - -sh3_device::sh3_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : sh3_base_device(mconfig, SH3LE, tag, owner, clock, ENDIANNESS_LITTLE) -{ -} - - -sh3be_device::sh3be_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : sh3_base_device(mconfig, SH3BE, tag, owner, clock, ENDIANNESS_BIG) -{ -} - - -sh4_device::sh4_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : sh4_base_device(mconfig, SH4LE, tag, owner, clock, ENDIANNESS_LITTLE) -{ -} - - -sh4be_device::sh4be_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : sh4_base_device(mconfig, SH4BE, tag, owner, clock, ENDIANNESS_BIG) -{ -} - - -offs_t sh34_base_device::disasm_disassemble(std::ostream &stream, offs_t pc, const uint8_t *oprom, const uint8_t *opram, uint32_t options) -{ - extern CPU_DISASSEMBLE( sh4 ); - - return CPU_DISASSEMBLE_NAME(sh4)(this, stream, pc, oprom, opram, options); -} - - -offs_t sh3be_device::disasm_disassemble(std::ostream &stream, offs_t pc, const uint8_t *oprom, const uint8_t *opram, uint32_t options) -{ - extern CPU_DISASSEMBLE( sh4be ); - - return CPU_DISASSEMBLE_NAME(sh4be)(this, stream, pc, oprom, opram, options); -} - - -offs_t sh4be_device::disasm_disassemble(std::ostream &stream, offs_t pc, const uint8_t *oprom, const uint8_t *opram, uint32_t options) -{ - extern CPU_DISASSEMBLE( sh4be ); - - return CPU_DISASSEMBLE_NAME(sh4be)(this, stream, pc, oprom, opram, options); -} - - -/* Called for unimplemented opcodes */ -void sh34_base_device::TODO(const uint16_t opcode) -{ -} - -void sh34_base_device::LDTLB(const uint16_t opcode) -{ - logerror("unhandled LDTLB for this CPU type\n"); -} - -void sh4_base_device::LDTLB(const uint16_t opcode) -{ - int replace = (m_m[MMUCR] & 0x0000fc00) >> 10; - - logerror("using LDTLB to replace UTLB entry %02x\n", replace); - - // these come from PTEH - m_utlb[replace].VPN = (m_m[PTEH] & 0xfffffc00) >> 10; -// m_utlb[replace].D = (m_m[PTEH] & 0x00000200) >> 9; // from PTEL -// m_utlb[replace].V = (m_m[PTEH] & 0x00000100) >> 8; // from PTEL - m_utlb[replace].ASID = (m_m[PTEH] & 0x000000ff) >> 0; - // these come from PTEL - m_utlb[replace].PPN = (m_m[PTEL] & 0x1ffffc00) >> 10; - m_utlb[replace].V = (m_m[PTEL] & 0x00000100) >> 8; - m_utlb[replace].PSZ = (m_m[PTEL] & 0x00000080) >> 6; - m_utlb[replace].PSZ |=(m_m[PTEL] & 0x00000010) >> 4; - m_utlb[replace].PPR= (m_m[PTEL] & 0x00000060) >> 5; - m_utlb[replace].C = (m_m[PTEL] & 0x00000008) >> 3; - m_utlb[replace].D = (m_m[PTEL] & 0x00000004) >> 2; - m_utlb[replace].SH = (m_m[PTEL] & 0x00000002) >> 1; - m_utlb[replace].WT = (m_m[PTEL] & 0x00000001) >> 0; - // these come from PTEA - m_utlb[replace].TC = (m_m[PTEA] & 0x00000008) >> 3; - m_utlb[replace].SA = (m_m[PTEA] & 0x00000007) >> 0; -} - -#if 0 -int sign_of(int n) -{ - return(m_fr[n]>>31); -} - -void zero(int n,int sign) -{ -if (sign == 0) - m_fr[n] = 0x00000000; -else - m_fr[n] = 0x80000000; -if ((m_fpscr & PR) == 1) - m_fr[n+1] = 0x00000000; -} - -int data_type_of(int n) -{ -uint32_t abs; - - abs = m_fr[n] & 0x7fffffff; - if ((m_fpscr & PR) == 0) { /* Single-precision */ - if (abs < 0x00800000) { - if (((m_fpscr & DN) == 1) || (abs == 0x00000000)) { - if (sign_of(n) == 0) { - zero(n, 0); - return(SH4_FPU_PZERO); - } else { - zero(n, 1); - return(SH4_FPU_NZERO); - } - } else - return(SH4_FPU_DENORM); - } else - if (abs < 0x7f800000) - return(SH4_FPU_NORM); - else - if (abs == 0x7f800000) { - if (sign_of(n) == 0) - return(SH4_FPU_PINF); - else - return(SH4_FPU_NINF); - } else - if (abs < 0x7fc00000) - return(SH4_FPU_qNaN); - else - return(SH4_FPU_sNaN); - } else { /* Double-precision */ - if (abs < 0x00100000) { - if (((m_fpscr & DN) == 1) || ((abs == 0x00000000) && (m_fr[n+1] == 0x00000000))) { - if(sign_of(n) == 0) { - zero(n, 0); - return(SH4_FPU_PZERO); - } else { - zero(n, 1); - return(SH4_FPU_NZERO); - } - } else - return(SH4_FPU_DENORM); - } else - if (abs < 0x7ff00000) - return(SH4_FPU_NORM); - else - if ((abs == 0x7ff00000) && (m_fr[n+1] == 0x00000000)) { - if (sign_of(n) == 0) - return(SH4_FPU_PINF); - else - return(SH4_FPU_NINF); - } else - if (abs < 0x7ff80000) - return(SH4_FPU_qNaN); - else - return(SH4_FPU_sNaN); - } - return(SH4_FPU_NORM); -} -#endif - -inline uint8_t sh34_base_device::RB(offs_t A) -{ - if (A >= 0xe0000000) - return m_program->read_byte(A); - - if (A >= 0x80000000) // P1/P2/P3 region - { -#if SH4_USE_FASTRAM_OPTIMIZATION - const offs_t _A = A & AM; - for (int ramnum = 0; ramnum < m_fastram_select; ramnum++) - { - if (_A < m_fastram[ramnum].start || _A > m_fastram[ramnum].end) - { - continue; - } - uint8_t *fastbase = (uint8_t*)m_fastram[ramnum].base - m_fastram[ramnum].start; - return fastbase[_A ^ m_byte_xor]; - } - return m_program->read_byte(_A); -#else - return m_program->read_byte(A & AM); -#endif - } - else // P0 region - { - if (!m_sh4_mmu_enabled) - { - return m_program->read_byte(A & AM); - } - else - { - A = get_remap(A & AM); - return m_program->read_byte(A); - } - } - -} - -inline uint16_t sh34_base_device::RW(offs_t A) -{ - if (A >= 0xe0000000) - return m_program->read_word(A); - - if (A >= 0x80000000) // P1/P2/P3 region - { -#if SH4_USE_FASTRAM_OPTIMIZATION - const offs_t _A = A & AM; - for (int ramnum = 0; ramnum < m_fastram_select; ramnum++) - { - if (_A < m_fastram[ramnum].start || _A > m_fastram[ramnum].end) - { - continue; - } - uint8_t *fastbase = (uint8_t*)m_fastram[ramnum].base - m_fastram[ramnum].start; - return ((uint16_t*)fastbase)[(_A ^ m_word_xor) >> 1]; - } - return m_program->read_word(_A); -#else - return m_program->read_word(A & AM); -#endif - } - else - { - if (!m_sh4_mmu_enabled) - { - return m_program->read_word(A & AM); - } - else - { - A = get_remap(A & AM); - return m_program->read_word(A); - } - } - -} - -inline uint32_t sh34_base_device::RL(offs_t A) -{ - if (A >= 0xe0000000) - return m_program->read_dword(A); - - if (A >= 0x80000000) // P1/P2/P3 region - { -#if SH4_USE_FASTRAM_OPTIMIZATION - const offs_t _A = A & AM; - for (int ramnum = 0; ramnum < m_fastram_select; ramnum++) - { - if (_A < m_fastram[ramnum].start || _A > m_fastram[ramnum].end) - { - continue; - } - uint8_t *fastbase = (uint8_t*)m_fastram[ramnum].base - m_fastram[ramnum].start; - return ((uint32_t*)fastbase)[(_A^m_dword_xor) >> 2]; - } - return m_program->read_dword(_A); -#else - return m_program->read_dword(A & AM); -#endif - } - else - { - if (!m_sh4_mmu_enabled) - { - return m_program->read_dword(A & AM); - } - else - { - A = get_remap(A & AM); - return m_program->read_dword(A); - } - } - -} - -inline void sh34_base_device::WB(offs_t A, uint8_t V) -{ - if (A >= 0xe0000000) - { - m_program->write_byte(A,V); - return; - } - - if (A >= 0x80000000) // P1/P2/P3 region - { -#if SH4_USE_FASTRAM_OPTIMIZATION - const offs_t _A = A & AM; - for (int ramnum = 0; ramnum < m_fastram_select; ramnum++) - { - if (m_fastram[ramnum].readonly == true || _A < m_fastram[ramnum].start || _A > m_fastram[ramnum].end) - { - continue; - } - uint8_t *fastbase = (uint8_t*)m_fastram[ramnum].base - m_fastram[ramnum].start; - fastbase[_A ^ m_byte_xor] = V; - return; - } - m_program->write_byte(_A, V); -#else - m_program->write_byte(A & AM, V); -#endif - } - else - { - if (!m_sh4_mmu_enabled) - { - m_program->write_byte(A & AM, V); - } - else - { - A = get_remap(A & AM); - m_program->write_byte(A, V); - } - } - -} - -inline void sh34_base_device::WW(offs_t A, uint16_t V) -{ - if (A >= 0xe0000000) - { - m_program->write_word(A,V); - return; - } - - if (A >= 0x80000000) // P1/P2/P3 region - { -#if SH4_USE_FASTRAM_OPTIMIZATION - const offs_t _A = A & AM; - for (int ramnum = 0; ramnum < m_fastram_select; ramnum++) - { - if (m_fastram[ramnum].readonly == true || _A < m_fastram[ramnum].start || _A > m_fastram[ramnum].end) - { - continue; - } - void *fastbase = (uint8_t*)m_fastram[ramnum].base - m_fastram[ramnum].start; - ((uint16_t*)fastbase)[(_A ^ m_word_xor) >> 1] = V; - return; - } - m_program->write_word(_A, V); -#else - m_program->write_word(A & AM, V); -#endif - } - else - { - if (!m_sh4_mmu_enabled) - { - m_program->write_word(A & AM, V); - } - else - { - A = get_remap(A & AM); - m_program->write_word(A, V); - } - } - -} - -inline void sh34_base_device::WL(offs_t A, uint32_t V) -{ - if (A >= 0xe0000000) - { - m_program->write_dword(A,V); - return; - } - - if (A >= 0x80000000) // P1/P2/P3 region - { -#if SH4_USE_FASTRAM_OPTIMIZATION - const offs_t _A = A & AM; - for (int ramnum = 0; ramnum < m_fastram_select; ramnum++) - { - if (m_fastram[ramnum].readonly == true || _A < m_fastram[ramnum].start || _A > m_fastram[ramnum].end) - { - continue; - } - void *fastbase = (uint8_t*)m_fastram[ramnum].base - m_fastram[ramnum].start; - ((uint32_t*)fastbase)[(_A ^ m_dword_xor) >> 2] = V; - return; - } - m_program->write_dword(_A, V); -#else - m_program->write_dword(A & AM, V); -#endif - } - else - { - if (!m_sh4_mmu_enabled) - { - m_program->write_dword(A & AM, V); - } - else - { - A = get_remap(A & AM); - m_program->write_dword(A, V); - } - } - -} - -/* code cycles t-bit - * 0011 nnnn mmmm 1100 1 - - * ADD Rm,Rn - */ -inline void sh34_base_device::ADD(const uint16_t opcode) -{ - m_r[Rn] += m_r[Rm]; -} - -/* code cycles t-bit - * 0111 nnnn iiii iiii 1 - - * ADD #imm,Rn - */ -inline void sh34_base_device::ADDI(const uint16_t opcode) -{ - m_r[Rn] += (int32_t)(int16_t)(int8_t)(opcode&0xff); -} - -/* code cycles t-bit - * 0011 nnnn mmmm 1110 1 carry - * ADDC Rm,Rn - */ -inline void sh34_base_device::ADDC(const uint16_t opcode) -{ - uint32_t m = Rm; uint32_t n = Rn; - uint32_t tmp0, tmp1; - - tmp1 = m_r[n] + m_r[m]; - tmp0 = m_r[n]; - m_r[n] = tmp1 + (m_sr & T); - if (tmp0 > tmp1) - m_sr |= T; - else - m_sr &= ~T; - if (tmp1 > m_r[n]) - m_sr |= T; -} - -/* code cycles t-bit - * 0011 nnnn mmmm 1111 1 overflow - * ADDV Rm,Rn - */ -inline void sh34_base_device::ADDV(const uint16_t opcode) -{ - uint32_t m = Rm; uint32_t n = Rn; - int32_t dest, src, ans; - - if ((int32_t) m_r[n] >= 0) - dest = 0; - else - dest = 1; - if ((int32_t) m_r[m] >= 0) - src = 0; - else - src = 1; - src += dest; - m_r[n] += m_r[m]; - if ((int32_t) m_r[n] >= 0) - ans = 0; - else - ans = 1; - ans += dest; - if (src == 0 || src == 2) - { - if (ans == 1) - m_sr |= T; - else - m_sr &= ~T; - } - else - m_sr &= ~T; -} - -/* code cycles t-bit - * 0010 nnnn mmmm 1001 1 - - * AND Rm,Rn - */ -inline void sh34_base_device::AND(const uint16_t opcode) -{ - m_r[Rn] &= m_r[Rm]; -} - - -/* code cycles t-bit - * 1100 1001 iiii iiii 1 - - * AND #imm,R0 - */ -inline void sh34_base_device::ANDI(const uint16_t opcode) -{ - m_r[0] &= (opcode&0xff); -} - -/* code cycles t-bit - * 1100 1101 iiii iiii 1 - - * AND.B #imm,@(R0,GBR) - */ -inline void sh34_base_device::ANDM(const uint16_t opcode) -{ - uint32_t temp; - - m_ea = m_gbr + m_r[0]; - temp = (opcode&0xff) & RB( m_ea ); - WB(m_ea, temp ); - m_sh4_icount -= 2; -} - -/* code cycles t-bit - * 1000 1011 dddd dddd 3/1 - - * BF disp8 - */ -inline void sh34_base_device::BF(const uint16_t opcode) -{ - if ((m_sr & T) == 0) - { - int32_t disp = ((int32_t)(opcode&0xff) << 24) >> 24; - m_pc = m_ea = m_pc + disp * 2 + 2; - m_sh4_icount -= 2; - } -} - -/* code cycles t-bit - * 1000 1111 dddd dddd 3/1 - - * BFS disp8 - */ -inline void sh34_base_device::BFS(const uint16_t opcode) -{ - if ((m_sr & T) == 0) - { - int32_t disp = ((int32_t)(opcode&0xff) << 24) >> 24; - m_delay = m_ea = m_pc + disp * 2 + 2; - m_sh4_icount--; - } -} - -/* code cycles t-bit - * 1010 dddd dddd dddd 2 - - * BRA disp12 - */ -inline void sh34_base_device::BRA(const uint16_t opcode) -{ - int32_t disp = ((int32_t)(opcode&0xfff) << 20) >> 20; - -#if BUSY_LOOP_HACKS - if (disp == -2) - { - uint32_t next_opcode = RW(m_pc & AM); - /* BRA $ - * NOP - */ - if (next_opcode == 0x0009) - m_sh4_icount %= 3; /* cycles for BRA $ and NOP taken (3) */ - } -#endif - m_delay = m_ea = m_pc + disp * 2 + 2; - m_sh4_icount--; -} - -/* code cycles t-bit - * 0000 mmmm 0010 0011 2 - - * BRAF Rm - */ -inline void sh34_base_device::BRAF(const uint16_t opcode) -{ - m_delay = m_pc + m_r[Rn] + 2; - m_sh4_icount--; -} - -/* code cycles t-bit - * 1011 dddd dddd dddd 2 - - * BSR disp12 - */ -inline void sh34_base_device::BSR(const uint16_t opcode) -{ - int32_t disp = ((int32_t)(opcode&0xfff) << 20) >> 20; - - m_pr = m_pc + 2; - m_delay = m_ea = m_pc + disp * 2 + 2; - m_sh4_icount--; -} - -/* code cycles t-bit - * 0000 mmmm 0000 0011 2 - - * BSRF Rm - */ -inline void sh34_base_device::BSRF(const uint16_t opcode) -{ - m_pr = m_pc + 2; - m_delay = m_pc + m_r[Rn] + 2; - m_sh4_icount--; -} - -/* code cycles t-bit - * 1000 1001 dddd dddd 3/1 - - * BT disp8 - */ -inline void sh34_base_device::BT(const uint16_t opcode) -{ - if ((m_sr & T) != 0) - { - int32_t disp = ((int32_t)(opcode&0xff) << 24) >> 24; - m_pc = m_ea = m_pc + disp * 2 + 2; - m_sh4_icount -= 2; - } -} - -/* code cycles t-bit - * 1000 1101 dddd dddd 2/1 - - * BTS disp8 - */ -inline void sh34_base_device::BTS(const uint16_t opcode) -{ - if ((m_sr & T) != 0) - { - int32_t disp = ((int32_t)(opcode&0xff) << 24) >> 24; - m_delay = m_ea = m_pc + disp * 2 + 2; - m_sh4_icount--; - } -} - -/* code cycles t-bit - * 0000 0000 0010 1000 1 - - * CLRMAC - */ -inline void sh34_base_device::CLRMAC(const uint16_t opcode) -{ - m_mach = 0; - m_macl = 0; -} - -/* code cycles t-bit - * 0000 0000 0000 1000 1 - - * CLRT - */ -inline void sh34_base_device::CLRT(const uint16_t opcode) -{ - m_sr &= ~T; -} - -/* code cycles t-bit - * 0011 nnnn mmmm 0000 1 comparison result - * CMP_EQ Rm,Rn - */ -inline void sh34_base_device::CMPEQ(const uint16_t opcode) -{ - if (m_r[Rn] == m_r[Rm]) - m_sr |= T; - else - m_sr &= ~T; -} - -/* code cycles t-bit - * 0011 nnnn mmmm 0011 1 comparison result - * CMP_GE Rm,Rn - */ -inline void sh34_base_device::CMPGE(const uint16_t opcode) -{ - if ((int32_t) m_r[Rn] >= (int32_t) m_r[Rm]) - m_sr |= T; - else - m_sr &= ~T; -} - -/* code cycles t-bit - * 0011 nnnn mmmm 0111 1 comparison result - * CMP_GT Rm,Rn - */ -inline void sh34_base_device::CMPGT(const uint16_t opcode) -{ - if ((int32_t) m_r[Rn] > (int32_t) m_r[Rm]) - m_sr |= T; - else - m_sr &= ~T; -} - -/* code cycles t-bit - * 0011 nnnn mmmm 0110 1 comparison result - * CMP_HI Rm,Rn - */ -inline void sh34_base_device::CMPHI(const uint16_t opcode) -{ - if ((uint32_t) m_r[Rn] > (uint32_t) m_r[Rm]) - m_sr |= T; - else - m_sr &= ~T; -} - -/* code cycles t-bit - * 0011 nnnn mmmm 0010 1 comparison result - * CMP_HS Rm,Rn - */ -inline void sh34_base_device::CMPHS(const uint16_t opcode) -{ - if ((uint32_t) m_r[Rn] >= (uint32_t) m_r[Rm]) - m_sr |= T; - else - m_sr &= ~T; -} - - -/* code cycles t-bit - * 0100 nnnn 0001 0101 1 comparison result - * CMP_PL Rn - */ -inline void sh34_base_device::CMPPL(const uint16_t opcode) -{ - if ((int32_t) m_r[Rn] > 0) - m_sr |= T; - else - m_sr &= ~T; -} - -/* code cycles t-bit - * 0100 nnnn 0001 0001 1 comparison result - * CMP_PZ Rn - */ -inline void sh34_base_device::CMPPZ(const uint16_t opcode) -{ - if ((int32_t) m_r[Rn] >= 0) - m_sr |= T; - else - m_sr &= ~T; -} - -/* code cycles t-bit - * 0010 nnnn mmmm 1100 1 comparison result - * CMP_STR Rm,Rn - */ -inline void sh34_base_device::CMPSTR(const uint16_t opcode) -{ - uint32_t temp; - int32_t HH, HL, LH, LL; - temp = m_r[Rn] ^ m_r[Rm]; - HH = (temp >> 24) & 0xff; - HL = (temp >> 16) & 0xff; - LH = (temp >> 8) & 0xff; - LL = temp & 0xff; - if (HH && HL && LH && LL) - m_sr &= ~T; - else - m_sr |= T; - } - - -/* code cycles t-bit - * 1000 1000 iiii iiii 1 comparison result - * CMP/EQ #imm,R0 - */ -inline void sh34_base_device::CMPIM(const uint16_t opcode) -{ - uint32_t imm = (uint32_t)(int32_t)(int16_t)(int8_t)(opcode&0xff); - - if (m_r[0] == imm) - m_sr |= T; - else - m_sr &= ~T; -} - -/* code cycles t-bit - * 0010 nnnn mmmm 0111 1 calculation result - * DIV0S Rm,Rn - */ -inline void sh34_base_device::DIV0S(const uint16_t opcode) -{ - uint32_t m = Rm; uint32_t n = Rn; - - if ((m_r[n] & 0x80000000) == 0) - m_sr &= ~Q; - else - m_sr |= Q; - if ((m_r[m] & 0x80000000) == 0) - m_sr &= ~M; - else - m_sr |= M; - if ((m_r[m] ^ m_r[n]) & 0x80000000) - m_sr |= T; - else - m_sr &= ~T; -} - -/* code cycles t-bit - * 0000 0000 0001 1001 1 0 - * DIV0U - */ -inline void sh34_base_device::DIV0U(const uint16_t opcode) -{ - m_sr &= ~(M | Q | T); -} - -/* code cycles t-bit - * 0011 nnnn mmmm 0100 1 calculation result - * DIV1 Rm,Rn - */ -inline void sh34_base_device::DIV1(const uint16_t opcode) -{ - uint32_t m = Rm; uint32_t n = Rn; - - uint32_t tmp0; - uint32_t old_q; - - old_q = m_sr & Q; - if (0x80000000 & m_r[n]) - m_sr |= Q; - else - m_sr &= ~Q; - - m_r[n] = (m_r[n] << 1) | (m_sr & T); - - if (!old_q) - { - if (!(m_sr & M)) - { - tmp0 = m_r[n]; - m_r[n] -= m_r[m]; - if(!(m_sr & Q)) - if(m_r[n] > tmp0) - m_sr |= Q; - else - m_sr &= ~Q; - else - if(m_r[n] > tmp0) - m_sr &= ~Q; - else - m_sr |= Q; - } - else - { - tmp0 = m_r[n]; - m_r[n] += m_r[m]; - if(!(m_sr & Q)) - { - if(m_r[n] < tmp0) - m_sr &= ~Q; - else - m_sr |= Q; - } - else - { - if(m_r[n] < tmp0) - m_sr |= Q; - else - m_sr &= ~Q; - } - } - } - else - { - if (!(m_sr & M)) - { - tmp0 = m_r[n]; - m_r[n] += m_r[m]; - if(!(m_sr & Q)) - if(m_r[n] < tmp0) - m_sr |= Q; - else - m_sr &= ~Q; - else - if(m_r[n] < tmp0) - m_sr &= ~Q; - else - m_sr |= Q; - } - else - { - tmp0 = m_r[n]; - m_r[n] -= m_r[m]; - if(!(m_sr & Q)) - if(m_r[n] > tmp0) - m_sr &= ~Q; - else - m_sr |= Q; - else - if(m_r[n] > tmp0) - m_sr |= Q; - else - m_sr &= ~Q; - } - } - - tmp0 = (m_sr & (Q | M)); - if((!tmp0) || (tmp0 == 0x300)) /* if Q == M set T else clear T */ - m_sr |= T; - else - m_sr &= ~T; -} - -/* DMULS.L Rm,Rn */ -inline void sh34_base_device::DMULS(const uint16_t opcode) -{ - uint32_t m = Rm; uint32_t n = Rn; - - uint32_t RnL, RnH, RmL, RmH, Res0, Res1, Res2; - uint32_t temp0, temp1, temp2, temp3; - int32_t tempm, tempn, fnLmL; - - tempn = (int32_t) m_r[n]; - tempm = (int32_t) m_r[m]; - if (tempn < 0) - tempn = 0 - tempn; - if (tempm < 0) - tempm = 0 - tempm; - if ((int32_t) (m_r[n] ^ m_r[m]) < 0) - fnLmL = -1; - else - fnLmL = 0; - temp1 = (uint32_t) tempn; - temp2 = (uint32_t) tempm; - RnL = temp1 & 0x0000ffff; - RnH = (temp1 >> 16) & 0x0000ffff; - RmL = temp2 & 0x0000ffff; - RmH = (temp2 >> 16) & 0x0000ffff; - temp0 = RmL * RnL; - temp1 = RmH * RnL; - temp2 = RmL * RnH; - temp3 = RmH * RnH; - Res2 = 0; - Res1 = temp1 + temp2; - if (Res1 < temp1) - Res2 += 0x00010000; - temp1 = (Res1 << 16) & 0xffff0000; - Res0 = temp0 + temp1; - if (Res0 < temp0) - Res2++; - Res2 = Res2 + ((Res1 >> 16) & 0x0000ffff) + temp3; - if (fnLmL < 0) - { - Res2 = ~Res2; - if (Res0 == 0) - Res2++; - else - Res0 = (~Res0) + 1; - } - m_mach = Res2; - m_macl = Res0; - m_sh4_icount--; -} - -/* DMULU.L Rm,Rn */ -inline void sh34_base_device::DMULU(const uint16_t opcode) -{ - uint32_t m = Rm; uint32_t n = Rn; - - uint32_t RnL, RnH, RmL, RmH, Res0, Res1, Res2; - uint32_t temp0, temp1, temp2, temp3; - - RnL = m_r[n] & 0x0000ffff; - RnH = (m_r[n] >> 16) & 0x0000ffff; - RmL = m_r[m] & 0x0000ffff; - RmH = (m_r[m] >> 16) & 0x0000ffff; - temp0 = RmL * RnL; - temp1 = RmH * RnL; - temp2 = RmL * RnH; - temp3 = RmH * RnH; - Res2 = 0; - Res1 = temp1 + temp2; - if (Res1 < temp1) - Res2 += 0x00010000; - temp1 = (Res1 << 16) & 0xffff0000; - Res0 = temp0 + temp1; - if (Res0 < temp0) - Res2++; - Res2 = Res2 + ((Res1 >> 16) & 0x0000ffff) + temp3; - m_mach = Res2; - m_macl = Res0; - m_sh4_icount--; -} - -/* DT Rn */ -inline void sh34_base_device::DT(const uint16_t opcode) -{ - uint32_t n = Rn; - - m_r[n]--; - if (m_r[n] == 0) - m_sr |= T; - else - m_sr &= ~T; -#if BUSY_LOOP_HACKS - { - uint32_t next_opcode = RW(m_pc & AM); - /* DT Rn - * BF $-2 - */ - if (next_opcode == 0x8bfd) - { - while (m_r[n] > 1 && m_sh4_icount > 4) - { - m_r[n]--; - m_sh4_icount -= 4; /* cycles for DT (1) and BF taken (3) */ - } - } - } -#endif -} - -/* EXTS.B Rm,Rn */ -inline void sh34_base_device::EXTSB(const uint16_t opcode) -{ - m_r[Rn] = ((int32_t)m_r[Rm] << 24) >> 24; -} - -/* EXTS.W Rm,Rn */ -inline void sh34_base_device::EXTSW(const uint16_t opcode) -{ - m_r[Rn] = ((int32_t)m_r[Rm] << 16) >> 16; -} - -/* EXTU.B Rm,Rn */ -inline void sh34_base_device::EXTUB(const uint16_t opcode) -{ - m_r[Rn] = m_r[Rm] & 0x000000ff; -} - -/* EXTU.W Rm,Rn */ -inline void sh34_base_device::EXTUW(const uint16_t opcode) -{ - m_r[Rn] = m_r[Rm] & 0x0000ffff; -} - -/* JMP @Rm */ -inline void sh34_base_device::JMP(const uint16_t opcode) -{ - m_delay = m_ea = m_r[Rn]; -} - -/* JSR @Rm */ -inline void sh34_base_device::JSR(const uint16_t opcode) -{ - m_pr = m_pc + 2; - m_delay = m_ea = m_r[Rn]; - m_sh4_icount--; -} - - -/* LDC Rm,SR */ -inline void sh34_base_device::LDCSR(const uint16_t opcode) -{ - uint32_t reg; - - reg = m_r[Rn]; - if ((machine().debug_flags & DEBUG_FLAG_ENABLED) != 0) - sh4_syncronize_register_bank((m_sr & sRB) >> 29); - if ((m_r[Rn] & sRB) != (m_sr & sRB)) - sh4_change_register_bank(m_r[Rn] & sRB ? 1 : 0); - m_sr = reg & FLAGS; - sh4_exception_recompute(); -} - -/* LDC Rm,GBR */ -inline void sh34_base_device::LDCGBR(const uint16_t opcode) -{ - m_gbr = m_r[Rn]; -} - -/* LDC Rm,VBR */ -inline void sh34_base_device::LDCVBR(const uint16_t opcode) -{ - m_vbr = m_r[Rn]; -} - -/* LDC.L @Rm+,SR */ -inline void sh34_base_device::LDCMSR(const uint16_t opcode) -{ - uint32_t old; - - old = m_sr; - m_ea = m_r[Rn]; - m_sr = RL(m_ea ) & FLAGS; - if ((machine().debug_flags & DEBUG_FLAG_ENABLED) != 0) - sh4_syncronize_register_bank((old & sRB) >> 29); - if ((old & sRB) != (m_sr & sRB)) - sh4_change_register_bank(m_sr & sRB ? 1 : 0); - m_r[Rn] += 4; - m_sh4_icount -= 2; - sh4_exception_recompute(); -} - -/* LDC.L @Rm+,GBR */ -inline void sh34_base_device::LDCMGBR(const uint16_t opcode) -{ - m_ea = m_r[Rn]; - m_gbr = RL(m_ea ); - m_r[Rn] += 4; - m_sh4_icount -= 2; -} - -/* LDC.L @Rm+,VBR */ -inline void sh34_base_device::LDCMVBR(const uint16_t opcode) -{ - m_ea = m_r[Rn]; - m_vbr = RL(m_ea ); - m_r[Rn] += 4; - m_sh4_icount -= 2; -} - -/* LDS Rm,MACH */ -inline void sh34_base_device::LDSMACH(const uint16_t opcode) -{ - m_mach = m_r[Rn]; -} - -/* LDS Rm,MACL */ -inline void sh34_base_device::LDSMACL(const uint16_t opcode) -{ - m_macl = m_r[Rn]; -} - -/* LDS Rm,PR */ -inline void sh34_base_device::LDSPR(const uint16_t opcode) -{ - m_pr = m_r[Rn]; -} - -/* LDS.L @Rm+,MACH */ -inline void sh34_base_device::LDSMMACH(const uint16_t opcode) -{ - m_ea = m_r[Rn]; - m_mach = RL(m_ea ); - m_r[Rn] += 4; -} - -/* LDS.L @Rm+,MACL */ -inline void sh34_base_device::LDSMMACL(const uint16_t opcode) -{ - m_ea = m_r[Rn]; - m_macl = RL(m_ea ); - m_r[Rn] += 4; -} - -/* LDS.L @Rm+,PR */ -inline void sh34_base_device::LDSMPR(const uint16_t opcode) -{ - m_ea = m_r[Rn]; - m_pr = RL(m_ea ); - m_r[Rn] += 4; -} - -/* MAC.L @Rm+,@Rn+ */ -inline void sh34_base_device::MAC_L(const uint16_t opcode) -{ - uint32_t m = Rm; uint32_t n = Rn; - - uint32_t RnL, RnH, RmL, RmH, Res0, Res1, Res2; - uint32_t temp0, temp1, temp2, temp3; - int32_t tempm, tempn, fnLmL; - - tempn = (int32_t) RL(m_r[n] ); - m_r[n] += 4; - tempm = (int32_t) RL(m_r[m] ); - m_r[m] += 4; - if ((int32_t) (tempn ^ tempm) < 0) - fnLmL = -1; - else - fnLmL = 0; - if (tempn < 0) - tempn = 0 - tempn; - if (tempm < 0) - tempm = 0 - tempm; - temp1 = (uint32_t) tempn; - temp2 = (uint32_t) tempm; - RnL = temp1 & 0x0000ffff; - RnH = (temp1 >> 16) & 0x0000ffff; - RmL = temp2 & 0x0000ffff; - RmH = (temp2 >> 16) & 0x0000ffff; - temp0 = RmL * RnL; - temp1 = RmH * RnL; - temp2 = RmL * RnH; - temp3 = RmH * RnH; - Res2 = 0; - Res1 = temp1 + temp2; - if (Res1 < temp1) - Res2 += 0x00010000; - temp1 = (Res1 << 16) & 0xffff0000; - Res0 = temp0 + temp1; - if (Res0 < temp0) - Res2++; - Res2 = Res2 + ((Res1 >> 16) & 0x0000ffff) + temp3; - if (fnLmL < 0) - { - Res2 = ~Res2; - if (Res0 == 0) - Res2++; - else - Res0 = (~Res0) + 1; - } - if (m_sr & S) - { - Res0 = m_macl + Res0; - if (m_macl > Res0) - Res2++; - Res2 += (m_mach & 0x0000ffff); - if (((int32_t) Res2 < 0) && (Res2 < 0xffff8000)) - { - Res2 = 0x00008000; - Res0 = 0x00000000; - } - else if (((int32_t) Res2 > 0) && (Res2 > 0x00007fff)) - { - Res2 = 0x00007fff; - Res0 = 0xffffffff; - } - m_mach = Res2; - m_macl = Res0; - } - else - { - Res0 = m_macl + Res0; - if (m_macl > Res0) - Res2++; - Res2 += m_mach; - m_mach = Res2; - m_macl = Res0; - } - m_sh4_icount -= 2; -} - -/* MAC.W @Rm+,@Rn+ */ -inline void sh34_base_device::MAC_W(const uint16_t opcode) -{ - uint32_t m = Rm; uint32_t n = Rn; - - int32_t tempm, tempn, dest, src, ans; - uint32_t templ; - - tempn = (int32_t) RW(m_r[n] ); - m_r[n] += 2; - tempm = (int32_t) RW(m_r[m] ); - m_r[m] += 2; - templ = m_macl; - tempm = ((int32_t) (short) tempn * (int32_t) (short) tempm); - if ((int32_t) m_macl >= 0) - dest = 0; - else - dest = 1; - if ((int32_t) tempm >= 0) - { - src = 0; - tempn = 0; - } - else - { - src = 1; - tempn = 0xffffffff; - } - src += dest; - m_macl += tempm; - if ((int32_t) m_macl >= 0) - ans = 0; - else - ans = 1; - ans += dest; - if (m_sr & S) - { - if (ans == 1) - { - if (src == 0) - m_macl = 0x7fffffff; - if (src == 2) - m_macl = 0x80000000; - } - } - else - { - m_mach += tempn; - if (templ > m_macl) - m_mach += 1; - } - m_sh4_icount -= 2; -} - -/* MOV Rm,Rn */ -inline void sh34_base_device::MOV(const uint16_t opcode) -{ - m_r[Rn] = m_r[Rm]; -} - -/* MOV.B Rm,@Rn */ -inline void sh34_base_device::MOVBS(const uint16_t opcode) -{ - m_ea = m_r[Rn]; - WB(m_ea, m_r[Rm] & 0x000000ff); -} - -/* MOV.W Rm,@Rn */ -inline void sh34_base_device::MOVWS(const uint16_t opcode) -{ - m_ea = m_r[Rn]; - WW(m_ea, m_r[Rm] & 0x0000ffff); -} - -/* MOV.L Rm,@Rn */ -inline void sh34_base_device::MOVLS(const uint16_t opcode) -{ - m_ea = m_r[Rn]; - WL(m_ea, m_r[Rm] ); -} - -/* MOV.B @Rm,Rn */ -inline void sh34_base_device::MOVBL(const uint16_t opcode) -{ - m_ea = m_r[Rm]; - m_r[Rn] = (uint32_t)(int32_t)(int16_t)(int8_t) RB( m_ea ); -} - -/* MOV.W @Rm,Rn */ -inline void sh34_base_device::MOVWL(const uint16_t opcode) -{ - m_ea = m_r[Rm]; - m_r[Rn] = (uint32_t)(int32_t)(int16_t) RW(m_ea ); -} - -/* MOV.L @Rm,Rn */ -inline void sh34_base_device::MOVLL(const uint16_t opcode) -{ - m_ea = m_r[Rm]; - m_r[Rn] = RL(m_ea ); -} - -/* MOV.B Rm,@-Rn */ -inline void sh34_base_device::MOVBM(const uint16_t opcode) -{ - uint32_t data = m_r[Rm] & 0x000000ff; - - m_r[Rn] -= 1; - WB(m_r[Rn], data ); -} - -/* MOV.W Rm,@-Rn */ -inline void sh34_base_device::MOVWM(const uint16_t opcode) -{ - uint32_t data = m_r[Rm] & 0x0000ffff; - - m_r[Rn] -= 2; - WW(m_r[Rn], data ); -} - -/* MOV.L Rm,@-Rn */ -inline void sh34_base_device::MOVLM(const uint16_t opcode) -{ - uint32_t data = m_r[Rm]; - - m_r[Rn] -= 4; - WL(m_r[Rn], data ); -} - -/* MOV.B @Rm+,Rn */ -inline void sh34_base_device::MOVBP(const uint16_t opcode) -{ - uint32_t m = Rm; uint32_t n = Rn; - - m_r[n] = (uint32_t)(int32_t)(int16_t)(int8_t) RB( m_r[m] ); - if (n != m) - m_r[m] += 1; -} - -/* MOV.W @Rm+,Rn */ -inline void sh34_base_device::MOVWP(const uint16_t opcode) -{ - uint32_t m = Rm; uint32_t n = Rn; - - m_r[n] = (uint32_t)(int32_t)(int16_t) RW(m_r[m] ); - if (n != m) - m_r[m] += 2; -} - -/* MOV.L @Rm+,Rn */ -inline void sh34_base_device::MOVLP(const uint16_t opcode) -{ - uint32_t m = Rm; uint32_t n = Rn; - - m_r[n] = RL(m_r[m] ); - if (n != m) - m_r[m] += 4; -} - -/* MOV.B Rm,@(R0,Rn) */ -inline void sh34_base_device::MOVBS0(const uint16_t opcode) -{ - m_ea = m_r[Rn] + m_r[0]; - WB(m_ea, m_r[Rm] & 0x000000ff ); -} - -/* MOV.W Rm,@(R0,Rn) */ -inline void sh34_base_device::MOVWS0(const uint16_t opcode) -{ - m_ea = m_r[Rn] + m_r[0]; - WW(m_ea, m_r[Rm] & 0x0000ffff ); -} - -/* MOV.L Rm,@(R0,Rn) */ -inline void sh34_base_device::MOVLS0(const uint16_t opcode) -{ - m_ea = m_r[Rn] + m_r[0]; - WL(m_ea, m_r[Rm] ); -} - -/* MOV.B @(R0,Rm),Rn */ -inline void sh34_base_device::MOVBL0(const uint16_t opcode) -{ - m_ea = m_r[Rm] + m_r[0]; - m_r[Rn] = (uint32_t)(int32_t)(int16_t)(int8_t) RB( m_ea ); -} - -/* MOV.W @(R0,Rm),Rn */ -inline void sh34_base_device::MOVWL0(const uint16_t opcode) -{ - m_ea = m_r[Rm] + m_r[0]; - m_r[Rn] = (uint32_t)(int32_t)(int16_t) RW(m_ea ); -} - -/* MOV.L @(R0,Rm),Rn */ -inline void sh34_base_device::MOVLL0(const uint16_t opcode) -{ - m_ea = m_r[Rm] + m_r[0]; - m_r[Rn] = RL(m_ea ); -} - -/* MOV #imm,Rn */ -inline void sh34_base_device::MOVI(const uint16_t opcode) -{ - m_r[Rn] = (uint32_t)(int32_t)(int16_t)(int8_t)(opcode&0xff); -} - -/* MOV.W @(disp8,PC),Rn */ -inline void sh34_base_device::MOVWI(const uint16_t opcode) -{ - uint32_t disp = opcode & 0xff; - m_ea = m_pc + disp * 2 + 2; - m_r[Rn] = (uint32_t)(int32_t)(int16_t) RW(m_ea ); -} - -/* MOV.L @(disp8,PC),Rn */ -inline void sh34_base_device::MOVLI(const uint16_t opcode) -{ - uint32_t disp = opcode & 0xff; - m_ea = ((m_pc + 2) & ~3) + disp * 4; - m_r[Rn] = RL(m_ea ); -} - -/* MOV.B @(disp8,GBR),R0 */ -inline void sh34_base_device::MOVBLG(const uint16_t opcode) -{ - uint32_t disp = opcode & 0xff; - m_ea = m_gbr + disp; - m_r[0] = (uint32_t)(int32_t)(int16_t)(int8_t) RB( m_ea ); -} - -/* MOV.W @(disp8,GBR),R0 */ -inline void sh34_base_device::MOVWLG(const uint16_t opcode) -{ - uint32_t disp = opcode & 0xff; - m_ea = m_gbr + disp * 2; - m_r[0] = (int32_t)(int16_t) RW(m_ea ); -} - -/* MOV.L @(disp8,GBR),R0 */ -inline void sh34_base_device::MOVLLG(const uint16_t opcode) -{ - uint32_t disp = opcode & 0xff; - m_ea = m_gbr + disp * 4; - m_r[0] = RL(m_ea ); -} - -/* MOV.B R0,@(disp8,GBR) */ -inline void sh34_base_device::MOVBSG(const uint16_t opcode) -{ - uint32_t disp = opcode & 0xff; - m_ea = m_gbr + disp; - WB(m_ea, m_r[0] & 0x000000ff ); -} - -/* MOV.W R0,@(disp8,GBR) */ -inline void sh34_base_device::MOVWSG(const uint16_t opcode) -{ - uint32_t disp = opcode & 0xff; - m_ea = m_gbr + disp * 2; - WW(m_ea, m_r[0] & 0x0000ffff ); -} - -/* MOV.L R0,@(disp8,GBR) */ -inline void sh34_base_device::MOVLSG(const uint16_t opcode) -{ - uint32_t disp = opcode & 0xff; - m_ea = m_gbr + disp * 4; - WL(m_ea, m_r[0] ); -} - -/* MOV.B R0,@(disp4,Rm) */ -inline void sh34_base_device::MOVBS4(const uint16_t opcode) -{ - uint32_t disp = opcode & 0x0f; - m_ea = m_r[Rm] + disp; - WB(m_ea, m_r[0] & 0x000000ff ); -} - -/* MOV.W R0,@(disp4,Rm) */ -inline void sh34_base_device::MOVWS4(const uint16_t opcode) -{ - uint32_t disp = opcode & 0x0f; - m_ea = m_r[Rm] + disp * 2; - WW(m_ea, m_r[0] & 0x0000ffff ); -} - -/* MOV.L Rm,@(disp4,Rn) */ -inline void sh34_base_device::MOVLS4(const uint16_t opcode) -{ - uint32_t disp = opcode & 0x0f; - m_ea = m_r[Rn] + disp * 4; - WL(m_ea, m_r[Rm] ); -} - -/* MOV.B @(disp4,Rm),R0 */ -inline void sh34_base_device::MOVBL4(const uint16_t opcode) -{ - uint32_t disp = opcode & 0x0f; - m_ea = m_r[Rm] + disp; - m_r[0] = (uint32_t)(int32_t)(int16_t)(int8_t) RB( m_ea ); -} - -/* MOV.W @(disp4,Rm),R0 */ -inline void sh34_base_device::MOVWL4(const uint16_t opcode) -{ - uint32_t disp = opcode & 0x0f; - m_ea = m_r[Rm] + disp * 2; - m_r[0] = (uint32_t)(int32_t)(int16_t) RW(m_ea ); -} - -/* MOV.L @(disp4,Rm),Rn */ -inline void sh34_base_device::MOVLL4(const uint16_t opcode) -{ - uint32_t disp = opcode & 0x0f; - m_ea = m_r[Rm] + disp * 4; - m_r[Rn] = RL(m_ea ); -} - -/* MOVA @(disp8,PC),R0 */ -inline void sh34_base_device::MOVA(const uint16_t opcode) -{ - uint32_t disp = opcode & 0xff; - m_ea = ((m_pc + 2) & ~3) + disp * 4; - m_r[0] = m_ea; -} - -/* MOVT Rn */ -void sh34_base_device::MOVT(const uint16_t opcode) -{ - m_r[Rn] = m_sr & T; -} - -/* MUL.L Rm,Rn */ -inline void sh34_base_device::MULL(const uint16_t opcode) -{ - m_macl = m_r[Rn] * m_r[Rm]; - m_sh4_icount--; -} - -/* MULS Rm,Rn */ -inline void sh34_base_device::MULS(const uint16_t opcode) -{ - m_macl = (int16_t) m_r[Rn] * (int16_t) m_r[Rm]; -} - -/* MULU Rm,Rn */ -inline void sh34_base_device::MULU(const uint16_t opcode) -{ - m_macl = (uint16_t) m_r[Rn] * (uint16_t) m_r[Rm]; -} - -/* NEG Rm,Rn */ -inline void sh34_base_device::NEG(const uint16_t opcode) -{ - m_r[Rn] = 0 - m_r[Rm]; -} - -/* NEGC Rm,Rn */ -inline void sh34_base_device::NEGC(const uint16_t opcode) -{ - uint32_t temp; - - temp = m_r[Rm]; - m_r[Rn] = -temp - (m_sr & T); - if (temp || (m_sr & T)) - m_sr |= T; - else - m_sr &= ~T; -} - -/* NOP */ -inline void sh34_base_device::NOP(const uint16_t opcode) -{ -} - -/* NOT Rm,Rn */ -inline void sh34_base_device::NOT(const uint16_t opcode) -{ - m_r[Rn] = ~m_r[Rm]; -} - -/* OR Rm,Rn */ -inline void sh34_base_device::OR(const uint16_t opcode) -{ - m_r[Rn] |= m_r[Rm]; -} - -/* OR #imm,R0 */ -inline void sh34_base_device::ORI(const uint16_t opcode) -{ - m_r[0] |= (opcode&0xff); - m_sh4_icount -= 2; -} - -/* OR.B #imm,@(R0,GBR) */ -inline void sh34_base_device::ORM(const uint16_t opcode) -{ - uint32_t temp; - - m_ea = m_gbr + m_r[0]; - temp = RB( m_ea ); - temp |= (opcode&0xff); - WB(m_ea, temp ); -} - -/* ROTCL Rn */ -inline void sh34_base_device::ROTCL(const uint16_t opcode) -{ - uint32_t n = Rn; - - uint32_t temp; - - temp = (m_r[n] >> 31) & T; - m_r[n] = (m_r[n] << 1) | (m_sr & T); - m_sr = (m_sr & ~T) | temp; -} - -/* ROTCR Rn */ -inline void sh34_base_device::ROTCR(const uint16_t opcode) -{ - uint32_t n = Rn; - - uint32_t temp; - temp = (m_sr & T) << 31; - if (m_r[n] & T) - m_sr |= T; - else - m_sr &= ~T; - m_r[n] = (m_r[n] >> 1) | temp; -} - -/* ROTL Rn */ -inline void sh34_base_device::ROTL(const uint16_t opcode) -{ - uint32_t n = Rn; - - m_sr = (m_sr & ~T) | ((m_r[n] >> 31) & T); - m_r[n] = (m_r[n] << 1) | (m_r[n] >> 31); -} - -/* ROTR Rn */ -inline void sh34_base_device::ROTR(const uint16_t opcode) -{ - uint32_t n = Rn; - - m_sr = (m_sr & ~T) | (m_r[n] & T); - m_r[n] = (m_r[n] >> 1) | (m_r[n] << 31); -} - -/* RTE */ -inline void sh34_base_device::RTE(const uint16_t opcode) -{ - m_delay = m_ea = m_spc; - if ((machine().debug_flags & DEBUG_FLAG_ENABLED) != 0) - sh4_syncronize_register_bank((m_sr & sRB) >> 29); - if ((m_ssr & sRB) != (m_sr & sRB)) - sh4_change_register_bank(m_ssr & sRB ? 1 : 0); - m_sr = m_ssr; - m_sh4_icount--; - sh4_exception_recompute(); -} - -/* RTS */ -inline void sh34_base_device::RTS(const uint16_t opcode) -{ - m_delay = m_ea = m_pr; - m_sh4_icount--; -} - -/* SETT */ -inline void sh34_base_device::SETT(const uint16_t opcode) -{ - m_sr |= T; -} - -/* SHAL Rn (same as SHLL) */ -inline void sh34_base_device::SHAL(const uint16_t opcode) -{ - uint32_t n = Rn; - - m_sr = (m_sr & ~T) | ((m_r[n] >> 31) & T); - m_r[n] <<= 1; -} - -/* SHAR Rn */ -inline void sh34_base_device::SHAR(const uint16_t opcode) -{ - uint32_t n = Rn; - - m_sr = (m_sr & ~T) | (m_r[n] & T); - m_r[n] = (uint32_t)((int32_t)m_r[n] >> 1); -} - -/* SHLL Rn (same as SHAL) */ -inline void sh34_base_device::SHLL(const uint16_t opcode) -{ - uint32_t n = Rn; - - m_sr = (m_sr & ~T) | ((m_r[n] >> 31) & T); - m_r[n] <<= 1; -} - -/* SHLL2 Rn */ -inline void sh34_base_device::SHLL2(const uint16_t opcode) -{ - m_r[Rn] <<= 2; -} - -/* SHLL8 Rn */ -inline void sh34_base_device::SHLL8(const uint16_t opcode) -{ - m_r[Rn] <<= 8; -} - -/* SHLL16 Rn */ -inline void sh34_base_device::SHLL16(const uint16_t opcode) -{ - m_r[Rn] <<= 16; -} - -/* SHLR Rn */ -inline void sh34_base_device::SHLR(const uint16_t opcode) -{ - uint32_t n = Rn; - - m_sr = (m_sr & ~T) | (m_r[n] & T); - m_r[n] >>= 1; -} - -/* SHLR2 Rn */ -inline void sh34_base_device::SHLR2(const uint16_t opcode) -{ - m_r[Rn] >>= 2; -} - -/* SHLR8 Rn */ -inline void sh34_base_device::SHLR8(const uint16_t opcode) -{ - m_r[Rn] >>= 8; -} - -/* SHLR16 Rn */ -inline void sh34_base_device::SHLR16(const uint16_t opcode) -{ - m_r[Rn] >>= 16; -} - -/* SLEEP */ -inline void sh34_base_device::SLEEP(const uint16_t opcode) -{ - /* 0 = normal mode */ - /* 1 = enters into power-down mode */ - /* 2 = go out the power-down mode after an exception */ - if(m_sleep_mode != 2) - m_pc -= 2; - m_sh4_icount -= 2; - /* Wait_for_exception; */ - if(m_sleep_mode == 0) - m_sleep_mode = 1; - else if(m_sleep_mode == 2) - m_sleep_mode = 0; -} - -/* STC SR,Rn */ -inline void sh34_base_device::STCSR(const uint16_t opcode) -{ - m_r[Rn] = m_sr; -} - -/* STC GBR,Rn */ -inline void sh34_base_device::STCGBR(const uint16_t opcode) -{ - m_r[Rn] = m_gbr; -} - -/* STC VBR,Rn */ -inline void sh34_base_device::STCVBR(const uint16_t opcode) -{ - m_r[Rn] = m_vbr; -} - -/* STC.L SR,@-Rn */ -inline void sh34_base_device::STCMSR(const uint16_t opcode) -{ - uint32_t n = Rn; - - m_r[n] -= 4; - m_ea = m_r[n]; - WL(m_ea, m_sr ); - m_sh4_icount--; -} - -/* STC.L GBR,@-Rn */ -inline void sh34_base_device::STCMGBR(const uint16_t opcode) -{ - uint32_t n = Rn; - - m_r[n] -= 4; - m_ea = m_r[n]; - WL(m_ea, m_gbr ); - m_sh4_icount--; -} - -/* STC.L VBR,@-Rn */ -inline void sh34_base_device::STCMVBR(const uint16_t opcode) -{ - uint32_t n = Rn; - - m_r[n] -= 4; - m_ea = m_r[n]; - WL(m_ea, m_vbr ); - m_sh4_icount--; -} - -/* STS MACH,Rn */ -inline void sh34_base_device::STSMACH(const uint16_t opcode) -{ - m_r[Rn] = m_mach; -} - -/* STS MACL,Rn */ -inline void sh34_base_device::STSMACL(const uint16_t opcode) -{ - m_r[Rn] = m_macl; -} - -/* STS PR,Rn */ -inline void sh34_base_device::STSPR(const uint16_t opcode) -{ - m_r[Rn] = m_pr; -} - -/* STS.L MACH,@-Rn */ -inline void sh34_base_device::STSMMACH(const uint16_t opcode) -{ - uint32_t n = Rn; - - m_r[n] -= 4; - m_ea = m_r[n]; - WL(m_ea, m_mach ); -} - -/* STS.L MACL,@-Rn */ -inline void sh34_base_device::STSMMACL(const uint16_t opcode) -{ - uint32_t n = Rn; - - m_r[n] -= 4; - m_ea = m_r[n]; - WL(m_ea, m_macl ); -} - -/* STS.L PR,@-Rn */ -inline void sh34_base_device::STSMPR(const uint16_t opcode) -{ - uint32_t n = Rn; - - m_r[n] -= 4; - m_ea = m_r[n]; - WL(m_ea, m_pr ); -} - -/* SUB Rm,Rn */ -inline void sh34_base_device::SUB(const uint16_t opcode) -{ - m_r[Rn] -= m_r[Rm]; -} - -/* SUBC Rm,Rn */ -inline void sh34_base_device::SUBC(const uint16_t opcode) -{ - uint32_t m = Rm; uint32_t n = Rn; - - uint32_t tmp0, tmp1; - - tmp1 = m_r[n] - m_r[m]; - tmp0 = m_r[n]; - m_r[n] = tmp1 - (m_sr & T); - if (tmp0 < tmp1) - m_sr |= T; - else - m_sr &= ~T; - if (tmp1 < m_r[n]) - m_sr |= T; -} - -/* SUBV Rm,Rn */ -inline void sh34_base_device::SUBV(const uint16_t opcode) -{ - uint32_t m = Rm; uint32_t n = Rn; - - int32_t dest, src, ans; - - if ((int32_t) m_r[n] >= 0) - dest = 0; - else - dest = 1; - if ((int32_t) m_r[m] >= 0) - src = 0; - else - src = 1; - src += dest; - m_r[n] -= m_r[m]; - if ((int32_t) m_r[n] >= 0) - ans = 0; - else - ans = 1; - ans += dest; - if (src == 1) - { - if (ans == 1) - m_sr |= T; - else - m_sr &= ~T; - } - else - m_sr &= ~T; -} - -/* SWAP.B Rm,Rn */ -inline void sh34_base_device::SWAPB(const uint16_t opcode) -{ - uint32_t m = Rm; uint32_t n = Rn; - - uint32_t temp0, temp1; - - temp0 = m_r[m] & 0xffff0000; - temp1 = (m_r[m] & 0x000000ff) << 8; - m_r[n] = (m_r[m] >> 8) & 0x000000ff; - m_r[n] = m_r[n] | temp1 | temp0; -} - -/* SWAP.W Rm,Rn */ -inline void sh34_base_device::SWAPW(const uint16_t opcode) -{ - uint32_t m = Rm; uint32_t n = Rn; - - uint32_t temp; - - temp = (m_r[m] >> 16) & 0x0000ffff; - m_r[n] = (m_r[m] << 16) | temp; -} - -/* TAS.B @Rn */ -inline void sh34_base_device::TAS(const uint16_t opcode) -{ - uint32_t n = Rn; - - uint32_t temp; - m_ea = m_r[n]; - /* Bus Lock enable */ - temp = RB( m_ea ); - if (temp == 0) - m_sr |= T; - else - m_sr &= ~T; - temp |= 0x80; - /* Bus Lock disable */ - WB(m_ea, temp ); - m_sh4_icount -= 3; -} - -/* TRAPA #imm */ -inline void sh34_base_device::TRAPA(const uint16_t opcode) -{ - uint32_t imm = opcode & 0xff; - - if (m_cpu_type == CPU_TYPE_SH4) - { - m_m[TRA] = imm << 2; - } - else /* SH3 */ - { - m_sh3internal_upper[SH3_TRA_ADDR] = imm << 2; - } - - - m_ssr = m_sr; - m_spc = m_pc; - m_sgr = m_r[15]; - - m_sr |= MD; - if ((machine().debug_flags & DEBUG_FLAG_ENABLED) != 0) - sh4_syncronize_register_bank((m_sr & sRB) >> 29); - if (!(m_sr & sRB)) - sh4_change_register_bank(1); - m_sr |= sRB; - m_sr |= BL; - sh4_exception_recompute(); - - if (m_cpu_type == CPU_TYPE_SH4) - { - m_m[EXPEVT] = 0x00000160; - } - else /* SH3 */ - { - m_sh3internal_upper[SH3_EXPEVT_ADDR] = 0x00000160; - } - - m_pc = m_vbr + 0x00000100; - - m_sh4_icount -= 7; -} - -/* TST Rm,Rn */ -inline void sh34_base_device::TST(const uint16_t opcode) -{ - if ((m_r[Rn] & m_r[Rm]) == 0) - m_sr |= T; - else - m_sr &= ~T; -} - -/* TST #imm,R0 */ -inline void sh34_base_device::TSTI(const uint16_t opcode) -{ - uint32_t imm = opcode & 0xff; - - if ((imm & m_r[0]) == 0) - m_sr |= T; - else - m_sr &= ~T; -} - -/* TST.B #imm,@(R0,GBR) */ -inline void sh34_base_device::TSTM(const uint16_t opcode) -{ - uint32_t imm = opcode & 0xff; - - m_ea = m_gbr + m_r[0]; - if ((imm & RB( m_ea )) == 0) - m_sr |= T; - else - m_sr &= ~T; - m_sh4_icount -= 2; -} - -/* XOR Rm,Rn */ -inline void sh34_base_device::XOR(const uint16_t opcode) -{ - m_r[Rn] ^= m_r[Rm]; -} - -/* XOR #imm,R0 */ -inline void sh34_base_device::XORI(const uint16_t opcode) -{ - uint32_t imm = opcode & 0xff; - m_r[0] ^= imm; -} - -/* XOR.B #imm,@(R0,GBR) */ -inline void sh34_base_device::XORM(const uint16_t opcode) -{ - uint32_t imm = opcode & 0xff; - uint32_t temp; - - m_ea = m_gbr + m_r[0]; - temp = RB( m_ea ); - temp ^= imm; - WB(m_ea, temp ); - m_sh4_icount -= 2; -} - -/* XTRCT Rm,Rn */ -inline void sh34_base_device::XTRCT(const uint16_t opcode) -{ - uint32_t m = Rm; uint32_t n = Rn; - - uint32_t temp; - - temp = (m_r[m] << 16) & 0xffff0000; - m_r[n] = (m_r[n] >> 16) & 0x0000ffff; - m_r[n] |= temp; -} - -/* STC SSR,Rn */ -inline void sh34_base_device::STCSSR(const uint16_t opcode) -{ - m_r[Rn] = m_ssr; -} - -/* STC SPC,Rn */ -inline void sh34_base_device::STCSPC(const uint16_t opcode) -{ - m_r[Rn] = m_spc; -} - -/* STC SGR,Rn */ -inline void sh34_base_device::STCSGR(const uint16_t opcode) -{ - m_r[Rn] = m_sgr; -} - -/* STS FPUL,Rn */ -inline void sh34_base_device::STSFPUL(const uint16_t opcode) -{ - m_r[Rn] = m_fpul; -} - -/* STS FPSCR,Rn */ -inline void sh34_base_device::STSFPSCR(const uint16_t opcode) -{ - m_r[Rn] = m_fpscr & 0x003FFFFF; -} - -/* STC DBR,Rn */ -inline void sh34_base_device::STCDBR(const uint16_t opcode) -{ - m_r[Rn] = m_dbr; -} - -/* STCRBANK Rm_BANK,Rn */ -inline void sh34_base_device::STCRBANK(const uint16_t opcode) -{ - uint32_t m = Rm; - - m_r[Rn] = m_rbnk[m_sr&sRB ? 0 : 1][m & 7]; -} - -/* STCMRBANK Rm_BANK,@-Rn */ -inline void sh34_base_device::STCMRBANK(const uint16_t opcode) -{ - uint32_t m = Rm; uint32_t n = Rn; - - m_r[n] -= 4; - m_ea = m_r[n]; - WL(m_ea, m_rbnk[m_sr&sRB ? 0 : 1][m & 7]); - m_sh4_icount--; -} - -/* MOVCA.L R0,@Rn */ -inline void sh34_base_device::MOVCAL(const uint16_t opcode) -{ - m_ea = m_r[Rn]; - WL(m_ea, m_r[0] ); -} - -inline void sh34_base_device::CLRS(const uint16_t opcode) -{ - m_sr &= ~S; -} - -inline void sh34_base_device::SETS(const uint16_t opcode) -{ - m_sr |= S; -} - -/* STS.L SGR,@-Rn */ -inline void sh34_base_device::STCMSGR(const uint16_t opcode) -{ - uint32_t n = Rn; - - m_r[n] -= 4; - m_ea = m_r[n]; - WL(m_ea, m_sgr ); -} - -/* STS.L FPUL,@-Rn */ -inline void sh34_base_device::STSMFPUL(const uint16_t opcode) -{ - uint32_t n = Rn; - - m_r[n] -= 4; - m_ea = m_r[n]; - WL(m_ea, m_fpul ); -} - -/* STS.L FPSCR,@-Rn */ -inline void sh34_base_device::STSMFPSCR(const uint16_t opcode) -{ - uint32_t n = Rn; - - m_r[n] -= 4; - m_ea = m_r[n]; - WL(m_ea, m_fpscr & 0x003FFFFF); -} - -/* STC.L DBR,@-Rn */ -inline void sh34_base_device::STCMDBR(const uint16_t opcode) -{ - uint32_t n = Rn; - - m_r[n] -= 4; - m_ea = m_r[n]; - WL(m_ea, m_dbr ); -} - -/* STC.L SSR,@-Rn */ -inline void sh34_base_device::STCMSSR(const uint16_t opcode) -{ - uint32_t n = Rn; - - m_r[n] -= 4; - m_ea = m_r[n]; - WL(m_ea, m_ssr ); -} - -/* STC.L SPC,@-Rn */ -inline void sh34_base_device::STCMSPC(const uint16_t opcode) -{ - uint32_t n = Rn; - - m_r[n] -= 4; - m_ea = m_r[n]; - WL(m_ea, m_spc ); -} - -/* LDS.L @Rm+,FPUL */ -inline void sh34_base_device::LDSMFPUL(const uint16_t opcode) -{ - m_ea = m_r[Rn]; - m_fpul = RL(m_ea ); - m_r[Rn] += 4; -} - -/* LDS.L @Rm+,FPSCR */ -inline void sh34_base_device::LDSMFPSCR(const uint16_t opcode) -{ - uint32_t s; - - s = m_fpscr; - m_ea = m_r[Rn]; - m_fpscr = RL(m_ea ); - m_fpscr &= 0x003FFFFF; - m_r[Rn] += 4; - if ((s & FR) != (m_fpscr & FR)) - sh4_swap_fp_registers(); -#ifdef LSB_FIRST - if ((s & PR) != (m_fpscr & PR)) - sh4_swap_fp_couples(); -#endif - m_fpu_sz = (m_fpscr & SZ) ? 1 : 0; - m_fpu_pr = (m_fpscr & PR) ? 1 : 0; -} - -/* LDC.L @Rm+,DBR */ -inline void sh34_base_device::LDCMDBR(const uint16_t opcode) -{ - m_ea = m_r[Rn]; - m_dbr = RL(m_ea ); - m_r[Rn] += 4; -} - -/* LDC.L @Rn+,Rm_BANK */ -inline void sh34_base_device::LDCMRBANK(const uint16_t opcode) -{ - uint32_t m = Rm; uint32_t n = Rn; - - m_ea = m_r[n]; - m_rbnk[m_sr&sRB ? 0 : 1][m & 7] = RL(m_ea ); - m_r[n] += 4; -} - -/* LDC.L @Rm+,SSR */ -inline void sh34_base_device::LDCMSSR(const uint16_t opcode) -{ - m_ea = m_r[Rn]; - m_ssr = RL(m_ea ); - m_r[Rn] += 4; -} - -/* LDC.L @Rm+,SPC */ -inline void sh34_base_device::LDCMSPC(const uint16_t opcode) -{ - m_ea = m_r[Rn]; - m_spc = RL(m_ea ); - m_r[Rn] += 4; -} - -/* LDS Rm,FPUL */ -inline void sh34_base_device::LDSFPUL(const uint16_t opcode) -{ - m_fpul = m_r[Rn]; -} - -/* LDS Rm,FPSCR */ -inline void sh34_base_device::LDSFPSCR(const uint16_t opcode) -{ - uint32_t s; - - s = m_fpscr; - m_fpscr = m_r[Rn] & 0x003FFFFF; - if ((s & FR) != (m_fpscr & FR)) - sh4_swap_fp_registers(); -#ifdef LSB_FIRST - if ((s & PR) != (m_fpscr & PR)) - sh4_swap_fp_couples(); -#endif - m_fpu_sz = (m_fpscr & SZ) ? 1 : 0; - m_fpu_pr = (m_fpscr & PR) ? 1 : 0; -} - -/* LDC Rm,DBR */ -inline void sh34_base_device::LDCDBR(const uint16_t opcode) -{ - m_dbr = m_r[Rn]; -} - -/* SHAD Rm,Rn */ -inline void sh34_base_device::SHAD(const uint16_t opcode) -{ - uint32_t m = Rm; uint32_t n = Rn; - - if ((m_r[m] & 0x80000000) == 0) - m_r[n] = m_r[n] << (m_r[m] & 0x1F); - else if ((m_r[m] & 0x1F) == 0) { - if ((m_r[n] & 0x80000000) == 0) - m_r[n] = 0; - else - m_r[n] = 0xFFFFFFFF; - } else - m_r[n]=(int32_t)m_r[n] >> ((~m_r[m] & 0x1F)+1); -} - -/* SHLD Rm,Rn */ -inline void sh34_base_device::SHLD(const uint16_t opcode) -{ - uint32_t m = Rm; uint32_t n = Rn; - - if ((m_r[m] & 0x80000000) == 0) - m_r[n] = m_r[n] << (m_r[m] & 0x1F); - else if ((m_r[m] & 0x1F) == 0) - m_r[n] = 0; - else - m_r[n] = m_r[n] >> ((~m_r[m] & 0x1F)+1); -} - -/* LDCRBANK Rn,Rm_BANK */ -inline void sh34_base_device::LDCRBANK(const uint16_t opcode) -{ - uint32_t m = Rm; - - m_rbnk[m_sr&sRB ? 0 : 1][m & 7] = m_r[Rn]; -} - -/* LDC Rm,SSR */ -inline void sh34_base_device::LDCSSR(const uint16_t opcode) -{ - m_ssr = m_r[Rn]; -} - -/* LDC Rm,SPC */ -inline void sh34_base_device::LDCSPC(const uint16_t opcode) -{ - m_spc = m_r[Rn]; -} - -/* PREF @Rn */ -inline void sh34_base_device::PREFM(const uint16_t opcode) -{ - int a; - uint32_t addr,dest,sq; - - addr = m_r[Rn]; // address - if ((addr >= 0xE0000000) && (addr <= 0xE3FFFFFF)) - { - if (m_sh4_mmu_enabled) - { - addr = addr & 0xFFFFFFE0; - dest = sh4_getsqremap(addr); // good enough for naomi-gd rom, probably not much else - - } - else - { - sq = (addr & 0x20) >> 5; - dest = addr & 0x03FFFFE0; - if (sq == 0) - { - if (m_cpu_type == CPU_TYPE_SH4) - { - dest |= (m_m[QACR0] & 0x1C) << 24; - } - else - { - fatalerror("m_cpu_type != CPU_TYPE_SH4 but access internal regs\n"); - } - } - else - { - if (m_cpu_type == CPU_TYPE_SH4) - { - dest |= (m_m[QACR1] & 0x1C) << 24; - } - else - { - fatalerror("m_cpu_type != CPU_TYPE_SH4 but access internal regs\n"); - } - - } - addr = addr & 0xFFFFFFE0; - } - - for (a = 0;a < 4;a++) - { - // shouldn't be causing a memory read, should store sq writes in registers. - m_program->write_qword(dest, m_program->read_qword(addr)); - addr += 8; - dest += 8; - } - } -} - -/***************************************************************************** - * OPCODE DISPATCHERS - *****************************************************************************/ - -// TODO: current SZ=1(64bit) FMOVs correct for SH4 in LE mode only - -/* FMOV.S @Rm+,FRn PR=0 SZ=0 1111nnnnmmmm1001 */ -/* FMOV @Rm+,DRn PR=0 SZ=1 1111nnn0mmmm1001 */ -/* FMOV @Rm+,XDn PR=0 SZ=1 1111nnn1mmmm1001 */ -/* FMOV @Rm+,XDn PR=1 1111nnn1mmmm1001 */ -inline void sh34_base_device::FMOVMRIFR(const uint16_t opcode) -{ - uint32_t m = Rm; uint32_t n = Rn; - - if (m_fpu_sz) { /* SZ = 1 */ - if (n & 1) { - n &= 14; -#ifdef LSB_FIRST - n ^= m_fpu_pr; -#endif - m_ea = m_r[m]; - m_xf[n] = RL(m_ea ); - m_r[m] += 4; - m_xf[n^1] = RL(m_ea+4 ); - m_r[m] += 4; - } else { -#ifdef LSB_FIRST - n ^= m_fpu_pr; -#endif - m_ea = m_r[m]; - m_fr[n] = RL(m_ea ); - m_r[m] += 4; - m_fr[n^1] = RL(m_ea+4 ); - m_r[m] += 4; - } - } else { /* SZ = 0 */ - m_ea = m_r[m]; -#ifdef LSB_FIRST - n ^= m_fpu_pr; -#endif - m_fr[n] = RL(m_ea ); - m_r[m] += 4; - } -} - -/* FMOV.S FRm,@Rn PR=0 SZ=0 1111nnnnmmmm1010 */ -/* FMOV DRm,@Rn PR=0 SZ=1 1111nnnnmmm01010 */ -/* FMOV XDm,@Rn PR=0 SZ=1 1111nnnnmmm11010 */ -/* FMOV XDm,@Rn PR=1 1111nnnnmmm11010 */ -inline void sh34_base_device::FMOVFRMR(const uint16_t opcode) -{ - uint32_t m = Rm; uint32_t n = Rn; - - if (m_fpu_sz) { /* SZ = 1 */ - if (m & 1) { - m &= 14; -#ifdef LSB_FIRST - m ^= m_fpu_pr; -#endif - m_ea = m_r[n]; - WL(m_ea,m_xf[m] ); - WL(m_ea+4,m_xf[m^1] ); - } else { -#ifdef LSB_FIRST - m ^= m_fpu_pr; -#endif - m_ea = m_r[n]; - WL(m_ea,m_fr[m] ); - WL(m_ea+4,m_fr[m^1] ); - } - } else { /* SZ = 0 */ - m_ea = m_r[n]; -#ifdef LSB_FIRST - m ^= m_fpu_pr; -#endif - WL(m_ea,m_fr[m] ); - } -} - -/* FMOV.S FRm,@-Rn PR=0 SZ=0 1111nnnnmmmm1011 */ -/* FMOV DRm,@-Rn PR=0 SZ=1 1111nnnnmmm01011 */ -/* FMOV XDm,@-Rn PR=0 SZ=1 1111nnnnmmm11011 */ -/* FMOV XDm,@-Rn PR=1 1111nnnnmmm11011 */ -inline void sh34_base_device::FMOVFRMDR(const uint16_t opcode) -{ - uint32_t m = Rm; uint32_t n = Rn; - - if (m_fpu_sz) { /* SZ = 1 */ - if (m & 1) { - m &= 14; -#ifdef LSB_FIRST - m ^= m_fpu_pr; -#endif - m_r[n] -= 8; - m_ea = m_r[n]; - WL(m_ea,m_xf[m] ); - WL(m_ea+4,m_xf[m^1] ); - } else { -#ifdef LSB_FIRST - m ^= m_fpu_pr; -#endif - m_r[n] -= 8; - m_ea = m_r[n]; - WL(m_ea,m_fr[m] ); - WL(m_ea+4,m_fr[m^1] ); - } - } else { /* SZ = 0 */ - m_r[n] -= 4; - m_ea = m_r[n]; -#ifdef LSB_FIRST - m ^= m_fpu_pr; -#endif - WL(m_ea,m_fr[m] ); - } -} - -/* FMOV.S FRm,@(R0,Rn) PR=0 SZ=0 1111nnnnmmmm0111 */ -/* FMOV DRm,@(R0,Rn) PR=0 SZ=1 1111nnnnmmm00111 */ -/* FMOV XDm,@(R0,Rn) PR=0 SZ=1 1111nnnnmmm10111 */ -/* FMOV XDm,@(R0,Rn) PR=1 1111nnnnmmm10111 */ -inline void sh34_base_device::FMOVFRS0(const uint16_t opcode) -{ - uint32_t m = Rm; uint32_t n = Rn; - - if (m_fpu_sz) { /* SZ = 1 */ - if (m & 1) { - m &= 14; -#ifdef LSB_FIRST - m ^= m_fpu_pr; -#endif - m_ea = m_r[0] + m_r[n]; - WL(m_ea,m_xf[m] ); - WL(m_ea+4,m_xf[m^1] ); - } else { -#ifdef LSB_FIRST - m ^= m_fpu_pr; -#endif - m_ea = m_r[0] + m_r[n]; - WL(m_ea,m_fr[m] ); - WL(m_ea+4,m_fr[m^1] ); - } - } else { /* SZ = 0 */ - m_ea = m_r[0] + m_r[n]; -#ifdef LSB_FIRST - m ^= m_fpu_pr; -#endif - WL(m_ea,m_fr[m] ); - } -} - -/* FMOV.S @(R0,Rm),FRn PR=0 SZ=0 1111nnnnmmmm0110 */ -/* FMOV @(R0,Rm),DRn PR=0 SZ=1 1111nnn0mmmm0110 */ -/* FMOV @(R0,Rm),XDn PR=0 SZ=1 1111nnn1mmmm0110 */ -/* FMOV @(R0,Rm),XDn PR=1 1111nnn1mmmm0110 */ -inline void sh34_base_device::FMOVS0FR(const uint16_t opcode) -{ - uint32_t m = Rm; uint32_t n = Rn; - - if (m_fpu_sz) { /* SZ = 1 */ - if (n & 1) { - n &= 14; -#ifdef LSB_FIRST - n ^= m_fpu_pr; -#endif - m_ea = m_r[0] + m_r[m]; - m_xf[n] = RL(m_ea ); - m_xf[n^1] = RL(m_ea+4 ); - } else { -#ifdef LSB_FIRST - n ^= m_fpu_pr; -#endif - m_ea = m_r[0] + m_r[m]; - m_fr[n] = RL(m_ea ); - m_fr[n^1] = RL(m_ea+4 ); - } - } else { /* SZ = 0 */ - m_ea = m_r[0] + m_r[m]; -#ifdef LSB_FIRST - n ^= m_fpu_pr; -#endif - m_fr[n] = RL(m_ea ); - } -} - -/* FMOV.S @Rm,FRn PR=0 SZ=0 1111nnnnmmmm1000 */ -/* FMOV @Rm,DRn PR=0 SZ=1 1111nnn0mmmm1000 */ -/* FMOV @Rm,XDn PR=0 SZ=1 1111nnn1mmmm1000 */ -/* FMOV @Rm,XDn PR=1 1111nnn1mmmm1000 */ -/* FMOV @Rm,DRn PR=1 1111nnn0mmmm1000 */ -inline void sh34_base_device::FMOVMRFR(const uint16_t opcode) -{ - uint32_t m = Rm; uint32_t n = Rn; - - if (m_fpu_sz) { /* SZ = 1 */ - if (n & 1) { - n &= 14; -#ifdef LSB_FIRST - n ^= m_fpu_pr; -#endif - m_ea = m_r[m]; - m_xf[n] = RL(m_ea ); - m_xf[n^1] = RL(m_ea+4 ); - } else { -#ifdef LSB_FIRST - n ^= m_fpu_pr; -#endif - m_ea = m_r[m]; - m_fr[n] = RL(m_ea ); - m_fr[n^1] = RL(m_ea+4 ); - } - } else { /* SZ = 0 */ - m_ea = m_r[m]; -#ifdef LSB_FIRST - n ^= m_fpu_pr; -#endif - m_fr[n] = RL(m_ea ); - } -} - -/* FMOV FRm,FRn PR=0 SZ=0 FRm -> FRn 1111nnnnmmmm1100 */ -/* FMOV DRm,DRn PR=0 SZ=1 DRm -> DRn 1111nnn0mmm01100 */ -/* FMOV XDm,DRn PR=1 XDm -> DRn 1111nnn0mmm11100 */ -/* FMOV DRm,XDn PR=1 DRm -> XDn 1111nnn1mmm01100 */ -/* FMOV XDm,XDn PR=1 XDm -> XDn 1111nnn1mmm11100 */ -inline void sh34_base_device::FMOVFR(const uint16_t opcode) -{ - uint32_t m = Rm; uint32_t n = Rn; - - if (m_fpu_sz == 0) { /* SZ = 0 */ -#ifdef LSB_FIRST - n ^= m_fpu_pr; - m ^= m_fpu_pr; -#endif - m_fr[n] = m_fr[m]; - } - else { /* SZ = 1 */ - if (m & 1) { - if (n & 1) { - m_xf[n & 14] = m_xf[m & 14]; - m_xf[n | 1] = m_xf[m | 1]; - } else { - m_fr[n] = m_xf[m & 14]; - m_fr[n | 1] = m_xf[m | 1]; - } - } else { - if (n & 1) { - m_xf[n & 14] = m_fr[m]; - m_xf[n | 1] = m_fr[m | 1]; // (a&14)+1 -> a|1 - } else { - m_fr[n] = m_fr[m]; - m_fr[n | 1] = m_fr[m | 1]; - } - } - } -} - -/* FLDI1 FRn 1111nnnn10011101 */ -inline void sh34_base_device::FLDI1(const uint16_t opcode) -{ -#ifdef LSB_FIRST - m_fr[Rn ^ m_fpu_pr] = 0x3F800000; -#else - m_fr[Rn] = 0x3F800000; -#endif -} - -/* FLDI0 FRn 1111nnnn10001101 */ -inline void sh34_base_device::FLDI0(const uint16_t opcode) -{ -#ifdef LSB_FIRST - m_fr[Rn ^ m_fpu_pr] = 0; -#else - m_fr[Rn] = 0; -#endif -} - -/* FLDS FRm,FPUL 1111mmmm00011101 */ -inline void sh34_base_device:: FLDS(const uint16_t opcode) -{ -#ifdef LSB_FIRST - m_fpul = m_fr[Rn ^ m_fpu_pr]; -#else - m_fpul = m_fr[Rn]; -#endif -} - -/* FSTS FPUL,FRn 1111nnnn00001101 */ -inline void sh34_base_device:: FSTS(const uint16_t opcode) -{ -#ifdef LSB_FIRST - m_fr[Rn ^ m_fpu_pr] = m_fpul; -#else - m_fr[Rn] = m_fpul; -#endif -} - -/* FRCHG 1111101111111101 */ -void sh34_base_device::FRCHG() -{ - m_fpscr ^= FR; - sh4_swap_fp_registers(); -} - -/* FSCHG 1111001111111101 */ -void sh34_base_device::FSCHG() -{ - m_fpscr ^= SZ; - m_fpu_sz = (m_fpscr & SZ) ? 1 : 0; -} - -/* FTRC FRm,FPUL PR=0 1111mmmm00111101 */ -/* FTRC DRm,FPUL PR=1 1111mmm000111101 */ -inline void sh34_base_device::FTRC(const uint16_t opcode) -{ - uint32_t n = Rn; - - if (m_fpu_pr) { /* PR = 1 */ - if(n & 1) - fatalerror("SH-4: FTRC opcode used with n %d",n); - - n = n & 14; - *((int32_t *)&m_fpul) = (int32_t)FP_RFD(n); - } else { /* PR = 0 */ - /* read m_fr[n] as float -> truncate -> fpul(32) */ - *((int32_t *)&m_fpul) = (int32_t)FP_RFS(n); - } -} - -/* FLOAT FPUL,FRn PR=0 1111nnnn00101101 */ -/* FLOAT FPUL,DRn PR=1 1111nnn000101101 */ -inline void sh34_base_device::FLOAT(const uint16_t opcode) -{ - uint32_t n = Rn; - - if (m_fpu_pr) { /* PR = 1 */ - if(n & 1) - fatalerror("SH-4: FLOAT opcode used with n %d",n); - - n = n & 14; - FP_RFD(n) = (double)*((int32_t *)&m_fpul); - } else { /* PR = 0 */ - FP_RFS(n) = (float)*((int32_t *)&m_fpul); - } -} - -/* FNEG FRn PR=0 1111nnnn01001101 */ -/* FNEG DRn PR=1 1111nnn001001101 */ -inline void sh34_base_device::FNEG(const uint16_t opcode) -{ - uint32_t n = Rn; - - if (m_fpu_pr) { /* PR = 1 */ - FP_RFD(n) = -FP_RFD(n); - } else { /* PR = 0 */ - FP_RFS(n) = -FP_RFS(n); - } -} - -/* FABS FRn PR=0 1111nnnn01011101 */ -/* FABS DRn PR=1 1111nnn001011101 */ -inline void sh34_base_device::FABS(const uint16_t opcode) -{ - uint32_t n = Rn; - - if (m_fpu_pr) { /* PR = 1 */ -#ifdef LSB_FIRST - n = n | 1; // n & 14 + 1 - m_fr[n] = m_fr[n] & 0x7fffffff; -#else - n = n & 14; - m_fr[n] = m_fr[n] & 0x7fffffff; -#endif - } else { /* PR = 0 */ - m_fr[n] = m_fr[n] & 0x7fffffff; - } -} - -/* FCMP/EQ FRm,FRn PR=0 1111nnnnmmmm0100 */ -/* FCMP/EQ DRm,DRn PR=1 1111nnn0mmm00100 */ -inline void sh34_base_device::FCMP_EQ(const uint16_t opcode) -{ - uint32_t m = Rm; uint32_t n = Rn; - - if (m_fpu_pr) { /* PR = 1 */ - n = n & 14; - m = m & 14; - if (FP_RFD(n) == FP_RFD(m)) - m_sr |= T; - else - m_sr &= ~T; - } else { /* PR = 0 */ - if (FP_RFS(n) == FP_RFS(m)) - m_sr |= T; - else - m_sr &= ~T; - } -} - -/* FCMP/GT FRm,FRn PR=0 1111nnnnmmmm0101 */ -/* FCMP/GT DRm,DRn PR=1 1111nnn0mmm00101 */ -inline void sh34_base_device::FCMP_GT(const uint16_t opcode) -{ - uint32_t m = Rm; uint32_t n = Rn; - - if (m_fpu_pr) { /* PR = 1 */ - n = n & 14; - m = m & 14; - if (FP_RFD(n) > FP_RFD(m)) - m_sr |= T; - else - m_sr &= ~T; - } else { /* PR = 0 */ - if (FP_RFS(n) > FP_RFS(m)) - m_sr |= T; - else - m_sr &= ~T; - } -} - -/* FCNVDS DRm,FPUL PR=1 1111mmm010111101 */ -inline void sh34_base_device::FCNVDS(const uint16_t opcode) -{ - uint32_t n = Rn; - - if (m_fpu_pr) { /* PR = 1 */ - n = n & 14; - if (m_fpscr & RM) - m_fr[n | NATIVE_ENDIAN_VALUE_LE_BE(0,1)] &= 0xe0000000; /* round toward zero*/ - *((float *)&m_fpul) = (float)FP_RFD(n); - } -} - -/* FCNVSD FPUL, DRn PR=1 1111nnn010101101 */ -inline void sh34_base_device::FCNVSD(const uint16_t opcode) -{ - uint32_t n = Rn; - - if (m_fpu_pr) { /* PR = 1 */ - n = n & 14; - FP_RFD(n) = (double)*((float *)&m_fpul); - } -} - -/* FADD FRm,FRn PR=0 1111nnnnmmmm0000 */ -/* FADD DRm,DRn PR=1 1111nnn0mmm00000 */ -inline void sh34_base_device::FADD(const uint16_t opcode) -{ - uint32_t m = Rm; uint32_t n = Rn; - - if (m_fpu_pr) { /* PR = 1 */ - n = n & 14; - m = m & 14; - FP_RFD(n) = FP_RFD(n) + FP_RFD(m); - } else { /* PR = 0 */ - FP_RFS(n) = FP_RFS(n) + FP_RFS(m); - } -} - -/* FSUB FRm,FRn PR=0 1111nnnnmmmm0001 */ -/* FSUB DRm,DRn PR=1 1111nnn0mmm00001 */ -inline void sh34_base_device::FSUB(const uint16_t opcode) -{ - uint32_t m = Rm; uint32_t n = Rn; - - if (m_fpu_pr) { /* PR = 1 */ - n = n & 14; - m = m & 14; - FP_RFD(n) = FP_RFD(n) - FP_RFD(m); - } else { /* PR = 0 */ - FP_RFS(n) = FP_RFS(n) - FP_RFS(m); - } -} - - -/* FMUL FRm,FRn PR=0 1111nnnnmmmm0010 */ -/* FMUL DRm,DRn PR=1 1111nnn0mmm00010 */ -inline void sh34_base_device::FMUL(const uint16_t opcode) -{ - uint32_t m = Rm; uint32_t n = Rn; - - if (m_fpu_pr) { /* PR = 1 */ - n = n & 14; - m = m & 14; - FP_RFD(n) = FP_RFD(n) * FP_RFD(m); - } else { /* PR = 0 */ - FP_RFS(n) = FP_RFS(n) * FP_RFS(m); - } -} - -/* FDIV FRm,FRn PR=0 1111nnnnmmmm0011 */ -/* FDIV DRm,DRn PR=1 1111nnn0mmm00011 */ -inline void sh34_base_device::FDIV(const uint16_t opcode) -{ - uint32_t m = Rm; uint32_t n = Rn; - - if (m_fpu_pr) { /* PR = 1 */ - n = n & 14; - m = m & 14; - if (FP_RFD(m) == 0) - return; - FP_RFD(n) = FP_RFD(n) / FP_RFD(m); - } else { /* PR = 0 */ - if (FP_RFS(m) == 0) - return; - FP_RFS(n) = FP_RFS(n) / FP_RFS(m); - } -} - -/* FMAC FR0,FRm,FRn PR=0 1111nnnnmmmm1110 */ -inline void sh34_base_device::FMAC(const uint16_t opcode) -{ - uint32_t m = Rm; uint32_t n = Rn; - - if (m_fpu_pr == 0) { /* PR = 0 */ - FP_RFS(n) = (FP_RFS(0) * FP_RFS(m)) + FP_RFS(n); - } -} - -/* FSQRT FRn PR=0 1111nnnn01101101 */ -/* FSQRT DRn PR=1 1111nnnn01101101 */ -inline void sh34_base_device::FSQRT(const uint16_t opcode) -{ - uint32_t n = Rn; - - if (m_fpu_pr) { /* PR = 1 */ - n = n & 14; - if (FP_RFD(n) < 0) - return; - FP_RFD(n) = sqrtf(FP_RFD(n)); - } else { /* PR = 0 */ - if (FP_RFS(n) < 0) - return; - FP_RFS(n) = sqrtf(FP_RFS(n)); - } -} - -/* FSRRA FRn PR=0 1111nnnn01111101 */ -inline void sh34_base_device::FSRRA(const uint16_t opcode) -{ - uint32_t n = Rn; - - if (FP_RFS(n) < 0) - return; - FP_RFS(n) = 1.0f / sqrtf(FP_RFS(n)); -} - -/* FSSCA FPUL,FRn PR=0 1111nnn011111101 */ -void sh34_base_device::FSSCA(const uint16_t opcode) -{ - uint32_t n = Rn; - - float angle; - - angle = (((float)(m_fpul & 0xFFFF)) / 65536.0f) * 2.0f * (float) M_PI; - FP_RFS(n) = sinf(angle); - FP_RFS(n+1) = cosf(angle); -} - -/* FIPR FVm,FVn PR=0 1111nnmm11101101 */ -inline void sh34_base_device::FIPR(const uint16_t opcode) -{ - uint32_t n = Rn; - -uint32_t m; -float ml[4]; -int a; - - m = (n & 3) << 2; - n = n & 12; - for (a = 0;a < 4;a++) - ml[a] = FP_RFS(n+a) * FP_RFS(m+a); - FP_RFS(n+3) = ml[0] + ml[1] + ml[2] + ml[3]; -} - -/* FTRV XMTRX,FVn PR=0 1111nn0111111101 */ -void sh34_base_device::FTRV(const uint16_t opcode) -{ - uint32_t n = Rn; - -int i,j; -float sum[4]; - - n = n & 12; - for (i = 0;i < 4;i++) { - sum[i] = 0; - for (j=0;j < 4;j++) - sum[i] += FP_XFS((j << 2) + i)*FP_RFS(n + j); - } - for (i = 0;i < 4;i++) - FP_RFS(n + i) = sum[i]; -} - -inline void sh34_base_device::op1111_0xf13(const uint16_t opcode) -{ - if (opcode & 0x100) { - if (opcode & 0x200) { - switch (opcode & 0xC00) - { - case 0x000: - FSCHG(); - break; - case 0x800: - FRCHG(); - break; - default: - machine().debug_break(); - break; - } - } else { - FTRV(opcode); - } - } else { - FSSCA(opcode); - } -} - -void sh34_base_device::dbreak(const uint16_t opcode) -{ - machine().debug_break(); -} - - -inline void sh34_base_device::op1111_0x13(uint16_t opcode) -{ - switch((opcode >> 4) & 0x0f) - { - case 0x00: FSTS(opcode); break; - case 0x01: FLDS(opcode); break; - case 0x02: FLOAT(opcode); break; - case 0x03: FTRC(opcode); break; - case 0x04: FNEG(opcode); break; - case 0x05: FABS(opcode); break; - case 0x06: FSQRT(opcode); break; - case 0x07: FSRRA(opcode); break; - case 0x08: FLDI0(opcode); break; - case 0x09: FLDI1(opcode); break; - case 0x0a: FCNVSD(opcode); break; - case 0x0b: FCNVDS(opcode); break; - case 0x0c: dbreak(opcode); break; - case 0x0d: dbreak(opcode); break; - case 0x0e: FIPR(opcode); break; - case 0x0f: op1111_0xf13(opcode); break; - } -} - - -/***************************************************************************** - * MAME CPU INTERFACE - *****************************************************************************/ - -void sh34_base_device::device_reset() -{ - m_spc = 0; - m_pr = 0; - m_sr = 0; - m_ssr = 0; - m_gbr = 0; - m_vbr = 0; - m_mach = 0; - m_macl = 0; - memset(m_r, 0, sizeof(m_r)); - memset(m_rbnk, 0, sizeof(m_rbnk)); - m_sgr = 0; - memset(m_fr, 0, sizeof(m_fr)); - memset(m_xf, 0, sizeof(m_xf)); - m_ea = 0; - m_delay = 0; - m_cpu_off = 0; - m_pending_irq = 0; - m_test_irq = 0; - memset(m_exception_priority, 0, sizeof(m_exception_priority)); - memset(m_exception_requesting, 0, sizeof(m_exception_requesting)); - memset(m_m, 0, sizeof(m_m)); - memset(m_sh3internal_upper, 0, sizeof(m_sh3internal_upper)); - memset(m_sh3internal_lower, 0, sizeof(m_sh3internal_lower)); - memset(m_irq_line_state, 0, sizeof(m_irq_line_state)); - m_SH4_TSTR = 0; - m_SH4_TCNT0 = 0; - m_SH4_TCNT1 = 0; - m_SH4_TCNT2 = 0; - m_SH4_TCR0 = 0; - m_SH4_TCR1 = 0; - m_SH4_TCR2 = 0; - m_SH4_TCOR0 = 0; - m_SH4_TCOR1 = 0; - m_SH4_TCOR2 = 0; - m_SH4_TOCR = 0; - m_SH4_TCPR2 = 0; - m_SH4_IPRA = 0; - m_SH4_IPRC = 0; - m_SH4_SAR0 = 0; - m_SH4_SAR1 = 0; - m_SH4_SAR2 = 0; - m_SH4_SAR3 = 0; - m_SH4_DAR0 = 0; - m_SH4_DAR1 = 0; - m_SH4_DAR2 = 0; - m_SH4_DAR3 = 0; - m_SH4_CHCR0 = 0; - m_SH4_CHCR1 = 0; - m_SH4_CHCR2 = 0; - m_SH4_CHCR3 = 0; - m_SH4_DMATCR0 = 0; - m_SH4_DMATCR1 = 0; - m_SH4_DMATCR2 = 0; - m_SH4_DMATCR3 = 0; - m_SH4_DMAOR = 0; - m_nmi_line_state = 0; - m_frt_input = 0; - m_internal_irq_vector = 0; - m_refresh_timer_base = 0; - memset(m_dma_timer_active, 0, sizeof(m_dma_timer_active)); - memset(m_dma_source, 0, sizeof(m_dma_source)); - memset(m_dma_destination, 0, sizeof(m_dma_destination)); - memset(m_dma_count, 0, sizeof(m_dma_count)); - memset(m_dma_wordsize, 0, sizeof(m_dma_wordsize)); - memset(m_dma_source_increment, 0, sizeof(m_dma_source_increment)); - memset(m_dma_destination_increment, 0, sizeof(m_dma_destination_increment)); - memset(m_dma_mode, 0, sizeof(m_dma_mode)); - m_ioport16_pullup = 0; - m_ioport16_direction = 0; - m_ioport4_pullup = 0; - m_ioport4_direction = 0; - - sh4_default_exception_priorities(); - - m_rtc_timer->adjust(attotime::from_hz(128)); - - m_pc = 0xa0000000; - m_ppc = m_pc & AM; - m_r[15] = RL(4); - m_sr = 0x700000f0; - m_fpscr = 0x00040001; - m_fpu_sz = (m_fpscr & SZ) ? 1 : 0; - m_fpu_pr = (m_fpscr & PR) ? 1 : 0; - m_fpul = 0; - m_dbr = 0; - - m_internal_irq_level = -1; - m_irln = 15; - m_sleep_mode = 0; - - m_sh4_mmu_enabled = 0; -} - -/*------------------------------------------------- - sh3_reset - reset the processor --------------------------------------------------*/ - -void sh3_base_device::device_reset() -{ - sh34_base_device::device_reset(); - - m_SH4_TCOR0 = 0xffffffff; - m_SH4_TCNT0 = 0xffffffff; - m_SH4_TCOR1 = 0xffffffff; - m_SH4_TCNT1 = 0xffffffff; - m_SH4_TCOR2 = 0xffffffff; - m_SH4_TCNT2 = 0xffffffff; -} - -void sh4_base_device::device_reset() -{ - sh34_base_device::device_reset(); - - m_m[RCR2] = 0x09; - m_SH4_TCOR0 = 0xffffffff; - m_SH4_TCNT0 = 0xffffffff; - m_SH4_TCOR1 = 0xffffffff; - m_SH4_TCNT1 = 0xffffffff; - m_SH4_TCOR2 = 0xffffffff; - m_SH4_TCNT2 = 0xffffffff; -} - -inline void sh34_base_device::execute_one_0000(const uint16_t opcode) -{ - switch(opcode & 0xff) - { - // 0x00 - case 0x00: NOP(opcode); break; - case 0x10: NOP(opcode); break; - case 0x20: NOP(opcode); break; - case 0x30: NOP(opcode); break; - case 0x40: NOP(opcode); break; - case 0x50: NOP(opcode); break; - case 0x60: NOP(opcode); break; - case 0x70: NOP(opcode); break; - case 0x80: NOP(opcode); break; - case 0x90: NOP(opcode); break; - case 0xa0: NOP(opcode); break; - case 0xb0: NOP(opcode); break; - case 0xc0: NOP(opcode); break; - case 0xd0: NOP(opcode); break; - case 0xe0: NOP(opcode); break; - case 0xf0: NOP(opcode); break; - // 0x10 - case 0x01: NOP(opcode); break; - case 0x11: NOP(opcode); break; - case 0x21: NOP(opcode); break; - case 0x31: NOP(opcode); break; - case 0x41: NOP(opcode); break; - case 0x51: NOP(opcode); break; - case 0x61: NOP(opcode); break; - case 0x71: NOP(opcode); break; - case 0x81: NOP(opcode); break; - case 0x91: NOP(opcode); break; - case 0xa1: NOP(opcode); break; - case 0xb1: NOP(opcode); break; - case 0xc1: NOP(opcode); break; - case 0xd1: NOP(opcode); break; - case 0xe1: NOP(opcode); break; - case 0xf1: NOP(opcode); break; - // 0x20 - case 0x02: STCSR(opcode); break; - case 0x12: STCGBR(opcode); break; - case 0x22: STCVBR(opcode); break; - case 0x32: STCSSR(opcode); break; - case 0x42: STCSPC(opcode); break; - case 0x52: NOP(opcode); break; - case 0x62: NOP(opcode); break; - case 0x72: NOP(opcode); break; - case 0x82: STCRBANK(opcode); break; - case 0x92: STCRBANK(opcode); break; - case 0xa2: STCRBANK(opcode); break; - case 0xb2: STCRBANK(opcode); break; - case 0xc2: STCRBANK(opcode); break; - case 0xd2: STCRBANK(opcode); break; - case 0xe2: STCRBANK(opcode); break; - case 0xf2: STCRBANK(opcode); break; - // 0x30 - case 0x03: BSRF(opcode); break; - case 0x13: NOP(opcode); break; - case 0x23: BRAF(opcode); break; - case 0x33: NOP(opcode); break; - case 0x43: NOP(opcode); break; - case 0x53: NOP(opcode); break; - case 0x63: NOP(opcode); break; - case 0x73: NOP(opcode); break; - case 0x83: PREFM(opcode); break; - case 0x93: TODO(opcode); break; - case 0xa3: TODO(opcode); break; - case 0xb3: TODO(opcode); break; - case 0xc3: MOVCAL(opcode); break; - case 0xd3: NOP(opcode); break; - case 0xe3: NOP(opcode); break; - case 0xf3: NOP(opcode); break; - // 0x40 - case 0x04: MOVBS0(opcode); break; - case 0x14: MOVBS0(opcode); break; - case 0x24: MOVBS0(opcode); break; - case 0x34: MOVBS0(opcode); break; - case 0x44: MOVBS0(opcode); break; - case 0x54: MOVBS0(opcode); break; - case 0x64: MOVBS0(opcode); break; - case 0x74: MOVBS0(opcode); break; - case 0x84: MOVBS0(opcode); break; - case 0x94: MOVBS0(opcode); break; - case 0xa4: MOVBS0(opcode); break; - case 0xb4: MOVBS0(opcode); break; - case 0xc4: MOVBS0(opcode); break; - case 0xd4: MOVBS0(opcode); break; - case 0xe4: MOVBS0(opcode); break; - case 0xf4: MOVBS0(opcode); break; - // 0x50 - case 0x05: MOVWS0(opcode); break; - case 0x15: MOVWS0(opcode); break; - case 0x25: MOVWS0(opcode); break; - case 0x35: MOVWS0(opcode); break; - case 0x45: MOVWS0(opcode); break; - case 0x55: MOVWS0(opcode); break; - case 0x65: MOVWS0(opcode); break; - case 0x75: MOVWS0(opcode); break; - case 0x85: MOVWS0(opcode); break; - case 0x95: MOVWS0(opcode); break; - case 0xa5: MOVWS0(opcode); break; - case 0xb5: MOVWS0(opcode); break; - case 0xc5: MOVWS0(opcode); break; - case 0xd5: MOVWS0(opcode); break; - case 0xe5: MOVWS0(opcode); break; - case 0xf5: MOVWS0(opcode); break; - // 0x60 - case 0x06: MOVLS0(opcode); break; - case 0x16: MOVLS0(opcode); break; - case 0x26: MOVLS0(opcode); break; - case 0x36: MOVLS0(opcode); break; - case 0x46: MOVLS0(opcode); break; - case 0x56: MOVLS0(opcode); break; - case 0x66: MOVLS0(opcode); break; - case 0x76: MOVLS0(opcode); break; - case 0x86: MOVLS0(opcode); break; - case 0x96: MOVLS0(opcode); break; - case 0xa6: MOVLS0(opcode); break; - case 0xb6: MOVLS0(opcode); break; - case 0xc6: MOVLS0(opcode); break; - case 0xd6: MOVLS0(opcode); break; - case 0xe6: MOVLS0(opcode); break; - case 0xf6: MOVLS0(opcode); break; - // 0x70 - case 0x07: MULL(opcode); break; - case 0x17: MULL(opcode); break; - case 0x27: MULL(opcode); break; - case 0x37: MULL(opcode); break; - case 0x47: MULL(opcode); break; - case 0x57: MULL(opcode); break; - case 0x67: MULL(opcode); break; - case 0x77: MULL(opcode); break; - case 0x87: MULL(opcode); break; - case 0x97: MULL(opcode); break; - case 0xa7: MULL(opcode); break; - case 0xb7: MULL(opcode); break; - case 0xc7: MULL(opcode); break; - case 0xd7: MULL(opcode); break; - case 0xe7: MULL(opcode); break; - case 0xf7: MULL(opcode); break; - // 0x80 - case 0x08: CLRT(opcode); break; - case 0x18: SETT(opcode); break; - case 0x28: CLRMAC(opcode); break; - case 0x38: LDTLB(opcode); break; - case 0x48: CLRS(opcode); break; - case 0x58: SETS(opcode); break; - case 0x68: NOP(opcode); break; - case 0x78: NOP(opcode); break; - case 0x88: CLRT(opcode); break; - case 0x98: SETT(opcode); break; - case 0xa8: CLRMAC(opcode); break; - case 0xb8: LDTLB(opcode); break; - case 0xc8: CLRS(opcode); break; - case 0xd8: SETS(opcode); break; - case 0xe8: NOP(opcode); break; - case 0xf8: NOP(opcode); break; - // 0x90 - case 0x09: NOP(opcode); break; - case 0x19: DIV0U(opcode); break; - case 0x29: MOVT(opcode); break; - case 0x39: NOP(opcode); break; - case 0x49: NOP(opcode); break; - case 0x59: DIV0U(opcode); break; - case 0x69: MOVT(opcode); break; - case 0x79: NOP(opcode); break; - case 0x89: NOP(opcode); break; - case 0x99: DIV0U(opcode); break; - case 0xa9: MOVT(opcode); break; - case 0xb9: NOP(opcode); break; - case 0xc9: NOP(opcode); break; - case 0xd9: DIV0U(opcode); break; - case 0xe9: MOVT(opcode); break; - case 0xf9: NOP(opcode); break; - // 0xa0 - case 0x0a: STSMACH(opcode); break; - case 0x1a: STSMACL(opcode); break; - case 0x2a: STSPR(opcode); break; - case 0x3a: STCSGR(opcode); break; - case 0x4a: NOP(opcode); break; - case 0x5a: STSFPUL(opcode); break; - case 0x6a: STSFPSCR(opcode); break; - case 0x7a: STCDBR(opcode); break; - case 0x8a: STSMACH(opcode); break; - case 0x9a: STSMACL(opcode); break; - case 0xaa: STSPR(opcode); break; - case 0xba: STCSGR(opcode); break; - case 0xca: NOP(opcode); break; - case 0xda: STSFPUL(opcode); break; - case 0xea: STSFPSCR(opcode); break; - case 0xfa: STCDBR(opcode); break; - // 0xb0 - case 0x0b: RTS(opcode); break; - case 0x1b: SLEEP(opcode); break; - case 0x2b: RTE(opcode); break; - case 0x3b: NOP(opcode); break; - case 0x4b: RTS(opcode); break; - case 0x5b: SLEEP(opcode); break; - case 0x6b: RTE(opcode); break; - case 0x7b: NOP(opcode); break; - case 0x8b: RTS(opcode); break; - case 0x9b: SLEEP(opcode); break; - case 0xab: RTE(opcode); break; - case 0xbb: NOP(opcode); break; - case 0xcb: RTS(opcode); break; - case 0xdb: SLEEP(opcode); break; - case 0xeb: RTE(opcode); break; - case 0xfb: NOP(opcode); break; - // 0xc0 - case 0x0c: MOVBL0(opcode); break; - case 0x1c: MOVBL0(opcode); break; - case 0x2c: MOVBL0(opcode); break; - case 0x3c: MOVBL0(opcode); break; - case 0x4c: MOVBL0(opcode); break; - case 0x5c: MOVBL0(opcode); break; - case 0x6c: MOVBL0(opcode); break; - case 0x7c: MOVBL0(opcode); break; - case 0x8c: MOVBL0(opcode); break; - case 0x9c: MOVBL0(opcode); break; - case 0xac: MOVBL0(opcode); break; - case 0xbc: MOVBL0(opcode); break; - case 0xcc: MOVBL0(opcode); break; - case 0xdc: MOVBL0(opcode); break; - case 0xec: MOVBL0(opcode); break; - case 0xfc: MOVBL0(opcode); break; - // 0xd0 - case 0x0d: MOVWL0(opcode); break; - case 0x1d: MOVWL0(opcode); break; - case 0x2d: MOVWL0(opcode); break; - case 0x3d: MOVWL0(opcode); break; - case 0x4d: MOVWL0(opcode); break; - case 0x5d: MOVWL0(opcode); break; - case 0x6d: MOVWL0(opcode); break; - case 0x7d: MOVWL0(opcode); break; - case 0x8d: MOVWL0(opcode); break; - case 0x9d: MOVWL0(opcode); break; - case 0xad: MOVWL0(opcode); break; - case 0xbd: MOVWL0(opcode); break; - case 0xcd: MOVWL0(opcode); break; - case 0xdd: MOVWL0(opcode); break; - case 0xed: MOVWL0(opcode); break; - case 0xfd: MOVWL0(opcode); break; - // 0xe0 - case 0x0e: MOVLL0(opcode); break; - case 0x1e: MOVLL0(opcode); break; - case 0x2e: MOVLL0(opcode); break; - case 0x3e: MOVLL0(opcode); break; - case 0x4e: MOVLL0(opcode); break; - case 0x5e: MOVLL0(opcode); break; - case 0x6e: MOVLL0(opcode); break; - case 0x7e: MOVLL0(opcode); break; - case 0x8e: MOVLL0(opcode); break; - case 0x9e: MOVLL0(opcode); break; - case 0xae: MOVLL0(opcode); break; - case 0xbe: MOVLL0(opcode); break; - case 0xce: MOVLL0(opcode); break; - case 0xde: MOVLL0(opcode); break; - case 0xee: MOVLL0(opcode); break; - case 0xfe: MOVLL0(opcode); break; - // 0xf0 - case 0x0f: MAC_L(opcode); break; - case 0x1f: MAC_L(opcode); break; - case 0x2f: MAC_L(opcode); break; - case 0x3f: MAC_L(opcode); break; - case 0x4f: MAC_L(opcode); break; - case 0x5f: MAC_L(opcode); break; - case 0x6f: MAC_L(opcode); break; - case 0x7f: MAC_L(opcode); break; - case 0x8f: MAC_L(opcode); break; - case 0x9f: MAC_L(opcode); break; - case 0xaf: MAC_L(opcode); break; - case 0xbf: MAC_L(opcode); break; - case 0xcf: MAC_L(opcode); break; - case 0xdf: MAC_L(opcode); break; - case 0xef: MAC_L(opcode); break; - case 0xff: MAC_L(opcode); break; - } -} - -inline void sh34_base_device::execute_one_4000(const uint16_t opcode) -{ - switch(opcode & 0xff) - { - // 0x00 - case 0x00: SHLL(opcode); break; - case 0x10: DT(opcode); break; - case 0x20: SHAL(opcode); break; - case 0x30: NOP(opcode); break; - case 0x40: SHLL(opcode); break; - case 0x50: DT(opcode); break; - case 0x60: SHAL(opcode); break; - case 0x70: NOP(opcode); break; - case 0x80: SHLL(opcode); break; - case 0x90: DT(opcode); break; - case 0xa0: SHAL(opcode); break; - case 0xb0: NOP(opcode); break; - case 0xc0: SHLL(opcode); break; - case 0xd0: DT(opcode); break; - case 0xe0: SHAL(opcode); break; - case 0xf0: NOP(opcode); break; - // 0x10 - case 0x01: SHLR(opcode); break; - case 0x11: CMPPZ(opcode); break; - case 0x21: SHAR(opcode); break; - case 0x31: NOP(opcode); break; - case 0x41: SHLR(opcode); break; - case 0x51: CMPPZ(opcode); break; - case 0x61: SHAR(opcode); break; - case 0x71: NOP(opcode); break; - case 0x81: SHLR(opcode); break; - case 0x91: CMPPZ(opcode); break; - case 0xa1: SHAR(opcode); break; - case 0xb1: NOP(opcode); break; - case 0xc1: SHLR(opcode); break; - case 0xd1: CMPPZ(opcode); break; - case 0xe1: SHAR(opcode); break; - case 0xf1: NOP(opcode); break; - // 0x20 - case 0x02: STSMMACH(opcode); break; - case 0x12: STSMMACL(opcode); break; - case 0x22: STSMPR(opcode); break; - case 0x32: STCMSGR(opcode); break; - case 0x42: NOP(opcode); break; - case 0x52: STSMFPUL(opcode); break; - case 0x62: STSMFPSCR(opcode); break; - case 0x72: NOP(opcode); break; - case 0x82: NOP(opcode); break; - case 0x92: NOP(opcode); break; - case 0xa2: NOP(opcode); break; - case 0xb2: NOP(opcode); break; - case 0xc2: NOP(opcode); break; - case 0xd2: NOP(opcode); break; - case 0xe2: NOP(opcode); break; - case 0xf2: STCMDBR(opcode); break; - // 0x30 - case 0x03: STCMSR(opcode); break; - case 0x13: STCMGBR(opcode); break; - case 0x23: STCMVBR(opcode); break; - case 0x33: STCMSSR(opcode); break; - case 0x43: STCMSPC(opcode); break; - case 0x53: NOP(opcode); break; - case 0x63: NOP(opcode); break; - case 0x73: NOP(opcode); break; - case 0x83: STCMRBANK(opcode); break; - case 0x93: STCMRBANK(opcode); break; - case 0xa3: STCMRBANK(opcode); break; - case 0xb3: STCMRBANK(opcode); break; - case 0xc3: STCMRBANK(opcode); break; - case 0xd3: STCMRBANK(opcode); break; - case 0xe3: STCMRBANK(opcode); break; - case 0xf3: STCMRBANK(opcode); break; - // 0x40 - case 0x04: ROTL(opcode); break; - case 0x14: NOP(opcode); break; - case 0x24: ROTCL(opcode); break; - case 0x34: NOP(opcode); break; - case 0x44: ROTL(opcode); break; - case 0x54: NOP(opcode); break; - case 0x64: ROTCL(opcode); break; - case 0x74: NOP(opcode); break; - case 0x84: ROTL(opcode); break; - case 0x94: NOP(opcode); break; - case 0xa4: ROTCL(opcode); break; - case 0xb4: NOP(opcode); break; - case 0xc4: ROTL(opcode); break; - case 0xd4: NOP(opcode); break; - case 0xe4: ROTCL(opcode); break; - case 0xf4: NOP(opcode); break; - // 0x50 - case 0x05: ROTR(opcode); break; - case 0x15: CMPPL(opcode); break; - case 0x25: ROTCR(opcode); break; - case 0x35: NOP(opcode); break; - case 0x45: ROTR(opcode); break; - case 0x55: CMPPL(opcode); break; - case 0x65: ROTCR(opcode); break; - case 0x75: NOP(opcode); break; - case 0x85: ROTR(opcode); break; - case 0x95: CMPPL(opcode); break; - case 0xa5: ROTCR(opcode); break; - case 0xb5: NOP(opcode); break; - case 0xc5: ROTR(opcode); break; - case 0xd5: CMPPL(opcode); break; - case 0xe5: ROTCR(opcode); break; - case 0xf5: NOP(opcode); break; - // 0x60 - case 0x06: LDSMMACH(opcode); break; - case 0x16: LDSMMACL(opcode); break; - case 0x26: LDSMPR(opcode); break; - case 0x36: NOP(opcode); break; - case 0x46: NOP(opcode); break; - case 0x56: LDSMFPUL(opcode); break; - case 0x66: LDSMFPSCR(opcode); break; - case 0x76: NOP(opcode); break; - case 0x86: NOP(opcode); break; - case 0x96: NOP(opcode); break; - case 0xa6: NOP(opcode); break; - case 0xb6: NOP(opcode); break; - case 0xc6: NOP(opcode); break; - case 0xd6: NOP(opcode); break; - case 0xe6: NOP(opcode); break; - case 0xf6: LDCMDBR(opcode); break; - // 0x70 - case 0x07: LDCMSR(opcode); break; - case 0x17: LDCMGBR(opcode); break; - case 0x27: LDCMVBR(opcode); break; - case 0x37: LDCMSSR(opcode); break; - case 0x47: LDCMSPC(opcode); break; - case 0x57: NOP(opcode); break; - case 0x67: NOP(opcode); break; - case 0x77: NOP(opcode); break; - case 0x87: LDCMRBANK(opcode); break; - case 0x97: LDCMRBANK(opcode); break; - case 0xa7: LDCMRBANK(opcode); break; - case 0xb7: LDCMRBANK(opcode); break; - case 0xc7: LDCMRBANK(opcode); break; - case 0xd7: LDCMRBANK(opcode); break; - case 0xe7: LDCMRBANK(opcode); break; - case 0xf7: LDCMRBANK(opcode); break; - // 0x80 - case 0x08: SHLL2(opcode); break; - case 0x18: SHLL8(opcode); break; - case 0x28: SHLL16(opcode); break; - case 0x38: NOP(opcode); break; - case 0x48: SHLL2(opcode); break; - case 0x58: SHLL8(opcode); break; - case 0x68: SHLL16(opcode); break; - case 0x78: NOP(opcode); break; - case 0x88: SHLL2(opcode); break; - case 0x98: SHLL8(opcode); break; - case 0xa8: SHLL16(opcode); break; - case 0xb8: NOP(opcode); break; - case 0xc8: SHLL2(opcode); break; - case 0xd8: SHLL8(opcode); break; - case 0xe8: SHLL16(opcode); break; - case 0xf8: NOP(opcode); break; - // 0x90 - case 0x09: SHLR2(opcode); break; - case 0x19: SHLR8(opcode); break; - case 0x29: SHLR16(opcode); break; - case 0x39: NOP(opcode); break; - case 0x49: SHLR2(opcode); break; - case 0x59: SHLR8(opcode); break; - case 0x69: SHLR16(opcode); break; - case 0x79: NOP(opcode); break; - case 0x89: SHLR2(opcode); break; - case 0x99: SHLR8(opcode); break; - case 0xa9: SHLR16(opcode); break; - case 0xb9: NOP(opcode); break; - case 0xc9: SHLR2(opcode); break; - case 0xd9: SHLR8(opcode); break; - case 0xe9: SHLR16(opcode); break; - case 0xf9: NOP(opcode); break; - // 0xa0 - case 0x0a: LDSMACH(opcode); break; - case 0x1a: LDSMACL(opcode); break; - case 0x2a: LDSPR(opcode); break; - case 0x3a: NOP(opcode); break; - case 0x4a: NOP(opcode); break; - case 0x5a: LDSFPUL(opcode); break; - case 0x6a: LDSFPSCR(opcode); break; - case 0x7a: NOP(opcode); break; - case 0x8a: NOP(opcode); break; - case 0x9a: NOP(opcode); break; - case 0xaa: NOP(opcode); break; - case 0xba: NOP(opcode); break; - case 0xca: NOP(opcode); break; - case 0xda: NOP(opcode); break; - case 0xea: NOP(opcode); break; - case 0xfa: LDCDBR(opcode); break; - // 0xb0 - case 0x0b: JSR(opcode); break; - case 0x1b: TAS(opcode); break; - case 0x2b: JMP(opcode); break; - case 0x3b: NOP(opcode); break; - case 0x4b: JSR(opcode); break; - case 0x5b: TAS(opcode); break; - case 0x6b: JMP(opcode); break; - case 0x7b: NOP(opcode); break; - case 0x8b: JSR(opcode); break; - case 0x9b: TAS(opcode); break; - case 0xab: JMP(opcode); break; - case 0xbb: NOP(opcode); break; - case 0xcb: JSR(opcode); break; - case 0xdb: TAS(opcode); break; - case 0xeb: JMP(opcode); break; - case 0xfb: NOP(opcode); break; - // 0xc0 - case 0x0c: SHAD(opcode); break; - case 0x1c: SHAD(opcode); break; - case 0x2c: SHAD(opcode); break; - case 0x3c: SHAD(opcode); break; - case 0x4c: SHAD(opcode); break; - case 0x5c: SHAD(opcode); break; - case 0x6c: SHAD(opcode); break; - case 0x7c: SHAD(opcode); break; - case 0x8c: SHAD(opcode); break; - case 0x9c: SHAD(opcode); break; - case 0xac: SHAD(opcode); break; - case 0xbc: SHAD(opcode); break; - case 0xcc: SHAD(opcode); break; - case 0xdc: SHAD(opcode); break; - case 0xec: SHAD(opcode); break; - case 0xfc: SHAD(opcode); break; - // 0xd0 - case 0x0d: SHLD(opcode); break; - case 0x1d: SHLD(opcode); break; - case 0x2d: SHLD(opcode); break; - case 0x3d: SHLD(opcode); break; - case 0x4d: SHLD(opcode); break; - case 0x5d: SHLD(opcode); break; - case 0x6d: SHLD(opcode); break; - case 0x7d: SHLD(opcode); break; - case 0x8d: SHLD(opcode); break; - case 0x9d: SHLD(opcode); break; - case 0xad: SHLD(opcode); break; - case 0xbd: SHLD(opcode); break; - case 0xcd: SHLD(opcode); break; - case 0xdd: SHLD(opcode); break; - case 0xed: SHLD(opcode); break; - case 0xfd: SHLD(opcode); break; - // 0xe0 - case 0x0e: LDCSR(opcode); break; - case 0x1e: LDCGBR(opcode); break; - case 0x2e: LDCVBR(opcode); break; - case 0x3e: LDCSSR(opcode); break; - case 0x4e: LDCSPC(opcode); break; - case 0x5e: NOP(opcode); break; - case 0x6e: NOP(opcode); break; - case 0x7e: NOP(opcode); break; - case 0x8e: LDCRBANK(opcode); break; - case 0x9e: LDCRBANK(opcode); break; - case 0xae: LDCRBANK(opcode); break; - case 0xbe: LDCRBANK(opcode); break; - case 0xce: LDCRBANK(opcode); break; - case 0xde: LDCRBANK(opcode); break; - case 0xee: LDCRBANK(opcode); break; - case 0xfe: LDCRBANK(opcode); break; - // 0xf0 - case 0x0f: MAC_W(opcode); break; - case 0x1f: MAC_W(opcode); break; - case 0x2f: MAC_W(opcode); break; - case 0x3f: MAC_W(opcode); break; - case 0x4f: MAC_W(opcode); break; - case 0x5f: MAC_W(opcode); break; - case 0x6f: MAC_W(opcode); break; - case 0x7f: MAC_W(opcode); break; - case 0x8f: MAC_W(opcode); break; - case 0x9f: MAC_W(opcode); break; - case 0xaf: MAC_W(opcode); break; - case 0xbf: MAC_W(opcode); break; - case 0xcf: MAC_W(opcode); break; - case 0xdf: MAC_W(opcode); break; - case 0xef: MAC_W(opcode); break; - case 0xff: MAC_W(opcode); break; - } -} - - -inline void sh34_base_device::execute_one(const uint16_t opcode) -{ - switch(opcode & 0xf000) - { - case 0x0000: - execute_one_0000(opcode); - break; - - case 0x1000: - MOVLS4(opcode); - break; - - case 0x2000: - switch(opcode & 0x0f) - { - case 0x00: MOVBS(opcode); break; - case 0x01: MOVWS(opcode); break; - case 0x02: MOVLS(opcode); break; - case 0x03: NOP(opcode); break; - case 0x04: MOVBM(opcode); break; - case 0x05: MOVWM(opcode); break; - case 0x06: MOVLM(opcode); break; - case 0x07: DIV0S(opcode); break; - case 0x08: TST(opcode); break; - case 0x09: AND(opcode); break; - case 0x0a: XOR(opcode); break; - case 0x0b: OR(opcode); break; - case 0x0c: CMPSTR(opcode); break; - case 0x0d: XTRCT(opcode); break; - case 0x0e: MULU(opcode); break; - case 0x0f: MULS(opcode); break; - } - break; - - case 0x3000: - switch(opcode & 0x0f) - { - case 0x00: CMPEQ(opcode); break; - case 0x01: NOP(opcode); break; - case 0x02: CMPHS(opcode); break; - case 0x03: CMPGE(opcode); break; - case 0x04: DIV1(opcode); break; - case 0x05: DMULU(opcode); break; - case 0x06: CMPHI(opcode); break; - case 0x07: CMPGT(opcode); break; - case 0x08: SUB(opcode); break; - case 0x09: NOP(opcode); break; - case 0x0a: SUBC(opcode); break; - case 0x0b: SUBV(opcode); break; - case 0x0c: ADD(opcode); break; - case 0x0d: DMULS(opcode); break; - case 0x0e: ADDC(opcode); break; - case 0x0f: ADDV(opcode); break; - } - break; - - case 0x4000: - execute_one_4000(opcode); - break; - - case 0x5000: - MOVLL4(opcode); - break; - - case 0x6000: - switch(opcode & 0x0f) - { - case 0x00: MOVBL(opcode); break; - case 0x01: MOVWL(opcode); break; - case 0x02: MOVLL(opcode); break; - case 0x03: MOV(opcode); break; - case 0x04: MOVBP(opcode); break; - case 0x05: MOVWP(opcode); break; - case 0x06: MOVLP(opcode); break; - case 0x07: NOT(opcode); break; - case 0x08: SWAPB(opcode); break; - case 0x09: SWAPW(opcode); break; - case 0x0a: NEGC(opcode); break; - case 0x0b: NEG(opcode); break; - case 0x0c: EXTUB(opcode); break; - case 0x0d: EXTUW(opcode); break; - case 0x0e: EXTSB(opcode); break; - case 0x0f: EXTSW(opcode); break; - } - break; - - case 0x7000: - ADDI(opcode); - break; - - case 0x8000: - switch((opcode >> 8) & 0x0f) - { - case 0x00: MOVBS4(opcode); break; - case 0x01: MOVWS4(opcode); break; - case 0x02: NOP(opcode); break; - case 0x03: NOP(opcode); break; - case 0x04: MOVBL4(opcode); break; - case 0x05: MOVWL4(opcode); break; - case 0x06: NOP(opcode); break; - case 0x07: NOP(opcode); break; - case 0x08: CMPIM(opcode); break; - case 0x09: BT(opcode); break; - case 0x0a: NOP(opcode); break; - case 0x0b: BF(opcode); break; - case 0x0c: NOP(opcode); break; - case 0x0d: BTS(opcode); break; - case 0x0e: NOP(opcode); break; - case 0x0f: BFS(opcode); break; - } - break; - - case 0x9000: - MOVWI(opcode); - break; - - case 0xa000: - BRA(opcode); - break; - - case 0xb000: - BSR(opcode); - break; - - case 0xc000: - switch((opcode >> 8) & 0x0f) - { - case 0x00: MOVBSG(opcode); break; - case 0x01: MOVWSG(opcode); break; - case 0x02: MOVLSG(opcode); break; - case 0x03: TRAPA(opcode); break; - case 0x04: MOVBLG(opcode); break; - case 0x05: MOVWLG(opcode); break; - case 0x06: MOVLLG(opcode); break; - case 0x07: MOVA(opcode); break; - case 0x08: TSTI(opcode); break; - case 0x09: ANDI(opcode); break; - case 0x0a: XORI(opcode); break; - case 0x0b: ORI(opcode); break; - case 0x0c: TSTM(opcode); break; - case 0x0d: ANDM(opcode); break; - case 0x0e: XORM(opcode); break; - case 0x0f: ORM(opcode); break; - } - break; - - case 0xd000: - MOVLI(opcode); - break; - - case 0xe000: - MOVI(opcode); - break; - - case 0xf000: - switch(opcode & 0x0f) - { - case 0x00: FADD(opcode); break; - case 0x01: FSUB(opcode); break; - case 0x02: FMUL(opcode); break; - case 0x03: FDIV(opcode); break; - case 0x04: FCMP_EQ(opcode); break; - case 0x05: FCMP_GT(opcode); break; - case 0x06: FMOVS0FR(opcode); break; - case 0x07: FMOVFRS0(opcode); break; - case 0x08: FMOVMRFR(opcode); break; - case 0x09: FMOVMRIFR(opcode); break; - case 0x0a: FMOVFRMR(opcode); break; - case 0x0b: FMOVFRMDR(opcode); break; - case 0x0c: FMOVFR(opcode); break; - case 0x0d: op1111_0x13(opcode); break; - case 0x0e: FMAC(opcode); break; - case 0x0f: dbreak(opcode); break; - } - break; - } -} - - -/* Execute cycles - returns number of cycles actually run */ -void sh34_base_device::execute_run() -{ - if (m_cpu_off) - { - m_sh4_icount = 0; - return; - } - - do - { - m_ppc = m_pc & AM; - debugger_instruction_hook(this, m_pc & AM); - - uint16_t opcode; - - if (!m_sh4_mmu_enabled) opcode = m_direct->read_word(m_pc & AM, WORD2_XOR_LE(0)); - else opcode = RW(m_pc); // should probably use a different function as this needs to go through the ITLB - - if (m_delay) - { - m_pc = m_delay; - m_delay = 0; - } - else - m_pc += 2; - - execute_one(opcode); - - if (m_test_irq && !m_delay) - { - sh4_check_pending_irq("mame_sh4_execute"); - } - - m_sh4_icount--; - } while( m_sh4_icount > 0 ); -} - -void sh3be_device::execute_run() -{ - if (m_cpu_off) - { - m_sh4_icount = 0; - return; - } - - do - { - m_ppc = m_pc & AM; - debugger_instruction_hook(this, m_pc & AM); - - const uint16_t opcode = m_direct->read_word(m_pc & AM, WORD_XOR_LE(6)); - - if (m_delay) - { - m_pc = m_delay; - m_delay = 0; - } - else - m_pc += 2; - - execute_one(opcode); - - if (m_test_irq && !m_delay) - { - sh4_check_pending_irq("mame_sh4_execute"); - } - - m_sh4_icount--; - } while( m_sh4_icount > 0 ); -} - -void sh4be_device::execute_run() -{ - if (m_cpu_off) - { - m_sh4_icount = 0; - return; - } - - do - { - m_ppc = m_pc & AM; - debugger_instruction_hook(this, m_pc & AM); - - const uint16_t opcode = m_direct->read_word(m_pc & AM, WORD_XOR_LE(6)); - - if (m_delay) - { - m_pc = m_delay; - m_delay = 0; - } - else - m_pc += 2; - - execute_one(opcode); - - if (m_test_irq && !m_delay) - { - sh4_check_pending_irq("mame_sh4_execute"); - } - - m_sh4_icount--; - } while( m_sh4_icount > 0 ); -} - -void sh4_base_device::device_start() -{ - sh34_base_device::device_start(); - - int i; - for (i=0;i<64;i++) - { - m_utlb[i].ASID = 0; - m_utlb[i].VPN = 0; - m_utlb[i].V = 0; - m_utlb[i].PPN = 0; - m_utlb[i].PSZ = 0; - m_utlb[i].SH = 0; - m_utlb[i].C = 0; - m_utlb[i].PPR = 0; - m_utlb[i].D = 0; - m_utlb[i].WT = 0; - m_utlb[i].SA = 0; - m_utlb[i].TC = 0; - } - - for (i=0;i<64;i++) - { - save_item(NAME(m_utlb[i].ASID), i); - save_item(NAME(m_utlb[i].VPN), i); - save_item(NAME(m_utlb[i].V), i); - save_item(NAME(m_utlb[i].PPN), i); - save_item(NAME(m_utlb[i].PSZ), i); - save_item(NAME(m_utlb[i].SH), i); - save_item(NAME(m_utlb[i].C), i); - save_item(NAME(m_utlb[i].PPR), i); - save_item(NAME(m_utlb[i].D), i); - save_item(NAME(m_utlb[i].WT), i); - save_item(NAME(m_utlb[i].SA), i); - save_item(NAME(m_utlb[i].TC), i); - } - -} - - - -void sh34_base_device::device_start() -{ - for (int i=0; i<3; i++) - { - m_timer[i] = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(sh34_base_device::sh4_timer_callback), this)); - m_timer[i]->adjust(attotime::never, i); - } - - for (int i=0; i<4; i++) - { - m_dma_timer[i] = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(sh34_base_device::sh4_dmac_callback), this)); - m_dma_timer[i]->adjust(attotime::never, i); - } - - m_refresh_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(sh34_base_device::sh4_refresh_timer_callback), this)); - m_refresh_timer->adjust(attotime::never); - m_refresh_timer_base = 0; - - m_rtc_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(sh34_base_device::sh4_rtc_timer_callback), this)); - m_rtc_timer->adjust(attotime::never); - - sh4_parse_configuration(); - - m_internal = &space(AS_PROGRAM); - m_program = &space(AS_PROGRAM); - m_io = &space(AS_IO); - m_direct = &m_program->direct(); - sh4_default_exception_priorities(); - m_irln = 15; - m_test_irq = 0; - - save_item(NAME(m_pc)); - save_item(NAME(m_r)); - save_item(NAME(m_sr)); - save_item(NAME(m_pr)); - save_item(NAME(m_gbr)); - save_item(NAME(m_vbr)); - save_item(NAME(m_mach)); - save_item(NAME(m_macl)); - save_item(NAME(m_spc)); - save_item(NAME(m_ssr)); - save_item(NAME(m_sgr)); - save_item(NAME(m_fpscr)); - save_item(NAME(m_rbnk)); - save_item(NAME(m_fr)); - save_item(NAME(m_xf)); - save_item(NAME(m_ea)); - save_item(NAME(m_delay)); - save_item(NAME(m_cpu_off)); - save_item(NAME(m_pending_irq)); - save_item(NAME(m_test_irq)); - save_item(NAME(m_fpul)); - save_item(NAME(m_dbr)); - save_item(NAME(m_exception_priority)); - save_item(NAME(m_exception_requesting)); - save_item(NAME(m_irq_line_state)); - save_item(NAME(m_m)); - save_item(NAME(m_SH4_TSTR)); - save_item(NAME(m_SH4_TCNT0)); - save_item(NAME(m_SH4_TCNT1)); - save_item(NAME(m_SH4_TCNT2)); - save_item(NAME(m_SH4_TCR0)); - save_item(NAME(m_SH4_TCR1)); - save_item(NAME(m_SH4_TCR2)); - save_item(NAME(m_SH4_TCOR0)); - save_item(NAME(m_SH4_TCOR1)); - save_item(NAME(m_SH4_TCOR2)); - save_item(NAME(m_SH4_TOCR)); - save_item(NAME(m_SH4_TCPR2)); - save_item(NAME(m_SH4_IPRA)); - save_item(NAME(m_SH4_IPRC)); - save_item(NAME(m_SH4_DAR0)); - save_item(NAME(m_SH4_DAR1)); - save_item(NAME(m_SH4_DAR2)); - save_item(NAME(m_SH4_DAR3)); - save_item(NAME(m_SH4_CHCR0)); - save_item(NAME(m_SH4_CHCR1)); - save_item(NAME(m_SH4_CHCR2)); - save_item(NAME(m_SH4_CHCR3)); - save_item(NAME(m_SH4_DMATCR0)); - save_item(NAME(m_SH4_DMATCR1)); - save_item(NAME(m_SH4_DMATCR2)); - save_item(NAME(m_SH4_DMATCR3)); - save_item(NAME(m_SH4_DMAOR)); - save_item(NAME(m_nmi_line_state)); - save_item(NAME(m_sleep_mode)); - save_item(NAME(m_frt_input)); - save_item(NAME(m_irln)); - save_item(NAME(m_internal_irq_level)); - save_item(NAME(m_internal_irq_vector)); - save_item(NAME(m_refresh_timer_base)); - save_item(NAME(m_dma_timer_active)); - save_item(NAME(m_dma_source)); - save_item(NAME(m_dma_destination)); - save_item(NAME(m_dma_count)); - save_item(NAME(m_dma_wordsize)); - save_item(NAME(m_dma_source_increment)); - save_item(NAME(m_dma_destination_increment)); - save_item(NAME(m_dma_mode)); - save_item(NAME(m_sh4_icount)); - save_item(NAME(m_fpu_sz)); - save_item(NAME(m_fpu_pr)); - save_item(NAME(m_ioport16_pullup)); - save_item(NAME( m_ioport16_direction)); - save_item(NAME(m_ioport4_pullup)); - save_item(NAME(m_ioport4_direction)); - save_item(NAME(m_sh4_mmu_enabled)); - save_item(NAME(m_sh3internal_upper)); - save_item(NAME(m_sh3internal_lower)); - - // Debugger state - - state_add(SH4_PC, "PC", m_pc).formatstr("%08X").callimport(); - state_add(SH4_SR, "SR", m_sr).formatstr("%08X").callimport(); - state_add(SH4_PR, "PR", m_pr).formatstr("%08X"); - state_add(SH4_GBR, "GBR", m_gbr).formatstr("%08X"); - state_add(SH4_VBR, "VBR", m_vbr).formatstr("%08X"); - state_add(SH4_DBR, "DBR", m_dbr).formatstr("%08X"); - state_add(SH4_MACH, "MACH", m_mach).formatstr("%08X"); - state_add(SH4_MACL, "MACL", m_macl).formatstr("%08X"); - state_add(SH4_R0, "R0", m_r[ 0]).formatstr("%08X"); - state_add(SH4_R1, "R1", m_r[ 1]).formatstr("%08X"); - state_add(SH4_R2, "R2", m_r[ 2]).formatstr("%08X"); - state_add(SH4_R3, "R3", m_r[ 3]).formatstr("%08X"); - state_add(SH4_R4, "R4", m_r[ 4]).formatstr("%08X"); - state_add(SH4_R5, "R5", m_r[ 5]).formatstr("%08X"); - state_add(SH4_R6, "R6", m_r[ 6]).formatstr("%08X"); - state_add(SH4_R7, "R7", m_r[ 7]).formatstr("%08X"); - state_add(SH4_R8, "R8", m_r[ 8]).formatstr("%08X"); - state_add(SH4_R9, "R9", m_r[ 9]).formatstr("%08X"); - state_add(SH4_R10, "R10", m_r[10]).formatstr("%08X"); - state_add(SH4_R11, "R11", m_r[11]).formatstr("%08X"); - state_add(SH4_R12, "R12", m_r[12]).formatstr("%08X"); - state_add(SH4_R13, "R13", m_r[13]).formatstr("%08X"); - state_add(SH4_R14, "R14", m_r[14]).formatstr("%08X"); - state_add(SH4_R15, "R15", m_r[15]).formatstr("%08X"); - state_add(SH4_EA, "EA", m_ea).formatstr("%08X"); - state_add(SH4_R0_BK0, "R0 BK 0", m_rbnk[0][0]).formatstr("%08X"); - state_add(SH4_R1_BK0, "R1 BK 0", m_rbnk[0][1]).formatstr("%08X"); - state_add(SH4_R2_BK0, "R2 BK 0", m_rbnk[0][2]).formatstr("%08X"); - state_add(SH4_R3_BK0, "R3 BK 0", m_rbnk[0][3]).formatstr("%08X"); - state_add(SH4_R4_BK0, "R4 BK 0", m_rbnk[0][4]).formatstr("%08X"); - state_add(SH4_R5_BK0, "R5 BK 0", m_rbnk[0][5]).formatstr("%08X"); - state_add(SH4_R6_BK0, "R6 BK 0", m_rbnk[0][6]).formatstr("%08X"); - state_add(SH4_R7_BK0, "R7 BK 0", m_rbnk[0][7]).formatstr("%08X"); - state_add(SH4_R0_BK1, "R0 BK 1", m_rbnk[1][0]).formatstr("%08X"); - state_add(SH4_R1_BK1, "R1 BK 1", m_rbnk[1][1]).formatstr("%08X"); - state_add(SH4_R2_BK1, "R2 BK 1", m_rbnk[1][2]).formatstr("%08X"); - state_add(SH4_R3_BK1, "R3 BK 1", m_rbnk[1][3]).formatstr("%08X"); - state_add(SH4_R4_BK1, "R4 BK 1", m_rbnk[1][4]).formatstr("%08X"); - state_add(SH4_R5_BK1, "R5 BK 1", m_rbnk[1][5]).formatstr("%08X"); - state_add(SH4_R6_BK1, "R6 BK 1", m_rbnk[1][6]).formatstr("%08X"); - state_add(SH4_R7_BK1, "R7 BK 1", m_rbnk[1][7]).formatstr("%08X"); - state_add(SH4_SPC, "SPC", m_spc).formatstr("%08X"); - state_add(SH4_SSR, "SSR", m_ssr).formatstr("%08X"); - state_add(SH4_SGR, "SGR", m_sgr).formatstr("%08X"); - state_add(SH4_FPSCR, "FPSCR", m_fpscr).formatstr("%08X"); - state_add(SH4_FPUL, "FPUL", m_fpul).formatstr("%08X"); - - state_add(SH4_FR0, "FR0", m_debugger_temp).callimport().formatstr("%25s"); - state_add(SH4_FR1, "FR1", m_debugger_temp).callimport().formatstr("%25s"); - state_add(SH4_FR2, "FR2", m_debugger_temp).callimport().formatstr("%25s"); - state_add(SH4_FR3, "FR3", m_debugger_temp).callimport().formatstr("%25s"); - state_add(SH4_FR4, "FR4", m_debugger_temp).callimport().formatstr("%25s"); - state_add(SH4_FR5, "FR5", m_debugger_temp).callimport().formatstr("%25s"); - state_add(SH4_FR6, "FR6", m_debugger_temp).callimport().formatstr("%25s"); - state_add(SH4_FR7, "FR7", m_debugger_temp).callimport().formatstr("%25s"); - state_add(SH4_FR8, "FR8", m_debugger_temp).callimport().formatstr("%25s"); - state_add(SH4_FR9, "FR9", m_debugger_temp).callimport().formatstr("%25s"); - state_add(SH4_FR10, "FR10", m_debugger_temp).callimport().formatstr("%25s"); - state_add(SH4_FR11, "FR11", m_debugger_temp).callimport().formatstr("%25s"); - state_add(SH4_FR12, "FR12", m_debugger_temp).callimport().formatstr("%25s"); - state_add(SH4_FR13, "FR13", m_debugger_temp).callimport().formatstr("%25s"); - state_add(SH4_FR14, "FR14", m_debugger_temp).callimport().formatstr("%25s"); - state_add(SH4_FR15, "FR15", m_debugger_temp).callimport().formatstr("%25s"); - state_add(SH4_XF0, "XF0", m_debugger_temp).callimport().formatstr("%25s"); - state_add(SH4_XF1, "XF1", m_debugger_temp).callimport().formatstr("%25s"); - state_add(SH4_XF2, "XF2", m_debugger_temp).callimport().formatstr("%25s"); - state_add(SH4_XF3, "XF3", m_debugger_temp).callimport().formatstr("%25s"); - state_add(SH4_XF4, "XF4", m_debugger_temp).callimport().formatstr("%25s"); - state_add(SH4_XF5, "XF5", m_debugger_temp).callimport().formatstr("%25s"); - state_add(SH4_XF6, "XF6", m_debugger_temp).callimport().formatstr("%25s"); - state_add(SH4_XF7, "XF7", m_debugger_temp).callimport().formatstr("%25s"); - state_add(SH4_XF8, "XF8", m_debugger_temp).callimport().formatstr("%25s"); - state_add(SH4_XF9, "XF9", m_debugger_temp).callimport().formatstr("%25s"); - state_add(SH4_XF10, "XF10", m_debugger_temp).callimport().formatstr("%25s"); - state_add(SH4_XF11, "XF11", m_debugger_temp).callimport().formatstr("%25s"); - state_add(SH4_XF12, "XF12", m_debugger_temp).callimport().formatstr("%25s"); - state_add(SH4_XF13, "XF13", m_debugger_temp).callimport().formatstr("%25s"); - state_add(SH4_XF14, "XF14", m_debugger_temp).callimport().formatstr("%25s"); - state_add(SH4_XF15, "XF15", m_debugger_temp).callimport().formatstr("%25s"); - - state_add(STATE_GENPC, "GENPC", m_debugger_temp).callimport().callexport().noshow(); - state_add(STATE_GENPCBASE, "CURPC", m_ppc).noshow(); - state_add(STATE_GENSP, "GENSP", m_r[15]).noshow(); - state_add(STATE_GENFLAGS, "GENFLAGS", m_sr).formatstr("%20s").noshow(); - - m_icountptr = &m_sh4_icount; -} - -void sh34_base_device::state_import(const device_state_entry &entry) -{ -#ifdef LSB_FIRST - uint8_t fpu_xor = m_fpu_pr; -#else - uint8_t fpu_xor = 0; -#endif - - switch (entry.index()) - { - case STATE_GENPC: - m_pc = m_debugger_temp; - case SH4_PC: - m_delay = 0; - break; - - case SH4_SR: - sh4_exception_recompute(); - sh4_check_pending_irq("sh4_set_info"); - break; - - case SH4_FR0: - m_fr[0 ^ fpu_xor] = m_debugger_temp; - break; - - case SH4_FR1: - m_fr[1 ^ fpu_xor] = m_debugger_temp; - break; - - case SH4_FR2: - m_fr[2 ^ fpu_xor] = m_debugger_temp; - break; - - case SH4_FR3: - m_fr[3 ^ fpu_xor] = m_debugger_temp; - break; - - case SH4_FR4: - m_fr[4 ^ fpu_xor] = m_debugger_temp; - break; - - case SH4_FR5: - m_fr[5 ^ fpu_xor] = m_debugger_temp; - break; - - case SH4_FR6: - m_fr[6 ^ fpu_xor] = m_debugger_temp; - break; - - case SH4_FR7: - m_fr[7 ^ fpu_xor] = m_debugger_temp; - break; - - case SH4_FR8: - m_fr[8 ^ fpu_xor] = m_debugger_temp; - break; - - case SH4_FR9: - m_fr[9 ^ fpu_xor] = m_debugger_temp; - break; - - case SH4_FR10: - m_fr[10 ^ fpu_xor] = m_debugger_temp; - break; - - case SH4_FR11: - m_fr[11 ^ fpu_xor] = m_debugger_temp; - break; - - case SH4_FR12: - m_fr[12 ^ fpu_xor] = m_debugger_temp; - break; - - case SH4_FR13: - m_fr[13 ^ fpu_xor] = m_debugger_temp; - break; - - case SH4_FR14: - m_fr[14 ^ fpu_xor] = m_debugger_temp; - break; - - case SH4_FR15: - m_fr[15 ^ fpu_xor] = m_debugger_temp; - break; - - case SH4_XF0: - m_xf[0 ^ fpu_xor] = m_debugger_temp; - break; - - case SH4_XF1: - m_xf[1 ^ fpu_xor] = m_debugger_temp; - break; - - case SH4_XF2: - m_xf[2 ^ fpu_xor] = m_debugger_temp; - break; - - case SH4_XF3: - m_xf[3 ^ fpu_xor] = m_debugger_temp; - break; - - case SH4_XF4: - m_xf[4 ^ fpu_xor] = m_debugger_temp; - break; - - case SH4_XF5: - m_xf[5 ^ fpu_xor] = m_debugger_temp; - break; - - case SH4_XF6: - m_xf[6 ^ fpu_xor] = m_debugger_temp; - break; - - case SH4_XF7: - m_xf[7 ^ fpu_xor] = m_debugger_temp; - break; - - case SH4_XF8: - m_xf[8 ^ fpu_xor] = m_debugger_temp; - break; - - case SH4_XF9: - m_xf[9 ^ fpu_xor] = m_debugger_temp; - break; - - case SH4_XF10: - m_xf[10 ^ fpu_xor] = m_debugger_temp; - break; - - case SH4_XF11: - m_xf[11 ^ fpu_xor] = m_debugger_temp; - break; - - case SH4_XF12: - m_xf[12 ^ fpu_xor] = m_debugger_temp; - break; - - case SH4_XF13: - m_xf[13 ^ fpu_xor] = m_debugger_temp; - break; - - case SH4_XF14: - m_xf[14 ^ fpu_xor] = m_debugger_temp; - break; - - case SH4_XF15: - m_xf[15 ^ fpu_xor] = m_debugger_temp; - break; - } -} - -void sh34_base_device::state_export(const device_state_entry &entry) -{ - switch (entry.index()) - { - case STATE_GENPC: - m_debugger_temp = (m_pc & AM); - break; - } -} - -void sh34_base_device::state_string_export(const device_state_entry &entry, std::string &str) const -{ -#ifdef LSB_FIRST - uint8_t fpu_xor = m_fpu_pr; -#else - uint8_t fpu_xor = 0; -#endif - - switch (entry.index()) - { - case STATE_GENFLAGS: - str = string_format("%s%s%s%s%c%c%d%c%c", - m_sr & MD ? "MD ":" ", - m_sr & sRB ? "RB ":" ", - m_sr & BL ? "BL ":" ", - m_sr & FD ? "FD ":" ", - m_sr & M ? 'M':'.', - m_sr & Q ? 'Q':'.', - (m_sr & I) >> 4, - m_sr & S ? 'S':'.', - m_sr & T ? 'T':'.'); - break; - - case SH4_FR0: - str = string_format("%08X %f", m_fr[0 ^ fpu_xor], (double)FP_RFS(0 ^ fpu_xor)); - break; - - case SH4_FR1: - str = string_format("%08X %f", m_fr[1 ^ fpu_xor], (double)FP_RFS(1 ^ fpu_xor)); - break; - - case SH4_FR2: - str = string_format("%08X %f", m_fr[2 ^ fpu_xor], (double)FP_RFS(2 ^ fpu_xor)); - break; - - case SH4_FR3: - str = string_format("%08X %f", m_fr[3 ^ fpu_xor], (double)FP_RFS(3 ^ fpu_xor)); - break; - - case SH4_FR4: - str = string_format("%08X %f", m_fr[4 ^ fpu_xor], (double)FP_RFS(4 ^ fpu_xor)); - break; - - case SH4_FR5: - str = string_format("%08X %f", m_fr[5 ^ fpu_xor], (double)FP_RFS(5 ^ fpu_xor)); - break; - - case SH4_FR6: - str = string_format("%08X %f", m_fr[6 ^ fpu_xor], (double)FP_RFS(6 ^ fpu_xor)); - break; - - case SH4_FR7: - str = string_format("%08X %f", m_fr[7 ^ fpu_xor], (double)FP_RFS(7 ^ fpu_xor)); - break; - - case SH4_FR8: - str = string_format("%08X %f", m_fr[8 ^ fpu_xor], (double)FP_RFS(8 ^ fpu_xor)); - break; - - case SH4_FR9: - str = string_format("%08X %f", m_fr[9 ^ fpu_xor], (double)FP_RFS(9 ^ fpu_xor)); - break; - - case SH4_FR10: - str = string_format("%08X %f", m_fr[10 ^ fpu_xor], (double)FP_RFS(10 ^ fpu_xor)); - break; - - case SH4_FR11: - str = string_format("%08X %f", m_fr[11 ^ fpu_xor], (double)FP_RFS(11 ^ fpu_xor)); - break; - - case SH4_FR12: - str = string_format("%08X %f", m_fr[12 ^ fpu_xor], (double)FP_RFS(12 ^ fpu_xor)); - break; - - case SH4_FR13: - str = string_format("%08X %f", m_fr[13 ^ fpu_xor], (double)FP_RFS(13 ^ fpu_xor)); - break; - - case SH4_FR14: - str = string_format("%08X %f", m_fr[14 ^ fpu_xor], (double)FP_RFS(14 ^ fpu_xor)); - break; - - case SH4_FR15: - str = string_format("%08X %f", m_fr[15 ^ fpu_xor], (double)FP_RFS(15 ^ fpu_xor)); - break; - - case SH4_XF0: - str = string_format("%08X %f", m_xf[0 ^ fpu_xor], (double)FP_XFS(0 ^ fpu_xor)); - break; - - case SH4_XF1: - str = string_format("%08X %f", m_xf[1 ^ fpu_xor], (double)FP_XFS(1 ^ fpu_xor)); - break; - - case SH4_XF2: - str = string_format("%08X %f", m_xf[2 ^ fpu_xor], (double)FP_XFS(2 ^ fpu_xor)); - break; - - case SH4_XF3: - str = string_format("%08X %f", m_xf[3 ^ fpu_xor], (double)FP_XFS(3 ^ fpu_xor)); - break; - - case SH4_XF4: - str = string_format("%08X %f", m_xf[4 ^ fpu_xor], (double)FP_XFS(4 ^ fpu_xor)); - break; - - case SH4_XF5: - str = string_format("%08X %f", m_xf[5 ^ fpu_xor], (double)FP_XFS(5 ^ fpu_xor)); - break; - - case SH4_XF6: - str = string_format("%08X %f", m_xf[6 ^ fpu_xor], (double)FP_XFS(6 ^ fpu_xor)); - break; - - case SH4_XF7: - str = string_format("%08X %f", m_xf[7 ^ fpu_xor], (double)FP_XFS(7 ^ fpu_xor)); - break; - - case SH4_XF8: - str = string_format("%08X %f", m_xf[8 ^ fpu_xor], (double)FP_XFS(8 ^ fpu_xor)); - break; - - case SH4_XF9: - str = string_format("%08X %f", m_xf[9 ^ fpu_xor], (double)FP_XFS(9 ^ fpu_xor)); - break; - - case SH4_XF10: - str = string_format("%08X %f", m_xf[10 ^ fpu_xor], (double)FP_XFS(10 ^ fpu_xor)); - break; - - case SH4_XF11: - str = string_format("%08X %f", m_xf[11 ^ fpu_xor], (double)FP_XFS(11 ^ fpu_xor)); - break; - - case SH4_XF12: - str = string_format("%08X %f", m_xf[12 ^ fpu_xor], (double)FP_XFS(12 ^ fpu_xor)); - break; - - case SH4_XF13: - str = string_format("%08X %f", m_xf[13 ^ fpu_xor], (double)FP_XFS(13 ^ fpu_xor)); - break; - - case SH4_XF14: - str = string_format("%08X %f", m_xf[14 ^ fpu_xor], (double)FP_XFS(14 ^ fpu_xor)); - break; - - case SH4_XF15: - str = string_format("%08X %f", m_xf[15 ^ fpu_xor], (double)FP_XFS(15 ^ fpu_xor)); - break; - - } -} - - -void sh34_base_device::sh4_set_ftcsr_callback(sh4_ftcsr_callback callback) -{ - m_ftcsr_read_callback = callback; -} diff --git a/src/devices/cpu/superh/sh4.h b/src/devices/cpu/superh/sh4.h deleted file mode 100644 index fad1d326750..00000000000 --- a/src/devices/cpu/superh/sh4.h +++ /dev/null @@ -1,844 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:R. Belmont -/***************************************************************************** - * - * sh4->h - * Portable Hitachi SH-4 (SH7750 family) emulator interface - * - * By R. Belmont, based on sh2.c by Juergen Buchmueller, Mariusz Wojcieszek, - * Olivier Galibert, Sylvain Glaize, and James Forshaw. - * - *****************************************************************************/ - -#ifndef MAME_CPU_SH4_SH4_H -#define MAME_CPU_SH4_SH4_H - -#pragma once - -// doesn't actually seem to improve performance at all -#define SH4_USE_FASTRAM_OPTIMIZATION 0 -#define SH4_MAX_FASTRAM 3 - -#define SH4_INT_NONE -1 -enum -{ - SH4_IRL0=0, SH4_IRL1, SH4_IRL2, SH4_IRL3, SH4_IRLn -}; - -enum -{ - SH4_PC=1, SH4_SR, SH4_PR, SH4_GBR, SH4_VBR, SH4_DBR, SH4_MACH, SH4_MACL, - SH4_R0, SH4_R1, SH4_R2, SH4_R3, SH4_R4, SH4_R5, SH4_R6, SH4_R7, - SH4_R8, SH4_R9, SH4_R10, SH4_R11, SH4_R12, SH4_R13, SH4_R14, SH4_R15, SH4_EA, - SH4_R0_BK0, SH4_R1_BK0, SH4_R2_BK0, SH4_R3_BK0, SH4_R4_BK0, SH4_R5_BK0, SH4_R6_BK0, SH4_R7_BK0, - SH4_R0_BK1, SH4_R1_BK1, SH4_R2_BK1, SH4_R3_BK1, SH4_R4_BK1, SH4_R5_BK1, SH4_R6_BK1, SH4_R7_BK1, - SH4_SPC, SH4_SSR, SH4_SGR, SH4_FPSCR, SH4_FPUL, SH4_FR0, SH4_FR1, SH4_FR2, SH4_FR3, SH4_FR4, SH4_FR5, - SH4_FR6, SH4_FR7, SH4_FR8, SH4_FR9, SH4_FR10, SH4_FR11, SH4_FR12, SH4_FR13, SH4_FR14, SH4_FR15, - SH4_XF0, SH4_XF1, SH4_XF2, SH4_XF3, SH4_XF4, SH4_XF5, SH4_XF6, SH4_XF7, - SH4_XF8, SH4_XF9, SH4_XF10, SH4_XF11, SH4_XF12, SH4_XF13, SH4_XF14, SH4_XF15 -}; - -enum -{ - SH4_INTC_NMI=23, - SH4_INTC_IRLn0, - SH4_INTC_IRLn1, - SH4_INTC_IRLn2, - SH4_INTC_IRLn3, - SH4_INTC_IRLn4, - SH4_INTC_IRLn5, - SH4_INTC_IRLn6, - SH4_INTC_IRLn7, - SH4_INTC_IRLn8, - SH4_INTC_IRLn9, - SH4_INTC_IRLnA, - SH4_INTC_IRLnB, - SH4_INTC_IRLnC, - SH4_INTC_IRLnD, - SH4_INTC_IRLnE, - - SH4_INTC_IRL0, - SH4_INTC_IRL1, - SH4_INTC_IRL2, - SH4_INTC_IRL3, - - SH4_INTC_HUDI, - SH4_INTC_GPOI, - - SH4_INTC_DMTE0, - SH4_INTC_DMTE1, - SH4_INTC_DMTE2, - SH4_INTC_DMTE3, - SH4_INTC_DMTE4, - SH4_INTC_DMTE5, - SH4_INTC_DMTE6, - SH4_INTC_DMTE7, - - SH4_INTC_DMAE, - - SH4_INTC_TUNI3, - SH4_INTC_TUNI4, - SH4_INTC_TUNI0, - SH4_INTC_TUNI1, - SH4_INTC_TUNI2, - SH4_INTC_TICPI2, - SH4_INTC_ATI, - SH4_INTC_PRI, - SH4_INTC_CUI, - SH4_INTC_SCI1ERI, - SH4_INTC_SCI1RXI, - - SH4_INTC_SCI1TXI, - SH4_INTC_SCI1TEI, - SH4_INTC_SCIFERI, - SH4_INTC_SCIFRXI, - SH4_INTC_SCIFBRI, - SH4_INTC_SCIFTXI, - SH4_INTC_ITI, - SH4_INTC_RCMI, - SH4_INTC_ROVI -}; - -#define SH4_FPU_PZERO 0 -#define SH4_FPU_NZERO 1 -#define SH4_FPU_DENORM 2 -#define SH4_FPU_NORM 3 -#define SH4_FPU_PINF 4 -#define SH4_FPU_NINF 5 -#define SH4_FPU_qNaN 6 -#define SH4_FPU_sNaN 7 - -enum -{ - SH4_IOPORT_16=8*0, - SH4_IOPORT_4=8*1, - SH4_IOPORT_DMA=8*2, - // future use - SH4_IOPORT_SCI=8*3, - SH4_IOPORT_SCIF=8*4 -}; - -struct sh4_device_dma -{ - uint32_t length; - uint32_t size; - void *buffer; - int channel; -}; - -struct sh4_ddt_dma -{ - uint32_t source; - uint32_t length; - uint32_t size; - uint32_t destination; - void *buffer; - int direction; - int channel; - int mode; -}; - - -// ASID [7:0] | VPN [31:10] | V | | PPN [28:10] | SZ[1:0] | SH | C | PR[1:0] | D | WT | SA[2:0] | TC - -struct sh4_utlb -{ - uint8_t ASID; - uint32_t VPN; - uint8_t V; - uint32_t PPN; - uint8_t PSZ; - uint8_t SH; - uint8_t C; - uint8_t PPR; - uint8_t D; - uint8_t WT; - uint8_t SA; - uint8_t TC; -}; - - -typedef void (*sh4_ftcsr_callback)(uint32_t); - - -#define MCFG_SH4_MD0(_md0) \ - sh34_base_device::set_md0(*device, _md0); - -#define MCFG_SH4_MD1(_md1) \ - sh34_base_device::set_md1(*device, _md1); - -#define MCFG_SH4_MD2(_md2) \ - sh34_base_device::set_md2(*device, _md2); - -#define MCFG_SH4_MD3(_md3) \ - sh34_base_device::set_md3(*device, _md3); - -#define MCFG_SH4_MD4(_md4) \ - sh34_base_device::set_md4(*device, _md4); - -#define MCFG_SH4_MD5(_md5) \ - sh34_base_device::set_md5(*device, _md5); - -#define MCFG_SH4_MD6(_md6) \ - sh34_base_device::set_md6(*device, _md6); - -#define MCFG_SH4_MD7(_md7) \ - sh34_base_device::set_md7(*device, _md7); - -#define MCFG_SH4_MD8(_md8) \ - sh34_base_device::set_md8(*device, _md8); - -#define MCFG_SH4_CLOCK(_clock) \ - sh34_base_device::set_sh4_clock(*device, _clock); - - -#define MCFG_MMU_HACK_TYPE(_hacktype) \ - sh34_base_device::set_mmu_hacktype(*device, _hacktype); - - -class sh34_base_device : public cpu_device -{ -public: -//#if SH4_USE_FASTRAM_OPTIMIZATION - void add_fastram(offs_t start, offs_t end, uint8_t readonly, void *base); -//#endif - - static void set_md0(device_t &device, int md0) { downcast(device).c_md0 = md0; } - static void set_md1(device_t &device, int md0) { downcast(device).c_md1 = md0; } - static void set_md2(device_t &device, int md0) { downcast(device).c_md2 = md0; } - static void set_md3(device_t &device, int md0) { downcast(device).c_md3 = md0; } - static void set_md4(device_t &device, int md0) { downcast(device).c_md4 = md0; } - static void set_md5(device_t &device, int md0) { downcast(device).c_md5 = md0; } - static void set_md6(device_t &device, int md0) { downcast(device).c_md6 = md0; } - static void set_md7(device_t &device, int md0) { downcast(device).c_md7 = md0; } - static void set_md8(device_t &device, int md0) { downcast(device).c_md8 = md0; } - static void set_sh4_clock(device_t &device, int clock) { downcast(device).c_clock = clock; } - - static void set_mmu_hacktype(device_t &device, int hacktype) { downcast(device).m_mmuhack = hacktype; } - - TIMER_CALLBACK_MEMBER( sh4_refresh_timer_callback ); - TIMER_CALLBACK_MEMBER( sh4_rtc_timer_callback ); - TIMER_CALLBACK_MEMBER( sh4_timer_callback ); - TIMER_CALLBACK_MEMBER( sh4_dmac_callback ); - - void sh4_set_frt_input(int state); - void sh4_set_irln_input(int value); - void sh4_set_ftcsr_callback(sh4_ftcsr_callback callback); - int sh4_dma_data(struct sh4_device_dma *s); - void sh4_dma_ddt(struct sh4_ddt_dma *s); - -protected: - // construction/destruction - sh34_base_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, endianness_t endianness, address_map_constructor internal); - - // device-level overrides - virtual void device_start() override; - virtual void device_reset() override; - - // device_execute_interface overrides - virtual uint32_t execute_min_cycles() const override { return 1; } - virtual uint32_t execute_max_cycles() const override { return 4; } - virtual uint32_t execute_input_lines() const override { return 5; } - virtual void execute_run() override; - virtual void execute_set_input(int inputnum, int state) override; - - // device_memory_interface overrides - virtual space_config_vector memory_space_config() const override; - - // device_state_interface overrides - virtual void state_import(const device_state_entry &entry) override; - virtual void state_export(const device_state_entry &entry) override; - virtual void state_string_export(const device_state_entry &entry, std::string &str) const override; - - // device_disasm_interface overrides - virtual uint32_t disasm_min_opcode_bytes() const override { return 2; } - virtual uint32_t disasm_max_opcode_bytes() const override { return 2; } - virtual offs_t disasm_disassemble(std::ostream &stream, offs_t pc, const uint8_t *oprom, const uint8_t *opram, uint32_t options) override; - - address_space_config m_program_config; - address_space_config m_io_config; - - int c_md2; - int c_md1; - int c_md0; - int c_md6; - int c_md4; - int c_md3; - int c_md5; - int c_md7; - int c_md8; - int c_clock; - - // hack 1 = Naomi hack, hack 2 = Work in Progress implementation - int m_mmuhack; - - uint32_t m_ppc; - uint32_t m_pc; - uint32_t m_spc; - uint32_t m_pr; - uint32_t m_sr; - uint32_t m_ssr; - uint32_t m_gbr; - uint32_t m_vbr; - uint32_t m_mach; - uint32_t m_macl; - uint32_t m_r[16]; - uint32_t m_rbnk[2][8]; - uint32_t m_sgr; - uint32_t m_fr[16]; - uint32_t m_xf[16]; - uint32_t m_ea; - uint32_t m_delay; - uint32_t m_cpu_off; - uint32_t m_pending_irq; - uint32_t m_test_irq; - uint32_t m_fpscr; - uint32_t m_fpul; - uint32_t m_dbr; - - uint32_t m_exception_priority[128]; - int m_exception_requesting[128]; - - int8_t m_irq_line_state[17]; - address_space *m_internal; - address_space *m_program; - direct_read_data *m_direct; - address_space *m_io; - - // sh4 internal - uint32_t m_m[16384]; - - // timer regs handled manually for reuse - uint32_t m_SH4_TSTR; - uint32_t m_SH4_TCNT0; - uint32_t m_SH4_TCNT1; - uint32_t m_SH4_TCNT2; - uint32_t m_SH4_TCR0; - uint32_t m_SH4_TCR1; - uint32_t m_SH4_TCR2; - uint32_t m_SH4_TCOR0; - uint32_t m_SH4_TCOR1; - uint32_t m_SH4_TCOR2; - uint32_t m_SH4_TOCR; - uint32_t m_SH4_TCPR2; - - // INTC regs - uint32_t m_SH4_IPRA; - - uint32_t m_SH4_IPRC; - - // DMAC regs - uint32_t m_SH4_SAR0; - uint32_t m_SH4_SAR1; - uint32_t m_SH4_SAR2; - uint32_t m_SH4_SAR3; - - uint32_t m_SH4_DAR0; - uint32_t m_SH4_DAR1; - uint32_t m_SH4_DAR2; - uint32_t m_SH4_DAR3; - - uint32_t m_SH4_CHCR0; - uint32_t m_SH4_CHCR1; - uint32_t m_SH4_CHCR2; - uint32_t m_SH4_CHCR3; - - uint32_t m_SH4_DMATCR0; - uint32_t m_SH4_DMATCR1; - uint32_t m_SH4_DMATCR2; - uint32_t m_SH4_DMATCR3; - - uint32_t m_SH4_DMAOR; - - int8_t m_nmi_line_state; - - uint8_t m_sleep_mode; - - int m_frt_input; - int m_irln; - int m_internal_irq_level; - int m_internal_irq_vector; - - emu_timer *m_dma_timer[4]; - emu_timer *m_refresh_timer; - emu_timer *m_rtc_timer; - emu_timer *m_timer[3]; - uint32_t m_refresh_timer_base; - int m_dma_timer_active[4]; - uint32_t m_dma_source[4]; - uint32_t m_dma_destination[4]; - uint32_t m_dma_count[4]; - int m_dma_wordsize[4]; - int m_dma_source_increment[4]; - int m_dma_destination_increment[4]; - int m_dma_mode[4]; - - int m_sh4_icount; - int m_is_slave; - int m_cpu_clock; - int m_bus_clock; - int m_pm_clock; - int m_fpu_sz; - int m_fpu_pr; - int m_ioport16_pullup; - int m_ioport16_direction; - int m_ioport4_pullup; - int m_ioport4_direction; - - void (*m_ftcsr_read_callback)(uint32_t data); - - /* This MMU simulation is good for the simple remap used on Naomi GD-ROM SQ access *ONLY* */ - uint8_t m_sh4_mmu_enabled; - - int m_cpu_type; - - // sh3 internal - uint32_t m_sh3internal_upper[0x3000/4]; - uint32_t m_sh3internal_lower[0x1000]; - - uint64_t m_debugger_temp; - - - void execute_one_0000(const uint16_t opcode); - void execute_one_4000(const uint16_t opcode); - void execute_one(const uint16_t opcode); - inline void sh4_check_pending_irq(const char *message) // look for highest priority active exception and handle it - { - int a,irq,z; - - irq = 0; - z = -1; - for (a=0;a <= SH4_INTC_ROVI;a++) - { - if (m_exception_requesting[a]) - { - if ((int)m_exception_priority[a] > z) - { - z = m_exception_priority[a]; - irq = a; - } - } - } - if (z >= 0) - { - sh4_exception(message, irq); - } - } - - void TODO(const uint16_t opcode); - void WB(offs_t A, uint8_t V); - void WW(offs_t A, uint16_t V); - void WL(offs_t A, uint32_t V); - void ADD(const uint16_t opcode); - void ADDI(const uint16_t opcode); - void ADDC(const uint16_t opcode); - void ADDV(const uint16_t opcode); - void AND(const uint16_t opcode); - void ANDI(const uint16_t opcode); - void ANDM(const uint16_t opcode); - void BF(const uint16_t opcode); - void BFS(const uint16_t opcode); - void BRA(const uint16_t opcode); - void BRAF(const uint16_t opcode); - void BSR(const uint16_t opcode); - void BSRF(const uint16_t opcode); - void BT(const uint16_t opcode); - void BTS(const uint16_t opcode); - void CLRMAC(const uint16_t opcode); - void CLRT(const uint16_t opcode); - void CMPEQ(const uint16_t opcode); - void CMPGE(const uint16_t opcode); - void CMPGT(const uint16_t opcode); - void CMPHI(const uint16_t opcode); - void CMPHS(const uint16_t opcode); - void CMPPL(const uint16_t opcode); - void CMPPZ(const uint16_t opcode); - void CMPSTR(const uint16_t opcode); - void CMPIM(const uint16_t opcode); - void DIV0S(const uint16_t opcode); - void DIV0U(const uint16_t opcode); - void DIV1(const uint16_t opcode); - void DMULS(const uint16_t opcode); - void DMULU(const uint16_t opcode); - void DT(const uint16_t opcode); - void EXTSB(const uint16_t opcode); - void EXTSW(const uint16_t opcode); - void EXTUB(const uint16_t opcode); - void EXTUW(const uint16_t opcode); - void JMP(const uint16_t opcode); - void JSR(const uint16_t opcode); - void LDCSR(const uint16_t opcode); - void LDCGBR(const uint16_t opcode); - void LDCVBR(const uint16_t opcode); - void LDCMSR(const uint16_t opcode); - void LDCMGBR(const uint16_t opcode); - void LDCMVBR(const uint16_t opcode); - void LDSMACH(const uint16_t opcode); - void LDSMACL(const uint16_t opcode); - void LDSPR(const uint16_t opcode); - void LDSMMACH(const uint16_t opcode); - void LDSMMACL(const uint16_t opcode); - void LDSMPR(const uint16_t opcode); - virtual void LDTLB(const uint16_t opcode); - void MAC_L(const uint16_t opcode); - void MAC_W(const uint16_t opcode); - void MOV(const uint16_t opcode); - void MOVBS(const uint16_t opcode); - void MOVWS(const uint16_t opcode); - void MOVLS(const uint16_t opcode); - void MOVBL(const uint16_t opcode); - void MOVWL(const uint16_t opcode); - void MOVLL(const uint16_t opcode); - void MOVBM(const uint16_t opcode); - void MOVWM(const uint16_t opcode); - void MOVLM(const uint16_t opcode); - void MOVBP(const uint16_t opcode); - void MOVWP(const uint16_t opcode); - void MOVLP(const uint16_t opcode); - void MOVBS0(const uint16_t opcode); - void MOVWS0(const uint16_t opcode); - void MOVLS0(const uint16_t opcode); - void MOVBL0(const uint16_t opcode); - void MOVWL0(const uint16_t opcode); - void MOVLL0(const uint16_t opcode); - void MOVI(const uint16_t opcode); - void MOVWI(const uint16_t opcode); - void MOVLI(const uint16_t opcode); - void MOVBLG(const uint16_t opcode); - void MOVWLG(const uint16_t opcode); - void MOVLLG(const uint16_t opcode); - void MOVBSG(const uint16_t opcode); - void MOVWSG(const uint16_t opcode); - void MOVLSG(const uint16_t opcode); - void MOVBS4(const uint16_t opcode); - void MOVWS4(const uint16_t opcode); - void MOVLS4(const uint16_t opcode); - void MOVBL4(const uint16_t opcode); - void MOVWL4(const uint16_t opcode); - void MOVLL4(const uint16_t opcode); - void MOVA(const uint16_t opcode); - void MOVT(const uint16_t opcode); - void MULL(const uint16_t opcode); - void MULS(const uint16_t opcode); - void MULU(const uint16_t opcode); - void NEG(const uint16_t opcode); - void NEGC(const uint16_t opcode); - void NOP(const uint16_t opcode); - void NOT(const uint16_t opcode); - void OR(const uint16_t opcode); - void ORI(const uint16_t opcode); - void ORM(const uint16_t opcode); - void ROTCL(const uint16_t opcode); - void ROTCR(const uint16_t opcode); - void ROTL(const uint16_t opcode); - void ROTR(const uint16_t opcode); - void RTE(const uint16_t opcode); - void RTS(const uint16_t opcode); - void SETT(const uint16_t opcode); - void SHAL(const uint16_t opcode); - void SHAR(const uint16_t opcode); - void SHLL(const uint16_t opcode); - void SHLL2(const uint16_t opcode); - void SHLL8(const uint16_t opcode); - void SHLL16(const uint16_t opcode); - void SHLR(const uint16_t opcode); - void SHLR2(const uint16_t opcode); - void SHLR8(const uint16_t opcode); - void SHLR16(const uint16_t opcode); - void SLEEP(const uint16_t opcode); - void STCSR(const uint16_t opcode); - void STCGBR(const uint16_t opcode); - void STCVBR(const uint16_t opcode); - void STCMSR(const uint16_t opcode); - void STCMGBR(const uint16_t opcode); - void STCMVBR(const uint16_t opcode); - void STSMACH(const uint16_t opcode); - void STSMACL(const uint16_t opcode); - void STSPR(const uint16_t opcode); - void STSMMACH(const uint16_t opcode); - void STSMMACL(const uint16_t opcode); - void STSMPR(const uint16_t opcode); - void SUB(const uint16_t opcode); - void SUBC(const uint16_t opcode); - void SUBV(const uint16_t opcode); - void SWAPB(const uint16_t opcode); - void SWAPW(const uint16_t opcode); - void TAS(const uint16_t opcode); - void TRAPA(const uint16_t opcode); - void TST(const uint16_t opcode); - void TSTI(const uint16_t opcode); - void TSTM(const uint16_t opcode); - void XOR(const uint16_t opcode); - void XORI(const uint16_t opcode); - void XORM(const uint16_t opcode); - void XTRCT(const uint16_t opcode); - void STCSSR(const uint16_t opcode); - void STCSPC(const uint16_t opcode); - void STCSGR(const uint16_t opcode); - void STSFPUL(const uint16_t opcode); - void STSFPSCR(const uint16_t opcode); - void STCDBR(const uint16_t opcode); - void STCRBANK(const uint16_t opcode); - void STCMRBANK(const uint16_t opcode); - void MOVCAL(const uint16_t opcode); - void CLRS(const uint16_t opcode); - void SETS(const uint16_t opcode); - void STCMSGR(const uint16_t opcode); - void STSMFPUL(const uint16_t opcode); - void STSMFPSCR(const uint16_t opcode); - void STCMDBR(const uint16_t opcode); - void STCMSSR(const uint16_t opcode); - void STCMSPC(const uint16_t opcode); - void LDSMFPUL(const uint16_t opcode); - void LDSMFPSCR(const uint16_t opcode); - void LDCMDBR(const uint16_t opcode); - void LDCMRBANK(const uint16_t opcode); - void LDCMSSR(const uint16_t opcode); - void LDCMSPC(const uint16_t opcode); - void LDSFPUL(const uint16_t opcode); - void LDSFPSCR(const uint16_t opcode); - void LDCDBR(const uint16_t opcode); - void SHAD(const uint16_t opcode); - void SHLD(const uint16_t opcode); - void LDCRBANK(const uint16_t opcode); - void LDCSSR(const uint16_t opcode); - void LDCSPC(const uint16_t opcode); - void PREFM(const uint16_t opcode); - void FMOVMRIFR(const uint16_t opcode); - void FMOVFRMR(const uint16_t opcode); - void FMOVFRMDR(const uint16_t opcode); - void FMOVFRS0(const uint16_t opcode); - void FMOVS0FR(const uint16_t opcode); - void FMOVMRFR(const uint16_t opcode); - void FMOVFR(const uint16_t opcode); - void FLDI1(const uint16_t opcode); - void FLDI0(const uint16_t opcode); - void FLDS(const uint16_t opcode); - void FSTS(const uint16_t opcode); - void FRCHG(); - void FSCHG(); - void FTRC(const uint16_t opcode); - void FLOAT(const uint16_t opcode); - void FNEG(const uint16_t opcode); - void FABS(const uint16_t opcode); - void FCMP_EQ(const uint16_t opcode); - void FCMP_GT(const uint16_t opcode); - void FCNVDS(const uint16_t opcode); - void FCNVSD(const uint16_t opcode); - void FADD(const uint16_t opcode); - void FSUB(const uint16_t opcode); - void FMUL(const uint16_t opcode); - void FDIV(const uint16_t opcode); - void FMAC(const uint16_t opcode); - void FSQRT(const uint16_t opcode); - void FSRRA(const uint16_t opcode); - void FSSCA(const uint16_t opcode); - void FIPR(const uint16_t opcode); - void FTRV(const uint16_t opcode); - void op1111_0xf13(const uint16_t opcode); - void dbreak(const uint16_t opcode); - void op1111_0x13(uint16_t opcode); - uint8_t RB(offs_t A); - uint16_t RW(offs_t A); - uint32_t RL(offs_t A); - void sh4_change_register_bank(int to); - void sh4_swap_fp_registers(); - void sh4_swap_fp_couples(); - void sh4_syncronize_register_bank(int to); - void sh4_default_exception_priorities(); - void sh4_exception_recompute(); - void sh4_exception_request(int exception); - void sh4_exception_unrequest(int exception); - void sh4_exception_checkunrequest(int exception); - void sh4_exception(const char *message, int exception); - uint32_t compute_ticks_refresh_timer(emu_timer *timer, int hertz, int base, int divisor); - void sh4_refresh_timer_recompute(); - void increment_rtc_time(int mode); - void sh4_dmac_nmi(); - void sh4_handler_ipra_w(uint32_t data, uint32_t mem_mask); - virtual uint32_t get_remap(uint32_t address); - virtual uint32_t sh4_getsqremap(uint32_t address); - void sh4_parse_configuration(); - void sh4_timer_recompute(int which); - uint32_t sh4_handle_tcnt0_addr_r(uint32_t mem_mask); - uint32_t sh4_handle_tcnt1_addr_r(uint32_t mem_mask); - uint32_t sh4_handle_tcnt2_addr_r(uint32_t mem_mask); - uint32_t sh4_handle_tcor0_addr_r(uint32_t mem_mask); - uint32_t sh4_handle_tcor1_addr_r(uint32_t mem_mask); - uint32_t sh4_handle_tcor2_addr_r(uint32_t mem_mask); - uint32_t sh4_handle_tcr0_addr_r(uint32_t mem_mask); - uint32_t sh4_handle_tcr1_addr_r(uint32_t mem_mask); - uint32_t sh4_handle_tcr2_addr_r(uint32_t mem_mask); - uint32_t sh4_handle_tstr_addr_r(uint32_t mem_mask); - uint32_t sh4_handle_tocr_addr_r(uint32_t mem_mask); - uint32_t sh4_handle_tcpr2_addr_r(uint32_t mem_mask); - void sh4_handle_tstr_addr_w(uint32_t data, uint32_t mem_mask); - void sh4_handle_tcr0_addr_w(uint32_t data, uint32_t mem_mask); - void sh4_handle_tcr1_addr_w(uint32_t data, uint32_t mem_mask); - void sh4_handle_tcr2_addr_w(uint32_t data, uint32_t mem_mask); - void sh4_handle_tcor0_addr_w(uint32_t data, uint32_t mem_mask); - void sh4_handle_tcor1_addr_w(uint32_t data, uint32_t mem_mask); - void sh4_handle_tcor2_addr_w(uint32_t data, uint32_t mem_mask); - void sh4_handle_tcnt0_addr_w(uint32_t data, uint32_t mem_mask); - void sh4_handle_tcnt1_addr_w(uint32_t data, uint32_t mem_mask); - void sh4_handle_tcnt2_addr_w(uint32_t data, uint32_t mem_mask); - void sh4_handle_tocr_addr_w(uint32_t data, uint32_t mem_mask); - void sh4_handle_tcpr2_addr_w(uint32_t data, uint32_t mem_mask); - int sh4_dma_transfer(int channel, int timermode, uint32_t chcr, uint32_t *sar, uint32_t *dar, uint32_t *dmatcr); - int sh4_dma_transfer_device(int channel, uint32_t chcr, uint32_t *sar, uint32_t *dar, uint32_t *dmatcr); - void sh4_dmac_check(int channel); - void sh4_handle_sar0_addr_w(uint32_t data, uint32_t mem_mask); - void sh4_handle_sar1_addr_w(uint32_t data, uint32_t mem_mask); - void sh4_handle_sar2_addr_w(uint32_t data, uint32_t mem_mask); - void sh4_handle_sar3_addr_w(uint32_t data, uint32_t mem_mask); - void sh4_handle_dar0_addr_w(uint32_t data, uint32_t mem_mask); - void sh4_handle_dar1_addr_w(uint32_t data, uint32_t mem_mask); - void sh4_handle_dar2_addr_w(uint32_t data, uint32_t mem_mask); - void sh4_handle_dar3_addr_w(uint32_t data, uint32_t mem_mask); - void sh4_handle_dmatcr0_addr_w(uint32_t data, uint32_t mem_mask); - void sh4_handle_dmatcr1_addr_w(uint32_t data, uint32_t mem_mask); - void sh4_handle_dmatcr2_addr_w(uint32_t data, uint32_t mem_mask); - void sh4_handle_dmatcr3_addr_w(uint32_t data, uint32_t mem_mask); - void sh4_handle_chcr0_addr_w(uint32_t data, uint32_t mem_mask); - void sh4_handle_chcr1_addr_w(uint32_t data, uint32_t mem_mask); - void sh4_handle_chcr2_addr_w(uint32_t data, uint32_t mem_mask); - void sh4_handle_chcr3_addr_w(uint32_t data, uint32_t mem_mask); - void sh4_handle_dmaor_addr_w(uint32_t data, uint32_t mem_mask); - uint32_t sh4_handle_sar0_addr_r(uint32_t mem_mask) { return m_SH4_SAR0; } - uint32_t sh4_handle_sar1_addr_r(uint32_t mem_mask) { return m_SH4_SAR1; } - uint32_t sh4_handle_sar2_addr_r(uint32_t mem_mask) { return m_SH4_SAR2; } - uint32_t sh4_handle_sar3_addr_r(uint32_t mem_mask) { return m_SH4_SAR3; } - uint32_t sh4_handle_dar0_addr_r(uint32_t mem_mask) { return m_SH4_DAR0; } - uint32_t sh4_handle_dar1_addr_r(uint32_t mem_mask) { return m_SH4_DAR1; } - uint32_t sh4_handle_dar2_addr_r(uint32_t mem_mask) { return m_SH4_DAR2; } - uint32_t sh4_handle_dar3_addr_r(uint32_t mem_mask) { return m_SH4_DAR3; } - uint32_t sh4_handle_dmatcr0_addr_r(uint32_t mem_mask) { return m_SH4_DMATCR0; } - uint32_t sh4_handle_dmatcr1_addr_r(uint32_t mem_mask) { return m_SH4_DMATCR1; } - uint32_t sh4_handle_dmatcr2_addr_r(uint32_t mem_mask) { return m_SH4_DMATCR2; } - uint32_t sh4_handle_dmatcr3_addr_r(uint32_t mem_mask) { return m_SH4_DMATCR3; } - uint32_t sh4_handle_chcr0_addr_r(uint32_t mem_mask) { return m_SH4_CHCR0; } - uint32_t sh4_handle_chcr1_addr_r(uint32_t mem_mask) { return m_SH4_CHCR1; } - uint32_t sh4_handle_chcr2_addr_r(uint32_t mem_mask) { return m_SH4_CHCR2; } - uint32_t sh4_handle_chcr3_addr_r(uint32_t mem_mask) { return m_SH4_CHCR3; } - uint32_t sh4_handle_dmaor_addr_r(uint32_t mem_mask) { return m_SH4_DMAOR; } - -#if SH4_USE_FASTRAM_OPTIMIZATION - /* fast RAM */ - bool m_bigendian; - uint32_t m_byte_xor; - uint32_t m_word_xor; - uint32_t m_dword_xor; - uint32_t m_fastram_select; - struct - { - offs_t start; /* start of the RAM block */ - offs_t end; /* end of the RAM block */ - bool readonly; /* true if read-only */ - void * base; /* base in memory where the RAM lives */ - } m_fastram[SH4_MAX_FASTRAM]; -#endif -}; - - -class sh3_base_device : public sh34_base_device -{ -public: - DECLARE_WRITE32_MEMBER( sh3_internal_w ); - DECLARE_READ32_MEMBER( sh3_internal_r ); - - DECLARE_WRITE32_MEMBER( sh3_internal_high_w ); - DECLARE_READ32_MEMBER( sh3_internal_high_r ); - -protected: - // construction/destruction - sh3_base_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, endianness_t endianness); - - virtual void device_reset() override; -}; - - -class sh4_base_device : public sh34_base_device -{ -public: - DECLARE_WRITE32_MEMBER( sh4_internal_w ); - DECLARE_READ32_MEMBER( sh4_internal_r ); - - DECLARE_READ64_MEMBER( sh4_utlb_address_array_r ); - DECLARE_WRITE64_MEMBER( sh4_utlb_address_array_w ); - DECLARE_READ64_MEMBER( sh4_utlb_data_array1_r ); - DECLARE_WRITE64_MEMBER( sh4_utlb_data_array1_w ); - DECLARE_READ64_MEMBER( sh4_utlb_data_array2_r ); - DECLARE_WRITE64_MEMBER( sh4_utlb_data_array2_w ); - - virtual void LDTLB(const uint16_t opcode) override; - - virtual uint32_t get_remap(uint32_t address) override; - virtual uint32_t sh4_getsqremap(uint32_t address) override; - sh4_utlb m_utlb[64]; - -protected: - // construction/destruction - sh4_base_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, endianness_t endianness); - - virtual void device_start() override; - virtual void device_reset() override; -}; - - -class sh3_device : public sh3_base_device -{ -public: - sh3_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); -}; - - -class sh3be_device : public sh3_base_device -{ -public: - sh3be_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); - -protected: - virtual void execute_run() override; - virtual offs_t disasm_disassemble(std::ostream &stream, offs_t pc, const uint8_t *oprom, const uint8_t *opram, uint32_t options) override; -}; - - -class sh4_device : public sh4_base_device -{ -public: - sh4_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); -}; - - -class sh4be_device : public sh4_base_device -{ -public: - sh4be_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); - -protected: - virtual void execute_run() override; - virtual offs_t disasm_disassemble(std::ostream &stream, offs_t pc, const uint8_t *oprom, const uint8_t *opram, uint32_t options) override; -}; - - -DECLARE_DEVICE_TYPE(SH3LE, sh3_device) -DECLARE_DEVICE_TYPE(SH3BE, sh3be_device) -DECLARE_DEVICE_TYPE(SH4LE, sh4_device) -DECLARE_DEVICE_TYPE(SH4BE, sh4be_device) - - -/*************************************************************************** - COMPILER-SPECIFIC OPTIONS -***************************************************************************/ - -#define SH4DRC_STRICT_VERIFY 0x0001 /* verify all instructions */ -#define SH4DRC_FLUSH_PC 0x0002 /* flush the PC value before each memory access */ -#define SH4DRC_STRICT_PCREL 0x0004 /* do actual loads on MOVLI/MOVWI instead of collapsing to immediates */ - -#define SH4DRC_COMPATIBLE_OPTIONS (SH4DRC_STRICT_VERIFY | SH4DRC_FLUSH_PC | SH4DRC_STRICT_PCREL) -#define SH4DRC_FASTEST_OPTIONS (0) - -void sh4drc_set_options(device_t *device, uint32_t options); -void sh4drc_add_pcflush(device_t *device, offs_t address); - -#endif // MAME_CPU_SH4_SH4_H diff --git a/src/devices/cpu/superh/sh4comn.cpp b/src/devices/cpu/superh/sh4comn.cpp deleted file mode 100644 index 4f7ae411e7d..00000000000 --- a/src/devices/cpu/superh/sh4comn.cpp +++ /dev/null @@ -1,1465 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:R. Belmont -/***************************************************************************** - * - * sh4comn.c - * - * SH-4 non-specific components - * - *****************************************************************************/ - -#include "emu.h" -#include "debugger.h" -#include "sh4.h" -#include "sh4regs.h" -#include "sh4comn.h" -#include "sh3comn.h" -#include "sh4tmu.h" -#include "sh4dmac.h" - -static const int rtcnt_div[8] = { 0, 4, 16, 64, 256, 1024, 2048, 4096 }; -static const int daysmonth[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; - - - -static const uint32_t exception_priority_default[] = { - EXPPRI(1,1,0,0), /* Power-on Reset */ - EXPPRI(1,2,0,1), /* Manual Reset */ - EXPPRI(1,1,0,2), /* H-UDI Reset */ - EXPPRI(1,3,0,3), /* Inst TLB Multiple Hit */ - EXPPRI(1,4,0,4), /* Data TLB Multiple Hit */ - - EXPPRI(2,0,0,5), /* User break Before Instruction */ - EXPPRI(2,1,0,6), /* Inst Address Error */ - EXPPRI(2,2,0,7), /* Inst TLB Miss */ - EXPPRI(2,3,0,8), /* Inst TLB Protection Violation */ - EXPPRI(2,4,0,9), /* Illegal Instruction */ - EXPPRI(2,4,0,10), /* Slot Illegal Instruction */ - EXPPRI(2,4,0,11), /* FPU Disable */ - EXPPRI(2,4,0,12), /* Slot FPU Disable */ - EXPPRI(2,5,0,13), /* Data Address Error (Read) */ - EXPPRI(2,5,0,14), /* Data Address Error (Write) */ - EXPPRI(2,6,0,15), /* Data TBL Miss Read */ - EXPPRI(2,6,0,16), /* Data TBL Miss Write */ - EXPPRI(2,7,0,17), /* Data TBL Protection Violation Read */ - EXPPRI(2,7,0,18), /* Data TBL Protection Violation Write */ - EXPPRI(2,8,0,19), /* FPU Exception */ - EXPPRI(2,9,0,20), /* Initial Page Write exception */ - - EXPPRI(2,4,0,21), /* Unconditional TRAP */ - EXPPRI(2,10,0,22), /* User break After Instruction */ - - EXPPRI(3,0,16,SH4_INTC_NMI) /* NMI */ - /* This is copied to a table, and the IRQ priorities filled in later */ -}; - -static const int exception_codes[] = - -{ 0x000, /* Power-on Reset */ - 0x020, /* Manual Reset */ - 0x000, /* H-UDI Reset */ - 0x140, /* Inst TLB Multiple Hit */ - 0x140, /* Data TLB Multiple Hit */ - - 0x1E0, /* User break Before Instruction */ - 0x0E0, /* Inst Address Error */ - 0x040, /* Inst TLB Miss */ - 0x0A0, /* Inst TLB Protection Violation */ - 0x180, /* Illegal Instruction */ - 0x1A0, /* Slot Illegal Instruction */ - 0x800, /* FPU Disable */ - 0x820, /* Slot FPU Disable */ - 0x0E0, /* Data Address Error (Read) */ - 0x100, /* Data Address Error (Write) */ - 0x040, /* Data TBL Miss Read */ - 0x060, /* Data TBL Miss Write */ - 0x0A0, /* Data TBL Protection Violation Read */ - 0x0C0, /* Data TBL Protection Violation Write */ - 0x120, /* FPU Exception */ - 0x080, /* Initial Page Write exception */ - - 0x160, /* Unconditional TRAP */ - 0x1E0, /* User break After Instruction */ - - 0x1C0, /* NMI */ /* SH4_INTC_NMI=23 represents this location in this list.. */ - - 0x200, /* EX Irq 0 */ - 0x220, /* 1 */ - 0x240, /* 2 */ - 0x260, /* 3 */ - 0x280, /* 4 */ - 0x2A0, /* 5 */ - 0x2C0, /* 6 */ - 0x2E0, /* 7 */ - 0x300, /* 8 */ - 0x320, /* 9 */ - 0x340, /* A */ - 0x360, /* B */ - 0x380, /* C */ - 0x3A0, /* D */ - 0x3C0, /* E */ - - 0x240, /* SH4_INTC_IRL0 */ - 0x2A0, /* SH4_INTC_IRL1 */ - 0x300, /* SH4_INTC_IRL2 */ - 0x360, /* SH4_INTC_IRL3 */ - - 0x600, /* HUDI */ - 0x620, /* SH4_INTC_GPOI */ - 0x640, /* SH4_INTC_DMTE0 */ - 0x660, /* SH4_INTC_DMTE1 */ - 0x680, /* SH4_INTC_DMTE2 */ - 0x6A0, /* SH4_INTC_DMTE3 */ - - 0x780, /* SH4_INTC_DMTE4 */ - 0x7A0, /* SH4_INTC_DMTE5 */ - 0x7C0, /* SH4_INTC_DMTE6 */ - 0x7E0, /* SH4_INTC_DMTE7 */ - - 0x6C0, /* SH4_INTC_DMAE */ - - 0xB00, /* SH4_INTC_TUNI3 */ - 0xB80, /* SH4_INTC_TUNI4 */ - 0x400, /* SH4_INTC_TUNI0 */ - 0x420, /* SH4_INTC_TUNI1 */ - 0x440, /* SH4_INTC_TUNI2 */ - 0x460, /* SH4_INTC_TICPI2 */ - 0x480, /* SH4_INTC_ATI */ - 0x4A0, /* SH4_INTC_PRI */ - 0x4C0, /* SH4_INTC_CUI */ - 0x4E0, /* SH4_INTC_SCI1ERI */ - 0x500, /* SH4_INTC_SCI1RXI */ - 0x520, /* SH4_INTC_SCI1TXI */ - 0x540, /* SH4_INTC_SCI1TEI */ - - 0x700, /* SH4_INTC_SCIFERI */ - 0x720, /* SH4_INTC_SCIFRXI */ - 0x740, /* SH4_INTC_SCIFBRI */ - 0x760, /* SH4_INTC_SCIFTXI */ - 0x560, /* SH4_INTC_ITI */ - 0x580, /* SH4_INTC_RCMI */ - 0x5A0 /* SH4_INTC_ROVI */ -}; - -/* SH3 INTEVT2 uses a different table - values of -1 aren't filled in yet, some may not exist on the sh3. */ -/* The above table should differ too, some things depend on the interrupt level rather than beign fixed values */ - -static const int sh3_intevt2_exception_codes[] = - -{ 0x000, /* Power-on Reset */ - -1, /* Manual Reset */ - -1, /* H-UDI Reset */ - -1, /* Inst TLB Multiple Hit */ - -1, /* Data TLB Multiple Hit */ - - -1, /* User break Before Instruction */ - -1, /* Inst Address Error */ - -1, /* Inst TLB Miss */ - -1, /* Inst TLB Protection Violation */ - -1, /* Illegal Instruction */ - -1, /* Slot Illegal Instruction */ - -1, /* FPU Disable */ - -1, /* Slot FPU Disable */ - -1, /* Data Address Error (Read) */ - -1, /* Data Address Error (Write) */ - -1, /* Data TBL Miss Read */ - -1, /* Data TBL Miss Write */ - -1, /* Data TBL Protection Violation Read */ - -1, /* Data TBL Protection Violation Write */ - -1, /* FPU Exception */ - -1, /* Initial Page Write exception */ - - -1, /* Unconditional TRAP */ - -1, /* User break After Instruction */ - - -1, /* NMI */ /* SH4_INTC_NMI=23 represents this location in this list.. */ - - -1, /* EX Irq 0 */ - -1, /* 1 */ - -1, /* 2 */ - -1, /* 3 */ - -1, /* 4 */ - -1, /* 5 */ - -1, /* 6 */ - -1, /* 7 */ - -1, /* 8 */ - -1, /* 9 */ - -1, /* A */ - -1, /* B */ - -1, /* C */ - -1, /* D */ - -1, /* E */ - - 0x600, /* SH4_INTC_IRL0 */ - 0x620, /* SH4_INTC_IRL1 */ - 0x640, /* SH4_INTC_IRL2 */ - 0x660, /* SH4_INTC_IRL3 */ - /* todo: SH3 should have lines 4+5 too? */ - - -1, /* HUDI */ - -1, /* SH4_INTC_GPOI */ - -1, /* SH4_INTC_DMTE0 */ - -1, /* SH4_INTC_DMTE1 */ - -1, /* SH4_INTC_DMTE2 */ - -1, /* SH4_INTC_DMTE3 */ - - -1, /* SH4_INTC_DMTE4 */ - -1, /* SH4_INTC_DMTE5 */ - -1, /* SH4_INTC_DMTE6 */ - -1, /* SH4_INTC_DMTE7 */ - - -1, /* SH4_INTC_DMAE */ - - -1, /* SH4_INTC_TUNI3 */ - -1, /* SH4_INTC_TUNI4 */ - 0x400, /* SH4_INTC_TUNI0 */ - 0x420, /* SH4_INTC_TUNI1 */ - 0x440, /* SH4_INTC_TUNI2 */ - 0x460, /* SH4_INTC_TICPI2 */ - -1, /* SH4_INTC_ATI */ - -1, /* SH4_INTC_PRI */ - -1, /* SH4_INTC_CUI */ - -1, /* SH4_INTC_SCI1ERI */ - -1, /* SH4_INTC_SCI1RXI */ - -1, /* SH4_INTC_SCI1TXI */ - -1, /* SH4_INTC_SCI1TEI */ - - -1, /* SH4_INTC_SCIFERI */ - -1, /* SH4_INTC_SCIFRXI */ - -1, /* SH4_INTC_SCIFBRI */ - -1, /* SH4_INTC_SCIFTXI */ - -1, /* SH4_INTC_ITI */ - -1, /* SH4_INTC_RCMI */ - -1 /* SH4_INTC_ROVI */ -}; - - - -void sh34_base_device::sh4_change_register_bank(int to) -{ - int s; - - if (to) // 0 -> 1 - { - for (s = 0;s < 8;s++) - { - m_rbnk[0][s] = m_r[s]; - m_r[s] = m_rbnk[1][s]; - } - } - else // 1 -> 0 - { - for (s = 0;s < 8;s++) - { - m_rbnk[1][s] = m_r[s]; - m_r[s] = m_rbnk[0][s]; - } - } -} - -void sh34_base_device::sh4_swap_fp_registers() -{ - int s; - uint32_t z; - - for (s = 0;s <= 15;s++) - { - z = m_fr[s]; - m_fr[s] = m_xf[s]; - m_xf[s] = z; - } -} - -void sh34_base_device::sh4_swap_fp_couples() -{ - int s; - uint32_t z; - - for (s = 0;s <= 15;s = s+2) - { - z = m_fr[s]; - m_fr[s] = m_fr[s + 1]; - m_fr[s + 1] = z; - z = m_xf[s]; - m_xf[s] = m_xf[s + 1]; - m_xf[s + 1] = z; - } -} - -void sh34_base_device::sh4_syncronize_register_bank(int to) -{ - int s; - - for (s = 0;s < 8;s++) - { - m_rbnk[to][s] = m_r[s]; - } -} - -void sh34_base_device::sh4_default_exception_priorities() // setup default priorities for exceptions -{ - int a; - - for (a=0;a <= SH4_INTC_NMI;a++) - m_exception_priority[a] = exception_priority_default[a]; - for (a=SH4_INTC_IRLn0;a <= SH4_INTC_IRLnE;a++) - m_exception_priority[a] = INTPRI(15-(a-SH4_INTC_IRLn0), a); - m_exception_priority[SH4_INTC_IRL0] = INTPRI(13, SH4_INTC_IRL0); - m_exception_priority[SH4_INTC_IRL1] = INTPRI(10, SH4_INTC_IRL1); - m_exception_priority[SH4_INTC_IRL2] = INTPRI(7, SH4_INTC_IRL2); - m_exception_priority[SH4_INTC_IRL3] = INTPRI(4, SH4_INTC_IRL3); - for (a=SH4_INTC_HUDI;a <= SH4_INTC_ROVI;a++) - m_exception_priority[a] = INTPRI(0, a); -} - -void sh34_base_device::sh4_exception_recompute() // checks if there is any interrupt with high enough priority -{ - int a,z; - - m_test_irq = 0; - if ((!m_pending_irq) || ((m_sr & BL) && (m_exception_requesting[SH4_INTC_NMI] == 0))) - return; - z = (m_sr >> 4) & 15; - for (a=0;a <= SH4_INTC_ROVI;a++) - { - if (m_exception_requesting[a]) - { - int pri = (((int)m_exception_priority[a] >> 8) & 255); - //logerror("pri is %02x z is %02x\n",pri,z); - if (pri > z) - { - //logerror("will test\n"); - m_test_irq = 1; // will check for exception at end of instructions - break; - } - } - } -} - -void sh34_base_device::sh4_exception_request(int exception) // start requesting an exception -{ - //logerror("sh4_exception_request a\n"); - if (!m_exception_requesting[exception]) - { - //logerror("sh4_exception_request b\n"); - m_exception_requesting[exception] = 1; - m_pending_irq++; - sh4_exception_recompute(); - } -} - -void sh34_base_device::sh4_exception_unrequest(int exception) // stop requesting an exception -{ - if (m_exception_requesting[exception]) - { - m_exception_requesting[exception] = 0; - m_pending_irq--; - sh4_exception_recompute(); - } -} - -void sh34_base_device::sh4_exception_checkunrequest(int exception) -{ - if (exception == SH4_INTC_NMI) - sh4_exception_unrequest(exception); - if ((exception == SH4_INTC_DMTE0) || (exception == SH4_INTC_DMTE1) || - (exception == SH4_INTC_DMTE2) || (exception == SH4_INTC_DMTE3)) - sh4_exception_unrequest(exception); -} - -void sh34_base_device::sh4_exception(const char *message, int exception) // handle exception -{ - uint32_t vector; - - - if (m_cpu_type == CPU_TYPE_SH4) - { - if (exception < SH4_INTC_NMI) - return; // Not yet supported - if (exception == SH4_INTC_NMI) { - if ((m_sr & BL) && (!(m_m[ICR] & 0x200))) - return; - - m_m[ICR] &= ~0x200; - m_m[INTEVT] = 0x1c0; - - - vector = 0x600; - standard_irq_callback(INPUT_LINE_NMI); - LOG(("SH-4 '%s' nmi exception after [%s]\n", tag(), message)); - } else { - // if ((m_m[ICR] & 0x4000) && (m_nmi_line_state == ASSERT_LINE)) - // return; - if (m_sr & BL) - return; - if (((m_exception_priority[exception] >> 8) & 255) <= ((m_sr >> 4) & 15)) - return; - m_m[INTEVT] = exception_codes[exception]; - vector = 0x600; - if ((exception >= SH4_INTC_IRL0) && (exception <= SH4_INTC_IRL3)) - standard_irq_callback((exception-SH4_INTC_IRL0)+SH4_IRL0); - else - standard_irq_callback(SH4_IRL3+1); - LOG(("SH-4 '%s' interrupt exception #%d after [%s]\n", tag(), exception, message)); - } - } - else /* SH3 exceptions */ - { - /***** ASSUME THIS TO BE WRONG FOR NOW *****/ - - if (exception < SH4_INTC_NMI) - return; // Not yet supported - if (exception == SH4_INTC_NMI) - { - return; - } - else - { - if (m_sr & BL) - return; - if (((m_exception_priority[exception] >> 8) & 255) <= ((m_sr >> 4) & 15)) - return; - - - vector = 0x600; - - if ((exception >= SH4_INTC_IRL0) && (exception <= SH4_INTC_IRL3)) - standard_irq_callback((exception-SH4_INTC_IRL0)+SH4_IRL0); - else - standard_irq_callback(SH4_IRL3+1); - - if (sh3_intevt2_exception_codes[exception]==-1) - fatalerror("sh3_intevt2_exception_codes unpopulated for exception %02x\n", exception); - - m_sh3internal_lower[INTEVT2] = sh3_intevt2_exception_codes[exception]; - m_sh3internal_upper[SH3_EXPEVT_ADDR] = exception_codes[exception]; - - - LOG(("SH-3 '%s' interrupt exception #%d after [%s]\n", tag(), exception, message)); - } - - /***** END ASSUME THIS TO BE WRONG FOR NOW *****/ - } - sh4_exception_checkunrequest(exception); - - m_spc = m_pc; - m_ssr = m_sr; - m_sgr = m_r[15]; - - m_sr |= MD; - if ((machine().debug_flags & DEBUG_FLAG_ENABLED) != 0) - sh4_syncronize_register_bank((m_sr & sRB) >> 29); - if (!(m_sr & sRB)) - sh4_change_register_bank(1); - m_sr |= sRB; - m_sr |= BL; - sh4_exception_recompute(); - - /* fetch PC */ - m_pc = m_vbr + vector; - /* wake up if a sleep opcode is triggered */ - if(m_sleep_mode == 1) { m_sleep_mode = 2; } -} - - -uint32_t sh34_base_device::compute_ticks_refresh_timer(emu_timer *timer, int hertz, int base, int divisor) -{ - // elapsed:total = x : ticks - // x=elapsed*tics/total -> x=elapsed*(double)100000000/rtcnt_div[(m_m[RTCSR] >> 3) & 7] - // ticks/total=ticks / ((rtcnt_div[(m_m[RTCSR] >> 3) & 7] * ticks) / 100000000)=1/((rtcnt_div[(m_m[RTCSR] >> 3) & 7] / 100000000)=100000000/rtcnt_div[(m_m[RTCSR] >> 3) & 7] - return base + (uint32_t)((timer->elapsed().as_double() * (double)hertz) / (double)divisor); -} - -void sh34_base_device::sh4_refresh_timer_recompute() -{ - uint32_t ticks; - - if (m_cpu_type != CPU_TYPE_SH4) - fatalerror("sh4_refresh_timer_recompute uses m_m[] with SH3\n"); - - - //if rtcnt < rtcor then rtcor-rtcnt - //if rtcnt >= rtcor then 256-rtcnt+rtcor=256+rtcor-rtcnt - ticks = m_m[RTCOR]-m_m[RTCNT]; - if (ticks <= 0) - ticks = 256 + ticks; - m_refresh_timer->adjust(attotime::from_hz(m_bus_clock) * rtcnt_div[(m_m[RTCSR] >> 3) & 7] * ticks); - m_refresh_timer_base = m_m[RTCNT]; -} - - -TIMER_CALLBACK_MEMBER( sh34_base_device::sh4_refresh_timer_callback ) -{ - if (m_cpu_type != CPU_TYPE_SH4) - fatalerror("sh4_refresh_timer_callback uses m_m[] with SH3\n"); - - m_m[RTCNT] = 0; - sh4_refresh_timer_recompute(); - m_m[RTCSR] |= 128; - if ((m_m[MCR] & 4) && !(m_m[MCR] & 2)) - { - m_m[RFCR] = (m_m[RFCR] + 1) & 1023; - if (((m_m[RTCSR] & 1) && (m_m[RFCR] == 512)) || (m_m[RFCR] == 0)) - { - m_m[RFCR] = 0; - m_m[RTCSR] |= 4; - } - } -} - -void sh34_base_device::increment_rtc_time(int mode) -{ - int carry, year, leap, days; - - if (m_cpu_type != CPU_TYPE_SH4) - fatalerror("increment_rtc_time uses m_m[] with SH3\n"); - - if (mode == 0) - { - carry = 0; - m_m[RSECCNT] = m_m[RSECCNT] + 1; - if ((m_m[RSECCNT] & 0xf) == 0xa) - m_m[RSECCNT] = m_m[RSECCNT] + 6; - if (m_m[RSECCNT] == 0x60) - { - m_m[RSECCNT] = 0; - carry=1; - } - else - return; - } - else - carry = 1; - - m_m[RMINCNT] = m_m[RMINCNT] + carry; - if ((m_m[RMINCNT] & 0xf) == 0xa) - m_m[RMINCNT] = m_m[RMINCNT] + 6; - carry=0; - if (m_m[RMINCNT] == 0x60) - { - m_m[RMINCNT] = 0; - carry = 1; - } - - m_m[RHRCNT] = m_m[RHRCNT] + carry; - if ((m_m[RHRCNT] & 0xf) == 0xa) - m_m[RHRCNT] = m_m[RHRCNT] + 6; - carry = 0; - if (m_m[RHRCNT] == 0x24) - { - m_m[RHRCNT] = 0; - carry = 1; - } - - m_m[RWKCNT] = m_m[RWKCNT] + carry; - if (m_m[RWKCNT] == 0x7) - { - m_m[RWKCNT] = 0; - } - - days = 0; - year = (m_m[RYRCNT] & 0xf) + ((m_m[RYRCNT] & 0xf0) >> 4)*10 + ((m_m[RYRCNT] & 0xf00) >> 8)*100 + ((m_m[RYRCNT] & 0xf000) >> 12)*1000; - leap = 0; - if (!(year%100)) - { - if (!(year%400)) - leap = 1; - } - else if (!(year%4)) - leap = 1; - if (m_m[RMONCNT] != 2) - leap = 0; - if (m_m[RMONCNT]) - days = daysmonth[(m_m[RMONCNT] & 0xf) + ((m_m[RMONCNT] & 0xf0) >> 4)*10 - 1]; - - m_m[RDAYCNT] = m_m[RDAYCNT] + carry; - if ((m_m[RDAYCNT] & 0xf) == 0xa) - m_m[RDAYCNT] = m_m[RDAYCNT] + 6; - carry = 0; - if (m_m[RDAYCNT] > (days+leap)) - { - m_m[RDAYCNT] = 1; - carry = 1; - } - - m_m[RMONCNT] = m_m[RMONCNT] + carry; - if ((m_m[RMONCNT] & 0xf) == 0xa) - m_m[RMONCNT] = m_m[RMONCNT] + 6; - carry=0; - if (m_m[RMONCNT] == 0x13) - { - m_m[RMONCNT] = 1; - carry = 1; - } - - m_m[RYRCNT] = m_m[RYRCNT] + carry; - if ((m_m[RYRCNT] & 0xf) >= 0xa) - m_m[RYRCNT] = m_m[RYRCNT] + 6; - if ((m_m[RYRCNT] & 0xf0) >= 0xa0) - m_m[RYRCNT] = m_m[RYRCNT] + 0x60; - if ((m_m[RYRCNT] & 0xf00) >= 0xa00) - m_m[RYRCNT] = m_m[RYRCNT] + 0x600; - if ((m_m[RYRCNT] & 0xf000) >= 0xa000) - m_m[RYRCNT] = 0; -} - -TIMER_CALLBACK_MEMBER( sh34_base_device::sh4_rtc_timer_callback ) -{ - if (m_cpu_type != CPU_TYPE_SH4) - { - logerror("sh4_rtc_timer_callback uses m_m[] with SH3\n"); - return; - } - - m_rtc_timer->adjust(attotime::from_hz(128)); - m_m[R64CNT] = (m_m[R64CNT]+1) & 0x7f; - if (m_m[R64CNT] == 64) - { - m_m[RCR1] |= 0x80; - increment_rtc_time(0); - //sh4_exception_request(SH4_INTC_NMI); // TEST - } -} - - -void sh34_base_device::sh4_dmac_nmi() // manage dma when nmi gets asserted -{ - int s; - - m_SH4_DMAOR |= DMAOR_NMIF; - for (s = 0;s < 4;s++) - { - if (m_dma_timer_active[s]) - { - logerror("SH4: DMA %d cancelled due to NMI but all data transferred", s); - m_dma_timer[s]->adjust(attotime::never, s); - m_dma_timer_active[s] = 0; - } - } -} - -void sh34_base_device::sh4_handler_ipra_w(uint32_t data, uint32_t mem_mask) -{ - COMBINE_DATA(&m_SH4_IPRA); - /* 15 - 12 TMU0 */ - /* 11 - 8 TMU1 */ - /* 7 - 4 TMU2 */ - /* 3 - 0 RTC */ - m_exception_priority[SH4_INTC_ATI] = INTPRI(m_SH4_IPRA & 0x000f, SH4_INTC_ATI); - m_exception_priority[SH4_INTC_PRI] = INTPRI(m_SH4_IPRA & 0x000f, SH4_INTC_PRI); - m_exception_priority[SH4_INTC_CUI] = INTPRI(m_SH4_IPRA & 0x000f, SH4_INTC_CUI); - - m_exception_priority[SH4_INTC_TUNI2] = INTPRI((m_SH4_IPRA & 0x00f0) >> 4, SH4_INTC_TUNI2); - m_exception_priority[SH4_INTC_TICPI2] = INTPRI((m_SH4_IPRA & 0x00f0) >> 4, SH4_INTC_TICPI2); - - m_exception_priority[SH4_INTC_TUNI1] = INTPRI((m_SH4_IPRA & 0x0f00) >> 8, SH4_INTC_TUNI1); - - m_exception_priority[SH4_INTC_TUNI0] = INTPRI((m_SH4_IPRA & 0xf000) >> 12, SH4_INTC_TUNI0); - - logerror("setting priorities TMU0 %01x TMU1 %01x TMU2 %01x RTC %01x\n", (m_SH4_IPRA & 0xf000)>>12, (m_SH4_IPRA & 0x0f00)>>8, (m_SH4_IPRA & 0x00f0)>>4, (m_SH4_IPRA & 0x000f)>>0); - - sh4_exception_recompute(); -} - - -WRITE32_MEMBER( sh4_base_device::sh4_internal_w ) -{ - int a; - uint32_t addr = (offset << 2) + 0xfe000000; - offset = ((addr & 0xfc) >> 2) | ((addr & 0x1fe0000) >> 11); - - if (m_cpu_type != CPU_TYPE_SH4) - fatalerror("sh4_internal_w uses m_m[] with SH3\n"); - - uint32_t old = m_m[offset]; - COMBINE_DATA(m_m+offset); - -// printf("sh4_internal_w: Write %08x (%x), %08x @ %08x\n", 0xfe000000+((offset & 0x3fc0) << 11)+((offset & 0x3f) << 2), offset, data, mem_mask); - - switch( offset ) - { - case PTEH: // for use with LDTLB opcode - m_m[PTEH] &= 0xffffffff; - /* - NNNN NNNN NNNN NNNN NNNN NN-- AAAA AAAA - - N = VPM = Virtual Page Number - A = ASID = Address Space Identifier - - same as the address table part of the utlb but with 2 unused bits (these are sourced from PTEL instead when LDTLB is called) - */ - - - break; - - case PTEL: - m_m[PTEL] &= 0xffffffff; - /* - ---P PPPP PPPP PPPP PPPP PP-V zRRz CDHW - - same format as data array 1 of the utlb - */ - break; - - case PTEA: - m_m[PTEA] &= 0xffffffff; - /* - ---- ---- ---- ---- ---- ---- ---- TSSS - - same format as data array 2 of the utlb - */ - break; - - case TTB: - m_m[TTB] &= 0xffffffff; - logerror("TTB set to %08x\n", data); - break; - - case TEA: - m_m[TEA] &= 0xffffffff; - logerror("TEA set to %08x\n", data); - break; - - - case MMUCR: // MMU Control - logerror("%s: MMUCR %08x\n", machine().describe_context(), data); - m_m[MMUCR] &= 0xffffffff; - /* - LLLL LL-- BBBB BB-- CCCC CCQV ---- -T-A - - L = LRUI = Least recently used ITLB - B = URB = UTLB replace boundary - C = URC = UTLB replace counter - Q = SQMD = Store Queue Mode Bit - V = SV = Single Virtual Mode Bit - T = TI = TLB invaldiate - A = AT = Address translation bit (enable) - */ - - - - if (data & MMUCR_AT) - { - m_sh4_mmu_enabled = 1; - - - if (m_mmuhack == 1) - { - printf("SH4 MMU Enabled\n"); - printf("If you're seeing this, but running something other than a Naomi GD-ROM game then chances are it won't work\n"); - printf("The MMU emulation is a hack specific to that system\n"); - } - - - if (m_mmuhack == 2) - { - for (int i = 0;i < 64;i++) - { - if (m_utlb[i].V) - { - printf("(entry %02x | ASID: %02x VPN: %08x V: %02x PPN: %08x SZ: %02x SH: %02x C: %02x PPR: %02x D: %02x WT %02x: SA: %02x TC: %02x)\n", - i, - m_utlb[i].ASID, - m_utlb[i].VPN << 10, - m_utlb[i].V, - m_utlb[i].PPN << 10, - m_utlb[i].PSZ, - m_utlb[i].SH, - m_utlb[i].C, - m_utlb[i].PPR, - m_utlb[i].D, - m_utlb[i].WT, - m_utlb[i].SA, - m_utlb[i].TC); - } - } - } - - - } - else - { - m_sh4_mmu_enabled = 0; - } - - break; - - // Memory refresh - case RTCSR: - m_m[RTCSR] &= 255; - if ((old >> 3) & 7) - m_m[RTCNT] = compute_ticks_refresh_timer(m_refresh_timer, m_bus_clock, m_refresh_timer_base, rtcnt_div[(old >> 3) & 7]) & 0xff; - if ((m_m[RTCSR] >> 3) & 7) - { // activated - sh4_refresh_timer_recompute(); - } - else - { - m_refresh_timer->adjust(attotime::never); - } - break; - - case RTCNT: - m_m[RTCNT] &= 255; - if ((m_m[RTCSR] >> 3) & 7) - { // active - sh4_refresh_timer_recompute(); - } - break; - - case RTCOR: - m_m[RTCOR] &= 255; - if ((m_m[RTCSR] >> 3) & 7) - { // active - m_m[RTCNT] = compute_ticks_refresh_timer(m_refresh_timer, m_bus_clock, m_refresh_timer_base, rtcnt_div[(m_m[RTCSR] >> 3) & 7]) & 0xff; - sh4_refresh_timer_recompute(); - } - break; - - case RFCR: - m_m[RFCR] &= 1023; - break; - - // RTC - case RCR1: - if ((m_m[RCR1] & 8) && (~old & 8)) // 0 -> 1 - m_m[RCR1] ^= 1; - break; - - case RCR2: - if (m_m[RCR2] & 2) - { - m_m[R64CNT] = 0; - m_m[RCR2] ^= 2; - } - if (m_m[RCR2] & 4) - { - m_m[R64CNT] = 0; - if (m_m[RSECCNT] >= 30) - increment_rtc_time(1); - m_m[RSECCNT] = 0; - } - if ((m_m[RCR2] & 8) && (~old & 8)) - { // 0 -> 1 - m_rtc_timer->adjust(attotime::from_hz(128)); - } - else if (~(m_m[RCR2]) & 8) - { // 0 - m_rtc_timer->adjust(attotime::never); - } - break; - -/********************************************************************************************************************* - TMU (Timer Unit) -*********************************************************************************************************************/ - case SH4_TSTR_ADDR: sh4_handle_tstr_addr_w(data,mem_mask); break; - case SH4_TCR0_ADDR: sh4_handle_tcr0_addr_w(data,mem_mask); break; - case SH4_TCR1_ADDR: sh4_handle_tcr1_addr_w(data,mem_mask); break; - case SH4_TCR2_ADDR: sh4_handle_tcr2_addr_w(data,mem_mask); break; - case SH4_TCOR0_ADDR: sh4_handle_tcor0_addr_w(data,mem_mask); break; - case SH4_TCNT0_ADDR: sh4_handle_tcnt0_addr_w(data,mem_mask); break; - case SH4_TCOR1_ADDR: sh4_handle_tcor1_addr_w(data,mem_mask); break; - case SH4_TCNT1_ADDR: sh4_handle_tcnt1_addr_w(data,mem_mask); break; - case SH4_TCOR2_ADDR: sh4_handle_tcor2_addr_w(data,mem_mask); break; - case SH4_TCNT2_ADDR: sh4_handle_tcnt2_addr_w(data,mem_mask); break; - case SH4_TOCR_ADDR: sh4_handle_tocr_addr_w(data,mem_mask); break; // not supported - case SH4_TCPR2_ADDR: sh4_handle_tcpr2_addr_w(data,mem_mask); break; // not supported -/********************************************************************************************************************* - INTC (Interrupt Controller) -*********************************************************************************************************************/ - case ICR: - m_m[ICR] = (m_m[ICR] & 0x7fff) | (old & 0x8000); - break; - case IPRA: sh4_handler_ipra_w(data, mem_mask); break; - case IPRB: - m_exception_priority[SH4_INTC_SCI1ERI] = INTPRI((m_m[IPRB] & 0x00f0) >> 4, SH4_INTC_SCI1ERI); - m_exception_priority[SH4_INTC_SCI1RXI] = INTPRI((m_m[IPRB] & 0x00f0) >> 4, SH4_INTC_SCI1RXI); - m_exception_priority[SH4_INTC_SCI1TXI] = INTPRI((m_m[IPRB] & 0x00f0) >> 4, SH4_INTC_SCI1TXI); - m_exception_priority[SH4_INTC_SCI1TEI] = INTPRI((m_m[IPRB] & 0x00f0) >> 4, SH4_INTC_SCI1TEI); - m_exception_priority[SH4_INTC_RCMI] = INTPRI((m_m[IPRB] & 0x0f00) >> 8, SH4_INTC_RCMI); - m_exception_priority[SH4_INTC_ROVI] = INTPRI((m_m[IPRB] & 0x0f00) >> 8, SH4_INTC_ROVI); - m_exception_priority[SH4_INTC_ITI] = INTPRI((m_m[IPRB] & 0xf000) >> 12, SH4_INTC_ITI); - sh4_exception_recompute(); - break; - case IPRC: - m_exception_priority[SH4_INTC_HUDI] = INTPRI(m_m[IPRC] & 0x000f, SH4_INTC_HUDI); - m_exception_priority[SH4_INTC_SCIFERI] = INTPRI((m_m[IPRC] & 0x00f0) >> 4, SH4_INTC_SCIFERI); - m_exception_priority[SH4_INTC_SCIFRXI] = INTPRI((m_m[IPRC] & 0x00f0) >> 4, SH4_INTC_SCIFRXI); - m_exception_priority[SH4_INTC_SCIFBRI] = INTPRI((m_m[IPRC] & 0x00f0) >> 4, SH4_INTC_SCIFBRI); - m_exception_priority[SH4_INTC_SCIFTXI] = INTPRI((m_m[IPRC] & 0x00f0) >> 4, SH4_INTC_SCIFTXI); - m_exception_priority[SH4_INTC_DMTE0] = INTPRI((m_m[IPRC] & 0x0f00) >> 8, SH4_INTC_DMTE0); - m_exception_priority[SH4_INTC_DMTE1] = INTPRI((m_m[IPRC] & 0x0f00) >> 8, SH4_INTC_DMTE1); - m_exception_priority[SH4_INTC_DMTE2] = INTPRI((m_m[IPRC] & 0x0f00) >> 8, SH4_INTC_DMTE2); - m_exception_priority[SH4_INTC_DMTE3] = INTPRI((m_m[IPRC] & 0x0f00) >> 8, SH4_INTC_DMTE3); - m_exception_priority[SH4_INTC_DMAE] = INTPRI((m_m[IPRC] & 0x0f00) >> 8, SH4_INTC_DMAE); - m_exception_priority[SH4_INTC_GPOI] = INTPRI((m_m[IPRC] & 0xf000) >> 12, SH4_INTC_GPOI); - sh4_exception_recompute(); - break; -/********************************************************************************************************************* - DMAC (DMA Controller) -*********************************************************************************************************************/ - case SH4_SAR0_ADDR: sh4_handle_sar0_addr_w(data,mem_mask); break; - case SH4_SAR1_ADDR: sh4_handle_sar1_addr_w(data,mem_mask); break; - case SH4_SAR2_ADDR: sh4_handle_sar2_addr_w(data,mem_mask); break; - case SH4_SAR3_ADDR: sh4_handle_sar3_addr_w(data,mem_mask); break; - case SH4_DAR0_ADDR: sh4_handle_dar0_addr_w(data,mem_mask); break; - case SH4_DAR1_ADDR: sh4_handle_dar1_addr_w(data,mem_mask); break; - case SH4_DAR2_ADDR: sh4_handle_dar2_addr_w(data,mem_mask); break; - case SH4_DAR3_ADDR: sh4_handle_dar3_addr_w(data,mem_mask); break; - case SH4_DMATCR0_ADDR: sh4_handle_dmatcr0_addr_w(data,mem_mask); break; - case SH4_DMATCR1_ADDR: sh4_handle_dmatcr1_addr_w(data,mem_mask); break; - case SH4_DMATCR2_ADDR: sh4_handle_dmatcr2_addr_w(data,mem_mask); break; - case SH4_DMATCR3_ADDR: sh4_handle_dmatcr3_addr_w(data,mem_mask); break; - case SH4_CHCR0_ADDR: sh4_handle_chcr0_addr_w(data,mem_mask); break; - case SH4_CHCR1_ADDR: sh4_handle_chcr1_addr_w(data,mem_mask); break; - case SH4_CHCR2_ADDR: sh4_handle_chcr2_addr_w(data,mem_mask); break; - case SH4_CHCR3_ADDR: sh4_handle_chcr3_addr_w(data,mem_mask); break; - case SH4_DMAOR_ADDR: sh4_handle_dmaor_addr_w(data,mem_mask); break; -/********************************************************************************************************************* - Store Queues -*********************************************************************************************************************/ - case QACR0: - case QACR1: - break; -/********************************************************************************************************************* - I/O -*********************************************************************************************************************/ - case PCTRA: - m_ioport16_pullup = 0; - m_ioport16_direction = 0; - for (a=0;a < 16;a++) { - m_ioport16_direction |= (m_m[PCTRA] & (1 << (a*2))) >> a; - m_ioport16_pullup |= (m_m[PCTRA] & (1 << (a*2+1))) >> (a+1); - } - m_ioport16_direction &= 0xffff; - m_ioport16_pullup = (m_ioport16_pullup | m_ioport16_direction) ^ 0xffff; - if (m_m[BCR2] & 1) - m_io->write_dword(SH4_IOPORT_16, (uint64_t)(m_m[PDTRA] & m_ioport16_direction) | ((uint64_t)m_m[PCTRA] << 16)); - break; - case PDTRA: - if (m_m[BCR2] & 1) - m_io->write_dword(SH4_IOPORT_16, (uint64_t)(m_m[PDTRA] & m_ioport16_direction) | ((uint64_t)m_m[PCTRA] << 16)); - break; - case PCTRB: - m_ioport4_pullup = 0; - m_ioport4_direction = 0; - for (a=0;a < 4;a++) { - m_ioport4_direction |= (m_m[PCTRB] & (1 << (a*2))) >> a; - m_ioport4_pullup |= (m_m[PCTRB] & (1 << (a*2+1))) >> (a+1); - } - m_ioport4_direction &= 0xf; - m_ioport4_pullup = (m_ioport4_pullup | m_ioport4_direction) ^ 0xf; - if (m_m[BCR2] & 1) - m_io->write_dword(SH4_IOPORT_4, (m_m[PDTRB] & m_ioport4_direction) | (m_m[PCTRB] << 16)); - break; - case PDTRB: - if (m_m[BCR2] & 1) - m_io->write_dword(SH4_IOPORT_4, (m_m[PDTRB] & m_ioport4_direction) | (m_m[PCTRB] << 16)); - break; - - case SCBRR2: - break; - - case SCSPTR2: //trips often in aristocrat mk-6 - break; - - default: - logerror("sh4_internal_w: Unmapped write %08x, %08x @ %08x\n", 0xfe000000+((offset & 0x3fc0) << 11)+((offset & 0x3f) << 2), data, mem_mask); - break; - } -} - -READ32_MEMBER( sh4_base_device::sh4_internal_r ) -{ - if (m_cpu_type != CPU_TYPE_SH4) - fatalerror("sh4_internal_r uses m_m[] with SH3\n"); - - uint32_t addr = (offset << 2) + 0xfe000000; - offset = ((addr & 0xfc) >> 2) | ((addr & 0x1fe0000) >> 11); - -// printf("sh4_internal_r: Read %08x (%x) @ %08x\n", 0xfe000000+((offset & 0x3fc0) << 11)+((offset & 0x3f) << 2), offset, mem_mask); - - switch( offset ) - { - case VERSION: - return PVR_SH7091; // 0x040205c1, this is what a real SH7091 in a Dreamcast returns - the later Naomi BIOSes check and care! - case PRR: - return 0; - case IPRD: - return 0x00000000; // SH7750 ignores writes here and always returns zero - case RTCNT: - if ((m_m[RTCSR] >> 3) & 7) - { // activated - //((double)rtcnt_div[(m_m[RTCSR] >> 3) & 7] / (double)100000000) - //return (refresh_timer_base + (m_refresh_timer->elapsed() * (double)100000000) / (double)rtcnt_div[(m_m[RTCSR] >> 3) & 7]) & 0xff; - return compute_ticks_refresh_timer(m_refresh_timer, m_bus_clock, m_refresh_timer_base, rtcnt_div[(m_m[RTCSR] >> 3) & 7]) & 0xff; - } - else - return m_m[RTCNT]; - -/********************************************************************************************************************* - INTC (Interrupt Controller) -*********************************************************************************************************************/ - - case IPRA: - return m_SH4_IPRA; - -/********************************************************************************************************************* - TMU (Timer Unit) -*********************************************************************************************************************/ - case SH4_TSTR_ADDR: return sh4_handle_tstr_addr_r(mem_mask); - case SH4_TCR0_ADDR: return sh4_handle_tcr0_addr_r(mem_mask); - case SH4_TCR1_ADDR: return sh4_handle_tcr1_addr_r(mem_mask); - case SH4_TCR2_ADDR: return sh4_handle_tcr2_addr_r(mem_mask); - case SH4_TCNT0_ADDR: return sh4_handle_tcnt0_addr_r(mem_mask); - case SH4_TCNT1_ADDR: return sh4_handle_tcnt1_addr_r(mem_mask); - case SH4_TCNT2_ADDR: return sh4_handle_tcnt2_addr_r(mem_mask); - case SH4_TCOR0_ADDR: return sh4_handle_tcor0_addr_r(mem_mask); - case SH4_TCOR1_ADDR: return sh4_handle_tcor1_addr_r(mem_mask); - case SH4_TCOR2_ADDR: return sh4_handle_tcor2_addr_r(mem_mask); - case SH4_TOCR_ADDR: return sh4_handle_tocr_addr_r(mem_mask); // not supported - case SH4_TCPR2_ADDR: return sh4_handle_tcpr2_addr_r(mem_mask); // not supported -/********************************************************************************************************************* - DMAC (DMA Controller) -*********************************************************************************************************************/ - case SH4_SAR0_ADDR: return sh4_handle_sar0_addr_r(mem_mask); - case SH4_SAR1_ADDR: return sh4_handle_sar1_addr_r(mem_mask); - case SH4_SAR2_ADDR: return sh4_handle_sar2_addr_r(mem_mask); - case SH4_SAR3_ADDR: return sh4_handle_sar3_addr_r(mem_mask); - case SH4_DAR0_ADDR: return sh4_handle_dar0_addr_r(mem_mask); - case SH4_DAR1_ADDR: return sh4_handle_dar1_addr_r(mem_mask); - case SH4_DAR2_ADDR: return sh4_handle_dar2_addr_r(mem_mask); - case SH4_DAR3_ADDR: return sh4_handle_dar3_addr_r(mem_mask); - case SH4_DMATCR0_ADDR: return sh4_handle_dmatcr0_addr_r(mem_mask); - case SH4_DMATCR1_ADDR: return sh4_handle_dmatcr1_addr_r(mem_mask); - case SH4_DMATCR2_ADDR: return sh4_handle_dmatcr2_addr_r(mem_mask); - case SH4_DMATCR3_ADDR: return sh4_handle_dmatcr3_addr_r(mem_mask); - case SH4_CHCR0_ADDR: return sh4_handle_chcr0_addr_r(mem_mask); - case SH4_CHCR1_ADDR: return sh4_handle_chcr1_addr_r(mem_mask); - case SH4_CHCR2_ADDR: return sh4_handle_chcr2_addr_r(mem_mask); - case SH4_CHCR3_ADDR: return sh4_handle_chcr3_addr_r(mem_mask); - case SH4_DMAOR_ADDR: return sh4_handle_dmaor_addr_r(mem_mask); -/********************************************************************************************************************* - I/O Ports -*********************************************************************************************************************/ - - case PDTRA: - if (m_m[BCR2] & 1) - return (m_io->read_dword(SH4_IOPORT_16) & ~m_ioport16_direction) | (m_m[PDTRA] & m_ioport16_direction); - break; - case PDTRB: - if (m_m[BCR2] & 1) - return (m_io->read_dword(SH4_IOPORT_4) & ~m_ioport4_direction) | (m_m[PDTRB] & m_ioport4_direction); - break; - - // SCIF (UART with FIFO) - case SCFSR2: - return 0x60; //read-only status register - } - return m_m[offset]; -} - -void sh34_base_device::sh4_set_frt_input(int state) -{ - if (m_cpu_type != CPU_TYPE_SH4) - fatalerror("sh4_set_frt_input uses m_m[] with SH3\n"); - - if(state == PULSE_LINE) - { - sh4_set_frt_input(ASSERT_LINE); - sh4_set_frt_input(CLEAR_LINE); - return; - } - - if(m_frt_input == state) { - return; - } - - m_frt_input = state; - - if (m_cpu_type == CPU_TYPE_SH4) - { - if(m_m[5] & 0x8000) { - if(state == CLEAR_LINE) { - return; - } - } else { - if(state == ASSERT_LINE) { - return; - } - } - } - else - { - fatalerror("sh4_set_frt_input uses m_m[] with SH3\n"); - } - -#if 0 - sh4_timer_resync(); - m_icr = m_frc; - m_m[4] |= ICF; - logerror("SH4 '%s': ICF activated (%x)\n", tag(), m_pc & AM); - sh4_recalc_irq(); -#endif -} - -void sh34_base_device::sh4_set_irln_input(int value) -{ - if (m_irln == value) - return; - m_irln = value; - set_input_line(SH4_IRLn, ASSERT_LINE); - set_input_line(SH4_IRLn, CLEAR_LINE); -} - -void sh34_base_device::execute_set_input(int irqline, int state) // set state of external interrupt line -{ - if (m_cpu_type == CPU_TYPE_SH3) - { - /***** ASSUME THIS TO BE WRONG FOR NOW *****/ - - if (irqline == INPUT_LINE_NMI) - { - fatalerror("SH3 NMI Unimplemented\n"); - } - else - { - //if (irqline > SH4_IRL3) - // return; - if (m_irq_line_state[irqline] == state) - return; - m_irq_line_state[irqline] = state; - - if( state == CLEAR_LINE ) - { - LOG(("SH-4 '%s' cleared external irq IRL%d\n", tag(), irqline)); - sh4_exception_unrequest(SH4_INTC_IRL0+irqline-SH4_IRL0); - } - else - { - LOG(("SH-4 '%s' assert external irq IRL%d\n", tag(), irqline)); - sh4_exception_request(SH4_INTC_IRL0+irqline-SH4_IRL0); - } - - } - - /***** END ASSUME THIS TO BE WRONG FOR NOW *****/ - } - else - { - int s; - - if (irqline == INPUT_LINE_NMI) - { - if (m_nmi_line_state == state) - return; - if (m_m[ICR] & 0x100) - { - if ((state == CLEAR_LINE) && (m_nmi_line_state == ASSERT_LINE)) // rising - { - LOG(("SH-4 '%s' assert nmi\n", tag())); - sh4_exception_request(SH4_INTC_NMI); - sh4_dmac_nmi(); - } - } - else - { - if ((state == ASSERT_LINE) && (m_nmi_line_state == CLEAR_LINE)) // falling - { - LOG(("SH-4 '%s' assert nmi\n", tag())); - sh4_exception_request(SH4_INTC_NMI); - sh4_dmac_nmi(); - } - } - if (state == CLEAR_LINE) - m_m[ICR] ^= 0x8000; - else - m_m[ICR] |= 0x8000; - m_nmi_line_state = state; - } - else - { - if (m_m[ICR] & 0x80) // four independent external interrupt sources - { - if (irqline > SH4_IRL3) - return; - if (m_irq_line_state[irqline] == state) - return; - m_irq_line_state[irqline] = state; - - if( state == CLEAR_LINE ) - { - LOG(("SH-4 '%s' cleared external irq IRL%d\n", tag(), irqline)); - sh4_exception_unrequest(SH4_INTC_IRL0+irqline-SH4_IRL0); - } - else - { - LOG(("SH-4 '%s' assert external irq IRL%d\n", tag(), irqline)); - sh4_exception_request(SH4_INTC_IRL0+irqline-SH4_IRL0); - } - } - else // level-encoded interrupt - { - if (irqline != SH4_IRLn) - return; - if ((m_irln > 15) || (m_irln < 0)) - return; - for (s = 0; s < 15; s++) - sh4_exception_unrequest(SH4_INTC_IRLn0+s); - if (m_irln < 15) - sh4_exception_request(SH4_INTC_IRLn0+m_irln); - LOG(("SH-4 '%s' IRLn0-IRLn3 level #%d\n", tag(), m_irln)); - } - } - if (m_test_irq && (!m_delay)) - sh4_check_pending_irq("sh4_set_irq_line"); - } -} - -void sh34_base_device::sh4_parse_configuration() -{ - if(c_clock > 0) - { - switch((c_md2 << 2) | (c_md1 << 1) | (c_md0)) - { - case 0: - m_cpu_clock = c_clock; - m_bus_clock = c_clock / 4; - m_pm_clock = c_clock / 4; - break; - case 1: - m_cpu_clock = c_clock; - m_bus_clock = c_clock / 6; - m_pm_clock = c_clock / 6; - break; - case 2: - m_cpu_clock = c_clock; - m_bus_clock = c_clock / 3; - m_pm_clock = c_clock / 6; - break; - case 3: - m_cpu_clock = c_clock; - m_bus_clock = c_clock / 3; - m_pm_clock = c_clock / 6; - break; - case 4: - m_cpu_clock = c_clock; - m_bus_clock = c_clock / 2; - m_pm_clock = c_clock / 4; - break; - case 5: - m_cpu_clock = c_clock; - m_bus_clock = c_clock / 2; - m_pm_clock = c_clock / 4; - break; - } - m_is_slave = (~(c_md7)) & 1; - } - else - { - m_cpu_clock = 200000000; - m_bus_clock = 100000000; - m_pm_clock = 50000000; - m_is_slave = 0; - } -} - -uint32_t sh34_base_device::get_remap(uint32_t address) -{ - return address; -} - -uint32_t sh4_base_device::get_remap(uint32_t address) -{ - if (m_mmuhack != 2) - return address; - - // is this the correct way around? - int i; - uint32_t topaddr = address&0xfff00000; - - for (i=0;i<64;i++) - { - if (m_utlb[i].V) - { - uint32_t topcmp = (m_utlb[i].PPN << 10) & 0xfff00000; - if (topcmp == topaddr) - return (address & 0x000fffff) | ((m_utlb[i].VPN << 10) & 0xfff00000); - } - } - - //printf("address not in UTLB? %08x\n", address); - - - return address; -} - -uint32_t sh34_base_device::sh4_getsqremap(uint32_t address) -{ - return address; -} - -uint32_t sh4_base_device::sh4_getsqremap(uint32_t address) -{ - if (!m_sh4_mmu_enabled || (m_mmuhack != 1)) - return address; - else - { - int i; - uint32_t topaddr = address&0xfff00000; - - for (i=0;i<64;i++) - { - uint32_t topcmp = (m_utlb[i].VPN<<10)&0xfff00000; - if (topcmp==topaddr) - return (address&0x000fffff) | ((m_utlb[i].PPN<<10)&0xfff00000); - } - } - - return address; -} - - -WRITE64_MEMBER( sh4_base_device::sh4_utlb_address_array_w ) -{ -/* uses bits 13:8 of address to select which UTLB entry we're addressing - bit 7 of the address enables 'associative' mode, causing a search - operation rather than a direct write. - - NNNN NNNN NNNN NNNN NNNN NNDV AAAA AAAA - - N = VPN = Virtual Page Number - D = Dirty Bit - V = Validity Bit - A = ASID = Address Space Identifier -*/ - - logerror("sh4_utlb_address_array_w %08x %08x\n", offset, data); - int offs = offset << 3; - - uint8_t associative = (offs >> 7) & 1; - - if (!associative) - { - // non-associative mode - uint8_t i = (offs >> 8) & 63; - - m_utlb[i].VPN = (data & 0xfffffc00) >> 10; - m_utlb[i].D = (data & 0x00000200) >> 9; - m_utlb[i].V = (data & 0x00000100) >> 8; - m_utlb[i].ASID = (data & 0x000000ff) >> 0; - } - else - { - // associative mode - fatalerror("SH4MMU: associative mode writes unsupported\n"); - } -} - -READ64_MEMBER( sh4_base_device::sh4_utlb_address_array_r ) -{ - // associative bit is ignored for reads - int offs = offset*8; - - uint32_t ret = 0; - - uint8_t i = (offs >> 8) & 63; - - ret |= m_utlb[i].VPN << 10; - ret |= m_utlb[i].D << 9; - ret |= m_utlb[i].V << 8; - ret |= m_utlb[i].ASID << 0; - - return ret; -} - - -WRITE64_MEMBER( sh4_base_device::sh4_utlb_data_array1_w ) -{ -/* uses bits 13:8 of address to select which UTLB entry we're addressing - - ---P PPPP PPPP PPPP PPPP PP-V zRRz CDHW - - P = PPN = Physical page number - V = Validity bit - z = SZ = Page Size (2 bits, split) - D = Dirty Bit - R = PR = Protection Key Data - C = Cacheable bit - H = Share status - W = Write through - - = unused (should be 0) -*/ - logerror("sh4_utlb_data_array1_w %08x %08x\n", offset, data); - int offs = offset*8; - - uint8_t i = (offs>>8)&63; - - m_utlb[i].PPN = (data & 0x1ffffc00) >> 10; - m_utlb[i].V = (data & 0x00000100) >> 8; - m_utlb[i].PSZ = (data & 0x00000080) >> 6; - m_utlb[i].PSZ |=(data & 0x00000010) >> 4; - m_utlb[i].PPR= (data & 0x00000060) >> 5; - m_utlb[i].C = (data & 0x00000008) >> 3; - m_utlb[i].D = (data & 0x00000004) >> 2; - m_utlb[i].SH = (data & 0x00000002) >> 1; - m_utlb[i].WT = (data & 0x00000001) >> 0; -} - - -READ64_MEMBER(sh4_base_device::sh4_utlb_data_array1_r) -{ - uint32_t ret = 0; - int offs = offset*8; - - uint8_t i = (offs>>8)&63; - - ret |= m_utlb[i].PPN << 10; - ret |= m_utlb[i].V << 8; - ret |= (m_utlb[i].PSZ & 2) << 6; - ret |= (m_utlb[i].PSZ & 1) << 4; - ret |= m_utlb[i].PPR << 5; - ret |= m_utlb[i].C << 3; - ret |= m_utlb[i].D << 2; - ret |= m_utlb[i].SH << 1; - ret |= m_utlb[i].WT << 0; - - return ret; -} - - - -WRITE64_MEMBER( sh4_base_device::sh4_utlb_data_array2_w ) -{ -/* uses bits 13:8 of address to select which UTLB entry we're addressing - - ---- ---- ---- ---- ---- ---- ---- TSSS - - T = TC = Timing Control - S = SA = Space attributes - - = unused (should be 0) - -*/ - - logerror("sh4_utlb_data_array2_w %08x %08x\n", offset, data); - int offs = offset*8; - - uint8_t i = (offs>>8)&63; - - m_utlb[i].TC = (data & 0x00000008) >> 3; - m_utlb[i].SA = (data & 0x00000007) >> 0; -} - - -READ64_MEMBER(sh4_base_device::sh4_utlb_data_array2_r) -{ - uint32_t ret = 0; - int offs = offset*8; - - uint8_t i = (offs>>8)&63; - - ret |= m_utlb[i].TC << 3; - ret |= m_utlb[i].SA << 0; - - return ret; -} diff --git a/src/devices/cpu/superh/sh4comn.h b/src/devices/cpu/superh/sh4comn.h deleted file mode 100644 index 230207652d6..00000000000 --- a/src/devices/cpu/superh/sh4comn.h +++ /dev/null @@ -1,174 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:R. Belmont -/***************************************************************************** - * - * sh4comn.h - * - * SH-4 non-specific components - * - *****************************************************************************/ - -#pragma once - -#ifndef __SH4COMN_H__ -#define __SH4COMN_H__ - -//#define USE_SH4DRC - -/* speed up delay loops, bail out of tight loops */ -#define BUSY_LOOP_HACKS 0 - -#define VERBOSE 0 - -#ifdef USE_SH4DRC -#include "cpu/drcfe.h" -#include "cpu/drcuml.h" -#include "cpu/drcumlsh.h" - -class sh4_frontend; -#endif - -#define CPU_TYPE_SH3 (2) -#define CPU_TYPE_SH4 (3) - -#define LOG(x) do { if (VERBOSE) logerror x; } while (0) - -#define EXPPRI(pl,po,p,n) (((4-(pl)) << 24) | ((15-(po)) << 16) | ((p) << 8) | (255-(n))) -#define NMIPRI() EXPPRI(3,0,16,SH4_INTC_NMI) -#define INTPRI(p,n) EXPPRI(4,2,p,n) - -#define FP_RS(r) m_fr[(r)] // binary representation of single precision floating point register r -#define FP_RFS(r) *( (float *)(m_fr+(r)) ) // single precision floating point register r -#define FP_RFD(r) *( (double *)(m_fr+(r)) ) // double precision floating point register r -#define FP_XS(r) m_xf[(r)] // binary representation of extended single precision floating point register r -#define FP_XFS(r) *( (float *)(m_xf+(r)) ) // single precision extended floating point register r -#define FP_XFD(r) *( (double *)(m_xf+(r)) ) // double precision extended floating point register r -#ifdef LSB_FIRST -#define FP_RS2(r) m_fr[(r) ^ m_fpu_pr] -#define FP_RFS2(r) *( (float *)(m_fr+((r) ^ m_fpu_pr)) ) -#define FP_XS2(r) m_xf[(r) ^ m_fpu_pr] -#define FP_XFS2(r) *( (float *)(m_xf+((r) ^ m_fpu_pr)) ) -#endif - - -#ifdef USE_SH4DRC -struct sh4_state -{ - int icount; - - int pcfsel; // last pcflush entry set - int maxpcfsel; // highest valid pcflush entry - uint32_t pcflushes[16]; // pcflush entries - - drc_cache * cache; /* pointer to the DRC code cache */ - drcuml_state * drcuml; /* DRC UML generator state */ - sh4_frontend * drcfe; /* pointer to the DRC front-end class */ - uint32_t drcoptions; /* configurable DRC options */ - - /* internal stuff */ - uint8_t cache_dirty; /* true if we need to flush the cache */ - - /* parameters for subroutines */ - uint64_t numcycles; /* return value from gettotalcycles */ - uint32_t arg0; /* print_debug argument 1 */ - uint32_t arg1; /* print_debug argument 2 */ - uint32_t irq; /* irq we're taking */ - - /* register mappings */ - uml::parameter regmap[16]; /* parameter to register mappings for all 16 integer registers */ - - uml::code_handle * entry; /* entry point */ - uml::code_handle * read8; /* read byte */ - uml::code_handle * write8; /* write byte */ - uml::code_handle * read16; /* read half */ - uml::code_handle * write16; /* write half */ - uml::code_handle * read32; /* read word */ - uml::code_handle * write32; /* write word */ - - uml::code_handle * interrupt; /* interrupt */ - uml::code_handle * nocode; /* nocode */ - uml::code_handle * out_of_cycles; /* out of cycles exception handler */ - - uint32_t prefadr; - uint32_t target; -}; -#endif - -#ifdef USE_SH4DRC -class sh4_frontend : public drc_frontend -{ -public: - sh4_frontend(sh4_state &state, uint32_t window_start, uint32_t window_end, uint32_t max_sequence); - -protected: - virtual bool describe(opcode_desc &desc, const opcode_desc *prev); - -private: - bool describe_group_0(opcode_desc &desc, const opcode_desc *prev, uint16_t opcode); - bool describe_group_2(opcode_desc &desc, const opcode_desc *prev, uint16_t opcode); - bool describe_group_3(opcode_desc &desc, const opcode_desc *prev, uint16_t opcode); - bool describe_group_4(opcode_desc &desc, const opcode_desc *prev, uint16_t opcode); - bool describe_group_6(opcode_desc &desc, const opcode_desc *prev, uint16_t opcode); - bool describe_group_8(opcode_desc &desc, const opcode_desc *prev, uint16_t opcode); - bool describe_group_12(opcode_desc &desc, const opcode_desc *prev, uint16_t opcode); - bool describe_group_15(opcode_desc &desc, const opcode_desc *prev, uint16_t opcode); - - sh4_state &m_context; -}; -#endif - - -enum -{ - ICF = 0x00800000, - OCFA = 0x00080000, - OCFB = 0x00040000, - OVF = 0x00020000 -}; - -/* Bits in SR */ -#define T 0x00000001 -#define S 0x00000002 -#define I 0x000000f0 -#define Q 0x00000100 -#define M 0x00000200 -#define FD 0x00008000 -#define BL 0x10000000 -#define sRB 0x20000000 -#define MD 0x40000000 - -/* 29 bits */ -#define AM 0x1fffffff - -#define FLAGS (MD|sRB|BL|FD|M|Q|I|S|T) - -/* Bits in FPSCR */ -#define RM 0x00000003 -#define DN 0x00040000 -#define PR 0x00080000 -#define SZ 0x00100000 -#define FR 0x00200000 - -#define Rn ((opcode>>8)&15) -#define Rm ((opcode>>4)&15) - -#define REGFLAG_R(n) (1 << (n)) -#define REGFLAG_FR(n) (1 << (n)) -#define REGFLAG_XR(n) (1 << (n)) - -/* register flags 1 */ -#define REGFLAG_PR (1 << 0) -#define REGFLAG_MACL (1 << 1) -#define REGFLAG_MACH (1 << 2) -#define REGFLAG_GBR (1 << 3) -#define REGFLAG_VBR (1 << 4) -#define REGFLAG_SR (1 << 5) -#define REGFLAG_SGR (1 << 6) -#define REGFLAG_FPUL (1 << 7) -#define REGFLAG_FPSCR (1 << 8) -#define REGFLAG_DBR (1 << 9) -#define REGFLAG_SSR (1 << 10) -#define REGFLAG_SPC (1 << 11) - - -#endif /* __SH4COMN_H__ */ diff --git a/src/devices/cpu/superh/sh4dasm.cpp b/src/devices/cpu/superh/sh4dasm.cpp deleted file mode 100644 index faff895f3a5..00000000000 --- a/src/devices/cpu/superh/sh4dasm.cpp +++ /dev/null @@ -1,905 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:R. Belmont -#include "emu.h" -#include "debugger.h" -#include "sh4.h" - -#define SIGNX8(x) (((int32_t)(x) << 24) >> 24) -#define SIGNX12(x) (((int32_t)(x) << 20) >> 20) - -#define Rn ((opcode >> 8) & 15) -#define Rm ((opcode >> 4) & 15) - -static const char *const regname[16] = { - "R0", "R1", "R2", "R3", "R4", "R5", "R6", "R7", - "R8", "R9", "R10","R11","R12","R13","R14","R15" -}; - -static uint32_t op0000(std::ostream &stream, uint32_t pc, uint16_t opcode) -{ - uint32_t flags = 0; - switch (opcode & 0xF) - { - case 0x0: - case 0x1: - util::stream_format(stream, "?????? $%04X", opcode); - break; - case 0x2: - if (opcode & 0x80) { - util::stream_format(stream, "STC %s_BANK,%s", regname[(Rm) & 7], regname[Rn]); - return flags; - } - switch (opcode & 0x70) - { - case 0x00: - util::stream_format(stream, "STC SR,%s", regname[Rn]); - break; - case 0x10: - util::stream_format(stream, "STC GBR,%s", regname[Rn]); - break; - case 0x20: - util::stream_format(stream, "STC VBR,%s", regname[Rn]); - break; - case 0x30: - util::stream_format(stream, "STC SSR,%s", regname[Rn]); - break; - case 0x40: - util::stream_format(stream, "STC SPC,%s", regname[Rn]); - break; - } - break; - case 0x3: - switch (opcode & 0xF0) - { - case 0x00: - util::stream_format(stream, "BSRF %s", regname[Rn]); - break; - case 0x20: - util::stream_format(stream, "BRAF %s", regname[Rn]); - break; - case 0x80: - util::stream_format(stream, "PREF @%s", regname[Rn]); - break; - case 0x90: - util::stream_format(stream, "OCBI @%s", regname[Rn]); - break; - case 0xA0: - util::stream_format(stream, "OCBP @%s", regname[Rn]); - break; - case 0xB0: - util::stream_format(stream, "OCBWB @%s", regname[Rn]); - break; - case 0xC0: - util::stream_format(stream, "MOVCA.L R0,@%s", regname[Rn]); - break; - } - break; - case 0x4: - util::stream_format(stream, "MOV.B %s,@(R0,%s)", regname[Rm], regname[Rn]); - break; - case 0x5: - util::stream_format(stream, "MOV.W %s,@(R0,%s)", regname[Rm], regname[Rn]); - break; - case 0x6: - util::stream_format(stream, "MOV.L %s,@(R0,%s)", regname[Rm], regname[Rn]); - break; - case 0x7: - util::stream_format(stream, "MUL.L %s,%s", regname[Rm], regname[Rn]); - break; - case 0x8: - switch (opcode & 0x70) - { - case 0x00: stream << "CLRT"; break; - case 0x10: stream << "SETT"; break; - case 0x20: stream << "CLRMAC"; break; - case 0x30: stream << "LDTLB"; break; - case 0x40: stream << "CLRS"; break; - case 0x50: stream << "SETS"; break; - } - break; - case 0x9: - switch (opcode & 0x30) - { - case 0x00: - stream << "NOP"; - break; - case 0x10: - stream << "DIV0U"; - break; - case 0x20: - util::stream_format(stream, "MOVT %s", regname[Rn]); - break; - } - break; - case 0xA: - switch (opcode & 0x70) - { - case 0x00: - util::stream_format(stream, "STS MACH,%s", regname[Rn]); - break; - case 0x10: - util::stream_format(stream, "STS MACL,%s", regname[Rn]); - break; - case 0x20: - util::stream_format(stream, "STS PR,%s", regname[Rn]); - break; - case 0x30: - util::stream_format(stream, "STC SGR,%s", regname[Rn]); - break; - case 0x50: - util::stream_format(stream, "STS FPUL,%s", regname[Rn]); - break; - case 0x60: - util::stream_format(stream, "STS FPSCR,%s", regname[Rn]); - break; - case 0x70: - util::stream_format(stream, "STC DBR,%s", regname[Rn]); - break; - } - break; - case 0xB: - switch (opcode & 0x30) - { - case 0x00: - stream << "RTS"; - flags = DASMFLAG_STEP_OUT; - break; - case 0x10: - stream << "SLEEP"; - break; - case 0x20: - stream << "RTE"; - flags = DASMFLAG_STEP_OUT; - break; - } - break; - case 0xC: - util::stream_format(stream, "MOV.B @(R0,%s),%s", regname[Rm], regname[Rn]); - break; - case 0xD: - util::stream_format(stream, "MOV.W @(R0,%s),%s", regname[Rm], regname[Rn]); - break; - case 0xE: - util::stream_format(stream, "MOV.L @(R0,%s),%s", regname[Rm], regname[Rn]); - break; - case 0xF: - util::stream_format(stream, "MAC.L @%s+,@%s+", regname[Rn], regname[Rm]); - break; - } - return flags; -} - -static uint32_t op0001(std::ostream &stream, uint32_t pc, uint16_t opcode) -{ - util::stream_format(stream, "MOV.L %s,@($%02X,%s)", regname[Rm], (opcode & 15) * 4, regname[Rn]); - return 0; -} - -static uint32_t op0010(std::ostream &stream, uint32_t pc, uint16_t opcode) -{ - switch (opcode & 15) - { - case 0: - util::stream_format(stream, "MOV.B %s,@%s", regname[Rm], regname[Rn]); - break; - case 1: - util::stream_format(stream, "MOV.W %s,@%s", regname[Rm], regname[Rn]); - break; - case 2: - util::stream_format(stream, "MOV.L %s,@%s", regname[Rm], regname[Rn]); - break; - case 3: - util::stream_format(stream, "?????? $%04X", opcode); - break; - case 4: - util::stream_format(stream, "MOV.B %s,@-%s", regname[Rm], regname[Rn]); - break; - case 5: - util::stream_format(stream, "MOV.W %s,@-%s", regname[Rm], regname[Rn]); - break; - case 6: - util::stream_format(stream, "MOV.L %s,@-%s", regname[Rm], regname[Rn]); - break; - case 7: - util::stream_format(stream, "DIV0S %s,%s", regname[Rm], regname[Rn]); - break; - case 8: - util::stream_format(stream, "TST %s,%s", regname[Rm], regname[Rn]); - break; - case 9: - util::stream_format(stream, "AND %s,%s", regname[Rm], regname[Rn]); - break; - case 10: - util::stream_format(stream, "XOR %s,%s", regname[Rm], regname[Rn]); - break; - case 11: - util::stream_format(stream, "OR %s,%s", regname[Rm], regname[Rn]); - break; - case 12: - util::stream_format(stream, "CMP/STR %s,%s", regname[Rm], regname[Rn]); - break; - case 13: - util::stream_format(stream, "XTRCT %s,%s", regname[Rm], regname[Rn]); - break; - case 14: - util::stream_format(stream, "MULU.W %s,%s", regname[Rm], regname[Rn]); - break; - case 15: - util::stream_format(stream, "MULS.W %s,%s", regname[Rm], regname[Rn]); - break; - } - return 0; -} - -static uint32_t op0011(std::ostream &stream, uint32_t pc, uint16_t opcode) -{ - switch (opcode & 15) - { - case 0: - util::stream_format(stream, "CMP/EQ %s,%s", regname[Rm], regname[Rn]); - break; - case 1: - util::stream_format(stream, "?????? %s,%s", regname[Rm], regname[Rn]); - break; - case 2: - util::stream_format(stream, "CMP/HS %s,%s", regname[Rm], regname[Rn]); - break; - case 3: - util::stream_format(stream, "CMP/GE %s,%s", regname[Rm], regname[Rn]); - break; - case 4: - util::stream_format(stream, "DIV1 %s,%s", regname[Rm], regname[Rn]); - break; - case 5: - util::stream_format(stream, "DMULU.L %s,%s", regname[Rm], regname[Rn]); - break; - case 6: - util::stream_format(stream, "CMP/HI %s,%s", regname[Rm], regname[Rn]); - break; - case 7: - util::stream_format(stream, "CMP/GT %s,%s", regname[Rm], regname[Rn]); - break; - case 8: - util::stream_format(stream, "SUB %s,%s", regname[Rm], regname[Rn]); - break; - case 9: - util::stream_format(stream, "?????? %s,%s", regname[Rm], regname[Rn]); - break; - case 10: - util::stream_format(stream, "SUBC %s,%s", regname[Rm], regname[Rn]); - break; - case 11: - util::stream_format(stream, "SUBV %s,%s", regname[Rm], regname[Rn]); - break; - case 12: - util::stream_format(stream, "ADD %s,%s", regname[Rm], regname[Rn]); - break; - case 13: - util::stream_format(stream, "DMULS.L %s,%s", regname[Rm], regname[Rn]); - break; - case 14: - util::stream_format(stream, "ADDC %s,%s", regname[Rm], regname[Rn]); - break; - case 15: - util::stream_format(stream, "ADDV %s,%s", regname[Rm], regname[Rn]); - break; - } - return 0; -} - -static uint32_t op0100(std::ostream &stream, uint32_t pc, uint16_t opcode) -{ - uint32_t flags = 0; - switch (opcode & 0xF) - { - case 0x0: - switch (opcode & 0x30) - { - case 0x00: - util::stream_format(stream, "SHLL %s", regname[Rn]); - break; - case 0x10: - util::stream_format(stream, "DT %s", regname[Rn]); - break; - case 0x20: - util::stream_format(stream, "SHAL %s", regname[Rn]); - break; - } - break; - case 0x1: - switch (opcode & 0x30) - { - case 0x00: - util::stream_format(stream, "SHLR %s", regname[Rn]); - break; - case 0x10: - util::stream_format(stream, "CMP/PZ %s", regname[Rn]); - break; - case 0x20: - util::stream_format(stream, "SHAR %s", regname[Rn]); - break; - } - break; - case 0x2: - switch (opcode & 0xF0) - { - case 0x00: - util::stream_format(stream, "STS.L MACH,@-%s", regname[Rn]); - break; - case 0x10: - util::stream_format(stream, "STS.L MACL,@-%s", regname[Rn]); - break; - case 0x20: - util::stream_format(stream, "STS.L PR,@-%s", regname[Rn]); - break; - case 0x30: - util::stream_format(stream, "STC.L SGR,@-%s", regname[Rn]); - break; - case 0x50: - util::stream_format(stream, "STS.L FPUL,@-%s", regname[Rn]); - break; - case 0x60: - util::stream_format(stream, "STS.L FPSCR,@-%s", regname[Rn]); - break; - case 0xF0: - util::stream_format(stream, "STC.L DBR,@-%s", regname[Rn]); - break; - } - break; - case 0x3: - if (opcode & 0x80) { - util::stream_format(stream, "STC.L %s_BANK,@-%s", regname[(Rm) & 7],regname[Rn]); - return flags; - } - switch (opcode & 0x70) - { - case 0x00: - util::stream_format(stream, "STC.L SR,@-%s", regname[Rn]); - break; - case 0x10: - util::stream_format(stream, "STC.L GBR,@-%s", regname[Rn]); - break; - case 0x20: - util::stream_format(stream, "STC.L VBR,@-%s", regname[Rn]); - break; - case 0x30: - util::stream_format(stream, "STC.L SSR,@-%s", regname[Rn]); - break; - case 0x40: - util::stream_format(stream, "STC.L SPC,@-%s", regname[Rn]); - break; - } - break; - case 0x4: - switch (opcode & 0x30) - { - case 0x00: - util::stream_format(stream, "ROTL %s", regname[Rn]); - break; - case 0x20: - util::stream_format(stream, "ROTCL %s", regname[Rn]); - break; - } - break; - case 0x5: - switch (opcode & 0x30) - { - case 0x00: - util::stream_format(stream, "ROTR %s", regname[Rn]); - break; - case 0x10: - util::stream_format(stream, "CMP/PL %s", regname[Rn]); - break; - case 0x20: - util::stream_format(stream, "ROTCR %s", regname[Rn]); - break; - } - break; - case 0x6: - switch (opcode & 0xF0) - { - case 0x00: - util::stream_format(stream, "LDS.L @%s+,MACH", regname[Rn]); - break; - case 0x10: - util::stream_format(stream, "LDS.L @%s+,MACL", regname[Rn]); - break; - case 0x20: - util::stream_format(stream, "LDS.L @%s+,PR", regname[Rn]); - break; - case 0x50: - util::stream_format(stream, "LDS.L @%s+,FPUL", regname[Rn]); - break; - case 0x60: - util::stream_format(stream, "LDS.L @%s+,FPSCR", regname[Rn]); - break; - case 0xF0: - util::stream_format(stream, "LDC.L @%s+,DBR", regname[Rn]); - break; - } - break; - case 0x7: - if (opcode & 0x80) { - util::stream_format(stream, "LDC.L @%s+,%s_BANK", regname[Rn],regname[(Rm) & 7]); - return flags; - } - switch (opcode & 0x70) - { - case 0x00: - util::stream_format(stream, "LDC.L @%s+,SR", regname[Rn]); - break; - case 0x10: - util::stream_format(stream, "LDC.L @%s+,GBR", regname[Rn]); - break; - case 0x20: - util::stream_format(stream, "LDC.L @%s+,VBR", regname[Rn]); - break; - case 0x30: - util::stream_format(stream, "LDC.L @%s+,SSR", regname[Rn]); - break; - case 0x40: - util::stream_format(stream, "LDC.L @%s+,SPC", regname[Rn]); - break; - } - break; - case 0x8: - switch (opcode & 0x30) - { - case 0x00: - util::stream_format(stream, "SHLL2 %s", regname[Rn]); - break; - case 0x10: - util::stream_format(stream, "SHLL8 %s", regname[Rn]); - break; - case 0x20: - util::stream_format(stream, "SHLL16 %s", regname[Rn]); - break; - } - break; - case 0x9: - switch (opcode & 0x30) - { - case 0x00: - util::stream_format(stream, "SHLR2 %s", regname[Rn]); - break; - case 0x10: - util::stream_format(stream, "SHLR8 %s", regname[Rn]); - break; - case 0x20: - util::stream_format(stream, "SHLR16 %s", regname[Rn]); - break; - } - break; - case 0xA: - switch (opcode & 0xF0) - { - case 0x00: - util::stream_format(stream, "LDS %s,MACH", regname[Rn]); - break; - case 0x10: - util::stream_format(stream, "LDS %s,MACL", regname[Rn]); - break; - case 0x20: - util::stream_format(stream, "LDS %s,PR", regname[Rn]); - break; - case 0x50: - util::stream_format(stream, "LDS %s,FPUL", regname[Rn]); - break; - case 0x60: - util::stream_format(stream, "LDS %s,FPSCR", regname[Rn]); - break; - case 0xF0: - util::stream_format(stream, "LDC %s,DBR", regname[Rn]); - break; - } - break; - case 0xB: - switch (opcode & 0x30) - { - case 0x00: - util::stream_format(stream, "JSR %s", regname[Rn]); - flags = DASMFLAG_STEP_OVER | DASMFLAG_STEP_OVER_EXTRA(1); - break; - case 0x10: - util::stream_format(stream, "TAS %s", regname[Rn]); - break; - case 0x20: - util::stream_format(stream, "JMP %s", regname[Rn]); - break; - } - break; - case 0xC: - util::stream_format(stream, "SHAD %s,%s", regname[Rm], regname[Rn]); - break; - case 0xD: - util::stream_format(stream, "SHLD %s,%s", regname[Rm], regname[Rn]); - break; - case 0xE: - if (opcode & 0x80) { - util::stream_format(stream, "LDC %s,%s_BANK", regname[Rn],regname[(Rm) & 7]); - return flags; - } - switch (opcode & 0x70) - { - case 0x00: - util::stream_format(stream, "LDC %s,SR", regname[Rn]); - break; - case 0x10: - util::stream_format(stream, "LDC %s,GBR", regname[Rn]); - break; - case 0x20: - util::stream_format(stream, "LDC %s,VBR", regname[Rn]); - break; - case 0x30: - util::stream_format(stream, "LDC %s,SSR", regname[Rn]); - break; - case 0x40: - util::stream_format(stream, "LDC %s,SPC", regname[Rn]); - break; - } - break; - case 0xF: - util::stream_format(stream, "MAC.W @%s+,@%s+", regname[Rm], regname[Rn]); - break; - } - return flags; -} - -static uint32_t op0101(std::ostream &stream, uint32_t pc, uint16_t opcode) -{ - util::stream_format(stream, "MOV.L @($%02X,%s),%s", (opcode & 15) * 4, regname[Rm], regname[Rn]); - return 0; -} - -static uint32_t op0110(std::ostream &stream, uint32_t pc, uint16_t opcode) - -{ - switch(opcode & 0xF) - { - case 0x00: - util::stream_format(stream, "MOV.B @%s,%s", regname[Rm], regname[Rn]); - break; - case 0x01: - util::stream_format(stream, "MOV.W @%s,%s", regname[Rm], regname[Rn]); - break; - case 0x02: - util::stream_format(stream, "MOV.L @%s,%s", regname[Rm], regname[Rn]); - break; - case 0x03: - util::stream_format(stream, "MOV %s,%s", regname[Rm], regname[Rn]); - break; - case 0x04: - util::stream_format(stream, "MOV.B @%s+,%s", regname[Rm], regname[Rn]); - break; - case 0x05: - util::stream_format(stream, "MOV.W @%s+,%s", regname[Rm], regname[Rn]); - break; - case 0x06: - util::stream_format(stream, "MOV.L @%s+,%s", regname[Rm], regname[Rn]); - break; - case 0x07: - util::stream_format(stream, "NOT %s,%s", regname[Rm], regname[Rn]); - break; - case 0x08: - util::stream_format(stream, "SWAP.B %s,%s", regname[Rm], regname[Rn]); - break; - case 0x09: - util::stream_format(stream, "SWAP.W %s,%s", regname[Rm], regname[Rn]); - break; - case 0x0a: - util::stream_format(stream, "NEGC %s,%s", regname[Rm], regname[Rn]); - break; - case 0x0b: - util::stream_format(stream, "NEG %s,%s", regname[Rm], regname[Rn]); - break; - case 0x0c: - util::stream_format(stream, "EXTU.B %s,%s", regname[Rm], regname[Rn]); - break; - case 0x0d: - util::stream_format(stream, "EXTU.W %s,%s", regname[Rm], regname[Rn]); - break; - case 0x0e: - util::stream_format(stream, "EXTS.B %s,%s", regname[Rm], regname[Rn]); - break; - case 0x0f: - util::stream_format(stream, "EXTS.W %s,%s", regname[Rm], regname[Rn]); - break; - } - return 0; -} - -static uint32_t op0111(std::ostream &stream, uint32_t pc, uint16_t opcode) -{ - util::stream_format(stream, "ADD #$%02X,%s", opcode & 0xff, regname[Rn]); - return 0; -} - -static uint32_t op1000(std::ostream &stream, uint32_t pc, uint16_t opcode) -{ - switch((opcode >> 8) & 15) - { - case 0: - util::stream_format(stream, "MOV.B R0,@($%02X,%s)", (opcode & 15), regname[Rm]); - break; - case 1: - util::stream_format(stream, "MOV.W R0,@($%02X,%s)", (opcode & 15) * 2, regname[Rm]); - break; - case 4: - util::stream_format(stream, "MOV.B @($%02X,%s),R0", (opcode & 15), regname[Rm]); - break; - case 5: - util::stream_format(stream, "MOV.W @($%02X,%s),R0", (opcode & 15) * 2, regname[Rm]); - break; - case 8: - util::stream_format(stream, "CMP/EQ #$%02X,R0", (opcode & 0xff)); - break; - case 9: - util::stream_format(stream, "BT $%08X", pc + SIGNX8(opcode & 0xff) * 2 + 2); - break; - case 11: - util::stream_format(stream, "BF $%08X", pc + SIGNX8(opcode & 0xff) * 2 + 2); - break; - case 13: - util::stream_format(stream, "BTS $%08X", pc + SIGNX8(opcode & 0xff) * 2 + 2); - break; - case 15: - util::stream_format(stream, "BFS $%08X", pc + SIGNX8(opcode & 0xff) * 2 + 2); - break; - default : - util::stream_format(stream, "invalid $%04X", opcode); - } - return 0; -} - -static uint32_t op1001(std::ostream &stream, uint32_t pc, uint16_t opcode) -{ -uint32_t ea=(pc+((opcode & 0xff) * 2)+2); - - util::stream_format(stream, "MOV.W @($%04X,PC),%s [%08X]", (opcode & 0xff) * 2, regname[Rn], ea); - return 0; -} - -static uint32_t op1010(std::ostream &stream, uint32_t pc, uint16_t opcode) -{ - util::stream_format(stream, "BRA $%08X", SIGNX12(opcode & 0xfff) * 2 + pc + 2); - return 0; -} - -static uint32_t op1011(std::ostream &stream, uint32_t pc, uint16_t opcode) -{ - util::stream_format(stream, "BSR $%08X", SIGNX12(opcode & 0xfff) * 2 + pc + 2); - return DASMFLAG_STEP_OVER | DASMFLAG_STEP_OVER_EXTRA(1); -} - -static uint32_t op1100(std::ostream &stream, uint32_t pc, uint16_t opcode) -{ - uint32_t flags = 0; - switch((opcode >> 8) & 15) - { - case 0: - util::stream_format(stream, "MOV.B R0,@($%02X,GBR)", opcode & 0xff); - break; - case 1: - util::stream_format(stream, "MOV.W R0,@($%04X,GBR)", (opcode & 0xff) * 2); - break; - case 2: - util::stream_format(stream, "MOV.L R0,@($%04X,GBR)", (opcode & 0xff) * 4); - break; - case 3: - util::stream_format(stream, "TRAPA #$%02X", opcode & 0xff); - flags = DASMFLAG_STEP_OVER; - break; - case 4: - util::stream_format(stream, "MOV.B @($%02X,GBR),R0", opcode & 0xff); - break; - case 5: - util::stream_format(stream, "MOV.W @($%04X,GBR),R0", (opcode & 0xff) * 2); - break; - case 6: - util::stream_format(stream, "MOV.L @($%04X,GBR),R0", (opcode & 0xff) * 4); - break; - case 7: - util::stream_format(stream, "MOVA @($%04X,PC),R0 [%08X]", (opcode & 0xff) * 4, ((pc + 2) & ~3) + (opcode & 0xff) * 4); - break; - case 8: - util::stream_format(stream, "TST #$%02X,R0", opcode & 0xff); - break; - case 9: - util::stream_format(stream, "AND #$%02X,R0", opcode & 0xff); - break; - case 10: - util::stream_format(stream, "XOR #$%02X,R0", opcode & 0xff); - break; - case 11: - util::stream_format(stream, "OR #$%02X,R0", opcode & 0xff); - break; - case 12: - util::stream_format(stream, "TST.B #$%02X,@(R0,GBR)", opcode & 0xff); - break; - case 13: - util::stream_format(stream, "AND.B #$%02X,@(R0,GBR)", opcode & 0xff); - break; - case 14: - util::stream_format(stream, "XOR.B #$%02X,@(R0,GBR)", opcode & 0xff); - break; - case 15: - util::stream_format(stream, "OR.B #$%02X,@(R0,GBR)", opcode & 0xff); - break; - } - return flags; -} - -static uint32_t op1101(std::ostream &stream, uint32_t pc, uint16_t opcode) -{ -uint32_t ea=((pc + 2) & ~3) + (opcode & 0xff) * 4; - - util::stream_format(stream, "MOV.L @($%04X,PC),%s [%08X]", (opcode & 0xff) * 4, regname[Rn], ea); - return 0; -} - -static uint32_t op1110(std::ostream &stream, uint32_t pc, uint16_t opcode) -{ - util::stream_format(stream, "MOV #$%02X,%s", (opcode & 0xff), regname[Rn]); - return 0; -} - -static uint32_t op1111(std::ostream &stream, uint32_t pc, uint16_t opcode) -{ - switch (opcode & 0xf) - { - case 0: - util::stream_format(stream, "FADD F%s, F%s", regname[Rm], regname[Rn]); - break; - case 1: - util::stream_format(stream, "FSUB F%s, F%s", regname[Rm], regname[Rn]); - break; - case 2: - util::stream_format(stream, "FMUL F%s, F%s", regname[Rm], regname[Rn]); - break; - case 3: - util::stream_format(stream, "FDIV F%s, F%s", regname[Rm], regname[Rn]); - break; - case 4: - util::stream_format(stream, "FCMP/EQ F%s, F%s", regname[Rm], regname[Rn]); - break; - case 5: - util::stream_format(stream, "FCMP/GT F%s, F%s", regname[Rm], regname[Rn]); - break; - case 6: - util::stream_format(stream, "FMOV.S @(R0,%s),F%s", regname[Rm], regname[Rn]); - break; - case 7: - util::stream_format(stream, "FMOV.S F%s, @(R0,%s)", regname[Rm], regname[Rn]); - break; - case 8: - util::stream_format(stream, "FMOV.S @%s, F%s", regname[Rm], regname[Rn]); - break; - case 9: - util::stream_format(stream, "FMOV.S @%s+, F%s", regname[Rm], regname[Rn]); - break; - case 10: - util::stream_format(stream, "FMOV.S F%s, @%s", regname[Rm], regname[Rn]); - break; - case 11: - util::stream_format(stream, "FMOV.S F%s, @-%s", regname[Rm], regname[Rn]); - break; - case 12: - util::stream_format(stream, "FMOV.S F%s, F%s", regname[Rm], regname[Rn]); - break; - case 13: - switch (opcode & 0xF0) - { - case 0x00: - util::stream_format(stream, "FSTS FPUL, F%s", regname[Rn]); - break; - case 0x10: - util::stream_format(stream, "FLDS F%s, FPUL", regname[Rn]); - break; - case 0x20: - util::stream_format(stream, "FLOAT FPUL, F%s", regname[Rn]); - break; - case 0x30: - util::stream_format(stream, "FTRC F%s, FPUL", regname[Rn]); - break; - case 0x40: - util::stream_format(stream, "FNEG F%s", regname[Rn]); - break; - case 0x50: - util::stream_format(stream, "FABS F%s", regname[Rn]); - break; - case 0x60: - util::stream_format(stream, "FSQRT F%s", regname[Rn]); - break; - case 0x70: - util::stream_format(stream, "FSRRA F%s", regname[Rn]); - break; - case 0x80: - util::stream_format(stream, "FLDI0 F%s", regname[Rn]); - break; - case 0x90: - util::stream_format(stream, "FLDI1 F%s", regname[Rn]); - break; - case 0xA0: - util::stream_format(stream, "FCNVSD FPUL, D%s", regname[Rn]); - break; - case 0xB0: - util::stream_format(stream, "FCNVDS D%s, FPUL", regname[Rn]); - break; - case 0xE0: - util::stream_format(stream, "FIPR FV%d, FV%d", (Rn & 3) << 2, Rn & 12); - break; - case 0xF0: - if (opcode & 0x100) { - if (opcode & 0x200) { - switch (opcode & 0xC00) - { - case 0x000: - stream << "FSCHG"; - break; - case 0x800: - stream << "FRCHG"; - break; - default: - util::stream_format(stream, "Funknown $%04X", opcode); - break; - } - } else { - util::stream_format(stream, "FTRV XMTRX, FV%d", Rn & 12); - } - } else { - util::stream_format(stream, "FSCA FPUL, F%s", regname[Rn & 14]); - } - break; - default: - util::stream_format(stream, "Funknown $%04X", opcode); - break; - } - break; - case 14: - util::stream_format(stream, "FMAC FR0, F%s,F%s", regname[Rm], regname[Rn]); - break; - default: - util::stream_format(stream, "Funknown $%04X", opcode); - break; - } - - return 0; -} - -unsigned DasmSH4(std::ostream &stream, unsigned pc, uint16_t opcode) -{ - uint32_t flags; - - pc += 2; - - switch ((opcode >> 12) & 15) - { - case 0: flags = op0000(stream, pc, opcode); break; - case 1: flags = op0001(stream, pc, opcode); break; - case 2: flags = op0010(stream, pc, opcode); break; - case 3: flags = op0011(stream, pc, opcode); break; - case 4: flags = op0100(stream, pc, opcode); break; - case 5: flags = op0101(stream, pc, opcode); break; - case 6: flags = op0110(stream, pc, opcode); break; - case 7: flags = op0111(stream, pc, opcode); break; - case 8: flags = op1000(stream, pc, opcode); break; - case 9: flags = op1001(stream, pc, opcode); break; - case 10: flags = op1010(stream, pc, opcode); break; - case 11: flags = op1011(stream, pc, opcode); break; - case 12: flags = op1100(stream, pc, opcode); break; - case 13: flags = op1101(stream, pc, opcode); break; - case 14: flags = op1110(stream, pc, opcode); break; - default: flags = op1111(stream, pc, opcode); break; - } - return 2 | flags | DASMFLAG_SUPPORTED; -} - -CPU_DISASSEMBLE(sh4) -{ - return DasmSH4(stream, pc, (oprom[1] << 8) | oprom[0]); -} - -CPU_DISASSEMBLE(sh4be) -{ - return DasmSH4(stream, pc, (oprom[0] << 8) | oprom[1]); -} diff --git a/src/devices/cpu/superh/sh4dmac.cpp b/src/devices/cpu/superh/sh4dmac.cpp deleted file mode 100644 index c06ffb034dd..00000000000 --- a/src/devices/cpu/superh/sh4dmac.cpp +++ /dev/null @@ -1,666 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:R. Belmont -/* SHA3/4 DMA Controller */ - -#include "emu.h" -#include "debugger.h" -#include "sh4.h" -#include "sh4comn.h" -#include "sh3comn.h" -#include "sh4dmac.h" - -static const int dmasize[8] = { 8, 1, 2, 4, 32, 0, 0, 0 }; - -static const int sh3_dmasize[4] = { 1, 2, 4, 16 }; - -TIMER_CALLBACK_MEMBER( sh34_base_device::sh4_dmac_callback ) -{ - int channel = param; - - LOG(("SH4 '%s': DMA %d complete\n", tag(), channel)); - m_dma_timer_active[channel] = 0; - switch (channel) - { - case 0: - m_SH4_DMATCR0 = 0; - m_SH4_CHCR0 |= CHCR_TE; - if (m_SH4_CHCR0 & CHCR_IE) - sh4_exception_request(SH4_INTC_DMTE0); - break; - case 1: - m_SH4_DMATCR1 = 0; - m_SH4_CHCR1 |= CHCR_TE; - if (m_SH4_CHCR1 & CHCR_IE) - sh4_exception_request(SH4_INTC_DMTE1); - break; - case 2: - m_SH4_DMATCR2 = 0; - m_SH4_CHCR2 |= CHCR_TE; - if (m_SH4_CHCR2 & CHCR_IE) - sh4_exception_request(SH4_INTC_DMTE2); - break; - case 3: - m_SH4_DMATCR3 = 0; - m_SH4_CHCR3 |= CHCR_TE; - if (m_SH4_CHCR3 & CHCR_IE) - sh4_exception_request(SH4_INTC_DMTE3); - break; - } -} - -int sh34_base_device::sh4_dma_transfer(int channel, int timermode, uint32_t chcr, uint32_t *sar, uint32_t *dar, uint32_t *dmatcr) -{ - int incs, incd, size; - uint32_t src, dst, count; - - incd = (chcr & CHCR_DM) >> 14; - incs = (chcr & CHCR_SM) >> 12; - - if (m_cpu_type == CPU_TYPE_SH4) - { - size = dmasize[(chcr & CHCR_TS) >> 4]; - } - else - { - size = sh3_dmasize[(chcr >> 3) & 3]; - } - - if(incd == 3 || incs == 3) - { - logerror("SH4: DMA: bad increment values (%d, %d, %d, %04x)\n", incd, incs, size, chcr); - return 0; - } - src = *sar; - dst = *dar; - count = *dmatcr; - if (!count) - count = 0x1000000; - - LOG(("SH4: DMA %d start %x, %x, %x, %04x, %d, %d, %d\n", channel, src, dst, count, chcr, incs, incd, size)); - - if (timermode == 1) // timer actvated after a time based on the number of words to transfer - { - m_dma_timer_active[channel] = 1; - m_dma_timer[channel]->adjust(cycles_to_attotime(2*count+1), channel); - } - else if (timermode == 2) // timer activated immediately - { - m_dma_timer_active[channel] = 1; - m_dma_timer[channel]->adjust(attotime::zero, channel); - } - - src &= AM; - dst &= AM; - - switch(size) - { - case 1: // 8 bit - for(;count > 0; count --) - { - if(incs == 2) - src --; - if(incd == 2) - dst --; - m_program->write_byte(dst, m_program->read_byte(src)); - if(incs == 1) - src ++; - if(incd == 1) - dst ++; - } - break; - case 2: // 16 bit - src &= ~1; - dst &= ~1; - for(;count > 0; count --) - { - if(incs == 2) - src -= 2; - if(incd == 2) - dst -= 2; - m_program->write_word(dst, m_program->read_word(src)); - if(incs == 1) - src += 2; - if(incd == 1) - dst += 2; - } - break; - case 8: // 64 bit - src &= ~7; - dst &= ~7; - for(;count > 0; count --) - { - if(incs == 2) - src -= 8; - if(incd == 2) - dst -= 8; - m_program->write_qword(dst, m_program->read_qword(src)); - if(incs == 1) - src += 8; - if(incd == 1) - dst += 8; - - } - break; - case 4: // 32 bit - src &= ~3; - dst &= ~3; - for(;count > 0; count --) - { - if(incs == 2) - src -= 4; - if(incd == 2) - dst -= 4; - m_program->write_dword(dst, m_program->read_dword(src)); - if(incs == 1) - src += 4; - if(incd == 1) - dst += 4; - - } - break; - case 32: - src &= ~31; - dst &= ~31; - for(;count > 0; count --) - { - if(incs == 2) - src -= 32; - if(incd == 2) - dst -= 32; - m_program->write_qword(dst, m_program->read_qword(src)); - m_program->write_qword(dst+8, m_program->read_qword(src+8)); - m_program->write_qword(dst+16, m_program->read_qword(src+16)); - m_program->write_qword(dst+24, m_program->read_qword(src+24)); - if(incs == 1) - src += 32; - if(incd == 1) - dst += 32; - } - break; - } - *sar = (*sar & ~AM) | src; - *dar = (*dar & ~AM) | dst; - *dmatcr = count; - return 1; -} - -int sh34_base_device::sh4_dma_transfer_device(int channel, uint32_t chcr, uint32_t *sar, uint32_t *dar, uint32_t *dmatcr) -{ - int incs, incd, size, mod; - uint32_t src, dst, count; - - incd = (chcr & CHCR_DM) >> 14; - incs = (chcr & CHCR_SM) >> 12; - - - if (m_cpu_type == CPU_TYPE_SH4) - { - size = dmasize[(chcr & CHCR_TS) >> 4]; - } - else - { - size = sh3_dmasize[(chcr >> 3) & 3]; - } - - mod = ((chcr & CHCR_RS) >> 8); - if (incd == 3 || incs == 3) - { - logerror("SH4: DMA: bad increment values (%d, %d, %d, %04x)\n", incd, incs, size, chcr); - return 0; - } - src = *sar; - dst = *dar; - count = *dmatcr; - if (!count) - count = 0x1000000; - - LOG(("SH4: DMA %d start device<->memory %x, %x, %x, %04x, %d, %d, %d\n", channel, src, dst, count, chcr, incs, incd, size)); - - m_dma_timer_active[channel] = 1; - - src &= AM; - dst &= AM; - - // remember parameters - m_dma_source[channel]=src; - m_dma_destination[channel]=dst; - m_dma_count[channel]=count; - m_dma_wordsize[channel]=size; - m_dma_source_increment[channel]=incs; - m_dma_destination_increment[channel]=incd; - m_dma_mode[channel]=mod; - - // inform device its ready to transfer - m_io->write_dword(SH4_IOPORT_DMA, channel | (mod << 16)); - return 1; -} - -void sh34_base_device::sh4_dmac_check(int channel) -{ - uint32_t dmatcr, chcr, sar, dar; - - switch (channel) - { - case 0: - sar = m_SH4_SAR0; - dar = m_SH4_DAR0; - chcr = m_SH4_CHCR0; - dmatcr = m_SH4_DMATCR0; - break; - case 1: - sar = m_SH4_SAR1; - dar = m_SH4_DAR1; - chcr = m_SH4_CHCR1; - dmatcr = m_SH4_DMATCR1; - break; - case 2: - sar = m_SH4_SAR2; - dar = m_SH4_DAR2; - chcr = m_SH4_CHCR2; - dmatcr = m_SH4_DMATCR2; - break; - case 3: - sar = m_SH4_SAR3; - dar = m_SH4_DAR3; - chcr = m_SH4_CHCR3; - dmatcr = m_SH4_DMATCR3; - break; - default: - return; - } - if (chcr & m_SH4_DMAOR & DMAOR_DME) - { - if ((((chcr & CHCR_RS) >> 8) < 2) || (((chcr & CHCR_RS) >> 8) > 6)) - return; - if (!m_dma_timer_active[channel] && !(chcr & CHCR_TE) && !(m_SH4_DMAOR & (DMAOR_AE | DMAOR_NMIF))) - { - if (((chcr & CHCR_RS) >> 8) > 3) - sh4_dma_transfer(channel, 1, chcr, &sar, &dar, &dmatcr); - else if ((m_SH4_DMAOR & DMAOR_DDT) == 0) - sh4_dma_transfer_device(channel, chcr, &sar, &dar, &dmatcr); // tell device we are ready to transfer - } - } - else - { - if (m_dma_timer_active[channel]) - { - logerror("SH4: DMA %d cancelled in-flight but all data transferred", channel); - m_dma_timer[channel]->adjust(attotime::never, channel); - m_dma_timer_active[channel] = 0; - } - } -} - - -// called by drivers to transfer data in a cpu<->device dma. 'device' must be a SH4 cpu -int sh34_base_device::sh4_dma_data(struct sh4_device_dma *s) -{ - uint32_t pos, len, siz; - int channel = s->channel; - void *data = s->buffer; - - if (!m_dma_timer_active[channel]) - return 0; - - if (m_dma_mode[channel] == 2) - { - // device receives data - len = m_dma_count[channel]; - if (s->length < len) - len = s->length; - siz = m_dma_wordsize[channel]; - for (pos = 0;pos < len;pos++) { - switch (siz) - { - case 8: - if (m_dma_source_increment[channel] == 2) - m_dma_source[channel] -= 8; - *(uint64_t *)data = m_program->read_qword(m_dma_source[channel] & ~7); - if (m_dma_source_increment[channel] == 1) - m_dma_source[channel] += 8; - break; - case 1: - if (m_dma_source_increment[channel] == 2) - m_dma_source[channel]--; - *(uint8_t *)data = m_program->read_byte(m_dma_source[channel]); - if (m_dma_source_increment[channel] == 1) - m_dma_source[channel]++; - break; - case 2: - if (m_dma_source_increment[channel] == 2) - m_dma_source[channel] -= 2; - *(uint16_t *)data = m_program->read_word(m_dma_source[channel] & ~1); - if (m_dma_source_increment[channel] == 1) - m_dma_source[channel] += 2; - break; - case 4: - if (m_dma_source_increment[channel] == 2) - m_dma_source[channel] -= 4; - *(uint32_t *)data = m_program->read_dword(m_dma_source[channel] & ~3); - if (m_dma_source_increment[channel] == 1) - m_dma_source[channel] += 4; - break; - case 32: - if (m_dma_source_increment[channel] == 2) - m_dma_source[channel] -= 32; - *(uint64_t *)data = m_program->read_qword(m_dma_source[channel] & ~31); - *((uint64_t *)data+1) = m_program->read_qword((m_dma_source[channel] & ~31)+8); - *((uint64_t *)data+2) = m_program->read_qword((m_dma_source[channel] & ~31)+16); - *((uint64_t *)data+3) = m_program->read_qword((m_dma_source[channel] & ~31)+24); - if (m_dma_source_increment[channel] == 1) - m_dma_source[channel] += 32; - break; - } - m_dma_count[channel]--; - } - if (m_dma_count[channel] == 0) // all data transferred ? - { - m_dma_timer[channel]->adjust(attotime::zero, channel); - return 2; - } - return 1; - } - else if (m_dma_mode[channel] == 3) - { - // device sends data - len = m_dma_count[channel]; - if (s->length < len) - len = s->length; - siz = m_dma_wordsize[channel]; - for (pos = 0;pos < len;pos++) { - switch (siz) - { - case 8: - if (m_dma_destination_increment[channel] == 2) - m_dma_destination[channel]-=8; - m_program->write_qword(m_dma_destination[channel] & ~7, *(uint64_t *)data); - if (m_dma_destination_increment[channel] == 1) - m_dma_destination[channel]+=8; - break; - case 1: - if (m_dma_destination_increment[channel] == 2) - m_dma_destination[channel]--; - m_program->write_byte(m_dma_destination[channel], *(uint8_t *)data); - if (m_dma_destination_increment[channel] == 1) - m_dma_destination[channel]++; - break; - case 2: - if (m_dma_destination_increment[channel] == 2) - m_dma_destination[channel]-=2; - m_program->write_word(m_dma_destination[channel] & ~1, *(uint16_t *)data); - if (m_dma_destination_increment[channel] == 1) - m_dma_destination[channel]+=2; - break; - case 4: - if (m_dma_destination_increment[channel] == 2) - m_dma_destination[channel]-=4; - m_program->write_dword(m_dma_destination[channel] & ~3, *(uint32_t *)data); - if (m_dma_destination_increment[channel] == 1) - m_dma_destination[channel]+=4; - break; - case 32: - if (m_dma_destination_increment[channel] == 2) - m_dma_destination[channel]-=32; - m_program->write_qword(m_dma_destination[channel] & ~31, *(uint64_t *)data); - m_program->write_qword((m_dma_destination[channel] & ~31)+8, *((uint64_t *)data+1)); - m_program->write_qword((m_dma_destination[channel] & ~31)+16, *((uint64_t *)data+2)); - m_program->write_qword((m_dma_destination[channel] & ~31)+24, *((uint64_t *)data+3)); - if (m_dma_destination_increment[channel] == 1) - m_dma_destination[channel]+=32; - break; - } - m_dma_count[channel]--; - } - - if (m_dma_count[channel] == 0) // all data transferred ? - { - m_dma_timer[channel]->adjust(attotime::zero, channel); - return 2; - } - return 1; - } - else - return 0; -} - -// called by drivers to transfer data in a DDT dma. -void sh34_base_device::sh4_dma_ddt(struct sh4_ddt_dma *s) -{ - uint32_t chcr; - uint32_t *p32bits; - uint64_t *p32bytes; - uint32_t pos,len,siz; - - if (m_cpu_type != CPU_TYPE_SH4) - fatalerror("sh4_dma_ddt uses m_m[] with SH3\n"); - - if (m_dma_timer_active[s->channel]) - return; - if (s->mode >= 0) { - switch (s->channel) - { - case 0: - if (s->mode & 1) - s->source = m_SH4_SAR0; - if (s->mode & 2) - m_SH4_SAR0 = s->source; - if (s->mode & 4) - s->destination = m_SH4_DAR0; - if (s->mode & 8) - m_SH4_DAR0 = s->destination; - break; - case 1: - if (s->mode & 1) - s->source = m_SH4_SAR1; - if (s->mode & 2) - m_SH4_SAR1 = s->source; - if (s->mode & 4) - s->destination = m_SH4_DAR1; - if (s->mode & 8) - m_SH4_DAR1 = s->destination; - break; - case 2: - if (s->mode & 1) - s->source = m_SH4_SAR2; - if (s->mode & 2) - m_SH4_SAR2 = s->source; - if (s->mode & 4) - s->destination = m_SH4_DAR2; - if (s->mode & 8) - m_SH4_DAR2 = s->destination; - break; - case 3: - default: - if (s->mode & 1) - s->source = m_SH4_SAR3; - if (s->mode & 2) - m_SH4_SAR3 = s->source; - if (s->mode & 4) - s->destination = m_SH4_DAR3; - if (s->mode & 8) - m_SH4_DAR3 = s->destination; - break; - } - switch (s->channel) - { - case 0: - chcr = m_SH4_CHCR0; - len = m_SH4_DMATCR0; - break; - case 1: - chcr = m_SH4_CHCR1; - len = m_SH4_DMATCR1; - break; - case 2: - chcr = m_SH4_CHCR2; - len = m_SH4_DMATCR2; - break; - case 3: - default: - chcr = m_SH4_CHCR3; - len = m_SH4_DMATCR3; - break; - } - if ((s->direction) == 0) { - chcr = (chcr & 0xffff3fff) | ((s->mode & 0x30) << 10); - } else { - chcr = (chcr & 0xffffcfff) | ((s->mode & 0x30) << 8); - } - - - if (m_cpu_type == CPU_TYPE_SH4) - { - //siz = dmasize[(chcr & CHCR_TS) >> 4]; - siz = dmasize[(chcr >> 4) & 7]; - } - else - { - siz = sh3_dmasize[(chcr >> 3) & 3]; - } - - - if (siz && (s->size)) - if ((len * siz) != (s->length * s->size)) - return; - sh4_dma_transfer(s->channel, 0, chcr, &s->source, &s->destination, &len); - } else { - if (s->size == 4) { - if ((s->direction) == 0) { - len = s->length; - p32bits = (uint32_t *)(s->buffer); - for (pos = 0;pos < len;pos++) { - *p32bits = m_program->read_dword(s->source); - p32bits++; - s->source = s->source + 4; - } - } else { - len = s->length; - p32bits = (uint32_t *)(s->buffer); - for (pos = 0;pos < len;pos++) { - m_program->write_dword(s->destination, *p32bits); - p32bits++; - s->destination = s->destination + 4; - } - } - } - if (s->size == 32) { - if ((s->direction) == 0) { - len = s->length * 4; - p32bytes = (uint64_t *)(s->buffer); - for (pos = 0;pos < len;pos++) { - *p32bytes = m_program->read_qword(s->source); - p32bytes++; - s->destination = s->destination + 8; - } - } else { - len = s->length * 4; - p32bytes = (uint64_t *)(s->buffer); - for (pos = 0;pos < len;pos++) { - m_program->write_qword(s->destination, *p32bytes); - p32bytes++; - s->destination = s->destination + 8; - } - } - } - } -} - - - void sh34_base_device::sh4_handle_sar0_addr_w(uint32_t data, uint32_t mem_mask) -{ - COMBINE_DATA(&m_SH4_SAR0); -} - - void sh34_base_device::sh4_handle_sar1_addr_w(uint32_t data, uint32_t mem_mask) -{ - COMBINE_DATA(&m_SH4_SAR1); -} - - void sh34_base_device::sh4_handle_sar2_addr_w(uint32_t data, uint32_t mem_mask) -{ - COMBINE_DATA(&m_SH4_SAR2); -} - - void sh34_base_device::sh4_handle_sar3_addr_w(uint32_t data, uint32_t mem_mask) -{ - COMBINE_DATA(&m_SH4_SAR3); -} - - void sh34_base_device::sh4_handle_dar0_addr_w(uint32_t data, uint32_t mem_mask) -{ - COMBINE_DATA(&m_SH4_DAR0); -} - - void sh34_base_device::sh4_handle_dar1_addr_w(uint32_t data, uint32_t mem_mask) -{ - COMBINE_DATA(&m_SH4_DAR1); -} - - void sh34_base_device::sh4_handle_dar2_addr_w(uint32_t data, uint32_t mem_mask) -{ - COMBINE_DATA(&m_SH4_DAR2); -} - - void sh34_base_device::sh4_handle_dar3_addr_w(uint32_t data, uint32_t mem_mask) -{ - COMBINE_DATA(&m_SH4_DAR3); -} - - void sh34_base_device::sh4_handle_dmatcr0_addr_w(uint32_t data, uint32_t mem_mask) -{ - COMBINE_DATA(&m_SH4_DMATCR0); -} - - void sh34_base_device::sh4_handle_dmatcr1_addr_w(uint32_t data, uint32_t mem_mask) -{ - COMBINE_DATA(&m_SH4_DMATCR1); -} - - void sh34_base_device::sh4_handle_dmatcr2_addr_w(uint32_t data, uint32_t mem_mask) -{ - COMBINE_DATA(&m_SH4_DMATCR2); -} - - void sh34_base_device::sh4_handle_dmatcr3_addr_w(uint32_t data, uint32_t mem_mask) -{ - COMBINE_DATA(&m_SH4_DMATCR3); -} - - void sh34_base_device::sh4_handle_chcr0_addr_w(uint32_t data, uint32_t mem_mask) -{ - COMBINE_DATA(&m_SH4_CHCR0); - sh4_dmac_check(0); -} - - void sh34_base_device::sh4_handle_chcr1_addr_w(uint32_t data, uint32_t mem_mask) -{ - COMBINE_DATA(&m_SH4_CHCR1); - sh4_dmac_check(1); -} - - void sh34_base_device::sh4_handle_chcr2_addr_w(uint32_t data, uint32_t mem_mask) -{ - COMBINE_DATA(&m_SH4_CHCR2); - sh4_dmac_check(2); -} - - void sh34_base_device::sh4_handle_chcr3_addr_w(uint32_t data, uint32_t mem_mask) -{ - COMBINE_DATA(&m_SH4_CHCR3); - sh4_dmac_check(3); -} - - void sh34_base_device::sh4_handle_dmaor_addr_w(uint32_t data, uint32_t mem_mask) -{ - uint32_t old = m_SH4_DMAOR; - COMBINE_DATA(&m_SH4_DMAOR); - - if ((m_SH4_DMAOR & DMAOR_AE) && (~old & DMAOR_AE)) - m_SH4_DMAOR &= ~DMAOR_AE; - if ((m_SH4_DMAOR & DMAOR_NMIF) && (~old & DMAOR_NMIF)) - m_SH4_DMAOR &= ~DMAOR_NMIF; - sh4_dmac_check(0); - sh4_dmac_check(1); - sh4_dmac_check(2); - sh4_dmac_check(3); -} diff --git a/src/devices/cpu/superh/sh4dmac.h b/src/devices/cpu/superh/sh4dmac.h deleted file mode 100644 index b7918fac997..00000000000 --- a/src/devices/cpu/superh/sh4dmac.h +++ /dev/null @@ -1,63 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:R. Belmont -/* SHA3/4 DMA Controller */ - -/* bit definitions */ -#define CHCR_SSA 0xe0000000 -#define CHCR_STC 0x10000000 -#define CHCR_DSA 0x0e000000 -#define CHCR_DTC 0x01000000 -#define CHCR_DS 0x00080000 -#define CHCR_RL 0x00040000 -#define CHCR_AM 0x00020000 -#define CHCR_AL 0x00010000 -#define CHCR_DM 0x0000c000 -#define CHCR_SM 0x00003000 -#define CHCR_RS 0x00000f00 -#define CHCR_TM 0x00000080 -#define CHCR_TS 0x00000070 -#define CHCR_IE 0x00000004 -#define CHCR_TE 0x00000002 -#define CHCR_DE 0x00000001 - -#define DMAOR_DDT 0x8000 -#define DMAOR_PR 0x0300 -#define DMAOR_COD 0x0010 -#define DMAOR_AE 0x0004 -#define DMAOR_NMIF 0x0002 -#define DMAOR_DME 0x0001 - -void sh4_handle_sar0_addr_w(uint32_t data, uint32_t mem_mask); -void sh4_handle_sar1_addr_w(uint32_t data, uint32_t mem_mask); -void sh4_handle_sar2_addr_w(uint32_t data, uint32_t mem_mask); -void sh4_handle_sar3_addr_w(uint32_t data, uint32_t mem_mask); -void sh4_handle_dar0_addr_w(uint32_t data, uint32_t mem_mask); -void sh4_handle_dar1_addr_w(uint32_t data, uint32_t mem_mask); -void sh4_handle_dar2_addr_w(uint32_t data, uint32_t mem_mask); -void sh4_handle_dar3_addr_w(uint32_t data, uint32_t mem_mask); -void sh4_handle_dmatcr0_addr_w(uint32_t data, uint32_t mem_mask); -void sh4_handle_dmatcr1_addr_w(uint32_t data, uint32_t mem_mask); -void sh4_handle_dmatcr2_addr_w(uint32_t data, uint32_t mem_mask); -void sh4_handle_dmatcr3_addr_w(uint32_t data, uint32_t mem_mask); -void sh4_handle_chcr0_addr_w(uint32_t data, uint32_t mem_mask); -void sh4_handle_chcr1_addr_w(uint32_t data, uint32_t mem_mask); -void sh4_handle_chcr2_addr_w(uint32_t data, uint32_t mem_mask); -void sh4_handle_chcr3_addr_w(uint32_t data, uint32_t mem_mask); -void sh4_handle_dmaor_addr_w(uint32_t data, uint32_t mem_mask); -uint32_t sh4_handle_sar0_addr_r(uint32_t mem_mask); -uint32_t sh4_handle_sar1_addr_r(uint32_t mem_mask); -uint32_t sh4_handle_sar2_addr_r(uint32_t mem_mask); -uint32_t sh4_handle_sar3_addr_r(uint32_t mem_mask); -uint32_t sh4_handle_dar0_addr_r(uint32_t mem_mask); -uint32_t sh4_handle_dar1_addr_r(uint32_t mem_mask); -uint32_t sh4_handle_dar2_addr_r(uint32_t mem_mask); -uint32_t sh4_handle_dar3_addr_r(uint32_t mem_mask); -uint32_t sh4_handle_dmatcr0_addr_r(uint32_t mem_mask); -uint32_t sh4_handle_dmatcr1_addr_r(uint32_t mem_mask); -uint32_t sh4_handle_dmatcr2_addr_r(uint32_t mem_mask); -uint32_t sh4_handle_dmatcr3_addr_r(uint32_t mem_mask); -uint32_t sh4_handle_chcr0_addr_r(uint32_t mem_mask); -uint32_t sh4_handle_chcr1_addr_r(uint32_t mem_mask); -uint32_t sh4_handle_chcr2_addr_r(uint32_t mem_mask); -uint32_t sh4_handle_chcr3_addr_r(uint32_t mem_mask); -uint32_t sh4_handle_dmaor_addr_r(uint32_t mem_mask); diff --git a/src/devices/cpu/superh/sh4regs.h b/src/devices/cpu/superh/sh4regs.h deleted file mode 100644 index 384f062858e..00000000000 --- a/src/devices/cpu/superh/sh4regs.h +++ /dev/null @@ -1,183 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:R. Belmont -#pragma once - -#ifndef __SH4REGS_H__ -#define __SH4REGS_H__ - -/* 00000001111111100000000011111100 */ -#define PTEH 0x2000 /* FF000000 */ -#define PTEL 0x2001 /* FF000004 */ -#define TTB 0x2002 /* FF000008 */ -#define TEA 0x2003 /* FF00000C */ -#define MMUCR 0x2004 /* FF000010 */ -#define BASRA 0x2005 /* FF000014 */ -#define BASRB 0x2006 /* FF000018 */ -#define CCR 0x2007 /* FF00001C */ -#define TRA 0x2008 /* FF000020 */ -#define EXPEVT 0x2009 /* FF000024 */ -#define INTEVT 0x200A /* FF000028 */ -#define VERSION 0x200C /* FF000030 */ -#define PTEA 0x200D /* FF000034 */ -#define QACR0 0x200E /* FF000038 */ -#define QACR1 0x200F /* FF00003C */ -#define PRR 0x2011 /* FF000044 */ -#define BARA 0x2400 /* FF200000 */ -#define BAMRA 0x2401 /* FF200004 */ -#define BBRA 0x2402 /* FF200008 */ -#define BARB 0x2403 /* FF20000C */ -#define BAMRB 0x2404 /* FF200010 */ -#define BBRB 0x2405 /* FF200014 */ -#define BDRB 0x2406 /* FF200018 */ -#define BDMRB 0x2407 /* FF20001C */ -#define BRCR 0x2408 /* FF200020 */ -#define BCR1 0x3000 /* FF800000 */ -#define BCR2 0x3001 /* FF800004 */ -#define BCR3 0x3014 /* FF800050 */ -#define BCR4 0x17C /* FE0A00F0 */ -#define WCR1 0x3002 /* FF800008 */ -#define WCR2 0x3003 /* FF80000C */ -#define WCR3 0x3004 /* FF800010 */ -#define MCR 0x3005 /* FF800014 */ -#define PCR 0x3006 /* FF800018 */ -#define RTCSR 0x3007 /* FF80001C */ -#define RTCNT 0x3008 /* FF800020 */ -#define RTCOR 0x3009 /* FF800024 */ -#define RFCR 0x300A /* FF800028 */ -#define PCTRA 0x300B /* FF80002C */ -#define PDTRA 0x300C /* FF800030 */ -#define PCTRB 0x3010 /* FF800040 */ -#define PDTRB 0x3011 /* FF800044 */ -#define GPIOIC 0x3012 /* FF800048 */ -#define SDMR2 0x3200 /* FF900000 */ -#define SDMR3 0x3280 /* FF940000 */ -#define SH4_SAR0_ADDR 0x3400 /* FFA00000 */ -#define SH4_DAR0_ADDR 0x3401 /* FFA00004 */ -#define SH4_DMATCR0_ADDR 0x3402 /* FFA00008 */ -#define SH4_CHCR0_ADDR 0x3403 /* FFA0000C */ -#define SH4_SAR1_ADDR 0x3404 /* FFA00010 */ -#define SH4_DAR1_ADDR 0x3405 /* FFA00014 */ -#define SH4_DMATCR1_ADDR 0x3406 /* FFA00018 */ -#define SH4_CHCR1_ADDR 0x3407 /* FFA0001C */ -#define SH4_SAR2_ADDR 0x3408 /* FFA00020 */ -#define SH4_DAR2_ADDR 0x3409 /* FFA00024 */ -#define SH4_DMATCR2_ADDR 0x340A /* FFA00028 */ -#define SH4_CHCR2_ADDR 0x340B /* FFA0002C */ -#define SH4_SAR3_ADDR 0x340C /* FFA00030 */ -#define SH4_DAR3_ADDR 0x340D /* FFA00034 */ -#define SH4_DMATCR3_ADDR 0x340E /* FFA00038 */ -#define SH4_CHCR3_ADDR 0x340F /* FFA0003C */ -#define SH4_DMAOR_ADDR 0x3410 /* FFA00040 */ -#define SAR4 0x3414 /* FFA00050 */ -#define DAR4 0x3415 /* FFA00054 */ -#define DMATCR4 0x3416 /* FFA00058 */ -#define CHCR4 0x3417 /* FFA0005C */ -#define SAR5 0x3418 /* FFA00060 */ -#define DAR5 0x3419 /* FFA00064 */ -#define DMATCR5 0x341A /* FFA00068 */ -#define CHCR5 0x341B /* FFA0006C */ -#define SAR6 0x341C /* FFA00070 */ -#define DAR6 0x341D /* FFA00074 */ -#define DMATCR6 0x341E /* FFA00078 */ -#define CHCR6 0x341F /* FFA0007C */ -#define SAR7 0x3420 /* FFA00080 */ -#define DAR7 0x3421 /* FFA00084 */ -#define DMATCR7 0x3422 /* FFA00088 */ -#define CHCR7 0x3423 /* FFA0008C */ -#define FRQCR 0x3800 /* FFC00000 */ -#define STBCR 0x3801 /* FFC00004 */ -#define WTCNT 0x3802 /* FFC00008 */ -#define WTCSR 0x3803 /* FFC0000C */ -#define STBCR2 0x3804 /* FFC00010 */ -#define R64CNT 0x3900 /* FFC80000 */ -#define RSECCNT 0x3901 /* FFC80004 */ -#define RMINCNT 0x3902 /* FFC80008 */ -#define RHRCNT 0x3903 /* FFC8000C */ -#define RWKCNT 0x3904 /* FFC80010 */ -#define RDAYCNT 0x3905 /* FFC80014 */ -#define RMONCNT 0x3906 /* FFC80018 */ -#define RYRCNT 0x3907 /* FFC8001C */ -#define RSECAR 0x3908 /* FFC80020 */ -#define RMINAR 0x3909 /* FFC80024 */ -#define RHRAR 0x390A /* FFC80028 */ -#define RWKAR 0x390B /* FFC8002C */ -#define RDAYAR 0x390C /* FFC80030 */ -#define RMONAR 0x390D /* FFC80034 */ -#define RCR1 0x390E /* FFC80038 */ -#define RCR2 0x390F /* FFC8003C */ -#define RCR3 0x3914 /* FFC80050 */ -#define RYRAR 0x3915 /* FFC80054 */ -#define ICR 0x3A00 /* FFD00000 */ -#define IPRA 0x3A01 /* FFD00004 */ -#define IPRB 0x3A02 /* FFD00008 */ -#define IPRC 0x3A03 /* FFD0000C */ -#define IPRD 0x3A04 /* FFD00010 */ -#define INTPRI00 0x100 /* FE080000 */ -#define INTREQ00 0x108 /* FE080020 */ -#define INTMSK00 0x110 /* FE080040 */ -#define INTMSKCLR00 0x118 /* FE080060 */ -#define CLKSTP00 0x140 /* FE0A0000 */ -#define CLKSTPCLR00 0x142 /* FE0A0008 */ -#define TSTR2 0x201 /* FE100004 */ -#define TCOR3 0x202 /* FE100008 */ -#define TCNT3 0x203 /* FE10000C */ -#define TCR3 0x204 /* FE100010 */ -#define TCOR4 0x205 /* FE100014 */ -#define TCNT4 0x206 /* FE100018 */ -#define TCR4 0x207 /* FE10001C */ -#define SH4_TOCR_ADDR 0x3B00 /* FFD80000 */ -#define SH4_TSTR_ADDR 0x3B01 /* FFD80004 */ -#define SH4_TCOR0_ADDR 0x3B02 /* FFD80008 */ -#define SH4_TCNT0_ADDR 0x3B03 /* FFD8000C */ -#define SH4_TCR0_ADDR 0x3B04 /* FFD80010 */ -#define SH4_TCOR1_ADDR 0x3B05 /* FFD80014 */ -#define SH4_TCNT1_ADDR 0x3B06 /* FFD80018 */ -#define SH4_TCR1_ADDR 0x3B07 /* FFD8001C */ -#define SH4_TCOR2_ADDR 0x3B08 /* FFD80020 */ -#define SH4_TCNT2_ADDR 0x3B09 /* FFD80024 */ -#define SH4_TCR2_ADDR 0x3B0A /* FFD80028 */ -#define SH4_TCPR2_ADDR 0x3B0B /* FFD8002C */ -#define SCSMR1 0x3C00 /* FFE00000 */ -#define SCBRR1 0x3C01 /* FFE00004 */ -#define SCSCR1 0x3C02 /* FFE00008 */ -#define SCTDR1 0x3C03 /* FFE0000C */ -#define SCSSR1 0x3C04 /* FFE00010 */ -#define SCRDR1 0x3C05 /* FFE00014 */ -#define SCSCMR1 0x3C06 /* FFE00018 */ -#define SCSPTR1 0x3C07 /* FFE0001C */ -#define SCSMR2 0x3D00 /* FFE80000 */ -#define SCBRR2 0x3D01 /* FFE80004 */ -#define SCSCR2 0x3D02 /* FFE80008 */ -#define SCFTDR2 0x3D03 /* FFE8000C */ -#define SCFSR2 0x3D04 /* FFE80010 */ -#define SCFRDR2 0x3D05 /* FFE80014 */ -#define SCFCR2 0x3D06 /* FFE80018 */ -#define SCFDR2 0x3D07 /* FFE8001C */ -#define SCSPTR2 0x3D08 /* FFE80020 */ -#define SCLSR2 0x3D09 /* FFE80024 */ -#define SDIR 0x3E00 /* FFF00000 */ -#define SDDR 0x3E02 /* FFF00008 */ -#define SDINT 0x3E05 /* FFF00014 */ -#define SIZEREGS 15878 - - - -#define MMUCR_LRUI 0xfc000000 -#define MMUCR_URB 0x00fc0000 -#define MMUCR_URC 0x0000fc00 -#define MMUCR_SQMD 0x00000200 -#define MMUCR_SV 0x00000100 -#define MMUCR_TI 0x00000004 -#define MMUCR_AT 0x00000001 - -/* constants */ -#define PVR_SH7091 0x040205c1 -#define PVR_SH7750 0x04020500 // from TN-SH7-361B/E -#define PVR_SH7750S 0x04020600 -#define PVR_SH7750R 0x04050000 -#define PRR_SH7750R 0x00000100 -#define PVR_SH7751 0x04110000 -#define PVR_SH7751R 0x04050000 -#define PRR_SH7751R 0x00000110 - -#endif /* __SH4REGS_H__ */ diff --git a/src/devices/cpu/superh/sh4tmu.cpp b/src/devices/cpu/superh/sh4tmu.cpp deleted file mode 100644 index 4735b8bba67..00000000000 --- a/src/devices/cpu/superh/sh4tmu.cpp +++ /dev/null @@ -1,324 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:R. Belmont -/* SH3/4 Timer Unit */ - -#include "emu.h" -#include "debugger.h" -#include "sh4.h" -#include "sh4comn.h" -#include "sh3comn.h" -#include "sh4tmu.h" - -static const int tcnt_div[8] = { 4, 16, 64, 256, 1024, 1, 1, 1 }; - -/*------------------------------------------------- - sh4_scale_up_mame_time - multiply a attotime by - a (constant+1) where 0 <= constant < 2^32 --------------------------------------------------*/ - -static inline attotime sh4_scale_up_mame_time(const attotime &_time1, uint32_t factor1) -{ - return _time1 * factor1 + _time1; -} - -static uint32_t compute_ticks_timer(emu_timer *timer, int hertz, int divisor) -{ - double ret; - - ret=((timer->remaining().as_double() * (double)hertz) / (double)divisor) - 1; - return (uint32_t)ret; -} - -void sh34_base_device::sh4_timer_recompute(int which) -{ - double ticks; - - uint32_t tcnt = 0; - uint32_t tcr = 0; - switch (which) - { - case 0: - tcr = m_SH4_TCR0; - tcnt = m_SH4_TCNT0; - break; - - case 1: - tcr = m_SH4_TCR1; - tcnt = m_SH4_TCNT1; - break; - - case 2: - tcr = m_SH4_TCR2; - tcnt = m_SH4_TCNT2; - break; - } - - ticks = tcnt; - m_timer[which]->adjust(sh4_scale_up_mame_time(attotime::from_hz(m_pm_clock) * tcnt_div[tcr & 7], ticks), which); -} - - -TIMER_CALLBACK_MEMBER( sh34_base_device::sh4_timer_callback ) -{ - int which = param; - - switch (which) - { - case 0: - m_SH4_TCNT0 = m_SH4_TCOR0; - break; - - case 1: - m_SH4_TCNT1 = m_SH4_TCOR1; - break; - - case 2: - m_SH4_TCNT2 = m_SH4_TCOR2; - break; - - } - - sh4_timer_recompute(which); - - switch (which) - { - case 0: - m_SH4_TCR0 |= 0x100; - break; - - case 1: - m_SH4_TCR1 |= 0x100; - break; - - case 2: - m_SH4_TCR2 |= 0x100; - break; - - } - - switch (which) - { - case 0: - if (m_SH4_TCR0 & 0x20) - { - sh4_exception_request(SH4_INTC_TUNI0); - // logerror("SH4_INTC_TUNI0 requested\n"); - } - break; - - case 1: - if (m_SH4_TCR1 & 0x20) - { - sh4_exception_request(SH4_INTC_TUNI1); - // logerror("SH4_INTC_TUNI1 requested\n"); - } - break; - - case 2: - if (m_SH4_TCR2 & 0x20) - { - sh4_exception_request(SH4_INTC_TUNI2); - // logerror("SH4_INTC_TUNI2 requested\n"); - } - break; - - } -} - - -uint32_t sh34_base_device::sh4_handle_tcnt0_addr_r(uint32_t mem_mask) -{ - if (m_SH4_TSTR & 1) - return compute_ticks_timer(m_timer[0], m_pm_clock, tcnt_div[m_SH4_TCR0 & 7]); - else - return m_SH4_TCNT0; -} - -uint32_t sh34_base_device::sh4_handle_tcnt1_addr_r(uint32_t mem_mask) -{ - if (m_SH4_TSTR & 2) - return compute_ticks_timer(m_timer[1], m_pm_clock, tcnt_div[m_SH4_TCR1 & 7]); - else - return m_SH4_TCNT1; -} - -uint32_t sh34_base_device::sh4_handle_tcnt2_addr_r(uint32_t mem_mask) -{ - if (m_SH4_TSTR & 4) - return compute_ticks_timer(m_timer[2], m_pm_clock, tcnt_div[m_SH4_TCR2 & 7]); - else - return m_SH4_TCNT2; -} - -uint32_t sh34_base_device::sh4_handle_tcor0_addr_r(uint32_t mem_mask) -{ - return m_SH4_TCOR0; -} - -uint32_t sh34_base_device::sh4_handle_tcor1_addr_r(uint32_t mem_mask) -{ - return m_SH4_TCOR1; -} - -uint32_t sh34_base_device::sh4_handle_tcor2_addr_r(uint32_t mem_mask) -{ - return m_SH4_TCOR2; -} - -uint32_t sh34_base_device::sh4_handle_tcr0_addr_r(uint32_t mem_mask) -{ - return m_SH4_TCR0; -} - -uint32_t sh34_base_device::sh4_handle_tcr1_addr_r(uint32_t mem_mask) -{ - return m_SH4_TCR1; -} - -uint32_t sh34_base_device::sh4_handle_tcr2_addr_r(uint32_t mem_mask) -{ - return m_SH4_TCR2; -} - -uint32_t sh34_base_device::sh4_handle_tstr_addr_r(uint32_t mem_mask) -{ - return m_SH4_TSTR; -} - -uint32_t sh34_base_device::sh4_handle_tocr_addr_r(uint32_t mem_mask) -{ - return m_SH4_TOCR; -} - -uint32_t sh34_base_device::sh4_handle_tcpr2_addr_r(uint32_t mem_mask) -{ - return m_SH4_TCPR2; -} - - -void sh34_base_device::sh4_handle_tstr_addr_w(uint32_t data, uint32_t mem_mask) -{ - uint32_t old2 = m_SH4_TSTR; - COMBINE_DATA(&m_SH4_TSTR); - - if (old2 & 1) - m_SH4_TCNT0 = compute_ticks_timer(m_timer[0], m_pm_clock, tcnt_div[m_SH4_TCR0 & 7]); - if ((m_SH4_TSTR & 1) == 0) { - m_timer[0]->adjust(attotime::never); - } else - sh4_timer_recompute(0); - - if (old2 & 2) - m_SH4_TCNT1 = compute_ticks_timer(m_timer[1], m_pm_clock, tcnt_div[m_SH4_TCR1 & 7]); - if ((m_SH4_TSTR & 2) == 0) { - m_timer[1]->adjust(attotime::never); - } else - sh4_timer_recompute(1); - - if (old2 & 4) - m_SH4_TCNT2 = compute_ticks_timer(m_timer[2], m_pm_clock, tcnt_div[m_SH4_TCR2 & 7]); - if ((m_SH4_TSTR & 4) == 0) { - m_timer[2]->adjust(attotime::never); - } else - sh4_timer_recompute(2); -} - -void sh34_base_device::sh4_handle_tcr0_addr_w(uint32_t data, uint32_t mem_mask) -{ - uint32_t old2 = m_SH4_TCR0; - COMBINE_DATA(&m_SH4_TCR0); - if (m_SH4_TSTR & 1) - { - m_SH4_TCNT0 = compute_ticks_timer(m_timer[0], m_pm_clock, tcnt_div[old2 & 7]); - sh4_timer_recompute(0); - } - if (!(m_SH4_TCR0 & 0x20) || !(m_SH4_TCR0 & 0x100)) - sh4_exception_unrequest(SH4_INTC_TUNI0); -} - -void sh34_base_device::sh4_handle_tcr1_addr_w(uint32_t data, uint32_t mem_mask) -{ - uint32_t old2 = m_SH4_TCR1; - COMBINE_DATA(&m_SH4_TCR1); - if (m_SH4_TSTR & 2) - { - m_SH4_TCNT1 = compute_ticks_timer(m_timer[1], m_pm_clock, tcnt_div[old2 & 7]); - sh4_timer_recompute(1); - } - if (!(m_SH4_TCR1 & 0x20) || !(m_SH4_TCR1 & 0x100)) - sh4_exception_unrequest(SH4_INTC_TUNI1); -} - -void sh34_base_device::sh4_handle_tcr2_addr_w(uint32_t data, uint32_t mem_mask) -{ - uint32_t old2 = m_SH4_TCR2; - COMBINE_DATA(&m_SH4_TCR2); - if (m_SH4_TSTR & 4) - { - m_SH4_TCNT2 = compute_ticks_timer(m_timer[2], m_pm_clock, tcnt_div[old2 & 7]); - sh4_timer_recompute(2); - } - if (!(m_SH4_TCR2 & 0x20) || !(m_SH4_TCR2 & 0x100)) - sh4_exception_unrequest(SH4_INTC_TUNI2); -} - -void sh34_base_device::sh4_handle_tcor0_addr_w(uint32_t data, uint32_t mem_mask) -{ - COMBINE_DATA(&m_SH4_TCOR0); - if (m_SH4_TSTR & 1) - { - m_SH4_TCNT0 = compute_ticks_timer(m_timer[0], m_pm_clock, tcnt_div[m_SH4_TCR0 & 7]); - sh4_timer_recompute(0); - } -} - -void sh34_base_device::sh4_handle_tcor1_addr_w(uint32_t data, uint32_t mem_mask) -{ - COMBINE_DATA(&m_SH4_TCOR1); - if (m_SH4_TSTR & 2) - { - m_SH4_TCNT1 = compute_ticks_timer(m_timer[1], m_pm_clock, tcnt_div[m_SH4_TCR1 & 7]); - sh4_timer_recompute(1); - } -} - -void sh34_base_device::sh4_handle_tcor2_addr_w(uint32_t data, uint32_t mem_mask) -{ - COMBINE_DATA(&m_SH4_TCOR2); - if (m_SH4_TSTR & 4) - { - m_SH4_TCNT2 = compute_ticks_timer(m_timer[2], m_pm_clock, tcnt_div[m_SH4_TCR2 & 7]); - sh4_timer_recompute(2); - } -} - -void sh34_base_device::sh4_handle_tcnt0_addr_w(uint32_t data, uint32_t mem_mask) -{ - COMBINE_DATA(&m_SH4_TCNT0); - if (m_SH4_TSTR & 1) - sh4_timer_recompute(0); -} - -void sh34_base_device::sh4_handle_tcnt1_addr_w(uint32_t data, uint32_t mem_mask) -{ - COMBINE_DATA(&m_SH4_TCNT1); - if (m_SH4_TSTR & 2) - sh4_timer_recompute(1); -} - -void sh34_base_device::sh4_handle_tcnt2_addr_w(uint32_t data, uint32_t mem_mask) -{ - COMBINE_DATA(&m_SH4_TCNT2); - if (m_SH4_TSTR & 4) - sh4_timer_recompute(2); -} - -void sh34_base_device::sh4_handle_tocr_addr_w(uint32_t data, uint32_t mem_mask) -{ - COMBINE_DATA(&m_SH4_TOCR); -} - -void sh34_base_device::sh4_handle_tcpr2_addr_w(uint32_t data, uint32_t mem_mask) -{ - COMBINE_DATA(&m_SH4_TCPR2); -} diff --git a/src/devices/cpu/superh/sh4tmu.h b/src/devices/cpu/superh/sh4tmu.h deleted file mode 100644 index 7bbad37a0c1..00000000000 --- a/src/devices/cpu/superh/sh4tmu.h +++ /dev/null @@ -1,3 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:R. Belmont -/* SH3/4 Timer Unit */ diff --git a/src/devices/cpu/superh/sh7604_bus.cpp b/src/devices/cpu/superh/sh7604_bus.cpp deleted file mode 100644 index f4000a46300..00000000000 --- a/src/devices/cpu/superh/sh7604_bus.cpp +++ /dev/null @@ -1,162 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Angelo Salese -/*************************************************************************** - - SH7604 BUS Controller - - Lies at 0xffffffe0-0xffffffff - - - TODO: - - Host CPU setter (is_slave and clock are needed); - - timer clock emulation; - - fix fatalerrors; - - bus control stuff, someday; - -***************************************************************************/ - -#include "emu.h" -#include "sh7604_bus.h" - -//************************************************************************** -// GLOBAL VARIABLES -//************************************************************************** - -// device type definition -DEFINE_DEVICE_TYPE(SH7604_BUS, sh7604_bus_device, "sh7604bus", "SH7604 BUS Controller") - - -//************************************************************************** -// LIVE DEVICE -//************************************************************************** - -READ16_MEMBER(sh7604_bus_device::bus_control_1_r) -{ - return (m_bcr1 & 0x1ff7) | (m_is_slave == true ? 0x8000 : 0); -} - -WRITE16_MEMBER(sh7604_bus_device::bus_control_1_w) -{ - COMBINE_DATA(&m_bcr1); - if(m_bcr1 & 0x1000) // ENDIAN - throw emu_fatalerror("%s: enabled little endian for Area 2\n", tag()); - if(m_bcr1 & 0x0800) // PSHR - throw emu_fatalerror("%s: enabled partial space share mode\n", tag()); -} - -READ16_MEMBER(sh7604_bus_device::bus_control_2_r) { return m_bcr2 & 0x00fc; } -WRITE16_MEMBER(sh7604_bus_device::bus_control_2_w) -{ - COMBINE_DATA(&m_bcr2); - if(m_bcr2 != 0x00fc) - throw emu_fatalerror("%s: unexpected bus size register set %04x\n", tag(),data); -} - -READ16_MEMBER(sh7604_bus_device::wait_control_r) { return m_wcr; } -WRITE16_MEMBER(sh7604_bus_device::wait_control_w) { COMBINE_DATA(&m_wcr); } - -READ16_MEMBER(sh7604_bus_device::memory_control_r) { return m_mcr & 0xfefc; } -WRITE16_MEMBER(sh7604_bus_device::memory_control_w) { COMBINE_DATA(&m_mcr); } - -READ16_MEMBER(sh7604_bus_device::refresh_timer_status_r) -{ - return m_rtcsr & 0x00f8; -} - -WRITE16_MEMBER(sh7604_bus_device::refresh_timer_control_w) -{ - COMBINE_DATA(&m_rtcsr); - - if(m_rtcsr & 0x40) - throw emu_fatalerror("%s: enabled timer irq register with clock setting = %02x\n",tag(),data & 0x38); -} - -READ16_MEMBER(sh7604_bus_device::refresh_timer_counter_r) -{ - throw emu_fatalerror("%s: reading timer counter!\n",tag()); - return 0; -} - -WRITE16_MEMBER(sh7604_bus_device::refresh_timer_counter_w) -{ - throw emu_fatalerror("%s: writing timer counter %04x\n",tag(),data); - //COMBINE_DATA(&m_rtcnt); -} - -READ16_MEMBER(sh7604_bus_device::refresh_timer_constant_r) -{ - return m_rtcor & 0xff; -} - -WRITE16_MEMBER(sh7604_bus_device::refresh_timer_constant_w) -{ - COMBINE_DATA(&m_rtcor); -} - -DEVICE_ADDRESS_MAP_START( bus_regs, 16, sh7604_bus_device ) - AM_RANGE(0x00, 0x01) AM_READWRITE(bus_control_1_r, bus_control_1_w) - AM_RANGE(0x02, 0x03) AM_READWRITE(bus_control_2_r, bus_control_2_w) - AM_RANGE(0x04, 0x05) AM_READWRITE(wait_control_r, wait_control_w) - AM_RANGE(0x06, 0x07) AM_READWRITE(memory_control_r, memory_control_w) - AM_RANGE(0x08, 0x09) AM_READWRITE(refresh_timer_status_r, refresh_timer_control_w) - AM_RANGE(0x0a, 0x0b) AM_READWRITE(refresh_timer_counter_r, refresh_timer_counter_w) - AM_RANGE(0x0c, 0x0d) AM_READWRITE(refresh_timer_constant_r, refresh_timer_constant_w) -// AM_RANGE(0x0e, 0x0f) unmapped, mirror? -ADDRESS_MAP_END - -//------------------------------------------------- -// sh7604_bus_device - constructor -//------------------------------------------------- - -sh7604_bus_device::sh7604_bus_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : device_t(mconfig, SH7604_BUS, tag, owner, clock) -{ -} - -//------------------------------------------------- -// device_start - device-specific startup -//------------------------------------------------- - -void sh7604_bus_device::device_start() -{ -} - - -//------------------------------------------------- -// device_reset - device-specific reset -//------------------------------------------------- - -void sh7604_bus_device::device_reset() -{ - m_bcr1 = 0x03f0; - m_bcr2 = 0x00fc; - m_wcr = 0xaaff; - m_mcr = 0x0000; - m_rtcsr = 0x0000; - m_rtcor = 0x0000; -} - - -//************************************************************************** -// READ/WRITE HANDLERS -//************************************************************************** - -READ32_MEMBER( sh7604_bus_device::read ) -{ - // 16 bit access only, TODO - return space.read_word(offset) & 0xffff; -} - -WRITE32_MEMBER( sh7604_bus_device::write ) -{ - // TODO: 8 bit access is invalid - // if accessing bits 16-31, one must write ID = 0xa55a - if(ACCESSING_BITS_16_31) - { - // throw fatalerror if something trips it, presumably the write is going to be ignored - if((data & 0xffff0000) != 0xa55a0000) - throw emu_fatalerror("%s: making bus write with ID signature = %04x!\n", tag(),data >> 16); - } - - space.write_word(offset,data & 0xffff); -} diff --git a/src/devices/cpu/superh/sh7604_bus.h b/src/devices/cpu/superh/sh7604_bus.h deleted file mode 100644 index 486ff93558f..00000000000 --- a/src/devices/cpu/superh/sh7604_bus.h +++ /dev/null @@ -1,77 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Angelo Salese -/*************************************************************************** - - SH7604 BUS Controller - -***************************************************************************/ - -#ifndef MAME_CPU_SH2_SH7604_BUS_H -#define MAME_CPU_SH2_SH7604_BUS_H - -#pragma once - - - -//************************************************************************** -// INTERFACE CONFIGURATION MACROS -//************************************************************************** - -#define MCFG_SH7604_BUS_ADD(_tag,_freq) \ - MCFG_DEVICE_ADD(_tag, SH7604_BUS, _freq) - -//************************************************************************** -// TYPE DEFINITIONS -//************************************************************************** - -// ======================> sh7604_bus_device - -class sh7604_bus_device : public device_t -{ -public: - // construction/destruction - sh7604_bus_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); - - // I/O operations - DECLARE_ADDRESS_MAP( bus_regs, 16 ); - - DECLARE_WRITE32_MEMBER( write ); - DECLARE_READ32_MEMBER( read ); - DECLARE_READ16_MEMBER( bus_control_1_r ); - DECLARE_WRITE16_MEMBER( bus_control_1_w ); - DECLARE_READ16_MEMBER( bus_control_2_r ); - DECLARE_WRITE16_MEMBER( bus_control_2_w ); - DECLARE_READ16_MEMBER( wait_control_r ); - DECLARE_WRITE16_MEMBER( wait_control_w ); - DECLARE_READ16_MEMBER( memory_control_r ); - DECLARE_WRITE16_MEMBER( memory_control_w ); - DECLARE_READ16_MEMBER( refresh_timer_status_r ); - DECLARE_WRITE16_MEMBER( refresh_timer_control_w ); - DECLARE_READ16_MEMBER( refresh_timer_counter_r ); - DECLARE_WRITE16_MEMBER( refresh_timer_counter_w ); - DECLARE_READ16_MEMBER( refresh_timer_constant_r ); - DECLARE_WRITE16_MEMBER( refresh_timer_constant_w ); - -protected: - // device-level overrides - //virtual void device_validity_check(validity_checker &valid) const; - virtual void device_start() override; - virtual void device_reset() override; - -private: - bool m_is_slave; - const address_space_config m_space_config; - - uint16_t m_bcr1; - uint16_t m_bcr2; - uint16_t m_wcr; - uint16_t m_mcr; - uint16_t m_rtcsr; - uint16_t m_rtcor; -}; - - -// device type definition -DECLARE_DEVICE_TYPE(SH7604_BUS, sh7604_bus_device) - -#endif // MAME_CPU_SH2_SH7604_BUS_H diff --git a/src/devices/cpu/superh/sh7604_sci.cpp b/src/devices/cpu/superh/sh7604_sci.cpp deleted file mode 100644 index 248e0112622..00000000000 --- a/src/devices/cpu/superh/sh7604_sci.cpp +++ /dev/null @@ -1,156 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Angelo Salese -/*************************************************************************** - - SH7604 SCI Controller - - Lies at 0xfffffe00-0xfffffe0f - - TODO: - - diserial; - - CPU callbacks for RX and TX; - -***************************************************************************/ - -#include "emu.h" -#include "sh7604_sci.h" - - - -//************************************************************************** -// GLOBAL VARIABLES -//************************************************************************** - -// device type definition -DEFINE_DEVICE_TYPE(SH7604_SCI, sh7604_sci_device, "sh7604sci", "SH7604 SCI Controller") - - -//************************************************************************** -// LIVE DEVICE -//************************************************************************** - -READ8_MEMBER(sh7604_sci_device::serial_mode_r) -{ - return m_smr; -} - -WRITE8_MEMBER(sh7604_sci_device::serial_mode_w) -{ - m_smr = data; - - logerror("%s: serial mode set:\n",tag()); - logerror("\tCommunication Mode: %s mode\n",data & 0x80 ? "clocked synchronous" : "asynchronous"); - logerror("\tCharacter Length: %s mode\n",data & 0x40 ? "7-bit" : "8-bit"); - logerror("\tParity Enable: %s\n",data & 0x20 ? "yes" : "no"); - logerror("\tParity Mode: %s\n",data & 0x10 ? "Odd" : "Even"); - logerror("\tStop bits: %s\n",data & 0x08 ? "2" : "1"); - logerror("\tMultiprocessor mode: %s\n",data & 0x04 ? "yes" : "no"); - logerror("\tClock select: clock/%d\n",4 << ((data & 0x03)*2)); -} - -READ8_MEMBER(sh7604_sci_device::serial_control_r) -{ - return m_scr; -} - -WRITE8_MEMBER(sh7604_sci_device::serial_control_w) -{ - m_scr = data; - - if(data & 0x30) - throw emu_fatalerror("%s: enabled serial control %02x\n", tag(),data); -} - -READ8_MEMBER(sh7604_sci_device::serial_status_r) -{ - return m_ssr; -} - -WRITE8_MEMBER(sh7604_sci_device::serial_ack_w) -{ - // TODO: verify this - m_ssr = (m_ssr & 0x06) | (m_ssr & data & 0xf9); -} - -READ8_MEMBER(sh7604_sci_device::bitrate_r ) -{ - return m_brr; -} - -WRITE8_MEMBER(sh7604_sci_device::bitrate_w ) -{ - m_brr = data; -} - -READ8_MEMBER(sh7604_sci_device::transmit_data_r) -{ - // ... - return 0; -} - -WRITE8_MEMBER(sh7604_sci_device::transmit_data_w) -{ - // ... -} - -READ8_MEMBER(sh7604_sci_device::receive_data_r) -{ - // ... - return 0; -} - -DEVICE_ADDRESS_MAP_START( sci_regs, 8, sh7604_sci_device ) - AM_RANGE(0x00, 0x00) AM_READWRITE(serial_mode_r, serial_mode_w) - AM_RANGE(0x01, 0x01) AM_READWRITE(bitrate_r, bitrate_w) - AM_RANGE(0x02, 0x02) AM_READWRITE(serial_control_r,serial_control_w) - AM_RANGE(0x03, 0x03) AM_READWRITE(transmit_data_r, transmit_data_w) - AM_RANGE(0x04, 0x04) AM_READWRITE(serial_status_r, serial_ack_w) - AM_RANGE(0x05, 0x05) AM_READ(receive_data_r) -ADDRESS_MAP_END - -//------------------------------------------------- -// sh7604_sci_device - constructor -//------------------------------------------------- - -sh7604_sci_device::sh7604_sci_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : device_t(mconfig, SH7604_SCI, tag, owner, clock) - -{ -} - - -//------------------------------------------------- -// device_start - device-specific startup -//------------------------------------------------- - -void sh7604_sci_device::device_start() -{ -} - - -//------------------------------------------------- -// device_reset - device-specific reset -//------------------------------------------------- - -void sh7604_sci_device::device_reset() -{ - m_smr = 0; - m_scr = 0; - m_ssr = STATUS_TDRE|STATUS_TEND; //0x84; - m_brr = 0xff; -} - - -//************************************************************************** -// READ/WRITE HANDLERS -//************************************************************************** - -READ8_MEMBER( sh7604_sci_device::read ) -{ - return space.read_byte(offset); -} - -WRITE8_MEMBER( sh7604_sci_device::write ) -{ - space.write_byte(offset,data); -} diff --git a/src/devices/cpu/superh/sh7604_sci.h b/src/devices/cpu/superh/sh7604_sci.h deleted file mode 100644 index d7a290f6946..00000000000 --- a/src/devices/cpu/superh/sh7604_sci.h +++ /dev/null @@ -1,83 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Angelo Salese -/*************************************************************************** - - SH7604 SCI Controller - -***************************************************************************/ - -#ifndef MAME_CPU_SH2_SH7604_SCI_H -#define MAME_CPU_SH2_SH7604_SCI_H - -#pragma once - - - -//************************************************************************** -// INTERFACE CONFIGURATION MACROS -//************************************************************************** - -#define MCFG_SH7604_SCI_ADD(_tag,_freq) \ - MCFG_DEVICE_ADD(_tag, SH7604_SCI, _freq) - -//************************************************************************** -// TYPE DEFINITIONS -//************************************************************************** - -// ======================> sh7604_sci_device - -class sh7604_sci_device : public device_t -{ -public: - // construction/destruction - sh7604_sci_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); - - // I/O operations - DECLARE_ADDRESS_MAP( sci_regs, 8 ); - - DECLARE_WRITE8_MEMBER( write ); - DECLARE_READ8_MEMBER( read ); - - DECLARE_READ8_MEMBER( serial_mode_r ); - DECLARE_WRITE8_MEMBER( serial_mode_w ); - DECLARE_READ8_MEMBER( bitrate_r ); - DECLARE_WRITE8_MEMBER( bitrate_w ); - DECLARE_READ8_MEMBER( serial_control_r ); - DECLARE_WRITE8_MEMBER( serial_control_w ); - - DECLARE_READ8_MEMBER( transmit_data_r ); - DECLARE_WRITE8_MEMBER( transmit_data_w ); - DECLARE_READ8_MEMBER( serial_status_r ); - DECLARE_WRITE8_MEMBER( serial_ack_w ); - DECLARE_READ8_MEMBER( receive_data_r ); - -protected: - enum { - STATUS_MPBT = 1 << 0, - STATUS_MPB = 1 << 1, - STATUS_TEND = 1 << 2, - STATUS_PER = 1 << 3, - STATUS_FER = 1 << 4, - STATUS_ORER = 1 << 5, - STATUS_RDRF = 1 << 6, - STATUS_TDRE = 1 << 7 - }; - - // device-level overrides -// virtual void device_validity_check(validity_checker &valid) const; - virtual void device_start() override; - virtual void device_reset() override; - -private: - const address_space_config m_space_config; - uint8_t m_smr; - uint8_t m_scr; - uint8_t m_ssr; - uint8_t m_brr; -}; - - -// device type definition -DECLARE_DEVICE_TYPE(SH7604_SCI, sh7604_sci_device) - -#endif // MAME_CPU_SH2_SH7604_SCI_H diff --git a/src/devices/cpu/superh/sh7604_wdt.cpp b/src/devices/cpu/superh/sh7604_wdt.cpp deleted file mode 100644 index 16b40f30768..00000000000 --- a/src/devices/cpu/superh/sh7604_wdt.cpp +++ /dev/null @@ -1,83 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Angelo Salese -/*************************************************************************** - - SH7604 Watchdog Timer Controller - - TODO: - - Host CPU setter (clock and callback for irq and reset lines); - - memory map (needs to verify if ID write is ok); - -***************************************************************************/ - -#include "emu.h" -#include "sh7604_wdt.h" - - - -//************************************************************************** -// GLOBAL VARIABLES -//************************************************************************** - -// device type definition -DEFINE_DEVICE_TYPE(SH7604_WDT, sh7604_wdt_device, "sh7604wdt", "SH7604 Watchdog Timer") - - -//************************************************************************** -// LIVE DEVICE -//************************************************************************** - -DEVICE_ADDRESS_MAP_START( wdt_regs, 8, sh7604_wdt_device ) -// AM_RANGE(0x00, 0x00) timer control/status -// AM_RANGE(0x01, 0x01) timer counter -// AM_RANGE(0x02, 0x02) write only, reset control register -// AM_RANGE(0x03, 0x03) read status register, write reset status register -ADDRESS_MAP_END - -//------------------------------------------------- -// sh7604_wdt_device - constructor -//------------------------------------------------- - -sh7604_wdt_device::sh7604_wdt_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : device_t(mconfig, SH7604_WDT, tag, owner, clock) -{ -} - - -//------------------------------------------------- -// device_start - device-specific startup -//------------------------------------------------- - -void sh7604_wdt_device::device_start() -{ -} - - -//------------------------------------------------- -// device_reset - device-specific reset -//------------------------------------------------- - -void sh7604_wdt_device::device_reset() -{ -} - - -//************************************************************************** -// READ/WRITE HANDLERS -//************************************************************************** - -READ8_MEMBER( sh7604_wdt_device::read ) -{ - return space.read_byte(offset); -} - -WRITE16_MEMBER( sh7604_wdt_device::write ) -{ - uint8_t id_param = data >> 8; - switch(id_param) - { - case 0xa5: space.write_byte(offset*2+0,data & 0xff); break; - case 0x5a: space.write_byte(offset*2+1,data & 0xff); break; - default: throw emu_fatalerror("%s: invalid id param write = %02x\n",tag(),id_param); - } -} diff --git a/src/devices/cpu/superh/sh7604_wdt.h b/src/devices/cpu/superh/sh7604_wdt.h deleted file mode 100644 index 7e014745f19..00000000000 --- a/src/devices/cpu/superh/sh7604_wdt.h +++ /dev/null @@ -1,54 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Angelo Salese -/*************************************************************************** - - SH7604 Watchdog Timer Controller - -***************************************************************************/ - -#ifndef MAME_CPU_SH7604_WDT_H -#define MAME_CPU_SH7604_WDT_H - -#pragma once - - - -//************************************************************************** -// INTERFACE CONFIGURATION MACROS -//************************************************************************** - -#define MCFG_SH7604_WDT_ADD(_tag,_freq) \ - MCFG_DEVICE_ADD(_tag, SH7604_WDT, _freq) - -//************************************************************************** -// TYPE DEFINITIONS -//************************************************************************** - -// ======================> sh7604_wdt_device - -class sh7604_wdt_device : public device_t -{ -public: - // construction/destruction - sh7604_wdt_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); - - // I/O operations - DECLARE_ADDRESS_MAP( wdt_regs, 8 ); - - DECLARE_WRITE16_MEMBER( write ); - DECLARE_READ8_MEMBER( read ); - -protected: - // device-level overrides -// virtual void device_validity_check(validity_checker &valid) const; - virtual void device_start() override; - virtual void device_reset() override; -private: - const address_space_config m_space_config; -}; - - -// device type definition -DECLARE_DEVICE_TYPE(SH7604_WDT, sh7604_wdt_device) - -#endif // MAME_CPU_SH7604_WDT_H diff --git a/src/mame/drivers/alien.cpp b/src/mame/drivers/alien.cpp index 280630ef6ab..69cb5f7ed12 100644 --- a/src/mame/drivers/alien.cpp +++ b/src/mame/drivers/alien.cpp @@ -24,7 +24,7 @@ #include "emu.h" -#include "cpu/superh/sh4.h" +#include "cpu/sh/sh4.h" #include "screen.h" #include "speaker.h" diff --git a/src/mame/drivers/aristmk6.cpp b/src/mame/drivers/aristmk6.cpp index 504367bdbee..896c20e774e 100644 --- a/src/mame/drivers/aristmk6.cpp +++ b/src/mame/drivers/aristmk6.cpp @@ -26,7 +26,7 @@ notes: */ #include "emu.h" -#include "cpu/superh/sh4.h" +#include "cpu/sh/sh4.h" #include "machine/ins8250.h" #include "machine/eepromser.h" #include "screen.h" diff --git a/src/mame/drivers/atvtrack.cpp b/src/mame/drivers/atvtrack.cpp index 7dd3e3d97f2..3e11412f391 100644 --- a/src/mame/drivers/atvtrack.cpp +++ b/src/mame/drivers/atvtrack.cpp @@ -101,7 +101,7 @@ TODO: */ #include "emu.h" -#include "cpu/superh/sh4.h" +#include "cpu/sh/sh4.h" #include "debugger.h" #include "screen.h" diff --git a/src/mame/drivers/casloopy.cpp b/src/mame/drivers/casloopy.cpp index 16bd45937cc..efd5ec2be4f 100644 --- a/src/mame/drivers/casloopy.cpp +++ b/src/mame/drivers/casloopy.cpp @@ -150,7 +150,7 @@ PCB 'Z545-1 A240570-1' ******************************************************************************/ #include "emu.h" -#include "cpu/superh/sh2.h" +#include "cpu/sh/sh2.h" #include "bus/generic/slot.h" #include "bus/generic/carts.h" #include "screen.h" diff --git a/src/mame/drivers/coolridr.cpp b/src/mame/drivers/coolridr.cpp index 526b4f99a37..da086c8a82d 100644 --- a/src/mame/drivers/coolridr.cpp +++ b/src/mame/drivers/coolridr.cpp @@ -283,7 +283,7 @@ to the same bank as defined through A20. #include "emu.h" #include "cpu/m68000/m68000.h" -#include "cpu/superh/sh2.h" +#include "cpu/sh/sh2.h" #include "machine/nvram.h" #include "machine/timer.h" #include "sound/scsp.h" diff --git a/src/mame/drivers/cps3.cpp b/src/mame/drivers/cps3.cpp index 72bd9d340ec..e062ed9d7c6 100644 --- a/src/mame/drivers/cps3.cpp +++ b/src/mame/drivers/cps3.cpp @@ -460,7 +460,7 @@ hardware modification to the security cart..... #include "emu.h" #include "cdrom.h" -#include "cpu/superh/sh2.h" +#include "cpu/sh/sh2.h" #include "machine/intelfsh.h" #include "machine/nvram.h" #include "includes/cps3.h" diff --git a/src/mame/drivers/cv1k.cpp b/src/mame/drivers/cv1k.cpp index 8e10b2cbc72..7483d5a52ea 100644 --- a/src/mame/drivers/cv1k.cpp +++ b/src/mame/drivers/cv1k.cpp @@ -173,8 +173,8 @@ Blitter Timing #include "emu.h" -#include "cpu/superh/sh3comn.h" -#include "cpu/superh/sh4.h" +#include "cpu/sh/sh3comn.h" +#include "cpu/sh/sh4.h" #include "machine/rtc9701.h" #include "machine/serflash.h" #include "sound/ymz770.h" diff --git a/src/mame/drivers/dccons.cpp b/src/mame/drivers/dccons.cpp index 9085567c08f..d5cbb09e2b4 100644 --- a/src/mame/drivers/dccons.cpp +++ b/src/mame/drivers/dccons.cpp @@ -265,7 +265,7 @@ #include "cpu/arm7/arm7.h" #include "cpu/arm7/arm7core.h" -#include "cpu/superh/sh4.h" +#include "cpu/sh/sh4.h" #include "imagedev/chd_cd.h" #include "machine/aicartc.h" #include "machine/dc-ctrl.h" diff --git a/src/mame/drivers/deco_mlc.cpp b/src/mame/drivers/deco_mlc.cpp index 615e5963dde..f828fa999ef 100644 --- a/src/mame/drivers/deco_mlc.cpp +++ b/src/mame/drivers/deco_mlc.cpp @@ -105,7 +105,7 @@ #include "machine/deco156.h" #include "machine/eepromser.h" #include "cpu/arm/arm.h" -#include "cpu/superh/sh2.h" +#include "cpu/sh/sh2.h" #include "speaker.h" diff --git a/src/mame/drivers/feversoc.cpp b/src/mame/drivers/feversoc.cpp index 7baa7fc5b71..990d72702e4 100644 --- a/src/mame/drivers/feversoc.cpp +++ b/src/mame/drivers/feversoc.cpp @@ -66,7 +66,7 @@ U0564 LH28F800SU OBJ4-1 *******************************************************************************************/ #include "emu.h" -#include "cpu/superh/sh2.h" +#include "cpu/sh/sh2.h" #include "machine/seibuspi.h" #include "sound/okim6295.h" #include "machine/eepromser.h" diff --git a/src/mame/drivers/hideseek.cpp b/src/mame/drivers/hideseek.cpp index 461f574774b..0ab3d531085 100644 --- a/src/mame/drivers/hideseek.cpp +++ b/src/mame/drivers/hideseek.cpp @@ -27,7 +27,7 @@ Other stuff: NEC D4992 (RTC?) and xtal possibly 32.768kHz, 3V coin battery, 93L4 #include "emu.h" -#include "cpu/superh/sh2.h" +#include "cpu/sh/sh2.h" #include "screen.h" #include "speaker.h" diff --git a/src/mame/drivers/hikaru.cpp b/src/mame/drivers/hikaru.cpp index 3a567338f25..b11db10b948 100644 --- a/src/mame/drivers/hikaru.cpp +++ b/src/mame/drivers/hikaru.cpp @@ -382,7 +382,7 @@ Notes: */ #include "emu.h" -#include "cpu/superh/sh4.h" +#include "cpu/sh/sh4.h" #include "screen.h" diff --git a/src/mame/drivers/namcos23.cpp b/src/mame/drivers/namcos23.cpp index b1bf576e736..3d46605e987 100644 --- a/src/mame/drivers/namcos23.cpp +++ b/src/mame/drivers/namcos23.cpp @@ -1258,7 +1258,7 @@ Notes: #include "cpu/h8/h83002.h" #include "cpu/h8/h83337.h" #include "cpu/mips/mips3.h" -#include "cpu/superh/sh2.h" +#include "cpu/sh/sh2.h" #include "machine/namco_settings.h" #include "machine/nvram.h" #include "machine/rtc4543.h" diff --git a/src/mame/drivers/psikyosh.cpp b/src/mame/drivers/psikyosh.cpp index ad1ebcbf3db..9dab45a6c38 100644 --- a/src/mame/drivers/psikyosh.cpp +++ b/src/mame/drivers/psikyosh.cpp @@ -276,7 +276,7 @@ Notes: #include "emu.h" #include "includes/psikyosh.h" -#include "cpu/superh/sh2.h" +#include "cpu/sh/sh2.h" #include "machine/eepromser.h" #include "machine/watchdog.h" #include "sound/ymf278b.h" diff --git a/src/mame/drivers/saturn.cpp b/src/mame/drivers/saturn.cpp index c4ba07dd2bb..73d1ff54fdb 100644 --- a/src/mame/drivers/saturn.cpp +++ b/src/mame/drivers/saturn.cpp @@ -427,7 +427,7 @@ test1f diagnostic hacks: #include "cpu/m68000/m68000.h" #include "cpu/scudsp/scudsp.h" -#include "cpu/superh/sh2.h" +#include "cpu/sh/sh2.h" #include "imagedev/chd_cd.h" #include "machine/eepromser.h" #include "machine/nvram.h" diff --git a/src/mame/drivers/segasp.cpp b/src/mame/drivers/segasp.cpp index 75cb574ada1..b99e285bbee 100644 --- a/src/mame/drivers/segasp.cpp +++ b/src/mame/drivers/segasp.cpp @@ -74,7 +74,7 @@ G 171-8278G 315-6416 2x 512Mbit RMI */ #include "emu.h" -#include "cpu/superh/sh4.h" +#include "cpu/sh/sh4.h" #include "debugger.h" #include "includes/segasp.h" #include "machine/naomim4.h" diff --git a/src/mame/drivers/sh4robot.cpp b/src/mame/drivers/sh4robot.cpp index 7fb1df99e84..344edd2e13b 100644 --- a/src/mame/drivers/sh4robot.cpp +++ b/src/mame/drivers/sh4robot.cpp @@ -28,7 +28,7 @@ ****************************************************************************/ #include "emu.h" -#include "cpu/superh/sh4.h" +#include "cpu/sh/sh4.h" class sh4robot_state : public driver_device { diff --git a/src/mame/drivers/stv.cpp b/src/mame/drivers/stv.cpp index b2faac037cc..d8de70f6fe8 100644 --- a/src/mame/drivers/stv.cpp +++ b/src/mame/drivers/stv.cpp @@ -40,7 +40,7 @@ #include "cpu/m68000/m68000.h" #include "cpu/scudsp/scudsp.h" -#include "cpu/superh/sh2.h" +#include "cpu/sh/sh2.h" #include "imagedev/chd_cd.h" #include "machine/eepromser.h" #include "machine/smpc.h" diff --git a/src/mame/drivers/suprnova.cpp b/src/mame/drivers/suprnova.cpp index 767e99d1804..c5ce025db7e 100644 --- a/src/mame/drivers/suprnova.cpp +++ b/src/mame/drivers/suprnova.cpp @@ -149,7 +149,7 @@ NEP-16 #include "emu.h" #include "includes/suprnova.h" -#include "cpu/superh/sh2.h" +#include "cpu/sh/sh2.h" #include "machine/msm6242.h" #include "machine/nvram.h" #include "sound/ymz280b.h" diff --git a/src/mame/includes/cps3.h b/src/mame/includes/cps3.h index a6beecdb470..c29d36441e5 100644 --- a/src/mame/includes/cps3.h +++ b/src/mame/includes/cps3.h @@ -7,7 +7,7 @@ ****************************************************************************/ #include "machine/intelfsh.h" -#include "cpu/superh/sh2.h" +#include "cpu/sh/sh2.h" #include "audio/cps3.h" diff --git a/src/mame/includes/naomi.h b/src/mame/includes/naomi.h index ac6a5623544..d6a7484f259 100644 --- a/src/mame/includes/naomi.h +++ b/src/mame/includes/naomi.h @@ -19,7 +19,7 @@ naomi.h -> NAOMI includes #include "machine/naomim2.h" #include "machine/naomim4.h" #include "machine/awboard.h" -#include "cpu/superh/sh4.h" +#include "cpu/sh/sh4.h" #include "cpu/arm7/arm7core.h" #include "sound/aica.h" #include "machine/aicartc.h" diff --git a/src/mame/includes/psikyo4.h b/src/mame/includes/psikyo4.h index 3c59f163291..74e3900a36a 100644 --- a/src/mame/includes/psikyo4.h +++ b/src/mame/includes/psikyo4.h @@ -6,7 +6,7 @@ *************************************************************************/ -#include "cpu/superh/sh2.h" +#include "cpu/sh/sh2.h" #include "sound/ymf278b.h" #include "machine/eepromser.h" #include "screen.h" diff --git a/src/mame/includes/psikyosh.h b/src/mame/includes/psikyosh.h index a112d52238f..8ae929348d0 100644 --- a/src/mame/includes/psikyosh.h +++ b/src/mame/includes/psikyosh.h @@ -2,7 +2,7 @@ // copyright-holders:David Haywood, Paul Priest #include "video/bufsprite.h" #include "machine/eepromser.h" -#include "cpu/superh/sh2.h" +#include "cpu/sh/sh2.h" #include "screen.h" diff --git a/src/mame/includes/saturn.h b/src/mame/includes/saturn.h index bcb83508d7f..86f5ce56109 100644 --- a/src/mame/includes/saturn.h +++ b/src/mame/includes/saturn.h @@ -7,7 +7,7 @@ #include "cpu/m68000/m68000.h" #include "cpu/adsp2100/adsp2100.h" #include "cpu/scudsp/scudsp.h" -#include "cpu/superh/sh2.h" +#include "cpu/sh/sh2.h" #include "bus/sat_ctrl/ctrl.h" diff --git a/src/mame/includes/suprnova.h b/src/mame/includes/suprnova.h index 66beb53e92f..f7563f5db00 100644 --- a/src/mame/includes/suprnova.h +++ b/src/mame/includes/suprnova.h @@ -4,7 +4,7 @@ #include "machine/timer.h" #include "video/sknsspr.h" -#include "cpu/superh/sh2.h" +#include "cpu/sh/sh2.h" struct hit_t diff --git a/src/mame/machine/dc.cpp b/src/mame/machine/dc.cpp index 9e7028b5027..380be28fe55 100644 --- a/src/mame/machine/dc.cpp +++ b/src/mame/machine/dc.cpp @@ -9,7 +9,7 @@ #include "emu.h" #include "debugger.h" #include "includes/dc.h" -#include "cpu/superh/sh4.h" +#include "cpu/sh/sh4.h" #include "cpu/arm7/arm7core.h" #include "machine/mie.h" #include "machine/naomig1.h" diff --git a/src/mame/machine/dccons.cpp b/src/mame/machine/dccons.cpp index 7e1dc48868c..7b252c32ea4 100644 --- a/src/mame/machine/dccons.cpp +++ b/src/mame/machine/dccons.cpp @@ -22,7 +22,7 @@ #include "cdrom.h" #include "debugger.h" #include "includes/dc.h" -#include "cpu/superh/sh4.h" +#include "cpu/sh/sh4.h" #include "sound/aica.h" #include "includes/dccons.h" diff --git a/src/mame/machine/maple-dc.h b/src/mame/machine/maple-dc.h index be061bdda85..095bf289b7d 100644 --- a/src/mame/machine/maple-dc.h +++ b/src/mame/machine/maple-dc.h @@ -5,7 +5,7 @@ #pragma once -#include "cpu/superh/sh4.h" +#include "cpu/sh/sh4.h" #define MCFG_MAPLE_DC_ADD(_tag, _maincpu_tag, _irq_cb) \ MCFG_DEVICE_ADD(_tag, MAPLE_DC, 0) \ diff --git a/src/mame/machine/mega32x.h b/src/mame/machine/mega32x.h index e1f8c0880c2..2e675ce435f 100644 --- a/src/mame/machine/mega32x.h +++ b/src/mame/machine/mega32x.h @@ -6,8 +6,8 @@ #pragma once -#include "cpu/superh/sh2.h" -#include "cpu/superh/sh2comn.h" +#include "cpu/sh/sh2.h" +#include "cpu/sh/sh2comn.h" #include "sound/dac.h" class sega_32x_device : public device_t diff --git a/src/mame/machine/naomig1.h b/src/mame/machine/naomig1.h index 14c5a1512db..aca93be6155 100644 --- a/src/mame/machine/naomig1.h +++ b/src/mame/machine/naomig1.h @@ -5,7 +5,7 @@ #pragma once -#include "cpu/superh/sh4.h" +#include "cpu/sh/sh4.h" #define MCFG_NAOMI_G1_ADD(_tag, type, _irq_cb) \ MCFG_DEVICE_ADD(_tag, type, 0) \ diff --git a/src/mame/machine/saturn.cpp b/src/mame/machine/saturn.cpp index 484a536c64c..3f67edf8f04 100644 --- a/src/mame/machine/saturn.cpp +++ b/src/mame/machine/saturn.cpp @@ -45,7 +45,7 @@ #include "emu.h" #include "includes/saturn.h" -#include "cpu/superh/sh2.h" +#include "cpu/sh/sh2.h" #include "cpu/scudsp/scudsp.h" /* TODO: do this in a verboselog style */ diff --git a/src/mame/machine/saturn_cdb.h b/src/mame/machine/saturn_cdb.h index 3fe76ad9311..f08a2a9efc2 100644 --- a/src/mame/machine/saturn_cdb.h +++ b/src/mame/machine/saturn_cdb.h @@ -6,7 +6,7 @@ #pragma once -#include "cpu/superh/sh2.h" +#include "cpu/sh/sh2.h" DECLARE_DEVICE_TYPE(SATURN_CDB, saturn_cdb_device) diff --git a/src/mame/video/powervr2.cpp b/src/mame/video/powervr2.cpp index 98176f84575..812f6c9ef02 100644 --- a/src/mame/video/powervr2.cpp +++ b/src/mame/video/powervr2.cpp @@ -8,7 +8,7 @@ #include "powervr2.h" #include "includes/dc.h" -#include "cpu/superh/sh4.h" +#include "cpu/sh/sh4.h" #include "video/rgbutil.h" #include "rendutil.h" -- cgit v1.2.3