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