#ifndef M68K__HEADER #define M68K__HEADER /* ======================================================================== */ /* ========================= LICENSING & COPYRIGHT ======================== */ /* ======================================================================== */ /* * MUSASHI * Version 3.32 * * A portable Motorola M680x0 processor emulation engine. * Copyright Karl Stenerud. All rights reserved. * * This code may be freely used for non-commercial purposes as long as this * copyright notice remains unaltered in the source code and any binary files * containing this code in compiled form. * * All other licensing terms must be negotiated with the author * (Karl Stenerud). * * The latest version of this code can be obtained at: * http://kstenerud.cjb.net */ /* Modified by Eke-Eke for Genesis Plus GX: - removed unused stuff to reduce memory usage / optimize execution (multiple CPU types support, NMI support, ...) - moved stuff to compile statically in a single object file - implemented support for global cycle count (shared by 68k & Z80 CPU) - added support for interrupt latency (Sesame's Street Counting Cafe, Fatal Rewind) - added proper cycle use on reset - added cycle accurate timings for MUL/DIV instructions (thanks to Jorge Cwik !) - fixed undocumented flags for DIV instructions (Blood Shot) */ /* ======================================================================== */ /* ============================= CONFIGURATION ============================ */ /* ======================================================================== */ /* Import the configuration for this build */ #include "m68kconf.h" /* ======================================================================== */ /* ============================ GENERAL DEFINES =========================== */ /* ======================================================================== */ /* There are 7 levels of interrupt to the 68K. * A transition from < 7 to 7 will cause a non-maskable interrupt (NMI). */ #define M68K_IRQ_NONE 0 #define M68K_IRQ_1 1 #define M68K_IRQ_2 2 #define M68K_IRQ_3 3 #define M68K_IRQ_4 4 #define M68K_IRQ_5 5 #define M68K_IRQ_6 6 #define M68K_IRQ_7 7 /* Special interrupt acknowledge values. * Use these as special returns from the interrupt acknowledge callback * (specified later in this header). */ /* Causes an interrupt autovector (0x18 + interrupt level) to be taken. * This happens in a real 68K if VPA or AVEC is asserted during an interrupt * acknowledge cycle instead of DTACK. */ #define M68K_INT_ACK_AUTOVECTOR 0xffffffff /* Causes the spurious interrupt vector (0x18) to be taken * This happens in a real 68K if BERR is asserted during the interrupt * acknowledge cycle (i.e. no devices responded to the acknowledge). */ #define M68K_INT_ACK_SPURIOUS 0xfffffffe /* Registers used by m68k_get_reg() and m68k_set_reg() */ typedef enum { /* Real registers */ M68K_REG_D0, /* Data registers */ M68K_REG_D1, M68K_REG_D2, M68K_REG_D3, M68K_REG_D4, M68K_REG_D5, M68K_REG_D6, M68K_REG_D7, M68K_REG_A0, /* Address registers */ M68K_REG_A1, M68K_REG_A2, M68K_REG_A3, M68K_REG_A4, M68K_REG_A5, M68K_REG_A6, M68K_REG_A7, M68K_REG_PC, /* Program Counter */ M68K_REG_SR, /* Status Register */ M68K_REG_SP, /* The current Stack Pointer (located in A7) */ M68K_REG_USP, /* User Stack Pointer */ M68K_REG_ISP, /* Interrupt Stack Pointer */ #if M68K_EMULATE_PREFETCH /* Assumed registers */ /* These are cheat registers which emulate the 1-longword prefetch * present in the 68000 and 68010. */ M68K_REG_PREF_ADDR, /* Last prefetch address */ M68K_REG_PREF_DATA, /* Last prefetch data */ #endif /* Convenience registers */ M68K_REG_IR /* Instruction register */ } m68k_register_t; /* ======================================================================== */ /* ====================== FUNCTIONS CALLED BY THE CPU ===================== */ /* ======================================================================== */ #include "macros.h" /* 68k memory map structure */ typedef struct { unsigned char *base; /* direct memory access (ROM, RAM) */ unsigned int (*read8)(unsigned int address); /* I/O byte read access */ unsigned int (*read16)(unsigned int address); /* I/O word read access */ void (*write8)(unsigned int address, unsigned int data); /* I/O byte write access */ void (*write16)(unsigned int address, unsigned int data); /* I/O word write access */ } _m68k_memory_map; /* 68k memory map */ _m68k_memory_map m68k_memory_map[256]; /* Read data immediately following the PC */ #define m68k_read_immediate_16(address) *(uint16 *)(m68k_memory_map[((address)>>16)&0xff].base + ((address) & 0xffff)) #define m68k_read_immediate_32(address) (m68k_read_immediate_16(address) << 16) | (m68k_read_immediate_16(address+2)) /* Read data relative to the PC */ #define m68k_read_pcrelative_8(address) READ_BYTE(m68k_memory_map[((address)>>16)&0xff].base, (address) & 0xffff) #define m68k_read_pcrelative_16(address) m68k_read_immediate_16(address) #define m68k_read_pcrelative_32(address) m68k_read_immediate_32(address) /* ======================================================================== */ /* ============================== CALLBACKS =============================== */ /* ======================================================================== */ /* These functions allow you to set callbacks to the host when specific events * occur. Note that you must enable the corresponding value in m68kconf.h * in order for these to do anything useful. * Note: I have defined default callbacks which are used if you have enabled * the corresponding #define in m68kconf.h but either haven't assigned a * callback or have assigned a callback of NULL. */ #if M68K_EMULATE_INT_ACK == OPT_ON /* Set the callback for an interrupt acknowledge. * You must enable M68K_EMULATE_INT_ACK in m68kconf.h. * The CPU will call the callback with the interrupt level being acknowledged. * The host program must return either a vector from 0x02-0xff, or one of the * special interrupt acknowledge values specified earlier in this header. * If this is not implemented, the CPU will always assume an autovectored * interrupt, and will automatically clear the interrupt request when it * services the interrupt. * Default behavior: return M68K_INT_ACK_AUTOVECTOR. */ void m68k_set_int_ack_callback(int (*callback)(int int_level)); #endif #if M68K_EMULATE_RESET == OPT_ON /* Set the callback for the RESET instruction. * You must enable M68K_EMULATE_RESET in m68kconf.h. * The CPU calls this callback every time it encounters a RESET instruction. * Default behavior: do nothing. */ void m68k_set_reset_instr_callback(void (*callback)(void)); #endif #if M68K_TAS_HAS_CALLBACK == OPT_ON /* Set the callback for the TAS instruction. * You must enable M68K_TAS_HAS_CALLBACK in m68kconf.h. * The CPU calls this callback every time it encounters a TAS instruction. * Default behavior: return 1, allow writeback. */ void m68k_set_tas_instr_callback(int (*callback)(void)); #endif #if M68K_EMULATE_FC == OPT_ON /* Set the callback for CPU function code changes. * You must enable M68K_EMULATE_FC in m68kconf.h. * The CPU calls this callback with the function code before every memory * access to set the CPU's function code according to what kind of memory * access it is (supervisor/user, program/data and such). * Default behavior: do nothing. */ void m68k_set_fc_callback(void (*callback)(unsigned int new_fc)); #endif /* ======================================================================== */ /* ====================== FUNCTIONS TO ACCESS THE CPU ===================== */ /* ======================================================================== */ /* Do whatever initialisations the core requires. Should be called * at least once at init time. */ extern void m68k_init(void); /* Pulse the RESET pin on the CPU. * You *MUST* reset the CPU at least once to initialize the emulation */ extern void m68k_pulse_reset(void); /* Run until given cycle count is reached */ extern void m68k_run(unsigned int cycles); /* Set the IPL0-IPL2 pins on the CPU (IRQ). * A transition from < 7 to 7 will cause a non-maskable interrupt (NMI). * Setting IRQ to 0 will clear an interrupt request. */ extern void m68k_update_irq(unsigned int mask); extern void m68k_set_irq(unsigned int int_level); extern void m68k_set_irq_delay(unsigned int int_level); /* Halt the CPU as if you pulsed the HALT pin. */ extern void m68k_pulse_halt(void); /* Peek at the internals of a CPU context. This can either be a context * retrieved using m68k_get_context() or the currently running context. * If context is NULL, the currently running CPU context will be used. */ extern unsigned int m68k_get_reg(m68k_register_t reg); /* Poke values into the internals of the currently running CPU context */ extern void m68k_set_reg(m68k_register_t reg, unsigned int value); /* ======================================================================== */ /* ============================== END OF FILE ============================= */ /* ======================================================================== */ #endif /* M68K__HEADER */