src/musashi/m68kcpu.c

Wed, 16 Apr 2014 02:20:43 -0600

author
andrew@localhost
date
Wed, 16 Apr 2014 02:20:43 -0600
changeset 147
ad888290cdff
parent 118
feee84e0b3bf
permissions
-rw-r--r--

fixed bus error handling for real this time (save registers before every instruction and push the saved registers if a bus error occurs, since the instruction may have changed registers before the bus error, and also stop the instruction immediately with longjmp so it won't change memory after the bus error)

This isn't actually what a real 68k does, but it is a good enough approximation. A real 68k will jump back into the middle of the faulted instruction and resume it from the memory access that faulted as opposed to restarting from the beginning like this CPU emulation does. It would be a lot harder to do that with the way this CPU library is designed. Newer versions of MESS basically do the same thing (they use a newer version of this library).

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