summaryrefslogtreecommitdiffstatshomepage
path: root/trunk/src/emu/cpu/lr35902/lr35902.c
diff options
context:
space:
mode:
Diffstat (limited to 'trunk/src/emu/cpu/lr35902/lr35902.c')
-rw-r--r--trunk/src/emu/cpu/lr35902/lr35902.c495
1 files changed, 495 insertions, 0 deletions
diff --git a/trunk/src/emu/cpu/lr35902/lr35902.c b/trunk/src/emu/cpu/lr35902/lr35902.c
new file mode 100644
index 00000000000..13b40d46782
--- /dev/null
+++ b/trunk/src/emu/cpu/lr35902/lr35902.c
@@ -0,0 +1,495 @@
+/*************************************************************/
+/** **/
+/** lr35902.c **/
+/** **/
+/** This file contains implementation for the GameBoy CPU. **/
+/** See lr35902.h for the relevant definitions. Please, note**/
+/** that this code can not be used to emulate a generic Z80 **/
+/** because the GameBoy version of it differs from Z80 in **/
+/** many ways. **/
+/** **/
+/** Orginal cpu code (PlayBoy) Carsten Sorensen 1998 **/
+/** MESS modifications Hans de Goede 1998 **/
+/** Adapted to new cpuintrf Juergen Buchmueller 2000 **/
+/** Adapted to new cpuintrf Anthony Kruize 2002 **/
+/** Changed reset function to **/
+/** reset all registers instead **/
+/** of just AF. Wilbert Pol 2004 **/
+/** **/
+/** 1.1: **/
+/** Removed dependency on the mess gameboy driver **/
+/** **/
+/** 1.2: **/
+/** Fixed cycle count for taking an interrupt **/
+/** Fixed cycle count for BIT X,(HL) instructions **/
+/** Fixed flags in RRCA instruction **/
+/** Fixed DAA instruction **/
+/** Fixed flags in ADD SP,n8 instruction **/
+/** Fixed flags in LD HL,SP+n8 instruction **/
+/** **/
+/** 1.3: **/
+/** Improved triggering of the HALT bug **/
+/** Added 4 cycle penalty when leaving HALT state for **/
+/** newer versions of the cpu core **/
+/** **/
+/** 1.4: **/
+/** Split fetch and execute cycles. **/
+/** **/
+/*************************************************************/
+
+#include "emu.h"
+#include "debugger.h"
+#include "lr35902.h"
+
+#define FLAG_Z 0x80
+#define FLAG_N 0x40
+#define FLAG_H 0x20
+#define FLAG_C 0x10
+
+#define CYCLES_PASSED(X) cpustate->w.icount -= ((X) / (cpustate->w.gb_speed)); \
+ if ( cpustate->w.timer_expired_func ) { \
+ cpustate->w.timer_expired_func( cpustate->w.device, X ); \
+ }
+
+typedef struct {
+ UINT16 AF;
+ UINT16 BC;
+ UINT16 DE;
+ UINT16 HL;
+
+ UINT16 SP;
+ UINT16 PC;
+ /* Interrupt related */
+ UINT8 IE;
+ UINT8 IF;
+ int irq_state;
+ int ei_delay;
+ device_irq_callback irq_callback;
+ legacy_cpu_device *device;
+ address_space *program;
+ int icount;
+ /* Timer stuff */
+ lr35902_timer_fired_func timer_expired_func;
+ /* Fetch & execute related */
+ int execution_state;
+ UINT8 op;
+ /* Others */
+ int gb_speed;
+ int gb_speed_change_pending;
+ int enable;
+ int doHALTbug;
+ UINT8 features;
+ const lr35902_cpu_core *config;
+} lr35902_16BitRegs;
+
+#ifdef LSB_FIRST
+typedef struct {
+ UINT8 F;
+ UINT8 A;
+ UINT8 C;
+ UINT8 B;
+ UINT8 E;
+ UINT8 D;
+ UINT8 L;
+ UINT8 H;
+} lr35902_8BitRegs;
+#else
+typedef struct {
+ UINT8 A;
+ UINT8 F;
+ UINT8 B;
+ UINT8 C;
+ UINT8 D;
+ UINT8 E;
+ UINT8 H;
+ UINT8 L;
+} lr35902_8BitRegs;
+#endif
+
+
+typedef union _lr35902_state lr35902_state;
+union _lr35902_state {
+ lr35902_16BitRegs w;
+ lr35902_8BitRegs b;
+};
+
+INLINE lr35902_state *get_safe_token(device_t *device)
+{
+ assert(device != NULL);
+ assert(device->type() == LR35902);
+ return (lr35902_state *)downcast<legacy_cpu_device *>(device)->token();
+}
+
+typedef int (*OpcodeEmulator) (lr35902_state *cpustate);
+
+#define IME 0x01
+#define HALTED 0x02
+
+/****************************************************************************/
+/* Memory functions */
+/****************************************************************************/
+
+#define mem_ReadByte(cs,A) ((UINT8)(cs)->w.program->read_byte(A))
+#define mem_WriteByte(cs,A,V) ((cs)->w.program->write_byte(A,V))
+
+INLINE UINT16 mem_ReadWord (lr35902_state *cpustate, UINT32 address)
+{
+ UINT16 value = (UINT16) mem_ReadByte (cpustate, (address + 1) & 0xffff) << 8;
+ value |= mem_ReadByte (cpustate, address);
+ return value;
+}
+
+INLINE void mem_WriteWord (lr35902_state *cpustate, UINT32 address, UINT16 value)
+{
+ mem_WriteByte (cpustate, address, value & 0xFF);
+ mem_WriteByte (cpustate, (address + 1) & 0xffff, value >> 8);
+}
+
+static const int Cycles[256] =
+{
+ 4,12, 8, 8, 4, 4, 8, 4,20, 8, 8, 8, 4, 4, 8, 4,
+ 4,12, 8, 8, 4, 4, 8, 4,12, 8, 8, 8, 4, 4, 8, 4,
+ 8,12, 8, 8, 4, 4, 8, 4, 8, 8, 8, 8, 4, 4, 8, 4,
+ 8,12, 8, 8,12,12,12, 4, 8, 8, 8, 8, 4, 4, 8, 4,
+ 4, 4, 4, 4, 4, 4, 8, 4, 4, 4, 4, 4, 4, 4, 8, 4,
+ 4, 4, 4, 4, 4, 4, 8, 4, 4, 4, 4, 4, 4, 4, 8, 4,
+ 4, 4, 4, 4, 4, 4, 8, 4, 4, 4, 4, 4, 4, 4, 8, 4,
+ 8, 8, 8, 8, 8, 8, 4, 8, 4, 4, 4, 4, 4, 4, 8, 4,
+ 4, 4, 4, 4, 4, 4, 8, 4, 4, 4, 4, 4, 4, 4, 8, 4,
+ 4, 4, 4, 4, 4, 4, 8, 4, 4, 4, 4, 4, 4, 4, 8, 4,
+ 4, 4, 4, 4, 4, 4, 8, 4, 4, 4, 4, 4, 4, 4, 8, 4,
+ 4, 4, 4, 4, 4, 4, 8, 4, 4, 4, 4, 4, 4, 4, 8, 4,
+ 8,12,12,16,12,16, 8,16, 8,16,12, 0,12,24, 8,16,
+ 8,12,12, 4,12,16, 8,16, 8,16,12, 4,12, 4, 8,16,
+ 12,12, 8, 4, 4,16, 8,16,16, 4,16, 4, 4, 4, 8,16,
+ 12,12, 8, 4, 4,16, 8,16,12, 8,16, 4, 4, 4, 8,16
+};
+
+static const int CyclesCB[256] =
+{
+ 8, 8, 8, 8, 8, 8,16, 8, 8, 8, 8, 8, 8, 8,16, 8,
+ 8, 8, 8, 8, 8, 8,16, 8, 8, 8, 8, 8, 8, 8,16, 8,
+ 8, 8, 8, 8, 8, 8,16, 8, 8, 8, 8, 8, 8, 8,16, 8,
+ 8, 8, 8, 8, 8, 8,16, 8, 8, 8, 8, 8, 8, 8,16, 8,
+ 8, 8, 8, 8, 8, 8,12, 8, 8, 8, 8, 8, 8, 8,12, 8,
+ 8, 8, 8, 8, 8, 8,12, 8, 8, 8, 8, 8, 8, 8,12, 8,
+ 8, 8, 8, 8, 8, 8,12, 8, 8, 8, 8, 8, 8, 8,12, 8,
+ 8, 8, 8, 8, 8, 8,12, 8, 8, 8, 8, 8, 8, 8,12, 8,
+ 8, 8, 8, 8, 8, 8,16, 8, 8, 8, 8, 8, 8, 8,16, 8,
+ 8, 8, 8, 8, 8, 8,16, 8, 8, 8, 8, 8, 8, 8,16, 8,
+ 8, 8, 8, 8, 8, 8,16, 8, 8, 8, 8, 8, 8, 8,16, 8,
+ 8, 8, 8, 8, 8, 8,16, 8, 8, 8, 8, 8, 8, 8,16, 8,
+ 8, 8, 8, 8, 8, 8,16, 8, 8, 8, 8, 8, 8, 8,16, 8,
+ 8, 8, 8, 8, 8, 8,16, 8, 8, 8, 8, 8, 8, 8,16, 8,
+ 8, 8, 8, 8, 8, 8,16, 8, 8, 8, 8, 8, 8, 8,16, 8,
+ 8, 8, 8, 8, 8, 8,16, 8, 8, 8, 8, 8, 8, 8,16, 8
+};
+
+static CPU_INIT( lr35902 )
+{
+ lr35902_state *cpustate = get_safe_token(device);
+
+ cpustate->w.config = (const lr35902_cpu_core *) device->static_config();
+ cpustate->w.irq_callback = irqcallback;
+ cpustate->w.device = device;
+ cpustate->w.program = device->space(AS_PROGRAM);
+}
+
+/*** Reset lr353902 registers: ******************************/
+/*** This function can be used to reset the register ***/
+/*** file before starting execution with lr35902_execute(cpustate)***/
+/*** It sets the registers to their initial values. ***/
+/************************************************************/
+static CPU_RESET( lr35902 )
+{
+ lr35902_state *cpustate = get_safe_token(device);
+
+ cpustate->w.AF = 0x0000;
+ cpustate->w.BC = 0x0000;
+ cpustate->w.DE = 0x0000;
+ cpustate->w.HL = 0x0000;
+ cpustate->w.SP = 0x0000;
+ cpustate->w.PC = 0x0000;
+ cpustate->w.timer_expired_func = NULL;
+ cpustate->w.features = LR35902_FEATURE_HALT_BUG;
+ if (cpustate->w.config)
+ {
+ if ( cpustate->w.config->regs ) {
+ cpustate->w.AF = cpustate->w.config->regs[0];
+ cpustate->w.BC = cpustate->w.config->regs[1];
+ cpustate->w.DE = cpustate->w.config->regs[2];
+ cpustate->w.HL = cpustate->w.config->regs[3];
+ cpustate->w.SP = cpustate->w.config->regs[4];
+ cpustate->w.PC = cpustate->w.config->regs[5];
+ }
+ cpustate->w.timer_expired_func = cpustate->w.config->timer_expired_func;
+ cpustate->w.features = cpustate->w.config->features;
+ }
+ cpustate->w.enable = 0;
+ cpustate->w.IE = 0;
+ cpustate->w.IF = 0;
+
+ cpustate->w.execution_state = 0;
+ cpustate->w.doHALTbug = 0;
+ cpustate->w.ei_delay = 0;
+ cpustate->w.gb_speed_change_pending = 0;
+ cpustate->w.gb_speed = 1;
+}
+
+INLINE void lr35902_ProcessInterrupts (lr35902_state *cpustate)
+{
+ UINT8 irq = cpustate->w.IE & cpustate->w.IF;
+
+ /* Interrupts should be taken after the first instruction after an EI instruction */
+ if (cpustate->w.ei_delay) {
+ cpustate->w.ei_delay = 0;
+ return;
+ }
+
+ /*
+ logerror("Attempting to process LR35902 Interrupt IRQ $%02X\n", irq);
+ logerror("Attempting to process LR35902 Interrupt IE $%02X\n", cpustate->w.IE);
+ logerror("Attempting to process LR35902 Interrupt IF $%02X\n", cpustate->w.IF);
+ */
+ if (irq)
+ {
+ int irqline = 0;
+ /*
+ logerror("LR35902 Interrupt IRQ $%02X\n", irq);
+ */
+
+ for( ; irqline < 5; irqline++ )
+ {
+ if( irq & (1<<irqline) )
+ {
+ if (cpustate->w.enable & HALTED)
+ {
+ cpustate->w.enable &= ~HALTED;
+ cpustate->w.PC++;
+ if ( cpustate->w.features & LR35902_FEATURE_HALT_BUG ) {
+ if ( ! ( cpustate->w.enable & IME ) ) {
+ /* Old cpu core (dmg/mgb/sgb) */
+ cpustate->w.doHALTbug = 1;
+ }
+ } else {
+ /* New cpu core (cgb/agb/ags) */
+ /* Adjust for internal syncing with video core */
+ /* This feature needs more investigation */
+ if ( irqline < 2 ) {
+ CYCLES_PASSED( 4 );
+ }
+ }
+ }
+ if ( cpustate->w.enable & IME ) {
+ if ( cpustate->w.irq_callback )
+ (*cpustate->w.irq_callback)(cpustate->w.device, irqline);
+ cpustate->w.enable &= ~IME;
+ cpustate->w.IF &= ~(1 << irqline);
+ CYCLES_PASSED( 20 );
+ cpustate->w.SP -= 2;
+ mem_WriteWord (cpustate, cpustate->w.SP, cpustate->w.PC);
+ cpustate->w.PC = 0x40 + irqline * 8;
+ /*logerror("LR35902 Interrupt PC $%04X\n", cpustate->w.PC );*/
+ return;
+ }
+ }
+ }
+ }
+}
+
+/************************************************************/
+/*** Execute lr35902 code for cycles cycles, return nr of ***/
+/*** cycles actually executed. ***/
+/************************************************************/
+static CPU_EXECUTE( lr35902 )
+{
+ lr35902_state *cpustate = get_safe_token(device);
+
+ do
+ {
+ if ( cpustate->w.execution_state ) {
+ UINT8 x;
+ /* Execute instruction */
+ switch( cpustate->w.op ) {
+#include "opc_main.h"
+ }
+ } else {
+ /* Fetch and count cycles */
+ lr35902_ProcessInterrupts (cpustate);
+ debugger_instruction_hook(device, cpustate->w.PC);
+ if ( cpustate->w.enable & HALTED ) {
+ CYCLES_PASSED( Cycles[0x76] );
+ cpustate->w.execution_state = 1;
+ } else {
+ cpustate->w.op = mem_ReadByte (cpustate, cpustate->w.PC++);
+ if ( cpustate->w.doHALTbug ) {
+ cpustate->w.PC--;
+ cpustate->w.doHALTbug = 0;
+ }
+ CYCLES_PASSED( Cycles[cpustate->w.op] );
+ }
+ }
+ cpustate->w.execution_state ^= 1;
+ } while (cpustate->w.icount > 0);
+}
+
+static CPU_BURN( lr35902 )
+{
+ lr35902_state *cpustate = get_safe_token(device);
+
+ if( cycles > 0 )
+ {
+ /* NOP takes 4 cycles per instruction */
+ int n = (cycles + 3) / 4;
+ cpustate->w.icount -= 4 * n;
+ }
+}
+
+static void lr35902_set_irq_line (lr35902_state *cpustate, int irqline, int state)
+{
+ /*logerror("setting irq line 0x%02x state 0x%08x\n", irqline, state);*/
+ //if( cpustate->w.irq_state == state )
+ // return;
+
+ cpustate->w.irq_state = state;
+ if( state == ASSERT_LINE )
+ {
+
+ cpustate->w.IF |= (0x01 << irqline);
+ /*logerror("LR35902 assert irq line %d ($%02X)\n", irqline, cpustate->w.IF);*/
+
+ }
+ else
+ {
+
+ cpustate->w.IF &= ~(0x01 << irqline);
+ /*logerror("LR35902 clear irq line %d ($%02X)\n", irqline, cpustate->w.IF);*/
+
+ }
+}
+
+#ifdef UNUSED_FUNCTION
+static void lr35902_clear_pending_interrupts (lr35902_state *cpustate)
+{
+ cpustate->w.IF = 0;
+}
+#endif
+
+static CPU_SET_INFO( lr35902 )
+{
+ lr35902_state *cpustate = get_safe_token(device);
+
+ switch (state)
+ {
+ /* --- the following bits of info are set as 64-bit signed integers --- */
+ case CPUINFO_INT_INPUT_STATE + 0:
+ case CPUINFO_INT_INPUT_STATE + 1:
+ case CPUINFO_INT_INPUT_STATE + 2:
+ case CPUINFO_INT_INPUT_STATE + 3:
+ case CPUINFO_INT_INPUT_STATE + 4: lr35902_set_irq_line(cpustate, state-CPUINFO_INT_INPUT_STATE, info->i); break;
+
+ case CPUINFO_INT_SP: cpustate->w.SP = info->i; break;
+ case CPUINFO_INT_PC: cpustate->w.PC = info->i; break;
+
+ case CPUINFO_INT_REGISTER + LR35902_PC: cpustate->w.PC = info->i; break;
+ case CPUINFO_INT_REGISTER + LR35902_SP: cpustate->w.SP = info->i; break;
+ case CPUINFO_INT_REGISTER + LR35902_AF: cpustate->w.AF = info->i; break;
+ case CPUINFO_INT_REGISTER + LR35902_BC: cpustate->w.BC = info->i; break;
+ case CPUINFO_INT_REGISTER + LR35902_DE: cpustate->w.DE = info->i; break;
+ case CPUINFO_INT_REGISTER + LR35902_HL: cpustate->w.HL = info->i; break;
+ case CPUINFO_INT_REGISTER + LR35902_IE: cpustate->w.IE = info->i; break;
+ case CPUINFO_INT_REGISTER + LR35902_IF: cpustate->w.IF = info->i; break;
+ case CPUINFO_INT_REGISTER + LR35902_SPEED: cpustate->w.gb_speed_change_pending = info->i & 0x01; break;
+ }
+}
+
+CPU_GET_INFO( lr35902 )
+{
+ lr35902_state *cpustate = (device != NULL && device->token() != NULL) ? get_safe_token(device) : NULL;
+
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case CPUINFO_INT_CONTEXT_SIZE: info->i = sizeof(lr35902_state); break;
+ case CPUINFO_INT_INPUT_LINES: info->i = 5; break;
+ case CPUINFO_INT_DEFAULT_IRQ_VECTOR: info->i = 0xff; break;
+ case DEVINFO_INT_ENDIANNESS: info->i = ENDIANNESS_LITTLE; 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 = 1; break;
+ case CPUINFO_INT_MAX_INSTRUCTION_BYTES: info->i = 4; break;
+ case CPUINFO_INT_MIN_CYCLES: info->i = 1; /* right? */ break;
+ case CPUINFO_INT_MAX_CYCLES: info->i = 16; /* right? */ break;
+
+ case DEVINFO_INT_DATABUS_WIDTH + AS_PROGRAM: info->i = 8; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_PROGRAM: info->i = 16; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_PROGRAM: info->i = 0; break;
+ case DEVINFO_INT_DATABUS_WIDTH + AS_DATA: info->i = 0; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_DATA: info->i = 0; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_DATA: info->i = 0; break;
+ case DEVINFO_INT_DATABUS_WIDTH + AS_IO: info->i = 8; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_IO: info->i = 16; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_IO: info->i = 0; break;
+
+ case CPUINFO_INT_SP: info->i = cpustate->w.SP; break;
+ case CPUINFO_INT_PC: info->i = cpustate->w.PC; break;
+ case CPUINFO_INT_PREVIOUSPC: info->i = 0; /* TODO??? */ break;
+
+ case CPUINFO_INT_INPUT_STATE + 0:
+ case CPUINFO_INT_INPUT_STATE + 1:
+ case CPUINFO_INT_INPUT_STATE + 2:
+ case CPUINFO_INT_INPUT_STATE + 3:
+ case CPUINFO_INT_INPUT_STATE + 4: info->i = cpustate->w.IF & (1 << (state-CPUINFO_INT_INPUT_STATE)); break;
+
+ case CPUINFO_INT_REGISTER + LR35902_PC: info->i = cpustate->w.PC; break;
+ case CPUINFO_INT_REGISTER + LR35902_SP: info->i = cpustate->w.SP; break;
+ case CPUINFO_INT_REGISTER + LR35902_AF: info->i = cpustate->w.AF; break;
+ case CPUINFO_INT_REGISTER + LR35902_BC: info->i = cpustate->w.BC; break;
+ case CPUINFO_INT_REGISTER + LR35902_DE: info->i = cpustate->w.DE; break;
+ case CPUINFO_INT_REGISTER + LR35902_HL: info->i = cpustate->w.HL; break;
+ case CPUINFO_INT_REGISTER + LR35902_IE: info->i = cpustate->w.IE; break;
+ case CPUINFO_INT_REGISTER + LR35902_IF: info->i = cpustate->w.IF; break;
+ case CPUINFO_INT_REGISTER + LR35902_SPEED: info->i = 0x7E | ( ( cpustate->w.gb_speed - 1 ) << 7 ) | cpustate->w.gb_speed_change_pending; break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_SET_INFO: info->setinfo = CPU_SET_INFO_NAME(lr35902); break;
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(lr35902); break;
+ case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(lr35902); break;
+ case CPUINFO_FCT_EXECUTE: info->execute = CPU_EXECUTE_NAME(lr35902); break;
+ case CPUINFO_FCT_BURN: info->burn = CPU_BURN_NAME(lr35902); break;
+ case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(lr35902); break;
+ case CPUINFO_PTR_INSTRUCTION_COUNTER: info->icount = &cpustate->w.icount; break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "LR35902"); break;
+ case DEVINFO_STR_FAMILY: strcpy(info->s, "Sharp LR35902"); break;
+ case DEVINFO_STR_VERSION: strcpy(info->s, "1.4"); break;
+ case DEVINFO_STR_SOURCE_FILE: strcpy(info->s, __FILE__); break;
+ case DEVINFO_STR_CREDITS: strcpy(info->s, "Copyright The MESS Team."); break;
+
+ case CPUINFO_STR_FLAGS:
+ sprintf(info->s, "%c%c%c%c%c%c%c%c",
+ cpustate->b.F & 0x80 ? 'Z':'.',
+ cpustate->b.F & 0x40 ? 'N':'.',
+ cpustate->b.F & 0x20 ? 'H':'.',
+ cpustate->b.F & 0x10 ? 'C':'.',
+ cpustate->b.F & 0x08 ? '3':'.',
+ cpustate->b.F & 0x04 ? '2':'.',
+ cpustate->b.F & 0x02 ? '1':'.',
+ cpustate->b.F & 0x01 ? '0':'.');
+ break;
+
+ case CPUINFO_STR_REGISTER + LR35902_PC: sprintf(info->s, "PC:%04X", cpustate->w.PC); break;
+ case CPUINFO_STR_REGISTER + LR35902_SP: sprintf(info->s, "SP:%04X", cpustate->w.SP); break;
+ case CPUINFO_STR_REGISTER + LR35902_AF: sprintf(info->s, "AF:%04X", cpustate->w.AF); break;
+ case CPUINFO_STR_REGISTER + LR35902_BC: sprintf(info->s, "BC:%04X", cpustate->w.BC); break;
+ case CPUINFO_STR_REGISTER + LR35902_DE: sprintf(info->s, "DE:%04X", cpustate->w.DE); break;
+ case CPUINFO_STR_REGISTER + LR35902_HL: sprintf(info->s, "HL:%04X", cpustate->w.HL); break;
+ case CPUINFO_STR_REGISTER + LR35902_IRQ_STATE: sprintf(info->s, "IRQ:%X", cpustate->w.enable & IME ); break;
+ case CPUINFO_STR_REGISTER + LR35902_IE: sprintf(info->s, "IE:%02X", cpustate->w.IE); break;
+ case CPUINFO_STR_REGISTER + LR35902_IF: sprintf(info->s, "IF:%02X", cpustate->w.IF); break;
+ case CPUINFO_STR_REGISTER + LR35902_SPEED: sprintf(info->s, "SPD:%02x", 0x7E | ( ( cpustate->w.gb_speed - 1 ) << 7 ) | cpustate->w.gb_speed_change_pending ); break;
+ }
+}
+
+DEFINE_LEGACY_CPU_DEVICE(LR35902, lr35902);