src/musashi/m68kcpu.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 110
acea4b2f396f
child 128
3246b74d96bc
child 147
ad888290cdff
permissions
-rw-r--r--

Check return value of fread()

philpem@0 1 #include <stdio.h>
philpem@0 2 /* ======================================================================== */
philpem@0 3 /* ========================= LICENSING & COPYRIGHT ======================== */
philpem@0 4 /* ======================================================================== */
philpem@0 5 /*
philpem@0 6 * MUSASHI
philpem@0 7 * Version 3.3
philpem@0 8 *
philpem@0 9 * A portable Motorola M680x0 processor emulation engine.
philpem@0 10 * Copyright 1998-2001 Karl Stenerud. All rights reserved.
philpem@0 11 *
philpem@0 12 * This code may be freely used for non-commercial purposes as long as this
philpem@0 13 * copyright notice remains unaltered in the source code and any binary files
philpem@0 14 * containing this code in compiled form.
philpem@0 15 *
philpem@0 16 * All other lisencing terms must be negotiated with the author
philpem@0 17 * (Karl Stenerud).
philpem@0 18 *
philpem@0 19 * The latest version of this code can be obtained at:
philpem@0 20 * http://kstenerud.cjb.net
philpem@0 21 */
philpem@0 22
philpem@0 23
philpem@0 24
philpem@0 25
philpem@0 26 #ifndef M68KCPU__HEADER
philpem@0 27 #define M68KCPU__HEADER
philpem@0 28
philpem@0 29 #include "m68k.h"
philpem@0 30 #include <limits.h>
philpem@0 31
philpem@0 32 #if M68K_EMULATE_ADDRESS_ERROR
philpem@0 33 #include <setjmp.h>
philpem@0 34 #endif /* M68K_EMULATE_ADDRESS_ERROR */
philpem@0 35
philpem@0 36 /* ======================================================================== */
philpem@0 37 /* ==================== ARCHITECTURE-DEPENDANT DEFINES ==================== */
philpem@0 38 /* ======================================================================== */
philpem@0 39
philpem@0 40 /* Check for > 32bit sizes */
philpem@0 41 #if UINT_MAX > 0xffffffff
philpem@0 42 #define M68K_INT_GT_32_BIT 1
philpem@0 43 #endif
philpem@0 44
philpem@0 45 /* Data types used in this emulation core */
philpem@0 46 #undef sint8
philpem@0 47 #undef sint16
philpem@0 48 #undef sint32
philpem@0 49 #undef sint64
philpem@0 50 #undef uint8
philpem@0 51 #undef uint16
philpem@0 52 #undef uint32
philpem@0 53 #undef uint64
philpem@0 54 #undef sint
philpem@0 55 #undef uint
philpem@0 56
philpem@0 57 #define sint8 signed char /* ASG: changed from char to signed char */
philpem@0 58 #define sint16 signed short
philpem@0 59 #define sint32 signed long
philpem@0 60 #define uint8 unsigned char
philpem@0 61 #define uint16 unsigned short
philpem@0 62 #define uint32 unsigned long
philpem@0 63
philpem@0 64 /* signed and unsigned int must be at least 32 bits wide */
philpem@0 65 #define sint signed int
philpem@0 66 #define uint unsigned int
philpem@0 67
philpem@0 68
philpem@0 69 #if M68K_USE_64_BIT
philpem@0 70 #define sint64 signed long long
philpem@0 71 #define uint64 unsigned long long
philpem@0 72 #else
philpem@0 73 #define sint64 sint32
philpem@0 74 #define uint64 uint32
philpem@0 75 #endif /* M68K_USE_64_BIT */
philpem@0 76
philpem@0 77
philpem@0 78
philpem@0 79 /* Allow for architectures that don't have 8-bit sizes */
philpem@0 80 #if UCHAR_MAX == 0xff
philpem@0 81 #define MAKE_INT_8(A) (sint8)(A)
philpem@0 82 #else
philpem@0 83 #undef sint8
philpem@0 84 #define sint8 signed int
philpem@0 85 #undef uint8
philpem@0 86 #define uint8 unsigned int
philpem@0 87 INLINE sint MAKE_INT_8(uint value)
philpem@0 88 {
philpem@0 89 return (value & 0x80) ? value | ~0xff : value & 0xff;
philpem@0 90 }
philpem@0 91 #endif /* UCHAR_MAX == 0xff */
philpem@0 92
philpem@0 93
philpem@0 94 /* Allow for architectures that don't have 16-bit sizes */
philpem@0 95 #if USHRT_MAX == 0xffff
philpem@0 96 #define MAKE_INT_16(A) (sint16)(A)
philpem@0 97 #else
philpem@0 98 #undef sint16
philpem@0 99 #define sint16 signed int
philpem@0 100 #undef uint16
philpem@0 101 #define uint16 unsigned int
philpem@0 102 INLINE sint MAKE_INT_16(uint value)
philpem@0 103 {
philpem@0 104 return (value & 0x8000) ? value | ~0xffff : value & 0xffff;
philpem@0 105 }
philpem@0 106 #endif /* USHRT_MAX == 0xffff */
philpem@0 107
philpem@0 108
philpem@0 109 /* Allow for architectures that don't have 32-bit sizes */
philpem@0 110 #if ULONG_MAX == 0xffffffff
philpem@0 111 #define MAKE_INT_32(A) (sint32)(A)
philpem@0 112 #else
philpem@0 113 #undef sint32
philpem@0 114 #define sint32 signed int
philpem@0 115 #undef uint32
philpem@0 116 #define uint32 unsigned int
philpem@0 117 INLINE sint MAKE_INT_32(uint value)
philpem@0 118 {
philpem@0 119 return (value & 0x80000000) ? value | ~0xffffffff : value & 0xffffffff;
philpem@0 120 }
philpem@0 121 #endif /* ULONG_MAX == 0xffffffff */
philpem@0 122
philpem@0 123
philpem@0 124
philpem@0 125
philpem@0 126 /* ======================================================================== */
philpem@0 127 /* ============================ GENERAL DEFINES =========================== */
philpem@0 128 /* ======================================================================== */
philpem@0 129
philpem@0 130 /* Exception Vectors handled by emulation */
philpem@0 131 #define EXCEPTION_BUS_ERROR 2 /* This one is not emulated! */
philpem@0 132 #define EXCEPTION_ADDRESS_ERROR 3 /* This one is partially emulated (doesn't stack a proper frame yet) */
philpem@0 133 #define EXCEPTION_ILLEGAL_INSTRUCTION 4
philpem@0 134 #define EXCEPTION_ZERO_DIVIDE 5
philpem@0 135 #define EXCEPTION_CHK 6
philpem@0 136 #define EXCEPTION_TRAPV 7
philpem@0 137 #define EXCEPTION_PRIVILEGE_VIOLATION 8
philpem@0 138 #define EXCEPTION_TRACE 9
philpem@0 139 #define EXCEPTION_1010 10
philpem@0 140 #define EXCEPTION_1111 11
philpem@0 141 #define EXCEPTION_FORMAT_ERROR 14
philpem@0 142 #define EXCEPTION_UNINITIALIZED_INTERRUPT 15
philpem@0 143 #define EXCEPTION_SPURIOUS_INTERRUPT 24
philpem@0 144 #define EXCEPTION_INTERRUPT_AUTOVECTOR 24
philpem@0 145 #define EXCEPTION_TRAP_BASE 32
philpem@0 146
philpem@0 147 /* Function codes set by CPU during data/address bus activity */
philpem@0 148 #define FUNCTION_CODE_USER_DATA 1
philpem@0 149 #define FUNCTION_CODE_USER_PROGRAM 2
philpem@0 150 #define FUNCTION_CODE_SUPERVISOR_DATA 5
philpem@0 151 #define FUNCTION_CODE_SUPERVISOR_PROGRAM 6
philpem@0 152 #define FUNCTION_CODE_CPU_SPACE 7
philpem@0 153
philpem@0 154 /* CPU types for deciding what to emulate */
philpem@0 155 #define CPU_TYPE_000 1
philpem@0 156 #define CPU_TYPE_010 2
philpem@0 157 #define CPU_TYPE_EC020 4
philpem@0 158 #define CPU_TYPE_020 8
philpem@0 159
philpem@0 160 /* Different ways to stop the CPU */
philpem@0 161 #define STOP_LEVEL_STOP 1
philpem@0 162 #define STOP_LEVEL_HALT 2
philpem@0 163
philpem@0 164 #ifndef NULL
philpem@0 165 #define NULL ((void*)0)
philpem@0 166 #endif
philpem@0 167
philpem@0 168 /* ======================================================================== */
philpem@0 169 /* ================================ MACROS ================================ */
philpem@0 170 /* ======================================================================== */
philpem@0 171
philpem@0 172
philpem@0 173 /* ---------------------------- General Macros ---------------------------- */
philpem@0 174
philpem@0 175 /* Bit Isolation Macros */
philpem@0 176 #define BIT_0(A) ((A) & 0x00000001)
philpem@0 177 #define BIT_1(A) ((A) & 0x00000002)
philpem@0 178 #define BIT_2(A) ((A) & 0x00000004)
philpem@0 179 #define BIT_3(A) ((A) & 0x00000008)
philpem@0 180 #define BIT_4(A) ((A) & 0x00000010)
philpem@0 181 #define BIT_5(A) ((A) & 0x00000020)
philpem@0 182 #define BIT_6(A) ((A) & 0x00000040)
philpem@0 183 #define BIT_7(A) ((A) & 0x00000080)
philpem@0 184 #define BIT_8(A) ((A) & 0x00000100)
philpem@0 185 #define BIT_9(A) ((A) & 0x00000200)
philpem@0 186 #define BIT_A(A) ((A) & 0x00000400)
philpem@0 187 #define BIT_B(A) ((A) & 0x00000800)
philpem@0 188 #define BIT_C(A) ((A) & 0x00001000)
philpem@0 189 #define BIT_D(A) ((A) & 0x00002000)
philpem@0 190 #define BIT_E(A) ((A) & 0x00004000)
philpem@0 191 #define BIT_F(A) ((A) & 0x00008000)
philpem@0 192 #define BIT_10(A) ((A) & 0x00010000)
philpem@0 193 #define BIT_11(A) ((A) & 0x00020000)
philpem@0 194 #define BIT_12(A) ((A) & 0x00040000)
philpem@0 195 #define BIT_13(A) ((A) & 0x00080000)
philpem@0 196 #define BIT_14(A) ((A) & 0x00100000)
philpem@0 197 #define BIT_15(A) ((A) & 0x00200000)
philpem@0 198 #define BIT_16(A) ((A) & 0x00400000)
philpem@0 199 #define BIT_17(A) ((A) & 0x00800000)
philpem@0 200 #define BIT_18(A) ((A) & 0x01000000)
philpem@0 201 #define BIT_19(A) ((A) & 0x02000000)
philpem@0 202 #define BIT_1A(A) ((A) & 0x04000000)
philpem@0 203 #define BIT_1B(A) ((A) & 0x08000000)
philpem@0 204 #define BIT_1C(A) ((A) & 0x10000000)
philpem@0 205 #define BIT_1D(A) ((A) & 0x20000000)
philpem@0 206 #define BIT_1E(A) ((A) & 0x40000000)
philpem@0 207 #define BIT_1F(A) ((A) & 0x80000000)
philpem@0 208
philpem@0 209 /* Get the most significant bit for specific sizes */
philpem@0 210 #define GET_MSB_8(A) ((A) & 0x80)
philpem@0 211 #define GET_MSB_9(A) ((A) & 0x100)
philpem@0 212 #define GET_MSB_16(A) ((A) & 0x8000)
philpem@0 213 #define GET_MSB_17(A) ((A) & 0x10000)
philpem@0 214 #define GET_MSB_32(A) ((A) & 0x80000000)
philpem@0 215 #if M68K_USE_64_BIT
philpem@0 216 #define GET_MSB_33(A) ((A) & 0x100000000)
philpem@0 217 #endif /* M68K_USE_64_BIT */
philpem@0 218
philpem@0 219 /* Isolate nibbles */
philpem@0 220 #define LOW_NIBBLE(A) ((A) & 0x0f)
philpem@0 221 #define HIGH_NIBBLE(A) ((A) & 0xf0)
philpem@0 222
philpem@0 223 /* These are used to isolate 8, 16, and 32 bit sizes */
philpem@0 224 #define MASK_OUT_ABOVE_2(A) ((A) & 3)
philpem@0 225 #define MASK_OUT_ABOVE_8(A) ((A) & 0xff)
philpem@0 226 #define MASK_OUT_ABOVE_16(A) ((A) & 0xffff)
philpem@0 227 #define MASK_OUT_BELOW_2(A) ((A) & ~3)
philpem@0 228 #define MASK_OUT_BELOW_8(A) ((A) & ~0xff)
philpem@0 229 #define MASK_OUT_BELOW_16(A) ((A) & ~0xffff)
philpem@0 230
philpem@0 231 /* No need to mask if we are 32 bit */
philpem@0 232 #if M68K_INT_GT_32BIT || M68K_USE_64_BIT
philpem@0 233 #define MASK_OUT_ABOVE_32(A) ((A) & 0xffffffff)
philpem@0 234 #define MASK_OUT_BELOW_32(A) ((A) & ~0xffffffff)
philpem@0 235 #else
philpem@0 236 #define MASK_OUT_ABOVE_32(A) (A)
philpem@0 237 #define MASK_OUT_BELOW_32(A) 0
philpem@0 238 #endif /* M68K_INT_GT_32BIT || M68K_USE_64_BIT */
philpem@0 239
philpem@0 240 /* Simulate address lines of 68k family */
philpem@0 241 #define ADDRESS_68K(A) ((A)&CPU_ADDRESS_MASK)
philpem@0 242
philpem@0 243
philpem@0 244 /* Shift & Rotate Macros. */
philpem@0 245 #define LSL(A, C) ((A) << (C))
philpem@0 246 #define LSR(A, C) ((A) >> (C))
philpem@0 247
philpem@0 248 /* Some > 32-bit optimizations */
philpem@0 249 #if M68K_INT_GT_32BIT
philpem@0 250 /* Shift left and right */
philpem@0 251 #define LSR_32(A, C) ((A) >> (C))
philpem@0 252 #define LSL_32(A, C) ((A) << (C))
philpem@0 253 #else
philpem@0 254 /* We have to do this because the morons at ANSI decided that shifts
philpem@0 255 * by >= data size are undefined.
philpem@0 256 */
philpem@0 257 #define LSR_32(A, C) ((C) < 32 ? (A) >> (C) : 0)
philpem@0 258 #define LSL_32(A, C) ((C) < 32 ? (A) << (C) : 0)
philpem@0 259 #endif /* M68K_INT_GT_32BIT */
philpem@0 260
philpem@0 261 #if M68K_USE_64_BIT
philpem@0 262 #define LSL_32_64(A, C) ((A) << (C))
philpem@0 263 #define LSR_32_64(A, C) ((A) >> (C))
philpem@0 264 #define ROL_33_64(A, C) (LSL_32_64(A, C) | LSR_32_64(A, 33-(C)))
philpem@0 265 #define ROR_33_64(A, C) (LSR_32_64(A, C) | LSL_32_64(A, 33-(C)))
philpem@0 266 #endif /* M68K_USE_64_BIT */
philpem@0 267
philpem@0 268 #define ROL_8(A, C) MASK_OUT_ABOVE_8(LSL(A, C) | LSR(A, 8-(C)))
philpem@0 269 #define ROL_9(A, C) (LSL(A, C) | LSR(A, 9-(C)))
philpem@0 270 #define ROL_16(A, C) MASK_OUT_ABOVE_16(LSL(A, C) | LSR(A, 16-(C)))
philpem@0 271 #define ROL_17(A, C) (LSL(A, C) | LSR(A, 17-(C)))
philpem@0 272 #define ROL_32(A, C) MASK_OUT_ABOVE_32(LSL_32(A, C) | LSR_32(A, 32-(C)))
philpem@0 273 #define ROL_33(A, C) (LSL_32(A, C) | LSR_32(A, 33-(C)))
philpem@0 274
philpem@0 275 #define ROR_8(A, C) MASK_OUT_ABOVE_8(LSR(A, C) | LSL(A, 8-(C)))
philpem@0 276 #define ROR_9(A, C) (LSR(A, C) | LSL(A, 9-(C)))
philpem@0 277 #define ROR_16(A, C) MASK_OUT_ABOVE_16(LSR(A, C) | LSL(A, 16-(C)))
philpem@0 278 #define ROR_17(A, C) (LSR(A, C) | LSL(A, 17-(C)))
philpem@0 279 #define ROR_32(A, C) MASK_OUT_ABOVE_32(LSR_32(A, C) | LSL_32(A, 32-(C)))
philpem@0 280 #define ROR_33(A, C) (LSR_32(A, C) | LSL_32(A, 33-(C)))
philpem@0 281
philpem@0 282
philpem@0 283
philpem@0 284 /* ------------------------------ CPU Access ------------------------------ */
philpem@0 285
philpem@0 286 /* Access the CPU registers */
philpem@0 287 #define CPU_TYPE m68ki_cpu.cpu_type
philpem@0 288
philpem@0 289 #define REG_DA m68ki_cpu.dar /* easy access to data and address regs */
philpem@0 290 #define REG_D m68ki_cpu.dar
philpem@0 291 #define REG_A (m68ki_cpu.dar+8)
philpem@0 292 #define REG_PPC m68ki_cpu.ppc
philpem@0 293 #define REG_PC m68ki_cpu.pc
philpem@0 294 #define REG_SP_BASE m68ki_cpu.sp
philpem@0 295 #define REG_USP m68ki_cpu.sp[0]
philpem@0 296 #define REG_ISP m68ki_cpu.sp[4]
philpem@0 297 #define REG_MSP m68ki_cpu.sp[6]
philpem@0 298 #define REG_SP m68ki_cpu.dar[15]
philpem@0 299 #define REG_VBR m68ki_cpu.vbr
philpem@0 300 #define REG_SFC m68ki_cpu.sfc
philpem@0 301 #define REG_DFC m68ki_cpu.dfc
philpem@0 302 #define REG_CACR m68ki_cpu.cacr
philpem@0 303 #define REG_CAAR m68ki_cpu.caar
philpem@0 304 #define REG_IR m68ki_cpu.ir
philpem@0 305
philpem@0 306 #define FLAG_T1 m68ki_cpu.t1_flag
philpem@0 307 #define FLAG_T0 m68ki_cpu.t0_flag
philpem@0 308 #define FLAG_S m68ki_cpu.s_flag
philpem@0 309 #define FLAG_M m68ki_cpu.m_flag
philpem@0 310 #define FLAG_X m68ki_cpu.x_flag
philpem@0 311 #define FLAG_N m68ki_cpu.n_flag
philpem@0 312 #define FLAG_Z m68ki_cpu.not_z_flag
philpem@0 313 #define FLAG_V m68ki_cpu.v_flag
philpem@0 314 #define FLAG_C m68ki_cpu.c_flag
philpem@0 315 #define FLAG_INT_MASK m68ki_cpu.int_mask
philpem@0 316
philpem@0 317 #define CPU_INT_LEVEL m68ki_cpu.int_level /* ASG: changed from CPU_INTS_PENDING */
philpem@0 318 #define CPU_INT_CYCLES m68ki_cpu.int_cycles /* ASG */
philpem@0 319 #define CPU_STOPPED m68ki_cpu.stopped
philpem@0 320 #define CPU_PREF_ADDR m68ki_cpu.pref_addr
philpem@0 321 #define CPU_PREF_DATA m68ki_cpu.pref_data
philpem@0 322 #define CPU_ADDRESS_MASK m68ki_cpu.address_mask
philpem@0 323 #define CPU_SR_MASK m68ki_cpu.sr_mask
philpem@0 324
philpem@109 325 #define BUS_ERROR_OCCURRED m68ki_cpu.bus_error_occurred
philpem@109 326
philpem@0 327 #define CYC_INSTRUCTION m68ki_cpu.cyc_instruction
philpem@0 328 #define CYC_EXCEPTION m68ki_cpu.cyc_exception
philpem@0 329 #define CYC_BCC_NOTAKE_B m68ki_cpu.cyc_bcc_notake_b
philpem@0 330 #define CYC_BCC_NOTAKE_W m68ki_cpu.cyc_bcc_notake_w
philpem@0 331 #define CYC_DBCC_F_NOEXP m68ki_cpu.cyc_dbcc_f_noexp
philpem@0 332 #define CYC_DBCC_F_EXP m68ki_cpu.cyc_dbcc_f_exp
philpem@0 333 #define CYC_SCC_R_FALSE m68ki_cpu.cyc_scc_r_false
philpem@0 334 #define CYC_MOVEM_W m68ki_cpu.cyc_movem_w
philpem@0 335 #define CYC_MOVEM_L m68ki_cpu.cyc_movem_l
philpem@0 336 #define CYC_SHIFT m68ki_cpu.cyc_shift
philpem@0 337 #define CYC_RESET m68ki_cpu.cyc_reset
philpem@0 338
philpem@0 339
philpem@0 340 #define CALLBACK_INT_ACK m68ki_cpu.int_ack_callback
philpem@0 341 #define CALLBACK_BKPT_ACK m68ki_cpu.bkpt_ack_callback
philpem@0 342 #define CALLBACK_RESET_INSTR m68ki_cpu.reset_instr_callback
philpem@0 343 #define CALLBACK_PC_CHANGED m68ki_cpu.pc_changed_callback
philpem@0 344 #define CALLBACK_SET_FC m68ki_cpu.set_fc_callback
philpem@0 345 #define CALLBACK_INSTR_HOOK m68ki_cpu.instr_hook_callback
philpem@0 346
philpem@0 347
philpem@0 348
philpem@0 349 /* ----------------------------- Configuration ---------------------------- */
philpem@0 350
philpem@0 351 /* These defines are dependant on the configuration defines in m68kconf.h */
philpem@0 352
philpem@0 353 /* Disable certain comparisons if we're not using all CPU types */
philpem@0 354 #if M68K_EMULATE_020
philpem@0 355 #define CPU_TYPE_IS_020_PLUS(A) ((A) & CPU_TYPE_020)
philpem@0 356 #define CPU_TYPE_IS_020_LESS(A) 1
philpem@0 357 #else
philpem@0 358 #define CPU_TYPE_IS_020_PLUS(A) 0
philpem@0 359 #define CPU_TYPE_IS_020_LESS(A) 1
philpem@0 360 #endif
philpem@0 361
philpem@0 362 #if M68K_EMULATE_EC020
philpem@0 363 #define CPU_TYPE_IS_EC020_PLUS(A) ((A) & (CPU_TYPE_EC020 | CPU_TYPE_020))
philpem@0 364 #define CPU_TYPE_IS_EC020_LESS(A) ((A) & (CPU_TYPE_000 | CPU_TYPE_010 | CPU_TYPE_EC020))
philpem@0 365 #else
philpem@0 366 #define CPU_TYPE_IS_EC020_PLUS(A) CPU_TYPE_IS_020_PLUS(A)
philpem@0 367 #define CPU_TYPE_IS_EC020_LESS(A) CPU_TYPE_IS_020_LESS(A)
philpem@0 368 #endif
philpem@0 369
philpem@0 370 #if M68K_EMULATE_010
philpem@0 371 #define CPU_TYPE_IS_010(A) ((A) == CPU_TYPE_010)
philpem@0 372 #define CPU_TYPE_IS_010_PLUS(A) ((A) & (CPU_TYPE_010 | CPU_TYPE_EC020 | CPU_TYPE_020))
philpem@0 373 #define CPU_TYPE_IS_010_LESS(A) ((A) & (CPU_TYPE_000 | CPU_TYPE_010))
philpem@0 374 #else
philpem@0 375 #define CPU_TYPE_IS_010(A) 0
philpem@0 376 #define CPU_TYPE_IS_010_PLUS(A) CPU_TYPE_IS_EC020_PLUS(A)
philpem@0 377 #define CPU_TYPE_IS_010_LESS(A) CPU_TYPE_IS_EC020_LESS(A)
philpem@0 378 #endif
philpem@0 379
philpem@0 380 #if M68K_EMULATE_020 || M68K_EMULATE_EC020
philpem@0 381 #define CPU_TYPE_IS_020_VARIANT(A) ((A) & (CPU_TYPE_EC020 | CPU_TYPE_020))
philpem@0 382 #else
philpem@0 383 #define CPU_TYPE_IS_020_VARIANT(A) 0
philpem@0 384 #endif
philpem@0 385
philpem@0 386 #if M68K_EMULATE_020 || M68K_EMULATE_EC020 || M68K_EMULATE_010
philpem@0 387 #define CPU_TYPE_IS_000(A) ((A) == CPU_TYPE_000)
philpem@0 388 #else
philpem@0 389 #define CPU_TYPE_IS_000(A) 1
philpem@0 390 #endif
philpem@0 391
philpem@0 392
philpem@0 393 #if !M68K_SEPARATE_READS
philpem@0 394 #define m68k_read_immediate_16(A) m68ki_read_program_16(A)
philpem@0 395 #define m68k_read_immediate_32(A) m68ki_read_program_32(A)
philpem@0 396
philpem@0 397 #define m68k_read_pcrelative_8(A) m68ki_read_program_8(A)
philpem@0 398 #define m68k_read_pcrelative_16(A) m68ki_read_program_16(A)
philpem@0 399 #define m68k_read_pcrelative_32(A) m68ki_read_program_32(A)
philpem@0 400 #endif /* M68K_SEPARATE_READS */
philpem@0 401
philpem@0 402
philpem@0 403 /* Enable or disable callback functions */
philpem@0 404 #if M68K_EMULATE_INT_ACK
philpem@0 405 #if M68K_EMULATE_INT_ACK == OPT_SPECIFY_HANDLER
philpem@0 406 #define m68ki_int_ack(A) M68K_INT_ACK_CALLBACK(A)
philpem@0 407 #else
philpem@0 408 #define m68ki_int_ack(A) CALLBACK_INT_ACK(A)
philpem@0 409 #endif
philpem@0 410 #else
philpem@0 411 /* Default action is to used autovector mode, which is most common */
philpem@0 412 #define m68ki_int_ack(A) M68K_INT_ACK_AUTOVECTOR
philpem@0 413 #endif /* M68K_EMULATE_INT_ACK */
philpem@0 414
philpem@0 415 #if M68K_EMULATE_BKPT_ACK
philpem@0 416 #if M68K_EMULATE_BKPT_ACK == OPT_SPECIFY_HANDLER
philpem@0 417 #define m68ki_bkpt_ack(A) M68K_BKPT_ACK_CALLBACK(A)
philpem@0 418 #else
philpem@0 419 #define m68ki_bkpt_ack(A) CALLBACK_BKPT_ACK(A)
philpem@0 420 #endif
philpem@0 421 #else
philpem@0 422 #define m68ki_bkpt_ack(A)
philpem@0 423 #endif /* M68K_EMULATE_BKPT_ACK */
philpem@0 424
philpem@0 425 #if M68K_EMULATE_RESET
philpem@0 426 #if M68K_EMULATE_RESET == OPT_SPECIFY_HANDLER
philpem@0 427 #define m68ki_output_reset() M68K_RESET_CALLBACK()
philpem@0 428 #else
philpem@0 429 #define m68ki_output_reset() CALLBACK_RESET_INSTR()
philpem@0 430 #endif
philpem@0 431 #else
philpem@0 432 #define m68ki_output_reset()
philpem@0 433 #endif /* M68K_EMULATE_RESET */
philpem@0 434
philpem@0 435 #if M68K_INSTRUCTION_HOOK
philpem@0 436 #if M68K_INSTRUCTION_HOOK == OPT_SPECIFY_HANDLER
philpem@0 437 #define m68ki_instr_hook() M68K_INSTRUCTION_CALLBACK()
philpem@0 438 #else
philpem@0 439 #define m68ki_instr_hook() CALLBACK_INSTR_HOOK()
philpem@0 440 #endif
philpem@0 441 #else
philpem@0 442 #define m68ki_instr_hook()
philpem@0 443 #endif /* M68K_INSTRUCTION_HOOK */
philpem@0 444
philpem@0 445 #if M68K_MONITOR_PC
philpem@0 446 #if M68K_MONITOR_PC == OPT_SPECIFY_HANDLER
philpem@0 447 #define m68ki_pc_changed(A) M68K_SET_PC_CALLBACK(ADDRESS_68K(A))
philpem@0 448 #else
philpem@0 449 #define m68ki_pc_changed(A) CALLBACK_PC_CHANGED(ADDRESS_68K(A))
philpem@0 450 #endif
philpem@0 451 #else
philpem@0 452 #define m68ki_pc_changed(A)
philpem@0 453 #endif /* M68K_MONITOR_PC */
philpem@0 454
philpem@0 455
philpem@0 456 /* Enable or disable function code emulation */
philpem@0 457 #if M68K_EMULATE_FC
philpem@0 458 #if M68K_EMULATE_FC == OPT_SPECIFY_HANDLER
philpem@0 459 #define m68ki_set_fc(A) M68K_SET_FC_CALLBACK(A)
philpem@0 460 #else
philpem@0 461 #define m68ki_set_fc(A) CALLBACK_SET_FC(A)
philpem@0 462 #endif
philpem@0 463 #define m68ki_use_data_space() m68ki_address_space = FUNCTION_CODE_USER_DATA
philpem@0 464 #define m68ki_use_program_space() m68ki_address_space = FUNCTION_CODE_USER_PROGRAM
philpem@0 465 #define m68ki_get_address_space() m68ki_address_space
philpem@0 466 #else
philpem@0 467 #define m68ki_set_fc(A)
philpem@0 468 #define m68ki_use_data_space()
philpem@0 469 #define m68ki_use_program_space()
philpem@0 470 #define m68ki_get_address_space() FUNCTION_CODE_USER_DATA
philpem@0 471 #endif /* M68K_EMULATE_FC */
philpem@0 472
philpem@0 473
philpem@0 474 /* Enable or disable trace emulation */
philpem@0 475 #if M68K_EMULATE_TRACE
philpem@0 476 /* Initiates trace checking before each instruction (t1) */
philpem@0 477 #define m68ki_trace_t1() m68ki_tracing = FLAG_T1
philpem@0 478 /* adds t0 to trace checking if we encounter change of flow */
philpem@0 479 #define m68ki_trace_t0() m68ki_tracing |= FLAG_T0
philpem@0 480 /* Clear all tracing */
philpem@0 481 #define m68ki_clear_trace() m68ki_tracing = 0
philpem@0 482 /* Cause a trace exception if we are tracing */
philpem@0 483 #define m68ki_exception_if_trace() if(m68ki_tracing) m68ki_exception_trace()
philpem@0 484 #else
philpem@0 485 #define m68ki_trace_t1()
philpem@0 486 #define m68ki_trace_t0()
philpem@0 487 #define m68ki_clear_trace()
philpem@0 488 #define m68ki_exception_if_trace()
philpem@0 489 #endif /* M68K_EMULATE_TRACE */
philpem@0 490
philpem@0 491
philpem@0 492
philpem@0 493 /* Address error */
philpem@0 494 #if M68K_EMULATE_ADDRESS_ERROR
philpem@0 495 extern jmp_buf m68ki_address_error_trap;
philpem@0 496 #define m68ki_set_address_error_trap() if(setjmp(m68ki_address_error_trap)) m68ki_exception_address_error();
philpem@0 497 #define m68ki_check_address_error(A) if((A)&1) longjmp(m68ki_address_error_jump, 1);
philpem@0 498 #else
philpem@0 499 #define m68ki_set_address_error_trap()
philpem@0 500 #define m68ki_check_address_error(A)
philpem@0 501 #endif /* M68K_ADDRESS_ERROR */
philpem@0 502
philpem@0 503 /* Logging */
philpem@0 504 #if M68K_LOG_ENABLE
philpem@0 505 #include <stdio.h>
philpem@0 506 extern FILE* M68K_LOG_FILEHANDLE
philpem@0 507 extern char* m68ki_cpu_names[];
philpem@0 508
philpem@0 509 #define M68K_DO_LOG(A) if(M68K_LOG_FILEHANDLE) fprintf A
philpem@0 510 #if M68K_LOG_1010_1111
philpem@0 511 #define M68K_DO_LOG_EMU(A) if(M68K_LOG_FILEHANDLE) fprintf A
philpem@0 512 #else
philpem@0 513 #define M68K_DO_LOG_EMU(A)
philpem@0 514 #endif
philpem@0 515 #else
philpem@0 516 #define M68K_DO_LOG(A)
philpem@0 517 #define M68K_DO_LOG_EMU(A)
philpem@0 518 #endif
philpem@0 519
philpem@0 520
philpem@0 521
philpem@0 522 /* -------------------------- EA / Operand Access ------------------------- */
philpem@0 523
philpem@0 524 /*
philpem@0 525 * The general instruction format follows this pattern:
philpem@0 526 * .... XXX. .... .YYY
philpem@0 527 * where XXX is register X and YYY is register Y
philpem@0 528 */
philpem@0 529 /* Data Register Isolation */
philpem@0 530 #define DX (REG_D[(REG_IR >> 9) & 7])
philpem@0 531 #define DY (REG_D[REG_IR & 7])
philpem@0 532 /* Address Register Isolation */
philpem@0 533 #define AX (REG_A[(REG_IR >> 9) & 7])
philpem@0 534 #define AY (REG_A[REG_IR & 7])
philpem@0 535
philpem@0 536
philpem@0 537 /* Effective Address Calculations */
philpem@0 538 #define EA_AY_AI_8() AY /* address register indirect */
philpem@0 539 #define EA_AY_AI_16() EA_AY_AI_8()
philpem@0 540 #define EA_AY_AI_32() EA_AY_AI_8()
philpem@0 541 #define EA_AY_PI_8() (AY++) /* postincrement (size = byte) */
philpem@0 542 #define EA_AY_PI_16() ((AY+=2)-2) /* postincrement (size = word) */
philpem@0 543 #define EA_AY_PI_32() ((AY+=4)-4) /* postincrement (size = long) */
philpem@0 544 #define EA_AY_PD_8() (--AY) /* predecrement (size = byte) */
philpem@0 545 #define EA_AY_PD_16() (AY-=2) /* predecrement (size = word) */
philpem@0 546 #define EA_AY_PD_32() (AY-=4) /* predecrement (size = long) */
philpem@0 547 #define EA_AY_DI_8() (AY+MAKE_INT_16(m68ki_read_imm_16())) /* displacement */
philpem@0 548 #define EA_AY_DI_16() EA_AY_DI_8()
philpem@0 549 #define EA_AY_DI_32() EA_AY_DI_8()
philpem@0 550 #define EA_AY_IX_8() m68ki_get_ea_ix(AY) /* indirect + index */
philpem@0 551 #define EA_AY_IX_16() EA_AY_IX_8()
philpem@0 552 #define EA_AY_IX_32() EA_AY_IX_8()
philpem@0 553
philpem@0 554 #define EA_AX_AI_8() AX
philpem@0 555 #define EA_AX_AI_16() EA_AX_AI_8()
philpem@0 556 #define EA_AX_AI_32() EA_AX_AI_8()
philpem@0 557 #define EA_AX_PI_8() (AX++)
philpem@0 558 #define EA_AX_PI_16() ((AX+=2)-2)
philpem@0 559 #define EA_AX_PI_32() ((AX+=4)-4)
philpem@0 560 #define EA_AX_PD_8() (--AX)
philpem@0 561 #define EA_AX_PD_16() (AX-=2)
philpem@0 562 #define EA_AX_PD_32() (AX-=4)
philpem@0 563 #define EA_AX_DI_8() (AX+MAKE_INT_16(m68ki_read_imm_16()))
philpem@0 564 #define EA_AX_DI_16() EA_AX_DI_8()
philpem@0 565 #define EA_AX_DI_32() EA_AX_DI_8()
philpem@0 566 #define EA_AX_IX_8() m68ki_get_ea_ix(AX)
philpem@0 567 #define EA_AX_IX_16() EA_AX_IX_8()
philpem@0 568 #define EA_AX_IX_32() EA_AX_IX_8()
philpem@0 569
philpem@0 570 #define EA_A7_PI_8() ((REG_A[7]+=2)-2)
philpem@0 571 #define EA_A7_PD_8() (REG_A[7]-=2)
philpem@0 572
philpem@0 573 #define EA_AW_8() MAKE_INT_16(m68ki_read_imm_16()) /* absolute word */
philpem@0 574 #define EA_AW_16() EA_AW_8()
philpem@0 575 #define EA_AW_32() EA_AW_8()
philpem@0 576 #define EA_AL_8() m68ki_read_imm_32() /* absolute long */
philpem@0 577 #define EA_AL_16() EA_AL_8()
philpem@0 578 #define EA_AL_32() EA_AL_8()
philpem@0 579 #define EA_PCDI_8() m68ki_get_ea_pcdi() /* pc indirect + displacement */
philpem@0 580 #define EA_PCDI_16() EA_PCDI_8()
philpem@0 581 #define EA_PCDI_32() EA_PCDI_8()
philpem@0 582 #define EA_PCIX_8() m68ki_get_ea_pcix() /* pc indirect + index */
philpem@0 583 #define EA_PCIX_16() EA_PCIX_8()
philpem@0 584 #define EA_PCIX_32() EA_PCIX_8()
philpem@0 585
philpem@0 586
philpem@0 587 #define OPER_I_8() m68ki_read_imm_8()
philpem@0 588 #define OPER_I_16() m68ki_read_imm_16()
philpem@0 589 #define OPER_I_32() m68ki_read_imm_32()
philpem@0 590
philpem@0 591
philpem@0 592
philpem@0 593 /* --------------------------- Status Register ---------------------------- */
philpem@0 594
philpem@0 595 /* Flag Calculation Macros */
philpem@0 596 #define CFLAG_8(A) (A)
philpem@0 597 #define CFLAG_16(A) ((A)>>8)
philpem@0 598
philpem@0 599 #if M68K_INT_GT_32_BIT
philpem@0 600 #define CFLAG_ADD_32(S, D, R) ((R)>>24)
philpem@0 601 #define CFLAG_SUB_32(S, D, R) ((R)>>24)
philpem@0 602 #else
philpem@0 603 #define CFLAG_ADD_32(S, D, R) (((S & D) | (~R & (S | D)))>>23)
philpem@0 604 #define CFLAG_SUB_32(S, D, R) (((S & R) | (~D & (S | R)))>>23)
philpem@0 605 #endif /* M68K_INT_GT_32_BIT */
philpem@0 606
philpem@0 607 #define VFLAG_ADD_8(S, D, R) ((S^R) & (D^R))
philpem@0 608 #define VFLAG_ADD_16(S, D, R) (((S^R) & (D^R))>>8)
philpem@0 609 #define VFLAG_ADD_32(S, D, R) (((S^R) & (D^R))>>24)
philpem@0 610
philpem@0 611 #define VFLAG_SUB_8(S, D, R) ((S^D) & (R^D))
philpem@0 612 #define VFLAG_SUB_16(S, D, R) (((S^D) & (R^D))>>8)
philpem@0 613 #define VFLAG_SUB_32(S, D, R) (((S^D) & (R^D))>>24)
philpem@0 614
philpem@0 615 #define NFLAG_8(A) (A)
philpem@0 616 #define NFLAG_16(A) ((A)>>8)
philpem@0 617 #define NFLAG_32(A) ((A)>>24)
philpem@0 618 #define NFLAG_64(A) ((A)>>56)
philpem@0 619
philpem@0 620 #define ZFLAG_8(A) MASK_OUT_ABOVE_8(A)
philpem@0 621 #define ZFLAG_16(A) MASK_OUT_ABOVE_16(A)
philpem@0 622 #define ZFLAG_32(A) MASK_OUT_ABOVE_32(A)
philpem@0 623
philpem@0 624
philpem@0 625 /* Flag values */
philpem@0 626 #define NFLAG_SET 0x80
philpem@0 627 #define NFLAG_CLEAR 0
philpem@0 628 #define CFLAG_SET 0x100
philpem@0 629 #define CFLAG_CLEAR 0
philpem@0 630 #define XFLAG_SET 0x100
philpem@0 631 #define XFLAG_CLEAR 0
philpem@0 632 #define VFLAG_SET 0x80
philpem@0 633 #define VFLAG_CLEAR 0
philpem@0 634 #define ZFLAG_SET 0
philpem@0 635 #define ZFLAG_CLEAR 0xffffffff
philpem@0 636
philpem@0 637 #define SFLAG_SET 4
philpem@0 638 #define SFLAG_CLEAR 0
philpem@0 639 #define MFLAG_SET 2
philpem@0 640 #define MFLAG_CLEAR 0
philpem@0 641
philpem@0 642 /* Turn flag values into 1 or 0 */
philpem@0 643 #define XFLAG_AS_1() ((FLAG_X>>8)&1)
philpem@0 644 #define NFLAG_AS_1() ((FLAG_N>>7)&1)
philpem@0 645 #define VFLAG_AS_1() ((FLAG_V>>7)&1)
philpem@0 646 #define ZFLAG_AS_1() (!FLAG_Z)
philpem@0 647 #define CFLAG_AS_1() ((FLAG_C>>8)&1)
philpem@0 648
philpem@0 649
philpem@0 650 /* Conditions */
philpem@0 651 #define COND_CS() (FLAG_C&0x100)
philpem@0 652 #define COND_CC() (!COND_CS())
philpem@0 653 #define COND_VS() (FLAG_V&0x80)
philpem@0 654 #define COND_VC() (!COND_VS())
philpem@0 655 #define COND_NE() FLAG_Z
philpem@0 656 #define COND_EQ() (!COND_NE())
philpem@0 657 #define COND_MI() (FLAG_N&0x80)
philpem@0 658 #define COND_PL() (!COND_MI())
philpem@0 659 #define COND_LT() ((FLAG_N^FLAG_V)&0x80)
philpem@0 660 #define COND_GE() (!COND_LT())
philpem@0 661 #define COND_HI() (COND_CC() && COND_NE())
philpem@0 662 #define COND_LS() (COND_CS() || COND_EQ())
philpem@0 663 #define COND_GT() (COND_GE() && COND_NE())
philpem@0 664 #define COND_LE() (COND_LT() || COND_EQ())
philpem@0 665
philpem@0 666 /* Reversed conditions */
philpem@0 667 #define COND_NOT_CS() COND_CC()
philpem@0 668 #define COND_NOT_CC() COND_CS()
philpem@0 669 #define COND_NOT_VS() COND_VC()
philpem@0 670 #define COND_NOT_VC() COND_VS()
philpem@0 671 #define COND_NOT_NE() COND_EQ()
philpem@0 672 #define COND_NOT_EQ() COND_NE()
philpem@0 673 #define COND_NOT_MI() COND_PL()
philpem@0 674 #define COND_NOT_PL() COND_MI()
philpem@0 675 #define COND_NOT_LT() COND_GE()
philpem@0 676 #define COND_NOT_GE() COND_LT()
philpem@0 677 #define COND_NOT_HI() COND_LS()
philpem@0 678 #define COND_NOT_LS() COND_HI()
philpem@0 679 #define COND_NOT_GT() COND_LE()
philpem@0 680 #define COND_NOT_LE() COND_GT()
philpem@0 681
philpem@0 682 /* Not real conditions, but here for convenience */
philpem@0 683 #define COND_XS() (FLAG_X&0x100)
philpem@0 684 #define COND_XC() (!COND_XS)
philpem@0 685
philpem@0 686
philpem@0 687 /* Get the condition code register */
philpem@0 688 #define m68ki_get_ccr() ((COND_XS() >> 4) | \
philpem@0 689 (COND_MI() >> 4) | \
philpem@0 690 (COND_EQ() << 2) | \
philpem@0 691 (COND_VS() >> 6) | \
philpem@0 692 (COND_CS() >> 8))
philpem@0 693
philpem@0 694 /* Get the status register */
philpem@0 695 #define m68ki_get_sr() ( FLAG_T1 | \
philpem@0 696 FLAG_T0 | \
philpem@0 697 (FLAG_S << 11) | \
philpem@0 698 (FLAG_M << 11) | \
philpem@0 699 FLAG_INT_MASK | \
philpem@0 700 m68ki_get_ccr())
philpem@0 701
philpem@0 702
philpem@0 703
philpem@0 704 /* ---------------------------- Cycle Counting ---------------------------- */
philpem@0 705
philpem@0 706 #define ADD_CYCLES(A) m68ki_remaining_cycles += (A)
philpem@0 707 #define USE_CYCLES(A) m68ki_remaining_cycles -= (A)
philpem@0 708 #define SET_CYCLES(A) m68ki_remaining_cycles = A
philpem@0 709 #define GET_CYCLES() m68ki_remaining_cycles
philpem@0 710 #define USE_ALL_CYCLES() m68ki_remaining_cycles = 0
philpem@0 711
philpem@0 712
philpem@0 713
philpem@0 714 /* ----------------------------- Read / Write ----------------------------- */
philpem@0 715
philpem@0 716 /* Read from the current address space */
philpem@0 717 #define m68ki_read_8(A) m68ki_read_8_fc (A, FLAG_S | m68ki_get_address_space())
philpem@0 718 #define m68ki_read_16(A) m68ki_read_16_fc(A, FLAG_S | m68ki_get_address_space())
philpem@0 719 #define m68ki_read_32(A) m68ki_read_32_fc(A, FLAG_S | m68ki_get_address_space())
philpem@0 720
philpem@0 721 /* Write to the current data space */
philpem@0 722 #define m68ki_write_8(A, V) m68ki_write_8_fc (A, FLAG_S | FUNCTION_CODE_USER_DATA, V)
philpem@0 723 #define m68ki_write_16(A, V) m68ki_write_16_fc(A, FLAG_S | FUNCTION_CODE_USER_DATA, V)
philpem@0 724 #define m68ki_write_32(A, V) m68ki_write_32_fc(A, FLAG_S | FUNCTION_CODE_USER_DATA, V)
philpem@0 725
philpem@0 726 /* map read immediate 8 to read immediate 16 */
philpem@0 727 #define m68ki_read_imm_8() MASK_OUT_ABOVE_8(m68ki_read_imm_16())
philpem@0 728
philpem@0 729 /* Map PC-relative reads */
philpem@0 730 #define m68ki_read_pcrel_8(A) m68k_read_pcrelative_8(A)
philpem@0 731 #define m68ki_read_pcrel_16(A) m68k_read_pcrelative_16(A)
philpem@0 732 #define m68ki_read_pcrel_32(A) m68k_read_pcrelative_32(A)
philpem@0 733
philpem@0 734 /* Read from the program space */
philpem@0 735 #define m68ki_read_program_8(A) m68ki_read_8_fc(A, FLAG_S | FUNCTION_CODE_USER_PROGRAM)
philpem@0 736 #define m68ki_read_program_16(A) m68ki_read_16_fc(A, FLAG_S | FUNCTION_CODE_USER_PROGRAM)
philpem@0 737 #define m68ki_read_program_32(A) m68ki_read_32_fc(A, FLAG_S | FUNCTION_CODE_USER_PROGRAM)
philpem@0 738
philpem@0 739 /* Read from the data space */
philpem@0 740 #define m68ki_read_data_8(A) m68ki_read_8_fc(A, FLAG_S | FUNCTION_CODE_USER_DATA)
philpem@0 741 #define m68ki_read_data_16(A) m68ki_read_16_fc(A, FLAG_S | FUNCTION_CODE_USER_DATA)
philpem@0 742 #define m68ki_read_data_32(A) m68ki_read_32_fc(A, FLAG_S | FUNCTION_CODE_USER_DATA)
philpem@0 743
philpem@0 744
philpem@0 745
philpem@0 746 /* ======================================================================== */
philpem@0 747 /* =============================== PROTOTYPES ============================= */
philpem@0 748 /* ======================================================================== */
philpem@0 749
philpem@0 750 typedef struct
philpem@0 751 {
philpem@0 752 uint cpu_type; /* CPU Type: 68000, 68010, 68EC020, or 68020 */
philpem@0 753 uint dar[16]; /* Data and Address Registers */
philpem@0 754 uint ppc; /* Previous program counter */
philpem@0 755 uint pc; /* Program Counter */
philpem@0 756 uint sp[7]; /* User, Interrupt, and Master Stack Pointers */
philpem@0 757 uint vbr; /* Vector Base Register (m68010+) */
philpem@0 758 uint sfc; /* Source Function Code Register (m68010+) */
philpem@0 759 uint dfc; /* Destination Function Code Register (m68010+) */
philpem@0 760 uint cacr; /* Cache Control Register (m68020, unemulated) */
philpem@0 761 uint caar; /* Cache Address Register (m68020, unemulated) */
philpem@0 762 uint ir; /* Instruction Register */
philpem@0 763 uint t1_flag; /* Trace 1 */
philpem@0 764 uint t0_flag; /* Trace 0 */
philpem@0 765 uint s_flag; /* Supervisor */
philpem@0 766 uint m_flag; /* Master/Interrupt state */
philpem@0 767 uint x_flag; /* Extend */
philpem@0 768 uint n_flag; /* Negative */
philpem@0 769 uint not_z_flag; /* Zero, inverted for speedups */
philpem@0 770 uint v_flag; /* Overflow */
philpem@0 771 uint c_flag; /* Carry */
philpem@0 772 uint int_mask; /* I0-I2 */
philpem@0 773 uint int_level; /* State of interrupt pins IPL0-IPL2 -- ASG: changed from ints_pending */
philpem@0 774 uint int_cycles; /* ASG: extra cycles from generated interrupts */
philpem@0 775 uint stopped; /* Stopped state */
philpem@0 776 uint pref_addr; /* Last prefetch address */
philpem@0 777 uint pref_data; /* Data in the prefetch queue */
philpem@0 778 uint address_mask; /* Available address pins */
philpem@0 779 uint sr_mask; /* Implemented status register bits */
philpem@0 780
philpem@109 781 uint bus_error_occurred;
philpem@109 782
philpem@0 783 /* Clocks required for instructions / exceptions */
philpem@0 784 uint cyc_bcc_notake_b;
philpem@0 785 uint cyc_bcc_notake_w;
philpem@0 786 uint cyc_dbcc_f_noexp;
philpem@0 787 uint cyc_dbcc_f_exp;
philpem@0 788 uint cyc_scc_r_false;
philpem@0 789 uint cyc_movem_w;
philpem@0 790 uint cyc_movem_l;
philpem@0 791 uint cyc_shift;
philpem@0 792 uint cyc_reset;
philpem@0 793 uint8* cyc_instruction;
philpem@0 794 uint8* cyc_exception;
philpem@0 795
philpem@0 796 /* Callbacks to host */
philpem@0 797 int (*int_ack_callback)(int int_line); /* Interrupt Acknowledge */
philpem@0 798 void (*bkpt_ack_callback)(unsigned int data); /* Breakpoint Acknowledge */
philpem@0 799 void (*reset_instr_callback)(void); /* Called when a RESET instruction is encountered */
philpem@0 800 void (*pc_changed_callback)(unsigned int new_pc); /* Called when the PC changes by a large amount */
philpem@0 801 void (*set_fc_callback)(unsigned int new_fc); /* Called when the CPU function code changes */
philpem@0 802 void (*instr_hook_callback)(void); /* Called every instruction cycle prior to execution */
philpem@0 803
philpem@0 804 } m68ki_cpu_core;
philpem@0 805
philpem@0 806
philpem@0 807 extern m68ki_cpu_core m68ki_cpu;
philpem@0 808 extern sint m68ki_remaining_cycles;
philpem@0 809 extern uint m68ki_tracing;
philpem@0 810 extern uint8 m68ki_shift_8_table[];
philpem@0 811 extern uint16 m68ki_shift_16_table[];
philpem@0 812 extern uint m68ki_shift_32_table[];
philpem@0 813 extern uint8 m68ki_exception_cycle_table[][256];
philpem@0 814 extern uint m68ki_address_space;
philpem@0 815 extern uint8 m68ki_ea_idx_cycle_table[];
philpem@0 816
philpem@0 817
philpem@0 818 /* Read data immediately after the program counter */
philpem@0 819 INLINE uint m68ki_read_imm_16(void);
philpem@0 820 INLINE uint m68ki_read_imm_32(void);
philpem@0 821
philpem@0 822 /* Read data with specific function code */
philpem@0 823 INLINE uint m68ki_read_8_fc (uint address, uint fc);
philpem@0 824 INLINE uint m68ki_read_16_fc (uint address, uint fc);
philpem@0 825 INLINE uint m68ki_read_32_fc (uint address, uint fc);
philpem@0 826
philpem@0 827 /* Write data with specific function code */
philpem@0 828 INLINE void m68ki_write_8_fc (uint address, uint fc, uint value);
philpem@0 829 INLINE void m68ki_write_16_fc(uint address, uint fc, uint value);
philpem@0 830 INLINE void m68ki_write_32_fc(uint address, uint fc, uint value);
philpem@0 831
philpem@0 832 /* Indexed and PC-relative ea fetching */
philpem@0 833 INLINE uint m68ki_get_ea_pcdi(void);
philpem@0 834 INLINE uint m68ki_get_ea_pcix(void);
philpem@0 835 INLINE uint m68ki_get_ea_ix(uint An);
philpem@0 836
philpem@0 837 /* Operand fetching */
philpem@0 838 INLINE uint OPER_AY_AI_8(void);
philpem@0 839 INLINE uint OPER_AY_AI_16(void);
philpem@0 840 INLINE uint OPER_AY_AI_32(void);
philpem@0 841 INLINE uint OPER_AY_PI_8(void);
philpem@0 842 INLINE uint OPER_AY_PI_16(void);
philpem@0 843 INLINE uint OPER_AY_PI_32(void);
philpem@0 844 INLINE uint OPER_AY_PD_8(void);
philpem@0 845 INLINE uint OPER_AY_PD_16(void);
philpem@0 846 INLINE uint OPER_AY_PD_32(void);
philpem@0 847 INLINE uint OPER_AY_DI_8(void);
philpem@0 848 INLINE uint OPER_AY_DI_16(void);
philpem@0 849 INLINE uint OPER_AY_DI_32(void);
philpem@0 850 INLINE uint OPER_AY_IX_8(void);
philpem@0 851 INLINE uint OPER_AY_IX_16(void);
philpem@0 852 INLINE uint OPER_AY_IX_32(void);
philpem@0 853
philpem@0 854 INLINE uint OPER_AX_AI_8(void);
philpem@0 855 INLINE uint OPER_AX_AI_16(void);
philpem@0 856 INLINE uint OPER_AX_AI_32(void);
philpem@0 857 INLINE uint OPER_AX_PI_8(void);
philpem@0 858 INLINE uint OPER_AX_PI_16(void);
philpem@0 859 INLINE uint OPER_AX_PI_32(void);
philpem@0 860 INLINE uint OPER_AX_PD_8(void);
philpem@0 861 INLINE uint OPER_AX_PD_16(void);
philpem@0 862 INLINE uint OPER_AX_PD_32(void);
philpem@0 863 INLINE uint OPER_AX_DI_8(void);
philpem@0 864 INLINE uint OPER_AX_DI_16(void);
philpem@0 865 INLINE uint OPER_AX_DI_32(void);
philpem@0 866 INLINE uint OPER_AX_IX_8(void);
philpem@0 867 INLINE uint OPER_AX_IX_16(void);
philpem@0 868 INLINE uint OPER_AX_IX_32(void);
philpem@0 869
philpem@0 870 INLINE uint OPER_A7_PI_8(void);
philpem@0 871 INLINE uint OPER_A7_PD_8(void);
philpem@0 872
philpem@0 873 INLINE uint OPER_AW_8(void);
philpem@0 874 INLINE uint OPER_AW_16(void);
philpem@0 875 INLINE uint OPER_AW_32(void);
philpem@0 876 INLINE uint OPER_AL_8(void);
philpem@0 877 INLINE uint OPER_AL_16(void);
philpem@0 878 INLINE uint OPER_AL_32(void);
philpem@0 879 INLINE uint OPER_PCDI_8(void);
philpem@0 880 INLINE uint OPER_PCDI_16(void);
philpem@0 881 INLINE uint OPER_PCDI_32(void);
philpem@0 882 INLINE uint OPER_PCIX_8(void);
philpem@0 883 INLINE uint OPER_PCIX_16(void);
philpem@0 884 INLINE uint OPER_PCIX_32(void);
philpem@0 885
philpem@0 886 /* Stack operations */
philpem@0 887 INLINE void m68ki_push_16(uint value);
philpem@0 888 INLINE void m68ki_push_32(uint value);
philpem@0 889 INLINE uint m68ki_pull_16(void);
philpem@0 890 INLINE uint m68ki_pull_32(void);
philpem@0 891
philpem@0 892 /* Program flow operations */
philpem@0 893 INLINE void m68ki_jump(uint new_pc);
philpem@0 894 INLINE void m68ki_jump_vector(uint vector);
philpem@0 895 INLINE void m68ki_branch_8(uint offset);
philpem@0 896 INLINE void m68ki_branch_16(uint offset);
philpem@0 897 INLINE void m68ki_branch_32(uint offset);
philpem@0 898
philpem@0 899 /* Status register operations. */
philpem@0 900 INLINE void m68ki_set_s_flag(uint value); /* Only bit 2 of value should be set (i.e. 4 or 0) */
philpem@0 901 INLINE void m68ki_set_sm_flag(uint value); /* only bits 1 and 2 of value should be set */
philpem@0 902 INLINE void m68ki_set_ccr(uint value); /* set the condition code register */
philpem@0 903 INLINE void m68ki_set_sr(uint value); /* set the status register */
philpem@0 904 INLINE void m68ki_set_sr_noint(uint value); /* set the status register */
philpem@0 905
philpem@0 906 /* Exception processing */
philpem@0 907 INLINE uint m68ki_init_exception(void); /* Initial exception processing */
philpem@0 908
philpem@0 909 INLINE void m68ki_stack_frame_3word(uint pc, uint sr); /* Stack various frame types */
philpem@0 910 INLINE void m68ki_stack_frame_buserr(uint pc, uint sr, uint address, uint write, uint instruction, uint fc);
philpem@0 911
philpem@0 912 INLINE void m68ki_stack_frame_0000(uint pc, uint sr, uint vector);
philpem@0 913 INLINE void m68ki_stack_frame_0001(uint pc, uint sr, uint vector);
philpem@0 914 INLINE void m68ki_stack_frame_0010(uint sr, uint vector);
philpem@0 915 INLINE void m68ki_stack_frame_1000(uint pc, uint sr, uint vector);
philpem@0 916 INLINE void m68ki_stack_frame_1010(uint sr, uint vector, uint pc);
philpem@0 917 INLINE void m68ki_stack_frame_1011(uint sr, uint vector, uint pc);
philpem@0 918
philpem@0 919 INLINE void m68ki_exception_trap(uint vector);
philpem@0 920 INLINE void m68ki_exception_trapN(uint vector);
philpem@0 921 INLINE void m68ki_exception_trace(void);
philpem@0 922 INLINE void m68ki_exception_privilege_violation(void);
philpem@19 923 INLINE void m68ki_exception_bus_error(void);
philpem@0 924 INLINE void m68ki_exception_1010(void);
philpem@0 925 INLINE void m68ki_exception_1111(void);
philpem@0 926 INLINE void m68ki_exception_illegal(void);
philpem@0 927 INLINE void m68ki_exception_format_error(void);
philpem@0 928 INLINE void m68ki_exception_address_error(void);
philpem@0 929 INLINE void m68ki_exception_interrupt(uint int_level);
philpem@0 930 INLINE void m68ki_check_interrupts(void); /* ASG: check for interrupts */
philpem@0 931
philpem@0 932 /* quick disassembly (used for logging) */
philpem@0 933 char* m68ki_disassemble_quick(unsigned int pc, unsigned int cpu_type);
philpem@0 934
philpem@0 935
philpem@0 936 /* ======================================================================== */
philpem@0 937 /* =========================== UTILITY FUNCTIONS ========================== */
philpem@0 938 /* ======================================================================== */
philpem@0 939
philpem@0 940
philpem@0 941 /* ---------------------------- Read Immediate ---------------------------- */
philpem@0 942
philpem@0 943 /* Handles all immediate reads, does address error check, function code setting,
philpem@0 944 * and prefetching if they are enabled in m68kconf.h
philpem@0 945 */
philpem@0 946 INLINE uint m68ki_read_imm_16(void)
philpem@0 947 {
philpem@0 948 m68ki_set_fc(FLAG_S | FUNCTION_CODE_USER_PROGRAM); /* auto-disable (see m68kcpu.h) */
philpem@0 949 m68ki_check_address_error(REG_PC); /* auto-disable (see m68kcpu.h) */
philpem@0 950 #if M68K_EMULATE_PREFETCH
philpem@0 951 if(MASK_OUT_BELOW_2(REG_PC) != CPU_PREF_ADDR)
philpem@0 952 {
philpem@0 953 CPU_PREF_ADDR = MASK_OUT_BELOW_2(REG_PC);
philpem@0 954 CPU_PREF_DATA = m68k_read_immediate_32(ADDRESS_68K(CPU_PREF_ADDR));
philpem@0 955 }
philpem@0 956 REG_PC += 2;
philpem@0 957 return MASK_OUT_ABOVE_16(CPU_PREF_DATA >> ((2-((REG_PC-2)&2))<<3));
philpem@0 958 #else
philpem@0 959 REG_PC += 2;
philpem@0 960 return m68k_read_immediate_16(ADDRESS_68K(REG_PC-2));
philpem@0 961 #endif /* M68K_EMULATE_PREFETCH */
philpem@0 962 }
philpem@0 963 INLINE uint m68ki_read_imm_32(void)
philpem@0 964 {
philpem@0 965 #if M68K_EMULATE_PREFETCH
philpem@0 966 uint temp_val;
philpem@0 967
philpem@0 968 m68ki_set_fc(FLAG_S | FUNCTION_CODE_USER_PROGRAM); /* auto-disable (see m68kcpu.h) */
philpem@0 969 m68ki_check_address_error(REG_PC); /* auto-disable (see m68kcpu.h) */
philpem@0 970 if(MASK_OUT_BELOW_2(REG_PC) != CPU_PREF_ADDR)
philpem@0 971 {
philpem@0 972 CPU_PREF_ADDR = MASK_OUT_BELOW_2(REG_PC);
philpem@0 973 CPU_PREF_DATA = m68k_read_immediate_32(ADDRESS_68K(CPU_PREF_ADDR));
philpem@0 974 }
philpem@0 975 temp_val = CPU_PREF_DATA;
philpem@0 976 REG_PC += 2;
philpem@0 977 if(MASK_OUT_BELOW_2(REG_PC) != CPU_PREF_ADDR)
philpem@0 978 {
philpem@0 979 CPU_PREF_ADDR = MASK_OUT_BELOW_2(REG_PC);
philpem@0 980 CPU_PREF_DATA = m68k_read_immediate_32(ADDRESS_68K(CPU_PREF_ADDR));
philpem@0 981 temp_val = MASK_OUT_ABOVE_32((temp_val << 16) | (CPU_PREF_DATA >> 16));
philpem@0 982 }
philpem@0 983 REG_PC += 2;
philpem@0 984
philpem@0 985 return temp_val;
philpem@0 986 #else
philpem@0 987 m68ki_set_fc(FLAG_S | FUNCTION_CODE_USER_PROGRAM); /* auto-disable (see m68kcpu.h) */
philpem@0 988 m68ki_check_address_error(REG_PC); /* auto-disable (see m68kcpu.h) */
philpem@0 989 REG_PC += 4;
philpem@0 990 return m68k_read_immediate_32(ADDRESS_68K(REG_PC-4));
philpem@0 991 #endif /* M68K_EMULATE_PREFETCH */
philpem@0 992 }
philpem@0 993
philpem@0 994
philpem@0 995
philpem@0 996 /* ------------------------- Top level read/write ------------------------- */
philpem@0 997
philpem@0 998 /* Handles all memory accesses (except for immediate reads if they are
philpem@0 999 * configured to use separate functions in m68kconf.h).
philpem@0 1000 * All memory accesses must go through these top level functions.
philpem@0 1001 * These functions will also check for address error and set the function
philpem@0 1002 * code if they are enabled in m68kconf.h.
philpem@0 1003 */
philpem@0 1004 INLINE uint m68ki_read_8_fc(uint address, uint fc)
philpem@0 1005 {
philpem@0 1006 m68ki_set_fc(fc); /* auto-disable (see m68kcpu.h) */
philpem@0 1007 return m68k_read_memory_8(ADDRESS_68K(address));
philpem@0 1008 }
philpem@0 1009 INLINE uint m68ki_read_16_fc(uint address, uint fc)
philpem@0 1010 {
philpem@0 1011 m68ki_set_fc(fc); /* auto-disable (see m68kcpu.h) */
philpem@0 1012 m68ki_check_address_error(address); /* auto-disable (see m68kcpu.h) */
philpem@0 1013 return m68k_read_memory_16(ADDRESS_68K(address));
philpem@0 1014 }
philpem@0 1015 INLINE uint m68ki_read_32_fc(uint address, uint fc)
philpem@0 1016 {
philpem@0 1017 m68ki_set_fc(fc); /* auto-disable (see m68kcpu.h) */
philpem@0 1018 m68ki_check_address_error(address); /* auto-disable (see m68kcpu.h) */
philpem@0 1019 return m68k_read_memory_32(ADDRESS_68K(address));
philpem@0 1020 }
philpem@0 1021
philpem@0 1022 INLINE void m68ki_write_8_fc(uint address, uint fc, uint value)
philpem@0 1023 {
philpem@0 1024 m68ki_set_fc(fc); /* auto-disable (see m68kcpu.h) */
philpem@0 1025 m68k_write_memory_8(ADDRESS_68K(address), value);
philpem@0 1026 }
philpem@0 1027 INLINE void m68ki_write_16_fc(uint address, uint fc, uint value)
philpem@0 1028 {
philpem@0 1029 m68ki_set_fc(fc); /* auto-disable (see m68kcpu.h) */
philpem@0 1030 m68ki_check_address_error(address); /* auto-disable (see m68kcpu.h) */
philpem@0 1031 m68k_write_memory_16(ADDRESS_68K(address), value);
philpem@0 1032 }
philpem@0 1033 INLINE void m68ki_write_32_fc(uint address, uint fc, uint value)
philpem@0 1034 {
philpem@0 1035 m68ki_set_fc(fc); /* auto-disable (see m68kcpu.h) */
philpem@0 1036 m68ki_check_address_error(address); /* auto-disable (see m68kcpu.h) */
philpem@0 1037 m68k_write_memory_32(ADDRESS_68K(address), value);
philpem@0 1038 }
philpem@0 1039
philpem@0 1040
philpem@0 1041
philpem@0 1042 /* --------------------- Effective Address Calculation -------------------- */
philpem@0 1043
philpem@0 1044 /* The program counter relative addressing modes cause operands to be
philpem@0 1045 * retrieved from program space, not data space.
philpem@0 1046 */
philpem@0 1047 INLINE uint m68ki_get_ea_pcdi(void)
philpem@0 1048 {
philpem@0 1049 uint old_pc = REG_PC;
philpem@0 1050 m68ki_use_program_space(); /* auto-disable */
philpem@0 1051 return old_pc + MAKE_INT_16(m68ki_read_imm_16());
philpem@0 1052 }
philpem@0 1053
philpem@0 1054
philpem@0 1055 INLINE uint m68ki_get_ea_pcix(void)
philpem@0 1056 {
philpem@0 1057 m68ki_use_program_space(); /* auto-disable */
philpem@0 1058 return m68ki_get_ea_ix(REG_PC);
philpem@0 1059 }
philpem@0 1060
philpem@0 1061 /* Indexed addressing modes are encoded as follows:
philpem@0 1062 *
philpem@0 1063 * Base instruction format:
philpem@0 1064 * F E D C B A 9 8 7 6 | 5 4 3 | 2 1 0
philpem@0 1065 * x x x x x x x x x x | 1 1 0 | BASE REGISTER (An)
philpem@0 1066 *
philpem@0 1067 * Base instruction format for destination EA in move instructions:
philpem@0 1068 * F E D C | B A 9 | 8 7 6 | 5 4 3 2 1 0
philpem@0 1069 * x x x x | BASE REG | 1 1 0 | X X X X X X (An)
philpem@0 1070 *
philpem@0 1071 * Brief extension format:
philpem@0 1072 * F | E D C | B | A 9 | 8 | 7 6 5 4 3 2 1 0
philpem@0 1073 * D/A | REGISTER | W/L | SCALE | 0 | DISPLACEMENT
philpem@0 1074 *
philpem@0 1075 * Full extension format:
philpem@0 1076 * F E D C B A 9 8 7 6 5 4 3 2 1 0
philpem@0 1077 * D/A | REGISTER | W/L | SCALE | 1 | BS | IS | BD SIZE | 0 | I/IS
philpem@0 1078 * BASE DISPLACEMENT (0, 16, 32 bit) (bd)
philpem@0 1079 * OUTER DISPLACEMENT (0, 16, 32 bit) (od)
philpem@0 1080 *
philpem@0 1081 * D/A: 0 = Dn, 1 = An (Xn)
philpem@0 1082 * W/L: 0 = W (sign extend), 1 = L (.SIZE)
philpem@0 1083 * SCALE: 00=1, 01=2, 10=4, 11=8 (*SCALE)
philpem@0 1084 * BS: 0=add base reg, 1=suppress base reg (An suppressed)
philpem@0 1085 * IS: 0=add index, 1=suppress index (Xn suppressed)
philpem@0 1086 * BD SIZE: 00=reserved, 01=NULL, 10=Word, 11=Long (size of bd)
philpem@0 1087 *
philpem@0 1088 * IS I/IS Operation
philpem@0 1089 * 0 000 No Memory Indirect
philpem@0 1090 * 0 001 indir prex with null outer
philpem@0 1091 * 0 010 indir prex with word outer
philpem@0 1092 * 0 011 indir prex with long outer
philpem@0 1093 * 0 100 reserved
philpem@0 1094 * 0 101 indir postx with null outer
philpem@0 1095 * 0 110 indir postx with word outer
philpem@0 1096 * 0 111 indir postx with long outer
philpem@0 1097 * 1 000 no memory indirect
philpem@0 1098 * 1 001 mem indir with null outer
philpem@0 1099 * 1 010 mem indir with word outer
philpem@0 1100 * 1 011 mem indir with long outer
philpem@0 1101 * 1 100-111 reserved
philpem@0 1102 */
philpem@0 1103 INLINE uint m68ki_get_ea_ix(uint An)
philpem@0 1104 {
philpem@0 1105 /* An = base register */
philpem@0 1106 uint extension = m68ki_read_imm_16();
philpem@0 1107 uint Xn = 0; /* Index register */
philpem@0 1108 uint bd = 0; /* Base Displacement */
philpem@0 1109 uint od = 0; /* Outer Displacement */
philpem@0 1110
philpem@0 1111 if(CPU_TYPE_IS_010_LESS(CPU_TYPE))
philpem@0 1112 {
philpem@0 1113 /* Calculate index */
philpem@0 1114 Xn = REG_DA[extension>>12]; /* Xn */
philpem@0 1115 if(!BIT_B(extension)) /* W/L */
philpem@0 1116 Xn = MAKE_INT_16(Xn);
philpem@0 1117
philpem@0 1118 /* Add base register and displacement and return */
philpem@0 1119 return An + Xn + MAKE_INT_8(extension);
philpem@0 1120 }
philpem@0 1121
philpem@0 1122 /* Brief extension format */
philpem@0 1123 if(!BIT_8(extension))
philpem@0 1124 {
philpem@0 1125 /* Calculate index */
philpem@0 1126 Xn = REG_DA[extension>>12]; /* Xn */
philpem@0 1127 if(!BIT_B(extension)) /* W/L */
philpem@0 1128 Xn = MAKE_INT_16(Xn);
philpem@0 1129 /* Add scale if proper CPU type */
philpem@0 1130 if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE))
philpem@0 1131 Xn <<= (extension>>9) & 3; /* SCALE */
philpem@0 1132
philpem@0 1133 /* Add base register and displacement and return */
philpem@0 1134 return An + Xn + MAKE_INT_8(extension);
philpem@0 1135 }
philpem@0 1136
philpem@0 1137 /* Full extension format */
philpem@0 1138
philpem@0 1139 USE_CYCLES(m68ki_ea_idx_cycle_table[extension&0x3f]);
philpem@0 1140
philpem@0 1141 /* Check if base register is present */
philpem@0 1142 if(BIT_7(extension)) /* BS */
philpem@0 1143 An = 0; /* An */
philpem@0 1144
philpem@0 1145 /* Check if index is present */
philpem@0 1146 if(!BIT_6(extension)) /* IS */
philpem@0 1147 {
philpem@0 1148 Xn = REG_DA[extension>>12]; /* Xn */
philpem@0 1149 if(!BIT_B(extension)) /* W/L */
philpem@0 1150 Xn = MAKE_INT_16(Xn);
philpem@0 1151 Xn <<= (extension>>9) & 3; /* SCALE */
philpem@0 1152 }
philpem@0 1153
philpem@0 1154 /* Check if base displacement is present */
philpem@0 1155 if(BIT_5(extension)) /* BD SIZE */
philpem@0 1156 bd = BIT_4(extension) ? m68ki_read_imm_32() : MAKE_INT_16(m68ki_read_imm_16());
philpem@0 1157
philpem@0 1158 /* If no indirect action, we are done */
philpem@0 1159 if(!(extension&7)) /* No Memory Indirect */
philpem@0 1160 return An + bd + Xn;
philpem@0 1161
philpem@0 1162 /* Check if outer displacement is present */
philpem@0 1163 if(BIT_1(extension)) /* I/IS: od */
philpem@0 1164 od = BIT_0(extension) ? m68ki_read_imm_32() : MAKE_INT_16(m68ki_read_imm_16());
philpem@0 1165
philpem@0 1166 /* Postindex */
philpem@0 1167 if(BIT_2(extension)) /* I/IS: 0 = preindex, 1 = postindex */
philpem@0 1168 return m68ki_read_32(An + bd) + Xn + od;
philpem@0 1169
philpem@0 1170 /* Preindex */
philpem@0 1171 return m68ki_read_32(An + bd + Xn) + od;
philpem@0 1172 }
philpem@0 1173
philpem@0 1174
philpem@0 1175 /* Fetch operands */
philpem@0 1176 INLINE uint OPER_AY_AI_8(void) {uint ea = EA_AY_AI_8(); return m68ki_read_8(ea); }
philpem@0 1177 INLINE uint OPER_AY_AI_16(void) {uint ea = EA_AY_AI_16(); return m68ki_read_16(ea);}
philpem@0 1178 INLINE uint OPER_AY_AI_32(void) {uint ea = EA_AY_AI_32(); return m68ki_read_32(ea);}
philpem@0 1179 INLINE uint OPER_AY_PI_8(void) {uint ea = EA_AY_PI_8(); return m68ki_read_8(ea); }
philpem@0 1180 INLINE uint OPER_AY_PI_16(void) {uint ea = EA_AY_PI_16(); return m68ki_read_16(ea);}
philpem@0 1181 INLINE uint OPER_AY_PI_32(void) {uint ea = EA_AY_PI_32(); return m68ki_read_32(ea);}
philpem@0 1182 INLINE uint OPER_AY_PD_8(void) {uint ea = EA_AY_PD_8(); return m68ki_read_8(ea); }
philpem@0 1183 INLINE uint OPER_AY_PD_16(void) {uint ea = EA_AY_PD_16(); return m68ki_read_16(ea);}
philpem@0 1184 INLINE uint OPER_AY_PD_32(void) {uint ea = EA_AY_PD_32(); return m68ki_read_32(ea);}
philpem@0 1185 INLINE uint OPER_AY_DI_8(void) {uint ea = EA_AY_DI_8(); return m68ki_read_8(ea); }
philpem@0 1186 INLINE uint OPER_AY_DI_16(void) {uint ea = EA_AY_DI_16(); return m68ki_read_16(ea);}
philpem@0 1187 INLINE uint OPER_AY_DI_32(void) {uint ea = EA_AY_DI_32(); return m68ki_read_32(ea);}
philpem@0 1188 INLINE uint OPER_AY_IX_8(void) {uint ea = EA_AY_IX_8(); return m68ki_read_8(ea); }
philpem@0 1189 INLINE uint OPER_AY_IX_16(void) {uint ea = EA_AY_IX_16(); return m68ki_read_16(ea);}
philpem@0 1190 INLINE uint OPER_AY_IX_32(void) {uint ea = EA_AY_IX_32(); return m68ki_read_32(ea);}
philpem@0 1191
philpem@0 1192 INLINE uint OPER_AX_AI_8(void) {uint ea = EA_AX_AI_8(); return m68ki_read_8(ea); }
philpem@0 1193 INLINE uint OPER_AX_AI_16(void) {uint ea = EA_AX_AI_16(); return m68ki_read_16(ea);}
philpem@0 1194 INLINE uint OPER_AX_AI_32(void) {uint ea = EA_AX_AI_32(); return m68ki_read_32(ea);}
philpem@0 1195 INLINE uint OPER_AX_PI_8(void) {uint ea = EA_AX_PI_8(); return m68ki_read_8(ea); }
philpem@0 1196 INLINE uint OPER_AX_PI_16(void) {uint ea = EA_AX_PI_16(); return m68ki_read_16(ea);}
philpem@0 1197 INLINE uint OPER_AX_PI_32(void) {uint ea = EA_AX_PI_32(); return m68ki_read_32(ea);}
philpem@0 1198 INLINE uint OPER_AX_PD_8(void) {uint ea = EA_AX_PD_8(); return m68ki_read_8(ea); }
philpem@0 1199 INLINE uint OPER_AX_PD_16(void) {uint ea = EA_AX_PD_16(); return m68ki_read_16(ea);}
philpem@0 1200 INLINE uint OPER_AX_PD_32(void) {uint ea = EA_AX_PD_32(); return m68ki_read_32(ea);}
philpem@0 1201 INLINE uint OPER_AX_DI_8(void) {uint ea = EA_AX_DI_8(); return m68ki_read_8(ea); }
philpem@0 1202 INLINE uint OPER_AX_DI_16(void) {uint ea = EA_AX_DI_16(); return m68ki_read_16(ea);}
philpem@0 1203 INLINE uint OPER_AX_DI_32(void) {uint ea = EA_AX_DI_32(); return m68ki_read_32(ea);}
philpem@0 1204 INLINE uint OPER_AX_IX_8(void) {uint ea = EA_AX_IX_8(); return m68ki_read_8(ea); }
philpem@0 1205 INLINE uint OPER_AX_IX_16(void) {uint ea = EA_AX_IX_16(); return m68ki_read_16(ea);}
philpem@0 1206 INLINE uint OPER_AX_IX_32(void) {uint ea = EA_AX_IX_32(); return m68ki_read_32(ea);}
philpem@0 1207
philpem@0 1208 INLINE uint OPER_A7_PI_8(void) {uint ea = EA_A7_PI_8(); return m68ki_read_8(ea); }
philpem@0 1209 INLINE uint OPER_A7_PD_8(void) {uint ea = EA_A7_PD_8(); return m68ki_read_8(ea); }
philpem@0 1210
philpem@0 1211 INLINE uint OPER_AW_8(void) {uint ea = EA_AW_8(); return m68ki_read_8(ea); }
philpem@0 1212 INLINE uint OPER_AW_16(void) {uint ea = EA_AW_16(); return m68ki_read_16(ea);}
philpem@0 1213 INLINE uint OPER_AW_32(void) {uint ea = EA_AW_32(); return m68ki_read_32(ea);}
philpem@0 1214 INLINE uint OPER_AL_8(void) {uint ea = EA_AL_8(); return m68ki_read_8(ea); }
philpem@0 1215 INLINE uint OPER_AL_16(void) {uint ea = EA_AL_16(); return m68ki_read_16(ea);}
philpem@0 1216 INLINE uint OPER_AL_32(void) {uint ea = EA_AL_32(); return m68ki_read_32(ea);}
philpem@0 1217 INLINE uint OPER_PCDI_8(void) {uint ea = EA_PCDI_8(); return m68ki_read_pcrel_8(ea); }
philpem@0 1218 INLINE uint OPER_PCDI_16(void) {uint ea = EA_PCDI_16(); return m68ki_read_pcrel_16(ea);}
philpem@0 1219 INLINE uint OPER_PCDI_32(void) {uint ea = EA_PCDI_32(); return m68ki_read_pcrel_32(ea);}
philpem@0 1220 INLINE uint OPER_PCIX_8(void) {uint ea = EA_PCIX_8(); return m68ki_read_pcrel_8(ea); }
philpem@0 1221 INLINE uint OPER_PCIX_16(void) {uint ea = EA_PCIX_16(); return m68ki_read_pcrel_16(ea);}
philpem@0 1222 INLINE uint OPER_PCIX_32(void) {uint ea = EA_PCIX_32(); return m68ki_read_pcrel_32(ea);}
philpem@0 1223
philpem@0 1224
philpem@0 1225
philpem@0 1226 /* ---------------------------- Stack Functions --------------------------- */
philpem@0 1227
philpem@0 1228 /* Push/pull data from the stack */
philpem@0 1229 INLINE void m68ki_push_16(uint value)
philpem@0 1230 {
philpem@0 1231 REG_SP = MASK_OUT_ABOVE_32(REG_SP - 2);
philpem@0 1232 m68ki_write_16(REG_SP, value);
philpem@0 1233 }
philpem@0 1234
philpem@0 1235 INLINE void m68ki_push_32(uint value)
philpem@0 1236 {
philpem@0 1237 REG_SP = MASK_OUT_ABOVE_32(REG_SP - 4);
philpem@0 1238 m68ki_write_32(REG_SP, value);
philpem@0 1239 }
philpem@0 1240
philpem@0 1241 INLINE uint m68ki_pull_16(void)
philpem@0 1242 {
philpem@0 1243 REG_SP = MASK_OUT_ABOVE_32(REG_SP + 2);
philpem@0 1244 return m68ki_read_16(REG_SP-2);
philpem@0 1245 }
philpem@0 1246
philpem@0 1247 INLINE uint m68ki_pull_32(void)
philpem@0 1248 {
philpem@0 1249 REG_SP = MASK_OUT_ABOVE_32(REG_SP + 4);
philpem@0 1250 return m68ki_read_32(REG_SP-4);
philpem@0 1251 }
philpem@0 1252
philpem@0 1253
philpem@0 1254 /* Increment/decrement the stack as if doing a push/pull but
philpem@0 1255 * don't do any memory access.
philpem@0 1256 */
philpem@0 1257 INLINE void m68ki_fake_push_16(void)
philpem@0 1258 {
philpem@0 1259 REG_SP = MASK_OUT_ABOVE_32(REG_SP - 2);
philpem@0 1260 }
philpem@0 1261
philpem@0 1262 INLINE void m68ki_fake_push_32(void)
philpem@0 1263 {
philpem@0 1264 REG_SP = MASK_OUT_ABOVE_32(REG_SP - 4);
philpem@0 1265 }
philpem@0 1266
philpem@0 1267 INLINE void m68ki_fake_pull_16(void)
philpem@0 1268 {
philpem@0 1269 REG_SP = MASK_OUT_ABOVE_32(REG_SP + 2);
philpem@0 1270 }
philpem@0 1271
philpem@0 1272 INLINE void m68ki_fake_pull_32(void)
philpem@0 1273 {
philpem@0 1274 REG_SP = MASK_OUT_ABOVE_32(REG_SP + 4);
philpem@0 1275 }
philpem@0 1276
philpem@0 1277
philpem@0 1278 /* ----------------------------- Program Flow ----------------------------- */
philpem@0 1279
philpem@0 1280 /* Jump to a new program location or vector.
philpem@0 1281 * These functions will also call the pc_changed callback if it was enabled
philpem@0 1282 * in m68kconf.h.
philpem@0 1283 */
philpem@0 1284 INLINE void m68ki_jump(uint new_pc)
philpem@0 1285 {
philpem@0 1286 REG_PC = new_pc;
philpem@0 1287 m68ki_pc_changed(REG_PC);
philpem@0 1288 }
philpem@0 1289
philpem@0 1290 INLINE void m68ki_jump_vector(uint vector)
philpem@0 1291 {
philpem@0 1292 REG_PC = (vector<<2) + REG_VBR;
philpem@0 1293 REG_PC = m68ki_read_data_32(REG_PC);
philpem@0 1294 m68ki_pc_changed(REG_PC);
philpem@0 1295 }
philpem@0 1296
philpem@0 1297
philpem@0 1298 /* Branch to a new memory location.
philpem@0 1299 * The 32-bit branch will call pc_changed if it was enabled in m68kconf.h.
philpem@0 1300 * So far I've found no problems with not calling pc_changed for 8 or 16
philpem@0 1301 * bit branches.
philpem@0 1302 */
philpem@0 1303 INLINE void m68ki_branch_8(uint offset)
philpem@0 1304 {
philpem@0 1305 REG_PC += MAKE_INT_8(offset);
philpem@0 1306 }
philpem@0 1307
philpem@0 1308 INLINE void m68ki_branch_16(uint offset)
philpem@0 1309 {
philpem@0 1310 REG_PC += MAKE_INT_16(offset);
philpem@0 1311 }
philpem@0 1312
philpem@0 1313 INLINE void m68ki_branch_32(uint offset)
philpem@0 1314 {
philpem@0 1315 REG_PC += offset;
philpem@0 1316 m68ki_pc_changed(REG_PC);
philpem@0 1317 }
philpem@0 1318
philpem@0 1319
philpem@0 1320
philpem@0 1321 /* ---------------------------- Status Register --------------------------- */
philpem@0 1322
philpem@0 1323 /* Set the S flag and change the active stack pointer.
philpem@0 1324 * Note that value MUST be 4 or 0.
philpem@0 1325 */
philpem@0 1326 INLINE void m68ki_set_s_flag(uint value)
philpem@0 1327 {
philpem@0 1328 /* Backup the old stack pointer */
philpem@0 1329 REG_SP_BASE[FLAG_S | ((FLAG_S>>1) & FLAG_M)] = REG_SP;
philpem@0 1330 /* Set the S flag */
philpem@0 1331 FLAG_S = value;
philpem@0 1332 /* Set the new stack pointer */
philpem@0 1333 REG_SP = REG_SP_BASE[FLAG_S | ((FLAG_S>>1) & FLAG_M)];
philpem@0 1334 }
philpem@0 1335
philpem@0 1336 /* Set the S and M flags and change the active stack pointer.
philpem@0 1337 * Note that value MUST be 0, 2, 4, or 6 (bit2 = S, bit1 = M).
philpem@0 1338 */
philpem@0 1339 INLINE void m68ki_set_sm_flag(uint value)
philpem@0 1340 {
philpem@0 1341 /* Backup the old stack pointer */
philpem@0 1342 REG_SP_BASE[FLAG_S | ((FLAG_S>>1) & FLAG_M)] = REG_SP;
philpem@0 1343 /* Set the S and M flags */
philpem@0 1344 FLAG_S = value & SFLAG_SET;
philpem@0 1345 FLAG_M = value & MFLAG_SET;
philpem@0 1346 /* Set the new stack pointer */
philpem@0 1347 REG_SP = REG_SP_BASE[FLAG_S | ((FLAG_S>>1) & FLAG_M)];
philpem@0 1348 }
philpem@0 1349
philpem@0 1350
philpem@0 1351 /* Set the condition code register */
philpem@0 1352 INLINE void m68ki_set_ccr(uint value)
philpem@0 1353 {
philpem@0 1354 FLAG_X = BIT_4(value) << 4;
philpem@0 1355 FLAG_N = BIT_3(value) << 4;
philpem@0 1356 FLAG_Z = !BIT_2(value);
philpem@0 1357 FLAG_V = BIT_1(value) << 6;
philpem@0 1358 FLAG_C = BIT_0(value) << 8;
philpem@0 1359 }
philpem@0 1360
philpem@0 1361 /* Set the status register but don't check for interrupts */
philpem@0 1362 INLINE void m68ki_set_sr_noint(uint value)
philpem@0 1363 {
philpem@0 1364 /* Mask out the "unimplemented" bits */
philpem@0 1365 value &= CPU_SR_MASK;
philpem@0 1366
philpem@0 1367 /* Now set the status register */
philpem@0 1368 FLAG_T1 = BIT_F(value);
philpem@0 1369 FLAG_T0 = BIT_E(value);
philpem@0 1370 FLAG_INT_MASK = value & 0x0700;
philpem@0 1371 m68ki_set_ccr(value);
philpem@0 1372 m68ki_set_sm_flag((value >> 11) & 6);
philpem@0 1373 }
philpem@0 1374
philpem@0 1375 /* Set the status register and check for interrupts */
philpem@0 1376 INLINE void m68ki_set_sr(uint value)
philpem@0 1377 {
philpem@0 1378 m68ki_set_sr_noint(value);
philpem@0 1379 m68ki_check_interrupts();
philpem@0 1380 }
philpem@0 1381
philpem@0 1382
philpem@0 1383 /* ------------------------- Exception Processing ------------------------- */
philpem@0 1384
philpem@0 1385 /* Initiate exception processing */
philpem@0 1386 INLINE uint m68ki_init_exception(void)
philpem@0 1387 {
philpem@0 1388 /* Save the old status register */
philpem@0 1389 uint sr = m68ki_get_sr();
philpem@0 1390
philpem@0 1391 /* Turn off trace flag, clear pending traces */
philpem@0 1392 FLAG_T1 = FLAG_T0 = 0;
philpem@0 1393 m68ki_clear_trace();
philpem@0 1394 /* Enter supervisor mode */
philpem@0 1395 m68ki_set_s_flag(SFLAG_SET);
philpem@0 1396
philpem@0 1397 return sr;
philpem@0 1398 }
philpem@0 1399
philpem@0 1400 /* 3 word stack frame (68000 only) */
philpem@0 1401 INLINE void m68ki_stack_frame_3word(uint pc, uint sr)
philpem@0 1402 {
philpem@0 1403 m68ki_push_32(pc);
philpem@0 1404 m68ki_push_16(sr);
philpem@0 1405 }
philpem@0 1406
philpem@0 1407 /* Format 0 stack frame.
philpem@0 1408 * This is the standard stack frame for 68010+.
philpem@0 1409 */
philpem@0 1410 INLINE void m68ki_stack_frame_0000(uint pc, uint sr, uint vector)
philpem@0 1411 {
philpem@0 1412 /* Stack a 3-word frame if we are 68000 */
philpem@0 1413 if(CPU_TYPE == CPU_TYPE_000)
philpem@0 1414 {
philpem@0 1415 m68ki_stack_frame_3word(pc, sr);
philpem@0 1416 return;
philpem@0 1417 }
philpem@0 1418 m68ki_push_16(vector<<2);
philpem@0 1419 m68ki_push_32(pc);
philpem@0 1420 m68ki_push_16(sr);
philpem@0 1421 }
philpem@0 1422
philpem@0 1423 /* Format 1 stack frame (68020).
philpem@0 1424 * For 68020, this is the 4 word throwaway frame.
philpem@0 1425 */
philpem@0 1426 INLINE void m68ki_stack_frame_0001(uint pc, uint sr, uint vector)
philpem@0 1427 {
philpem@0 1428 m68ki_push_16(0x1000 | (vector<<2));
philpem@0 1429 m68ki_push_32(pc);
philpem@0 1430 m68ki_push_16(sr);
philpem@0 1431 }
philpem@0 1432
philpem@0 1433 /* Format 2 stack frame.
philpem@0 1434 * This is used only by 68020 for trap exceptions.
philpem@0 1435 */
philpem@0 1436 INLINE void m68ki_stack_frame_0010(uint sr, uint vector)
philpem@0 1437 {
philpem@0 1438 m68ki_push_32(REG_PPC);
philpem@0 1439 m68ki_push_16(0x2000 | (vector<<2));
philpem@0 1440 m68ki_push_32(REG_PC);
philpem@0 1441 m68ki_push_16(sr);
philpem@0 1442 }
philpem@0 1443
philpem@0 1444
philpem@0 1445 /* Bus error stack frame (68000 only).
philpem@0 1446 */
philpem@0 1447 INLINE void m68ki_stack_frame_buserr(uint pc, uint sr, uint address, uint write, uint instruction, uint fc)
philpem@0 1448 {
philpem@0 1449 m68ki_push_32(pc);
philpem@0 1450 m68ki_push_16(sr);
philpem@0 1451 m68ki_push_16(REG_IR);
philpem@0 1452 m68ki_push_32(address); /* access address */
philpem@0 1453 /* 0 0 0 0 0 0 0 0 0 0 0 R/W I/N FC
philpem@0 1454 * R/W 0 = write, 1 = read
philpem@0 1455 * I/N 0 = instruction, 1 = not
philpem@0 1456 * FC 3-bit function code
philpem@0 1457 */
philpem@0 1458 m68ki_push_16(((!write)<<4) | ((!instruction)<<3) | fc);
philpem@0 1459 }
philpem@0 1460
philpem@0 1461 /* Format 8 stack frame (68010).
philpem@0 1462 * 68010 only. This is the 29 word bus/address error frame.
philpem@0 1463 */
philpem@0 1464 void m68ki_stack_frame_1000(uint pc, uint sr, uint vector)
philpem@0 1465 {
philpem@0 1466 /* VERSION
philpem@0 1467 * NUMBER
philpem@0 1468 * INTERNAL INFORMATION, 16 WORDS
philpem@0 1469 */
philpem@0 1470 m68ki_fake_push_32();
philpem@0 1471 m68ki_fake_push_32();
philpem@0 1472 m68ki_fake_push_32();
philpem@0 1473 m68ki_fake_push_32();
philpem@0 1474 m68ki_fake_push_32();
philpem@0 1475 m68ki_fake_push_32();
philpem@0 1476 m68ki_fake_push_32();
philpem@0 1477 m68ki_fake_push_32();
philpem@0 1478
philpem@0 1479 /* INSTRUCTION INPUT BUFFER */
philpem@0 1480 m68ki_push_16(0);
philpem@0 1481
philpem@0 1482 /* UNUSED, RESERVED (not written) */
philpem@0 1483 m68ki_fake_push_16();
philpem@0 1484
philpem@0 1485 /* DATA INPUT BUFFER */
philpem@0 1486 m68ki_push_16(0);
philpem@0 1487
philpem@0 1488 /* UNUSED, RESERVED (not written) */
philpem@0 1489 m68ki_fake_push_16();
philpem@0 1490
philpem@0 1491 /* DATA OUTPUT BUFFER */
philpem@0 1492 m68ki_push_16(0);
philpem@0 1493
philpem@0 1494 /* UNUSED, RESERVED (not written) */
philpem@0 1495 m68ki_fake_push_16();
philpem@0 1496
philpem@0 1497 /* FAULT ADDRESS */
philpem@0 1498 m68ki_push_32(0);
philpem@0 1499
philpem@0 1500 /* SPECIAL STATUS WORD */
philpem@0 1501 m68ki_push_16(0);
philpem@0 1502
philpem@0 1503 /* 1000, VECTOR OFFSET */
philpem@0 1504 m68ki_push_16(0x8000 | (vector<<2));
philpem@0 1505
philpem@0 1506 /* PROGRAM COUNTER */
philpem@0 1507 m68ki_push_32(pc);
philpem@0 1508
philpem@0 1509 /* STATUS REGISTER */
philpem@0 1510 m68ki_push_16(sr);
philpem@0 1511 }
philpem@0 1512
philpem@0 1513 /* Format A stack frame (short bus fault).
philpem@0 1514 * This is used only by 68020 for bus fault and address error
philpem@0 1515 * if the error happens at an instruction boundary.
philpem@0 1516 * PC stacked is address of next instruction.
philpem@0 1517 */
philpem@0 1518 void m68ki_stack_frame_1010(uint sr, uint vector, uint pc)
philpem@0 1519 {
philpem@0 1520 /* INTERNAL REGISTER */
philpem@0 1521 m68ki_push_16(0);
philpem@0 1522
philpem@0 1523 /* INTERNAL REGISTER */
philpem@0 1524 m68ki_push_16(0);
philpem@0 1525
philpem@0 1526 /* DATA OUTPUT BUFFER (2 words) */
philpem@0 1527 m68ki_push_32(0);
philpem@0 1528
philpem@0 1529 /* INTERNAL REGISTER */
philpem@0 1530 m68ki_push_16(0);
philpem@0 1531
philpem@0 1532 /* INTERNAL REGISTER */
philpem@0 1533 m68ki_push_16(0);
philpem@0 1534
philpem@0 1535 /* DATA CYCLE FAULT ADDRESS (2 words) */
philpem@0 1536 m68ki_push_32(0);
philpem@0 1537
philpem@0 1538 /* INSTRUCTION PIPE STAGE B */
philpem@0 1539 m68ki_push_16(0);
philpem@0 1540
philpem@0 1541 /* INSTRUCTION PIPE STAGE C */
philpem@0 1542 m68ki_push_16(0);
philpem@0 1543
philpem@0 1544 /* SPECIAL STATUS REGISTER */
philpem@0 1545 m68ki_push_16(0);
philpem@0 1546
philpem@0 1547 /* INTERNAL REGISTER */
philpem@0 1548 m68ki_push_16(0);
philpem@0 1549
philpem@0 1550 /* 1010, VECTOR OFFSET */
philpem@0 1551 m68ki_push_16(0xa000 | (vector<<2));
philpem@0 1552
philpem@0 1553 /* PROGRAM COUNTER */
philpem@0 1554 m68ki_push_32(pc);
philpem@0 1555
philpem@0 1556 /* STATUS REGISTER */
philpem@0 1557 m68ki_push_16(sr);
philpem@0 1558 }
philpem@0 1559
philpem@0 1560 /* Format B stack frame (long bus fault).
philpem@0 1561 * This is used only by 68020 for bus fault and address error
philpem@0 1562 * if the error happens during instruction execution.
philpem@0 1563 * PC stacked is address of instruction in progress.
philpem@0 1564 */
philpem@0 1565 void m68ki_stack_frame_1011(uint sr, uint vector, uint pc)
philpem@0 1566 {
philpem@0 1567 /* INTERNAL REGISTERS (18 words) */
philpem@0 1568 m68ki_push_32(0);
philpem@0 1569 m68ki_push_32(0);
philpem@0 1570 m68ki_push_32(0);
philpem@0 1571 m68ki_push_32(0);
philpem@0 1572 m68ki_push_32(0);
philpem@0 1573 m68ki_push_32(0);
philpem@0 1574 m68ki_push_32(0);
philpem@0 1575 m68ki_push_32(0);
philpem@0 1576 m68ki_push_32(0);
philpem@0 1577
philpem@0 1578 /* VERSION# (4 bits), INTERNAL INFORMATION */
philpem@0 1579 m68ki_push_16(0);
philpem@0 1580
philpem@0 1581 /* INTERNAL REGISTERS (3 words) */
philpem@0 1582 m68ki_push_32(0);
philpem@0 1583 m68ki_push_16(0);
philpem@0 1584
philpem@0 1585 /* DATA INTPUT BUFFER (2 words) */
philpem@0 1586 m68ki_push_32(0);
philpem@0 1587
philpem@0 1588 /* INTERNAL REGISTERS (2 words) */
philpem@0 1589 m68ki_push_32(0);
philpem@0 1590
philpem@0 1591 /* STAGE B ADDRESS (2 words) */
philpem@0 1592 m68ki_push_32(0);
philpem@0 1593
philpem@0 1594 /* INTERNAL REGISTER (4 words) */
philpem@0 1595 m68ki_push_32(0);
philpem@0 1596 m68ki_push_32(0);
philpem@0 1597
philpem@0 1598 /* DATA OUTPUT BUFFER (2 words) */
philpem@0 1599 m68ki_push_32(0);
philpem@0 1600
philpem@0 1601 /* INTERNAL REGISTER */
philpem@0 1602 m68ki_push_16(0);
philpem@0 1603
philpem@0 1604 /* INTERNAL REGISTER */
philpem@0 1605 m68ki_push_16(0);
philpem@0 1606
philpem@0 1607 /* DATA CYCLE FAULT ADDRESS (2 words) */
philpem@0 1608 m68ki_push_32(0);
philpem@0 1609
philpem@0 1610 /* INSTRUCTION PIPE STAGE B */
philpem@0 1611 m68ki_push_16(0);
philpem@0 1612
philpem@0 1613 /* INSTRUCTION PIPE STAGE C */
philpem@0 1614 m68ki_push_16(0);
philpem@0 1615
philpem@0 1616 /* SPECIAL STATUS REGISTER */
philpem@0 1617 m68ki_push_16(0);
philpem@0 1618
philpem@0 1619 /* INTERNAL REGISTER */
philpem@0 1620 m68ki_push_16(0);
philpem@0 1621
philpem@0 1622 /* 1011, VECTOR OFFSET */
philpem@0 1623 m68ki_push_16(0xb000 | (vector<<2));
philpem@0 1624
philpem@0 1625 /* PROGRAM COUNTER */
philpem@0 1626 m68ki_push_32(pc);
philpem@0 1627
philpem@0 1628 /* STATUS REGISTER */
philpem@0 1629 m68ki_push_16(sr);
philpem@0 1630 }
philpem@0 1631
philpem@0 1632
philpem@0 1633 /* Used for Group 2 exceptions.
philpem@0 1634 * These stack a type 2 frame on the 020.
philpem@0 1635 */
philpem@0 1636 INLINE void m68ki_exception_trap(uint vector)
philpem@0 1637 {
philpem@0 1638 uint sr = m68ki_init_exception();
philpem@0 1639
philpem@0 1640 if(CPU_TYPE_IS_010_LESS(CPU_TYPE))
philpem@0 1641 m68ki_stack_frame_0000(REG_PC, sr, vector);
philpem@0 1642 else
philpem@0 1643 m68ki_stack_frame_0010(sr, vector);
philpem@0 1644
philpem@0 1645 m68ki_jump_vector(vector);
philpem@0 1646
philpem@0 1647 /* Use up some clock cycles */
philpem@0 1648 USE_CYCLES(CYC_EXCEPTION[vector]);
philpem@0 1649 }
philpem@0 1650
philpem@0 1651 /* Trap#n stacks a 0 frame but behaves like group2 otherwise */
philpem@0 1652 INLINE void m68ki_exception_trapN(uint vector)
philpem@0 1653 {
philpem@0 1654 uint sr = m68ki_init_exception();
philpem@0 1655 m68ki_stack_frame_0000(REG_PC, sr, vector);
philpem@0 1656 m68ki_jump_vector(vector);
philpem@0 1657
philpem@0 1658 /* Use up some clock cycles */
philpem@0 1659 USE_CYCLES(CYC_EXCEPTION[vector]);
philpem@0 1660 }
philpem@0 1661
philpem@0 1662 /* Exception for trace mode */
philpem@0 1663 INLINE void m68ki_exception_trace(void)
philpem@0 1664 {
philpem@0 1665 uint sr = m68ki_init_exception();
philpem@0 1666
philpem@0 1667 if(CPU_TYPE_IS_010_LESS(CPU_TYPE))
philpem@0 1668 m68ki_stack_frame_0000(REG_PC, sr, EXCEPTION_TRACE);
philpem@0 1669 else
philpem@0 1670 m68ki_stack_frame_0010(sr, EXCEPTION_TRACE);
philpem@0 1671
philpem@0 1672 m68ki_jump_vector(EXCEPTION_TRACE);
philpem@0 1673
philpem@0 1674 /* Trace nullifies a STOP instruction */
philpem@0 1675 CPU_STOPPED &= ~STOP_LEVEL_STOP;
philpem@0 1676
philpem@0 1677 /* Use up some clock cycles */
philpem@0 1678 USE_CYCLES(CYC_EXCEPTION[EXCEPTION_TRACE]);
philpem@0 1679 }
philpem@0 1680
philpem@0 1681 /* Exception for privilege violation */
philpem@0 1682 INLINE void m68ki_exception_privilege_violation(void)
philpem@0 1683 {
philpem@0 1684 uint sr = m68ki_init_exception();
philpem@0 1685 m68ki_stack_frame_0000(REG_PC, sr, EXCEPTION_PRIVILEGE_VIOLATION);
philpem@0 1686 m68ki_jump_vector(EXCEPTION_PRIVILEGE_VIOLATION);
philpem@0 1687
philpem@0 1688 /* Use up some clock cycles and undo the instruction's cycles */
philpem@0 1689 USE_CYCLES(CYC_EXCEPTION[EXCEPTION_PRIVILEGE_VIOLATION] - CYC_INSTRUCTION[REG_IR]);
philpem@0 1690 }
philpem@0 1691
philpem@19 1692 /* Exception for bus error */
philpem@19 1693 INLINE void m68ki_exception_bus_error(void)
philpem@19 1694 {
philpem@109 1695 BUS_ERROR_OCCURRED = 1;
philpem@19 1696 /* Use up some clock cycles and undo the instruction's cycles */
philpem@19 1697 USE_CYCLES(CYC_EXCEPTION[EXCEPTION_BUS_ERROR] - CYC_INSTRUCTION[REG_IR]);
philpem@19 1698 }
philpem@19 1699
philpem@109 1700 INLINE void m68ki_jump_bus_error_vector(void)
philpem@109 1701 {
philpem@109 1702 uint sr = m68ki_init_exception();
philpem@110 1703 m68ki_stack_frame_1000(REG_PPC, sr, EXCEPTION_BUS_ERROR);
philpem@109 1704 m68ki_jump_vector(EXCEPTION_BUS_ERROR);
philpem@109 1705 }
philpem@19 1706
philpem@0 1707 /* Exception for A-Line instructions */
philpem@0 1708 INLINE void m68ki_exception_1010(void)
philpem@0 1709 {
philpem@0 1710 uint sr;
philpem@0 1711 #if M68K_LOG_1010_1111 == OPT_ON
philpem@0 1712 M68K_DO_LOG_EMU((M68K_LOG_FILEHANDLE "%s at %08x: called 1010 instruction %04x (%s)\n",
philpem@0 1713 m68ki_cpu_names[CPU_TYPE], ADDRESS_68K(REG_PPC), REG_IR,
philpem@0 1714 m68ki_disassemble_quick(ADDRESS_68K(REG_PPC))));
philpem@0 1715 #endif
philpem@0 1716
philpem@0 1717 sr = m68ki_init_exception();
philpem@0 1718 m68ki_stack_frame_0000(REG_PC-2, sr, EXCEPTION_1010);
philpem@0 1719 m68ki_jump_vector(EXCEPTION_1010);
philpem@0 1720
philpem@0 1721 /* Use up some clock cycles and undo the instruction's cycles */
philpem@0 1722 USE_CYCLES(CYC_EXCEPTION[EXCEPTION_1010] - CYC_INSTRUCTION[REG_IR]);
philpem@0 1723 }
philpem@0 1724
philpem@0 1725 /* Exception for F-Line instructions */
philpem@0 1726 INLINE void m68ki_exception_1111(void)
philpem@0 1727 {
philpem@0 1728 uint sr;
philpem@0 1729
philpem@0 1730 #if M68K_LOG_1010_1111 == OPT_ON
philpem@0 1731 M68K_DO_LOG_EMU((M68K_LOG_FILEHANDLE "%s at %08x: called 1111 instruction %04x (%s)\n",
philpem@0 1732 m68ki_cpu_names[CPU_TYPE], ADDRESS_68K(REG_PPC), REG_IR,
philpem@0 1733 m68ki_disassemble_quick(ADDRESS_68K(REG_PPC))));
philpem@0 1734 #endif
philpem@0 1735
philpem@0 1736 sr = m68ki_init_exception();
philpem@0 1737 m68ki_stack_frame_0000(REG_PC-2, sr, EXCEPTION_1111);
philpem@0 1738 m68ki_jump_vector(EXCEPTION_1111);
philpem@0 1739
philpem@0 1740 /* Use up some clock cycles and undo the instruction's cycles */
philpem@0 1741 USE_CYCLES(CYC_EXCEPTION[EXCEPTION_1111] - CYC_INSTRUCTION[REG_IR]);
philpem@0 1742 }
philpem@0 1743
philpem@0 1744 /* Exception for illegal instructions */
philpem@0 1745 INLINE void m68ki_exception_illegal(void)
philpem@0 1746 {
philpem@0 1747 uint sr;
philpem@0 1748
philpem@0 1749 M68K_DO_LOG((M68K_LOG_FILEHANDLE "%s at %08x: illegal instruction %04x (%s)\n",
philpem@0 1750 m68ki_cpu_names[CPU_TYPE], ADDRESS_68K(REG_PPC), REG_IR,
philpem@0 1751 m68ki_disassemble_quick(ADDRESS_68K(REG_PPC))));
philpem@0 1752
philpem@0 1753 sr = m68ki_init_exception();
philpem@0 1754 m68ki_stack_frame_0000(REG_PC, sr, EXCEPTION_ILLEGAL_INSTRUCTION);
philpem@0 1755 m68ki_jump_vector(EXCEPTION_ILLEGAL_INSTRUCTION);
philpem@0 1756
philpem@0 1757 /* Use up some clock cycles and undo the instruction's cycles */
philpem@0 1758 USE_CYCLES(CYC_EXCEPTION[EXCEPTION_ILLEGAL_INSTRUCTION] - CYC_INSTRUCTION[REG_IR]);
philpem@0 1759 }
philpem@0 1760
philpem@0 1761 /* Exception for format errror in RTE */
philpem@0 1762 INLINE void m68ki_exception_format_error(void)
philpem@0 1763 {
philpem@0 1764 uint sr = m68ki_init_exception();
philpem@0 1765 m68ki_stack_frame_0000(REG_PC, sr, EXCEPTION_FORMAT_ERROR);
philpem@0 1766 m68ki_jump_vector(EXCEPTION_FORMAT_ERROR);
philpem@0 1767
philpem@0 1768 /* Use up some clock cycles and undo the instruction's cycles */
philpem@0 1769 USE_CYCLES(CYC_EXCEPTION[EXCEPTION_FORMAT_ERROR] - CYC_INSTRUCTION[REG_IR]);
philpem@0 1770 }
philpem@0 1771
philpem@0 1772 /* Exception for address error */
philpem@0 1773 INLINE void m68ki_exception_address_error(void)
philpem@0 1774 {
philpem@0 1775 /* Not emulated yet */
philpem@0 1776 }
philpem@0 1777
philpem@0 1778
philpem@0 1779 /* Service an interrupt request and start exception processing */
philpem@0 1780 void m68ki_exception_interrupt(uint int_level)
philpem@0 1781 {
philpem@0 1782 uint vector;
philpem@0 1783 uint sr;
philpem@0 1784 uint new_pc;
philpem@0 1785
philpem@0 1786 /* Turn off the stopped state */
philpem@0 1787 CPU_STOPPED &= ~STOP_LEVEL_STOP;
philpem@0 1788
philpem@0 1789 /* If we are halted, don't do anything */
philpem@0 1790 if(CPU_STOPPED)
philpem@0 1791 return;
philpem@0 1792
philpem@0 1793 /* Acknowledge the interrupt */
philpem@0 1794 vector = m68ki_int_ack(int_level);
philpem@0 1795
philpem@0 1796 /* Get the interrupt vector */
philpem@0 1797 if(vector == M68K_INT_ACK_AUTOVECTOR)
philpem@0 1798 /* Use the autovectors. This is the most commonly used implementation */
philpem@0 1799 vector = EXCEPTION_INTERRUPT_AUTOVECTOR+int_level;
philpem@0 1800 else if(vector == M68K_INT_ACK_SPURIOUS)
philpem@0 1801 /* Called if no devices respond to the interrupt acknowledge */
philpem@0 1802 vector = EXCEPTION_SPURIOUS_INTERRUPT;
philpem@0 1803 else if(vector > 255)
philpem@0 1804 {
philpem@0 1805 M68K_DO_LOG_EMU((M68K_LOG_FILEHANDLE "%s at %08x: Interrupt acknowledge returned invalid vector $%x\n",
philpem@0 1806 m68ki_cpu_names[CPU_TYPE], ADDRESS_68K(REG_PC), vector));
philpem@0 1807 return;
philpem@0 1808 }
philpem@0 1809
philpem@0 1810 /* Start exception processing */
philpem@0 1811 sr = m68ki_init_exception();
philpem@0 1812
philpem@0 1813 /* Set the interrupt mask to the level of the one being serviced */
philpem@0 1814 FLAG_INT_MASK = int_level<<8;
philpem@0 1815
philpem@0 1816 /* Get the new PC */
philpem@0 1817 new_pc = m68ki_read_data_32((vector<<2) + REG_VBR);
philpem@0 1818
philpem@0 1819 /* If vector is uninitialized, call the uninitialized interrupt vector */
philpem@0 1820 if(new_pc == 0)
philpem@0 1821 new_pc = m68ki_read_data_32((EXCEPTION_UNINITIALIZED_INTERRUPT<<2) + REG_VBR);
philpem@0 1822
philpem@0 1823 /* Generate a stack frame */
philpem@0 1824 m68ki_stack_frame_0000(REG_PC, sr, vector);
philpem@0 1825 if(FLAG_M && CPU_TYPE_IS_EC020_PLUS(CPU_TYPE))
philpem@0 1826 {
philpem@0 1827 /* Create throwaway frame */
philpem@0 1828 m68ki_set_sm_flag(FLAG_S); /* clear M */
philpem@0 1829 sr |= 0x2000; /* Same as SR in master stack frame except S is forced high */
philpem@0 1830 m68ki_stack_frame_0001(REG_PC, sr, vector);
philpem@0 1831 }
philpem@0 1832
philpem@0 1833 m68ki_jump(new_pc);
philpem@0 1834
philpem@0 1835 /* Defer cycle counting until later */
philpem@0 1836 CPU_INT_CYCLES += CYC_EXCEPTION[vector];
philpem@0 1837
philpem@0 1838 #if !M68K_EMULATE_INT_ACK
philpem@0 1839 /* Automatically clear IRQ if we are not using an acknowledge scheme */
philpem@0 1840 CPU_INT_LEVEL = 0;
philpem@0 1841 #endif /* M68K_EMULATE_INT_ACK */
philpem@0 1842 }
philpem@0 1843
philpem@0 1844
philpem@0 1845 /* ASG: Check for interrupts */
philpem@0 1846 INLINE void m68ki_check_interrupts(void)
philpem@0 1847 {
philpem@0 1848 if(CPU_INT_LEVEL > FLAG_INT_MASK)
philpem@0 1849 m68ki_exception_interrupt(CPU_INT_LEVEL>>8);
philpem@0 1850 }
philpem@0 1851
philpem@0 1852
philpem@0 1853
philpem@0 1854 /* ======================================================================== */
philpem@0 1855 /* ============================== END OF FILE ============================= */
philpem@0 1856 /* ======================================================================== */
philpem@0 1857
philpem@0 1858 #endif /* M68KCPU__HEADER */