src/musashi/m68kcpu.c

Fri, 12 Apr 2013 16:26:25 +0100

author
Philip Pemberton <philpem@philpem.me.uk>
date
Fri, 12 Apr 2013 16:26:25 +0100
branch
experimental_memory_mapper_v2
changeset 144
609707511166
parent 118
feee84e0b3bf
child 147
ad888290cdff
permissions
-rw-r--r--

Don't set PS1 if there is a level-7 interrupt or bus error

PS1 should only be set if the page was originally present (PS1 or PS0 set). If
PS0 and PS1 are clear (page not present) then do NOT set PS1.

Once again the TRM is blatantly and spectacularly wrong...

philpem@0 1 /* ======================================================================== */
philpem@0 2 /* ========================= LICENSING & COPYRIGHT ======================== */
philpem@0 3 /* ======================================================================== */
philpem@0 4
philpem@0 5 #if 0
philpem@0 6 static const char* copyright_notice =
philpem@0 7 "MUSASHI\n"
philpem@0 8 "Version 3.3 (2001-01-29)\n"
philpem@0 9 "A portable Motorola M680x0 processor emulation engine.\n"
philpem@0 10 "Copyright 1998-2001 Karl Stenerud. All rights reserved.\n"
philpem@0 11 "\n"
philpem@0 12 "This code may be freely used for non-commercial purpooses as long as this\n"
philpem@0 13 "copyright notice remains unaltered in the source code and any binary files\n"
philpem@0 14 "containing this code in compiled form.\n"
philpem@0 15 "\n"
philpem@0 16 "All other lisencing terms must be negotiated with the author\n"
philpem@0 17 "(Karl Stenerud).\n"
philpem@0 18 "\n"
philpem@0 19 "The latest version of this code can be obtained at:\n"
philpem@0 20 "http://kstenerud.cjb.net\n"
philpem@0 21 ;
philpem@0 22 #endif
philpem@0 23
philpem@0 24
philpem@0 25 /* ======================================================================== */
philpem@0 26 /* ================================= NOTES ================================ */
philpem@0 27 /* ======================================================================== */
philpem@0 28
philpem@0 29
philpem@0 30
philpem@0 31 /* ======================================================================== */
philpem@0 32 /* ================================ INCLUDES ============================== */
philpem@0 33 /* ======================================================================== */
philpem@0 34
philpem@0 35 #include "m68kops.h"
philpem@0 36 #include "m68kcpu.h"
philpem@0 37
philpem@0 38 /* ======================================================================== */
philpem@0 39 /* ================================= DATA ================================= */
philpem@0 40 /* ======================================================================== */
philpem@0 41
philpem@0 42 int m68ki_initial_cycles;
philpem@0 43 int m68ki_remaining_cycles = 0; /* Number of clocks remaining */
philpem@0 44 uint m68ki_tracing = 0;
philpem@0 45 uint m68ki_address_space;
philpem@0 46
philpem@0 47 #ifdef M68K_LOG_ENABLE
philpem@0 48 char* m68ki_cpu_names[9] =
philpem@0 49 {
philpem@0 50 "Invalid CPU",
philpem@0 51 "M68000",
philpem@0 52 "M68010",
philpem@0 53 "Invalid CPU",
philpem@0 54 "M68EC020"
philpem@0 55 "Invalid CPU",
philpem@0 56 "Invalid CPU",
philpem@0 57 "Invalid CPU",
philpem@0 58 "M68020"
philpem@0 59 };
philpem@0 60 #endif /* M68K_LOG_ENABLE */
philpem@0 61
philpem@0 62 /* The CPU core */
philpem@0 63 m68ki_cpu_core m68ki_cpu = {0};
philpem@0 64
philpem@0 65 #if M68K_EMULATE_ADDRESS_ERROR
philpem@0 66 jmp_buf m68ki_address_error_trap;
philpem@0 67 #endif /* M68K_EMULATE_ADDRESS_ERROR */
philpem@0 68
philpem@0 69 /* Used by shift & rotate instructions */
philpem@0 70 uint8 m68ki_shift_8_table[65] =
philpem@0 71 {
philpem@0 72 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff, 0xff, 0xff, 0xff,
philpem@0 73 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
philpem@0 74 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
philpem@0 75 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
philpem@0 76 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
philpem@0 77 0xff, 0xff, 0xff, 0xff, 0xff
philpem@0 78 };
philpem@0 79 uint16 m68ki_shift_16_table[65] =
philpem@0 80 {
philpem@0 81 0x0000, 0x8000, 0xc000, 0xe000, 0xf000, 0xf800, 0xfc00, 0xfe00, 0xff00,
philpem@0 82 0xff80, 0xffc0, 0xffe0, 0xfff0, 0xfff8, 0xfffc, 0xfffe, 0xffff, 0xffff,
philpem@0 83 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
philpem@0 84 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
philpem@0 85 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
philpem@0 86 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
philpem@0 87 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
philpem@0 88 0xffff, 0xffff
philpem@0 89 };
philpem@0 90 uint m68ki_shift_32_table[65] =
philpem@0 91 {
philpem@0 92 0x00000000, 0x80000000, 0xc0000000, 0xe0000000, 0xf0000000, 0xf8000000,
philpem@0 93 0xfc000000, 0xfe000000, 0xff000000, 0xff800000, 0xffc00000, 0xffe00000,
philpem@0 94 0xfff00000, 0xfff80000, 0xfffc0000, 0xfffe0000, 0xffff0000, 0xffff8000,
philpem@0 95 0xffffc000, 0xffffe000, 0xfffff000, 0xfffff800, 0xfffffc00, 0xfffffe00,
philpem@0 96 0xffffff00, 0xffffff80, 0xffffffc0, 0xffffffe0, 0xfffffff0, 0xfffffff8,
philpem@0 97 0xfffffffc, 0xfffffffe, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
philpem@0 98 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
philpem@0 99 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
philpem@0 100 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
philpem@0 101 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
philpem@0 102 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff
philpem@0 103 };
philpem@0 104
philpem@0 105
philpem@0 106 /* Number of clock cycles to use for exception processing.
philpem@0 107 * I used 4 for any vectors that are undocumented for processing times.
philpem@0 108 */
philpem@0 109 uint8 m68ki_exception_cycle_table[3][256] =
philpem@0 110 {
philpem@0 111 { /* 000 */
philpem@0 112 4, /* 0: Reset - Initial Stack Pointer */
philpem@0 113 4, /* 1: Reset - Initial Program Counter */
philpem@0 114 50, /* 2: Bus Error (unemulated) */
philpem@0 115 50, /* 3: Address Error (unemulated) */
philpem@0 116 34, /* 4: Illegal Instruction */
philpem@0 117 38, /* 5: Divide by Zero -- ASG: changed from 42 */
philpem@0 118 40, /* 6: CHK -- ASG: chanaged from 44 */
philpem@0 119 34, /* 7: TRAPV */
philpem@0 120 34, /* 8: Privilege Violation */
philpem@0 121 34, /* 9: Trace */
philpem@0 122 4, /* 10: 1010 */
philpem@0 123 4, /* 11: 1111 */
philpem@0 124 4, /* 12: RESERVED */
philpem@0 125 4, /* 13: Coprocessor Protocol Violation (unemulated) */
philpem@0 126 4, /* 14: Format Error */
philpem@0 127 44, /* 15: Uninitialized Interrupt */
philpem@0 128 4, /* 16: RESERVED */
philpem@0 129 4, /* 17: RESERVED */
philpem@0 130 4, /* 18: RESERVED */
philpem@0 131 4, /* 19: RESERVED */
philpem@0 132 4, /* 20: RESERVED */
philpem@0 133 4, /* 21: RESERVED */
philpem@0 134 4, /* 22: RESERVED */
philpem@0 135 4, /* 23: RESERVED */
philpem@0 136 44, /* 24: Spurious Interrupt */
philpem@0 137 44, /* 25: Level 1 Interrupt Autovector */
philpem@0 138 44, /* 26: Level 2 Interrupt Autovector */
philpem@0 139 44, /* 27: Level 3 Interrupt Autovector */
philpem@0 140 44, /* 28: Level 4 Interrupt Autovector */
philpem@0 141 44, /* 29: Level 5 Interrupt Autovector */
philpem@0 142 44, /* 30: Level 6 Interrupt Autovector */
philpem@0 143 44, /* 31: Level 7 Interrupt Autovector */
philpem@0 144 34, /* 32: TRAP #0 -- ASG: chanaged from 38 */
philpem@0 145 34, /* 33: TRAP #1 */
philpem@0 146 34, /* 34: TRAP #2 */
philpem@0 147 34, /* 35: TRAP #3 */
philpem@0 148 34, /* 36: TRAP #4 */
philpem@0 149 34, /* 37: TRAP #5 */
philpem@0 150 34, /* 38: TRAP #6 */
philpem@0 151 34, /* 39: TRAP #7 */
philpem@0 152 34, /* 40: TRAP #8 */
philpem@0 153 34, /* 41: TRAP #9 */
philpem@0 154 34, /* 42: TRAP #10 */
philpem@0 155 34, /* 43: TRAP #11 */
philpem@0 156 34, /* 44: TRAP #12 */
philpem@0 157 34, /* 45: TRAP #13 */
philpem@0 158 34, /* 46: TRAP #14 */
philpem@0 159 34, /* 47: TRAP #15 */
philpem@0 160 4, /* 48: FP Branch or Set on Unknown Condition (unemulated) */
philpem@0 161 4, /* 49: FP Inexact Result (unemulated) */
philpem@0 162 4, /* 50: FP Divide by Zero (unemulated) */
philpem@0 163 4, /* 51: FP Underflow (unemulated) */
philpem@0 164 4, /* 52: FP Operand Error (unemulated) */
philpem@0 165 4, /* 53: FP Overflow (unemulated) */
philpem@0 166 4, /* 54: FP Signaling NAN (unemulated) */
philpem@0 167 4, /* 55: FP Unimplemented Data Type (unemulated) */
philpem@0 168 4, /* 56: MMU Configuration Error (unemulated) */
philpem@0 169 4, /* 57: MMU Illegal Operation Error (unemulated) */
philpem@0 170 4, /* 58: MMU Access Level Violation Error (unemulated) */
philpem@0 171 4, /* 59: RESERVED */
philpem@0 172 4, /* 60: RESERVED */
philpem@0 173 4, /* 61: RESERVED */
philpem@0 174 4, /* 62: RESERVED */
philpem@0 175 4, /* 63: RESERVED */
philpem@0 176 /* 64-255: User Defined */
philpem@0 177 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
philpem@0 178 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
philpem@0 179 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
philpem@0 180 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
philpem@0 181 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
philpem@0 182 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4
philpem@0 183 },
philpem@0 184 { /* 010 */
philpem@0 185 4, /* 0: Reset - Initial Stack Pointer */
philpem@0 186 4, /* 1: Reset - Initial Program Counter */
philpem@0 187 126, /* 2: Bus Error (unemulated) */
philpem@0 188 126, /* 3: Address Error (unemulated) */
philpem@0 189 38, /* 4: Illegal Instruction */
philpem@0 190 44, /* 5: Divide by Zero */
philpem@0 191 44, /* 6: CHK */
philpem@0 192 34, /* 7: TRAPV */
philpem@0 193 38, /* 8: Privilege Violation */
philpem@0 194 38, /* 9: Trace */
philpem@0 195 4, /* 10: 1010 */
philpem@0 196 4, /* 11: 1111 */
philpem@0 197 4, /* 12: RESERVED */
philpem@0 198 4, /* 13: Coprocessor Protocol Violation (unemulated) */
philpem@0 199 4, /* 14: Format Error */
philpem@0 200 44, /* 15: Uninitialized Interrupt */
philpem@0 201 4, /* 16: RESERVED */
philpem@0 202 4, /* 17: RESERVED */
philpem@0 203 4, /* 18: RESERVED */
philpem@0 204 4, /* 19: RESERVED */
philpem@0 205 4, /* 20: RESERVED */
philpem@0 206 4, /* 21: RESERVED */
philpem@0 207 4, /* 22: RESERVED */
philpem@0 208 4, /* 23: RESERVED */
philpem@0 209 46, /* 24: Spurious Interrupt */
philpem@0 210 46, /* 25: Level 1 Interrupt Autovector */
philpem@0 211 46, /* 26: Level 2 Interrupt Autovector */
philpem@0 212 46, /* 27: Level 3 Interrupt Autovector */
philpem@0 213 46, /* 28: Level 4 Interrupt Autovector */
philpem@0 214 46, /* 29: Level 5 Interrupt Autovector */
philpem@0 215 46, /* 30: Level 6 Interrupt Autovector */
philpem@0 216 46, /* 31: Level 7 Interrupt Autovector */
philpem@0 217 38, /* 32: TRAP #0 */
philpem@0 218 38, /* 33: TRAP #1 */
philpem@0 219 38, /* 34: TRAP #2 */
philpem@0 220 38, /* 35: TRAP #3 */
philpem@0 221 38, /* 36: TRAP #4 */
philpem@0 222 38, /* 37: TRAP #5 */
philpem@0 223 38, /* 38: TRAP #6 */
philpem@0 224 38, /* 39: TRAP #7 */
philpem@0 225 38, /* 40: TRAP #8 */
philpem@0 226 38, /* 41: TRAP #9 */
philpem@0 227 38, /* 42: TRAP #10 */
philpem@0 228 38, /* 43: TRAP #11 */
philpem@0 229 38, /* 44: TRAP #12 */
philpem@0 230 38, /* 45: TRAP #13 */
philpem@0 231 38, /* 46: TRAP #14 */
philpem@0 232 38, /* 47: TRAP #15 */
philpem@0 233 4, /* 48: FP Branch or Set on Unknown Condition (unemulated) */
philpem@0 234 4, /* 49: FP Inexact Result (unemulated) */
philpem@0 235 4, /* 50: FP Divide by Zero (unemulated) */
philpem@0 236 4, /* 51: FP Underflow (unemulated) */
philpem@0 237 4, /* 52: FP Operand Error (unemulated) */
philpem@0 238 4, /* 53: FP Overflow (unemulated) */
philpem@0 239 4, /* 54: FP Signaling NAN (unemulated) */
philpem@0 240 4, /* 55: FP Unimplemented Data Type (unemulated) */
philpem@0 241 4, /* 56: MMU Configuration Error (unemulated) */
philpem@0 242 4, /* 57: MMU Illegal Operation Error (unemulated) */
philpem@0 243 4, /* 58: MMU Access Level Violation Error (unemulated) */
philpem@0 244 4, /* 59: RESERVED */
philpem@0 245 4, /* 60: RESERVED */
philpem@0 246 4, /* 61: RESERVED */
philpem@0 247 4, /* 62: RESERVED */
philpem@0 248 4, /* 63: RESERVED */
philpem@0 249 /* 64-255: User Defined */
philpem@0 250 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
philpem@0 251 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
philpem@0 252 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
philpem@0 253 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
philpem@0 254 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
philpem@0 255 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4
philpem@0 256 },
philpem@0 257 { /* 020 */
philpem@0 258 4, /* 0: Reset - Initial Stack Pointer */
philpem@0 259 4, /* 1: Reset - Initial Program Counter */
philpem@0 260 50, /* 2: Bus Error (unemulated) */
philpem@0 261 50, /* 3: Address Error (unemulated) */
philpem@0 262 20, /* 4: Illegal Instruction */
philpem@0 263 38, /* 5: Divide by Zero */
philpem@0 264 40, /* 6: CHK */
philpem@0 265 20, /* 7: TRAPV */
philpem@0 266 34, /* 8: Privilege Violation */
philpem@0 267 25, /* 9: Trace */
philpem@0 268 20, /* 10: 1010 */
philpem@0 269 20, /* 11: 1111 */
philpem@0 270 4, /* 12: RESERVED */
philpem@0 271 4, /* 13: Coprocessor Protocol Violation (unemulated) */
philpem@0 272 4, /* 14: Format Error */
philpem@0 273 30, /* 15: Uninitialized Interrupt */
philpem@0 274 4, /* 16: RESERVED */
philpem@0 275 4, /* 17: RESERVED */
philpem@0 276 4, /* 18: RESERVED */
philpem@0 277 4, /* 19: RESERVED */
philpem@0 278 4, /* 20: RESERVED */
philpem@0 279 4, /* 21: RESERVED */
philpem@0 280 4, /* 22: RESERVED */
philpem@0 281 4, /* 23: RESERVED */
philpem@0 282 30, /* 24: Spurious Interrupt */
philpem@0 283 30, /* 25: Level 1 Interrupt Autovector */
philpem@0 284 30, /* 26: Level 2 Interrupt Autovector */
philpem@0 285 30, /* 27: Level 3 Interrupt Autovector */
philpem@0 286 30, /* 28: Level 4 Interrupt Autovector */
philpem@0 287 30, /* 29: Level 5 Interrupt Autovector */
philpem@0 288 30, /* 30: Level 6 Interrupt Autovector */
philpem@0 289 30, /* 31: Level 7 Interrupt Autovector */
philpem@0 290 20, /* 32: TRAP #0 */
philpem@0 291 20, /* 33: TRAP #1 */
philpem@0 292 20, /* 34: TRAP #2 */
philpem@0 293 20, /* 35: TRAP #3 */
philpem@0 294 20, /* 36: TRAP #4 */
philpem@0 295 20, /* 37: TRAP #5 */
philpem@0 296 20, /* 38: TRAP #6 */
philpem@0 297 20, /* 39: TRAP #7 */
philpem@0 298 20, /* 40: TRAP #8 */
philpem@0 299 20, /* 41: TRAP #9 */
philpem@0 300 20, /* 42: TRAP #10 */
philpem@0 301 20, /* 43: TRAP #11 */
philpem@0 302 20, /* 44: TRAP #12 */
philpem@0 303 20, /* 45: TRAP #13 */
philpem@0 304 20, /* 46: TRAP #14 */
philpem@0 305 20, /* 47: TRAP #15 */
philpem@0 306 4, /* 48: FP Branch or Set on Unknown Condition (unemulated) */
philpem@0 307 4, /* 49: FP Inexact Result (unemulated) */
philpem@0 308 4, /* 50: FP Divide by Zero (unemulated) */
philpem@0 309 4, /* 51: FP Underflow (unemulated) */
philpem@0 310 4, /* 52: FP Operand Error (unemulated) */
philpem@0 311 4, /* 53: FP Overflow (unemulated) */
philpem@0 312 4, /* 54: FP Signaling NAN (unemulated) */
philpem@0 313 4, /* 55: FP Unimplemented Data Type (unemulated) */
philpem@0 314 4, /* 56: MMU Configuration Error (unemulated) */
philpem@0 315 4, /* 57: MMU Illegal Operation Error (unemulated) */
philpem@0 316 4, /* 58: MMU Access Level Violation Error (unemulated) */
philpem@0 317 4, /* 59: RESERVED */
philpem@0 318 4, /* 60: RESERVED */
philpem@0 319 4, /* 61: RESERVED */
philpem@0 320 4, /* 62: RESERVED */
philpem@0 321 4, /* 63: RESERVED */
philpem@0 322 /* 64-255: User Defined */
philpem@0 323 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
philpem@0 324 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
philpem@0 325 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
philpem@0 326 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
philpem@0 327 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
philpem@0 328 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4
philpem@0 329 }
philpem@0 330 };
philpem@0 331
philpem@0 332 uint8 m68ki_ea_idx_cycle_table[64] =
philpem@0 333 {
philpem@0 334 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
philpem@0 335 0, /* ..01.000 no memory indirect, base NULL */
philpem@0 336 5, /* ..01..01 memory indirect, base NULL, outer NULL */
philpem@0 337 7, /* ..01..10 memory indirect, base NULL, outer 16 */
philpem@0 338 7, /* ..01..11 memory indirect, base NULL, outer 32 */
philpem@0 339 0, 5, 7, 7, 0, 5, 7, 7, 0, 5, 7, 7,
philpem@0 340 2, /* ..10.000 no memory indirect, base 16 */
philpem@0 341 7, /* ..10..01 memory indirect, base 16, outer NULL */
philpem@0 342 9, /* ..10..10 memory indirect, base 16, outer 16 */
philpem@0 343 9, /* ..10..11 memory indirect, base 16, outer 32 */
philpem@0 344 0, 7, 9, 9, 0, 7, 9, 9, 0, 7, 9, 9,
philpem@0 345 6, /* ..11.000 no memory indirect, base 32 */
philpem@0 346 11, /* ..11..01 memory indirect, base 32, outer NULL */
philpem@0 347 13, /* ..11..10 memory indirect, base 32, outer 16 */
philpem@0 348 13, /* ..11..11 memory indirect, base 32, outer 32 */
philpem@0 349 0, 11, 13, 13, 0, 11, 13, 13, 0, 11, 13, 13
philpem@0 350 };
philpem@0 351
philpem@0 352
philpem@0 353
philpem@0 354 /* ======================================================================== */
philpem@0 355 /* =============================== CALLBACKS ============================== */
philpem@0 356 /* ======================================================================== */
philpem@0 357
philpem@0 358 /* Default callbacks used if the callback hasn't been set yet, or if the
philpem@0 359 * callback is set to NULL
philpem@0 360 */
philpem@0 361
philpem@0 362 /* Interrupt acknowledge */
philpem@0 363 static int default_int_ack_callback_data;
philpem@0 364 static int default_int_ack_callback(int int_level)
philpem@0 365 {
philpem@0 366 default_int_ack_callback_data = int_level;
philpem@0 367 CPU_INT_LEVEL = 0;
philpem@0 368 return M68K_INT_ACK_AUTOVECTOR;
philpem@0 369 }
philpem@0 370
philpem@0 371 /* Breakpoint acknowledge */
philpem@0 372 static unsigned int default_bkpt_ack_callback_data;
philpem@0 373 static void default_bkpt_ack_callback(unsigned int data)
philpem@0 374 {
philpem@0 375 default_bkpt_ack_callback_data = data;
philpem@0 376 }
philpem@0 377
philpem@0 378 /* Called when a reset instruction is executed */
philpem@0 379 static void default_reset_instr_callback(void)
philpem@0 380 {
philpem@0 381 }
philpem@0 382
philpem@0 383 /* Called when the program counter changed by a large value */
philpem@0 384 static unsigned int default_pc_changed_callback_data;
philpem@0 385 static void default_pc_changed_callback(unsigned int new_pc)
philpem@0 386 {
philpem@0 387 default_pc_changed_callback_data = new_pc;
philpem@0 388 }
philpem@0 389
philpem@0 390 /* Called every time there's bus activity (read/write to/from memory */
philpem@0 391 static unsigned int default_set_fc_callback_data;
philpem@0 392 static void default_set_fc_callback(unsigned int new_fc)
philpem@0 393 {
philpem@0 394 default_set_fc_callback_data = new_fc;
philpem@0 395 }
philpem@0 396
philpem@0 397 /* Called every instruction cycle prior to execution */
philpem@0 398 static void default_instr_hook_callback(void)
philpem@0 399 {
philpem@0 400 }
philpem@0 401
philpem@0 402
philpem@0 403
philpem@0 404 /* ======================================================================== */
philpem@0 405 /* ================================= API ================================== */
philpem@0 406 /* ======================================================================== */
philpem@0 407
philpem@0 408 /* Access the internals of the CPU */
philpem@0 409 unsigned int m68k_get_reg(void* context, m68k_register_t regnum)
philpem@0 410 {
philpem@0 411 m68ki_cpu_core* cpu = context != NULL ?(m68ki_cpu_core*)context : &m68ki_cpu;
philpem@0 412
philpem@0 413 switch(regnum)
philpem@0 414 {
philpem@0 415 case M68K_REG_D0: return cpu->dar[0];
philpem@0 416 case M68K_REG_D1: return cpu->dar[1];
philpem@0 417 case M68K_REG_D2: return cpu->dar[2];
philpem@0 418 case M68K_REG_D3: return cpu->dar[3];
philpem@0 419 case M68K_REG_D4: return cpu->dar[4];
philpem@0 420 case M68K_REG_D5: return cpu->dar[5];
philpem@0 421 case M68K_REG_D6: return cpu->dar[6];
philpem@0 422 case M68K_REG_D7: return cpu->dar[7];
philpem@0 423 case M68K_REG_A0: return cpu->dar[8];
philpem@0 424 case M68K_REG_A1: return cpu->dar[9];
philpem@0 425 case M68K_REG_A2: return cpu->dar[10];
philpem@0 426 case M68K_REG_A3: return cpu->dar[11];
philpem@0 427 case M68K_REG_A4: return cpu->dar[12];
philpem@0 428 case M68K_REG_A5: return cpu->dar[13];
philpem@0 429 case M68K_REG_A6: return cpu->dar[14];
philpem@0 430 case M68K_REG_A7: return cpu->dar[15];
philpem@0 431 case M68K_REG_PC: return MASK_OUT_ABOVE_32(cpu->pc);
philpem@0 432 case M68K_REG_SR: return cpu->t1_flag |
philpem@0 433 cpu->t0_flag |
philpem@0 434 (cpu->s_flag << 11) |
philpem@0 435 (cpu->m_flag << 11) |
philpem@0 436 cpu->int_mask |
philpem@0 437 ((cpu->x_flag & XFLAG_SET) >> 4) |
philpem@0 438 ((cpu->n_flag & NFLAG_SET) >> 4) |
philpem@0 439 ((!cpu->not_z_flag) << 2) |
philpem@0 440 ((cpu->v_flag & VFLAG_SET) >> 6) |
philpem@0 441 ((cpu->c_flag & CFLAG_SET) >> 8);
philpem@0 442 case M68K_REG_SP: return cpu->dar[15];
philpem@0 443 case M68K_REG_USP: return cpu->s_flag ? cpu->sp[0] : cpu->dar[15];
philpem@0 444 case M68K_REG_ISP: return cpu->s_flag && !cpu->m_flag ? cpu->dar[15] : cpu->sp[4];
philpem@0 445 case M68K_REG_MSP: return cpu->s_flag && cpu->m_flag ? cpu->dar[15] : cpu->sp[6];
philpem@0 446 case M68K_REG_SFC: return cpu->sfc;
philpem@0 447 case M68K_REG_DFC: return cpu->dfc;
philpem@0 448 case M68K_REG_VBR: return cpu->vbr;
philpem@0 449 case M68K_REG_CACR: return cpu->cacr;
philpem@0 450 case M68K_REG_CAAR: return cpu->caar;
philpem@0 451 case M68K_REG_PREF_ADDR: return cpu->pref_addr;
philpem@0 452 case M68K_REG_PREF_DATA: return cpu->pref_data;
philpem@0 453 case M68K_REG_PPC: return MASK_OUT_ABOVE_32(cpu->ppc);
philpem@0 454 case M68K_REG_IR: return cpu->ir;
philpem@0 455 case M68K_REG_CPU_TYPE:
philpem@0 456 switch(cpu->cpu_type)
philpem@0 457 {
philpem@0 458 case CPU_TYPE_000: return (unsigned int)M68K_CPU_TYPE_68000;
philpem@0 459 case CPU_TYPE_010: return (unsigned int)M68K_CPU_TYPE_68010;
philpem@0 460 case CPU_TYPE_EC020: return (unsigned int)M68K_CPU_TYPE_68EC020;
philpem@0 461 case CPU_TYPE_020: return (unsigned int)M68K_CPU_TYPE_68020;
philpem@0 462 }
philpem@0 463 return M68K_CPU_TYPE_INVALID;
philpem@0 464 default: return 0;
philpem@0 465 }
philpem@0 466 return 0;
philpem@0 467 }
philpem@0 468
philpem@0 469 void m68k_set_reg(m68k_register_t regnum, unsigned int value)
philpem@0 470 {
philpem@0 471 switch(regnum)
philpem@0 472 {
philpem@0 473 case M68K_REG_D0: REG_D[0] = MASK_OUT_ABOVE_32(value); return;
philpem@0 474 case M68K_REG_D1: REG_D[1] = MASK_OUT_ABOVE_32(value); return;
philpem@0 475 case M68K_REG_D2: REG_D[2] = MASK_OUT_ABOVE_32(value); return;
philpem@0 476 case M68K_REG_D3: REG_D[3] = MASK_OUT_ABOVE_32(value); return;
philpem@0 477 case M68K_REG_D4: REG_D[4] = MASK_OUT_ABOVE_32(value); return;
philpem@0 478 case M68K_REG_D5: REG_D[5] = MASK_OUT_ABOVE_32(value); return;
philpem@0 479 case M68K_REG_D6: REG_D[6] = MASK_OUT_ABOVE_32(value); return;
philpem@0 480 case M68K_REG_D7: REG_D[7] = MASK_OUT_ABOVE_32(value); return;
philpem@0 481 case M68K_REG_A0: REG_A[0] = MASK_OUT_ABOVE_32(value); return;
philpem@0 482 case M68K_REG_A1: REG_A[1] = MASK_OUT_ABOVE_32(value); return;
philpem@0 483 case M68K_REG_A2: REG_A[2] = MASK_OUT_ABOVE_32(value); return;
philpem@0 484 case M68K_REG_A3: REG_A[3] = MASK_OUT_ABOVE_32(value); return;
philpem@0 485 case M68K_REG_A4: REG_A[4] = MASK_OUT_ABOVE_32(value); return;
philpem@0 486 case M68K_REG_A5: REG_A[5] = MASK_OUT_ABOVE_32(value); return;
philpem@0 487 case M68K_REG_A6: REG_A[6] = MASK_OUT_ABOVE_32(value); return;
philpem@0 488 case M68K_REG_A7: REG_A[7] = MASK_OUT_ABOVE_32(value); return;
philpem@0 489 case M68K_REG_PC: m68ki_jump(MASK_OUT_ABOVE_32(value)); return;
philpem@0 490 case M68K_REG_SR: m68ki_set_sr(value); return;
philpem@0 491 case M68K_REG_SP: REG_SP = MASK_OUT_ABOVE_32(value); return;
philpem@0 492 case M68K_REG_USP: if(FLAG_S)
philpem@0 493 REG_USP = MASK_OUT_ABOVE_32(value);
philpem@0 494 else
philpem@0 495 REG_SP = MASK_OUT_ABOVE_32(value);
philpem@0 496 return;
philpem@0 497 case M68K_REG_ISP: if(FLAG_S && !FLAG_M)
philpem@0 498 REG_SP = MASK_OUT_ABOVE_32(value);
philpem@0 499 else
philpem@0 500 REG_ISP = MASK_OUT_ABOVE_32(value);
philpem@0 501 return;
philpem@0 502 case M68K_REG_MSP: if(FLAG_S && FLAG_M)
philpem@0 503 REG_SP = MASK_OUT_ABOVE_32(value);
philpem@0 504 else
philpem@0 505 REG_MSP = MASK_OUT_ABOVE_32(value);
philpem@0 506 return;
philpem@0 507 case M68K_REG_VBR: REG_VBR = MASK_OUT_ABOVE_32(value); return;
philpem@0 508 case M68K_REG_SFC: REG_SFC = value & 7; return;
philpem@0 509 case M68K_REG_DFC: REG_DFC = value & 7; return;
philpem@0 510 case M68K_REG_CACR: REG_CACR = MASK_OUT_ABOVE_32(value); return;
philpem@0 511 case M68K_REG_CAAR: REG_CAAR = MASK_OUT_ABOVE_32(value); return;
philpem@0 512 case M68K_REG_PPC: REG_PPC = MASK_OUT_ABOVE_32(value); return;
philpem@0 513 case M68K_REG_IR: REG_IR = MASK_OUT_ABOVE_16(value); return;
philpem@0 514 case M68K_REG_CPU_TYPE: m68k_set_cpu_type(value); return;
philpem@0 515 default: return;
philpem@0 516 }
philpem@0 517 }
philpem@0 518
philpem@0 519 /* Set the callbacks */
philpem@0 520 void m68k_set_int_ack_callback(int (*callback)(int int_level))
philpem@0 521 {
philpem@0 522 CALLBACK_INT_ACK = callback ? callback : default_int_ack_callback;
philpem@0 523 }
philpem@0 524
philpem@0 525 void m68k_set_bkpt_ack_callback(void (*callback)(unsigned int data))
philpem@0 526 {
philpem@0 527 CALLBACK_BKPT_ACK = callback ? callback : default_bkpt_ack_callback;
philpem@0 528 }
philpem@0 529
philpem@0 530 void m68k_set_reset_instr_callback(void (*callback)(void))
philpem@0 531 {
philpem@0 532 CALLBACK_RESET_INSTR = callback ? callback : default_reset_instr_callback;
philpem@0 533 }
philpem@0 534
philpem@0 535 void m68k_set_pc_changed_callback(void (*callback)(unsigned int new_pc))
philpem@0 536 {
philpem@0 537 CALLBACK_PC_CHANGED = callback ? callback : default_pc_changed_callback;
philpem@0 538 }
philpem@0 539
philpem@0 540 void m68k_set_fc_callback(void (*callback)(unsigned int new_fc))
philpem@0 541 {
philpem@0 542 CALLBACK_SET_FC = callback ? callback : default_set_fc_callback;
philpem@0 543 }
philpem@0 544
philpem@0 545 void m68k_set_instr_hook_callback(void (*callback)(void))
philpem@0 546 {
philpem@0 547 CALLBACK_INSTR_HOOK = callback ? callback : default_instr_hook_callback;
philpem@0 548 }
philpem@0 549
philpem@0 550 #include <stdio.h>
philpem@0 551 /* Set the CPU type. */
philpem@0 552 void m68k_set_cpu_type(unsigned int cpu_type)
philpem@0 553 {
philpem@0 554 switch(cpu_type)
philpem@0 555 {
philpem@0 556 case M68K_CPU_TYPE_68000:
philpem@0 557 CPU_TYPE = CPU_TYPE_000;
philpem@0 558 CPU_ADDRESS_MASK = 0x00ffffff;
philpem@0 559 CPU_SR_MASK = 0xa71f; /* T1 -- S -- -- I2 I1 I0 -- -- -- X N Z V C */
philpem@0 560 CYC_INSTRUCTION = m68ki_cycles[0];
philpem@0 561 CYC_EXCEPTION = m68ki_exception_cycle_table[0];
philpem@0 562 CYC_BCC_NOTAKE_B = -2;
philpem@0 563 CYC_BCC_NOTAKE_W = 2;
philpem@0 564 CYC_DBCC_F_NOEXP = -2;
philpem@0 565 CYC_DBCC_F_EXP = 2;
philpem@0 566 CYC_SCC_R_FALSE = 2;
philpem@0 567 CYC_MOVEM_W = 2;
philpem@0 568 CYC_MOVEM_L = 3;
philpem@0 569 CYC_SHIFT = 1;
philpem@0 570 CYC_RESET = 132;
philpem@0 571 return;
philpem@0 572 case M68K_CPU_TYPE_68010:
philpem@0 573 CPU_TYPE = CPU_TYPE_010;
philpem@0 574 CPU_ADDRESS_MASK = 0x00ffffff;
philpem@0 575 CPU_SR_MASK = 0xa71f; /* T1 -- S -- -- I2 I1 I0 -- -- -- X N Z V C */
philpem@0 576 CYC_INSTRUCTION = m68ki_cycles[1];
philpem@0 577 CYC_EXCEPTION = m68ki_exception_cycle_table[1];
philpem@0 578 CYC_BCC_NOTAKE_B = -4;
philpem@0 579 CYC_BCC_NOTAKE_W = 0;
philpem@0 580 CYC_DBCC_F_NOEXP = 0;
philpem@0 581 CYC_DBCC_F_EXP = 6;
philpem@0 582 CYC_SCC_R_FALSE = 0;
philpem@0 583 CYC_MOVEM_W = 2;
philpem@0 584 CYC_MOVEM_L = 3;
philpem@0 585 CYC_SHIFT = 1;
philpem@0 586 CYC_RESET = 130;
philpem@0 587 return;
philpem@0 588 case M68K_CPU_TYPE_68EC020:
philpem@0 589 CPU_TYPE = CPU_TYPE_EC020;
philpem@0 590 CPU_ADDRESS_MASK = 0x00ffffff;
philpem@0 591 CPU_SR_MASK = 0xf71f; /* T1 T0 S M -- I2 I1 I0 -- -- -- X N Z V C */
philpem@0 592 CYC_INSTRUCTION = m68ki_cycles[2];
philpem@0 593 CYC_EXCEPTION = m68ki_exception_cycle_table[2];
philpem@0 594 CYC_BCC_NOTAKE_B = -2;
philpem@0 595 CYC_BCC_NOTAKE_W = 0;
philpem@0 596 CYC_DBCC_F_NOEXP = 0;
philpem@0 597 CYC_DBCC_F_EXP = 4;
philpem@0 598 CYC_SCC_R_FALSE = 0;
philpem@0 599 CYC_MOVEM_W = 2;
philpem@0 600 CYC_MOVEM_L = 2;
philpem@0 601 CYC_SHIFT = 0;
philpem@0 602 CYC_RESET = 518;
philpem@0 603 return;
philpem@0 604 case M68K_CPU_TYPE_68020:
philpem@0 605 CPU_TYPE = CPU_TYPE_020;
philpem@0 606 CPU_ADDRESS_MASK = 0xffffffff;
philpem@0 607 CPU_SR_MASK = 0xf71f; /* T1 T0 S M -- I2 I1 I0 -- -- -- X N Z V C */
philpem@0 608 CYC_INSTRUCTION = m68ki_cycles[2];
philpem@0 609 CYC_EXCEPTION = m68ki_exception_cycle_table[2];
philpem@0 610 CYC_BCC_NOTAKE_B = -2;
philpem@0 611 CYC_BCC_NOTAKE_W = 0;
philpem@0 612 CYC_DBCC_F_NOEXP = 0;
philpem@0 613 CYC_DBCC_F_EXP = 4;
philpem@0 614 CYC_SCC_R_FALSE = 0;
philpem@0 615 CYC_MOVEM_W = 2;
philpem@0 616 CYC_MOVEM_L = 2;
philpem@0 617 CYC_SHIFT = 0;
philpem@0 618 CYC_RESET = 518;
philpem@0 619 return;
philpem@0 620 }
philpem@0 621 }
philpem@0 622
philpem@0 623 /* Execute some instructions until we use up num_cycles clock cycles */
philpem@0 624 /* ASG: removed per-instruction interrupt checks */
philpem@0 625 int m68k_execute(int num_cycles)
philpem@0 626 {
philpem@0 627 /* Make sure we're not stopped */
philpem@0 628 if(!CPU_STOPPED)
philpem@0 629 {
philpem@0 630 /* Set our pool of clock cycles available */
philpem@0 631 SET_CYCLES(num_cycles);
philpem@0 632 m68ki_initial_cycles = num_cycles;
philpem@0 633
philpem@0 634 /* ASG: update cycles */
philpem@0 635 USE_CYCLES(CPU_INT_CYCLES);
philpem@0 636 CPU_INT_CYCLES = 0;
philpem@0 637
philpem@0 638 /* Return point if we had an address error */
philpem@0 639 m68ki_set_address_error_trap(); /* auto-disable (see m68kcpu.h) */
philpem@0 640
philpem@0 641 /* Main loop. Keep going until we run out of clock cycles */
philpem@0 642 do
philpem@0 643 {
philpem@0 644 /* Set tracing accodring to T1. (T0 is done inside instruction) */
philpem@0 645 m68ki_trace_t1(); /* auto-disable (see m68kcpu.h) */
philpem@0 646
philpem@0 647 /* Set the address space for reads */
philpem@0 648 m68ki_use_data_space(); /* auto-disable (see m68kcpu.h) */
philpem@0 649
philpem@0 650 /* Call external hook to peek at CPU */
philpem@0 651 m68ki_instr_hook(); /* auto-disable (see m68kcpu.h) */
philpem@0 652
philpem@0 653 /* Record previous program counter */
philpem@0 654 REG_PPC = REG_PC;
philpem@0 655
philpem@0 656 /* Read an instruction and call its handler */
philpem@0 657 REG_IR = m68ki_read_imm_16();
philpem@118 658 if (!BUS_ERROR_OCCURRED){
philpem@118 659 m68ki_instruction_jump_table[REG_IR]();
philpem@118 660 }
philpem@0 661 USE_CYCLES(CYC_INSTRUCTION[REG_IR]);
philpem@0 662
philpem@0 663 /* Trace m68k_exception, if necessary */
philpem@0 664 m68ki_exception_if_trace(); /* auto-disable (see m68kcpu.h) */
philpem@118 665
philpem@118 666 if (BUS_ERROR_OCCURRED){
philpem@118 667 m68ki_jump_bus_error_vector();
philpem@118 668 BUS_ERROR_OCCURRED = 0;
philpem@118 669 }
philpem@0 670 } while(GET_CYCLES() > 0);
philpem@0 671
philpem@0 672 /* set previous PC to current PC for the next entry into the loop */
philpem@0 673 REG_PPC = REG_PC;
philpem@0 674
philpem@0 675 /* ASG: update cycles */
philpem@0 676 USE_CYCLES(CPU_INT_CYCLES);
philpem@0 677 CPU_INT_CYCLES = 0;
philpem@0 678
philpem@0 679 /* return how many clocks we used */
philpem@0 680 return m68ki_initial_cycles - GET_CYCLES();
philpem@0 681 }
philpem@0 682
philpem@0 683 /* We get here if the CPU is stopped or halted */
philpem@0 684 SET_CYCLES(0);
philpem@0 685 CPU_INT_CYCLES = 0;
philpem@0 686
philpem@0 687 return num_cycles;
philpem@0 688 }
philpem@0 689
philpem@0 690
philpem@0 691 int m68k_cycles_run(void)
philpem@0 692 {
philpem@0 693 return m68ki_initial_cycles - GET_CYCLES();
philpem@0 694 }
philpem@0 695
philpem@0 696 int m68k_cycles_remaining(void)
philpem@0 697 {
philpem@0 698 return GET_CYCLES();
philpem@0 699 }
philpem@0 700
philpem@0 701 /* Change the timeslice */
philpem@0 702 void m68k_modify_timeslice(int cycles)
philpem@0 703 {
philpem@0 704 m68ki_initial_cycles += cycles;
philpem@0 705 ADD_CYCLES(cycles);
philpem@0 706 }
philpem@0 707
philpem@0 708
philpem@0 709 void m68k_end_timeslice(void)
philpem@0 710 {
philpem@0 711 m68ki_initial_cycles = GET_CYCLES();
philpem@0 712 SET_CYCLES(0);
philpem@0 713 }
philpem@0 714
philpem@0 715
philpem@0 716 /* ASG: rewrote so that the int_level is a mask of the IPL0/IPL1/IPL2 bits */
philpem@0 717 /* KS: Modified so that IPL* bits match with mask positions in the SR
philpem@0 718 * and cleaned out remenants of the interrupt controller.
philpem@0 719 */
philpem@0 720 void m68k_set_irq(unsigned int int_level)
philpem@0 721 {
philpem@0 722 uint old_level = CPU_INT_LEVEL;
philpem@0 723 CPU_INT_LEVEL = int_level << 8;
philpem@0 724
philpem@0 725 /* A transition from < 7 to 7 always interrupts (NMI) */
philpem@0 726 /* Note: Level 7 can also level trigger like a normal IRQ */
philpem@0 727 if(old_level != 0x0700 && CPU_INT_LEVEL == 0x0700)
philpem@0 728 m68ki_exception_interrupt(7); /* Edge triggered level 7 (NMI) */
philpem@0 729 else
philpem@0 730 m68ki_check_interrupts(); /* Level triggered (IRQ) */
philpem@0 731 }
philpem@0 732
philpem@0 733
philpem@19 734 /* Trigger a Bus Error exception */
philpem@31 735 void m68k_pulse_bus_error(void)
philpem@19 736 {
philpem@19 737 m68ki_exception_bus_error();
philpem@19 738 }
philpem@19 739
philpem@19 740
philpem@0 741 /* Pulse the RESET line on the CPU */
philpem@0 742 void m68k_pulse_reset(void)
philpem@0 743 {
philpem@0 744 static uint emulation_initialized = 0;
philpem@0 745
philpem@0 746 /* The first call to this function initializes the opcode handler jump table */
philpem@0 747 if(!emulation_initialized)
philpem@0 748 {
philpem@0 749 m68ki_build_opcode_table();
philpem@0 750 m68k_set_int_ack_callback(NULL);
philpem@0 751 m68k_set_bkpt_ack_callback(NULL);
philpem@0 752 m68k_set_reset_instr_callback(NULL);
philpem@0 753 m68k_set_pc_changed_callback(NULL);
philpem@0 754 m68k_set_fc_callback(NULL);
philpem@0 755 m68k_set_instr_hook_callback(NULL);
philpem@0 756
philpem@0 757 emulation_initialized = 1;
philpem@0 758 }
philpem@0 759
philpem@0 760
philpem@0 761 if(CPU_TYPE == 0) /* KW 990319 */
philpem@0 762 m68k_set_cpu_type(M68K_CPU_TYPE_68000);
philpem@0 763
philpem@0 764 /* Clear all stop levels and eat up all remaining cycles */
philpem@0 765 CPU_STOPPED = 0;
philpem@0 766 SET_CYCLES(0);
philpem@0 767
philpem@0 768 /* Turn off tracing */
philpem@0 769 FLAG_T1 = FLAG_T0 = 0;
philpem@0 770 m68ki_clear_trace();
philpem@0 771 /* Interrupt mask to level 7 */
philpem@0 772 FLAG_INT_MASK = 0x0700;
philpem@0 773 /* Reset VBR */
philpem@0 774 REG_VBR = 0;
philpem@0 775 /* Go to supervisor mode */
philpem@0 776 m68ki_set_sm_flag(SFLAG_SET | MFLAG_CLEAR);
philpem@0 777
philpem@0 778 /* Invalidate the prefetch queue */
philpem@0 779 #if M68K_EMULATE_PREFETCH
philpem@0 780 /* Set to arbitrary number since our first fetch is from 0 */
philpem@0 781 CPU_PREF_ADDR = 0x1000;
philpem@0 782 #endif /* M68K_EMULATE_PREFETCH */
philpem@0 783
philpem@0 784 /* Read the initial stack pointer and program counter */
philpem@0 785 m68ki_jump(0);
philpem@0 786 REG_SP = m68ki_read_imm_32();
philpem@0 787 REG_PC = m68ki_read_imm_32();
philpem@0 788 m68ki_jump(REG_PC);
philpem@0 789 }
philpem@0 790
philpem@0 791 /* Pulse the HALT line on the CPU */
philpem@0 792 void m68k_pulse_halt(void)
philpem@0 793 {
philpem@0 794 CPU_STOPPED |= STOP_LEVEL_HALT;
philpem@0 795 }
philpem@0 796
philpem@0 797
philpem@0 798 /* Get and set the current CPU context */
philpem@0 799 /* This is to allow for multiple CPUs */
philpem@0 800 unsigned int m68k_context_size()
philpem@0 801 {
philpem@0 802 return sizeof(m68ki_cpu_core);
philpem@0 803 }
philpem@0 804
philpem@0 805 unsigned int m68k_get_context(void* dst)
philpem@0 806 {
philpem@0 807 if(dst) *(m68ki_cpu_core*)dst = m68ki_cpu;
philpem@0 808 return sizeof(m68ki_cpu_core);
philpem@0 809 }
philpem@0 810
philpem@0 811 void m68k_set_context(void* src)
philpem@0 812 {
philpem@0 813 if(src) m68ki_cpu = *(m68ki_cpu_core*)src;
philpem@0 814 }
philpem@0 815
philpem@0 816 void m68k_save_context( void (*save_value)(char*, unsigned int))
philpem@0 817 {
philpem@0 818 if(!save_value)
philpem@0 819 return;
philpem@0 820
philpem@0 821 save_value("CPU_TYPE" , m68k_get_reg(NULL, M68K_REG_CPU_TYPE));
philpem@0 822 save_value("D0" , REG_D[0]);
philpem@0 823 save_value("D1" , REG_D[1]);
philpem@0 824 save_value("D2" , REG_D[2]);
philpem@0 825 save_value("D3" , REG_D[3]);
philpem@0 826 save_value("D4" , REG_D[4]);
philpem@0 827 save_value("D5" , REG_D[5]);
philpem@0 828 save_value("D6" , REG_D[6]);
philpem@0 829 save_value("D7" , REG_D[7]);
philpem@0 830 save_value("A0" , REG_A[0]);
philpem@0 831 save_value("A1" , REG_A[1]);
philpem@0 832 save_value("A2" , REG_A[2]);
philpem@0 833 save_value("A3" , REG_A[3]);
philpem@0 834 save_value("A4" , REG_A[4]);
philpem@0 835 save_value("A5" , REG_A[5]);
philpem@0 836 save_value("A6" , REG_A[6]);
philpem@0 837 save_value("A7" , REG_A[7]);
philpem@0 838 save_value("PPC" , REG_PPC);
philpem@0 839 save_value("PC" , REG_PC);
philpem@0 840 save_value("USP" , REG_USP);
philpem@0 841 save_value("ISP" , REG_ISP);
philpem@0 842 save_value("MSP" , REG_MSP);
philpem@0 843 save_value("VBR" , REG_VBR);
philpem@0 844 save_value("SFC" , REG_SFC);
philpem@0 845 save_value("DFC" , REG_DFC);
philpem@0 846 save_value("CACR" , REG_CACR);
philpem@0 847 save_value("CAAR" , REG_CAAR);
philpem@0 848 save_value("SR" , m68ki_get_sr());
philpem@0 849 save_value("INT_LEVEL" , CPU_INT_LEVEL);
philpem@0 850 save_value("INT_CYCLES", CPU_INT_CYCLES);
philpem@0 851 save_value("STOPPED" , (CPU_STOPPED & STOP_LEVEL_STOP) != 0);
philpem@0 852 save_value("HALTED" , (CPU_STOPPED & STOP_LEVEL_HALT) != 0);
philpem@0 853 save_value("PREF_ADDR" , CPU_PREF_ADDR);
philpem@0 854 save_value("PREF_DATA" , CPU_PREF_DATA);
philpem@0 855 }
philpem@0 856
philpem@0 857 void m68k_load_context(unsigned int (*load_value)(char*))
philpem@0 858 {
philpem@0 859 unsigned int temp;
philpem@0 860
philpem@0 861 m68k_set_cpu_type(load_value("CPU_TYPE"));
philpem@0 862 REG_PPC = load_value("PPC");
philpem@0 863 REG_PC = load_value("PC");
philpem@0 864 m68ki_jump(REG_PC);
philpem@0 865 CPU_INT_LEVEL = 0;
philpem@0 866 m68ki_set_sr_noint(load_value("SR"));
philpem@0 867 REG_D[0] = load_value("D0");
philpem@0 868 REG_D[1] = load_value("D1");
philpem@0 869 REG_D[2] = load_value("D2");
philpem@0 870 REG_D[3] = load_value("D3");
philpem@0 871 REG_D[4] = load_value("D4");
philpem@0 872 REG_D[5] = load_value("D5");
philpem@0 873 REG_D[6] = load_value("D6");
philpem@0 874 REG_D[7] = load_value("D7");
philpem@0 875 REG_A[0] = load_value("A0");
philpem@0 876 REG_A[1] = load_value("A1");
philpem@0 877 REG_A[2] = load_value("A2");
philpem@0 878 REG_A[3] = load_value("A3");
philpem@0 879 REG_A[4] = load_value("A4");
philpem@0 880 REG_A[5] = load_value("A5");
philpem@0 881 REG_A[6] = load_value("A6");
philpem@0 882 REG_A[7] = load_value("A7");
philpem@0 883 REG_USP = load_value("USP");
philpem@0 884 REG_ISP = load_value("ISP");
philpem@0 885 REG_MSP = load_value("MSP");
philpem@0 886 REG_VBR = load_value("VBR");
philpem@0 887 REG_SFC = load_value("SFC");
philpem@0 888 REG_DFC = load_value("DFC");
philpem@0 889 REG_CACR = load_value("CACR");
philpem@0 890 REG_CAAR = load_value("CAAR");
philpem@0 891 CPU_INT_LEVEL = load_value("INT_LEVEL");
philpem@0 892 CPU_INT_CYCLES = load_value("INT_CYCLES");
philpem@0 893
philpem@0 894 CPU_STOPPED = 0;
philpem@0 895 temp = load_value("STOPPED");
philpem@0 896 if(temp) CPU_STOPPED |= STOP_LEVEL_STOP;
philpem@0 897 temp = load_value("HALTED");
philpem@0 898 if(temp) CPU_STOPPED |= STOP_LEVEL_HALT;
philpem@0 899
philpem@0 900 CPU_PREF_ADDR = load_value("PREF_ADDR");
philpem@0 901 CPU_PREF_DATA = load_value("PREF_DATA");
philpem@0 902 }
philpem@0 903
philpem@0 904
philpem@0 905
philpem@0 906 /* ======================================================================== */
philpem@0 907 /* ============================== END OF FILE ============================= */
philpem@0 908 /* ======================================================================== */