summaryrefslogtreecommitdiffstatshomepage
path: root/src
diff options
context:
space:
mode:
author R. Belmont <rb6502@users.noreply.github.com>2008-07-13 23:40:54 +0000
committer R. Belmont <rb6502@users.noreply.github.com>2008-07-13 23:40:54 +0000
commit1f9a29d7fac7512b4bb14f71f3ede213264cdc8e (patch)
treef54c289dd32297fdcf8b797c4ab5256f08d652a5 /src
parent4b6e06f1754109e757ec8e158669734dd4494f6b (diff)
UDRC-based SH-2 dynamic recompiler.
- All games on all drivers should work as before except "colmns97" and "stress" which crash due to sound system trouble. - All idle skips are still included. They are quite a bit less effective than they were on the interpreter, but they still give a boost. - Fast RAM bypass is not included yet so this does not represent final performance. That said, it's consistently faster than the interpreter even now. Example: sfiii3 on 0.126 gets 609% on the interpreter and 961% on the DRC. Major thanks to Aaron for his assistance with several sticky core bugs and other issues encountered writing this.
Diffstat (limited to 'src')
-rw-r--r--src/emu/cpu/cpu.mak10
-rw-r--r--src/emu/cpu/sh2/sh2.c16
-rw-r--r--src/emu/cpu/sh2/sh2.h29
-rw-r--r--src/emu/cpu/sh2/sh2comn.c53
-rw-r--r--src/emu/cpu/sh2/sh2comn.h63
-rw-r--r--src/emu/cpu/sh2/sh2drc.c3320
-rw-r--r--src/emu/cpu/sh2/sh2fe.c861
-rw-r--r--src/mame/drivers/cps3.c90
-rw-r--r--src/mame/drivers/psikyosh.c119
-rw-r--r--src/mame/drivers/stv.c11
-rw-r--r--src/mame/drivers/stvinit.c391
-rw-r--r--src/mame/drivers/suprnova.c78
12 files changed, 4837 insertions, 204 deletions
diff --git a/src/emu/cpu/cpu.mak b/src/emu/cpu/cpu.mak
index 4fd1dae5f54..eb36432fa1d 100644
--- a/src/emu/cpu/cpu.mak
+++ b/src/emu/cpu/cpu.mak
@@ -465,7 +465,7 @@ CPUDEFS += -DHAS_SH2=$(if $(filter SH2,$(CPUS)),1,0)
ifneq ($(filter SH2,$(CPUS)),)
OBJDIRS += $(CPUOBJ)/sh2
-CPUOBJS += $(CPUOBJ)/sh2/sh2.o $(CPUOBJ)/sh2/sh2comn.o
+CPUOBJS += $(CPUOBJ)/sh2/sh2.o $(CPUOBJ)/sh2/sh2comn.o $(CPUOBJ)/sh2/sh2drc.o $(CPUOBJ)/sh2/sh2fe.o
DBGOBJS += $(CPUOBJ)/sh2/sh2dasm.o
endif
@@ -477,6 +477,14 @@ $(CPUOBJ)/sh2/sh2comn.o: $(CPUSRC)/sh2/sh2comn.c \
$(CPUSRC)/sh2/sh2comn.h \
$(CPUSRC)/sh2/sh2.h
+$(CPUOBJ)/sh2/sh2drc.o: $(CPUSRC)/sh2/sh2drc.c \
+ $(CPUSRC)/sh2/sh2.h \
+ $(CPUSRC)/sh2/sh2comn.h
+
+$(CPUOBJ)/sh2/sh2fe.o: $(CPUSRC)/sh2/sh2fe.c \
+ $(CPUSRC)/sh2/sh2.h \
+ $(CPUSRC)/sh2/sh2comn.h
+
#-------------------------------------------------
# Hitachi SH4
#-------------------------------------------------
diff --git a/src/emu/cpu/sh2/sh2.c b/src/emu/cpu/sh2/sh2.c
index 2280a42bf5f..ba5e285225e 100644
--- a/src/emu/cpu/sh2/sh2.c
+++ b/src/emu/cpu/sh2/sh2.c
@@ -105,6 +105,8 @@
#include "sh2.h"
#include "sh2comn.h"
+#ifndef USE_SH2DRC
+
/* speed up delay loops, bail out of tight loops */
#define BUSY_LOOP_HACKS 1
@@ -2251,6 +2253,16 @@ static offs_t sh2_dasm(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8
return DasmSH2( buffer, pc, (oprom[0] << 8) | oprom[1] );
}
+static void sh2_init(int index, int clock, const void *config, int (*irqcallback)(int))
+{
+ /* allocate the core memory */
+ sh2 = auto_malloc(sizeof(SH2));
+ memset(sh2, 0, sizeof(SH2));
+
+ /* initialize the common core parts */
+ sh2_common_init(0, index, clock, config, irqcallback);
+}
+
/**************************************************************************
* Generic set_info
**************************************************************************/
@@ -2397,7 +2409,7 @@ void sh2_get_info(UINT32 state, cpuinfo *info)
case CPUINFO_PTR_SET_INFO: info->setinfo = sh2_set_info; break;
case CPUINFO_PTR_GET_CONTEXT: info->getcontext = sh2_get_context; break;
case CPUINFO_PTR_SET_CONTEXT: info->setcontext = sh2_set_context; break;
- case CPUINFO_PTR_INIT: info->init = sh2_common_init; break;
+ case CPUINFO_PTR_INIT: info->init = sh2_init; break;
case CPUINFO_PTR_RESET: info->reset = sh2_reset; break;
case CPUINFO_PTR_EXECUTE: info->execute = sh2_execute; break;
case CPUINFO_PTR_BURN: info->burn = NULL; break;
@@ -2449,3 +2461,5 @@ void sh2_get_info(UINT32 state, cpuinfo *info)
}
}
+
+#endif
diff --git a/src/emu/cpu/sh2/sh2.h b/src/emu/cpu/sh2/sh2.h
index d893271bb2d..aa608ac34f5 100644
--- a/src/emu/cpu/sh2/sh2.h
+++ b/src/emu/cpu/sh2/sh2.h
@@ -57,12 +57,29 @@ enum {
enum
{
- CPUINFO_INT_SH2_FRT_INPUT = CPUINFO_INT_CPU_SPECIFIC
+ CPUINFO_INT_SH2_FRT_INPUT = CPUINFO_INT_CPU_SPECIFIC,
+
+ CPUINFO_INT_SH2_DRC_OPTIONS,
+
+ CPUINFO_INT_SH2_FASTRAM_SELECT,
+ CPUINFO_INT_SH2_FASTRAM_START,
+ CPUINFO_INT_SH2_FASTRAM_END,
+ CPUINFO_INT_SH2_FASTRAM_READONLY,
+
+ CPUINFO_INT_SH2_HOTSPOT_SELECT,
+ CPUINFO_INT_SH2_HOTSPOT_PC,
+ CPUINFO_INT_SH2_HOTSPOT_OPCODE,
+ CPUINFO_INT_SH2_HOTSPOT_CYCLES,
+
+ CPUINFO_INT_SH2_PCFLUSH_SELECT,
+ CPUINFO_INT_SH2_PCFLUSH_ADDR
};
enum
{
CPUINFO_PTR_SH2_FTCSR_READ_CALLBACK = CPUINFO_PTR_CPU_SPECIFIC,
+
+ CPUINFO_PTR_SH2_FASTRAM_BASE
};
struct sh2_config
@@ -77,5 +94,15 @@ READ32_HANDLER( sh2_internal_r );
extern unsigned DasmSH2( char *dst, unsigned pc, UINT16 opcode );
+/***************************************************************************
+ 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_COMPATIBLE_OPTIONS (SH2DRC_STRICT_VERIFY | SH2DRC_FLUSH_PC)
+#define SH2DRC_FASTEST_OPTIONS (0)
+
#endif /* _SH2_H */
diff --git a/src/emu/cpu/sh2/sh2comn.c b/src/emu/cpu/sh2/sh2comn.c
index f3a010645f7..b7671fd5fe2 100644
--- a/src/emu/cpu/sh2/sh2comn.c
+++ b/src/emu/cpu/sh2/sh2comn.c
@@ -259,19 +259,28 @@ static void sh2_dmac_check(int dma)
WRITE32_HANDLER( sh2_internal_w )
{
- UINT32 old = sh2->m[offset];
+ UINT32 old;
+
+#ifdef USE_SH2DRC
+ offset &= 0x7f;
+#endif
+
+ old = sh2->m[offset];
COMBINE_DATA(sh2->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, activecpu_get_pc());
+
switch( offset )
{
// Timers
case 0x04: // TIER, FTCSR, FRC
if((mem_mask & 0x00ffffff) != 0)
sh2_timer_resync();
- logerror("SH2.%d: TIER write %04x @ %04x\n", sh2->cpu_number, data >> 16, mem_mask>>16);
+// printf("SH2.%d: TIER write %04x @ %04x\n", sh2->cpu_number, data >> 16, mem_mask>>16);
sh2->m[4] = (sh2->m[4] & ~(ICF|OCFA|OCFB|OVF)) | (old & sh2->m[4] & (ICF|OCFA|OCFB|OVF));
COMBINE_DATA(&sh2->frc);
if((mem_mask & 0x00ffffff) != 0)
@@ -279,7 +288,7 @@ WRITE32_HANDLER( sh2_internal_w )
sh2_recalc_irq();
break;
case 0x05: // OCRx, TCR, TOCR
- logerror("SH2.%d: TCR write %08x @ %08x\n", sh2->cpu_number, data, mem_mask);
+// printf("SH2.%d: TCR write %08x @ %08x\n", sh2->cpu_number, data, mem_mask);
sh2_timer_resync();
if(sh2->m[5] & 0x10)
sh2->ocrb = (sh2->ocrb & (~mem_mask >> 16)) | ((data & mem_mask) >> 16);
@@ -427,6 +436,9 @@ WRITE32_HANDLER( sh2_internal_w )
READ32_HANDLER( sh2_internal_r )
{
+#ifdef USE_SH2DRC
+ offset &= 0x7f;
+#endif
// logerror("sh2_internal_r: Read %08x (%x) @ %08x\n", 0xfffffe00+offset*4, offset, mem_mask);
switch( offset )
{
@@ -513,7 +525,12 @@ void sh2_set_irq_line(int irqline, int state)
else
{
LOG(("SH-2 #%d assert nmi\n", cpu_getactivecpu()));
- sh2_exception("sh2_set_irq_line/nmi", 16);
+
+ sh2_exception("Set IRQ line", 16);
+
+ #ifdef USE_SH2DRC
+ sh2->pending_nmi = 1;
+ #endif
}
}
else
@@ -531,10 +548,14 @@ void sh2_set_irq_line(int irqline, int state)
{
LOG(("SH-2 #%d assert irq #%d\n", cpu_getactivecpu(), irqline));
sh2->pending_irq |= 1 << irqline;
+ #ifdef USE_SH2DRC
+ sh2->test_irq = 1;
+ #else
if(sh2->delay)
sh2->test_irq = 1;
else
CHECK_PENDING_IRQ("sh2_set_irq_line");
+ #endif
}
}
}
@@ -578,7 +599,6 @@ void sh2_recalc_irq(void)
}
}
-
sh2->internal_irq_level = irq;
sh2->internal_irq_vector = vector;
sh2->test_irq = 1;
@@ -620,6 +640,19 @@ void sh2_exception(const char *message, int irqline)
LOG(("SH-2 #%d nmi exception (autovector: $%x) after [%s]\n", cpu_getactivecpu(), vector, message));
}
+ #ifdef USE_SH2DRC
+ sh2->evec = RL( sh2->vbr + vector * 4 );
+ sh2->evec &= AM;
+ sh2->irqsr = sh2->sr;
+
+ /* set I flags in SR */
+ if (irqline > SH2_INT_15)
+ sh2->sr = sh2->sr | I;
+ else
+ sh2->sr = (sh2->sr & ~I) | (irqline << 4);
+
+// printf("sh2_exception [%s] irqline %x evec %x save SR %x new SR %x\n", message, irqline, sh2->evec, sh2->irqsr, sh2->sr);
+ #else
sh2->r[15] -= 4;
WL( sh2->r[15], sh2->sr ); /* push SR onto stack */
sh2->r[15] -= 4;
@@ -634,14 +667,18 @@ void sh2_exception(const char *message, int irqline)
/* fetch PC */
sh2->pc = RL( sh2->vbr + vector * 4 );
change_pc(sh2->pc & AM);
+ #endif
}
-void sh2_common_init(int index, int clock, const void *config, int (*irqcallback)(int))
+void sh2_common_init(int alloc, int index, int clock, const void *config, int (*irqcallback)(int))
{
const struct sh2_config *conf = config;
- sh2 = (SH2 *)auto_malloc(sizeof(SH2));
- memset(sh2, 0, sizeof(SH2));
+ if (alloc)
+ {
+ sh2 = (SH2 *)auto_malloc(sizeof(SH2));
+ memset(sh2, 0, sizeof(SH2));
+ }
sh2->timer = timer_alloc(sh2_timer_callback, NULL);
timer_adjust_oneshot(sh2->timer, attotime_never, 0);
diff --git a/src/emu/cpu/sh2/sh2comn.h b/src/emu/cpu/sh2/sh2comn.h
index 622eb3d3c92..cf3a26dd162 100644
--- a/src/emu/cpu/sh2/sh2comn.h
+++ b/src/emu/cpu/sh2/sh2comn.h
@@ -9,6 +9,14 @@
#ifndef _SH2_COMMON_H_
#define _SH2_COMMON_H_
+#define USE_SH2DRC
+
+#ifdef USE_SH2DRC
+#include "cpu/drcfe.h"
+#include "cpu/drcuml.h"
+#include "cpu/drcumlsh.h"
+#endif
+
typedef struct
{
int irq_vector;
@@ -35,6 +43,16 @@ enum {
#define Rn ((opcode>>8)&15)
#define Rm ((opcode>>4)&15)
+#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; \
@@ -73,9 +91,17 @@ typedef struct
UINT32 cpu_off;
UINT32 dvsr, dvdnth, dvdntl, dvcr;
UINT32 pending_irq;
- UINT32 test_irq;
+ UINT32 test_irq;
+ UINT32 pending_nmi;
+ UINT32 evec; // exception vector for DRC
+ UINT32 irqsr; // IRQ-time old SR for DRC
+ UINT32 target; // target for jmp/jsr/etc so the delay slot can't kill it
irq_entry irq_queue[16];
+ int pcfsel; // last pcflush entry set
+ int maxpcfsel; // highest valid pcflush entry
+ UINT32 pcflushes[16]; // pcflush entries
+
INT8 irq_line_state[17];
int (*irq_callback)(int irqline);
UINT32 *m;
@@ -96,12 +122,45 @@ typedef struct
int is_slave, cpu_number;
void (*ftcsr_read_callback)(UINT32 data);
+
+#ifdef USE_SH2DRC
+ drccache * cache; /* pointer to the DRC code cache */
+ drcuml_state * drcuml; /* DRC UML generator state */
+ drcfe_state * drcfe; /* pointer to the DRC front-end state */
+ UINT32 drcoptions; /* configurable DRC options */
+
+ int icount;
+
+ /* internal stuff */
+ UINT8 cache_dirty; /* true if we need to flush the cache */
+
+ /* parameters for subroutines */
+ UINT64 numcycles; /* return value from gettotalcycles */
+ UINT32 arg0; /* print_debug argument 1 */
+ UINT32 arg1; /* print_debug argument 2 */
+ UINT32 irq; /* irq we're taking */
+
+ /* register mappings */
+ drcuml_parameter regmap[16]; /* parameter to register mappings for all 16 integer registers */
+
+ drcuml_codehandle * entry; /* entry point */
+ drcuml_codehandle * read8; /* read byte */
+ drcuml_codehandle * write8; /* write byte */
+ drcuml_codehandle * read16; /* read half */
+ drcuml_codehandle * write16; /* write half */
+ drcuml_codehandle * read32; /* read word */
+ drcuml_codehandle * write32; /* write word */
+
+ drcuml_codehandle * interrupt; /* interrupt */
+ drcuml_codehandle * nocode; /* nocode */
+ drcuml_codehandle * out_of_cycles; /* out of cycles exception handler */
+#endif
} SH2;
TIMER_CALLBACK( sh2_timer_callback );
TIMER_CALLBACK( sh2_dmac_callback );
-void sh2_common_init(int index, int clock, const void *config, int (*irqcallback)(int));
+void sh2_common_init(int alloc, int index, int clock, const void *config, int (*irqcallback)(int));
void sh2_recalc_irq(void);
void sh2_set_irq_line(int irqline, int state);
void sh2_set_frt_input(int cpunum, int state);
diff --git a/src/emu/cpu/sh2/sh2drc.c b/src/emu/cpu/sh2/sh2drc.c
new file mode 100644
index 00000000000..337d21708f0
--- /dev/null
+++ b/src/emu/cpu/sh2/sh2drc.c
@@ -0,0 +1,3320 @@
+/***************************************************************************
+
+ sh2drc.c
+ Universal machine language-based SH-2 emulator.
+ By R. Belmont
+
+ Released for general non-commercial use under the MAME license
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+ ST-V status:
+ colmns97 & stress crash due to SCSP stream->machine getting corrupted.
+
+***************************************************************************/
+
+#include "debugger.h"
+#include "deprecat.h"
+#include "sh2.h"
+#include "sh2comn.h"
+
+#ifdef USE_SH2DRC
+
+/***************************************************************************
+ DEBUGGING
+***************************************************************************/
+
+#define FORCE_C_BACKEND (0) // use the C backend even when a native one is available
+#define LOG_UML (0) // log UML assembly
+#define LOG_NATIVE (0) // log native assembly
+
+#define SET_EA (0) // makes slower but "shows work" in the EA register like the interpreter
+
+#define DISABLE_FAST_REGISTERS (0) // set to 1 to turn off usage of register caching
+#define SINGLE_INSTRUCTION_MODE (0)
+
+#define VERBOSE 0
+#define LOG(x) do { if (VERBOSE) logerror x; } while (0)
+
+#if SET_EA
+#define SETEA(x) UML_MOV(block, MEM(&sh2->ea), IREG(x))
+#else
+#define SETEA(x)
+#endif
+
+/***************************************************************************
+ CONSTANTS
+***************************************************************************/
+
+/* map variables */
+#define MAPVAR_PC MVAR(0)
+#define MAPVAR_CYCLES MVAR(1)
+
+/* 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
+
+/* 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
+
+extern int sh2_describe(void *param, opcode_desc *desc, const opcode_desc *prev);
+
+/***************************************************************************
+ MACROS
+***************************************************************************/
+
+#define R32(reg) sh2->regmap[reg].type, sh2->regmap[reg].value
+
+/***************************************************************************
+ STRUCTURES & TYPEDEFS
+***************************************************************************/
+
+/* internal compiler state */
+typedef struct _compiler_state compiler_state;
+struct _compiler_state
+{
+ UINT32 cycles; /* accumulated cycles */
+ UINT8 checkints; /* need to check interrupts before next instruction */
+ drcuml_codelabel labelnum; /* index for local labels */
+};
+
+/***************************************************************************
+ FUNCTION PROTOTYPES
+***************************************************************************/
+
+static void static_generate_entry_point(drcuml_state *drcuml);
+static void static_generate_nocode_handler(drcuml_state *drcuml);
+static void static_generate_out_of_cycles(drcuml_state *drcuml);
+static void static_generate_memory_accessor(drcuml_state *drcuml, int size, int iswrite, const char *name, drcuml_codehandle **handleptr);
+
+static void generate_update_cycles(drcuml_block *block, compiler_state *compiler, drcuml_ptype ptype, UINT64 pvalue, int allow_exception);
+static void generate_checksum_block(drcuml_block *block, compiler_state *compiler, const opcode_desc *seqhead, const opcode_desc *seqlast);
+static void generate_sequence_instruction(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
+static void generate_delay_slot(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
+
+static int generate_opcode(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
+static int generate_group_0(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, UINT16 opcode, int in_delay_slot);
+static int generate_group_2(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, UINT16 opcode, int in_delay_slot);
+static int generate_group_3(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, UINT16 opcode);
+static int generate_group_4(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, UINT16 opcode, int in_delay_slot);
+static int generate_group_6(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, UINT16 opcode, int in_delay_slot);
+static int generate_group_8(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, UINT16 opcode, int in_delay_slot);
+static int generate_group_12(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, UINT16 opcode, int in_delay_slot);
+
+static void code_compile_block(drcuml_state *drcuml, UINT8 mode, offs_t pc);
+
+static void log_opcode_desc(drcuml_state *drcuml, const opcode_desc *desclist, int indent);
+static void log_register_list(drcuml_state *drcuml, const char *string, const UINT32 *reglist, const UINT32 *regnostarlist);
+static void log_add_disasm_comment(drcuml_block *block, UINT32 pc, UINT32 op);
+static const char *log_desc_flags_to_string(UINT32 flags);
+
+static void cfunc_printf_probe(void *param);
+static void cfunc_unimplemented(void *param);
+static void cfunc_checkirqs(void *param);
+static void cfunc_MAC_W(void *param);
+static void cfunc_MAC_L(void *param);
+static void cfunc_DIV1(void *param);
+
+/***************************************************************************
+ PRIVATE GLOBAL VARIABLES
+***************************************************************************/
+
+SH2 *sh2;
+
+/***************************************************************************
+ INLINE FUNCTIONS
+***************************************************************************/
+
+/*-------------------------------------------------
+ epc - compute the exception PC from a
+ descriptor
+-------------------------------------------------*/
+
+INLINE UINT32 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
+-------------------------------------------------*/
+
+INLINE void alloc_handle(drcuml_state *drcuml, drcuml_codehandle **handleptr, const char *name)
+{
+ if (*handleptr == NULL)
+ *handleptr = drcuml_handle_alloc(drcuml, name);
+}
+
+/*-------------------------------------------------
+ load_fast_iregs - load any fast integer
+ registers
+-------------------------------------------------*/
+
+INLINE void load_fast_iregs(drcuml_block *block)
+{
+ int regnum;
+
+ for (regnum = 0; regnum < ARRAY_LENGTH(sh2->regmap); regnum++)
+ {
+ if (sh2->regmap[regnum].type == DRCUML_PTYPE_INT_REGISTER)
+ {
+ UML_MOV(block, IREG(sh2->regmap[regnum].value - DRCUML_REG_I0), MEM(&sh2->r[regnum]));
+ }
+ }
+}
+
+
+/*-------------------------------------------------
+ save_fast_iregs - save any fast integer
+ registers
+-------------------------------------------------*/
+
+INLINE void save_fast_iregs(drcuml_block *block)
+{
+ int regnum;
+
+ for (regnum = 0; regnum < ARRAY_LENGTH(sh2->regmap); regnum++)
+ {
+ if (sh2->regmap[regnum].type == DRCUML_PTYPE_INT_REGISTER)
+ {
+ UML_MOV(block, MEM(&sh2->r[regnum]), IREG(sh2->regmap[regnum].value - DRCUML_REG_I0));
+ }
+ }
+}
+
+/*-------------------------------------------------
+ cfunc_printf_probe - print the current CPU
+ state and return
+-------------------------------------------------*/
+
+static void cfunc_printf_probe(void *param)
+{
+ UINT32 pc = (UINT32)(FPTR)param;
+
+ printf(" PC=%08X r0=%08X r1=%08X r2=%08X\n",
+ pc,
+ (UINT32)sh2->r[0],
+ (UINT32)sh2->r[1],
+ (UINT32)sh2->r[2]);
+ printf(" r3=%08X r4=%08X r5=%08X r6=%08X\n",
+ (UINT32)sh2->r[3],
+ (UINT32)sh2->r[4],
+ (UINT32)sh2->r[5],
+ (UINT32)sh2->r[6]);
+ printf(" r7=%08X r8=%08X r9=%08X r10=%08X\n",
+ (UINT32)sh2->r[7],
+ (UINT32)sh2->r[8],
+ (UINT32)sh2->r[9],
+ (UINT32)sh2->r[10]);
+ printf(" r11=%08X r12=%08X r13=%08X r14=%08X\n",
+ (UINT32)sh2->r[11],
+ (UINT32)sh2->r[12],
+ (UINT32)sh2->r[13],
+ (UINT32)sh2->r[14]);
+ printf(" r15=%08X macl=%08X mach=%08X gbr=%08X\n",
+ (UINT32)sh2->r[15],
+ (UINT32)sh2->macl,
+ (UINT32)sh2->mach,
+ (UINT32)sh2->gbr);
+ printf(" evec %x irqsr %x\n",
+ (UINT32)sh2->evec,
+ (UINT32)sh2->irqsr);
+}
+
+/*-------------------------------------------------
+ cfunc_unimplemented - handler for
+ unimplemented opcdes
+-------------------------------------------------*/
+
+static void cfunc_unimplemented(void *param)
+{
+ UINT16 opcode = (FPTR)param;
+ fatalerror("PC=%08X: Unimplemented op %04X", sh2->pc, opcode);
+}
+
+/*-------------------------------------------------
+ cfunc_checkirqs - checks for pending IRQs
+-------------------------------------------------*/
+static void cfunc_checkirqs(void *param)
+{
+ // if NMI is pending, evec etc are already set up
+ if (sh2->pending_nmi)
+ {
+ sh2->pending_nmi = 0;
+ }
+ else
+ {
+ sh2->evec = 0xffffffff;
+ CHECK_PENDING_IRQ("cfunc_checkirqs");
+ }
+}
+
+INLINE UINT16 RW(offs_t A)
+{
+ if (A >= 0xe0000000)
+ return sh2_internal_r(Machine, (A & 0x1fc)>>2, 0xffff << (((~A) & 2)*8)) >> (((~A) & 2)*8);
+
+ if (A >= 0xc0000000)
+ return program_read_word_32be(A);
+
+ return program_read_word_32be(A & AM);
+}
+
+/*-------------------------------------------------
+ cfunc_MAC_W - implementation of MAC_W Rm,Rn
+-------------------------------------------------*/
+static void cfunc_MAC_W(void *param)
+{
+ INT32 tempm, tempn, dest, src, ans;
+ UINT32 templ;
+ UINT16 *opptr, opcode;
+ int n, m;
+
+ // recover the opcode
+ opptr = (UINT16 *)param;
+ opcode = *opptr;
+
+ // extract the operands
+ n = Rn;
+ m = Rm;
+
+ tempn = (INT32) RW( sh2->r[n] );
+ sh2->r[n] += 2;
+ tempm = (INT32) RW( sh2->r[m] );
+ sh2->r[m] += 2;
+ templ = sh2->macl;
+ tempm = ((INT32) (short) tempn * (INT32) (short) tempm);
+ if ((INT32) sh2->macl >= 0)
+ dest = 0;
+ else
+ dest = 1;
+ if ((INT32) tempm >= 0)
+ {
+ src = 0;
+ tempn = 0;
+ }
+ else
+ {
+ src = 1;
+ tempn = 0xffffffff;
+ }
+ src += dest;
+ sh2->macl += tempm;
+ if ((INT32) sh2->macl >= 0)
+ ans = 0;
+ else
+ ans = 1;
+ ans += dest;
+ if (sh2->sr & S)
+ {
+ if (ans == 1)
+ {
+ if (src == 0)
+ sh2->macl = 0x7fffffff;
+ if (src == 2)
+ sh2->macl = 0x80000000;
+ }
+ }
+ else
+ {
+ sh2->mach += tempn;
+ if (templ > sh2->macl)
+ sh2->mach += 1;
+ }
+}
+
+INLINE UINT32 RL(offs_t A)
+{
+ if (A >= 0xe0000000)
+ return sh2_internal_r(Machine, (A & 0x1fc)>>2, 0xffffffff);
+
+ if (A >= 0xc0000000)
+ return program_read_dword_32be(A);
+
+ return program_read_dword_32be(A & AM);
+}
+
+/*-------------------------------------------------
+ cfunc_MAC_L - implementation of MAC_L Rm,Rn
+-------------------------------------------------*/
+static void cfunc_MAC_L(void *param)
+{
+ UINT32 RnL, RnH, RmL, RmH, Res0, Res1, Res2;
+ UINT32 temp0, temp1, temp2, temp3;
+ INT32 tempm, tempn, fnLmL;
+ UINT16 *opptr, opcode;
+ int n, m;
+
+ // recover the opcode
+ opptr = (UINT16 *)param;
+ opcode = *opptr;
+
+ // extract the operands
+ n = Rn;
+ m = Rm;
+
+ tempn = (INT32) RL( sh2->r[n] );
+ sh2->r[n] += 4;
+ tempm = (INT32) RL( sh2->r[m] );
+ sh2->r[m] += 4;
+ if ((INT32) (tempn ^ tempm) < 0)
+ fnLmL = -1;
+ else
+ fnLmL = 0;
+ if (tempn < 0)
+ tempn = 0 - tempn;
+ if (tempm < 0)
+ tempm = 0 - tempm;
+ temp1 = (UINT32) tempn;
+ temp2 = (UINT32) 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 (sh2->sr & S)
+ {
+ Res0 = sh2->macl + Res0;
+ if (sh2->macl > Res0)
+ Res2++;
+ Res2 += (sh2->mach & 0x0000ffff);
+ if (((INT32) Res2 < 0) && (Res2 < 0xffff8000))
+ {
+ Res2 = 0x00008000;
+ Res0 = 0x00000000;
+ }
+ else if (((INT32) Res2 > 0) && (Res2 > 0x00007fff))
+ {
+ Res2 = 0x00007fff;
+ Res0 = 0xffffffff;
+ }
+ sh2->mach = Res2;
+ sh2->macl = Res0;
+ }
+ else
+ {
+ Res0 = sh2->macl + Res0;
+ if (sh2->macl > Res0)
+ Res2++;
+ Res2 += sh2->mach;
+ sh2->mach = Res2;
+ sh2->macl = Res0;
+ }
+}
+
+/*-------------------------------------------------
+ cfunc_DIV1 - implementation of DIV1 Rm,Rn
+-------------------------------------------------*/
+static void cfunc_DIV1(void *param)
+{
+ UINT32 tmp0;
+ UINT32 old_q;
+ UINT16 *opptr, opcode;
+ int n, m;
+
+ // recover the opcode
+ opptr = (UINT16 *)param;
+ opcode = *opptr;
+
+ // extract the operands
+ n = Rn;
+ m = Rm;
+
+ old_q = sh2->sr & Q;
+ if (0x80000000 & sh2->r[n])
+ sh2->sr |= Q;
+ else
+ sh2->sr &= ~Q;
+
+ sh2->r[n] = (sh2->r[n] << 1) | (sh2->sr & T);
+
+ if (!old_q)
+ {
+ if (!(sh2->sr & M))
+ {
+ tmp0 = sh2->r[n];
+ sh2->r[n] -= sh2->r[m];
+ if(!(sh2->sr & Q))
+ if(sh2->r[n] > tmp0)
+ sh2->sr |= Q;
+ else
+ sh2->sr &= ~Q;
+ else
+ if(sh2->r[n] > tmp0)
+ sh2->sr &= ~Q;
+ else
+ sh2->sr |= Q;
+ }
+ else
+ {
+ tmp0 = sh2->r[n];
+ sh2->r[n] += sh2->r[m];
+ if(!(sh2->sr & Q))
+ {
+ if(sh2->r[n] < tmp0)
+ sh2->sr &= ~Q;
+ else
+ sh2->sr |= Q;
+ }
+ else
+ {
+ if(sh2->r[n] < tmp0)
+ sh2->sr |= Q;
+ else
+ sh2->sr &= ~Q;
+ }
+ }
+ }
+ else
+ {
+ if (!(sh2->sr & M))
+ {
+ tmp0 = sh2->r[n];
+ sh2->r[n] += sh2->r[m];
+ if(!(sh2->sr & Q))
+ if(sh2->r[n] < tmp0)
+ sh2->sr |= Q;
+ else
+ sh2->sr &= ~Q;
+ else
+ if(sh2->r[n] < tmp0)
+ sh2->sr &= ~Q;
+ else
+ sh2->sr |= Q;
+ }
+ else
+ {
+ tmp0 = sh2->r[n];
+ sh2->r[n] -= sh2->r[m];
+ if(!(sh2->sr & Q))
+ if(sh2->r[n] > tmp0)
+ sh2->sr &= ~Q;
+ else
+ sh2->sr |= Q;
+ else
+ if(sh2->r[n] > tmp0)
+ sh2->sr |= Q;
+ else
+ sh2->sr &= ~Q;
+ }
+ }
+
+ tmp0 = (sh2->sr & (Q | M));
+ if((!tmp0) || (tmp0 == 0x300)) /* if Q == M set T else clear T */
+ sh2->sr |= T;
+ else
+ sh2->sr &= ~T;
+}
+
+/*-------------------------------------------------
+ sh2_init - initialize the processor
+-------------------------------------------------*/
+
+static void sh2_init(int index, int clock, const void *config, int (*irqcallback)(int))
+{
+ drcfe_config feconfig =
+ {
+ COMPILE_BACKWARDS_BYTES, /* code window start offset = startpc - window_start */
+ COMPILE_FORWARDS_BYTES, /* code window end offset = startpc + window_end */
+ COMPILE_MAX_SEQUENCE, /* maximum instructions to include in a sequence */
+ sh2_describe /* callback to describe a single instruction */
+ };
+ drccache *cache;
+ drcbe_info beinfo;
+ UINT32 flags = 0;
+ int regnum;
+
+ /* allocate enough space for the cache and the core */
+ cache = drccache_alloc(CACHE_SIZE + sizeof(SH2));
+ if (cache == NULL)
+ fatalerror("Unable to allocate cache of size %d", (UINT32)(CACHE_SIZE + sizeof(SH2)));
+
+ /* allocate the core memory */
+ sh2 = drccache_memory_alloc_near(cache, sizeof(SH2));
+ memset(sh2, 0, sizeof(SH2));
+
+ /* initialize the common core parts */
+ sh2_common_init(0, index, clock, config, irqcallback);
+
+ /* allocate the implementation-specific state from the full cache */
+ sh2->cache = cache;
+
+ /* reset per-driver pcflushes */
+ sh2->pcfsel = sh2->maxpcfsel = -1;
+
+ /* initialize the UML generator */
+ if (FORCE_C_BACKEND)
+ flags |= DRCUML_OPTION_USE_C;
+ if (LOG_UML)
+ flags |= DRCUML_OPTION_LOG_UML;
+ if (LOG_NATIVE)
+ flags |= DRCUML_OPTION_LOG_NATIVE;
+ sh2->drcuml = drcuml_alloc(cache, flags, 1, 32, 0);
+ if (sh2->drcuml == NULL)
+ fatalerror("Error initializing the UML");
+
+ /* add symbols for our stuff */
+ drcuml_symbol_add(sh2->drcuml, &sh2->pc, sizeof(sh2->pc), "pc");
+ drcuml_symbol_add(sh2->drcuml, &sh2->icount, sizeof(sh2->icount), "icount");
+ for (regnum = 0; regnum < 16; regnum++)
+ {
+ char buf[10];
+ sprintf(buf, "r%d", regnum);
+ drcuml_symbol_add(sh2->drcuml, &sh2->r[regnum], sizeof(sh2->r[regnum]), buf);
+ }
+ drcuml_symbol_add(sh2->drcuml, &sh2->pr, sizeof(sh2->pr), "pr");
+ drcuml_symbol_add(sh2->drcuml, &sh2->sr, sizeof(sh2->sr), "sr");
+ drcuml_symbol_add(sh2->drcuml, &sh2->gbr, sizeof(sh2->gbr), "gbr");
+ drcuml_symbol_add(sh2->drcuml, &sh2->vbr, sizeof(sh2->vbr), "vbr");
+ drcuml_symbol_add(sh2->drcuml, &sh2->macl, sizeof(sh2->macl), "macl");
+ drcuml_symbol_add(sh2->drcuml, &sh2->mach, sizeof(sh2->macl), "mach");
+
+ /* initialize the front-end helper */
+ if (SINGLE_INSTRUCTION_MODE)
+ feconfig.max_sequence = 1;
+ sh2->drcfe = drcfe_init(&feconfig, sh2);
+
+ /* compute the register parameters */
+ for (regnum = 0; regnum < 16; regnum++)
+ {
+ sh2->regmap[regnum].type = DRCUML_PTYPE_MEMORY;
+ sh2->regmap[regnum].value = (FPTR)&sh2->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)
+ {
+ drcuml_get_backend_info(sh2->drcuml, &beinfo);
+ if (beinfo.direct_iregs > 4)
+ {
+ sh2->regmap[0].type = DRCUML_PTYPE_INT_REGISTER;
+ sh2->regmap[0].value = DRCUML_REG_I4;
+ }
+ if (beinfo.direct_iregs > 5)
+ {
+ sh2->regmap[1].type = DRCUML_PTYPE_INT_REGISTER;
+ sh2->regmap[1].value = DRCUML_REG_I5;
+ }
+ if (beinfo.direct_iregs > 6)
+ {
+ sh2->regmap[2].type = DRCUML_PTYPE_INT_REGISTER;
+ sh2->regmap[2].value = DRCUML_REG_I6;
+ }
+ }
+
+ /* mark the cache dirty so it is updated on next execute */
+ sh2->cache_dirty = TRUE;
+}
+
+/*-------------------------------------------------
+ sh2_reset - reset the processor
+-------------------------------------------------*/
+
+static void sh2_reset(void)
+{
+ void *tsave, *tsaved0, *tsaved1;
+ UINT32 *m;
+ int cpunum;
+
+ void (*f)(UINT32 data);
+ int (*save_irqcallback)(int);
+
+ cpunum = sh2->cpu_number;
+ m = sh2->m;
+ tsave = sh2->timer;
+ tsaved0 = sh2->dma_timer[0];
+ tsaved1 = sh2->dma_timer[1];
+
+ f = sh2->ftcsr_read_callback;
+ save_irqcallback = sh2->irq_callback;
+
+ sh2->ppc = sh2->pc = sh2->pr = sh2->sr = sh2->gbr = sh2->vbr = sh2->mach = sh2->macl = 0;
+ sh2->evec = sh2->irqsr = 0;
+ memset(&sh2->r[0], 0, sizeof(sh2->r[0])*16);
+ sh2->ea = sh2->delay = sh2->cpu_off = sh2->dvsr = sh2->dvdnth = sh2->dvdntl = sh2->dvcr = 0;
+ sh2->pending_irq = sh2->test_irq = 0;
+ memset(&sh2->irq_queue[0], 0, sizeof(sh2->irq_queue[0])*16);
+ memset(&sh2->irq_line_state[0], 0, sizeof(sh2->irq_line_state[0])*17);
+ sh2->frc = sh2->ocra = sh2->ocrb = sh2->icr = 0;
+ sh2->frc_base = 0;
+ sh2->frt_input = sh2->internal_irq_level = sh2->internal_irq_vector = 0;
+ sh2->dma_timer_active[0] = sh2->dma_timer_active[1] = 0;
+
+ sh2->ftcsr_read_callback = f;
+ sh2->irq_callback = save_irqcallback;
+
+ sh2->timer = tsave;
+ sh2->dma_timer[0] = tsaved0;
+ sh2->dma_timer[1] = tsaved1;
+ sh2->cpu_number = cpunum;
+ sh2->m = m;
+ memset(sh2->m, 0, 0x200);
+
+ sh2->pc = program_read_dword_32be(0);
+ sh2->r[15] = program_read_dword_32be(4);
+ sh2->sr = I;
+ change_pc(sh2->pc & AM);
+
+ sh2->internal_irq_level = -1;
+
+ sh2->cache_dirty = TRUE;
+}
+
+/*-------------------------------------------------
+ code_flush_cache - flush the cache and
+ regenerate static code
+-------------------------------------------------*/
+
+static void code_flush_cache(drcuml_state *drcuml)
+{
+ /* empty the transient cache contents */
+ drcuml_reset(drcuml);
+
+ /* generate the entry point and out-of-cycles handlers */
+ static_generate_nocode_handler(drcuml);
+ static_generate_out_of_cycles(drcuml);
+ static_generate_entry_point(drcuml);
+
+ /* add subroutines for memory accesses */
+ static_generate_memory_accessor(drcuml, 1, FALSE, "read8", &sh2->read8);
+ static_generate_memory_accessor(drcuml, 1, TRUE, "write8", &sh2->write8);
+ static_generate_memory_accessor(drcuml, 2, FALSE, "read16", &sh2->read16);
+ static_generate_memory_accessor(drcuml, 2, TRUE, "write16", &sh2->write16);
+ static_generate_memory_accessor(drcuml, 4, FALSE, "read32", &sh2->read32);
+ static_generate_memory_accessor(drcuml, 4, TRUE, "write32", &sh2->write32);
+
+ sh2->cache_dirty = FALSE;
+}
+
+/* Execute cycles - returns number of cycles actually run */
+static int sh2_execute(int cycles)
+{
+ drcuml_state *drcuml = sh2->drcuml;
+ int execute_result;
+
+ /* reset the cache if dirty */
+ if (sh2->cache_dirty)
+ code_flush_cache(drcuml);
+
+ /* execute */
+ sh2->icount = cycles;
+ do
+ {
+ /* run as much as we can */
+ execute_result = drcuml_execute(drcuml, sh2->entry);
+
+ /* if we need to recompile, do it */
+ if (execute_result == EXECUTE_MISSING_CODE)
+ {
+ code_compile_block(drcuml, 0, sh2->pc);
+ }
+ else if (execute_result == EXECUTE_UNMAPPED_CODE)
+ {
+ fatalerror("Attempted to execute unmapped code at PC=%08X\n", sh2->pc);
+ }
+ else if (execute_result == EXECUTE_RESET_CACHE)
+ {
+ code_flush_cache(drcuml);
+ }
+ } while (execute_result != EXECUTE_OUT_OF_CYCLES);
+
+ /* return the number of cycles executed */
+ return cycles - sh2->icount;
+}
+
+/*-------------------------------------------------
+ code_compile_block - compile a block of the
+ given mode at the specified pc
+-------------------------------------------------*/
+
+static void code_compile_block(drcuml_state *drcuml, UINT8 mode, offs_t pc)
+{
+ compiler_state compiler = { 0 };
+ const opcode_desc *seqhead, *seqlast;
+ const opcode_desc *desclist;
+ int override = FALSE;
+ drcuml_block *block;
+ jmp_buf errorbuf;
+
+ /* get a description of this sequence */
+ desclist = drcfe_describe_code(sh2->drcfe, pc);
+ if (LOG_UML || LOG_NATIVE)
+ log_opcode_desc(drcuml, desclist, 0);
+
+ /* if we get an error back, flush the cache and try again */
+ if (setjmp(errorbuf) != 0)
+ code_flush_cache(drcuml);
+
+ /* start the block */
+ block = drcuml_block_begin(drcuml, 4096, &errorbuf);
+
+ /* loop until we get through all instruction sequences */
+ for (seqhead = desclist; seqhead != NULL; seqhead = seqlast->next)
+ {
+ const opcode_desc *curdesc;
+ UINT32 nextpc;
+
+ /* add a code log entry */
+ if (LOG_UML)
+ UML_COMMENT(block, "-------------------------"); // comment
+
+ /* determine the last instruction in this sequence */
+ for (seqlast = seqhead; seqlast != NULL; seqlast = seqlast->next)
+ if (seqlast->flags & OPFLAG_END_SEQUENCE)
+ break;
+ assert(seqlast != NULL);
+
+ /* if we don't have a hash for this mode/pc, or if we are overriding all, add one */
+ if (override || !drcuml_hash_exists(drcuml, 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, IMM(0), IMM(seqhead->pc), sh2->nocode);
+ // hashjmp <mode>,seqhead->pc,nocode
+ continue;
+ }
+
+ /* validate this code block if we're not pointing into ROM */
+ if (memory_get_write_ptr(cpu_getactivecpu(), ADDRESS_SPACE_PROGRAM, seqhead->physpc) != NULL)
+ 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);
+ }
+
+ /* 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, IMM(nextpc), TRUE); // <subtract cycles>
+
+ /* SH2 has no modes */
+ if (seqlast->next == NULL || seqlast->next->pc != nextpc)
+ {
+ UML_HASHJMP(block, IMM(0), IMM(nextpc), sh2->nocode);
+ }
+ // hashjmp <mode>,nextpc,nocode
+ }
+
+ /* end the sequence */
+ drcuml_block_end(block);
+}
+
+/*-------------------------------------------------
+ static_generate_entry_point - generate a
+ static entry point
+-------------------------------------------------*/
+
+static void static_generate_entry_point(drcuml_state *drcuml)
+{
+ drcuml_codelabel skip = 1;
+ drcuml_block *block;
+ jmp_buf errorbuf;
+
+ /* if we get an error back, we're screwed */
+ if (setjmp(errorbuf) != 0)
+ fatalerror("Unrecoverable error in static_generate_entry_point");
+
+ /* begin generating */
+ block = drcuml_block_begin(drcuml, 200, &errorbuf);
+
+ /* forward references */
+ alloc_handle(drcuml, &sh2->nocode, "nocode");
+ alloc_handle(drcuml, &sh2->write32, "write32"); // necessary?
+ alloc_handle(drcuml, &sh2->entry, "entry");
+ UML_HANDLE(block, sh2->entry); // handle entry
+
+ /* load fast integer registers */
+ load_fast_iregs(block);
+
+ /* check for interrupts */
+ UML_CALLC(block, cfunc_checkirqs, NULL);
+
+ UML_MOV(block, IREG(0), MEM(&sh2->evec)); // mov r0, evec
+ UML_CMP(block, IREG(0), IMM(0xffffffff)); // cmp r0, 0xffffffff
+ UML_JMPc(block, IF_Z, skip); // jz skip
+
+ UML_SUB(block, R32(15), R32(15), IMM(4)); // sub R15, R15, #4
+ UML_MOV(block, IREG(0), R32(15)); // mov r0, R15
+ UML_MOV(block, IREG(1), MEM(&sh2->irqsr)); // mov r1, irqsr
+ UML_CALLH(block, sh2->write32); // call write32
+
+ UML_SUB(block, R32(15), R32(15), IMM(4)); // sub R15, R15, #4
+ UML_MOV(block, IREG(0), R32(15)); // mov r0, R15
+ UML_MOV(block, IREG(1), MEM(&sh2->pc)); // mov r1, pc
+ UML_CALLH(block, sh2->write32); // call write32
+
+ UML_MOV(block, MEM(&sh2->pc), MEM(&sh2->evec)); // mov pc, evec
+
+ UML_LABEL(block, skip); // skip:
+
+ /* generate a hash jump via the current mode and PC */
+ UML_HASHJMP(block, IMM(0), MEM(&sh2->pc), sh2->nocode); // hashjmp <mode>,<pc>,nocode
+
+ drcuml_block_end(block);
+}
+
+/*-------------------------------------------------
+ static_generate_nocode_handler - generate an
+ exception handler for "out of code"
+-------------------------------------------------*/
+
+static void static_generate_nocode_handler(drcuml_state *drcuml)
+{
+ drcuml_block *block;
+ jmp_buf errorbuf;
+
+ /* if we get an error back, we're screwed */
+ if (setjmp(errorbuf) != 0)
+ fatalerror("Unrecoverable error in static_generate_nocode_handler");
+
+ /* begin generating */
+ block = drcuml_block_begin(drcuml, 10, &errorbuf);
+
+ /* generate a hash jump via the current mode and PC */
+ alloc_handle(drcuml, &sh2->nocode, "nocode");
+ UML_HANDLE(block, sh2->nocode); // handle nocode
+ UML_GETEXP(block, IREG(0)); // getexp i0
+ UML_MOV(block, MEM(&sh2->pc), IREG(0)); // mov [pc],i0
+ save_fast_iregs(block);
+ UML_EXIT(block, IMM(EXECUTE_MISSING_CODE)); // exit EXECUTE_MISSING_CODE
+
+ drcuml_block_end(block);
+}
+
+
+/*-------------------------------------------------
+ static_generate_out_of_cycles - generate an
+ out of cycles exception handler
+-------------------------------------------------*/
+
+static void static_generate_out_of_cycles(drcuml_state *drcuml)
+{
+ drcuml_block *block;
+ jmp_buf errorbuf;
+
+ /* if we get an error back, we're screwed */
+ if (setjmp(errorbuf) != 0)
+ fatalerror("Unrecoverable error in static_generate_out_of_cycles");
+
+ /* begin generating */
+ block = drcuml_block_begin(drcuml, 10, &errorbuf);
+
+ /* generate a hash jump via the current mode and PC */
+ alloc_handle(drcuml, &sh2->out_of_cycles, "out_of_cycles");
+ UML_HANDLE(block, sh2->out_of_cycles); // handle out_of_cycles
+ UML_GETEXP(block, IREG(0)); // getexp i0
+ UML_MOV(block, MEM(&sh2->pc), IREG(0)); // mov <pc>,i0
+ save_fast_iregs(block);
+ UML_EXIT(block, IMM(EXECUTE_OUT_OF_CYCLES)); // exit EXECUTE_OUT_OF_CYCLES
+
+ drcuml_block_end(block);
+}
+
+/*------------------------------------------------------------------
+ static_generate_memory_accessor
+------------------------------------------------------------------*/
+
+static void static_generate_memory_accessor(drcuml_state *drcuml, int size, int iswrite, const char *name, drcuml_codehandle **handleptr)
+{
+ /* on entry, address is in I0; data for writes is in I1 */
+ /* on exit, read result is in I0 */
+ /* routine trashes I0 */
+ drcuml_block *block;
+ jmp_buf errorbuf;
+ int label = 1;
+
+ /* if we get an error back, we're screwed */
+ if (setjmp(errorbuf) != 0)
+ fatalerror("Unrecoverable error in static_generate_memory_accessor");
+
+ /* begin generating */
+ block = drcuml_block_begin(drcuml, 1024, &errorbuf);
+
+ /* 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, IREG(0), IMM(0x80000000)); // test r0, #0x80000000
+ UML_JMPc(block, IF_NZ, label+1); // if high bit is set, don't mask
+
+ UML_CMP(block, IREG(0), IMM(0x40000000)); // cmp #0x40000000, r0
+ UML_JMPc(block, IF_Z, label);
+ UML_JMPc(block, IF_GE, label+1); // bge label+1
+
+ UML_LABEL(block, label++); // label:
+
+ UML_AND(block, IREG(0), IREG(0), IMM(AM)); // and r0, r0, #AM (0xc7ffffff)
+
+ UML_LABEL(block, label++); // label:
+
+ if (iswrite)
+ {
+ switch (size)
+ {
+ case 1:
+ UML_WRITE(block, IREG(0), IREG(1), PROGRAM_BYTE); // write r0, r1, program_byte
+ break;
+
+ case 2:
+ UML_WRITE(block, IREG(0), IREG(1), PROGRAM_WORD); // write r0, r1, program_word
+ break;
+
+ case 4:
+ UML_WRITE(block, IREG(0), IREG(1), PROGRAM_DWORD); // write r0, r1, program_dword
+ break;
+ }
+ }
+ else
+ {
+ switch (size)
+ {
+ case 1:
+ UML_READ(block, IREG(0), IREG(0), PROGRAM_BYTE); // read r0, program_byte
+ break;
+
+ case 2:
+ UML_READ(block, IREG(0), IREG(0), PROGRAM_WORD); // read r0, program_word
+ break;
+
+ case 4:
+ UML_READ(block, IREG(0), IREG(0), PROGRAM_DWORD); // read r0, program_dword
+ break;
+ }
+ }
+
+ UML_RET(block); // ret
+
+ drcuml_block_end(block);
+}
+
+/*-------------------------------------------------
+ log_desc_flags_to_string - generate a string
+ representing the instruction description
+ flags
+-------------------------------------------------*/
+
+static const char *log_desc_flags_to_string(UINT32 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
+-------------------------------------------------*/
+
+static void log_register_list(drcuml_state *drcuml, const char *string, const UINT32 *reglist, const UINT32 *regnostarlist)
+{
+ int count = 0;
+ int regnum;
+
+ /* skip if nothing */
+ if (reglist[0] == 0 && reglist[1] == 0 && reglist[2] == 0)
+ return;
+
+ drcuml_log_printf(drcuml, "[%s:", string);
+
+ for (regnum = 0; regnum < 16; regnum++)
+ {
+ if (reglist[0] & REGFLAG_R(regnum))
+ {
+ drcuml_log_printf(drcuml, "%sr%d", (count++ == 0) ? "" : ",", regnum);
+ if (regnostarlist != NULL && !(regnostarlist[0] & REGFLAG_R(regnum)))
+ drcuml_log_printf(drcuml, "*");
+ }
+ }
+
+ if (reglist[1] & REGFLAG_PR)
+ {
+ drcuml_log_printf(drcuml, "%spr", (count++ == 0) ? "" : ",");
+ if (regnostarlist != NULL && !(regnostarlist[1] & REGFLAG_PR))
+ drcuml_log_printf(drcuml, "*");
+ }
+
+ if (reglist[1] & REGFLAG_SR)
+ {
+ drcuml_log_printf(drcuml, "%ssr", (count++ == 0) ? "" : ",");
+ if (regnostarlist != NULL && !(regnostarlist[1] & REGFLAG_SR))
+ drcuml_log_printf(drcuml, "*");
+ }
+
+ if (reglist[1] & REGFLAG_MACL)
+ {
+ drcuml_log_printf(drcuml, "%smacl", (count++ == 0) ? "" : ",");
+ if (regnostarlist != NULL && !(regnostarlist[1] & REGFLAG_MACL))
+ drcuml_log_printf(drcuml, "*");
+ }
+
+ if (reglist[1] & REGFLAG_MACH)
+ {
+ drcuml_log_printf(drcuml, "%smach", (count++ == 0) ? "" : ",");
+ if (regnostarlist != NULL && !(regnostarlist[1] & REGFLAG_MACH))
+ drcuml_log_printf(drcuml, "*");
+ }
+
+ if (reglist[1] & REGFLAG_GBR)
+ {
+ drcuml_log_printf(drcuml, "%sgbr", (count++ == 0) ? "" : ",");
+ if (regnostarlist != NULL && !(regnostarlist[1] & REGFLAG_GBR))
+ drcuml_log_printf(drcuml, "*");
+ }
+
+ if (reglist[1] & REGFLAG_VBR)
+ {
+ drcuml_log_printf(drcuml, "%svbr", (count++ == 0) ? "" : ",");
+ if (regnostarlist != NULL && !(regnostarlist[1] & REGFLAG_VBR))
+ drcuml_log_printf(drcuml, "*");
+ }
+
+ drcuml_log_printf(drcuml, "] ");
+}
+
+/*-------------------------------------------------
+ log_opcode_desc - log a list of descriptions
+-------------------------------------------------*/
+
+static void 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(drcuml, "\nDescriptor list @ %08X\n", desclist->pc);
+
+ /* output each descriptor */
+ for ( ; desclist != NULL; desclist = desclist->next)
+ {
+ char buffer[100];
+
+ /* disassemle the current instruction and output it to the log */
+#if (LOG_UML || LOG_NATIVE)
+ if (desclist->flags & OPFLAG_VIRTUAL_NOOP)
+ strcpy(buffer, "<virtual nop>");
+ else
+ DasmSH2(buffer, desclist->pc, *desclist->opptr.w);
+#else
+ strcpy(buffer, "???");
+#endif
+ drcuml_log_printf(drcuml, "%08X [%08X] t:%08X f:%s: %-30s", desclist->pc, desclist->physpc, desclist->targetpc, log_desc_flags_to_string(desclist->flags), buffer);
+
+ /* output register states */
+ log_register_list(drcuml, "use", desclist->regin, NULL);
+ log_register_list(drcuml, "mod", desclist->regout, desclist->regreq);
+ drcuml_log_printf(drcuml, "\n");
+
+ /* if we have a delay slot, output it recursively */
+ if (desclist->delay != NULL)
+ log_opcode_desc(drcuml, desclist->delay, indent + 1);
+
+ /* at the end of a sequence add a dividing line */
+ if (desclist->flags & OPFLAG_END_SEQUENCE)
+ drcuml_log_printf(drcuml, "-----\n");
+ }
+}
+
+/*-------------------------------------------------
+ log_add_disasm_comment - add a comment
+ including disassembly of a MIPS instruction
+-------------------------------------------------*/
+
+static void log_add_disasm_comment(drcuml_block *block, UINT32 pc, UINT32 op)
+{
+#if (LOG_UML)
+ char buffer[100];
+ DasmSH2(buffer, pc, op);
+ UML_COMMENT(block, "%08X: %s", pc, buffer); // comment
+#endif
+}
+
+/*-------------------------------------------------
+ generate_update_cycles - generate code to
+ subtract cycles from the icount and generate
+ an exception if out
+-------------------------------------------------*/
+static void generate_update_cycles(drcuml_block *block, compiler_state *compiler, drcuml_ptype ptype, UINT64 pvalue, int allow_exception)
+{
+ /* check full interrupts if pending */
+ if (compiler->checkints)
+ {
+ drcuml_codelabel skip = compiler->labelnum++;
+
+ compiler->checkints = FALSE;
+
+ /* check for interrupts */
+ UML_CALLC(block, cfunc_checkirqs, NULL);
+
+ UML_MOV(block, IREG(0), MEM(&sh2->evec)); // mov r0, evec
+ UML_CMP(block, IREG(0), IMM(0xffffffff)); // cmp r0, 0xffffffff
+ UML_JMPc(block, IF_Z, skip); // jz skip
+
+ UML_SUB(block, R32(15), R32(15), IMM(4)); // sub R15, R15, #4
+ UML_MOV(block, IREG(0), R32(15)); // mov r0, R15
+ UML_MOV(block, IREG(1), MEM(&sh2->irqsr)); // mov r1, irqsr
+ UML_CALLH(block, sh2->write32); // call write32
+
+ UML_SUB(block, R32(15), R32(15), IMM(4)); // sub R15, R15, #4
+ UML_MOV(block, IREG(0), R32(15)); // mov r0, R15
+ UML_MOV(block, IREG(1), PARAM(ptype, pvalue)); // mov r1, nextpc
+ UML_CALLH(block, sh2->write32); // call write32
+
+ UML_HASHJMP(block, IMM(0), MEM(&sh2->evec), sh2->nocode); // hashjmp sh2->evec
+
+ UML_LABEL(block, skip); // skip:
+ }
+
+ /* account for cycles */
+ if (compiler->cycles > 0)
+ {
+ UML_SUB(block, MEM(&sh2->icount), MEM(&sh2->icount), MAPVAR_CYCLES); // sub icount,icount,cycles
+ UML_MAPVAR(block, MAPVAR_CYCLES, 0); // mapvar cycles,0
+ if (allow_exception)
+ UML_EXHc(block, IF_S, sh2->out_of_cycles, PARAM(ptype, pvalue));
+ // exh out_of_cycles,nextpc
+ }
+ compiler->cycles = 0;
+}
+
+/*-------------------------------------------------
+ generate_checksum_block - generate code to
+ validate a sequence of opcodes
+-------------------------------------------------*/
+
+static void generate_checksum_block(drcuml_block *block, compiler_state *compiler, const opcode_desc *seqhead, const opcode_desc *seqlast)
+{
+ const opcode_desc *curdesc;
+ if (LOG_UML)
+ UML_COMMENT(block, "[Validation for %08X]", seqhead->pc); // comment
+
+ /* loose verify or single instruction: just compare and fail */
+ if (!(sh2->drcoptions & SH2DRC_STRICT_VERIFY) || seqhead->next == NULL)
+ {
+ if (!(seqhead->flags & OPFLAG_VIRTUAL_NOOP))
+ {
+ UML_LOAD(block, IREG(0), seqhead->opptr.l, IMM(0), DWORD); // load i0,*opptr,0,dword
+ UML_CMP(block, IREG(0), IMM(*seqhead->opptr.l)); // cmp i0,*opptr
+ UML_EXHc(block, IF_NE, sh2->nocode, IMM(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))
+ {
+ UML_LOAD(block, IREG(0), curdesc->opptr.w, IMM(0), WORD); // load i0,*opptr,0,word
+ UML_CMP(block, IREG(0), IMM(*curdesc->opptr.w)); // cmp i0,*opptr
+ UML_EXHc(block, IF_NE, sh2->nocode, IMM(epc(seqhead))); // exne nocode,seqhead->pc
+ }
+#else
+ UINT32 sum = 0;
+ UML_LOAD(block, IREG(0), seqhead->opptr.l, IMM(0), DWORD); // load i0,*opptr,0,dword
+ sum += *seqhead->opptr.l;
+ for (curdesc = seqhead->next; curdesc != seqlast->next; curdesc = curdesc->next)
+ if (!(curdesc->flags & OPFLAG_VIRTUAL_NOOP))
+ {
+ UML_LOAD(block, IREG(1), curdesc->opptr.l, IMM(0), DWORD); // load i1,*opptr,dword
+ UML_ADD(block, IREG(0), IREG(0), IREG(1)); // add i0,i0,i1
+ sum += *curdesc->opptr.l;
+ }
+ UML_CMP(block, IREG(0), IMM(sum)); // cmp i0,sum
+ UML_EXHc(block, IF_NE, sh2->nocode, IMM(epc(seqhead))); // exne nocode,seqhead->pc
+#endif
+ }
+}
+
+
+/*-------------------------------------------------
+ generate_sequence_instruction - generate code
+ for a single instruction in a sequence
+-------------------------------------------------*/
+
+static void generate_sequence_instruction(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc)
+{
+ offs_t expc;
+
+ /* add an entry for the log */
+ if (LOG_UML && !(desc->flags & OPFLAG_VIRTUAL_NOOP))
+ log_add_disasm_comment(block, desc->pc, *desc->opptr.l);
+
+ /* 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_CALLC(block, cfunc_printf_probe, desc->pc); // callc cfunc_printf_probe,desc->pc
+
+ /* if we are debugging, call the debugger */
+ if ((Machine->debug_flags & DEBUG_FLAG_ENABLED) != 0)
+ {
+ UML_MOV(block, MEM(&sh2->pc), IMM(desc->pc)); // mov [pc],desc->pc
+ save_fast_iregs(block);
+ UML_DEBUG(block, IMM(desc->pc)); // debug desc->pc
+ }
+ else // not debug, see what other reasons there are for flushing the PC
+ {
+ if (sh2->drcoptions & SH2DRC_FLUSH_PC) // always flush?
+ {
+ UML_MOV(block, MEM(&sh2->pc), IMM(desc->pc)); // mov sh2->pc, desc->pc
+ }
+ else // check for driver-selected flushes
+ {
+ if (sh2->maxpcfsel != -1)
+ {
+ int pcflush;
+
+ for (pcflush = 0; pcflush <= sh2->maxpcfsel; pcflush++)
+ {
+ if (desc->pc == sh2->pcflushes[pcflush])
+ {
+ UML_MOV(block, MEM(&sh2->pc), IMM(desc->pc)); // mov sh2->pc, desc->pc
+ }
+ }
+ }
+ }
+ }
+
+
+ /* if we hit an unmapped address, fatal error */
+ if (desc->flags & OPFLAG_COMPILER_UNMAPPED)
+ {
+ UML_MOV(block, MEM(&sh2->pc), IMM(desc->pc)); // mov [pc],desc->pc
+ save_fast_iregs(block);
+ UML_EXIT(block, IMM(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))
+ {
+ UML_MOV(block, MEM(&sh2->pc), IMM(desc->pc)); // mov [pc],desc->pc
+ UML_CALLC(block, cfunc_unimplemented, (void *)(FPTR)*desc->opptr.w); // callc cfunc_unimplemented
+ }
+ }
+}
+
+/*------------------------------------------------------------------
+ generate_delay_slot
+------------------------------------------------------------------*/
+
+static void generate_delay_slot(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc)
+{
+ compiler_state compiler_temp = *compiler;
+
+ /* compile the delay slot using temporary compiler state */
+ assert(desc->delay != NULL);
+ generate_sequence_instruction(block, &compiler_temp, desc->delay); // <next instruction>
+
+ /* update the label */
+ compiler->labelnum = compiler_temp.labelnum;
+}
+
+/*-------------------------------------------------
+ generate_opcode - generate code for a specific
+ opcode
+-------------------------------------------------*/
+
+static int generate_opcode(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc)
+{
+ UINT32 scratch, scratch2;
+ INT32 disp;
+ UINT16 opcode = *desc->opptr.w;
+ UINT8 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);
+ break;
+
+ case 1: // MOVLS4
+ scratch = (opcode & 0x0f) * 4;
+ UML_ADD(block, IREG(0), R32(Rn), IMM(scratch)); // add r0, Rn, scratch
+ UML_MOV(block, IREG(1), R32(Rm)); // mov r1, Rm
+ SETEA(0); // set ea for debug
+ UML_CALLH(block, sh2->write32);
+
+ if (!in_delay_slot)
+ generate_update_cycles(block, compiler, IMM(desc->pc + 2), TRUE);
+ return TRUE;
+ break;
+
+ case 2:
+ return generate_group_2(block, compiler, desc, opcode, in_delay_slot);
+ break;
+ case 3:
+ return generate_group_3(block, compiler, desc, opcode);
+ break;
+ case 4:
+ return generate_group_4(block, compiler, desc, opcode, in_delay_slot);
+ break;
+
+ case 5: // MOVLL4
+ scratch = (opcode & 0x0f) * 4;
+ UML_ADD(block, IREG(0), R32(Rm), IMM(scratch)); // add r0, Rm, scratch
+ SETEA(0); // set ea for debug
+ UML_CALLH(block, sh2->read32); // call read32
+ UML_MOV(block, R32(Rn), IREG(0)); // mov Rn, r0
+
+ if (!in_delay_slot)
+ generate_update_cycles(block, compiler, IMM(desc->pc + 2), TRUE);
+ return TRUE;
+ break;
+
+ case 6:
+ return generate_group_6(block, compiler, desc, opcode, in_delay_slot);
+ break;
+
+ case 7: // ADDI
+ scratch = opcode & 0xff;
+ scratch2 = (UINT32)(INT32)(INT16)(INT8)scratch;
+ UML_ADD(block, R32(Rn), R32(Rn), IMM(scratch2)); // add Rn, Rn, scratch2
+ return TRUE;
+ break;
+
+ case 8:
+ return generate_group_8(block, compiler, desc, opcode, in_delay_slot);
+ break;
+
+ case 9: // MOVWI
+ scratch = (desc->pc + 2) + ((opcode & 0xff) * 2) + 2;
+ UML_MOV(block, IREG(0), IMM(scratch)); // mov r0, scratch
+ SETEA(0); // set ea for debug
+ UML_CALLH(block, sh2->read16); // read16(r0, r1)
+ UML_SEXT(block, R32(Rn), IREG(0), WORD); // sext Rn, r0, WORD
+
+ if (!in_delay_slot)
+ generate_update_cycles(block, compiler, IMM(desc->pc + 2), TRUE);
+ return TRUE;
+ break;
+
+ case 10: // BRA
+ generate_delay_slot(block, compiler, desc);
+
+ disp = ((INT32)opcode << 20) >> 20;
+
+ sh2->ea = (desc->pc + 2) + disp * 2 + 2; // sh2->ea = pc+4 + disp*2 + 2
+
+ generate_update_cycles(block, compiler, IMM(sh2->ea), TRUE); // <subtract cycles>
+ UML_HASHJMP(block, IMM(0), IMM(sh2->ea), sh2->nocode); // hashjmp sh2->ea
+ return TRUE;
+ break;
+
+ case 11: // BSR
+ generate_delay_slot(block, compiler, desc);
+
+ disp = ((INT32)opcode << 20) >> 20;
+
+ UML_ADD(block, MEM(&sh2->pr), IMM(desc->pc), IMM(4)); // add sh2->pr, desc->pc, #4 (skip the current insn & delay slot)
+
+ sh2->ea = (desc->pc + 2) + disp * 2 + 2; // sh2->ea = pc+4 + disp*2 + 2
+ generate_update_cycles(block, compiler, IMM(sh2->ea), TRUE); // <subtract cycles>
+ UML_HASHJMP(block, IMM(0), IMM(sh2->ea), sh2->nocode); // hashjmp sh2->ea
+ return TRUE;
+ break;
+
+ case 12:
+ return generate_group_12(block, compiler, desc, opcode, in_delay_slot);
+ break;
+
+ case 13: // MOVLI
+ scratch = ((desc->pc + 4) & ~3) + ((opcode & 0xff) * 4);
+ UML_MOV(block, IREG(0), IMM(scratch)); // mov r0, scratch
+ UML_CALLH(block, sh2->read32); // read32(r0, r1)
+ UML_MOV(block, R32(Rn), IREG(0)); // mov Rn, r0
+
+ if (!in_delay_slot)
+ generate_update_cycles(block, compiler, IMM(desc->pc + 2), TRUE);
+ return TRUE;
+ break;
+
+ case 14: // MOVI
+ scratch = opcode & 0xff;
+ scratch2 = (UINT32)(INT32)(INT16)(INT8)scratch;
+ UML_MOV(block, R32(Rn), IMM(scratch2));
+ return TRUE;
+ break;
+
+ case 15: // NOP
+ return TRUE;
+ break;
+ }
+
+ return FALSE;
+}
+
+static int generate_group_0(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, UINT16 opcode, int in_delay_slot)
+{
+ 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;
+ break;
+
+ case 0x02: // STCSR(Rn);
+ UML_MOV(block, R32(Rn), MEM(&sh2->sr));
+ return TRUE;
+ break;
+
+ case 0x03: // BSRF(Rn);
+ UML_ADD(block, MEM(&sh2->target), R32(Rn), IMM(4)); // add target, Rm, #4
+ UML_ADD(block, MEM(&sh2->target), MEM(&sh2->target), IMM(desc->pc)); // add target, target, pc
+
+ generate_delay_slot(block, compiler, desc);
+
+ UML_ADD(block, MEM(&sh2->pr), IMM(desc->pc), IMM(4)); // add sh2->pr, desc->pc, #4 (skip the current insn & delay slot)
+
+ generate_update_cycles(block, compiler, MEM(&sh2->target), TRUE); // <subtract cycles>
+ UML_HASHJMP(block, IMM(0), MEM(&sh2->target), sh2->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, IREG(0), R32(0), R32(Rn)); // add r0, R0, Rn
+ UML_MOV(block, IREG(1), R32(Rm)); // mov r1, Rm
+ UML_AND(block, IREG(1), IREG(1), IMM(0x000000ff)); // and r1, r1, 0xff
+ UML_CALLH(block, sh2->write8); // call write8
+
+ if (!in_delay_slot)
+ generate_update_cycles(block, compiler, IMM(desc->pc + 2), TRUE);
+ return TRUE;
+ break;
+
+ case 0x05: // MOVWS0(Rm, Rn);
+ case 0x15: // MOVWS0(Rm, Rn);
+ case 0x25: // MOVWS0(Rm, Rn);
+ case 0x35: // MOVWS0(Rm, Rn);
+ UML_ADD(block, IREG(0), R32(0), R32(Rn)); // add r0, R0, Rn
+ UML_MOV(block, IREG(1), R32(Rm)); // mov r1, Rm
+ UML_AND(block, IREG(1), IREG(1), IMM(0x0000ffff)); // and r1, r1, 0xffff
+ UML_CALLH(block, sh2->write16); // call write16
+
+ if (!in_delay_slot)
+ generate_update_cycles(block, compiler, IMM(desc->pc + 2), TRUE);
+ return TRUE;
+ break;
+
+ case 0x06: // MOVLS0(Rm, Rn);
+ case 0x16: // MOVLS0(Rm, Rn);
+ case 0x26: // MOVLS0(Rm, Rn);
+ case 0x36: // MOVLS0(Rm, Rn);
+ UML_ADD(block, IREG(0), R32(0), R32(Rn)); // add r0, R0, Rn
+ UML_MOV(block, IREG(1), R32(Rm)); // mov r1, Rm
+ UML_CALLH(block, sh2->write32); // call write32
+
+ if (!in_delay_slot)
+ generate_update_cycles(block, compiler, IMM(desc->pc + 2), TRUE);
+ return TRUE;
+ break;
+
+ case 0x07: // MULL(Rm, Rn);
+ case 0x17: // MULL(Rm, Rn);
+ case 0x27: // MULL(Rm, Rn);
+ case 0x37: // MULL(Rm, Rn);
+ UML_MULU(block, MEM(&sh2->macl), MEM(&sh2->ea), R32(Rn), R32(Rm)); // mulu macl, ea, Rn, Rm
+ return TRUE;
+ break;
+
+ case 0x08: // CLRT();
+ UML_AND(block, MEM(&sh2->sr), MEM(&sh2->sr), IMM(~T)); // and r0, sr, ~T (clear the T bit)
+ return TRUE;
+ break;
+
+ case 0x0a: // STSMACH(Rn);
+ UML_MOV(block, R32(Rn), MEM(&sh2->mach)); // mov Rn, mach
+ return TRUE;
+ break;
+
+ case 0x0b: // RTS();
+ UML_MOV(block, MEM(&sh2->target), MEM(&sh2->pr)); // mov target, pr (in case of d-slot shenanigans)
+
+ generate_delay_slot(block, compiler, desc);
+
+ generate_update_cycles(block, compiler, MEM(&sh2->target), TRUE); // <subtract cycles>
+ UML_HASHJMP(block, IMM(0), MEM(&sh2->target), sh2->nocode);
+ return TRUE;
+ break;
+
+ case 0x0c: // MOVBL0(Rm, Rn);
+ case 0x1c: // MOVBL0(Rm, Rn);
+ case 0x2c: // MOVBL0(Rm, Rn);
+ case 0x3c: // MOVBL0(Rm, Rn);
+ UML_ADD(block, IREG(0), R32(0), R32(Rm)); // add r0, R0, Rm
+ UML_CALLH(block, sh2->read8); // call read8
+ UML_SEXT(block, R32(Rn), IREG(0), BYTE); // sext Rn, r0, BYTE
+
+ if (!in_delay_slot)
+ generate_update_cycles(block, compiler, IMM(desc->pc + 2), TRUE);
+ return TRUE;
+ break;
+
+ case 0x0d: // MOVWL0(Rm, Rn);
+ case 0x1d: // MOVWL0(Rm, Rn);
+ case 0x2d: // MOVWL0(Rm, Rn);
+ case 0x3d: // MOVWL0(Rm, Rn);
+ UML_ADD(block, IREG(0), R32(0), R32(Rm)); // add r0, R0, Rm
+ UML_CALLH(block, sh2->read16); // call read16
+ UML_SEXT(block, R32(Rn), IREG(0), WORD); // sext Rn, r0, WORD
+
+ if (!in_delay_slot)
+ generate_update_cycles(block, compiler, IMM(desc->pc + 2), TRUE);
+ return TRUE;
+ break;
+
+ case 0x0e: // MOVLL0(Rm, Rn);
+ case 0x1e: // MOVLL0(Rm, Rn);
+ case 0x2e: // MOVLL0(Rm, Rn);
+ case 0x3e: // MOVLL0(Rm, Rn);
+ UML_ADD(block, IREG(0), R32(0), R32(Rm)); // add r0, R0, Rm
+ UML_CALLH(block, sh2->read32); // call read32
+ UML_MOV(block, R32(Rn), IREG(0)); // mov Rn, r0
+
+ if (!in_delay_slot)
+ generate_update_cycles(block, compiler, IMM(desc->pc + 2), TRUE);
+ return TRUE;
+ break;
+
+ case 0x0f: // MAC_L(Rm, Rn);
+ case 0x1f: // MAC_L(Rm, Rn);
+ case 0x2f: // MAC_L(Rm, Rn);
+ case 0x3f: // MAC_L(Rm, Rn);
+ save_fast_iregs(block);
+ UML_CALLC(block, cfunc_MAC_L, desc->opptr.w);
+ load_fast_iregs(block);
+ return TRUE;
+ break;
+
+ case 0x12: // STCGBR(Rn);
+ UML_MOV(block, R32(Rn), MEM(&sh2->gbr)); // mov Rn, gbr
+ return TRUE;
+ break;
+
+ case 0x18: // SETT();
+ UML_OR(block, MEM(&sh2->sr), MEM(&sh2->sr), IMM(T)); // or sr, sr, T
+ return TRUE;
+ break;
+
+ case 0x19: // DIV0U();
+ UML_AND(block, MEM(&sh2->sr), MEM(&sh2->sr), IMM(~(M|Q|T))); // and sr, sr, ~(M|Q|T)
+ return TRUE;
+ break;
+
+ case 0x1a: // STSMACL(Rn);
+ UML_MOV(block, R32(Rn), MEM(&sh2->macl)); // mov Rn, macl
+ return TRUE;
+ break;
+
+ case 0x1b: // SLEEP();
+ // inlined special version of generate_update_cycles here
+ // if an interrupt is taken, the return address is set to the next instruction
+ UML_CALLC(block, cfunc_checkirqs, NULL);
+
+ UML_MOV(block, IREG(0), MEM(&sh2->evec)); // mov r0, evec
+ UML_CMP(block, IREG(0), IMM(0xffffffff)); // cmp r0, 0xffffffff
+ UML_JMPc(block, IF_Z, compiler->labelnum); // jz skip
+
+ UML_SUB(block, R32(15), R32(15), IMM(4)); // sub R15, R15, #4
+ UML_MOV(block, IREG(0), R32(15)); // mov r0, R15
+ UML_MOV(block, IREG(1), MEM(&sh2->irqsr)); // mov r1, irqsr
+ UML_CALLH(block, sh2->write32); // call write32
+
+ UML_SUB(block, R32(15), R32(15), IMM(4)); // sub R15, R15, #4
+ UML_MOV(block, IREG(0), R32(15)); // mov r0, R15
+ UML_MOV(block, IREG(1), IMM(desc->pc+2)); // mov r1, nextpc
+ UML_CALLH(block, sh2->write32); // call write32
+
+ UML_HASHJMP(block, IMM(0), MEM(&sh2->evec), sh2->nocode); // hashjmp sh2->evec
+
+ UML_LABEL(block, compiler->labelnum++); // skip:
+
+ // now go "out of cycles"
+ if (compiler->cycles > 0)
+ {
+ UML_MOV(block, MEM(&sh2->icount), IMM(0)); // mov icount, #0
+ UML_MAPVAR(block, MAPVAR_CYCLES, 0); // mapvar cycles,0
+ UML_EXH(block, sh2->out_of_cycles, IMM(desc->pc)); // go out of cycles
+ }
+ else
+ {
+ UML_HASHJMP(block, IMM(0), IMM(desc->pc), sh2->nocode);
+ }
+
+ return TRUE;
+ break;
+
+ case 0x22: // STCVBR(Rn);
+ UML_MOV(block, R32(Rn), MEM(&sh2->vbr)); // mov Rn, vbr
+ return TRUE;
+ break;
+
+ case 0x23: // BRAF(Rn); 0x40 + 9054 = 9098
+ UML_ADD(block, MEM(&sh2->target), R32(Rn), IMM(desc->pc+4)); // add target, Rn, pc+4
+
+ generate_delay_slot(block, compiler, desc);
+
+ generate_update_cycles(block, compiler, MEM(&sh2->target), TRUE); // <subtract cycles>
+ UML_HASHJMP(block, IMM(0), MEM(&sh2->target), sh2->nocode); // jmp target
+ break;
+
+ case 0x28: // CLRMAC();
+ UML_MOV(block, MEM(&sh2->macl), IMM(0)); // mov macl, #0
+ UML_MOV(block, MEM(&sh2->mach), IMM(0)); // mov mach, #0
+ return TRUE;
+ break;
+
+ case 0x29: // MOVT(Rn);
+ UML_AND(block, R32(Rn), MEM(&sh2->sr), IMM(T)); // and Rn, sr, T
+ return TRUE;
+ break;
+
+ case 0x2a: // STSPR(Rn);
+ UML_MOV(block, R32(Rn), MEM(&sh2->pr)); // mov Rn, pr
+ return TRUE;
+ break;
+
+ case 0x2b: // RTE();
+ generate_delay_slot(block, compiler, desc);
+
+ UML_MOV(block, IREG(0), R32(15)); // mov r0, R15
+ UML_CALLH(block, sh2->read32); // call read32
+ UML_MOV(block, MEM(&sh2->pc), IREG(0)); // mov pc, r0
+ UML_ADD(block, R32(15), R32(15), IMM(4)); // add R15, R15, #4
+
+ UML_MOV(block, IREG(0), R32(15)); // mov r0, R15
+ UML_CALLH(block, sh2->read32); // call read32
+ UML_MOV(block, MEM(&sh2->sr), IREG(0)); // mov sr, r0
+ UML_ADD(block, R32(15), R32(15), IMM(4)); // add R15, R15, #4
+
+ compiler->checkints = TRUE;
+ UML_MOV(block, MEM(&sh2->ea), MEM(&sh2->pc)); // mov ea, pc
+ generate_update_cycles(block, compiler, MEM(&sh2->ea), TRUE); // <subtract cycles>
+ UML_HASHJMP(block, IMM(0), MEM(&sh2->pc), sh2->nocode); // and jump to the "resume PC"
+
+ return TRUE;
+ break;
+ }
+
+ return FALSE;
+}
+
+static int generate_group_2(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, UINT16 opcode, int in_delay_slot)
+{
+ switch (opcode & 15)
+ {
+ case 0: // MOVBS(Rm, Rn);
+ UML_MOV(block, IREG(0), R32(Rn)); // mov r0, Rn
+ UML_MOV(block, IREG(1), R32(Rm)); // mov r1, Rm
+ UML_AND(block, IREG(1), IREG(1), IMM(0xff)); // and r1, r1, 0xff
+ UML_CALLH(block, sh2->write8);
+
+ if (!in_delay_slot)
+ generate_update_cycles(block, compiler, IMM(desc->pc + 2), TRUE);
+ return TRUE;
+ break;
+
+ case 1: // MOVWS(Rm, Rn);
+ UML_MOV(block, IREG(0), R32(Rn)); // mov r0, Rn
+ UML_MOV(block, IREG(1), R32(Rm)); // mov r1, Rm
+ UML_AND(block, IREG(1), IREG(1), IMM(0xffff)); // and r1, r1, 0xffff
+ UML_CALLH(block, sh2->write16);
+
+ if (!in_delay_slot)
+ generate_update_cycles(block, compiler, IMM(desc->pc + 2), TRUE);
+ return TRUE;
+ break;
+
+ case 2: // MOVLS(Rm, Rn);
+ UML_MOV(block, IREG(0), R32(Rn)); // mov r0, Rn
+ UML_MOV(block, IREG(1), R32(Rm)); // mov r1, Rm
+ UML_CALLH(block, sh2->write32);
+
+ if (!in_delay_slot)
+ generate_update_cycles(block, compiler, IMM(desc->pc + 2), TRUE);
+ return TRUE;
+ break;
+
+ case 3: // NOP();
+ return TRUE;
+ break;
+
+ case 4: // MOVBM(Rm, Rn);
+ UML_MOV(block, IREG(1), R32(Rm)); // mov r1, Rm
+ UML_SUB(block, R32(Rn), R32(Rn), IMM(1)); // sub Rn, Rn, 1
+ UML_MOV(block, IREG(0), R32(Rn)); // mov r0, Rn
+ UML_CALLH(block, sh2->write8); // call write8
+
+ if (!in_delay_slot)
+ generate_update_cycles(block, compiler, IMM(desc->pc + 2), TRUE);
+ return TRUE;
+ break;
+
+ case 5: // MOVWM(Rm, Rn);
+ UML_MOV(block, IREG(1), R32(Rm)); // mov r1, Rm
+ UML_SUB(block, R32(Rn), R32(Rn), IMM(2)); // sub Rn, Rn, 2
+ UML_MOV(block, IREG(0), R32(Rn)); // mov r0, Rn
+ UML_CALLH(block, sh2->write16); // call write16
+
+ if (!in_delay_slot)
+ generate_update_cycles(block, compiler, IMM(desc->pc + 2), TRUE);
+ return TRUE;
+ break;
+
+ case 6: // MOVLM(Rm, Rn);
+ UML_MOV(block, IREG(1), R32(Rm)); // mov r1, Rm
+ UML_SUB(block, R32(Rn), R32(Rn), IMM(4)); // sub Rn, Rn, 4
+ UML_MOV(block, IREG(0), R32(Rn)); // mov r0, Rn
+ UML_CALLH(block, sh2->write32); // call write32
+
+ if (!in_delay_slot)
+ generate_update_cycles(block, compiler, IMM(desc->pc + 2), TRUE);
+ return TRUE;
+ break;
+
+ case 13: // XTRCT(Rm, Rn);
+ UML_SHL(block, IREG(0), R32(Rm), IMM(16)); // shl r0, Rm, #16
+ UML_AND(block, IREG(0), IREG(0), IMM(0xffff0000)); // and r0, r0, #0xffff0000
+
+ UML_SHR(block, IREG(1), R32(Rn), IMM(16)); // shr, r1, Rn, #16
+ UML_AND(block, IREG(1), IREG(1), IMM(0xffff)); // and r1, r1, #0x0000ffff
+
+ UML_OR(block, R32(Rn), IREG(0), IREG(1)); // or Rn, r0, r1
+ return TRUE;
+ break;
+
+ case 7: // DIV0S(Rm, Rn);
+ UML_MOV(block, IREG(0), MEM(&sh2->sr)); // move r0, sr
+ UML_AND(block, IREG(0), IREG(0), IMM(~(Q|M|T))); // and r0, r0, ~(Q|M|T) (clear the Q,M, and T bits)
+
+ UML_TEST(block, R32(Rn), IMM(0x80000000)); // test Rn, #0x80000000
+ UML_JMPc(block, IF_Z, compiler->labelnum); // jz labelnum
+
+ UML_OR(block, IREG(0), IREG(0), IMM(Q)); // or r0, r0, Q
+ UML_LABEL(block, compiler->labelnum++); // labelnum:
+
+ UML_TEST(block, R32(Rm), IMM(0x80000000)); // test Rm, #0x80000000
+ UML_JMPc(block, IF_Z, compiler->labelnum); // jz labelnum
+
+ UML_OR(block, IREG(0), IREG(0), IMM(M)); // or r0, r0, M
+ UML_LABEL(block, compiler->labelnum++); // labelnum:
+
+ UML_XOR(block, IREG(1), R32(Rn), R32(Rm)); // xor r1, Rn, Rm
+ UML_TEST(block, IREG(1), IMM(0x80000000)); // test r1, #0x80000000
+ UML_JMPc(block, IF_Z, compiler->labelnum); // jz labelnum
+
+ UML_OR(block, IREG(0), IREG(0), IMM(T)); // or r0, r0, T
+ UML_LABEL(block, compiler->labelnum++); // labelnum:
+ UML_MOV(block, MEM(&sh2->sr), IREG(0)); // mov sr, r0
+ return TRUE;
+ break;
+
+ case 8: // TST(Rm, Rn);
+ UML_AND(block, IREG(0), MEM(&sh2->sr), IMM(~T)); // and r0, sr, ~T (clear the T bit)
+ UML_TEST(block, R32(Rm), R32(Rn)); // test Rm, Rn
+ UML_JMPc(block, IF_NZ, compiler->labelnum); // jnz compiler->labelnum
+
+ UML_OR(block, IREG(0), IREG(0), IMM(T)); // or r0, r0, T
+ UML_LABEL(block, compiler->labelnum++); // desc->pc:
+
+ UML_MOV(block, MEM(&sh2->sr), IREG(0)); // mov sh2->sr, r0
+ return TRUE;
+ break;
+
+ case 12: // CMPSTR(Rm, Rn);
+ UML_XOR(block, IREG(0), R32(Rn), R32(Rm)); // xor r0, Rn, Rm (temp)
+
+ UML_SHR(block, IREG(1), IREG(0), IMM(24)); // shr r1, r0, #24 (HH)
+ UML_AND(block, IREG(1), IREG(1), IMM(0xff)); // and r1, r1, #0xff
+
+ UML_SHR(block, IREG(2), IREG(0), IMM(16)); // shr r2, r0, #16 (HL)
+ UML_AND(block, IREG(2), IREG(2), IMM(0xff)); // and r2, r2, #0xff
+
+ UML_SHR(block, IREG(3), IREG(0), IMM(8)); // shr r3, r0, #8 (LH)
+ UML_AND(block, IREG(3), IREG(3), IMM(0xff)); // and r3, r3, #0xff
+
+ UML_AND(block, IREG(7), IREG(0), IMM(0xff)); // and r7, r0, #0xff (LL)
+
+ UML_AND(block, MEM(&sh2->sr), MEM(&sh2->sr), IMM(~T)); // and sr, sr, ~T (clear the T bit)
+
+ UML_CMP(block, IREG(1), IMM(0)); // cmp r1, #0
+ UML_JMPc(block, IF_Z, compiler->labelnum); // jnz labelnum
+ UML_CMP(block, IREG(2), IMM(0)); // cmp r2, #0
+ UML_JMPc(block, IF_Z, compiler->labelnum); // jnz labelnum
+ UML_CMP(block, IREG(3), IMM(0)); // cmp r3, #0
+ UML_JMPc(block, IF_Z, compiler->labelnum); // jnz labelnum
+ UML_CMP(block, IREG(7), IMM(0)); // cmp r7, #0
+ UML_JMPc(block, IF_NZ, compiler->labelnum+1); // jnz labelnum
+
+ UML_LABEL(block, compiler->labelnum++); // labelnum:
+ UML_OR(block, MEM(&sh2->sr), MEM(&sh2->sr), IMM(T)); // or sr, sr, T
+
+ UML_LABEL(block, compiler->labelnum++); // labelnum+1:
+ return TRUE;
+ break;
+
+ case 9: // AND(Rm, Rn);
+ UML_AND(block, R32(Rn), R32(Rn), R32(Rm)); // and Rn, Rn, Rm
+ return TRUE;
+ break;
+
+ case 10: // XOR(Rm, Rn);
+ UML_XOR(block, R32(Rn), R32(Rn), R32(Rm)); // xor Rn, Rn, Rm
+ return TRUE;
+ break;
+
+ case 11: // OR(Rm, Rn);
+ UML_OR(block, R32(Rn), R32(Rn), R32(Rm)); // or Rn, Rn, Rm
+ return TRUE;
+ break;
+
+ case 14: // MULU(Rm, Rn);
+ UML_AND(block, IREG(0), R32(Rm), IMM(0xffff)); // and r0, Rm, 0xffff
+ UML_AND(block, IREG(1), R32(Rn), IMM(0xffff)); // and r1, Rn, 0xffff
+ UML_MULU(block, MEM(&sh2->macl), MEM(&sh2->ea), IREG(0), IREG(1)); // mulu macl, ea, r0, r1
+ return TRUE;
+ break;
+
+ case 15: // MULS(Rm, Rn);
+ UML_SEXT(block, IREG(0), R32(Rm), WORD); // sext r0, Rm
+ UML_SEXT(block, IREG(1), R32(Rn), WORD); // sext r1, Rn
+ UML_MULS(block, MEM(&sh2->macl), MEM(&sh2->ea), IREG(0), IREG(1)); // muls macl, ea, r0, r1
+ return TRUE;
+ break;
+ }
+
+ return FALSE;
+}
+
+static int generate_group_3(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, UINT16 opcode)
+{
+ switch (opcode & 15)
+ {
+ case 0: // CMPEQ(Rm, Rn); (equality)
+ UML_AND(block, IREG(0), MEM(&sh2->sr), IMM(~T)); // and r0, sr, ~T (clear the T bit)
+ UML_CMP(block, R32(Rm), R32(Rn)); // cmp Rm, Rn
+ UML_JMPc(block, IF_NE, compiler->labelnum); // jne compiler->labelnum
+
+ UML_OR(block, IREG(0), IREG(0), IMM(T)); // or r0, r0, T
+ UML_LABEL(block, compiler->labelnum++); // desc->pc:
+
+ UML_MOV(block, MEM(&sh2->sr), IREG(0)); // mov sh2->sr, r0
+ return TRUE;
+ break;
+
+ case 2: // CMPHS(Rm, Rn); (unsigned greater than or equal)
+ UML_AND(block, IREG(0), MEM(&sh2->sr), IMM(~T)); // and r0, sr, ~T (clear the T bit)
+
+ UML_CMP(block, R32(Rm), R32(Rn)); // cmp Rm, Rn
+ UML_JMPc(block, IF_A, compiler->labelnum); // ja labelnum
+
+ UML_OR(block, IREG(0), IREG(0), IMM(T)); // or r0, r0, T
+ UML_LABEL(block, compiler->labelnum++); // labelnum+1:
+
+ UML_MOV(block, MEM(&sh2->sr), IREG(0)); // mov sh2->sr, r0
+ return TRUE;
+ break;
+
+ case 3: // CMPGE(Rm, Rn); (signed greater than or equal)
+ UML_AND(block, IREG(0), MEM(&sh2->sr), IMM(~T)); // and r0, sr, ~T (clear the T bit)
+ UML_CMP(block, R32(Rm), R32(Rn)); // cmp Rm, Rn
+ UML_JMPc(block, IF_G, compiler->labelnum); // jg compiler->labelnum
+
+ UML_OR(block, IREG(0), IREG(0), IMM(T)); // or r0, r0, T
+ UML_LABEL(block, compiler->labelnum++); // labelnum:
+
+ UML_MOV(block, MEM(&sh2->sr), IREG(0)); // mov sh2->sr, r0
+ return TRUE;
+ break;
+
+ case 6: // CMPHI(Rm, Rn); (unsigned greater than)
+ UML_AND(block, IREG(0), MEM(&sh2->sr), IMM(~T)); // and r0, sr, ~T (clear the T bit)
+ UML_CMP(block, R32(Rn), R32(Rm)); // cmp Rn, Rm (Rm - Rn)
+ UML_JMPc(block, IF_BE, compiler->labelnum); // jbe compiler->labelnum
+
+ UML_OR(block, IREG(0), IREG(0), IMM(T)); // or r0, r0, T
+ UML_LABEL(block, compiler->labelnum++); // desc->pc:
+
+ UML_MOV(block, MEM(&sh2->sr), IREG(0)); // mov sh2->sr, r0
+ return TRUE;
+ break;
+
+ case 7: // CMPGT(Rm, Rn); (signed greater than)
+ UML_AND(block, IREG(0), MEM(&sh2->sr), IMM(~T)); // and r0, sr, ~T (clear the T bit)
+ UML_CMP(block, R32(Rm), R32(Rn)); // cmp Rm, Rn
+ UML_JMPc(block, IF_GE, compiler->labelnum); // jle compiler->labelnum
+
+ UML_OR(block, IREG(0), IREG(0), IMM(T)); // or r0, r0, T
+ UML_LABEL(block, compiler->labelnum++); // desc->pc:
+ UML_MOV(block, MEM(&sh2->sr), IREG(0)); // mov sh2->sr, r0
+ return TRUE;
+ break;
+
+ case 1: // NOP();
+ case 9: // NOP();
+ return TRUE;
+ break;
+
+ case 4: // DIV1(Rm, Rn);
+ save_fast_iregs(block);
+ UML_CALLC(block, cfunc_DIV1, desc->opptr.w);
+ load_fast_iregs(block);
+ return TRUE;
+ break;
+
+ case 5: // DMULU(Rm, Rn);
+ UML_MULU(block, MEM(&sh2->macl), MEM(&sh2->mach), R32(Rn), R32(Rm));
+ return TRUE;
+ break;
+
+ case 13: // DMULS(Rm, Rn);
+ UML_MULS(block, MEM(&sh2->macl), MEM(&sh2->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;
+ break;
+
+ case 12: // ADD(Rm, Rn);
+ UML_ADD(block, R32(Rn), R32(Rn), R32(Rm)); // add Rn, Rn, Rm
+ return TRUE;
+ break;
+
+ case 10: // SUBC(Rm, Rn);
+
+ UML_MOV(block, IREG(0), MEM(&sh2->sr)); // mov r0, sr (save SR)
+ UML_AND(block, MEM(&sh2->sr), MEM(&sh2->sr), IMM(~T)); // and sr, sr, ~T (clear the T bit)
+ UML_CARRY(block, IREG(0), IMM(0)); // carry = T (T is bit 0 of SR)
+ UML_SUBB(block, R32(Rn), R32(Rn), R32(Rm)); // subb Rn, Rn, Rm
+
+ UML_JMPc(block, IF_NC, compiler->labelnum); // jnc labelnum
+
+ UML_OR(block, MEM(&sh2->sr), MEM(&sh2->sr), IMM(T)); // or sr, sr, T
+
+ UML_LABEL(block, compiler->labelnum++); // labelnum:
+
+ return TRUE;
+ break;
+
+ case 11: // SUBV(Rm, Rn);
+ break;
+
+ case 14: // ADDC(Rm, Rn);
+ UML_MOV(block, IREG(0), MEM(&sh2->sr)); // mov r0, sr (save SR)
+ UML_AND(block, MEM(&sh2->sr), MEM(&sh2->sr), IMM(~T)); // and sr, sr, ~T (clear the T bit)
+ UML_CARRY(block, IREG(0), IMM(0)); // carry = T (T is bit 0 of SR)
+ UML_ADDC(block, R32(Rn), R32(Rn), R32(Rm)); // addc Rn, Rn, Rm
+ UML_JMPc(block, IF_NC, compiler->labelnum); // jnc labelnum
+
+ UML_OR(block, MEM(&sh2->sr), MEM(&sh2->sr), IMM(T)); // or sr, sr, T
+
+ UML_LABEL(block, compiler->labelnum++); // labelnum:
+ return TRUE;
+ break;
+
+ case 15: // ADDV(Rm, Rn);
+ UML_AND(block, MEM(&sh2->sr), MEM(&sh2->sr), IMM(~T)); // and sr, sr, ~T (clear the T bit)
+ UML_ADD(block, R32(Rn), R32(Rn), R32(Rm)); // add Rn, Rn, Rm
+ UML_JMPc(block, IF_NV, compiler->labelnum); // jnc labelnum
+
+ UML_OR(block, MEM(&sh2->sr), MEM(&sh2->sr), IMM(T)); // or sr, sr, T
+
+ UML_LABEL(block, compiler->labelnum++); // labelnum:
+ return TRUE;
+ break;
+ }
+ return FALSE;
+}
+
+static int generate_group_4(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, UINT16 opcode, int in_delay_slot)
+{
+ switch (opcode & 0x3F)
+ {
+ case 0x00: // SHLL(Rn);
+ UML_AND(block, IREG(0), MEM(&sh2->sr), IMM(~T)); // and r0, sr, ~T (clear the T bit)
+ UML_SHR(block, IREG(1), R32(Rn), IMM(31)); // shr r1, Rn, 31
+ UML_AND(block, IREG(1), IREG(1), IMM(T)); // and r1, r1, T
+ UML_OR(block, MEM(&sh2->sr), IREG(1), IREG(0)); // or sr, r1, r0
+ UML_SHL(block, R32(Rn), R32(Rn), IMM(1)); // shl Rn, Rn, 1
+ return TRUE;
+ break;
+
+ case 0x01: // SHLR(Rn);
+ UML_AND(block, IREG(0), MEM(&sh2->sr), IMM(~T)); // and r0, sr, ~T (clear the T bit)
+ UML_AND(block, IREG(1), R32(Rn), IMM(T)); // and r1, Rn, T
+ UML_OR(block, MEM(&sh2->sr), IREG(0), IREG(1)); // or sr, r0, r1
+ UML_SHR(block, R32(Rn), R32(Rn), IMM(1)); // shr Rn, Rn, 1
+ return TRUE;
+ break;
+
+ case 0x04: // ROTL(Rn);
+ UML_AND(block, MEM(&sh2->sr), MEM(&sh2->sr), IMM(~T)); // and sr, sr, ~T (clear the T bit)
+ UML_CARRY(block, R32(Rn), IMM(31)); // carry = high bit of source
+ UML_ROLC(block, R32(Rn), R32(Rn), IMM(1)); // rolc Rn, Rn, #1
+
+ UML_JMPc(block, IF_NC, compiler->labelnum); // jnc labelnum
+
+ UML_OR(block, MEM(&sh2->sr), MEM(&sh2->sr), IMM(T)); // or sr, sr, T
+
+ UML_LABEL(block, compiler->labelnum++); // labelnum:
+
+ return TRUE;
+ break;
+
+ case 0x05: // ROTR(Rn);
+ UML_AND(block, MEM(&sh2->sr), MEM(&sh2->sr), IMM(~T)); // and sr, sr, ~T (clear the T bit)
+ UML_CARRY(block, R32(Rn), IMM(0)); // carry = low bit of source
+ UML_RORC(block, R32(Rn), R32(Rn), IMM(1)); // rorc Rn, Rn, #1
+
+ UML_JMPc(block, IF_NC, compiler->labelnum); // jnc labelnum
+
+ UML_OR(block, MEM(&sh2->sr), MEM(&sh2->sr), IMM(T)); // or sr, sr, T
+
+ UML_LABEL(block, compiler->labelnum++); // labelnum:
+
+ return TRUE;
+ break;
+
+ case 0x02: // STSMMACH(Rn);
+ UML_SUB(block, R32(Rn), R32(Rn), IMM(4)); // sub Rn, Rn, #4
+ UML_MOV(block, IREG(0), R32(Rn)); // mov r0, Rn
+ UML_MOV(block, IREG(1), MEM(&sh2->mach)); // mov r1, mach
+ SETEA(0); // set ea for debug
+ UML_CALLH(block, sh2->write32); // call write32
+
+ if (!in_delay_slot)
+ generate_update_cycles(block, compiler, IMM(desc->pc + 2), TRUE);
+ return TRUE;
+ break;
+
+ case 0x03: // STCMSR(Rn);
+ UML_SUB(block, R32(Rn), R32(Rn), IMM(4)); // sub Rn, Rn, #4
+ UML_MOV(block, IREG(0), R32(Rn)); // mov r0, Rn
+ UML_MOV(block, IREG(1), MEM(&sh2->sr)); // mov r1, sr
+ SETEA(0); // set ea for debug
+ UML_CALLH(block, sh2->write32); // call write32
+
+ if (!in_delay_slot)
+ generate_update_cycles(block, compiler, IMM(desc->pc + 2), TRUE);
+ return TRUE;
+ break;
+
+ case 0x06: // LDSMMACH(Rn);
+ UML_MOV(block, IREG(0), R32(Rn)); // mov r0, Rn
+ SETEA(0);
+ UML_CALLH(block, sh2->read32); // call read32
+ UML_ADD(block, R32(Rn), R32(Rn), IMM(4)); // add Rn, #4
+ UML_MOV(block, MEM(&sh2->mach), IREG(0)); // mov mach, r0
+
+ if (!in_delay_slot)
+ generate_update_cycles(block, compiler, IMM(desc->pc + 2), TRUE);
+ return TRUE;
+ break;
+
+ case 0x07: // LDCMSR(Rn);
+ UML_MOV(block, IREG(0), R32(Rn)); // mov r0, Rn
+ SETEA(0);
+ UML_CALLH(block, sh2->read32); // call read32
+ UML_ADD(block, R32(Rn), R32(Rn), IMM(4)); // add Rn, #4
+ UML_MOV(block, MEM(&sh2->sr), IREG(0)); // mov sr, r0
+
+ compiler->checkints = TRUE;
+ if (!in_delay_slot)
+ generate_update_cycles(block, compiler, IMM(desc->pc + 2), TRUE);
+ return TRUE;
+ break;
+
+ case 0x08: // SHLL2(Rn);
+ UML_SHL(block, R32(Rn), R32(Rn), IMM(2));
+ return TRUE;
+ break;
+
+ case 0x09: // SHLR2(Rn);
+ UML_SHR(block, R32(Rn), R32(Rn), IMM(2));
+ return TRUE;
+ break;
+
+ case 0x18: // SHLL8(Rn);
+ UML_SHL(block, R32(Rn), R32(Rn), IMM(8));
+ return TRUE;
+ break;
+
+ case 0x19: // SHLR8(Rn);
+ UML_SHR(block, R32(Rn), R32(Rn), IMM(8));
+ return TRUE;
+ break;
+
+ case 0x28: // SHLL16(Rn);
+ UML_SHL(block, R32(Rn), R32(Rn), IMM(16));
+ return TRUE;
+ break;
+
+ case 0x29: // SHLR16(Rn);
+ UML_SHR(block, R32(Rn), R32(Rn), IMM(16));
+ return TRUE;
+ break;
+
+ case 0x0a: // LDSMACH(Rn);
+ UML_MOV(block, MEM(&sh2->mach), R32(Rn)); // mov mach, Rn
+ return TRUE;
+ break;
+
+ case 0x0b: // JSR(Rn);
+ UML_MOV(block, MEM(&sh2->target), R32(Rn)); // mov target, Rn
+
+ generate_delay_slot(block, compiler, desc);
+
+ UML_ADD(block, MEM(&sh2->pr), IMM(desc->pc), IMM(4)); // add sh2->pr, desc->pc, #4 (skip the current insn & delay slot)
+
+ generate_update_cycles(block, compiler, MEM(&sh2->target), TRUE); // <subtract cycles>
+ UML_HASHJMP(block, IMM(0), MEM(&sh2->target), sh2->nocode); // and do the jump
+ return TRUE;
+ break;
+
+ case 0x0e: // LDCSR(Rn);
+ UML_MOV(block, IREG(0), R32(Rn)); // mov r0, Rn
+ UML_AND(block, IREG(0), IREG(0), IMM(FLAGS)); // and r0, r0, FLAGS
+ UML_MOV(block, MEM(&sh2->sr), IREG(0));
+
+ compiler->checkints = TRUE;
+ return TRUE;
+ break;
+
+ 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_CALLC(block, cfunc_MAC_W, desc->opptr.w);
+ load_fast_iregs(block);
+ return TRUE;
+ break;
+
+ case 0x10: // DT(Rn);
+ UML_AND(block, IREG(0), MEM(&sh2->sr), IMM(~T)); // and r0, sr, ~T (clear the T bit)
+ UML_SUB(block, R32(Rn), R32(Rn), IMM(1)); // sub Rn, Rn, 1
+ UML_JMPc(block, IF_NZ, compiler->labelnum); // jz compiler->labelnum
+
+ UML_OR(block, IREG(0), IREG(0), IMM(T)); // or r0, r0, T
+ UML_LABEL(block, compiler->labelnum++); // desc->pc:
+
+ UML_MOV(block, MEM(&sh2->sr), IREG(0)); // mov sh2->sr, r0
+ return TRUE;
+ break;
+
+ case 0x11: // CMPPZ(Rn);
+ UML_AND(block, IREG(0), MEM(&sh2->sr), IMM(~T)); // and r0, sr, ~T (clear the T bit)
+
+ UML_CMP(block, R32(Rn), IMM(0)); // cmp Rn, 0
+ UML_JMPc(block, IF_S, compiler->labelnum); // js compiler->labelnum (if negative)
+
+ UML_OR(block, IREG(0), IREG(0), IMM(T)); // or r0, r0, T
+ UML_LABEL(block, compiler->labelnum++); // desc->pc:
+
+ UML_MOV(block, MEM(&sh2->sr), IREG(0)); // mov sh2->sr, r0
+ return TRUE;
+ break;
+
+ case 0x15: // CMPPL(Rn);
+ UML_AND(block, IREG(0), MEM(&sh2->sr), IMM(~T)); // and r0, sr, ~T (clear the T bit)
+
+ UML_CMP(block, R32(Rn), IMM(0)); // cmp Rn, 0
+
+ UML_JMPc(block, IF_S, compiler->labelnum); // js compiler->labelnum (if negative)
+ UML_JMPc(block, IF_Z, compiler->labelnum); // jz compiler->labelnum (if zero)
+
+ UML_OR(block, IREG(0), IREG(0), IMM(T)); // or r0, r0, T
+
+ UML_LABEL(block, compiler->labelnum++); // desc->pc:
+ UML_MOV(block, MEM(&sh2->sr), IREG(0)); // mov sh2->sr, r0
+ return TRUE;
+ break;
+
+ case 0x12: // STSMMACL(Rn);
+ UML_SUB(block, R32(Rn), R32(Rn), IMM(4)); // sub Rn, Rn, #4
+ UML_MOV(block, IREG(0), R32(Rn)); // mov r0, Rn
+ UML_MOV(block, IREG(1), MEM(&sh2->macl)); // mov r1, macl
+ SETEA(0); // set ea for debug
+ UML_CALLH(block, sh2->write32); // call write32
+
+ if (!in_delay_slot)
+ generate_update_cycles(block, compiler, IMM(desc->pc + 2), TRUE);
+ return TRUE;
+ break;
+
+ case 0x13: // STCMGBR(Rn);
+ UML_SUB(block, R32(Rn), R32(Rn), IMM(4)); // sub Rn, Rn, #4
+ UML_MOV(block, IREG(0), R32(Rn)); // mov r0, Rn
+ UML_MOV(block, IREG(1), MEM(&sh2->gbr)); // mov r1, gbr
+ SETEA(0); // set ea for debug
+ UML_CALLH(block, sh2->write32); // call write32
+
+ if (!in_delay_slot)
+ generate_update_cycles(block, compiler, IMM(desc->pc + 2), TRUE);
+ return TRUE;
+ break;
+
+ case 0x16: // LDSMMACL(Rn);
+ UML_MOV(block, IREG(0), R32(Rn)); // mov r0, Rn
+ SETEA(0);
+ UML_CALLH(block, sh2->read32); // call read32
+ UML_ADD(block, R32(Rn), R32(Rn), IMM(4)); // add Rn, #4
+ UML_MOV(block, MEM(&sh2->macl), IREG(0)); // mov macl, r0
+
+ if (!in_delay_slot)
+ generate_update_cycles(block, compiler, IMM(desc->pc + 2), TRUE);
+ return TRUE;
+ break;
+
+ case 0x17: // LDCMGBR(Rn);
+ UML_MOV(block, IREG(0), R32(Rn)); // mov r0, Rn
+ SETEA(0);
+ UML_CALLH(block, sh2->read32); // call read32
+ UML_ADD(block, R32(Rn), R32(Rn), IMM(4)); // add Rn, #4
+ UML_MOV(block, MEM(&sh2->gbr), IREG(0)); // mov gbr, r0
+
+ if (!in_delay_slot)
+ generate_update_cycles(block, compiler, IMM(desc->pc + 2), TRUE);
+ return TRUE;
+ break;
+
+ case 0x1a: // LDSMACL(Rn);
+ UML_MOV(block, MEM(&sh2->macl), R32(Rn)); // mov macl, Rn
+ return TRUE;
+ break;
+
+ case 0x1b: // TAS(Rn);
+ UML_MOV(block, IREG(0), R32(Rn)); // mov r0, Rn
+ SETEA(0);
+ UML_CALLH(block, sh2->read8); // call read8
+
+ UML_AND(block, MEM(&sh2->sr), MEM(&sh2->sr), IMM(~T)); // and sr, sr, ~T
+
+ UML_CMP(block, IREG(0), IMM(0)); // cmp r0, #0
+ UML_JMPc(block, IF_NZ, compiler->labelnum); // jnz labelnum
+
+ UML_OR(block, MEM(&sh2->sr), MEM(&sh2->sr), IMM(T)); // or sr, sr, T
+
+ UML_LABEL(block, compiler->labelnum++); // labelnum:
+
+ UML_OR(block, IREG(1), IREG(0), IMM(0x80)); // or r1, r0, #0x80
+
+ UML_MOV(block, IREG(0), R32(Rn)); // mov r0, Rn
+ UML_CALLH(block, sh2->write8); // write the value back
+
+ if (!in_delay_slot)
+ generate_update_cycles(block, compiler, IMM(desc->pc + 2), TRUE);
+ return TRUE;
+ break;
+
+ case 0x1e: // LDCGBR(Rn);
+ UML_MOV(block, MEM(&sh2->gbr), R32(Rn)); // mov gbr, Rn
+ return TRUE;
+ break;
+
+ case 0x20: // SHAL(Rn);
+ UML_AND(block, MEM(&sh2->sr), MEM(&sh2->sr), IMM(~T)); // and sr, sr, ~T
+ UML_SHR(block, IREG(0), R32(Rn), IMM(31)); // shr r0, Rn, 31
+ UML_AND(block, IREG(0), IREG(0), IMM(T)); // and r0, r0, T
+ UML_OR(block, MEM(&sh2->sr), MEM(&sh2->sr), IREG(0)); // or sr, sr, r0
+ UML_SHL(block, R32(Rn), R32(Rn), IMM(1)); // shl Rn, Rn, 1
+ return TRUE;
+ break;
+
+ case 0x21: // SHAR(Rn);
+ UML_AND(block, MEM(&sh2->sr), MEM(&sh2->sr), IMM(~T)); // and sr, sr, ~T
+ UML_AND(block, IREG(0), R32(Rn), IMM(T)); // and r0, Rn, T
+ UML_OR(block, MEM(&sh2->sr), MEM(&sh2->sr), IREG(0)); // or sr, sr, r0
+ UML_SAR(block, R32(Rn), R32(Rn), IMM(1)); // sar Rn, Rn, 1
+ return TRUE;
+ break;
+
+ case 0x22: // STSMPR(Rn);
+ UML_SUB(block, R32(Rn), R32(Rn), IMM(4)); // sub Rn, Rn, 4
+ UML_MOV(block, IREG(0), R32(Rn)); // mov r0, Rn
+ SETEA(0);
+ UML_MOV(block, IREG(1), MEM(&sh2->pr)); // mov r1, pr
+ UML_CALLH(block, sh2->write32); // call write32
+
+ if (!in_delay_slot)
+ generate_update_cycles(block, compiler, IMM(desc->pc + 2), TRUE);
+ return TRUE;
+ break;
+
+ case 0x23: // STCMVBR(Rn);
+ UML_SUB(block, R32(Rn), R32(Rn), IMM(4)); // sub Rn, Rn, 4
+ UML_MOV(block, IREG(0), R32(Rn)); // mov r0, Rn
+ SETEA(0);
+ UML_MOV(block, IREG(1), MEM(&sh2->vbr)); // mov r1, vbr
+ UML_CALLH(block, sh2->write32); // call write32
+
+ if (!in_delay_slot)
+ generate_update_cycles(block, compiler, IMM(desc->pc + 2), TRUE);
+ return TRUE;
+ break;
+
+ case 0x24: // ROTCL(Rn);
+ UML_SHR(block, IREG(0), R32(Rn), IMM(31)); // shr r0, Rn, 31
+ UML_AND(block, IREG(0), IREG(0), IMM(T)); // and r0, r0, T
+
+ UML_AND(block, IREG(1), MEM(&sh2->sr), IMM(T)); // and r1, sr, T
+
+ UML_SHL(block, R32(Rn), R32(Rn), IMM(1)); // shl Rn, Rn, 1
+ UML_OR(block, R32(Rn), R32(Rn), IREG(1)); // or Rn, Rn, r1
+
+ UML_AND(block, MEM(&sh2->sr), MEM(&sh2->sr), IMM(~T)); // and sr, sr, ~T
+ UML_OR(block, MEM(&sh2->sr), MEM(&sh2->sr), IREG(0)); // or sr, sr, r0
+ return TRUE;
+ break;
+
+ case 0x25: // ROTCR(Rn);
+ UML_AND(block, IREG(0), MEM(&sh2->sr), IMM(T)); // and r0, sr, T
+ UML_SHL(block, IREG(0), IREG(0), IMM(31)); // shl r0, r0, #31 (r0 = temp)
+
+ UML_AND(block, IREG(1), R32(Rn), IMM(T)); // and r1, Rn, T (r1 = Rn & T)
+
+ UML_AND(block, MEM(&sh2->sr), MEM(&sh2->sr), IMM(~T)); // and sr, sr, ~T
+
+ UML_CMP(block, IREG(1), IMM(0)); // cmp r1, #0
+ UML_JMPc(block, IF_Z, compiler->labelnum); // jz labelnum
+
+ UML_OR(block, MEM(&sh2->sr), MEM(&sh2->sr), IMM(T)); // or sr, sr, T
+
+ UML_LABEL(block, compiler->labelnum++); // labelnum:
+
+ UML_SHR(block, R32(Rn), R32(Rn), IMM(1)); // shr Rn, Rn, #1
+ UML_OR(block, R32(Rn), R32(Rn), IREG(0)); // or Rn, Rn, r0
+ return TRUE;
+ break;
+
+ case 0x26: // LDSMPR(Rn);
+ UML_MOV(block, IREG(0), R32(Rn)); // mov r0, Rn
+ SETEA(0);
+ UML_CALLH(block, sh2->read32); // call read32
+ UML_MOV(block, MEM(&sh2->pr), IREG(0)); // mov sh2->pr, r0
+ UML_ADD(block, R32(Rn), R32(Rn), IMM(4)); // add Rn, Rn, #4
+
+ if (!in_delay_slot)
+ generate_update_cycles(block, compiler, IMM(desc->pc + 2), TRUE);
+ return TRUE;
+ break;
+
+ case 0x27: // LDCMVBR(Rn);
+ UML_MOV(block, IREG(0), R32(Rn)); // mov r0, Rn
+ SETEA(0);
+ UML_CALLH(block, sh2->read32); // call read32
+ UML_MOV(block, MEM(&sh2->vbr), IREG(0)); // mov sh2->vbr, r0
+ UML_ADD(block, R32(Rn), R32(Rn), IMM(4)); // add Rn, Rn, #4
+
+ if (!in_delay_slot)
+ generate_update_cycles(block, compiler, IMM(desc->pc + 2), TRUE);
+ return TRUE;
+ break;
+
+ case 0x2a: // LDSPR(Rn);
+ UML_MOV(block, MEM(&sh2->pr), R32(Rn)); // mov sh2->pr, Rn
+ return TRUE;
+ break;
+
+ case 0x2b: // JMP(Rn);
+ UML_MOV(block, MEM(&sh2->target), R32(Rn)); // mov target, Rn
+
+ generate_delay_slot(block, compiler, desc);
+
+ generate_update_cycles(block, compiler, MEM(&sh2->target), TRUE); // <subtract cycles>
+ UML_HASHJMP(block, IMM(0), MEM(&sh2->target), sh2->nocode); // jmp (target)
+ return TRUE;
+ break;
+
+ case 0x2e: // LDCVBR(Rn);
+ UML_MOV(block, MEM(&sh2->vbr), R32(Rn)); // mov vbr, Rn
+ return TRUE;
+ break;
+
+ 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;
+ break;
+
+ }
+
+ return FALSE;
+}
+
+static int generate_group_6(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, UINT16 opcode, int in_delay_slot)
+{
+ switch (opcode & 15)
+ {
+ case 0: // MOVBL(Rm, Rn);
+ UML_MOV(block, IREG(0), R32(Rm)); // mov r0, Rm
+ SETEA(0); // debug: ea = r0
+ UML_CALLH(block, sh2->read8); // call read8
+ UML_SEXT(block, R32(Rn), IREG(0), BYTE); // sext Rn, r0, BYTE
+
+ if (!in_delay_slot)
+ generate_update_cycles(block, compiler, IMM(desc->pc + 2), TRUE);
+ return TRUE;
+ break;
+
+ case 1: // MOVWL(Rm, Rn);
+ UML_MOV(block, IREG(0), R32(Rm)); // mov r0, Rm
+ SETEA(0); // debug: ea = r0
+ UML_CALLH(block, sh2->read16); // call read16
+ UML_SEXT(block, R32(Rn), IREG(0), WORD); // sext Rn, r0, WORD
+
+ if (!in_delay_slot)
+ generate_update_cycles(block, compiler, IMM(desc->pc + 2), TRUE);
+ return TRUE;
+ break;
+
+ case 2: // MOVLL(Rm, Rn);
+ UML_MOV(block, IREG(0), R32(Rm)); // mov r0, Rm
+ SETEA(0); // debug: ea = r0
+ UML_CALLH(block, sh2->read32); // call read32
+ UML_MOV(block, R32(Rn), IREG(0)); // mov Rn, r0
+
+ if (!in_delay_slot)
+ generate_update_cycles(block, compiler, IMM(desc->pc + 2), TRUE);
+ return TRUE;
+ break;
+
+ case 3: // MOV(Rm, Rn);
+ UML_MOV(block, R32(Rn), R32(Rm)); // mov Rn, Rm
+ return TRUE;
+ break;
+
+ case 7: // NOT(Rm, Rn);
+ UML_XOR(block, R32(Rn), R32(Rm), IMM(0xffffffff)); // xor Rn, Rm, 0xffffffff
+ return TRUE;
+ break;
+
+ case 9: // SWAPW(Rm, Rn);
+ UML_ROL(block, R32(Rn), R32(Rm), IMM(16)); // rol Rn, Rm, 16
+ return TRUE;
+ break;
+
+ case 11: // NEG(Rm, Rn);
+ UML_SUB(block, R32(Rn), IMM(0), R32(Rm)); // sub Rn, 0, Rm
+ return TRUE;
+ break;
+
+ case 12: // EXTUB(Rm, Rn);
+ UML_AND(block, R32(Rn), R32(Rm), IMM(0x000000ff)); // and Rn, Rm, 0xff
+ return TRUE;
+ break;
+
+ case 13: // EXTUW(Rm, Rn);
+ UML_AND(block, R32(Rn), R32(Rm), IMM(0x0000ffff)); // and Rn, Rm, 0xffff
+ return TRUE;
+ break;
+
+ case 14: // EXTSB(Rm, Rn);
+ UML_SEXT(block, R32(Rn), R32(Rm), BYTE); // sext Rn, Rm, BYTE
+ return TRUE;
+ break;
+
+ case 15: // EXTSW(Rm, Rn);
+ UML_SEXT(block, R32(Rn), R32(Rm), WORD); // sext Rn, Rm, WORD
+ return TRUE;
+ break;
+
+ case 4: // MOVBP(Rm, Rn);
+ UML_MOV(block, IREG(0), R32(Rm)); // mov r0, Rm
+ UML_CALLH(block, sh2->read8); // call read8
+ UML_SEXT(block, R32(Rn), IREG(0), BYTE); // sext Rn, r0, BYTE
+
+ UML_CMP(block, IMM(Rn), IMM(Rm)); // cmp N, M
+ UML_JMPc(block, IF_Z, compiler->labelnum); // jz compiler->labelnum
+
+ UML_ADD(block, R32(Rm), R32(Rm), IMM(1)); // add Rm, Rm, #1
+
+ UML_LABEL(block, compiler->labelnum++); // labelnum:
+
+ if (!in_delay_slot)
+ generate_update_cycles(block, compiler, IMM(desc->pc + 2), TRUE);
+ return TRUE;
+ break;
+
+ case 5: // MOVWP(Rm, Rn);
+ UML_MOV(block, IREG(0), R32(Rm)); // mov r0, Rm
+ UML_CALLH(block, sh2->read16); // call read16
+ UML_SEXT(block, R32(Rn), IREG(0), WORD); // sext Rn, r0, WORD
+
+ UML_CMP(block, IMM(Rn), IMM(Rm)); // cmp N, M
+ UML_JMPc(block, IF_Z, compiler->labelnum); // jz compiler->labelnum
+
+ UML_ADD(block, R32(Rm), R32(Rm), IMM(2)); // add Rm, Rm, #2
+
+ UML_LABEL(block, compiler->labelnum++); // labelnum:
+
+ if (!in_delay_slot)
+ generate_update_cycles(block, compiler, IMM(desc->pc + 2), TRUE);
+ return TRUE;
+ break;
+
+ case 6: // MOVLP(Rm, Rn);
+ UML_MOV(block, IREG(0), R32(Rm)); // mov r0, Rm
+ UML_CALLH(block, sh2->read32); // call read32
+ UML_MOV(block, R32(Rn), IREG(0)); // mov Rn, r0
+
+ UML_CMP(block, IMM(Rn), IMM(Rm)); // cmp N, M
+ UML_JMPc(block, IF_Z, compiler->labelnum); // jz compiler->labelnum
+
+ UML_ADD(block, R32(Rm), R32(Rm), IMM(4)); // add Rm, Rm, #4
+
+ UML_LABEL(block, compiler->labelnum++); // labelnum:
+
+ if (!in_delay_slot)
+ generate_update_cycles(block, compiler, IMM(desc->pc + 2), TRUE);
+ return TRUE;
+ break;
+
+ case 8: // SWAPB(Rm, Rn);
+ UML_AND(block, IREG(0), R32(Rm), IMM(0xffff0000)); // and r0, Rm, #0xffff0000
+ UML_AND(block, IREG(1), R32(Rm), IMM(0x000000ff)); // and r0, Rm, #0x000000ff
+ UML_AND(block, IREG(2), R32(Rm), IMM(0x0000ff00)); // and r0, Rm, #0x0000ff00
+ UML_SHL(block, IREG(1), IREG(1), IMM(8)); // shl r1, r1, #8
+ UML_SHR(block, IREG(2), IREG(2), IMM(8)); // shr r2, r2, #8
+ UML_OR(block, IREG(0), IREG(0), IREG(1)); // or r0, r0, r1
+ UML_OR(block, R32(Rn), IREG(0), IREG(2)); // or Rn, r0, r2
+ return TRUE;
+ break;
+
+ case 10: // NEGC(Rm, Rn);
+ UML_MOV(block, IREG(0), MEM(&sh2->sr)); // mov r0, sr (save SR)
+ UML_AND(block, MEM(&sh2->sr), MEM(&sh2->sr), IMM(~T)); // and sr, sr, ~T (clear the T bit)
+ UML_CARRY(block, IREG(0), IMM(0)); // carry = T (T is bit 0 of SR)
+ UML_SUBB(block, R32(Rn), IMM(0), R32(Rm)); // subb Rn, #0, Rm
+
+ UML_JMPc(block, IF_NC, compiler->labelnum); // jnc labelnum
+
+ UML_OR(block, MEM(&sh2->sr), MEM(&sh2->sr), IMM(T)); // or sr, sr, T
+
+ UML_LABEL(block, compiler->labelnum++); // labelnum:
+
+ return TRUE;
+ break;
+ }
+
+ return FALSE;
+}
+
+static int generate_group_8(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, UINT16 opcode, int in_delay_slot)
+{
+ INT32 disp;
+ UINT32 udisp;
+ drcuml_codelabel templabel;
+
+ switch ( opcode & (15<<8) )
+ {
+ case 0 << 8: // MOVBS4(opcode & 0x0f, Rm);
+ udisp = (opcode & 0x0f);
+ UML_ADD(block, IREG(0), R32(Rm), IMM(udisp)); // add r0, Rm, udisp
+ UML_MOV(block, IREG(1), R32(0)); // mov r1, R0
+ UML_CALLH(block, sh2->write8); // call write8
+
+ if (!in_delay_slot)
+ generate_update_cycles(block, compiler, IMM(desc->pc + 2), TRUE);
+ return TRUE;
+ break;
+
+ case 1 << 8: // MOVWS4(opcode & 0x0f, Rm);
+ udisp = (opcode & 0x0f) * 2;
+ UML_ADD(block, IREG(0), R32(Rm), IMM(udisp)); // add r0, Rm, udisp
+ UML_MOV(block, IREG(1), R32(0)); // mov r1, R0
+ UML_CALLH(block, sh2->write16); // call write16
+
+ if (!in_delay_slot)
+ generate_update_cycles(block, compiler, IMM(desc->pc + 2), TRUE);
+ return TRUE;
+ break;
+
+ 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;
+ break;
+
+ case 4<< 8: // MOVBL4(Rm, opcode & 0x0f);
+ udisp = opcode & 0x0f;
+ UML_ADD(block, IREG(0), R32(Rm), IMM(udisp)); // add r0, Rm, udisp
+ SETEA(0);
+ UML_CALLH(block, sh2->read8); // call read8
+ UML_SEXT(block, R32(0), IREG(0), BYTE); // sext R0, r0, BYTE
+
+ if (!in_delay_slot)
+ generate_update_cycles(block, compiler, IMM(desc->pc + 2), TRUE);
+ return TRUE;
+ break;
+
+ case 5<< 8: // MOVWL4(Rm, opcode & 0x0f);
+ udisp = (opcode & 0x0f)*2;
+ UML_ADD(block, IREG(0), R32(Rm), IMM(udisp)); // add r0, Rm, udisp
+ SETEA(0);
+ UML_CALLH(block, sh2->read16); // call read16
+ UML_SEXT(block, R32(0), IREG(0), WORD); // sext R0, r0, WORD
+
+ if (!in_delay_slot)
+ generate_update_cycles(block, compiler, IMM(desc->pc + 2), TRUE);
+ return TRUE;
+ break;
+
+ case 8<< 8: // CMPIM(opcode & 0xff);
+ UML_AND(block, IREG(0), MEM(&sh2->sr), IMM(~T)); // and r0, sr, ~T (clear the T bit)
+
+ UML_SEXT(block, IREG(1), IMM(opcode&0xff), BYTE); // sext r1, opcode&0xff, BYTE
+ UML_CMP(block, IREG(1), R32(0)); // cmp r1, R0
+ UML_JMPc(block, IF_NZ, compiler->labelnum); // jnz compiler->labelnum (if negative)
+
+ UML_OR(block, IREG(0), IREG(0), IMM(T)); // or r0, r0, T
+
+ UML_LABEL(block, compiler->labelnum++); // labelnum:
+ UML_MOV(block, MEM(&sh2->sr), IREG(0)); // mov sh2->sr, r0
+ return TRUE;
+ break;
+
+ case 9<< 8: // BT(opcode & 0xff);
+ UML_TEST(block, MEM(&sh2->sr), IMM(T)); // test sh2->sr, T
+ UML_JMPc(block, IF_Z, compiler->labelnum); // jz compiler->labelnum
+
+ disp = ((INT32)opcode << 24) >> 24;
+ sh2->ea = (desc->pc + 2) + disp * 2 + 2; // sh2->ea = destination
+
+ generate_update_cycles(block, compiler, IMM(sh2->ea), TRUE); // <subtract cycles>
+ UML_HASHJMP(block, IMM(0), IMM(sh2->ea), sh2->nocode); // jmp sh2->ea
+
+ UML_LABEL(block, compiler->labelnum++); // labelnum:
+ return TRUE;
+ break;
+
+ case 11<< 8: // BF(opcode & 0xff);
+ UML_TEST(block, MEM(&sh2->sr), IMM(T)); // test sh2->sr, T
+ UML_JMPc(block, IF_NZ, compiler->labelnum); // jnz compiler->labelnum
+
+ disp = ((INT32)opcode << 24) >> 24;
+ sh2->ea = (desc->pc + 2) + disp * 2 + 2; // sh2->ea = destination
+
+ generate_update_cycles(block, compiler, IMM(sh2->ea), TRUE); // <subtract cycles>
+ UML_HASHJMP(block, IMM(0), IMM(sh2->ea), sh2->nocode); // jmp sh2->ea
+
+ UML_LABEL(block, compiler->labelnum++); // labelnum:
+ return TRUE;
+ break;
+
+ case 13<< 8: // BTS(opcode & 0xff);
+ UML_TEST(block, MEM(&sh2->sr), IMM(T)); // test sh2->sr, T
+ UML_JMPc(block, IF_Z, compiler->labelnum); // jz compiler->labelnum
+
+ templabel = compiler->labelnum; // save our label
+ compiler->labelnum++; // make sure the delay slot doesn't use it
+ generate_delay_slot(block, compiler, desc);
+
+ disp = ((INT32)opcode << 24) >> 24;
+ sh2->ea = (desc->pc + 2) + disp * 2 + 2; // sh2->ea = destination
+
+ generate_update_cycles(block, compiler, IMM(sh2->ea), TRUE); // <subtract cycles>
+ UML_HASHJMP(block, IMM(0), IMM(sh2->ea), sh2->nocode); // jmp sh2->ea
+
+ UML_LABEL(block, templabel); // labelnum:
+ return TRUE;
+ break;
+
+ case 15<< 8: // BFS(opcode & 0xff);
+ UML_TEST(block, MEM(&sh2->sr), IMM(T)); // test sh2->sr, T
+ UML_JMPc(block, IF_NZ, compiler->labelnum); // jnz compiler->labelnum
+
+ templabel = compiler->labelnum; // save our label
+ compiler->labelnum++; // make sure the delay slot doesn't use it
+ generate_delay_slot(block, compiler, desc); // delay slot only if the branch is taken
+
+ disp = ((INT32)opcode << 24) >> 24;
+ sh2->ea = (desc->pc + 2) + disp * 2 + 2; // sh2->ea = destination
+
+ generate_update_cycles(block, compiler, IMM(sh2->ea), TRUE); // <subtract cycles>
+ UML_HASHJMP(block, IMM(0), IMM(sh2->ea), sh2->nocode); // jmp sh2->ea
+
+ UML_LABEL(block, templabel); // labelnum:
+ return TRUE;
+ break;
+ }
+
+ return FALSE;
+}
+
+static int generate_group_12(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, UINT16 opcode, int in_delay_slot)
+{
+ UINT32 scratch;
+
+ switch (opcode & (15<<8))
+ {
+ case 0<<8: // MOVBSG(opcode & 0xff);
+ scratch = (opcode & 0xff);
+ UML_ADD(block, IREG(0), MEM(&sh2->gbr), IMM(scratch)); // add r0, gbr, scratch
+ UML_AND(block, IREG(1), R32(0), IMM(0xff)); // and r1, R0, 0xff
+ UML_CALLH(block, sh2->write8); // call write8
+
+ if (!in_delay_slot)
+ generate_update_cycles(block, compiler, IMM(desc->pc + 2), TRUE);
+ return TRUE;
+ break;
+
+ case 1<<8: // MOVWSG(opcode & 0xff);
+ scratch = (opcode & 0xff) * 2;
+ UML_ADD(block, IREG(0), MEM(&sh2->gbr), IMM(scratch)); // add r0, gbr, scratch
+ UML_AND(block, IREG(1), R32(0), IMM(0xffff)); // and r1, R0, 0xffff
+ UML_CALLH(block, sh2->write16); // call write16
+
+ if (!in_delay_slot)
+ generate_update_cycles(block, compiler, IMM(desc->pc + 2), TRUE);
+ return TRUE;
+ break;
+
+ case 2<<8: // MOVLSG(opcode & 0xff);
+ scratch = (opcode & 0xff) * 4;
+ UML_ADD(block, IREG(0), MEM(&sh2->gbr), IMM(scratch)); // add r0, gbr, scratch
+ UML_MOV(block, IREG(1), R32(0)); // mov r1, R0
+ UML_CALLH(block, sh2->write32); // call write32
+
+ if (!in_delay_slot)
+ generate_update_cycles(block, compiler, IMM(desc->pc + 2), TRUE);
+ return TRUE;
+ break;
+
+ case 3<<8: // TRAPA(opcode & 0xff);
+ scratch = (opcode & 0xff) * 4;
+ UML_ADD(block, MEM(&sh2->ea), MEM(&sh2->vbr), IMM(scratch)); // add ea, vbr, scratch
+
+ UML_SUB(block, R32(15), R32(15), IMM(4)); // sub R15, R15, #4
+ UML_MOV(block, IREG(0), R32(15)); // mov r0, R15
+ UML_MOV(block, IREG(1), MEM(&sh2->sr)); // mov r1, sr
+ UML_CALLH(block, sh2->write32); // write32
+
+ UML_SUB(block, R32(15), R32(15), IMM(4)); // sub R15, R15, #4
+ UML_MOV(block, IREG(0), R32(15)); // mov r0, R15
+ UML_MOV(block, IREG(1), IMM(desc->pc+2)); // mov r1, pc+2
+ UML_CALLH(block, sh2->write32); // write32
+
+ UML_MOV(block, IREG(0), MEM(&sh2->ea)); // mov r0, ea
+ UML_CALLH(block, sh2->read32); // read32
+ UML_HASHJMP(block, IMM(0), IREG(0), sh2->nocode); // jmp (r0)
+
+ return TRUE;
+ break;
+
+ case 4<<8: // MOVBLG(opcode & 0xff);
+ scratch = (opcode & 0xff);
+ UML_ADD(block, IREG(0), MEM(&sh2->gbr), IMM(scratch)); // add r0, gbr, scratch
+ UML_CALLH(block, sh2->read8); // call read16
+ UML_SEXT(block, R32(0), IREG(0), BYTE); // sext R0, r0, BYTE
+
+ if (!in_delay_slot)
+ generate_update_cycles(block, compiler, IMM(desc->pc + 2), TRUE);
+ return TRUE;
+ break;
+
+ case 5<<8: // MOVWLG(opcode & 0xff);
+ scratch = (opcode & 0xff) * 2;
+ UML_ADD(block, IREG(0), MEM(&sh2->gbr), IMM(scratch)); // add r0, gbr, scratch
+ UML_CALLH(block, sh2->read16); // call read16
+ UML_SEXT(block, R32(0), IREG(0), WORD); // sext R0, r0, WORD
+
+ if (!in_delay_slot)
+ generate_update_cycles(block, compiler, IMM(desc->pc + 2), TRUE);
+ return TRUE;
+ break;
+
+ case 6<<8: // MOVLLG(opcode & 0xff);
+ scratch = (opcode & 0xff) * 4;
+ UML_ADD(block, IREG(0), MEM(&sh2->gbr), IMM(scratch)); // add r0, gbr, scratch
+ UML_CALLH(block, sh2->read32); // call read32
+ UML_MOV(block, R32(0), IREG(0)); // mov R0, r0
+
+ if (!in_delay_slot)
+ generate_update_cycles(block, compiler, IMM(desc->pc + 2), TRUE);
+ return TRUE;
+ break;
+
+ case 7<<8: // MOVA(opcode & 0xff);
+ scratch = (opcode & 0xff) * 4;
+ scratch += ((desc->pc + 4) & ~3);
+
+ UML_MOV(block, R32(0), IMM(scratch)); // mov R0, scratch
+ return TRUE;
+ break;
+
+ case 8<<8: // TSTI(opcode & 0xff);
+ scratch = opcode & 0xff;
+
+ UML_AND(block, MEM(&sh2->sr), MEM(&sh2->sr), IMM(~T)); // and sr, sr, ~T (clear the T bit)
+ UML_AND(block, IREG(0), R32(0), IMM(scratch)); // and r0, R0, scratch
+ UML_CMP(block, IREG(0), IMM(0)); // cmp r0, #0
+ UML_JMPc(block, IF_NZ, compiler->labelnum); // jnz labelnum
+
+ UML_OR(block, MEM(&sh2->sr), MEM(&sh2->sr), IMM(T)); // or sr, sr, T
+
+ UML_LABEL(block, compiler->labelnum++); // labelnum:
+ return TRUE;
+ break;
+
+ case 9<<8: // ANDI(opcode & 0xff);
+ UML_AND(block, R32(0), R32(0), IMM(opcode & 0xff)); // and r0, r0, opcode & 0xff
+ return TRUE;
+ break;
+
+ case 10<<8: // XORI(opcode & 0xff);
+ UML_XOR(block, R32(0), R32(0), IMM(opcode & 0xff)); // xor r0, r0, opcode & 0xff
+ return TRUE;
+ break;
+
+ case 11<<8: // ORI(opcode & 0xff);
+ UML_OR(block, R32(0), R32(0), IMM(opcode & 0xff)); // or r0, r0, opcode & 0xff
+ return TRUE;
+ break;
+
+ case 12<<8: // TSTM(opcode & 0xff);
+ case 13<<8: // ANDM(opcode & 0xff);
+ case 14<<8: // XORM(opcode & 0xff);
+ break;
+
+ case 15<<8: // ORM(opcode & 0xff);
+ UML_ADD(block, IREG(0), R32(0), MEM(&sh2->gbr)); // add r0, R0, gbr
+ UML_CALLH(block, sh2->read8); // read8
+
+ UML_OR(block, IREG(1), IREG(0), IMM(opcode&0xff)); // or r1, r0, #opcode&0xff
+ UML_ADD(block, IREG(0), R32(0), MEM(&sh2->gbr)); // add r0, R0, gbr
+ SETEA(0);
+ UML_CALLH(block, sh2->write8); // write8
+ return TRUE;
+ break;
+ }
+
+ return FALSE;
+}
+
+/***************************************************************************
+ CORE CALLBACKS
+***************************************************************************/
+
+/*-------------------------------------------------
+ sh2_get_context - return a copy of the
+ current context
+-------------------------------------------------*/
+
+static void sh2_get_context(void *dst)
+{
+ if( dst )
+ *(SH2 **)dst = sh2;
+}
+
+/*-------------------------------------------------
+ sh2_set_context - copy the current context
+ into the global state
+-------------------------------------------------*/
+
+static void sh2_set_context(void *src)
+{
+ if( src )
+ sh2 = *(SH2 **)src;
+}
+
+/*-------------------------------------------------
+ sh2_dasm - disassemble an instruction
+-------------------------------------------------*/
+
+static offs_t sh2_dasm(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram)
+{
+ return DasmSH2( buffer, pc, (oprom[0] << 8) | oprom[1] );
+}
+
+/*-------------------------------------------------
+ sh2_internal_a5 - read handler for
+ SH2 internal map
+-------------------------------------------------*/
+
+static READ32_HANDLER(sh2_internal_a5)
+{
+ return 0xa5a5a5a5;
+}
+
+
+/*-------------------------------------------------
+ sh2_internal_map - maps SH2 built-ins
+-------------------------------------------------*/
+
+static ADDRESS_MAP_START( sh2_internal_map, ADDRESS_SPACE_PROGRAM, 32 )
+ AM_RANGE(0x40000000, 0xbfffffff) AM_READ(sh2_internal_a5)
+ AM_RANGE(0xe0000000, 0xffffffff) AM_READWRITE(sh2_internal_r, sh2_internal_w)
+ADDRESS_MAP_END
+
+/*-------------------------------------------------
+ sh2_set_info - set information about a given
+ CPU instance
+-------------------------------------------------*/
+
+static void sh2_set_info(UINT32 state, cpuinfo *info)
+{
+ switch (state)
+ {
+ /* --- the following bits of info are set as 64-bit signed integers --- */
+ case CPUINFO_INT_SH2_DRC_OPTIONS: sh2->drcoptions = info->i; break;
+
+ case CPUINFO_INT_SH2_PCFLUSH_SELECT: sh2->pcfsel = info->i; if (sh2->pcfsel > sh2->maxpcfsel) sh2->maxpcfsel = sh2->pcfsel; break;
+ case CPUINFO_INT_SH2_PCFLUSH_ADDR: sh2->pcflushes[sh2->pcfsel] = info->i; break;
+
+ case CPUINFO_INT_INPUT_STATE + SH2_INT_VBLIN: sh2_set_irq_line(SH2_INT_VBLIN, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + SH2_INT_VBLOUT: sh2_set_irq_line(SH2_INT_VBLOUT, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + SH2_INT_HBLIN: sh2_set_irq_line(SH2_INT_HBLIN, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + SH2_INT_TIMER0: sh2_set_irq_line(SH2_INT_TIMER0, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + SH2_INT_TIMER1: sh2_set_irq_line(SH2_INT_TIMER1, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + SH2_INT_DSP: sh2_set_irq_line(SH2_INT_DSP, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + SH2_INT_SOUND: sh2_set_irq_line(SH2_INT_SOUND, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + SH2_INT_SMPC: sh2_set_irq_line(SH2_INT_SMPC, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + SH2_INT_PAD: sh2_set_irq_line(SH2_INT_PAD, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + SH2_INT_DMA2: sh2_set_irq_line(SH2_INT_DMA2, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + SH2_INT_DMA1: sh2_set_irq_line(SH2_INT_DMA1, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + SH2_INT_DMA0: sh2_set_irq_line(SH2_INT_DMA0, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + SH2_INT_DMAILL: sh2_set_irq_line(SH2_INT_DMAILL, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + SH2_INT_SPRITE: sh2_set_irq_line(SH2_INT_SPRITE, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + SH2_INT_14: sh2_set_irq_line(SH2_INT_14, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + SH2_INT_15: sh2_set_irq_line(SH2_INT_15, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + SH2_INT_ABUS: sh2_set_irq_line(SH2_INT_ABUS, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + INPUT_LINE_NMI: sh2_set_irq_line(INPUT_LINE_NMI, info->i); break;
+
+ case CPUINFO_INT_REGISTER + SH2_PC:
+ case CPUINFO_INT_PC: sh2->pc = info->i; sh2->delay = 0; break;
+ case CPUINFO_INT_SP: sh2->r[15] = info->i; break;
+ case CPUINFO_INT_REGISTER + SH2_PR: sh2->pr = info->i; break;
+ case CPUINFO_INT_REGISTER + SH2_SR: sh2->sr = info->i; cfunc_checkirqs((void *)"sh2_set_reg"); break;
+ case CPUINFO_INT_REGISTER + SH2_GBR: sh2->gbr = info->i; break;
+ case CPUINFO_INT_REGISTER + SH2_VBR: sh2->vbr = info->i; break;
+ case CPUINFO_INT_REGISTER + SH2_MACH: sh2->mach = info->i; break;
+ case CPUINFO_INT_REGISTER + SH2_MACL: sh2->macl = info->i; break;
+ case CPUINFO_INT_REGISTER + SH2_R0: sh2->r[ 0] = info->i; break;
+ case CPUINFO_INT_REGISTER + SH2_R1: sh2->r[ 1] = info->i; break;
+ case CPUINFO_INT_REGISTER + SH2_R2: sh2->r[ 2] = info->i; break;
+ case CPUINFO_INT_REGISTER + SH2_R3: sh2->r[ 3] = info->i; break;
+ case CPUINFO_INT_REGISTER + SH2_R4: sh2->r[ 4] = info->i; break;
+ case CPUINFO_INT_REGISTER + SH2_R5: sh2->r[ 5] = info->i; break;
+ case CPUINFO_INT_REGISTER + SH2_R6: sh2->r[ 6] = info->i; break;
+ case CPUINFO_INT_REGISTER + SH2_R7: sh2->r[ 7] = info->i; break;
+ case CPUINFO_INT_REGISTER + SH2_R8: sh2->r[ 8] = info->i; break;
+ case CPUINFO_INT_REGISTER + SH2_R9: sh2->r[ 9] = info->i; break;
+ case CPUINFO_INT_REGISTER + SH2_R10: sh2->r[10] = info->i; break;
+ case CPUINFO_INT_REGISTER + SH2_R11: sh2->r[11] = info->i; break;
+ case CPUINFO_INT_REGISTER + SH2_R12: sh2->r[12] = info->i; break;
+ case CPUINFO_INT_REGISTER + SH2_R13: sh2->r[13] = info->i; break;
+ case CPUINFO_INT_REGISTER + SH2_R14: sh2->r[14] = info->i; break;
+ case CPUINFO_INT_REGISTER + SH2_R15: sh2->r[15] = info->i; break;
+ case CPUINFO_INT_REGISTER + SH2_EA: sh2->ea = info->i; break;
+
+ case CPUINFO_INT_SH2_FRT_INPUT: sh2_set_frt_input(cpu_getactivecpu(), info->i); break;
+
+ /* --- the following bits of info are set as pointers to data or functions --- */
+ case CPUINFO_PTR_SH2_FTCSR_READ_CALLBACK: sh2->ftcsr_read_callback = (void (*) (UINT32 ))info->f; break;
+ }
+}
+
+/*-------------------------------------------------
+ sh2_get_info - return information about a
+ given CPU instance
+-------------------------------------------------*/
+
+void sh2_get_info(UINT32 state, cpuinfo *info)
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case CPUINFO_INT_CONTEXT_SIZE: info->i = sizeof(SH2); break;
+ case CPUINFO_INT_INPUT_LINES: info->i = 16; break;
+ case CPUINFO_INT_DEFAULT_IRQ_VECTOR: info->i = 0; break;
+ case CPUINFO_INT_ENDIANNESS: info->i = CPU_IS_BE; break;
+ case CPUINFO_INT_CLOCK_MULTIPLIER: info->i = 1; break;
+ case CPUINFO_INT_CLOCK_DIVIDER: info->i = 1; break;
+ case CPUINFO_INT_MIN_INSTRUCTION_BYTES: info->i = 2; break;
+ case CPUINFO_INT_MAX_INSTRUCTION_BYTES: info->i = 2; break;
+ case CPUINFO_INT_MIN_CYCLES: info->i = 1; break;
+ case CPUINFO_INT_MAX_CYCLES: info->i = 4; break;
+
+ case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_PROGRAM: info->i = 32; break;
+ case CPUINFO_INT_ADDRBUS_WIDTH + ADDRESS_SPACE_PROGRAM: info->i = 32; break;
+ case CPUINFO_INT_ADDRBUS_SHIFT + ADDRESS_SPACE_PROGRAM: info->i = 0; break;
+ case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_DATA: info->i = 0; break;
+ case CPUINFO_INT_ADDRBUS_WIDTH + ADDRESS_SPACE_DATA: info->i = 0; break;
+ case CPUINFO_INT_ADDRBUS_SHIFT + ADDRESS_SPACE_DATA: info->i = 0; break;
+ case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_IO: info->i = 0; break;
+ case CPUINFO_INT_ADDRBUS_WIDTH + ADDRESS_SPACE_IO: info->i = 0; break;
+ case CPUINFO_INT_ADDRBUS_SHIFT + ADDRESS_SPACE_IO: info->i = 0; break;
+
+ // Internal maps
+ case CPUINFO_PTR_INTERNAL_MEMORY_MAP + ADDRESS_SPACE_PROGRAM: info->internal_map32 = address_map_sh2_internal_map; break;
+ case CPUINFO_PTR_INTERNAL_MEMORY_MAP + ADDRESS_SPACE_DATA: info->internal_map32 = NULL; break;
+ case CPUINFO_PTR_INTERNAL_MEMORY_MAP + ADDRESS_SPACE_IO: info->internal_map32 = NULL; break;
+
+ case CPUINFO_INT_INPUT_STATE + SH2_INT_VBLIN: info->i = sh2->irq_line_state[SH2_INT_VBLIN]; break;
+ case CPUINFO_INT_INPUT_STATE + SH2_INT_VBLOUT: info->i = sh2->irq_line_state[SH2_INT_VBLOUT]; break;
+ case CPUINFO_INT_INPUT_STATE + SH2_INT_HBLIN: info->i = sh2->irq_line_state[SH2_INT_HBLIN]; break;
+ case CPUINFO_INT_INPUT_STATE + SH2_INT_TIMER0: info->i = sh2->irq_line_state[SH2_INT_TIMER0]; break;
+ case CPUINFO_INT_INPUT_STATE + SH2_INT_TIMER1: info->i = sh2->irq_line_state[SH2_INT_TIMER1]; break;
+ case CPUINFO_INT_INPUT_STATE + SH2_INT_DSP: info->i = sh2->irq_line_state[SH2_INT_DSP]; break;
+ case CPUINFO_INT_INPUT_STATE + SH2_INT_SOUND: info->i = sh2->irq_line_state[SH2_INT_SOUND]; break;
+ case CPUINFO_INT_INPUT_STATE + SH2_INT_SMPC: info->i = sh2->irq_line_state[SH2_INT_SMPC]; break;
+ case CPUINFO_INT_INPUT_STATE + SH2_INT_PAD: info->i = sh2->irq_line_state[SH2_INT_PAD]; break;
+ case CPUINFO_INT_INPUT_STATE + SH2_INT_DMA2: info->i = sh2->irq_line_state[SH2_INT_DMA2]; break;
+ case CPUINFO_INT_INPUT_STATE + SH2_INT_DMA1: info->i = sh2->irq_line_state[SH2_INT_DMA1]; break;
+ case CPUINFO_INT_INPUT_STATE + SH2_INT_DMA0: info->i = sh2->irq_line_state[SH2_INT_DMA0]; break;
+ case CPUINFO_INT_INPUT_STATE + SH2_INT_DMAILL: info->i = sh2->irq_line_state[SH2_INT_DMAILL]; break;
+ case CPUINFO_INT_INPUT_STATE + SH2_INT_SPRITE: info->i = sh2->irq_line_state[SH2_INT_SPRITE]; break;
+ case CPUINFO_INT_INPUT_STATE + SH2_INT_14: info->i = sh2->irq_line_state[SH2_INT_14]; break;
+ case CPUINFO_INT_INPUT_STATE + SH2_INT_15: info->i = sh2->irq_line_state[SH2_INT_15]; break;
+ case CPUINFO_INT_INPUT_STATE + SH2_INT_ABUS: info->i = sh2->irq_line_state[SH2_INT_ABUS]; break;
+ case CPUINFO_INT_INPUT_STATE + INPUT_LINE_NMI: info->i = sh2->nmi_line_state; break;
+
+ case CPUINFO_INT_PREVIOUSPC: info->i = sh2->ppc; break;
+
+ case CPUINFO_INT_PC:
+ case CPUINFO_INT_REGISTER + SH2_PC: info->i = (sh2->delay) ? (sh2->delay & AM) : (sh2->pc & AM); break;
+ case CPUINFO_INT_SP: info->i = sh2->r[15]; break;
+ case CPUINFO_INT_REGISTER + SH2_PR: info->i = sh2->pr; break;
+ case CPUINFO_INT_REGISTER + SH2_SR: info->i = sh2->sr; break;
+ case CPUINFO_INT_REGISTER + SH2_GBR: info->i = sh2->gbr; break;
+ case CPUINFO_INT_REGISTER + SH2_VBR: info->i = sh2->vbr; break;
+ case CPUINFO_INT_REGISTER + SH2_MACH: info->i = sh2->mach; break;
+ case CPUINFO_INT_REGISTER + SH2_MACL: info->i = sh2->macl; break;
+ case CPUINFO_INT_REGISTER + SH2_R0: info->i = sh2->r[ 0]; break;
+ case CPUINFO_INT_REGISTER + SH2_R1: info->i = sh2->r[ 1]; break;
+ case CPUINFO_INT_REGISTER + SH2_R2: info->i = sh2->r[ 2]; break;
+ case CPUINFO_INT_REGISTER + SH2_R3: info->i = sh2->r[ 3]; break;
+ case CPUINFO_INT_REGISTER + SH2_R4: info->i = sh2->r[ 4]; break;
+ case CPUINFO_INT_REGISTER + SH2_R5: info->i = sh2->r[ 5]; break;
+ case CPUINFO_INT_REGISTER + SH2_R6: info->i = sh2->r[ 6]; break;
+ case CPUINFO_INT_REGISTER + SH2_R7: info->i = sh2->r[ 7]; break;
+ case CPUINFO_INT_REGISTER + SH2_R8: info->i = sh2->r[ 8]; break;
+ case CPUINFO_INT_REGISTER + SH2_R9: info->i = sh2->r[ 9]; break;
+ case CPUINFO_INT_REGISTER + SH2_R10: info->i = sh2->r[10]; break;
+ case CPUINFO_INT_REGISTER + SH2_R11: info->i = sh2->r[11]; break;
+ case CPUINFO_INT_REGISTER + SH2_R12: info->i = sh2->r[12]; break;
+ case CPUINFO_INT_REGISTER + SH2_R13: info->i = sh2->r[13]; break;
+ case CPUINFO_INT_REGISTER + SH2_R14: info->i = sh2->r[14]; break;
+ case CPUINFO_INT_REGISTER + SH2_R15: info->i = sh2->r[15]; break;
+ case CPUINFO_INT_REGISTER + SH2_EA: info->i = sh2->ea; break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_PTR_SET_INFO: info->setinfo = sh2_set_info; break;
+ case CPUINFO_PTR_GET_CONTEXT: info->getcontext = sh2_get_context; break;
+ case CPUINFO_PTR_SET_CONTEXT: info->setcontext = sh2_set_context; break;
+ case CPUINFO_PTR_INIT: info->init = sh2_init; break;
+ case CPUINFO_PTR_RESET: info->reset = sh2_reset; break;
+ case CPUINFO_PTR_EXECUTE: info->execute = sh2_execute; break;
+ case CPUINFO_PTR_BURN: info->burn = NULL; break;
+ case CPUINFO_PTR_DISASSEMBLE: info->disassemble = sh2_dasm; break;
+ case CPUINFO_PTR_INSTRUCTION_COUNTER: info->icount = &sh2->icount; break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case CPUINFO_STR_NAME: strcpy(info->s, "SH-2"); break;
+ case CPUINFO_STR_CORE_FAMILY: strcpy(info->s, "Hitachi SH7600"); break;
+ case CPUINFO_STR_CORE_VERSION: strcpy(info->s, "2.0"); break;
+ case CPUINFO_STR_CORE_FILE: strcpy(info->s, __FILE__); break;
+ case CPUINFO_STR_CORE_CREDITS: strcpy(info->s, "Copyright Nicola Salmoria and the MAME team, all rights reserved."); break;
+
+ case CPUINFO_STR_FLAGS:
+ sprintf(info->s, "%c%c%d%c%c",
+ sh2->sr & M ? 'M':'.',
+ sh2->sr & Q ? 'Q':'.',
+ (sh2->sr & I) >> 4,
+ sh2->sr & S ? 'S':'.',
+ sh2->sr & T ? 'T':'.');
+ break;
+
+ case CPUINFO_STR_REGISTER + SH2_PC: sprintf(info->s, "PC :%08X", sh2->pc); break;
+ case CPUINFO_STR_REGISTER + SH2_SR: sprintf(info->s, "SR :%08X", sh2->sr); break;
+ case CPUINFO_STR_REGISTER + SH2_PR: sprintf(info->s, "PR :%08X", sh2->pr); break;
+ case CPUINFO_STR_REGISTER + SH2_GBR: sprintf(info->s, "GBR :%08X", sh2->gbr); break;
+ case CPUINFO_STR_REGISTER + SH2_VBR: sprintf(info->s, "VBR :%08X", sh2->vbr); break;
+ case CPUINFO_STR_REGISTER + SH2_MACH: sprintf(info->s, "MACH:%08X", sh2->mach); break;
+ case CPUINFO_STR_REGISTER + SH2_MACL: sprintf(info->s, "MACL:%08X", sh2->macl); break;
+ case CPUINFO_STR_REGISTER + SH2_R0: sprintf(info->s, "R0 :%08X", sh2->r[ 0]); break;
+ case CPUINFO_STR_REGISTER + SH2_R1: sprintf(info->s, "R1 :%08X", sh2->r[ 1]); break;
+ case CPUINFO_STR_REGISTER + SH2_R2: sprintf(info->s, "R2 :%08X", sh2->r[ 2]); break;
+ case CPUINFO_STR_REGISTER + SH2_R3: sprintf(info->s, "R3 :%08X", sh2->r[ 3]); break;
+ case CPUINFO_STR_REGISTER + SH2_R4: sprintf(info->s, "R4 :%08X", sh2->r[ 4]); break;
+ case CPUINFO_STR_REGISTER + SH2_R5: sprintf(info->s, "R5 :%08X", sh2->r[ 5]); break;
+ case CPUINFO_STR_REGISTER + SH2_R6: sprintf(info->s, "R6 :%08X", sh2->r[ 6]); break;
+ case CPUINFO_STR_REGISTER + SH2_R7: sprintf(info->s, "R7 :%08X", sh2->r[ 7]); break;
+ case CPUINFO_STR_REGISTER + SH2_R8: sprintf(info->s, "R8 :%08X", sh2->r[ 8]); break;
+ case CPUINFO_STR_REGISTER + SH2_R9: sprintf(info->s, "R9 :%08X", sh2->r[ 9]); break;
+ case CPUINFO_STR_REGISTER + SH2_R10: sprintf(info->s, "R10 :%08X", sh2->r[10]); break;
+ case CPUINFO_STR_REGISTER + SH2_R11: sprintf(info->s, "R11 :%08X", sh2->r[11]); break;
+ case CPUINFO_STR_REGISTER + SH2_R12: sprintf(info->s, "R12 :%08X", sh2->r[12]); break;
+ case CPUINFO_STR_REGISTER + SH2_R13: sprintf(info->s, "R13 :%08X", sh2->r[13]); break;
+ case CPUINFO_STR_REGISTER + SH2_R14: sprintf(info->s, "R14 :%08X", sh2->r[14]); break;
+ case CPUINFO_STR_REGISTER + SH2_R15: sprintf(info->s, "R15 :%08X", sh2->r[15]); break;
+ case CPUINFO_STR_REGISTER + SH2_EA: sprintf(info->s, "EA :%08X", sh2->ea); break;
+
+ case CPUINFO_PTR_SH2_FTCSR_READ_CALLBACK: info->f = (genf*)sh2->ftcsr_read_callback; break;
+
+ }
+}
+
+#endif // USE_SH2DRC
diff --git a/src/emu/cpu/sh2/sh2fe.c b/src/emu/cpu/sh2/sh2fe.c
new file mode 100644
index 00000000000..f7ec3be0c47
--- /dev/null
+++ b/src/emu/cpu/sh2/sh2fe.c
@@ -0,0 +1,861 @@
+/***************************************************************************
+
+ sh2fe.c
+
+ Front end for SH-2 recompiler
+
+ Released for general non-commercial use under the MAME license
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+***************************************************************************/
+
+#include "cpuintrf.h"
+#include "sh2.h"
+#include "sh2comn.h"
+#include "cpu/drcfe.h"
+
+/***************************************************************************
+ FUNCTION PROTOTYPES
+***************************************************************************/
+
+static int describe_group_0(SH2 *context, opcode_desc *desc, const opcode_desc *prev, UINT16 opcode);
+static int describe_group_2(SH2 *context, opcode_desc *desc, const opcode_desc *prev, UINT16 opcode);
+static int describe_group_3(SH2 *context, opcode_desc *desc, const opcode_desc *prev, UINT16 opcode);
+static int describe_group_4(SH2 *context, opcode_desc *desc, const opcode_desc *prev, UINT16 opcode);
+static int describe_group_6(SH2 *context, opcode_desc *desc, const opcode_desc *prev, UINT16 opcode);
+static int describe_group_8(SH2 *context, opcode_desc *desc, const opcode_desc *prev, UINT16 opcode);
+static int describe_group_12(SH2 *context, opcode_desc *desc, const opcode_desc *prev, UINT16 opcode);
+
+/***************************************************************************
+ INSTRUCTION PARSERS
+***************************************************************************/
+
+/*-------------------------------------------------
+ describe_instruction - build a description
+ of a single instruction
+-------------------------------------------------*/
+
+int sh2_describe(void *param, opcode_desc *desc, const opcode_desc *prev)
+{
+ UINT16 opcode = *desc->opptr.w;
+ SH2 *context = (SH2 *)param;
+
+ /* 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(context, desc, prev, opcode);
+ break;
+
+ case 1: // MOVLS4
+ desc->regin[0] |= REGFLAG_R(Rn) | REGFLAG_R(Rm);
+ desc->flags |= OPFLAG_WRITES_MEMORY;
+ return TRUE;
+ break;
+
+ case 2:
+ return describe_group_2(context, desc, prev, opcode);
+ break;
+
+ case 3:
+ return describe_group_3(context, desc, prev, opcode);
+ break;
+
+ case 4:
+ return describe_group_4(context, desc, prev, opcode);
+ break;
+
+ case 5: // MOVLL4
+ desc->regin[0] |= REGFLAG_R(Rm);
+ desc->regout[0] |= REGFLAG_R(Rn);
+ desc->flags |= OPFLAG_READS_MEMORY;
+ return TRUE;
+ break;
+
+ case 6:
+ return describe_group_6(context, desc, prev, opcode);
+ break;
+
+ case 7: // ADDI
+ desc->regin[0] |= REGFLAG_R(Rn);
+ desc->regout[0] |= REGFLAG_R(Rn);
+ return TRUE;
+ break;
+
+ case 8:
+ return describe_group_8(context, desc, prev, opcode);
+ break;
+
+ case 9: // MOVWI
+ desc->regout[0] |= REGFLAG_R(Rn);
+ desc->flags |= OPFLAG_READS_MEMORY;
+ return TRUE;
+ break;
+
+ 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 disp = ((INT32)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;
+ }
+ break;
+
+ case 12:
+ return describe_group_12(context, desc, prev, opcode);
+ break;
+
+ case 13: // MOVLI
+ desc->regout[0] |= REGFLAG_R(Rn);
+ desc->flags |= OPFLAG_READS_MEMORY;
+ return TRUE;
+ break;
+
+ case 14: // MOVI
+ desc->regout[0] |= REGFLAG_R(Rn);
+ return TRUE;
+ break;
+
+ case 15: // NOP
+ return TRUE;
+ break;
+ }
+
+ return FALSE;
+}
+
+static int describe_group_0(SH2 *context, opcode_desc *desc, const opcode_desc *prev, UINT16 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;
+ break;
+
+ case 0x02: // STCSR(Rn);
+ desc->regout[0] |= REGFLAG_R(Rn);
+ return TRUE;
+ break;
+
+ 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;
+ break;
+
+ 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;
+ break;
+
+ 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;
+ break;
+
+ case 0x08: // CLRT();
+ desc->regout[1] |= REGFLAG_SR;
+ return TRUE;
+ break;
+
+ case 0x0a: // STSMACH(Rn);
+ desc->regout[0] |= REGFLAG_R(Rn);
+ desc->regout[1] |= REGFLAG_MACH;
+ return TRUE;
+ break;
+
+ 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;
+ break;
+
+ 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;
+ break;
+
+ 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;
+ break;
+
+ case 0x12: // STCGBR(Rn);
+ desc->regout[0] |= REGFLAG_R(Rn);
+ desc->regin[1] |= REGFLAG_GBR;
+ return TRUE;
+ break;
+
+ case 0x18: // SETT();
+ desc->regout[1] |= REGFLAG_SR;
+ return TRUE;
+ break;
+
+ case 0x19: // DIV0U();
+ desc->regout[1] |= REGFLAG_SR;
+ return TRUE;
+ break;
+
+ case 0x1a: // STSMACL(Rn);
+ desc->regin[1] |= REGFLAG_MACL;
+ desc->regout[0] |= REGFLAG_R(Rn);
+ return TRUE;
+ break;
+
+ case 0x1b: // SLEEP();
+ desc->cycles = 3;
+ return TRUE;
+ break;
+
+ case 0x22: // STCVBR(Rn);
+ desc->regin[0] |= REGFLAG_R(Rn);
+ desc->regout[1] |= REGFLAG_VBR;
+ return TRUE;
+ break;
+
+ 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;
+ break;
+
+ case 0x28: // CLRMAC();
+ desc->regout[1] |= REGFLAG_MACL | REGFLAG_MACH;
+ return TRUE;
+ break;
+
+ case 0x29: // MOVT(Rn);
+ desc->regin[1] |= REGFLAG_SR;
+ desc->regout[0] |= REGFLAG_R(Rn);
+ return TRUE;
+ break;
+
+ case 0x2a: // STSPR(Rn);
+ desc->regin[1] |= REGFLAG_PR;
+ desc->regout[0] |= REGFLAG_R(Rn);
+ return TRUE;
+ break;
+
+ 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;
+ break;
+ }
+
+ return FALSE;
+}
+
+static int describe_group_2(SH2 *context, opcode_desc *desc, const opcode_desc *prev, UINT16 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;
+ break;
+
+ case 3: // NOP();
+ return TRUE;
+ break;
+
+ 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;
+ break;
+
+ 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;
+ break;
+
+ 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;
+ break;
+
+ 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;
+ break;
+ }
+
+ return FALSE;
+}
+
+static int describe_group_3(SH2 *context, opcode_desc *desc, const opcode_desc *prev, UINT16 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;
+ break;
+
+ case 1: // NOP();
+ case 9: // NOP();
+ return TRUE;
+ break;
+
+ 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;
+ break;
+
+ 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;
+ break;
+
+ 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;
+ break;
+
+ 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;
+ break;
+ }
+ return FALSE;
+}
+
+static int describe_group_4(SH2 *context, opcode_desc *desc, const opcode_desc *prev, UINT16 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;
+ break;
+
+ 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;
+ break;
+
+ 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;
+ break;
+
+ 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;
+ break;
+
+ 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;
+ break;
+
+ 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;
+ break;
+
+ case 0x0a: // LDSMACH(Rn);
+ desc->regin[0] |= REGFLAG_R(Rn);
+ desc->regout[1] |= REGFLAG_MACH;
+ return TRUE;
+ break;
+
+ 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;
+ break;
+
+ 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;
+ break;
+
+ 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;
+ break;
+
+ 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;
+ break;
+
+ 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;
+ break;
+
+ 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;
+ break;
+
+ 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;
+ break;
+
+ 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;
+ break;
+
+ 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;
+ break;
+
+ case 0x1a: // LDSMACL(Rn);
+ desc->regin[0] |= REGFLAG_R(Rn);
+ desc->regout[1] |= REGFLAG_MACL;
+ return TRUE;
+ break;
+
+ 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;
+ break;
+
+ case 0x1e: // LDCGBR(Rn);
+ desc->regin[0] |= REGFLAG_R(Rn);
+ desc->regout[1] |= REGFLAG_GBR;
+ return TRUE;
+ break;
+
+ 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;
+ break;
+
+ 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;
+ break;
+
+ 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;
+ break;
+
+ 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;
+ break;
+
+ 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;
+ break;
+
+ 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;
+ break;
+
+ case 0x2a: // LDSPR(Rn);
+ desc->regin[0] |= REGFLAG_R(Rn);
+ desc->regout[1] |= REGFLAG_PR;
+ return TRUE;
+ break;
+
+ 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;
+ break;
+
+ case 0x2e: // LDCVBR(Rn);
+ desc->regin[0] |= REGFLAG_R(Rn);
+ desc->regout[1] |= REGFLAG_VBR;
+ return TRUE;
+ break;
+
+ 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;
+ break;
+
+ }
+
+ return FALSE;
+}
+
+static int describe_group_6(SH2 *context, opcode_desc *desc, const opcode_desc *prev, UINT16 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;
+ break;
+
+ 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;
+ break;
+
+ case 8: // SWAPB(Rm, Rn);
+ desc->regin[0] |= REGFLAG_R(Rm) | REGFLAG_R(Rn);
+ desc->regout[0] |= REGFLAG_R(Rn);
+ return TRUE;
+ break;
+
+ case 10: // NEGC(Rm, Rn);
+ desc->regin[0] |= REGFLAG_R(Rm);
+ desc->regout[0] |= REGFLAG_R(Rn);
+ desc->regout[1] |= REGFLAG_SR;
+ return TRUE;
+ break;
+ }
+ return FALSE;
+}
+
+static int describe_group_8(SH2 *context, opcode_desc *desc, const opcode_desc *prev, UINT16 opcode)
+{
+ INT32 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;
+ break;
+
+ 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;
+ break;
+
+ 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;
+ break;
+
+ case 8<< 8: // CMPIM(opcode & 0xff);
+ desc->regin[0] |= REGFLAG_R(Rm);
+ desc->regin[1] |= REGFLAG_SR;
+ desc->regout[1] |= REGFLAG_SR;
+ return TRUE;
+ break;
+
+ case 9<< 8: // BT(opcode & 0xff);
+ case 11<< 8: // BF(opcode & 0xff);
+ desc->flags |= OPFLAG_IS_CONDITIONAL_BRANCH;
+ desc->cycles = 3;
+ disp = ((INT32)opcode << 24) >> 24;
+ desc->targetpc = (desc->pc + 2) + disp * 2 + 2;
+ return TRUE;
+ break;
+
+ case 13<< 8: // BTS(opcode & 0xff);
+ case 15<< 8: // BFS(opcode & 0xff);
+ desc->flags |= OPFLAG_IS_CONDITIONAL_BRANCH;
+ desc->cycles = 2;
+ disp = ((INT32)opcode << 24) >> 24;
+ desc->targetpc = (desc->pc + 2) + disp * 2 + 2;
+ desc->delayslots = 1;
+ return TRUE;
+ break;
+ }
+
+ return FALSE;
+}
+
+static int describe_group_12(SH2 *context, opcode_desc *desc, const opcode_desc *prev, UINT16 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;
+ break;
+
+ 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;
+ break;
+
+ 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;
+ break;
+
+ case 8<<8: // TSTI(opcode & 0xff);
+ desc->regin[0] |= REGFLAG_R(0);
+ desc->regin[1] |= REGFLAG_SR;
+ desc->regout[1] |= REGFLAG_SR;
+ return TRUE;
+ break;
+
+ 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;
+ break;
+
+ 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;
+ break;
+ }
+
+ return FALSE;
+}
+
diff --git a/src/mame/drivers/cps3.c b/src/mame/drivers/cps3.c
index 03873d013bd..497ba64d648 100644
--- a/src/mame/drivers/cps3.c
+++ b/src/mame/drivers/cps3.c
@@ -726,15 +726,15 @@ static void cps3_decrypt_bios(running_machine *machine)
#endif
}
-
-
-
static DRIVER_INIT( cps3crpt )
{
const char *gamename = machine->gamedrv->name;
const struct game_keys2 *k = &keys_table2[0];
int i;
+ // set strict verify
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_DRC_OPTIONS, SH2DRC_STRICT_VERIFY);
+
cps3_key1 = -1;
cps3_key2 = -1;
cps3_isSpecial = -1;
@@ -1578,25 +1578,25 @@ struct cps3_test_hacks
static const struct cps3_test_hacks testhack_table[] =
{
// name mainram address code address
- { "jojo", 0x0011c2c, 0x6172568 },
- { "jojon", 0x0011c2c, 0x6172568 },
- { "jojoalt", 0x0011c2c, 0x6172798 },
- { "jojoaltn", 0x0011c2c, 0x6172798 },
- { "jojoba", 0x0011c90, 0x61c45bc },
- { "jojoban", 0x0011c90, 0x61c45bc },
- { "jojobane", 0x0011c90, 0x61c45bc },
- { "sfiii", 0x00166b4, 0x63cdff4 },
- { "sfiiiu", 0x00166b4, 0x63cdff4 },
- { "sfiiin", 0x00166b4, 0x63cdff4 },
+ { "jojo", 0x0011c2a, 0x6172566 },
+ { "jojon", 0x0011c2a, 0x6172566 },
+ { "jojoalt", 0x0011c2a, 0x6172796 },
+ { "jojoaltn", 0x0011c2a, 0x6172796 },
+ { "jojoba", 0x0011c8e, 0x61c45ba },
+ { "jojoban", 0x0011c8e, 0x61c45ba },
+ { "jojobane", 0x0011c8e, 0x61c45ba },
+ { "sfiii", 0x00166b2, 0x63cdff2 },
+ { "sfiiiu", 0x00166b2, 0x63cdff2 },
+ { "sfiiin", 0x00166b2, 0x63cdff2 },
{ "sfiii2", 0, 0 },
{ "sfiii2u", 0, 0 },
{ "sfiii2n", 0, 0 },
- { "sfiii3", 0x0011c44, 0x613a9fc },
- { "sfiii3n", 0x0011c44, 0x613a9fc },
- { "sfiii3a", 0x0011c44, 0x613ab48 },
- { "sfiii3an", 0x0011c44, 0x613ab48 },
- { "warzard", 0x0016530, 0x60105f0 },
- { "redearth", 0x0016530, 0x60105f0 },
+ { "sfiii3", 0x0011c42, 0x613a9fa },
+ { "sfiii3n", 0x0011c42, 0x613a9fa },
+ { "sfiii3a", 0x0011c42, 0x613ab46 },
+ { "sfiii3an", 0x0011c42, 0x613ab46 },
+ { "warzard", 0x001652e, 0x60105ee },
+ { "redearth", 0x001652e, 0x60105ee },
{ 0 } // end of table
};
@@ -1614,6 +1614,12 @@ static DRIVER_INIT( cps3_testhacks )
{
cps3_bios_test_hack = k->bios_test_hack;
cps3_game_test_hack = k->game_test_hack;
+
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_PCFLUSH_SELECT, 1);
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_PCFLUSH_ADDR, cps3_bios_test_hack);
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_PCFLUSH_SELECT, 2);
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_PCFLUSH_ADDR, cps3_game_test_hack);
+
break;
}
++k;
@@ -2980,25 +2986,25 @@ struct cps3_speedups
static const struct cps3_speedups speedup_table[] =
{
// name mainram address code address
- { "jojo", 0x223c0, 0x600065c },
- { "jojon", 0x223c0, 0x600065c },
- { "jojoalt", 0x223d8, 0x600065c },
- { "jojoaltn", 0x223d8, 0x600065c },
- { "jojoba", 0x267dc, 0x600065c },
- { "jojoban", 0x267dc, 0x600065c },
- { "jojobane", 0x267dc, 0x600065c },
- { "sfiii", 0x0cc6c, 0x6000884 },
- { "sfiiiu", 0x0cc6c, 0x6000884 },
- { "sfiiin", 0x0cc6c, 0x6000884 },
- { "sfiii2", 0x0dfe4, 0x6000884 },
- { "sfiii2u", 0x0dfe4, 0x6000884 },
- { "sfiii2n", 0x0dfe4, 0x6000884 },
- { "sfiii3", 0x0d794, 0x6000884 },
- { "sfiii3n", 0x0d794, 0x6000884 },
- { "sfiii3a", 0x0d794, 0x6000884 },
- { "sfiii3an", 0x0d794, 0x6000884 },
- { "warzard", 0x2136c, 0x600194e },
- { "redearth", 0x2136c, 0x600194e },
+ { "jojo", 0x223c0, 0x600065a },
+ { "jojon", 0x223c0, 0x600065a },
+ { "jojoalt", 0x223d8, 0x600065a },
+ { "jojoaltn", 0x223d8, 0x600065a },
+ { "jojoba", 0x267dc, 0x600065a },
+ { "jojoban", 0x267dc, 0x600065a },
+ { "jojobane", 0x267dc, 0x600065a },
+ { "sfiii", 0x0cc6c, 0x6000882 },
+ { "sfiiiu", 0x0cc6c, 0x6000882 },
+ { "sfiiin", 0x0cc6c, 0x6000882 },
+ { "sfiii2", 0x0dfe4, 0x6000882 },
+ { "sfiii2u", 0x0dfe4, 0x6000882 },
+ { "sfiii2n", 0x0dfe4, 0x6000882 },
+ { "sfiii3", 0x0d794, 0x6000882 },
+ { "sfiii3n", 0x0d794, 0x6000882 },
+ { "sfiii3a", 0x0d794, 0x6000882 },
+ { "sfiii3an", 0x0d794, 0x6000882 },
+ { "warzard", 0x2136c, 0x600194c },
+ { "redearth", 0x2136c, 0x600194c },
{ 0 } // end of table
};
@@ -3032,7 +3038,13 @@ static DRIVER_INIT( cps3_speedups )
//printf("speedup %08x %08x\n",cps3_speedup_ram_address,cps3_speedup_code_address);
- if (cps3_speedup_code_address!=0) memory_install_read32_handler(machine, 0, ADDRESS_SPACE_PROGRAM, cps3_speedup_ram_address+0x02000000, cps3_speedup_ram_address+0x02000003, 0, 0, cps3_speedup_r );
+ if (cps3_speedup_code_address!=0)
+ {
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_PCFLUSH_SELECT, 0);
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_PCFLUSH_ADDR, cps3_speedup_code_address);
+
+ memory_install_read32_handler(machine, 0, ADDRESS_SPACE_PROGRAM, cps3_speedup_ram_address+0x02000000, cps3_speedup_ram_address+0x02000003, 0, 0, cps3_speedup_r );
+ }
}
diff --git a/src/mame/drivers/psikyosh.c b/src/mame/drivers/psikyosh.c
index 8362a0c9b71..9f1c8222811 100644
--- a/src/mame/drivers/psikyosh.c
+++ b/src/mame/drivers/psikyosh.c
@@ -1095,8 +1095,8 @@ PC : 0001AE7C: MOV.L @R3,R0
PC : 0001AE7E: TST R0,R0
PC : 0001AE80: BT $0001AE74
*/
- if (activecpu_get_pc()==0x0001AFAC) cpu_spinuntil_int(); // Character Select + InGame
- if (activecpu_get_pc()==0x0001AE76) cpu_spinuntil_int(); // Everything Else?
+ if (activecpu_get_pc()==0x0001AFAA) cpu_spinuntil_int(); // Character Select + InGame
+ if (activecpu_get_pc()==0x0001AE74) cpu_spinuntil_int(); // Everything Else?
return psh_ram[0x00000C/4];
}
@@ -1112,9 +1112,9 @@ PC : 0609FC70: MOV.L @R3,R0 // whats there into r0
PC : 0609FC72: TST R0,R0 // test
PC : 0609FC74: BT $0609FC68
*/
- if (activecpu_get_pc()==0x609FC6A) cpu_spinuntil_int(); // Title Screens
- if (activecpu_get_pc()==0x609FED4) cpu_spinuntil_int(); // In Game
- if (activecpu_get_pc()==0x60A0172) cpu_spinuntil_int(); // Attract Demo
+ if (activecpu_get_pc()==0x609FC68) cpu_spinuntil_int(); // Title Screens
+ if (activecpu_get_pc()==0x609FED2) cpu_spinuntil_int(); // In Game
+ if (activecpu_get_pc()==0x60A0170) cpu_spinuntil_int(); // Attract Demo
return psh_ram[0x00000C/4];
}
@@ -1131,8 +1131,8 @@ PC : 00047622: MOV.L @R3,R0
PC : 00047624: TST R0,R0
PC : 00047626: BT $00047618
*/
- if (activecpu_get_pc()==0x0004761C) cpu_spinuntil_int(); // title
- if (activecpu_get_pc()==0x00047978) cpu_spinuntil_int(); // ingame
+ if (activecpu_get_pc()==0x0004761a) cpu_spinuntil_int(); // title
+ if (activecpu_get_pc()==0x00047976) cpu_spinuntil_int(); // ingame
return psh_ram[0x00000C/4];
}
@@ -1148,9 +1148,9 @@ PC : 060A10F4: MOV.L @R1,R2
PC : 060A10F6: TST R2,R2
PC : 060A10F8: BT $060A10EC
*/
- if (activecpu_get_pc()==0x060A10EE) cpu_spinuntil_int(); // title
- if (activecpu_get_pc()==0x060A165A) cpu_spinuntil_int(); // attract
- if (activecpu_get_pc()==0x060A1382) cpu_spinuntil_int(); // game
+ if (activecpu_get_pc()==0x060A10EC) cpu_spinuntil_int(); // title
+ if (activecpu_get_pc()==0x060A1658) cpu_spinuntil_int(); // attract
+ if (activecpu_get_pc()==0x060A1380) cpu_spinuntil_int(); // game
return psh_ram[0x00000C/4];
}
@@ -1166,19 +1166,19 @@ PC : 0602897A: MOV.L @R1,R2
PC : 0602897C: TST R2,R2
PC : 0602897E: BT $06028972
*/
- if (activecpu_get_pc()==0x06028974) cpu_spinuntil_int();
- if (activecpu_get_pc()==0x06028E64) cpu_spinuntil_int();
- if (activecpu_get_pc()==0x06028BE6) cpu_spinuntil_int();
+ if (activecpu_get_pc()==0x06028972) cpu_spinuntil_int();
+ if (activecpu_get_pc()==0x06028E62) cpu_spinuntil_int();
+ if (activecpu_get_pc()==0x06028BE4) cpu_spinuntil_int();
return psh_ram[0x04000C/4];
}
static READ32_HANDLER( s1945iii_speedup_r )
{
- if (activecpu_get_pc()==0x0602B464) cpu_spinuntil_int(); // start up text
- if (activecpu_get_pc()==0x0602B6E2) cpu_spinuntil_int(); // intro attract
- if (activecpu_get_pc()==0x0602BC1E) cpu_spinuntil_int(); // game attract
- if (activecpu_get_pc()==0x0602B97C) cpu_spinuntil_int(); // game
+ if (activecpu_get_pc()==0x0602B462) cpu_spinuntil_int(); // start up text
+ if (activecpu_get_pc()==0x0602B6E0) cpu_spinuntil_int(); // intro attract
+ if (activecpu_get_pc()==0x0602BC1C) cpu_spinuntil_int(); // game attract
+ if (activecpu_get_pc()==0x0602B97A) cpu_spinuntil_int(); // game
return psh_ram[0x06000C/4];
}
@@ -1186,10 +1186,10 @@ static READ32_HANDLER( s1945iii_speedup_r )
static READ32_HANDLER( dragnblz_speedup_r )
{
- if (activecpu_get_pc()==0x06027440) cpu_spinuntil_int(); // startup texts
- if (activecpu_get_pc()==0x060276E6) cpu_spinuntil_int(); // attract intro
- if (activecpu_get_pc()==0x06027C74) cpu_spinuntil_int(); // attract game
- if (activecpu_get_pc()==0x060279A8) cpu_spinuntil_int(); // game
+ if (activecpu_get_pc()==0x0602743e) cpu_spinuntil_int(); // startup texts
+ if (activecpu_get_pc()==0x060276e4) cpu_spinuntil_int(); // attract intro
+ if (activecpu_get_pc()==0x06027C72) cpu_spinuntil_int(); // attract game
+ if (activecpu_get_pc()==0x060279A6) cpu_spinuntil_int(); // game
return psh_ram[0x006000C/4];
}
@@ -1206,10 +1206,10 @@ PC :0602CAF0: TST R2,R2
PC :0602CAF2: BT $0602CAE6
*/
- if (activecpu_get_pc()==0x0602CAE8) cpu_spinuntil_int(); // title logos
- if (activecpu_get_pc()==0x0602CD88) cpu_spinuntil_int(); // attract intro
- if (activecpu_get_pc()==0x0602D2F0) cpu_spinuntil_int(); // game attract
- if (activecpu_get_pc()==0x0602D042) cpu_spinuntil_int(); // game play
+ if (activecpu_get_pc()==0x0602CAE6) cpu_spinuntil_int(); // title logos
+ if (activecpu_get_pc()==0x0602CD86) cpu_spinuntil_int(); // attract intro
+ if (activecpu_get_pc()==0x0602D2ee) cpu_spinuntil_int(); // game attract
+ if (activecpu_get_pc()==0x0602D040) cpu_spinuntil_int(); // game play
return psh_ram[0x006000C/4];
}
@@ -1217,24 +1217,34 @@ PC :0602CAF2: BT $0602CAE6
static READ32_HANDLER( mjgtaste_speedup_r )
{
- if (activecpu_get_pc()==0x6031f04) {cpu_spinuntil_int();return psh_ram[0x006000C/4];} // title logos
- if (activecpu_get_pc()==0x603214c) {cpu_spinuntil_int();return psh_ram[0x006000C/4];} // attract game
+ if (activecpu_get_pc()==0x6031f02) {cpu_spinuntil_int();return psh_ram[0x006000C/4];} // title logos
+ if (activecpu_get_pc()==0x603214a) {cpu_spinuntil_int();return psh_ram[0x006000C/4];} // attract game
// mame_printf_debug("at %08x\n",activecpu_get_pc());
return psh_ram[0x006000C/4];
}
-
-
static DRIVER_INIT( soldivid )
{
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_DRC_OPTIONS, SH2DRC_FASTEST_OPTIONS);
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_PCFLUSH_SELECT, 0);
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_PCFLUSH_ADDR, 0x1afaa);
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_PCFLUSH_SELECT, 1);
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_PCFLUSH_ADDR, 0x1ae74);
memory_install_read32_handler(machine, 0, ADDRESS_SPACE_PROGRAM, 0x600000c, 0x600000f, 0, 0, soldivid_speedup_r );
use_factory_eeprom=eeprom_0;
}
static DRIVER_INIT( s1945ii )
{
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_DRC_OPTIONS, SH2DRC_FASTEST_OPTIONS);
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_PCFLUSH_SELECT, 0);
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_PCFLUSH_ADDR, 0x609fc68);
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_PCFLUSH_SELECT, 1);
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_PCFLUSH_ADDR, 0x609fed2);
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_PCFLUSH_SELECT, 2);
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_PCFLUSH_ADDR, 0x60a0170);
memory_install_read32_handler(machine, 0, ADDRESS_SPACE_PROGRAM, 0x600000c, 0x600000f, 0, 0, s1945ii_speedup_r );
use_factory_eeprom=eeprom_DEFAULT;
}
@@ -1242,6 +1252,11 @@ static DRIVER_INIT( s1945ii )
static DRIVER_INIT( daraku )
{
UINT8 *RAM = memory_region(machine, REGION_CPU1);
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_DRC_OPTIONS, SH2DRC_FASTEST_OPTIONS);
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_PCFLUSH_SELECT, 0);
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_PCFLUSH_ADDR, 0x4761a);
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_PCFLUSH_SELECT, 1);
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_PCFLUSH_ADDR, 0x47976);
memory_set_bankptr(1,&RAM[0x100000]);
memory_install_read32_handler(machine, 0, ADDRESS_SPACE_PROGRAM, 0x600000c, 0x600000f, 0, 0, daraku_speedup_r );
use_factory_eeprom=eeprom_DARAKU;
@@ -1249,6 +1264,13 @@ static DRIVER_INIT( daraku )
static DRIVER_INIT( sbomberb )
{
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_DRC_OPTIONS, SH2DRC_FASTEST_OPTIONS);
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_PCFLUSH_SELECT, 0);
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_PCFLUSH_ADDR, 0x60a10ec);
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_PCFLUSH_SELECT, 1);
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_PCFLUSH_ADDR, 0x60a1658);
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_PCFLUSH_SELECT, 2);
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_PCFLUSH_ADDR, 0x60a1380);
memory_install_read32_handler(machine, 0, ADDRESS_SPACE_PROGRAM, 0x600000c, 0x600000f, 0, 0, sbomberb_speedup_r );
use_factory_eeprom=eeprom_DEFAULT;
}
@@ -1256,6 +1278,13 @@ static DRIVER_INIT( sbomberb )
static DRIVER_INIT( gunbird2 )
{
UINT8 *RAM = memory_region(machine, REGION_CPU1);
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_DRC_OPTIONS, SH2DRC_FASTEST_OPTIONS);
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_PCFLUSH_SELECT, 0);
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_PCFLUSH_ADDR, 0x6028972);
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_PCFLUSH_SELECT, 1);
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_PCFLUSH_ADDR, 0x6028e62);
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_PCFLUSH_SELECT, 2);
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_PCFLUSH_ADDR, 0x6028be4);
memory_set_bankptr(1,&RAM[0x100000]);
memory_install_read32_handler(machine, 0, ADDRESS_SPACE_PROGRAM, 0x604000c, 0x604000f, 0, 0, gunbird2_speedup_r );
use_factory_eeprom=eeprom_DEFAULT;
@@ -1264,6 +1293,15 @@ static DRIVER_INIT( gunbird2 )
static DRIVER_INIT( s1945iii )
{
UINT8 *RAM = memory_region(machine, REGION_CPU1);
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_DRC_OPTIONS, SH2DRC_FASTEST_OPTIONS);
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_PCFLUSH_SELECT, 0);
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_PCFLUSH_ADDR, 0x602b462);
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_PCFLUSH_SELECT, 1);
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_PCFLUSH_ADDR, 0x602b6e0);
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_PCFLUSH_SELECT, 2);
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_PCFLUSH_ADDR, 0x602bc1c);
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_PCFLUSH_SELECT, 3);
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_PCFLUSH_ADDR, 0x602b97a);
memory_set_bankptr(1,&RAM[0x100000]);
memory_install_read32_handler(machine, 0, ADDRESS_SPACE_PROGRAM, 0x606000c, 0x606000f, 0, 0, s1945iii_speedup_r );
use_factory_eeprom=eeprom_S1945III;
@@ -1271,18 +1309,41 @@ static DRIVER_INIT( s1945iii )
static DRIVER_INIT( dragnblz )
{
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_DRC_OPTIONS, SH2DRC_FASTEST_OPTIONS);
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_PCFLUSH_SELECT, 0);
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_PCFLUSH_ADDR, 0x602743e);
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_PCFLUSH_SELECT, 1);
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_PCFLUSH_ADDR, 0x60276e4);
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_PCFLUSH_SELECT, 2);
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_PCFLUSH_ADDR, 0x6027c72);
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_PCFLUSH_SELECT, 3);
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_PCFLUSH_ADDR, 0x60279a6);
memory_install_read32_handler(machine, 0, ADDRESS_SPACE_PROGRAM, 0x606000c, 0x606000f, 0, 0, dragnblz_speedup_r );
use_factory_eeprom=eeprom_DRAGNBLZ;
}
static DRIVER_INIT( gnbarich )
{
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_DRC_OPTIONS, SH2DRC_FASTEST_OPTIONS);
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_PCFLUSH_SELECT, 0);
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_PCFLUSH_ADDR, 0x602cae6);
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_PCFLUSH_SELECT, 1);
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_PCFLUSH_ADDR, 0x602cd86);
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_PCFLUSH_SELECT, 2);
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_PCFLUSH_ADDR, 0x602d2ee);
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_PCFLUSH_SELECT, 3);
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_PCFLUSH_ADDR, 0x602d040);
memory_install_read32_handler(machine, 0, ADDRESS_SPACE_PROGRAM, 0x606000c, 0x606000f, 0, 0, gnbarich_speedup_r );
use_factory_eeprom=eeprom_GNBARICH;
}
static DRIVER_INIT( mjgtaste )
{
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_DRC_OPTIONS, SH2DRC_FASTEST_OPTIONS);
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_PCFLUSH_SELECT, 0);
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_PCFLUSH_ADDR, 0x6031f02);
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_PCFLUSH_SELECT, 1);
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_PCFLUSH_ADDR, 0x603214a);
memory_install_read32_handler(machine, 0, ADDRESS_SPACE_PROGRAM, 0x606000c, 0x606000f, 0, 0, mjgtaste_speedup_r );
use_factory_eeprom=eeprom_MJGTASTE;
/* needs to install mahjong controls too (can select joystick in test mode tho) */
diff --git a/src/mame/drivers/stv.c b/src/mame/drivers/stv.c
index a99be68c552..c4952c8761c 100644
--- a/src/mame/drivers/stv.c
+++ b/src/mame/drivers/stv.c
@@ -2019,7 +2019,7 @@ static READ32_HANDLER( stv_sh2_random_r )
#endif
static ADDRESS_MAP_START( stv_mem, ADDRESS_SPACE_PROGRAM, 32 )
- AM_RANGE(0x00000000, 0x0007ffff) AM_ROM // bios
+ AM_RANGE(0x00000000, 0x0007ffff) AM_ROM AM_SHARE(6) // bios
AM_RANGE(0x00100000, 0x0010007f) AM_READWRITE(stv_SMPC_r32, stv_SMPC_w32)
AM_RANGE(0x00180000, 0x0018ffff) AM_RAM AM_SHARE(1) AM_BASE(&stv_backupram)
AM_RANGE(0x00200000, 0x002fffff) AM_RAM AM_MIRROR(0x100000) AM_SHARE(2) AM_BASE(&stv_workram_l)
@@ -2028,7 +2028,7 @@ static ADDRESS_MAP_START( stv_mem, ADDRESS_SPACE_PROGRAM, 32 )
AM_RANGE(0x01406f40, 0x01406f43) AM_WRITE(minit_w) // prikura seems to write here ..
// AM_RANGE(0x01000000, 0x01000003) AM_WRITE(minit_w) AM_MIRROR(0x00080000)
AM_RANGE(0x01800000, 0x01800003) AM_WRITE(sinit_w)
- AM_RANGE(0x02000000, 0x04ffffff) AM_ROM AM_ROMBANK(1) AM_REGION(REGION_USER1, 0) // cartridge
+ AM_RANGE(0x02000000, 0x04ffffff) AM_ROM AM_ROMBANK(1) AM_SHARE(7) AM_REGION(REGION_USER1, 0) // cartridge
AM_RANGE(0x05800000, 0x0589ffff) AM_READWRITE(stvcd_r, stvcd_w)
/* Sound */
AM_RANGE(0x05a00000, 0x05a7ffff) AM_READWRITE(stv_sh2_soundram_r, stv_sh2_soundram_w)
@@ -2047,6 +2047,8 @@ static ADDRESS_MAP_START( stv_mem, ADDRESS_SPACE_PROGRAM, 32 )
AM_RANGE(0x05f80000, 0x05fbffff) AM_READWRITE(stv_vdp2_regs_r, stv_vdp2_regs_w)
AM_RANGE(0x05fe0000, 0x05fe00cf) AM_READWRITE(stv_scu_r32, stv_scu_w32)
AM_RANGE(0x06000000, 0x060fffff) AM_RAM AM_MIRROR(0x01f00000) AM_SHARE(3) AM_BASE(&stv_workram_h)
+ AM_RANGE(0x20000000, 0x2007ffff) AM_ROM AM_SHARE(6) // bios mirror
+ AM_RANGE(0x22000000, 0x24ffffff) AM_ROM AM_SHARE(7) // cart mirror
ADDRESS_MAP_END
static ADDRESS_MAP_START( sound_mem, ADDRESS_SPACE_PROGRAM, 16 )
@@ -2434,6 +2436,11 @@ DRIVER_INIT ( stv )
install_stvbios_speedups(machine);
+ // do strict overwrite verification - maruchan and rsgun crash after coinup without this.
+ // todo: test what games need this and don't turn it on for them...
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_DRC_OPTIONS, SH2DRC_STRICT_VERIFY);
+ cpunum_set_info_int(1, CPUINFO_INT_SH2_DRC_OPTIONS, SH2DRC_STRICT_VERIFY);
+
/* debug .. watch the command buffer rsgun, cottonbm etc. appear to use to communicate between cpus */
memory_install_write32_handler(machine, 0, ADDRESS_SPACE_PROGRAM, 0x60ffc44, 0x60ffc47, 0, 0, w60ffc44_write );
memory_install_write32_handler(machine, 0, ADDRESS_SPACE_PROGRAM, 0x60ffc48, 0x60ffc4b, 0, 0, w60ffc48_write );
diff --git a/src/mame/drivers/stvinit.c b/src/mame/drivers/stvinit.c
index ce51d6d267d..550d38ae215 100644
--- a/src/mame/drivers/stvinit.c
+++ b/src/mame/drivers/stvinit.c
@@ -11,6 +11,8 @@ to be honest i think some of these cause more problems than they're worth ...
#include "machine/stvprot.h"
#include "includes/stv.h"
+#define FIRST_SPEEDUP_SLOT (2) // in case we remove/alter the BIOS speedups later
+
/*
IC-13 rom shifter routine,on 2000000-21fffff the game maps the rom bytes on the
ODD (in every sense) bytes.This gets the IC-13 rom status to good and ends a emulation
@@ -174,20 +176,34 @@ NVRAM_HANDLER( stv )
static READ32_HANDLER( stv_speedup_r )
{
- if (activecpu_get_pc()==0x60154b4) cpu_spinuntil_int(); // bios menus..
+ if (activecpu_get_pc()==0x60154b2) cpu_spinuntil_int(); // bios menus..
+ cpu_spinuntil_int();
return stv_workram_h[0x0335d0/4];
}
static READ32_HANDLER( stv_speedup2_r )
{
- if (activecpu_get_pc()==0x6013af0) cpu_spinuntil_int(); // for use in japan
+ if (activecpu_get_pc()==0x6013aee) cpu_spinuntil_int(); // for use in japan
+
+ cpu_spinuntil_int();
return stv_workram_h[0x0335bc/4];
}
void install_stvbios_speedups(running_machine *machine)
{
+ // flushes 0 & 1 on both CPUs are for the BIOS speedups
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_PCFLUSH_SELECT, 0);
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_PCFLUSH_ADDR, 0x60154b2);
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_PCFLUSH_SELECT, 1);
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_PCFLUSH_ADDR, 0x6013aee);
+
+ cpunum_set_info_int(1, CPUINFO_INT_SH2_PCFLUSH_SELECT, 0);
+ cpunum_set_info_int(1, CPUINFO_INT_SH2_PCFLUSH_ADDR, 0x60154b2);
+ cpunum_set_info_int(1, CPUINFO_INT_SH2_PCFLUSH_SELECT, 1);
+ cpunum_set_info_int(1, CPUINFO_INT_SH2_PCFLUSH_ADDR, 0x6013aee);
+
/* idle skip bios? .. not 100% sure this is safe .. we'll see */
memory_install_read32_handler(machine, 0, ADDRESS_SPACE_PROGRAM, 0x60335d0, 0x60335d3, 0, 0, stv_speedup_r );
memory_install_read32_handler(machine, 0, ADDRESS_SPACE_PROGRAM, 0x60335bc, 0x60335bf, 0, 0, stv_speedup2_r );
@@ -195,7 +211,7 @@ void install_stvbios_speedups(running_machine *machine)
static READ32_HANDLER( shienryu_slave_speedup_r )
{
- if (activecpu_get_pc()==0x06004410)
+ if (activecpu_get_pc()==0x0600440e)
cpu_spinuntil_time(ATTOTIME_IN_USEC(20)); // is this safe... we can't skip till vbl because its not a vbl wait loop
return stv_workram_h[0x0ae8e4/4];
@@ -204,7 +220,7 @@ static READ32_HANDLER( shienryu_slave_speedup_r )
static READ32_HANDLER( shienryu_speedup_r )
{
- if (activecpu_get_pc()==0x060041C8) cpu_spinuntil_int(); // after you enable the sound cpu ...
+ if (activecpu_get_pc()==0x060041C6) cpu_spinuntil_int(); // after you enable the sound cpu ...
return stv_workram_h[0x0ae8e0/4];
}
@@ -214,6 +230,13 @@ DRIVER_INIT(shienryu)
stv_default_eeprom = shienryu_default_eeprom;
stv_default_eeprom_length = sizeof(shienryu_default_eeprom);
+ // master
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_PCFLUSH_SELECT, FIRST_SPEEDUP_SLOT);
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_PCFLUSH_ADDR, 0x60041c6);
+ // slave
+ cpunum_set_info_int(1, CPUINFO_INT_SH2_PCFLUSH_SELECT, FIRST_SPEEDUP_SLOT);
+ cpunum_set_info_int(1, CPUINFO_INT_SH2_PCFLUSH_ADDR, 0x600440e);
+
memory_install_read32_handler(machine, 0, ADDRESS_SPACE_PROGRAM, 0x60ae8e0, 0x60ae8e3, 0, 0, shienryu_speedup_r ); // after you enable sound cpu
memory_install_read32_handler(machine, 1, ADDRESS_SPACE_PROGRAM, 0x60ae8e4, 0x60ae8e7, 0, 0, shienryu_slave_speedup_r ); // after you enable sound cpu
@@ -222,13 +245,13 @@ DRIVER_INIT(shienryu)
static READ32_HANDLER( prikura_speedup_r )
{
- if (activecpu_get_pc()==0x6018642) cpu_spinuntil_int(); // after you enable the sound cpu ...
+ if (activecpu_get_pc()==0x6018640) cpu_spinuntil_int(); // after you enable the sound cpu ...
return stv_workram_h[0x0b9228/4];
}
static void prikura_slave_speedup( UINT32 data )
{
- if ( activecpu_get_pc() == 0x06018c70 )
+ if ( activecpu_get_pc() == 0x06018c6e )
if ( (data & 0x00800000) == 0 )
cpunum_spinuntil_trigger(1, 1000);
}
@@ -242,6 +265,13 @@ DRIVER_INIT(prikura)
(loops for 263473 instructions)
*/
+ // master
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_PCFLUSH_SELECT, FIRST_SPEEDUP_SLOT);
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_PCFLUSH_ADDR, 0x6018640);
+ // slave
+ cpunum_set_info_int(1, CPUINFO_INT_SH2_PCFLUSH_SELECT, FIRST_SPEEDUP_SLOT);
+ cpunum_set_info_int(1, CPUINFO_INT_SH2_PCFLUSH_ADDR, 0x6018c6e);
+
memory_install_read32_handler(machine, 0, ADDRESS_SPACE_PROGRAM, 0x60b9228, 0x60b922b, 0, 0, prikura_speedup_r );
cpunum_set_info_fct(1, CPUINFO_PTR_SH2_FTCSR_READ_CALLBACK, (genf*)prikura_slave_speedup );
@@ -255,7 +285,7 @@ DRIVER_INIT(prikura)
static READ32_HANDLER( hanagumi_speedup_r )
{
- if (activecpu_get_pc()==0x06010162) cpu_spinuntil_int(); // title logos
+ if (activecpu_get_pc()==0x06010160) cpu_spinuntil_int(); // title logos
return stv_workram_h[0x94188/4];
}
@@ -287,6 +317,9 @@ DRIVER_INIT(hanagumi)
(loops for 288688 instructions)
*/
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_PCFLUSH_SELECT, FIRST_SPEEDUP_SLOT);
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_PCFLUSH_ADDR, 0x6010160);
+
memory_install_read32_handler(machine, 0, ADDRESS_SPACE_PROGRAM, 0x6094188, 0x609418b, 0, 0, hanagumi_speedup_r );
memory_install_read32_handler(machine, 1, ADDRESS_SPACE_PROGRAM, 0x6015438, 0x601543b, 0, 0, hanagumi_slave_off );
@@ -314,7 +347,7 @@ CPU0: Aids Screen
static READ32_HANDLER( puyosun_speedup_r )
{
- if (activecpu_get_pc()==0x6021CF2) cpu_spinuntil_time(ATTOTIME_IN_USEC(400)); // spinuntilint breaks controls again .. urgh
+ if (activecpu_get_pc()==0x6021CF0) cpu_spinuntil_time(ATTOTIME_IN_USEC(400)); // spinuntilint breaks controls again .. urgh
return stv_workram_h[0x0ffc10/4];
@@ -322,13 +355,19 @@ static READ32_HANDLER( puyosun_speedup_r )
static void puyosun_slave_speedup( UINT32 data )
{
- if ( activecpu_get_pc() == 0x6023700 )
+ if ( activecpu_get_pc() == 0x60236fe )
if ( (data & 0x00800000) == 0 )
cpunum_spinuntil_trigger(1, 1000);
}
DRIVER_INIT(puyosun)
{
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_PCFLUSH_SELECT, FIRST_SPEEDUP_SLOT);
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_PCFLUSH_ADDR, 0x6021cf0);
+
+ cpunum_set_info_int(1, CPUINFO_INT_SH2_PCFLUSH_SELECT, FIRST_SPEEDUP_SLOT);
+ cpunum_set_info_int(1, CPUINFO_INT_SH2_PCFLUSH_ADDR, 0x60236fe);
+
memory_install_read32_handler(machine, 0, ADDRESS_SPACE_PROGRAM, 0x60ffc10, 0x60ffc13, 0, 0, puyosun_speedup_r ); // idle loop of main cpu
cpunum_set_info_fct(1, CPUINFO_PTR_SH2_FTCSR_READ_CALLBACK, (genf*)puyosun_slave_speedup );
@@ -350,13 +389,16 @@ CPU0 Data East Logo:
static READ32_HANDLER( mausuke_speedup_r )
{
- if (activecpu_get_pc()==0x060461A2) cpu_spinuntil_time(ATTOTIME_IN_USEC(20)); // spinuntilint breaks controls again .. urgh
+ if (activecpu_get_pc()==0x060461A0) cpu_spinuntil_time(ATTOTIME_IN_USEC(20)); // spinuntilint breaks controls again .. urgh
return stv_workram_h[0x0ffc10/4];
}
DRIVER_INIT(mausuke)
{
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_PCFLUSH_SELECT, FIRST_SPEEDUP_SLOT);
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_PCFLUSH_ADDR, 0x60461A0);
+
memory_install_read32_handler(machine, 0, ADDRESS_SPACE_PROGRAM, 0x60ffc10, 0x60ffc13, 0, 0, mausuke_speedup_r ); // idle loop of main cpu
DRIVER_INIT_CALL(ic13);
@@ -367,14 +409,14 @@ DRIVER_INIT(mausuke)
static READ32_HANDLER( cottonbm_speedup_r )
{
- if (activecpu_get_pc()==0x06030EE4) cpu_spinuntil_time(ATTOTIME_IN_USEC(20)); // spinuntilint breaks lots of things
+ if (activecpu_get_pc()==0x06030EE2) cpu_spinuntil_time(ATTOTIME_IN_USEC(20)); // spinuntilint breaks lots of things
return stv_workram_h[0x0ffc10/4];
}
static void cottonbm_slave_speedup( UINT32 data )
{
- if (activecpu_get_pc() == 0x6032b54)
+ if (activecpu_get_pc() == 0x6032b52)
if ( (data & 0x00800000) == 0 )
{
if (
@@ -394,6 +436,11 @@ static void cottonbm_slave_speedup( UINT32 data )
DRIVER_INIT(cottonbm)
{
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_PCFLUSH_SELECT, FIRST_SPEEDUP_SLOT);
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_PCFLUSH_ADDR, 0x6030EE2);
+ cpunum_set_info_int(1, CPUINFO_INT_SH2_PCFLUSH_SELECT, FIRST_SPEEDUP_SLOT);
+ cpunum_set_info_int(1, CPUINFO_INT_SH2_PCFLUSH_ADDR, 0x6032b52);
+
memory_install_read32_handler(machine, 0, ADDRESS_SPACE_PROGRAM, 0x60ffc10, 0x60ffc13, 0, 0, cottonbm_speedup_r ); // idle loop of main cpu
cpunum_set_info_fct(1, CPUINFO_PTR_SH2_FTCSR_READ_CALLBACK, (genf*)cottonbm_slave_speedup );
@@ -404,14 +451,14 @@ DRIVER_INIT(cottonbm)
static READ32_HANDLER( cotton2_speedup_r )
{
- if (activecpu_get_pc()==0x06031c7c) cpu_spinuntil_time(ATTOTIME_IN_USEC(20)); // spinuntilint breaks lots of things
+ if (activecpu_get_pc()==0x06031c7a) cpu_spinuntil_time(ATTOTIME_IN_USEC(20)); // spinuntilint breaks lots of things
return stv_workram_h[0x0ffc10/4];
}
static void cotton2_slave_speedup( UINT32 data )
{
- if (activecpu_get_pc() == 0x60338ec)
+ if (activecpu_get_pc() == 0x60338ea)
if ( (data & 0x00800000) == 0 )
{
if (
@@ -430,6 +477,11 @@ static void cotton2_slave_speedup( UINT32 data )
DRIVER_INIT(cotton2)
{
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_PCFLUSH_SELECT, FIRST_SPEEDUP_SLOT);
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_PCFLUSH_ADDR, 0x6031c7a);
+ cpunum_set_info_int(1, CPUINFO_INT_SH2_PCFLUSH_SELECT, FIRST_SPEEDUP_SLOT);
+ cpunum_set_info_int(1, CPUINFO_INT_SH2_PCFLUSH_ADDR, 0x60338ea);
+
memory_install_read32_handler(machine, 0, ADDRESS_SPACE_PROGRAM, 0x60ffc10, 0x60ffc13, 0, 0, cotton2_speedup_r ); // idle loop of main cpu
cpunum_set_info_fct(1, CPUINFO_PTR_SH2_FTCSR_READ_CALLBACK, (genf*)cotton2_slave_speedup );
@@ -442,14 +494,14 @@ static int dnmtdeka_pending_commands;
static READ32_HANDLER( dnmtdeka_speedup_r )
{
- if (activecpu_get_pc()==0x6027c92) cpu_spinuntil_int();//cpu_spinuntil_time(ATTOTIME_IN_USEC(20));
+ if (activecpu_get_pc()==0x6027c90) cpu_spinuntil_int();//cpu_spinuntil_time(ATTOTIME_IN_USEC(20));
return stv_workram_h[0x0985a0/4];
}
static WRITE32_HANDLER(dnmtdeka_cmd_write)
{
COMBINE_DATA(&stv_workram_h[0x0e0ad4/4 + offset]);
- if ( (cpu_getactivecpu() == 0) && (activecpu_get_pc() == 0x00000d06) )
+ if ( (cpu_getactivecpu() == 0) && (activecpu_get_pc() == 0x00000d04) )
return;
if ( data != 0 ) dnmtdeka_pending_commands++;
@@ -460,7 +512,7 @@ static WRITE32_HANDLER(dnmtdeka_cmd_write)
static READ32_HANDLER(dnmtdeka_cmd_read)
{
//logerror( "CMD: Read by cpu=%d, at = %08X, offset = %08X, data = %08X, commands = %d\n", cpu_getactivecpu(), activecpu_get_pc(), offset, stv_workram_h[0xe0bd0/4 + offset], dnmtdeka_pending_commands );
- if ( activecpu_get_pc() == 0x060051f4 )
+ if ( activecpu_get_pc() == 0x060051f2 )
{
if ( stv_workram_h[0x0e0ad4/4 + offset] == 0 )
{
@@ -479,6 +531,21 @@ static READ32_HANDLER(dnmtdeka_cmd_read)
DRIVER_INIT(dnmtdeka)
{
+ // install all 3 speedups on both master and slave
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_PCFLUSH_SELECT, FIRST_SPEEDUP_SLOT);
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_PCFLUSH_ADDR, 0x6027c90);
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_PCFLUSH_SELECT, FIRST_SPEEDUP_SLOT+1);
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_PCFLUSH_ADDR, 0xd04);
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_PCFLUSH_SELECT, FIRST_SPEEDUP_SLOT+2);
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_PCFLUSH_ADDR, 0x60051f2);
+
+ cpunum_set_info_int(1, CPUINFO_INT_SH2_PCFLUSH_SELECT, FIRST_SPEEDUP_SLOT);
+ cpunum_set_info_int(1, CPUINFO_INT_SH2_PCFLUSH_ADDR, 0x6027c90);
+ cpunum_set_info_int(1, CPUINFO_INT_SH2_PCFLUSH_SELECT, FIRST_SPEEDUP_SLOT+1);
+ cpunum_set_info_int(1, CPUINFO_INT_SH2_PCFLUSH_ADDR, 0xd04);
+ cpunum_set_info_int(1, CPUINFO_INT_SH2_PCFLUSH_SELECT, FIRST_SPEEDUP_SLOT+2);
+ cpunum_set_info_int(1, CPUINFO_INT_SH2_PCFLUSH_ADDR, 0x60051f2);
+
dnmtdeka_pending_commands = 0;
memory_install_read32_handler(machine, 0, ADDRESS_SPACE_PROGRAM, 0x60985a0, 0x60985a3, 0, 0, dnmtdeka_speedup_r ); // idle loop of main cpu
@@ -491,14 +558,14 @@ static int diehard_pending_commands;
static READ32_HANDLER(diehard_speedup_r)
{
- if ( activecpu_get_pc() == 0x06027c9a ) cpu_spinuntil_int();
+ if ( activecpu_get_pc() == 0x06027c98 ) cpu_spinuntil_int();
return stv_workram_h[0x000986ac/4];
}
static WRITE32_HANDLER(diehard_cmd_write)
{
COMBINE_DATA(&stv_workram_h[0xe0bd0/4 + offset]);
- if ( (cpu_getactivecpu() == 0) && (activecpu_get_pc() == 0x00000d06) )
+ if ( (cpu_getactivecpu() == 0) && (activecpu_get_pc() == 0x00000d04) )
return;
if ( data != 0 ) diehard_pending_commands++;
@@ -509,7 +576,7 @@ static WRITE32_HANDLER(diehard_cmd_write)
static READ32_HANDLER(diehard_cmd_read)
{
//logerror( "CMD: Read by cpu=%d, at = %08X, offset = %08X, data = %08X, commands = %d\n", cpu_getactivecpu(), activecpu_get_pc(), offset, stv_workram_h[0xe0bd0/4 + offset], diehard_pending_commands );
- if ( activecpu_get_pc() == 0x060051f4 )
+ if ( activecpu_get_pc() == 0x060051f2 )
{
if ( stv_workram_h[0xe0bd0/4 + offset] == 0 )
{
@@ -553,6 +620,22 @@ DRIVER_INIT(diehard)
{
diehard_pending_commands = 0;
+ // install all 3 speedups on both master and slave
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_PCFLUSH_SELECT, FIRST_SPEEDUP_SLOT);
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_PCFLUSH_ADDR, 0x6027c98);
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_PCFLUSH_SELECT, FIRST_SPEEDUP_SLOT+1);
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_PCFLUSH_ADDR, 0xd04);
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_PCFLUSH_SELECT, FIRST_SPEEDUP_SLOT+2);
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_PCFLUSH_ADDR, 0x60051f2);
+
+ cpunum_set_info_int(1, CPUINFO_INT_SH2_PCFLUSH_SELECT, FIRST_SPEEDUP_SLOT);
+ cpunum_set_info_int(1, CPUINFO_INT_SH2_PCFLUSH_ADDR, 0x6027c98);
+ cpunum_set_info_int(1, CPUINFO_INT_SH2_PCFLUSH_SELECT, FIRST_SPEEDUP_SLOT+1);
+ cpunum_set_info_int(1, CPUINFO_INT_SH2_PCFLUSH_ADDR, 0xd04);
+ cpunum_set_info_int(1, CPUINFO_INT_SH2_PCFLUSH_SELECT, FIRST_SPEEDUP_SLOT+2);
+ cpunum_set_info_int(1, CPUINFO_INT_SH2_PCFLUSH_ADDR, 0x60051f2);
+
+
memory_install_read32_handler(machine, 0, ADDRESS_SPACE_PROGRAM, 0x060986ac, 0x060986af, 0, 0, diehard_speedup_r );
memory_install_write32_handler(machine, 0, ADDRESS_SPACE_PROGRAM, 0x060e0bd0, 0x060e0dcf, 0, 0, diehard_cmd_write );
memory_install_read32_handler(machine, 1, ADDRESS_SPACE_PROGRAM, 0x060e0bd0, 0x060e0dcf, 0, 0, diehard_cmd_read );
@@ -562,19 +645,18 @@ DRIVER_INIT(diehard)
DRIVER_INIT_CALL(ic13);
-
}
static READ32_HANDLER( fhboxers_speedup_r )
{
- if (activecpu_get_pc()==0x060041c4) cpu_spinuntil_time(ATTOTIME_IN_USEC(20));
+ if (activecpu_get_pc()==0x060041c2) cpu_spinuntil_time(ATTOTIME_IN_USEC(20));
return stv_workram_h[0x00420c/4];
}
static READ32_HANDLER( fhboxers_speedup2_r )
{
- if (activecpu_get_pc()==0x0600bb0c) cpu_spinuntil_time(ATTOTIME_IN_USEC(20));
+ if (activecpu_get_pc()==0x0600bb0a) cpu_spinuntil_time(ATTOTIME_IN_USEC(20));
return stv_workram_h[0x090740/4];
@@ -582,7 +664,7 @@ static READ32_HANDLER( fhboxers_speedup2_r )
static READ32_HANDLER( fhboxers_speedup3_r )
{
- if (activecpu_get_pc()==0x0600b320 )
+ if (activecpu_get_pc()==0x0600b31e )
cpu_spinuntil_int();
return stv_workram_h[0x90bb4/4];
@@ -590,6 +672,13 @@ static READ32_HANDLER( fhboxers_speedup3_r )
DRIVER_INIT(fhboxers)
{
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_PCFLUSH_SELECT, FIRST_SPEEDUP_SLOT);
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_PCFLUSH_ADDR, 0x60041c2);
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_PCFLUSH_SELECT, FIRST_SPEEDUP_SLOT+1);
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_PCFLUSH_ADDR, 0x600bb0a);
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_PCFLUSH_SELECT, FIRST_SPEEDUP_SLOT+2);
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_PCFLUSH_ADDR, 0x600b31e);
+
memory_install_read32_handler(machine, 0, ADDRESS_SPACE_PROGRAM, 0x600420c, 0x600420f, 0, 0, fhboxers_speedup_r ); // idle loop of main cpu
memory_install_read32_handler(machine, 1, ADDRESS_SPACE_PROGRAM, 0x6090740, 0x6090743, 0, 0, fhboxers_speedup2_r ); // idle loop of second cpu
memory_install_read32_handler(machine, 0, ADDRESS_SPACE_PROGRAM, 0x06090bb4, 0x06090bb7, 0, 0, fhboxers_speedup3_r ); // idle loop of main cpu
@@ -600,46 +689,41 @@ DRIVER_INIT(fhboxers)
static READ32_HANDLER( bakubaku_speedup_r )
{
- if (activecpu_get_pc()==0x06036dc8) cpu_spinuntil_int(); // title logos
+ if (activecpu_get_pc()==0x06036dc6) cpu_spinuntil_int(); // title logos
return stv_workram_h[0x0833f0/4];
}
static READ32_HANDLER( bakubaku_speedup2_r )
{
- if (activecpu_get_pc()==0x06033762) cpunum_set_input_line(machine, 1, INPUT_LINE_HALT, ASSERT_LINE);
+ if (activecpu_get_pc()==0x06033760) cpunum_set_input_line(machine, 1, INPUT_LINE_HALT, ASSERT_LINE);
return stv_workram_h[0x0033762/4];
}
-#ifdef UNUSED_FUNCTION
-static READ32_HANDLER( bakubaku_hangskip_r )
-{
- if (activecpu_get_pc()==0x060335e4) stv_workram_h[0x0335e6/4] = 0x32300909;
-
- return stv_workram_h[0x033660/4];
-}
-#endif
-
DRIVER_INIT(bakubaku)
{
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_PCFLUSH_SELECT, FIRST_SPEEDUP_SLOT);
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_PCFLUSH_ADDR, 0x6036dc6);
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_PCFLUSH_SELECT, FIRST_SPEEDUP_SLOT+1);
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_PCFLUSH_ADDR, 0x6033760);
+
memory_install_read32_handler(machine, 0, ADDRESS_SPACE_PROGRAM, 0x60833f0, 0x60833f3, 0, 0, bakubaku_speedup_r ); // idle loop of main cpu
memory_install_read32_handler(machine, 1, ADDRESS_SPACE_PROGRAM, 0x60fdfe8, 0x60fdfeb, 0, 0, bakubaku_speedup2_r ); // turn off slave sh2, is it needed after boot ??
- //memory_install_read32_handler(machine, 0, ADDRESS_SPACE_PROGRAM, 0x6033660, 0x6033663, 0, 0, bakubaku_hangskip_r ); // it waits for a ram address to change what should change it?
DRIVER_INIT_CALL(ic13);
}
static READ32_HANDLER( groovef_hack1_r )
{
- if(activecpu_get_pc() == 0x6005e7e) stv_workram_h[0x0fffcc/4] = 0x00000000;
+ if(activecpu_get_pc() == 0x6005e7c) stv_workram_h[0x0fffcc/4] = 0x00000000;
// popmessage("1 %08x",activecpu_get_pc());
return stv_workram_h[0x0fffcc/4];
}
static READ32_HANDLER( groovef_hack2_r )
{
- if(activecpu_get_pc() == 0x6005e88) stv_workram_h[0x0ca6cc/4] = 0x00000000;
+ if(activecpu_get_pc() == 0x6005e86) stv_workram_h[0x0ca6cc/4] = 0x00000000;
// popmessage("2 %08x",activecpu_get_pc());
return stv_workram_h[0x0ca6cc/4];
}
@@ -647,7 +731,7 @@ static READ32_HANDLER( groovef_hack2_r )
static READ32_HANDLER( groovef_speedup_r )
{
// logerror ("groove speedup \n");
- if (activecpu_get_pc()==0x060a4972)
+ if (activecpu_get_pc()==0x060a4970)
{
cpu_spinuntil_int(); // title logos
// logerror ("groove speedup skipping\n");
@@ -666,13 +750,23 @@ static READ32_HANDLER( groovef_second_cpu_off_r )
static void groovef_slave_speedup( UINT32 data )
{
- if ( activecpu_get_pc() == 0x060060c4 )
+ if ( activecpu_get_pc() == 0x060060c2 )
if ( (data & 0x00800000) == 0 )
cpunum_spinuntil_trigger(1, 1000);
}
DRIVER_INIT( groovef )
{
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_PCFLUSH_SELECT, FIRST_SPEEDUP_SLOT);
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_PCFLUSH_ADDR, 0x6005e7c);
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_PCFLUSH_SELECT, FIRST_SPEEDUP_SLOT+1);
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_PCFLUSH_ADDR, 0x6005e86);
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_PCFLUSH_SELECT, FIRST_SPEEDUP_SLOT+2);
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_PCFLUSH_ADDR, 0x60a4970);
+
+ cpunum_set_info_int(1, CPUINFO_INT_SH2_PCFLUSH_SELECT, FIRST_SPEEDUP_SLOT);
+ cpunum_set_info_int(1, CPUINFO_INT_SH2_PCFLUSH_ADDR, 0x60060c2);
+
/* prevent game from hanging on startup -- todo: remove these hacks */
memory_install_read32_handler(machine, 0, ADDRESS_SPACE_PROGRAM, 0x60ca6cc, 0x60ca6cf, 0, 0, groovef_hack2_r );
memory_install_read32_handler(machine, 0, ADDRESS_SPACE_PROGRAM, 0x60fffcc, 0x60fffcf, 0, 0, groovef_hack1_r );
@@ -717,26 +811,33 @@ and Hanafuda works without hack now (unless the sound ram one)
static READ32_HANDLER( danchih_hack_r )
{
logerror( "DMASt_SCU1: Read at PC=%08x, value = %08x\n", activecpu_get_pc(), stv_workram_h[0x0ffcbc/4] );
- if (activecpu_get_pc()==0x06028b2a) return 0x0e0c0000;
+ if (activecpu_get_pc()==0x06028b28) return 0x0e0c0000;
return stv_workram_h[0x0ffcbc/4];
}
static READ32_HANDLER( danchih_speedup_r )
{
- if (activecpu_get_pc()==0x06028c90) cpu_spinuntil_time(ATTOTIME_IN_USEC(20));
+ if (activecpu_get_pc()==0x06028c8e) cpu_spinuntil_time(ATTOTIME_IN_USEC(20));
return stv_workram_h[0x0ffc10/4];
}
static void danchih_slave_speedup( UINT32 data )
{
- if ( activecpu_get_pc() == 0x0602ae28 )
+ if ( activecpu_get_pc() == 0x0602ae26 )
if ( (data & 0x00800000) == 0 )
cpunum_spinuntil_trigger(1, 1000);
}
DRIVER_INIT( danchih )
{
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_PCFLUSH_SELECT, FIRST_SPEEDUP_SLOT);
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_PCFLUSH_ADDR, 0x6028b28);
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_PCFLUSH_SELECT, FIRST_SPEEDUP_SLOT+1);
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_PCFLUSH_ADDR, 0x6028c8e);
+ cpunum_set_info_int(1, CPUINFO_INT_SH2_PCFLUSH_SELECT, FIRST_SPEEDUP_SLOT);
+ cpunum_set_info_int(1, CPUINFO_INT_SH2_PCFLUSH_ADDR, 0x602ae26);
+
/* prevent game from hanging on title screen -- todo: remove these hacks */
memory_install_read32_handler(machine, 0, ADDRESS_SPACE_PROGRAM, 0x60ffcbc, 0x60ffcbf, 0, 0, danchih_hack_r );
@@ -771,14 +872,14 @@ TODO: understand where it gets 0x02020000,it must be 0x0000000
static READ32_HANDLER( astrass_hack_r )
{
- if(activecpu_get_pc()==0x60011bc) return 0x00000000;
+ if(activecpu_get_pc()==0x60011b8) return 0x00000000;
return stv_workram_h[0x000770/4];
}
static READ32_HANDLER( astrass_speedup_r )
{
- if(activecpu_get_pc() == 0x0605b9dc )
+ if(activecpu_get_pc() == 0x0605b9da )
cpu_spinuntil_time(ATTOTIME_IN_USEC(20));
return stv_workram_h[0x8e4d8/4];
@@ -786,6 +887,11 @@ static READ32_HANDLER( astrass_speedup_r )
DRIVER_INIT( astrass )
{
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_PCFLUSH_SELECT, FIRST_SPEEDUP_SLOT);
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_PCFLUSH_ADDR, 0x60011b8);
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_PCFLUSH_SELECT, FIRST_SPEEDUP_SLOT+1);
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_PCFLUSH_ADDR, 0x605b9da);
+
memory_install_read32_handler(machine, 0, ADDRESS_SPACE_PROGRAM, 0x6000770, 0x6000773, 0, 0, astrass_hack_r );
memory_install_read32_handler(machine, 0, ADDRESS_SPACE_PROGRAM, 0x0608e4d8, 0x0608e4db, 0, 0, astrass_speedup_r );
@@ -799,25 +905,32 @@ DRIVER_INIT( astrass )
static READ32_HANDLER(thunt_speedup_r)
{
- if (activecpu_get_pc() == 0x0602A026) cpu_spinuntil_int();
+ if (activecpu_get_pc() == 0x0602A024) cpu_spinuntil_int();
return stv_workram_h[0x00031424/4];
}
static READ32_HANDLER(thunt_speedup2_r)
{
- if (activecpu_get_pc() == 0x06013EEC) cpu_spinuntil_int();
+ if (activecpu_get_pc() == 0x06013EEA) cpu_spinuntil_int();
return stv_workram_h[0x00075958/4];
}
static void thunt_slave_speedup(UINT32 data)
{
- if (activecpu_get_pc() == 0x0602AAFA)
+ if (activecpu_get_pc() == 0x0602AAF8)
if ( (data & 0x00800000) == 0 )
cpunum_spinuntil_trigger(1, 1000);
}
DRIVER_INIT(thunt)
{
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_PCFLUSH_SELECT, FIRST_SPEEDUP_SLOT);
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_PCFLUSH_ADDR, 0x602A024);
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_PCFLUSH_SELECT, FIRST_SPEEDUP_SLOT+1);
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_PCFLUSH_ADDR, 0x6013EEA);
+ cpunum_set_info_int(1, CPUINFO_INT_SH2_PCFLUSH_SELECT, FIRST_SPEEDUP_SLOT);
+ cpunum_set_info_int(1, CPUINFO_INT_SH2_PCFLUSH_ADDR, 0x602AAF8);
+
/*
0602A024: MOV.L @R6,R0 // 06031424
0602A026: TST R0,R0
@@ -854,26 +967,33 @@ DRIVER_INIT(thunt)
static READ32_HANDLER(sandor_speedup_r)
{
- if (activecpu_get_pc() == 0x0602a0fa) cpu_spinuntil_int();
+ if (activecpu_get_pc() == 0x0602a0f8) cpu_spinuntil_int();
return stv_workram_h[0x000314f8/4];
}
static READ32_HANDLER(sandor_speedup2_r)
{
- if (activecpu_get_pc() == 0x06013fc0) cpu_spinuntil_int();
+ if (activecpu_get_pc() == 0x06013fbe) cpu_spinuntil_int();
return stv_workram_h[0x00075a2c/4];
}
static void sandor_slave_speedup(UINT32 data)
{
- if (activecpu_get_pc() == 0x0602abce)
+ if (activecpu_get_pc() == 0x0602abcc)
if ( (data & 0x00800000) == 0 )
cpunum_spinuntil_trigger(1, 1000);
}
DRIVER_INIT(sandor)
{
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_PCFLUSH_SELECT, FIRST_SPEEDUP_SLOT);
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_PCFLUSH_ADDR, 0x602a0f8);
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_PCFLUSH_SELECT, FIRST_SPEEDUP_SLOT+1);
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_PCFLUSH_ADDR, 0x6013fbe);
+ cpunum_set_info_int(1, CPUINFO_INT_SH2_PCFLUSH_SELECT, FIRST_SPEEDUP_SLOT);
+ cpunum_set_info_int(1, CPUINFO_INT_SH2_PCFLUSH_ADDR, 0x602abcc);
+
memory_install_read32_handler(machine, 0, ADDRESS_SPACE_PROGRAM, 0x060314f8, 0x060314fb, 0, 0, sandor_speedup_r );
memory_install_read32_handler(machine, 0, ADDRESS_SPACE_PROGRAM, 0x06075a2c, 0x06075a2f, 0, 0, sandor_speedup2_r );
cpunum_set_info_fct(1, CPUINFO_PTR_SH2_FTCSR_READ_CALLBACK, (genf *)sandor_slave_speedup);
@@ -884,13 +1004,13 @@ DRIVER_INIT(sandor)
static READ32_HANDLER(grdforce_speedup_r)
{
- if ( activecpu_get_pc() == 0x06041E34 ) cpu_spinuntil_time(ATTOTIME_IN_USEC(20));
+ if ( activecpu_get_pc() == 0x06041E32 ) cpu_spinuntil_time(ATTOTIME_IN_USEC(20));
return stv_workram_h[0x000ffc10/4];
}
static void grdforce_slave_speedup( UINT32 data )
{
- if (activecpu_get_pc() == 0x06043aa4)
+ if (activecpu_get_pc() == 0x06043aa2)
if ( (data & 0x00800000) == 0 )
{
if (
@@ -910,6 +1030,10 @@ static void grdforce_slave_speedup( UINT32 data )
DRIVER_INIT(grdforce)
{
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_PCFLUSH_SELECT, FIRST_SPEEDUP_SLOT);
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_PCFLUSH_ADDR, 0x6041e32);
+ cpunum_set_info_int(1, CPUINFO_INT_SH2_PCFLUSH_SELECT, FIRST_SPEEDUP_SLOT);
+ cpunum_set_info_int(1, CPUINFO_INT_SH2_PCFLUSH_ADDR, 0x6043aa2);
/*
06041E2C: MOV.L @($03C8,GBR),R0
06041E2E: JSR R0
@@ -932,7 +1056,7 @@ DRIVER_INIT(grdforce)
static READ32_HANDLER( batmanfr_speedup_r )
{
//logerror( "batmanfr speedup: pc = %08x, mem = %08x\n", activecpu_get_pc(), stv_workram_h[0x0002acf0/4] );
- if ( activecpu_get_pc() != 0x060121c2 )
+ if ( activecpu_get_pc() != 0x060121c0 )
cpu_spinuntil_int();
return stv_workram_h[0x0002acf0/4];
@@ -940,7 +1064,7 @@ static READ32_HANDLER( batmanfr_speedup_r )
static void batmanfr_slave_speedup( UINT32 data )
{
- if (activecpu_get_pc() == 0x060125be )
+ if (activecpu_get_pc() == 0x060125bc )
if ( (data & 0x00800000) == 0 )
cpunum_spinuntil_trigger(1, 1000);
}
@@ -948,6 +1072,11 @@ static void batmanfr_slave_speedup( UINT32 data )
DRIVER_INIT(batmanfr)
{
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_PCFLUSH_SELECT, FIRST_SPEEDUP_SLOT);
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_PCFLUSH_ADDR, 0x60121c0);
+ cpunum_set_info_int(1, CPUINFO_INT_SH2_PCFLUSH_SELECT, FIRST_SPEEDUP_SLOT);
+ cpunum_set_info_int(1, CPUINFO_INT_SH2_PCFLUSH_ADDR, 0x60125bc);
+
memory_install_read32_handler(machine, 0, ADDRESS_SPACE_PROGRAM, 0x0602acf0, 0x0602acf3, 0, 0, batmanfr_speedup_r );
cpunum_set_info_fct(1, CPUINFO_PTR_SH2_FTCSR_READ_CALLBACK, (genf*)batmanfr_slave_speedup );
@@ -959,7 +1088,7 @@ DRIVER_INIT(batmanfr)
static void colmns97_slave_speedup( UINT32 data )
{
- if (activecpu_get_pc() == 0x060298a4 )
+ if (activecpu_get_pc() == 0x060298a2 )
if ( (data & 0x00800000) == 0 )
if ( (stv_workram_h[0x0ffc48/4] != 0x260ef3fc) )
{
@@ -971,6 +1100,9 @@ static void colmns97_slave_speedup( UINT32 data )
DRIVER_INIT(colmns97)
{
+ cpunum_set_info_int(1, CPUINFO_INT_SH2_PCFLUSH_SELECT, FIRST_SPEEDUP_SLOT);
+ cpunum_set_info_int(1, CPUINFO_INT_SH2_PCFLUSH_ADDR, 0x60298a2);
+
cpunum_set_info_fct(1, CPUINFO_PTR_SH2_FTCSR_READ_CALLBACK, (genf*)colmns97_slave_speedup );
DRIVER_INIT_CALL(ic13);
@@ -981,19 +1113,24 @@ DRIVER_INIT(colmns97)
static READ32_HANDLER(winterht_speedup_r)
{
- if ( activecpu_get_pc() == 0x06098aec ) cpu_spinuntil_time(ATTOTIME_IN_USEC(20));//cpu_spinuntil_int();
+ if ( activecpu_get_pc() == 0x06098aea ) cpu_spinuntil_time(ATTOTIME_IN_USEC(20));//cpu_spinuntil_int();
return stv_workram_h[0x000ffc10/4];
}
static void winterht_slave_speedup( UINT32 data )
{
- if (activecpu_get_pc() == 0x0609ae50 )
+ if (activecpu_get_pc() == 0x0609ae4e )
if ( (data & 0x00800000) == 0 )
cpunum_spinuntil_trigger(1, 1000);
}
DRIVER_INIT(winterht)
{
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_PCFLUSH_SELECT, FIRST_SPEEDUP_SLOT);
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_PCFLUSH_ADDR, 0x6098aea);
+ cpunum_set_info_int(1, CPUINFO_INT_SH2_PCFLUSH_SELECT, FIRST_SPEEDUP_SLOT);
+ cpunum_set_info_int(1, CPUINFO_INT_SH2_PCFLUSH_ADDR, 0x609ae4e);
+
memory_install_read32_handler(machine, 0, ADDRESS_SPACE_PROGRAM, 0x060ffc10, 0x060ffc13, 0, 0, winterht_speedup_r );
cpunum_set_info_fct(1, CPUINFO_PTR_SH2_FTCSR_READ_CALLBACK, (genf*)winterht_slave_speedup );
@@ -1005,13 +1142,13 @@ DRIVER_INIT(winterht)
static READ32_HANDLER(seabass_speedup_r)
{
- if ( activecpu_get_pc() == 0x0602cbfc ) cpu_spinuntil_time(ATTOTIME_IN_USEC(20));
+ if ( activecpu_get_pc() == 0x0602cbfa ) cpu_spinuntil_time(ATTOTIME_IN_USEC(20));
return stv_workram_h[0x000ffc10/4];
}
static void seabass_slave_speedup( UINT32 data )
{
- if (activecpu_get_pc() == 0x060321f0 )
+ if (activecpu_get_pc() == 0x060321ee )
if ( (data & 0x00800000) == 0 )
cpunum_spinuntil_trigger(1, 1000);
}
@@ -1019,6 +1156,11 @@ static void seabass_slave_speedup( UINT32 data )
DRIVER_INIT(seabass)
{
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_PCFLUSH_SELECT, FIRST_SPEEDUP_SLOT);
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_PCFLUSH_ADDR, 0x602cbfa);
+ cpunum_set_info_int(1, CPUINFO_INT_SH2_PCFLUSH_SELECT, FIRST_SPEEDUP_SLOT);
+ cpunum_set_info_int(1, CPUINFO_INT_SH2_PCFLUSH_ADDR, 0x60321ee);
+
memory_install_read32_handler(machine, 0, ADDRESS_SPACE_PROGRAM, 0x060ffc10, 0x060ffc13, 0, 0, seabass_speedup_r );
cpunum_set_info_fct(1, CPUINFO_PTR_SH2_FTCSR_READ_CALLBACK, (genf*)seabass_slave_speedup );
@@ -1030,19 +1172,24 @@ DRIVER_INIT(seabass)
static void vfremix_slave_speedup( UINT32 data )
{
- if (activecpu_get_pc() == 0x0604C334 )
+ if (activecpu_get_pc() == 0x0604C332 )
if ( (data & 0x00800000) == 0 )
cpunum_spinuntil_trigger(1, 1000);
}
static READ32_HANDLER(vfremix_speedup_r)
{
- if ( activecpu_get_pc() == 0x0602c30e ) cpu_spinuntil_int();
+ if ( activecpu_get_pc() == 0x0602c30c ) cpu_spinuntil_int();
return stv_workram_h[0x00074f98/4];
}
DRIVER_INIT(vfremix)
{
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_PCFLUSH_SELECT, FIRST_SPEEDUP_SLOT);
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_PCFLUSH_ADDR, 0x602c30c);
+ cpunum_set_info_int(1, CPUINFO_INT_SH2_PCFLUSH_SELECT, FIRST_SPEEDUP_SLOT);
+ cpunum_set_info_int(1, CPUINFO_INT_SH2_PCFLUSH_ADDR, 0x604c332);
+
memory_install_read32_handler(machine, 0, ADDRESS_SPACE_PROGRAM, 0x06074f98, 0x06074f9b, 0, 0, vfremix_speedup_r );
cpunum_set_info_fct(1, CPUINFO_PTR_SH2_FTCSR_READ_CALLBACK, (genf*)vfremix_slave_speedup );
@@ -1054,19 +1201,24 @@ DRIVER_INIT(vfremix)
static READ32_HANDLER(sss_speedup_r)
{
- if ( activecpu_get_pc() == 0x0602639a ) cpu_spinuntil_int();
+ if ( activecpu_get_pc() == 0x06026398 ) cpu_spinuntil_int();
return stv_workram_h[0x000ffc10/4];
}
static void sss_slave_speedup( UINT32 data )
{
- if (activecpu_get_pc() == 0x06028cd8 )
+ if (activecpu_get_pc() == 0x06028cd6 )
if ( (data & 0x00800000) == 0 )
cpunum_spinuntil_trigger(1, 1000);
}
DRIVER_INIT(sss)
{
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_PCFLUSH_SELECT, FIRST_SPEEDUP_SLOT);
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_PCFLUSH_ADDR, 0x6026398);
+ cpunum_set_info_int(1, CPUINFO_INT_SH2_PCFLUSH_SELECT, FIRST_SPEEDUP_SLOT);
+ cpunum_set_info_int(1, CPUINFO_INT_SH2_PCFLUSH_ADDR, 0x6028cd6);
+
install_standard_protection(machine);
memory_install_read32_handler(machine, 0, ADDRESS_SPACE_PROGRAM, 0x060ffc10, 0x060ffc13, 0, 0, sss_speedup_r );
cpunum_set_info_fct(1, CPUINFO_PTR_SH2_FTCSR_READ_CALLBACK, (genf*)sss_slave_speedup );
@@ -1078,13 +1230,13 @@ DRIVER_INIT(sss)
static READ32_HANDLER(othellos_speedup_r)
{
- if ( activecpu_get_pc() == 0x0602bcc0 ) cpu_spinuntil_time(ATTOTIME_IN_USEC(20));
+ if ( activecpu_get_pc() == 0x0602bcbe ) cpu_spinuntil_time(ATTOTIME_IN_USEC(20));
return stv_workram_h[0x000ffc10/4];
}
static void othellos_slave_speedup( UINT32 data )
{
- if (activecpu_get_pc() == 0x0602d930 )
+ if (activecpu_get_pc() == 0x0602d92e )
if ( (data & 0x00800000) == 0 )
if ( (stv_workram_h[0x0ffc48/4] != 0x260fd25c ) )
{
@@ -1095,6 +1247,11 @@ static void othellos_slave_speedup( UINT32 data )
DRIVER_INIT(othellos)
{
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_PCFLUSH_SELECT, FIRST_SPEEDUP_SLOT);
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_PCFLUSH_ADDR, 0x602bcbe);
+ cpunum_set_info_int(1, CPUINFO_INT_SH2_PCFLUSH_SELECT, FIRST_SPEEDUP_SLOT);
+ cpunum_set_info_int(1, CPUINFO_INT_SH2_PCFLUSH_ADDR, 0x602d92e);
+
memory_install_read32_handler(machine, 0, ADDRESS_SPACE_PROGRAM, 0x060ffc10, 0x060ffc13, 0, 0, othellos_speedup_r );
cpunum_set_info_fct(1, CPUINFO_PTR_SH2_FTCSR_READ_CALLBACK, (genf*)othellos_slave_speedup );
@@ -1106,13 +1263,16 @@ DRIVER_INIT(othellos)
static void sasissu_slave_speedup( UINT32 data )
{
- if ( activecpu_get_pc() == 0x060710C0 )
+ if ( activecpu_get_pc() == 0x060710be )
if ( (data & 0x00800000) == 0 )
cpunum_spinuntil_trigger(1, 1000);
}
DRIVER_INIT(sasissu)
{
+ cpunum_set_info_int(1, CPUINFO_INT_SH2_PCFLUSH_SELECT, FIRST_SPEEDUP_SLOT);
+ cpunum_set_info_int(1, CPUINFO_INT_SH2_PCFLUSH_ADDR, 0x60710be);
+
cpunum_set_info_fct(1, CPUINFO_PTR_SH2_FTCSR_READ_CALLBACK, (genf*)sasissu_slave_speedup );
DRIVER_INIT_CALL(ic13);
@@ -1122,24 +1282,30 @@ DRIVER_INIT(sasissu)
static READ32_HANDLER(gaxeduel_speedup_r)
{
- if ( activecpu_get_pc() == 0x06012ee6 ) cpu_spinuntil_int();
+ if ( activecpu_get_pc() == 0x06012ee4 ) cpu_spinuntil_int();
return stv_workram_l[0x000f4068 / 4];
}
DRIVER_INIT(gaxeduel)
{
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_PCFLUSH_SELECT, FIRST_SPEEDUP_SLOT);
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_PCFLUSH_ADDR, 0x6012ee4);
+
memory_install_read32_handler(machine, 0, ADDRESS_SPACE_PROGRAM, 0x002f4068, 0x002f406b, 0, 0, gaxeduel_speedup_r);
DRIVER_INIT_CALL(ic13);
}
static READ32_HANDLER(suikoenb_speedup_r)
{
- if ( activecpu_get_pc() == 0x06013f7c ) cpu_spinuntil_int();
+ if ( activecpu_get_pc() == 0x06013f7a ) cpu_spinuntil_int();
return stv_workram_h[0x000705d0 / 4];
}
DRIVER_INIT(suikoenb)
{
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_PCFLUSH_SELECT, FIRST_SPEEDUP_SLOT);
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_PCFLUSH_ADDR, 0x6013f7a);
+
memory_install_read32_handler(machine, 0, ADDRESS_SPACE_PROGRAM, 0x060705d0, 0x060705d3, 0, 0, suikoenb_speedup_r);
DRIVER_INIT_CALL(ic13);
}
@@ -1148,19 +1314,24 @@ static void sokyugrt_slave_speedup( UINT32 data )
{
logerror( "SlaveSH2: Idle loop skip, data = %08X\n", data );
if (stv_enable_slave_sh2)
- if ( activecpu_get_pc() == 0x0605eec2 )
+ if ( activecpu_get_pc() == 0x0605eec0 )
if ( (data & 0x00800000) == 0 )
cpunum_spinuntil_trigger(1, 1000);
}
static READ32_HANDLER(sokyugrt_speedup_r)
{
- if ( activecpu_get_pc() == 0x0605d9dc ) cpu_spinuntil_int();
+ if ( activecpu_get_pc() == 0x0605d9da ) cpu_spinuntil_int();
return stv_workram_h[0x000788cc / 4];
}
DRIVER_INIT(sokyugrt)
{
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_PCFLUSH_SELECT, FIRST_SPEEDUP_SLOT);
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_PCFLUSH_ADDR, 0x605d9da);
+ cpunum_set_info_int(1, CPUINFO_INT_SH2_PCFLUSH_SELECT, FIRST_SPEEDUP_SLOT);
+ cpunum_set_info_int(1, CPUINFO_INT_SH2_PCFLUSH_ADDR, 0x605eec0);
+
cpunum_set_info_fct(1, CPUINFO_PTR_SH2_FTCSR_READ_CALLBACK, (genf*)sokyugrt_slave_speedup );
memory_install_read32_handler(machine, 0, ADDRESS_SPACE_PROGRAM, 0x060788cc, 0x060788cf, 0, 0, sokyugrt_speedup_r);
DRIVER_INIT_CALL(ic13);
@@ -1170,13 +1341,13 @@ DRIVER_INIT(sokyugrt)
static READ32_HANDLER( znpwfv_speedup_r )
{
- if (activecpu_get_pc()==0x6012ec4) cpu_spinuntil_time(ATTOTIME_IN_USEC(20));
+ if (activecpu_get_pc()==0x6012ec2) cpu_spinuntil_time(ATTOTIME_IN_USEC(20));
return stv_workram_h[0x0ffc10/4];
}
static void znpwfv_slave_speedup( UINT32 data )
{
- if ( activecpu_get_pc() == 0x060175a8 )
+ if ( activecpu_get_pc() == 0x060175a6 )
if ( (data & 0x00800000) == 0 )
{
if (
@@ -1194,6 +1365,11 @@ static void znpwfv_slave_speedup( UINT32 data )
DRIVER_INIT(znpwfv)
{
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_PCFLUSH_SELECT, FIRST_SPEEDUP_SLOT);
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_PCFLUSH_ADDR, 0x6012ec2);
+ cpunum_set_info_int(1, CPUINFO_INT_SH2_PCFLUSH_SELECT, FIRST_SPEEDUP_SLOT);
+ cpunum_set_info_int(1, CPUINFO_INT_SH2_PCFLUSH_ADDR, 0x60175a6);
+
cpunum_set_info_fct(1, CPUINFO_PTR_SH2_FTCSR_READ_CALLBACK, (genf*)znpwfv_slave_speedup );
memory_install_read32_handler(machine, 0, ADDRESS_SPACE_PROGRAM, 0x60ffc10, 0x60ffc13, 0, 0, znpwfv_speedup_r );
@@ -1203,19 +1379,24 @@ DRIVER_INIT(znpwfv)
static READ32_HANDLER( twcup98_speedup_r )
{
- if (activecpu_get_pc()==0x605ede0) cpu_spinuntil_time(ATTOTIME_IN_USEC(20));
+ if (activecpu_get_pc()==0x605edde) cpu_spinuntil_time(ATTOTIME_IN_USEC(20));
return stv_workram_h[0x0ffc10/4];
}
static void twcup98_slave_speedup( UINT32 data )
{
- if ( activecpu_get_pc() == 0x06062bcc )
+ if ( activecpu_get_pc() == 0x06062bca )
if ( (data & 0x00800000) == 0 )
cpunum_spinuntil_trigger(1, 1000);
}
DRIVER_INIT(twcup98)
{
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_PCFLUSH_SELECT, FIRST_SPEEDUP_SLOT);
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_PCFLUSH_ADDR, 0x605edde);
+ cpunum_set_info_int(1, CPUINFO_INT_SH2_PCFLUSH_SELECT, FIRST_SPEEDUP_SLOT);
+ cpunum_set_info_int(1, CPUINFO_INT_SH2_PCFLUSH_ADDR, 0x6062bca);
+
cpunum_set_info_fct(1, CPUINFO_PTR_SH2_FTCSR_READ_CALLBACK, (genf*)twcup98_slave_speedup );
memory_install_read32_handler(machine, 0, ADDRESS_SPACE_PROGRAM, 0x60ffc10, 0x60ffc13, 0, 0, twcup98_speedup_r );
@@ -1227,19 +1408,24 @@ DRIVER_INIT(twcup98)
static READ32_HANDLER( smleague_speedup_r )
{
- if (activecpu_get_pc()==0x6063bf6) cpu_spinuntil_time(ATTOTIME_IN_USEC(20));
+ if (activecpu_get_pc()==0x6063bf4) cpu_spinuntil_time(ATTOTIME_IN_USEC(20));
return stv_workram_h[0x0ffc10/4];
}
static void smleague_slave_speedup( UINT32 data )
{
- if ( activecpu_get_pc() == 0x06062bcc )
+ if ( activecpu_get_pc() == 0x06062bca )
if ( (data & 0x00800000) == 0 )
cpunum_spinuntil_trigger(1, 1000);
}
DRIVER_INIT(smleague)
{
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_PCFLUSH_SELECT, FIRST_SPEEDUP_SLOT);
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_PCFLUSH_ADDR, 0x6063bf4);
+ cpunum_set_info_int(1, CPUINFO_INT_SH2_PCFLUSH_SELECT, FIRST_SPEEDUP_SLOT);
+ cpunum_set_info_int(1, CPUINFO_INT_SH2_PCFLUSH_ADDR, 0x6062bca);
+
cpunum_set_info_fct(1, CPUINFO_PTR_SH2_FTCSR_READ_CALLBACK, (genf*)smleague_slave_speedup );
memory_install_read32_handler(machine, 0, ADDRESS_SPACE_PROGRAM, 0x60ffc10, 0x60ffc13, 0, 0, smleague_speedup_r );
@@ -1250,13 +1436,16 @@ DRIVER_INIT(smleague)
static READ32_HANDLER( finlarch_speedup_r )
{
- if (activecpu_get_pc()==0x6064d62) cpu_spinuntil_int();
+ if (activecpu_get_pc()==0x6064d60) cpu_spinuntil_int();
return stv_workram_h[0x0ffc10/4];
}
DRIVER_INIT(finlarch)
{
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_PCFLUSH_SELECT, FIRST_SPEEDUP_SLOT);
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_PCFLUSH_ADDR, 0x6064d60);
+
memory_install_read32_handler(machine, 0, ADDRESS_SPACE_PROGRAM, 0x60ffc10, 0x60ffc13, 0, 0, finlarch_speedup_r );
DRIVER_INIT_CALL(ic13);
@@ -1265,13 +1454,13 @@ DRIVER_INIT(finlarch)
static READ32_HANDLER( maruchan_speedup_r )
{
- if (activecpu_get_pc()==0x06012a54) cpu_spinuntil_time(ATTOTIME_IN_USEC(20));
+ if (activecpu_get_pc()==0x06012a52) cpu_spinuntil_time(ATTOTIME_IN_USEC(20));
return stv_workram_h[0x0ffc10/4];
}
static void maruchan_slave_speedup( UINT32 data )
{
- if ( activecpu_get_pc() == 0x0601ba48 )
+ if ( activecpu_get_pc() == 0x0601ba46 )
if ( (data & 0x00800000) == 0 )
if (
(stv_workram_h[0x0ffc48/4] != 0x260ef3c8) &&
@@ -1287,6 +1476,11 @@ static void maruchan_slave_speedup( UINT32 data )
DRIVER_INIT(maruchan)
{
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_PCFLUSH_SELECT, FIRST_SPEEDUP_SLOT);
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_PCFLUSH_ADDR, 0x601ba46);
+ cpunum_set_info_int(1, CPUINFO_INT_SH2_PCFLUSH_SELECT, FIRST_SPEEDUP_SLOT);
+ cpunum_set_info_int(1, CPUINFO_INT_SH2_PCFLUSH_ADDR, 0x601ba46);
+
cpunum_set_info_fct(1, CPUINFO_PTR_SH2_FTCSR_READ_CALLBACK, (genf*)maruchan_slave_speedup );
memory_install_read32_handler(machine, 0, ADDRESS_SPACE_PROGRAM, 0x60ffc10, 0x60ffc13, 0, 0, maruchan_speedup_r );
@@ -1297,7 +1491,7 @@ DRIVER_INIT(maruchan)
static READ32_HANDLER( pblbeach_speedup_r )
{
- if (activecpu_get_pc()==0x0605eb7a)
+ if (activecpu_get_pc()==0x0605eb78)
if (stv_workram_h[0x006c398/4] != 0)
cpu_spinuntil_int();
return stv_workram_h[0x006c398/4];
@@ -1305,6 +1499,9 @@ static READ32_HANDLER( pblbeach_speedup_r )
DRIVER_INIT(pblbeach)
{
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_PCFLUSH_SELECT, FIRST_SPEEDUP_SLOT);
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_PCFLUSH_ADDR, 0x605eb78);
+
memory_install_read32_handler(machine, 0, ADDRESS_SPACE_PROGRAM, 0x0606c398, 0x0606c39b, 0, 0, pblbeach_speedup_r );
DRIVER_INIT_CALL(ic13);
@@ -1312,13 +1509,16 @@ DRIVER_INIT(pblbeach)
static READ32_HANDLER( shanhigw_speedup_r )
{
- if (activecpu_get_pc()==0x06020c5e)
+ if (activecpu_get_pc()==0x06020c5c)
cpu_spinuntil_int();
return stv_workram_h[0x95cd8/4];
}
DRIVER_INIT(shanhigw)
{
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_PCFLUSH_SELECT, FIRST_SPEEDUP_SLOT);
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_PCFLUSH_ADDR, 0x6020c5c);
+
memory_install_read32_handler(machine, 0, ADDRESS_SPACE_PROGRAM, 0x06095cd8, 0x06095cdb, 0, 0, shanhigw_speedup_r );
DRIVER_INIT_CALL(stv);
@@ -1326,14 +1526,14 @@ DRIVER_INIT(shanhigw)
static READ32_HANDLER( elandore_speedup_r )
{
- if (activecpu_get_pc()==0x0604eac2) cpu_spinuntil_time(ATTOTIME_IN_USEC(20));
+ if (activecpu_get_pc()==0x0604eac0) cpu_spinuntil_time(ATTOTIME_IN_USEC(20));
return stv_workram_h[0x0ffc10/4];
}
static void elandore_slave_speedup(UINT32 data)
{
- if (activecpu_get_pc() == 0x0605340c)
+ if (activecpu_get_pc() == 0x0605340a)
if ( (data & 0x00800000) == 0 )
if ( (stv_workram_h[0x0ffc48/4] != 0x260ee018) )
{
@@ -1345,6 +1545,11 @@ static void elandore_slave_speedup(UINT32 data)
DRIVER_INIT(elandore)
{
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_PCFLUSH_SELECT, FIRST_SPEEDUP_SLOT);
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_PCFLUSH_ADDR, 0x604eac0);
+ cpunum_set_info_int(1, CPUINFO_INT_SH2_PCFLUSH_SELECT, FIRST_SPEEDUP_SLOT);
+ cpunum_set_info_int(1, CPUINFO_INT_SH2_PCFLUSH_ADDR, 0x605340a);
+
install_standard_protection(machine);
memory_install_read32_handler(machine, 0, ADDRESS_SPACE_PROGRAM, 0x60ffc10, 0x60ffc13, 0, 0, elandore_speedup_r );
cpunum_set_info_fct(1, CPUINFO_PTR_SH2_FTCSR_READ_CALLBACK, (genf *)elandore_slave_speedup);
@@ -1355,13 +1560,13 @@ DRIVER_INIT(elandore)
static READ32_HANDLER( rsgun_speedup_r )
{
- if (activecpu_get_pc()==0x06034d06) cpu_spinuntil_time(ATTOTIME_IN_USEC(20));
+ if (activecpu_get_pc()==0x06034d04) cpu_spinuntil_time(ATTOTIME_IN_USEC(20));
return stv_workram_h[0x0ffc10/4];
}
static void rsgun_slave_speedup(UINT32 data)
{
- if (activecpu_get_pc() == 0x06036154)
+ if (activecpu_get_pc() == 0x06036152)
if ( (data & 0x00800000) == 0 )
if ((stv_workram_h[0x0ffc48/4] != 0x260efc50))
{
@@ -1373,6 +1578,11 @@ static void rsgun_slave_speedup(UINT32 data)
DRIVER_INIT(rsgun)
{
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_PCFLUSH_SELECT, FIRST_SPEEDUP_SLOT);
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_PCFLUSH_ADDR, 0x6034d04);
+ cpunum_set_info_int(1, CPUINFO_INT_SH2_PCFLUSH_SELECT, FIRST_SPEEDUP_SLOT);
+ cpunum_set_info_int(1, CPUINFO_INT_SH2_PCFLUSH_ADDR, 0x6036152);
+
install_standard_protection(machine);
memory_install_read32_handler(machine, 0, ADDRESS_SPACE_PROGRAM, 0x60ffc10, 0x60ffc13, 0, 0, rsgun_speedup_r );
cpunum_set_info_fct(1, CPUINFO_PTR_SH2_FTCSR_READ_CALLBACK, (genf *)rsgun_slave_speedup);
@@ -1397,19 +1607,24 @@ DRIVER_INIT(decathlt)
static READ32_HANDLER( nameclv3_speedup_r )
{
- if (activecpu_get_pc()==0x601eb4e) cpu_spinuntil_time(ATTOTIME_IN_USEC(30));
+ if (activecpu_get_pc()==0x601eb4c) cpu_spinuntil_time(ATTOTIME_IN_USEC(30));
return stv_workram_h[0x0452c0/4];
}
static void nameclv3_slave_speedup( UINT32 data )
{
- if ( activecpu_get_pc() == 0x0602B810 )
+ if ( activecpu_get_pc() == 0x0602B80e )
if ( (data & 0x00800000) == 0 )
cpunum_spinuntil_trigger(1, 1000);
}
DRIVER_INIT(nameclv3)
{
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_PCFLUSH_SELECT, FIRST_SPEEDUP_SLOT);
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_PCFLUSH_ADDR, 0x601eb4c);
+ cpunum_set_info_int(1, CPUINFO_INT_SH2_PCFLUSH_SELECT, FIRST_SPEEDUP_SLOT);
+ cpunum_set_info_int(1, CPUINFO_INT_SH2_PCFLUSH_ADDR, 0x602b80e);
+
memory_install_read32_handler(machine, 0, ADDRESS_SPACE_PROGRAM, 0x60452c0, 0x60452c3, 0, 0, nameclv3_speedup_r );
cpunum_set_info_fct(1, CPUINFO_PTR_SH2_FTCSR_READ_CALLBACK, (genf*)nameclv3_slave_speedup );
DRIVER_INIT_CALL(stv);
diff --git a/src/mame/drivers/suprnova.c b/src/mame/drivers/suprnova.c
index da97adc87f8..224f488abd1 100644
--- a/src/mame/drivers/suprnova.c
+++ b/src/mame/drivers/suprnova.c
@@ -186,6 +186,7 @@ NEP-16
#include "driver.h"
#include "deprecat.h"
#include "sound/ymz280b.h"
+#include "cpu/sh2/sh2.h"
#define BIOS_SKIP 1 // Skip Bios as it takes too long and doesn't complete atm.
@@ -770,7 +771,7 @@ static WRITE32_HANDLER( skns_io_w )
cpunum_set_input_line(machine, 0,0xf,CLEAR_LINE);*/
/* idle skip for vblokbrk/sarukani, i can't find a better place to put it :-( but i think it works ok unless its making the game too fast */
- if (activecpu_get_pc()==0x04013B44)
+ if (activecpu_get_pc()==0x04013B42)
{
if (!strcmp(machine->gamedrv->name,"vblokbrk") ||
!strcmp(machine->gamedrv->name,"sarukani"))
@@ -986,7 +987,7 @@ MACHINE_DRIVER_END
static READ32_HANDLER( bios_skip_r )
{
#if BIOS_SKIP
- if (activecpu_get_pc()==0x6fa) program_write_byte(0x06000029,1);
+ if ((activecpu_get_pc()==0x6f8) || (activecpu_get_pc()==0x6fa)) program_write_byte(0x06000029,1);
#endif
return skns_main_ram[0x00028/4];
}
@@ -1003,7 +1004,7 @@ static READ32_HANDLER( gutsn_speedup_r )
04022072: CMP/EQ R2,R3
04022074: BT $0402206C
*/
- if (activecpu_get_pc()==0x4022070)
+ if (activecpu_get_pc()==0x402206e)
{
if(skns_main_ram[0x00078/4] == skns_main_ram[0x0c780/4])
cpu_spinuntil_int();
@@ -1013,19 +1014,19 @@ static READ32_HANDLER( gutsn_speedup_r )
static READ32_HANDLER( cyvern_speedup_r )
{
- if (activecpu_get_pc()==0x402ebd4) cpu_spinuntil_int();
+ if (activecpu_get_pc()==0x402ebd2) cpu_spinuntil_int();
return skns_main_ram[0x4d3c8/4];
}
static READ32_HANDLER( puzloopj_speedup_r )
{
- if (activecpu_get_pc()==0x401dca2) cpu_spinuntil_int();
+ if (activecpu_get_pc()==0x401dca0) cpu_spinuntil_int();
return skns_main_ram[0x86714/4];
}
static READ32_HANDLER( puzloopu_speedup_r )
{
- if (activecpu_get_pc()==0x401dab2) cpu_spinuntil_int();
+ if (activecpu_get_pc()==0x401dab0) cpu_spinuntil_int();
return skns_main_ram[0x85cec/4];
}
@@ -1038,86 +1039,97 @@ static READ32_HANDLER( puzzloop_speedup_r )
0401DA18: BF $0401DA26
0401DA26: BRA $0401DA12
*/
- if (activecpu_get_pc()==0x401da16) cpu_spinuntil_int();
+ if (activecpu_get_pc()==0x401da14) cpu_spinuntil_int();
return skns_main_ram[0x81d38/4];
}
static READ32_HANDLER( senknow_speedup_r )
{
- if (activecpu_get_pc()==0x4017dd0) cpu_spinuntil_int();
+ if (activecpu_get_pc()==0x4017dce) cpu_spinuntil_int();
return skns_main_ram[0x0000dc/4];
}
static READ32_HANDLER( teljan_speedup_r )
{
- if (activecpu_get_pc()==0x401ba34) cpu_spinuntil_int();
+ if (activecpu_get_pc()==0x401ba32) cpu_spinuntil_int();
return skns_main_ram[0x002fb4/4];
}
static READ32_HANDLER( jjparads_speedup_r )
{
- if (activecpu_get_pc()==0x4015e86) cpu_spinuntil_int();
+ if (activecpu_get_pc()==0x4015e84) cpu_spinuntil_int();
return skns_main_ram[0x000994/4];
}
static READ32_HANDLER( jjparad2_speedup_r )
{
- if (activecpu_get_pc()==0x401620c) cpu_spinuntil_int();
+ if (activecpu_get_pc()==0x401620a) cpu_spinuntil_int();
return skns_main_ram[0x000984/4];
}
static READ32_HANDLER( ryouran_speedup_r )
{
- if (activecpu_get_pc()==0x40182d0) cpu_spinuntil_int();
+ if (activecpu_get_pc()==0x40182ce) cpu_spinuntil_int();
return skns_main_ram[0x000a14/4];
}
static READ32_HANDLER( galpans2_speedup_r )
{
- if (activecpu_get_pc()==0x4049ae4) cpu_spinuntil_int();
+ if (activecpu_get_pc()==0x4049ae2) cpu_spinuntil_int();
return skns_main_ram[0x0fb6bc/4];
}
static READ32_HANDLER( panicstr_speedup_r )
{
- if (activecpu_get_pc()==0x404e68c) cpu_spinuntil_int();
+ if (activecpu_get_pc()==0x404e68a) cpu_spinuntil_int();
return skns_main_ram[0x0f19e4/4];
}
static READ32_HANDLER( sengekis_speedup_r ) // 60006ee 600308e
{
- if (activecpu_get_pc()==0x60006ee) cpu_spinuntil_int();
+ if (activecpu_get_pc()==0x60006ec) cpu_spinuntil_int();
return skns_main_ram[0xb74bc/4];
}
static READ32_HANDLER( sengekij_speedup_r ) // 60006ee 600308e
{
- if (activecpu_get_pc()==0x60006ee) cpu_spinuntil_int();
+ if (activecpu_get_pc()==0x60006ec) cpu_spinuntil_int();
return skns_main_ram[0xb7380/4];
}
static void init_skns(running_machine *machine)
{
+ // init DRC to fastest options
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_DRC_OPTIONS, SH2DRC_FASTEST_OPTIONS);
+
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_PCFLUSH_SELECT, 0);
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_PCFLUSH_ADDR, 0x6f8);
memory_install_read32_handler(machine, 0, ADDRESS_SPACE_PROGRAM, 0x6000028, 0x600002b, 0, 0, bios_skip_r );
}
-static DRIVER_INIT( galpani4 ) { skns_sprite_kludge(-5,-1); init_skns(machine); } // Idle Loop caught by sh-2 core
-static DRIVER_INIT( galpanis ) { skns_sprite_kludge(-5,-1); init_skns(machine); } // Idle Loop caught by sh-2 core
-static DRIVER_INIT( cyvern ) { skns_sprite_kludge(+0,+2); init_skns(machine); memory_install_read32_handler(machine, 0, ADDRESS_SPACE_PROGRAM, 0x604d3c8, 0x604d3cb, 0, 0, cyvern_speedup_r ); }
-static DRIVER_INIT( galpans2 ) { skns_sprite_kludge(-1,-1); init_skns(machine); memory_install_read32_handler(machine, 0, ADDRESS_SPACE_PROGRAM, 0x60fb6bc, 0x60fb6bf, 0, 0, galpans2_speedup_r ); }
-static DRIVER_INIT( gutsn ) { skns_sprite_kludge(+0,+0); init_skns(machine); memory_install_read32_handler(machine, 0, ADDRESS_SPACE_PROGRAM, 0x600c780, 0x600c783, 0, 0, gutsn_speedup_r ); }
-static DRIVER_INIT( panicstr ) { skns_sprite_kludge(-1,-1); init_skns(machine); memory_install_read32_handler(machine, 0, ADDRESS_SPACE_PROGRAM, 0x60f19e4, 0x60f19e7, 0, 0, panicstr_speedup_r ); }
-static DRIVER_INIT( senknow ) { skns_sprite_kludge(+1,+1); init_skns(machine); memory_install_read32_handler(machine, 0, ADDRESS_SPACE_PROGRAM, 0x60000dc, 0x60000df, 0, 0, senknow_speedup_r ); }
-static DRIVER_INIT( puzzloop ) { skns_sprite_kludge(-9,-1); init_skns(machine); memory_install_read32_handler(machine, 0, ADDRESS_SPACE_PROGRAM, 0x6081d38, 0x6081d3b, 0, 0, puzzloop_speedup_r ); }
-static DRIVER_INIT( puzloopj ) { skns_sprite_kludge(-9,-1); init_skns(machine); memory_install_read32_handler(machine, 0, ADDRESS_SPACE_PROGRAM, 0x6086714, 0x6086717, 0, 0, puzloopj_speedup_r ); }
-static DRIVER_INIT( puzloopu ) { skns_sprite_kludge(-9,-1); init_skns(machine); memory_install_read32_handler(machine, 0, ADDRESS_SPACE_PROGRAM, 0x6085cec, 0x6085cef, 0, 0, puzloopu_speedup_r ); }
-static DRIVER_INIT( jjparads ) { skns_sprite_kludge(+5,+1); init_skns(machine); memory_install_read32_handler(machine, 0, ADDRESS_SPACE_PROGRAM, 0x6000994, 0x6000997, 0, 0, jjparads_speedup_r ); }
-static DRIVER_INIT( jjparad2 ) { skns_sprite_kludge(+5,+1); init_skns(machine); memory_install_read32_handler(machine, 0, ADDRESS_SPACE_PROGRAM, 0x6000984, 0x6000987, 0, 0, jjparad2_speedup_r ); }
-static DRIVER_INIT( ryouran ) { skns_sprite_kludge(+5,+1); init_skns(machine); memory_install_read32_handler(machine, 0, ADDRESS_SPACE_PROGRAM, 0x6000a14, 0x6000a17, 0, 0, ryouran_speedup_r ); }
-static DRIVER_INIT( teljan ) { skns_sprite_kludge(+5,+1); init_skns(machine); memory_install_read32_handler(machine, 0, ADDRESS_SPACE_PROGRAM, 0x6002fb4, 0x6002fb7, 0, 0, teljan_speedup_r ); }
-static DRIVER_INIT( sengekis ) { skns_sprite_kludge(-192,-272); init_skns(machine); memory_install_read32_handler(machine, 0, ADDRESS_SPACE_PROGRAM, 0x60b74bc, 0x60b74bf, 0, 0, sengekis_speedup_r ); }
-static DRIVER_INIT( sengekij ) { skns_sprite_kludge(-192,-272); init_skns(machine); memory_install_read32_handler(machine, 0, ADDRESS_SPACE_PROGRAM, 0x60b7380, 0x60b7383, 0, 0, sengekij_speedup_r ); }
-static DRIVER_INIT( sarukani ) { skns_sprite_kludge(-1,-1); init_skns(machine); } // Speedup is in skns_io_w()
+static void set_drc_pcflush(UINT32 addr)
+{
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_PCFLUSH_SELECT, 1);
+ cpunum_set_info_int(0, CPUINFO_INT_SH2_PCFLUSH_ADDR, addr);
+}
+
+static DRIVER_INIT( galpani4 ) { skns_sprite_kludge(-5,-1); init_skns(machine); }
+static DRIVER_INIT( galpanis ) { skns_sprite_kludge(-5,-1); init_skns(machine); }
+static DRIVER_INIT( cyvern ) { skns_sprite_kludge(+0,+2); init_skns(machine); memory_install_read32_handler(machine, 0, ADDRESS_SPACE_PROGRAM, 0x604d3c8, 0x604d3cb, 0, 0, cyvern_speedup_r ); set_drc_pcflush(0x402ebd2); }
+static DRIVER_INIT( galpans2 ) { skns_sprite_kludge(-1,-1); init_skns(machine); memory_install_read32_handler(machine, 0, ADDRESS_SPACE_PROGRAM, 0x60fb6bc, 0x60fb6bf, 0, 0, galpans2_speedup_r ); set_drc_pcflush(0x4049ae2); }
+static DRIVER_INIT( gutsn ) { skns_sprite_kludge(+0,+0); init_skns(machine); memory_install_read32_handler(machine, 0, ADDRESS_SPACE_PROGRAM, 0x600c780, 0x600c783, 0, 0, gutsn_speedup_r ); set_drc_pcflush(0x402206e); }
+static DRIVER_INIT( panicstr ) { skns_sprite_kludge(-1,-1); init_skns(machine); memory_install_read32_handler(machine, 0, ADDRESS_SPACE_PROGRAM, 0x60f19e4, 0x60f19e7, 0, 0, panicstr_speedup_r ); set_drc_pcflush(0x404e68a); }
+static DRIVER_INIT( senknow ) { skns_sprite_kludge(+1,+1); init_skns(machine); memory_install_read32_handler(machine, 0, ADDRESS_SPACE_PROGRAM, 0x60000dc, 0x60000df, 0, 0, senknow_speedup_r ); set_drc_pcflush(0x4017dce); }
+static DRIVER_INIT( puzzloop ) { skns_sprite_kludge(-9,-1); init_skns(machine); memory_install_read32_handler(machine, 0, ADDRESS_SPACE_PROGRAM, 0x6081d38, 0x6081d3b, 0, 0, puzzloop_speedup_r ); set_drc_pcflush(0x401da14); }
+static DRIVER_INIT( puzloopj ) { skns_sprite_kludge(-9,-1); init_skns(machine); memory_install_read32_handler(machine, 0, ADDRESS_SPACE_PROGRAM, 0x6086714, 0x6086717, 0, 0, puzloopj_speedup_r ); set_drc_pcflush(0x401dca0); }
+static DRIVER_INIT( puzloopu ) { skns_sprite_kludge(-9,-1); init_skns(machine); memory_install_read32_handler(machine, 0, ADDRESS_SPACE_PROGRAM, 0x6085cec, 0x6085cef, 0, 0, puzloopu_speedup_r ); set_drc_pcflush(0x401dab0); }
+static DRIVER_INIT( jjparads ) { skns_sprite_kludge(+5,+1); init_skns(machine); memory_install_read32_handler(machine, 0, ADDRESS_SPACE_PROGRAM, 0x6000994, 0x6000997, 0, 0, jjparads_speedup_r ); set_drc_pcflush(0x4015e84); }
+static DRIVER_INIT( jjparad2 ) { skns_sprite_kludge(+5,+1); init_skns(machine); memory_install_read32_handler(machine, 0, ADDRESS_SPACE_PROGRAM, 0x6000984, 0x6000987, 0, 0, jjparad2_speedup_r ); set_drc_pcflush(0x401620a); }
+static DRIVER_INIT( ryouran ) { skns_sprite_kludge(+5,+1); init_skns(machine); memory_install_read32_handler(machine, 0, ADDRESS_SPACE_PROGRAM, 0x6000a14, 0x6000a17, 0, 0, ryouran_speedup_r ); set_drc_pcflush(0x40182ce); }
+static DRIVER_INIT( teljan ) { skns_sprite_kludge(+5,+1); init_skns(machine); memory_install_read32_handler(machine, 0, ADDRESS_SPACE_PROGRAM, 0x6002fb4, 0x6002fb7, 0, 0, teljan_speedup_r ); set_drc_pcflush(0x401ba32); }
+static DRIVER_INIT( sengekis ) { skns_sprite_kludge(-192,-272); init_skns(machine); memory_install_read32_handler(machine, 0, ADDRESS_SPACE_PROGRAM, 0x60b74bc, 0x60b74bf, 0, 0, sengekis_speedup_r ); set_drc_pcflush(0x60006ec); }
+static DRIVER_INIT( sengekij ) { skns_sprite_kludge(-192,-272); init_skns(machine); memory_install_read32_handler(machine, 0, ADDRESS_SPACE_PROGRAM, 0x60b7380, 0x60b7383, 0, 0, sengekij_speedup_r ); set_drc_pcflush(0x60006ec); }
+static DRIVER_INIT( sarukani ) { skns_sprite_kludge(-1,-1); init_skns(machine); set_drc_pcflush(0x4013b42); } // Speedup is in skns_io_w()