#ifndef M68K__HEADER1#define M68K__HEADER23/* ======================================================================== */4/* ========================= LICENSING & COPYRIGHT ======================== */5/* ======================================================================== */6/*7* MUSASHI8* Version 3.329*10* A portable Motorola M680x0 processor emulation engine.11* Copyright Karl Stenerud. All rights reserved.12*13* This code may be freely used for non-commercial purposes as long as this14* copyright notice remains unaltered in the source code and any binary files15* containing this code in compiled form.16*17* All other licensing terms must be negotiated with the author18* (Karl Stenerud).19*20* The latest version of this code can be obtained at:21* http://kstenerud.cjb.net22*/2324/* Modified by Eke-Eke for Genesis Plus GX:2526- removed unused stuff to reduce memory usage / optimize execution (multiple CPU types support, NMI support, ...)27- moved stuff to compile statically in a single object file28- implemented support for global cycle count (shared by 68k & Z80 CPU)29- added support for interrupt latency (Sesame's Street Counting Cafe, Fatal Rewind)30- added proper cycle use on reset31- added cycle accurate timings for MUL/DIV instructions (thanks to Jorge Cwik !)32- fixed undocumented flags for DIV instructions (Blood Shot)33- added MAIN-CPU & SUB-CPU support for Mega CD emulation3435*/3637/* ======================================================================== */38/* ================================ INCLUDES ============================== */39/* ======================================================================== */4041#include <setjmp.h>42#include "macros.h"4344/* ======================================================================== */45/* ==================== ARCHITECTURE-DEPENDANT DEFINES ==================== */46/* ======================================================================== */4748/* Check for > 32bit sizes */49#if UINT_MAX > 0xffffffff50#define M68K_INT_GT_32_BIT 151#else52#define M68K_INT_GT_32_BIT 053#endif5455/* Data types used in this emulation core */56#undef sint857#undef sint1658#undef sint3259#undef sint6460#undef uint861#undef uint1662#undef uint3263#undef uint6464#undef sint65#undef uint6667#define sint8 signed char /* ASG: changed from char to signed char */68#define sint16 signed short69#define sint32 signed int /* AWJ: changed from long to int */70#define uint8 unsigned char71#define uint16 unsigned short72#define uint32 unsigned int /* AWJ: changed from long to int */7374/* signed and unsigned int must be at least 32 bits wide */75#define sint signed int76#define uint unsigned int777879#if M68K_USE_64_BIT80#define sint64 signed long long81#define uint64 unsigned long long82#else83#define sint64 sint3284#define uint64 uint3285#endif /* M68K_USE_64_BIT */86878889/* Allow for architectures that don't have 8-bit sizes */90/*#if UCHAR_MAX == 0xff*/91#define MAKE_INT_8(A) (sint8)(A)92/*#else93#undef sint894#define sint8 signed int95#undef uint896#define uint8 unsigned int97INLINE sint MAKE_INT_8(uint value)98{99return (value & 0x80) ? value | ~0xff : value & 0xff;100}*/101/*#endif *//* UCHAR_MAX == 0xff */102103104/* Allow for architectures that don't have 16-bit sizes */105/*#if USHRT_MAX == 0xffff*/106#define MAKE_INT_16(A) (sint16)(A)107/*#else108#undef sint16109#define sint16 signed int110#undef uint16111#define uint16 unsigned int112INLINE sint MAKE_INT_16(uint value)113{114return (value & 0x8000) ? value | ~0xffff : value & 0xffff;115}*/116/*#endif *//* USHRT_MAX == 0xffff */117118119/* Allow for architectures that don't have 32-bit sizes */120/*#if UINT_MAX == 0xffffffff*/121#define MAKE_INT_32(A) (sint32)(A)122/*#else123#undef sint32124#define sint32 signed int125#undef uint32126#define uint32 unsigned int127INLINE sint MAKE_INT_32(uint value)128{129return (value & 0x80000000) ? value | ~0xffffffff : value & 0xffffffff;130}*/131/*#endif *//* UINT_MAX == 0xffffffff */132133134135/* ======================================================================== */136/* ============================ GENERAL DEFINES =========================== */137138/* ======================================================================== */139140/* There are 7 levels of interrupt to the 68K.141* A transition from < 7 to 7 will cause a non-maskable interrupt (NMI).142*/143#define M68K_IRQ_NONE 0144#define M68K_IRQ_1 1145#define M68K_IRQ_2 2146#define M68K_IRQ_3 3147#define M68K_IRQ_4 4148#define M68K_IRQ_5 5149#define M68K_IRQ_6 6150#define M68K_IRQ_7 7151152153/* Special interrupt acknowledge values.154* Use these as special returns from the interrupt acknowledge callback155* (specified later in this header).156*/157158/* Causes an interrupt autovector (0x18 + interrupt level) to be taken.159* This happens in a real 68K if VPA or AVEC is asserted during an interrupt160* acknowledge cycle instead of DTACK.161*/162#define M68K_INT_ACK_AUTOVECTOR 0xffffffff163164/* Causes the spurious interrupt vector (0x18) to be taken165* This happens in a real 68K if BERR is asserted during the interrupt166* acknowledge cycle (i.e. no devices responded to the acknowledge).167*/168#define M68K_INT_ACK_SPURIOUS 0xfffffffe169170171/* Registers used by m68k_get_reg() and m68k_set_reg() */172typedef enum173{174/* Real registers */175M68K_REG_D0, /* Data registers */176M68K_REG_D1,177M68K_REG_D2,178M68K_REG_D3,179M68K_REG_D4,180M68K_REG_D5,181M68K_REG_D6,182M68K_REG_D7,183M68K_REG_A0, /* Address registers */184M68K_REG_A1,185M68K_REG_A2,186M68K_REG_A3,187M68K_REG_A4,188M68K_REG_A5,189M68K_REG_A6,190M68K_REG_A7,191M68K_REG_PC, /* Program Counter */192M68K_REG_SR, /* Status Register */193M68K_REG_SP, /* The current Stack Pointer (located in A7) */194M68K_REG_USP, /* User Stack Pointer */195M68K_REG_ISP, /* Interrupt Stack Pointer */196197#if M68K_EMULATE_PREFETCH198/* Assumed registers */199/* These are cheat registers which emulate the 1-longword prefetch200* present in the 68000 and 68010.201*/202M68K_REG_PREF_ADDR, /* Last prefetch address */203M68K_REG_PREF_DATA, /* Last prefetch data */204#endif205206/* Convenience registers */207M68K_REG_IR /* Instruction register */208} m68k_register_t;209210211/* 68k memory map structure */212typedef struct213{214unsigned char *base; /* memory-based access (ROM, RAM) */215unsigned int (*read8)(unsigned int address); /* I/O byte read access */216unsigned int (*read16)(unsigned int address); /* I/O word read access */217void (*write8)(unsigned int address, unsigned int data); /* I/O byte write access */218void (*write16)(unsigned int address, unsigned int data); /* I/O word write access */219} cpu_memory_map;220221/* 68k idle loop detection */222typedef struct223{224uint pc;225uint cycle;226uint detected;227} cpu_idle_t;228229typedef struct230{231cpu_memory_map memory_map[256]; /* memory mapping */232233cpu_idle_t poll; /* polling detection */ // 0x1400234235uint cycles; /* current master cycle count */236uint cycle_end; /* aimed master cycle count for current execution frame */237238uint dar[16]; /* Data and Address Registers */239uint pc; /* Program Counter */240uint sp[5]; /* User and Interrupt Stack Pointers */241uint ir; /* Instruction Register */242uint t1_flag; /* Trace 1 */243uint s_flag; /* Supervisor */244uint x_flag; /* Extend */245uint n_flag; /* Negative */246uint not_z_flag; /* Zero, inverted for speedups */247uint v_flag; /* Overflow */248uint c_flag; /* Carry */249uint int_mask; /* I0-I2 */250uint int_level; /* State of interrupt pins IPL0-IPL2 -- ASG: changed from ints_pending */251uint stopped; /* Stopped state */252253uint pref_addr; /* Last prefetch address */254uint pref_data; /* Data in the prefetch queue */255256uint instr_mode; /* Stores whether we are in instruction mode or group 0/1 exception mode */257uint run_mode; /* Stores whether we are processing a reset, bus error, address error, or something else */258uint aerr_enabled; /* Enables/deisables address error checks at runtime */259jmp_buf aerr_trap; /* Address error jump */260uint aerr_address; /* Address error location */261uint aerr_write_mode; /* Address error write mode */262uint aerr_fc; /* Address error FC code */263264uint tracing; /* Tracing enable flag */265266uint address_space; /* Current FC code */267268/* Callbacks to host */269int (*int_ack_callback)(int int_line); /* Interrupt Acknowledge */270void (*reset_instr_callback)(void); /* Called when a RESET instruction is encountered */271int (*tas_instr_callback)(void); /* Called when a TAS instruction is encountered, allows / disallows writeback */272void (*set_fc_callback)(unsigned int new_fc); /* Called when the CPU function code changes */273} m68ki_cpu_core;274275/* CPU cores */276extern m68ki_cpu_core m68k;277extern m68ki_cpu_core s68k;278279280/* ======================================================================== */281/* ============================== CALLBACKS =============================== */282/* ======================================================================== */283284/* These functions allow you to set callbacks to the host when specific events285* occur. Note that you must enable the corresponding value in m68kconf.h286* in order for these to do anything useful.287* Note: I have defined default callbacks which are used if you have enabled288* the corresponding #define in m68kconf.h but either haven't assigned a289* callback or have assigned a callback of NULL.290*/291292#if M68K_EMULATE_INT_ACK == OPT_ON293/* Set the callback for an interrupt acknowledge.294* You must enable M68K_EMULATE_INT_ACK in m68kconf.h.295* The CPU will call the callback with the interrupt level being acknowledged.296* The host program must return either a vector from 0x02-0xff, or one of the297* special interrupt acknowledge values specified earlier in this header.298* If this is not implemented, the CPU will always assume an autovectored299* interrupt, and will automatically clear the interrupt request when it300* services the interrupt.301* Default behavior: return M68K_INT_ACK_AUTOVECTOR.302*/303void m68k_set_int_ack_callback(int (*callback)(int int_level));304#endif305306#if M68K_EMULATE_RESET == OPT_ON307/* Set the callback for the RESET instruction.308* You must enable M68K_EMULATE_RESET in m68kconf.h.309* The CPU calls this callback every time it encounters a RESET instruction.310* Default behavior: do nothing.311*/312void m68k_set_reset_instr_callback(void (*callback)(void));313#endif314315#if M68K_TAS_HAS_CALLBACK == OPT_ON316/* Set the callback for the TAS instruction.317* You must enable M68K_TAS_HAS_CALLBACK in m68kconf.h.318* The CPU calls this callback every time it encounters a TAS instruction.319* Default behavior: return 1, allow writeback.320*/321void m68k_set_tas_instr_callback(int (*callback)(void));322#endif323324#if M68K_EMULATE_FC == OPT_ON325/* Set the callback for CPU function code changes.326* You must enable M68K_EMULATE_FC in m68kconf.h.327* The CPU calls this callback with the function code before every memory328* access to set the CPU's function code according to what kind of memory329* access it is (supervisor/user, program/data and such).330* Default behavior: do nothing.331*/332void m68k_set_fc_callback(void (*callback)(unsigned int new_fc));333#endif334335336/* ======================================================================== */337/* ====================== FUNCTIONS TO ACCESS THE CPU ===================== */338/* ======================================================================== */339340/* Do whatever initialisations the core requires. Should be called341* at least once at init time.342*/343extern void m68k_init(void);344extern void s68k_init(void);345346/* Pulse the RESET pin on the CPU.347* You *MUST* reset the CPU at least once to initialize the emulation348*/349extern void m68k_pulse_reset(void);350extern void s68k_pulse_reset(void);351352/* Run until given cycle count is reached */353extern void m68k_run(unsigned int cycles);354extern void s68k_run(unsigned int cycles);355356/* Set the IPL0-IPL2 pins on the CPU (IRQ).357* A transition from < 7 to 7 will cause a non-maskable interrupt (NMI).358* Setting IRQ to 0 will clear an interrupt request.359*/360extern void m68k_set_irq(unsigned int int_level);361extern void m68k_set_irq_delay(unsigned int int_level);362extern void m68k_update_irq(unsigned int mask);363extern void s68k_update_irq(unsigned int mask);364365/* Halt the CPU as if you pulsed the HALT pin. */366extern void m68k_pulse_halt(void);367extern void m68k_clear_halt(void);368extern void s68k_pulse_halt(void);369extern void s68k_clear_halt(void);370371372/* Peek at the internals of a CPU context. This can either be a context373* retrieved using m68k_get_context() or the currently running context.374* If context is NULL, the currently running CPU context will be used.375*/376extern unsigned int m68k_get_reg(m68k_register_t reg);377extern unsigned int s68k_get_reg(m68k_register_t reg);378379/* Poke values into the internals of the currently running CPU context */380extern void m68k_set_reg(m68k_register_t reg, unsigned int value);381extern void s68k_set_reg(m68k_register_t reg, unsigned int value);382383384/* ======================================================================== */385/* ============================== END OF FILE ============================= */386/* ======================================================================== */387388#endif /* M68K__HEADER */389390391