src/musashi/m68k.h

Thu, 11 Apr 2013 09:37:11 +0100

author
Philip Pemberton <philpem@philpem.me.uk>
date
Thu, 11 Apr 2013 09:37:11 +0100
changeset 138
d744db15cdf7
parent 19
ea417ac1d83a
permissions
-rw-r--r--

Check return value of fread()

philpem@0 1 #ifndef M68K__HEADER
philpem@0 2 #define M68K__HEADER
philpem@0 3
philpem@0 4 /* ======================================================================== */
philpem@0 5 /* ========================= LICENSING & COPYRIGHT ======================== */
philpem@0 6 /* ======================================================================== */
philpem@0 7 /*
philpem@0 8 * MUSASHI
philpem@0 9 * Version 3.3
philpem@0 10 *
philpem@0 11 * A portable Motorola M680x0 processor emulation engine.
philpem@0 12 * Copyright 1998-2001 Karl Stenerud. All rights reserved.
philpem@0 13 *
philpem@0 14 * This code may be freely used for non-commercial purposes as long as this
philpem@0 15 * copyright notice remains unaltered in the source code and any binary files
philpem@0 16 * containing this code in compiled form.
philpem@0 17 *
philpem@0 18 * All other lisencing terms must be negotiated with the author
philpem@0 19 * (Karl Stenerud).
philpem@0 20 *
philpem@0 21 * The latest version of this code can be obtained at:
philpem@0 22 * http://kstenerud.cjb.net
philpem@0 23 */
philpem@0 24
philpem@0 25
philpem@0 26
philpem@0 27 /* ======================================================================== */
philpem@0 28 /* ============================ GENERAL DEFINES =========================== */
philpem@0 29
philpem@0 30 /* ======================================================================== */
philpem@0 31
philpem@0 32 /* There are 7 levels of interrupt to the 68K.
philpem@0 33 * A transition from < 7 to 7 will cause a non-maskable interrupt (NMI).
philpem@0 34 */
philpem@0 35 #define M68K_IRQ_NONE 0
philpem@0 36 #define M68K_IRQ_1 1
philpem@0 37 #define M68K_IRQ_2 2
philpem@0 38 #define M68K_IRQ_3 3
philpem@0 39 #define M68K_IRQ_4 4
philpem@0 40 #define M68K_IRQ_5 5
philpem@0 41 #define M68K_IRQ_6 6
philpem@0 42 #define M68K_IRQ_7 7
philpem@0 43
philpem@0 44
philpem@0 45 /* Special interrupt acknowledge values.
philpem@0 46 * Use these as special returns from the interrupt acknowledge callback
philpem@0 47 * (specified later in this header).
philpem@0 48 */
philpem@0 49
philpem@0 50 /* Causes an interrupt autovector (0x18 + interrupt level) to be taken.
philpem@0 51 * This happens in a real 68K if VPA or AVEC is asserted during an interrupt
philpem@0 52 * acknowledge cycle instead of DTACK.
philpem@0 53 */
philpem@0 54 #define M68K_INT_ACK_AUTOVECTOR 0xffffffff
philpem@0 55
philpem@0 56 /* Causes the spurious interrupt vector (0x18) to be taken
philpem@0 57 * This happens in a real 68K if BERR is asserted during the interrupt
philpem@0 58 * acknowledge cycle (i.e. no devices responded to the acknowledge).
philpem@0 59 */
philpem@0 60 #define M68K_INT_ACK_SPURIOUS 0xfffffffe
philpem@0 61
philpem@0 62
philpem@0 63 /* CPU types for use in m68k_set_cpu_type() */
philpem@0 64 enum
philpem@0 65 {
philpem@0 66 M68K_CPU_TYPE_INVALID,
philpem@0 67 M68K_CPU_TYPE_68000,
philpem@0 68 M68K_CPU_TYPE_68010,
philpem@0 69 M68K_CPU_TYPE_68EC020,
philpem@0 70 M68K_CPU_TYPE_68020,
philpem@0 71 M68K_CPU_TYPE_68030, /* Supported by disassembler ONLY */
philpem@0 72 M68K_CPU_TYPE_68040 /* Supported by disassembler ONLY */
philpem@0 73 };
philpem@0 74
philpem@0 75 /* Registers used by m68k_get_reg() and m68k_set_reg() */
philpem@0 76 typedef enum
philpem@0 77 {
philpem@0 78 /* Real registers */
philpem@0 79 M68K_REG_D0, /* Data registers */
philpem@0 80 M68K_REG_D1,
philpem@0 81 M68K_REG_D2,
philpem@0 82 M68K_REG_D3,
philpem@0 83 M68K_REG_D4,
philpem@0 84 M68K_REG_D5,
philpem@0 85 M68K_REG_D6,
philpem@0 86 M68K_REG_D7,
philpem@0 87 M68K_REG_A0, /* Address registers */
philpem@0 88 M68K_REG_A1,
philpem@0 89 M68K_REG_A2,
philpem@0 90 M68K_REG_A3,
philpem@0 91 M68K_REG_A4,
philpem@0 92 M68K_REG_A5,
philpem@0 93 M68K_REG_A6,
philpem@0 94 M68K_REG_A7,
philpem@0 95 M68K_REG_PC, /* Program Counter */
philpem@0 96 M68K_REG_SR, /* Status Register */
philpem@0 97 M68K_REG_SP, /* The current Stack Pointer (located in A7) */
philpem@0 98 M68K_REG_USP, /* User Stack Pointer */
philpem@0 99 M68K_REG_ISP, /* Interrupt Stack Pointer */
philpem@0 100 M68K_REG_MSP, /* Master Stack Pointer */
philpem@0 101 M68K_REG_SFC, /* Source Function Code */
philpem@0 102 M68K_REG_DFC, /* Destination Function Code */
philpem@0 103 M68K_REG_VBR, /* Vector Base Register */
philpem@0 104 M68K_REG_CACR, /* Cache Control Register */
philpem@0 105 M68K_REG_CAAR, /* Cache Address Register */
philpem@0 106
philpem@0 107 /* Assumed registers */
philpem@0 108 /* These are cheat registers which emulate the 1-longword prefetch
philpem@0 109 * present in the 68000 and 68010.
philpem@0 110 */
philpem@0 111 M68K_REG_PREF_ADDR, /* Last prefetch address */
philpem@0 112 M68K_REG_PREF_DATA, /* Last prefetch data */
philpem@0 113
philpem@0 114 /* Convenience registers */
philpem@0 115 M68K_REG_PPC, /* Previous value in the program counter */
philpem@0 116 M68K_REG_IR, /* Instruction register */
philpem@0 117 M68K_REG_CPU_TYPE /* Type of CPU being run */
philpem@0 118 } m68k_register_t;
philpem@0 119
philpem@0 120 /* ======================================================================== */
philpem@0 121 /* ====================== FUNCTIONS CALLED BY THE CPU ===================== */
philpem@0 122 /* ======================================================================== */
philpem@0 123
philpem@0 124 /* You will have to implement these functions */
philpem@0 125
philpem@0 126 /* read/write functions called by the CPU to access memory.
philpem@0 127 * while values used are 32 bits, only the appropriate number
philpem@0 128 * of bits are relevant (i.e. in write_memory_8, only the lower 8 bits
philpem@0 129 * of value should be written to memory).
philpem@0 130 *
philpem@0 131 * NOTE: I have separated the immediate and PC-relative memory fetches
philpem@0 132 * from the other memory fetches because some systems require
philpem@0 133 * differentiation between PROGRAM and DATA fetches (usually
philpem@0 134 * for security setups such as encryption).
philpem@0 135 * This separation can either be achieved by setting
philpem@0 136 * M68K_SEPARATE_READS in m68kconf.h and defining
philpem@0 137 * the read functions, or by setting M68K_EMULATE_FC and
philpem@0 138 * making a function code callback function.
philpem@0 139 * Using the callback offers better emulation coverage
philpem@0 140 * because you can also monitor whether the CPU is in SYSTEM or
philpem@0 141 * USER mode, but it is also slower.
philpem@0 142 */
philpem@0 143
philpem@0 144 /* Read from anywhere */
philpem@0 145 unsigned int m68k_read_memory_8(unsigned int address);
philpem@0 146 unsigned int m68k_read_memory_16(unsigned int address);
philpem@0 147 unsigned int m68k_read_memory_32(unsigned int address);
philpem@0 148
philpem@0 149 /* Read data immediately following the PC */
philpem@0 150 unsigned int m68k_read_immediate_16(unsigned int address);
philpem@0 151 unsigned int m68k_read_immediate_32(unsigned int address);
philpem@0 152
philpem@0 153 /* Read data relative to the PC */
philpem@0 154 unsigned int m68k_read_pcrelative_8(unsigned int address);
philpem@0 155 unsigned int m68k_read_pcrelative_16(unsigned int address);
philpem@0 156 unsigned int m68k_read_pcrelative_32(unsigned int address);
philpem@0 157
philpem@0 158 /* Memory access for the disassembler */
philpem@0 159 unsigned int m68k_read_disassembler_8 (unsigned int address);
philpem@0 160 unsigned int m68k_read_disassembler_16 (unsigned int address);
philpem@0 161 unsigned int m68k_read_disassembler_32 (unsigned int address);
philpem@0 162
philpem@0 163 /* Write to anywhere */
philpem@0 164 void m68k_write_memory_8(unsigned int address, unsigned int value);
philpem@0 165 void m68k_write_memory_16(unsigned int address, unsigned int value);
philpem@0 166 void m68k_write_memory_32(unsigned int address, unsigned int value);
philpem@0 167
philpem@0 168
philpem@0 169
philpem@0 170 /* ======================================================================== */
philpem@0 171 /* ============================== CALLBACKS =============================== */
philpem@0 172 /* ======================================================================== */
philpem@0 173
philpem@0 174 /* These functions allow you to set callbacks to the host when specific events
philpem@0 175 * occur. Note that you must enable the corresponding value in m68kconf.h
philpem@0 176 * in order for these to do anything useful.
philpem@0 177 * Note: I have defined default callbacks which are used if you have enabled
philpem@0 178 * the corresponding #define in m68kconf.h but either haven't assigned a
philpem@0 179 * callback or have assigned a callback of NULL.
philpem@0 180 */
philpem@0 181
philpem@0 182 /* Set the callback for an interrupt acknowledge.
philpem@0 183 * You must enable M68K_EMULATE_INT_ACK in m68kconf.h.
philpem@0 184 * The CPU will call the callback with the interrupt level being acknowledged.
philpem@0 185 * The host program must return either a vector from 0x02-0xff, or one of the
philpem@0 186 * special interrupt acknowledge values specified earlier in this header.
philpem@0 187 * If this is not implemented, the CPU will always assume an autovectored
philpem@0 188 * interrupt, and will automatically clear the interrupt request when it
philpem@0 189 * services the interrupt.
philpem@0 190 * Default behavior: return M68K_INT_ACK_AUTOVECTOR.
philpem@0 191 */
philpem@0 192 void m68k_set_int_ack_callback(int (*callback)(int int_level));
philpem@0 193
philpem@0 194
philpem@0 195 /* Set the callback for a breakpoint acknowledge (68010+).
philpem@0 196 * You must enable M68K_EMULATE_BKPT_ACK in m68kconf.h.
philpem@0 197 * The CPU will call the callback with whatever was in the data field of the
philpem@0 198 * BKPT instruction for 68020+, or 0 for 68010.
philpem@0 199 * Default behavior: do nothing.
philpem@0 200 */
philpem@0 201 void m68k_set_bkpt_ack_callback(void (*callback)(unsigned int data));
philpem@0 202
philpem@0 203
philpem@0 204 /* Set the callback for the RESET instruction.
philpem@0 205 * You must enable M68K_EMULATE_RESET in m68kconf.h.
philpem@0 206 * The CPU calls this callback every time it encounters a RESET instruction.
philpem@0 207 * Default behavior: do nothing.
philpem@0 208 */
philpem@0 209 void m68k_set_reset_instr_callback(void (*callback)(void));
philpem@0 210
philpem@0 211
philpem@0 212 /* Set the callback for informing of a large PC change.
philpem@0 213 * You must enable M68K_MONITOR_PC in m68kconf.h.
philpem@0 214 * The CPU calls this callback with the new PC value every time the PC changes
philpem@0 215 * by a large value (currently set for changes by longwords).
philpem@0 216 * Default behavior: do nothing.
philpem@0 217 */
philpem@0 218 void m68k_set_pc_changed_callback(void (*callback)(unsigned int new_pc));
philpem@0 219
philpem@0 220
philpem@0 221 /* Set the callback for CPU function code changes.
philpem@0 222 * You must enable M68K_EMULATE_FC in m68kconf.h.
philpem@0 223 * The CPU calls this callback with the function code before every memory
philpem@0 224 * access to set the CPU's function code according to what kind of memory
philpem@0 225 * access it is (supervisor/user, program/data and such).
philpem@0 226 * Default behavior: do nothing.
philpem@0 227 */
philpem@0 228 void m68k_set_fc_callback(void (*callback)(unsigned int new_fc));
philpem@0 229
philpem@0 230
philpem@0 231 /* Set a callback for the instruction cycle of the CPU.
philpem@0 232 * You must enable M68K_INSTRUCTION_HOOK in m68kconf.h.
philpem@0 233 * The CPU calls this callback just before fetching the opcode in the
philpem@0 234 * instruction cycle.
philpem@0 235 * Default behavior: do nothing.
philpem@0 236 */
philpem@0 237 void m68k_set_instr_hook_callback(void (*callback)(void));
philpem@0 238
philpem@0 239
philpem@0 240
philpem@0 241 /* ======================================================================== */
philpem@0 242 /* ====================== FUNCTIONS TO ACCESS THE CPU ===================== */
philpem@0 243 /* ======================================================================== */
philpem@0 244
philpem@0 245 /* Use this function to set the CPU type you want to emulate.
philpem@0 246 * Currently supported types are: M68K_CPU_TYPE_68000, M68K_CPU_TYPE_68010,
philpem@0 247 * M68K_CPU_TYPE_EC020, and M68K_CPU_TYPE_68020.
philpem@0 248 */
philpem@0 249 void m68k_set_cpu_type(unsigned int cpu_type);
philpem@0 250
philpem@0 251 /* Pulse the RESET pin on the CPU.
philpem@0 252 * You *MUST* reset the CPU at least once to initialize the emulation
philpem@0 253 * Note: If you didn't call m68k_set_cpu_type() before resetting
philpem@0 254 * the CPU for the first time, the CPU will be set to
philpem@0 255 * M68K_CPU_TYPE_68000.
philpem@0 256 */
philpem@0 257 void m68k_pulse_reset(void);
philpem@0 258
philpem@0 259 /* execute num_cycles worth of instructions. returns number of cycles used */
philpem@0 260 int m68k_execute(int num_cycles);
philpem@0 261
philpem@0 262 /* These functions let you read/write/modify the number of cycles left to run
philpem@0 263 * while m68k_execute() is running.
philpem@0 264 * These are useful if the 68k accesses a memory-mapped port on another device
philpem@0 265 * that requires immediate processing by another CPU.
philpem@0 266 */
philpem@0 267 int m68k_cycles_run(void); /* Number of cycles run so far */
philpem@0 268 int m68k_cycles_remaining(void); /* Number of cycles left */
philpem@0 269 void m68k_modify_timeslice(int cycles); /* Modify cycles left */
philpem@0 270 void m68k_end_timeslice(void); /* End timeslice now */
philpem@0 271
philpem@0 272 /* Set the IPL0-IPL2 pins on the CPU (IRQ).
philpem@0 273 * A transition from < 7 to 7 will cause a non-maskable interrupt (NMI).
philpem@0 274 * Setting IRQ to 0 will clear an interrupt request.
philpem@0 275 */
philpem@0 276 void m68k_set_irq(unsigned int int_level);
philpem@0 277
philpem@0 278
philpem@0 279 /* Halt the CPU as if you pulsed the HALT pin. */
philpem@0 280 void m68k_pulse_halt(void);
philpem@0 281
philpem@0 282
philpem@19 283 /* Trigger a bus error exception */
philpem@19 284 void m68k_pulse_bus_error(void);
philpem@19 285
philpem@19 286
philpem@0 287 /* Context switching to allow multiple CPUs */
philpem@0 288
philpem@0 289 /* Get the size of the cpu context in bytes */
philpem@0 290 unsigned int m68k_context_size(void);
philpem@0 291
philpem@0 292 /* Get a cpu context */
philpem@0 293 unsigned int m68k_get_context(void* dst);
philpem@0 294
philpem@0 295 /* set the current cpu context */
philpem@0 296 void m68k_set_context(void* dst);
philpem@0 297
philpem@0 298 /* Save the current cpu context to disk.
philpem@0 299 * You must provide a function pointer of the form:
philpem@0 300 * void save_value(char* identifier, unsigned int value)
philpem@0 301 */
philpem@0 302 void m68k_save_context( void (*save_value)(char* identifier, unsigned int value));
philpem@0 303
philpem@0 304 /* Load a cpu context from disk.
philpem@0 305 * You must provide a function pointer of the form:
philpem@0 306 * unsigned int load_value(char* identifier)
philpem@0 307 */
philpem@0 308 void m68k_load_context(unsigned int (*load_value)(char* identifier));
philpem@0 309
philpem@0 310
philpem@0 311
philpem@0 312 /* Peek at the internals of a CPU context. This can either be a context
philpem@0 313 * retrieved using m68k_get_context() or the currently running context.
philpem@0 314 * If context is NULL, the currently running CPU context will be used.
philpem@0 315 */
philpem@0 316 unsigned int m68k_get_reg(void* context, m68k_register_t reg);
philpem@0 317
philpem@0 318 /* Poke values into the internals of the currently running CPU context */
philpem@0 319 void m68k_set_reg(m68k_register_t reg, unsigned int value);
philpem@0 320
philpem@0 321 /* Check if an instruction is valid for the specified CPU type */
philpem@0 322 unsigned int m68k_is_valid_instruction(unsigned int instruction, unsigned int cpu_type);
philpem@0 323
philpem@0 324 /* Disassemble 1 instruction using the epecified CPU type at pc. Stores
philpem@0 325 * disassembly in str_buff and returns the size of the instruction in bytes.
philpem@0 326 */
philpem@0 327 unsigned int m68k_disassemble(char* str_buff, unsigned int pc, unsigned int cpu_type);
philpem@0 328
philpem@0 329
philpem@0 330 /* ======================================================================== */
philpem@0 331 /* ============================= CONFIGURATION ============================ */
philpem@0 332 /* ======================================================================== */
philpem@0 333
philpem@0 334 /* Import the configuration for this build */
philpem@0 335 #include "m68kconf.h"
philpem@0 336
philpem@0 337
philpem@0 338
philpem@0 339 /* ======================================================================== */
philpem@0 340 /* ============================== END OF FILE ============================= */
philpem@0 341 /* ======================================================================== */
philpem@0 342
philpem@0 343 #endif /* M68K__HEADER */