1 /*
2  * 65816core.c - 65816/65802 emulation core.
3  *
4  * Written by
5  *  Marco van den Heuvel <blackystardust68@yahoo.com>
6  *  Kajtar Zsolt <soci@c64.rulez.org>
7  *
8  * This file is part of VICE, the Versatile Commodore Emulator.
9  * See README for copyright notice.
10  *
11  *  This program is free software; you can redistribute it and/or modify
12  *  it under the terms of the GNU General Public License as published by
13  *  the Free Software Foundation; either version 2 of the License, or
14  *  (at your option) any later version.
15  *
16  *  This program is distributed in the hope that it will be useful,
17  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
18  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  *  GNU General Public License for more details.
20  *
21  *  You should have received a copy of the GNU General Public License
22  *  along with this program; if not, write to the Free Software
23  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
24  *  02111-1307  USA.
25  *
26  */
27 
28 /* This file is included by the following CPU definition files:
29  * - main65816cpu.c
30  */
31 
32 /* any CPU definition file that includes this file needs to do the following:
33  *
34  * - define reg_c as 16bit (8bit on 6502/65C02).
35  * - define reg_x as 16bit (8bit on 6502/65C02).
36  * - define reg_y as 16bit (8bit on 6502/65C02).
37  * - define reg_pbr (Program Bank Register) as 8bit.
38  * - define reg_dbr (Data Bank Register) as 8bit.
39  * - define reg_dpr (Direct Page Register) as 16bit.
40  * - define reg_emul (65C02 Emulation) as int.
41  * - define reg_sp as 16bit (8bit on 6502/65C02).
42  * - define reg_p as 8bit.
43  * - define reg_pc as 16bit.
44  * - define a function to handle the STP opcode (STP_65816(void)).
45  * - define a function to handle the WAI opcode (WAI_65816(void)).
46  * - define a function to handle the COP opcode (COP_65816(BYTE value)).
47  *
48  * reg_a and reg_b combined is reg_c.
49  *
50  * the way to define the a, b and c regs is:
51  * union regs {
52  *     WORD reg_s;
53  *     BYTE reg_c[2];
54  * } regs65816;
55  *
56  * #define reg_c regs65816.reg_s
57  * #ifndef WORDS_BIGENDIAN
58  * #define reg_a regs65816.reg_c[0]
59  * #define reg_b regs65816.reg_c[1]
60  * #else
61  * #define reg_a regs65816.reg_c[1]
62  * #define reg_b regs65816.reg_c[0]
63  * #endif
64  */
65 
66 #ifndef CPU_STR
67 #define CPU_STR "65816/65802 CPU"
68 #endif
69 
70 #include "traps.h"
71 
72 /* To avoid 'magic' numbers, the following defines are used. */
73 
74 #define CYCLES_0   0
75 #define CYCLES_1   1
76 #define CYCLES_2   2
77 #define CYCLES_3   3
78 #define CYCLES_4   4
79 #define CYCLES_5   5
80 #define CYCLES_6   6
81 #define CYCLES_7   7
82 
83 #define SIZE_1   1
84 #define SIZE_2   2
85 #define SIZE_3   3
86 #define SIZE_4   4
87 
88 #define BITS8    1
89 #define BITS16   0
90 
91 #define RESET_CYCLES    6
92 
93 #define SET_OPCODE(o) p0 = o
94 /* ------------------------------------------------------------------------- */
95 /* Backup for non-variable cycle CPUs.  */
96 
97 #ifndef CLK_INC
98 #define CLK_INC(clock) clock++
99 #endif
100 
101 /* ------------------------------------------------------------------------- */
102 /* Hook for additional delay.  */
103 
104 #ifndef EMULATION_MODE_CHANGED
105 #define EMULATION_MODE_CHANGED
106 #endif
107 
108 #ifndef WAI_65816
109 #define WAI_65816() NOP()
110 #endif
111 
112 #ifndef STP_65816
113 #define STP_65816() NOP()
114 #endif
115 
116 #ifndef COP_65816
117 #define COP_65816(value) NOP()
118 #endif
119 
120 
121 #ifndef FETCH_PARAM_DUMMY
122 #define FETCH_PARAM_DUMMY(addr) FETCH_PARAM(addr)
123 #endif
124 
125 #ifndef LOAD_LONG_DUMMY
126 #define LOAD_LONG_DUMMY(addr) LOAD_LONG(addr)
127 #endif
128 
129 #define CHECK_INTERRUPT() (interrupt65816 = CPU_INT_STATUS->global_pending_int & (LOCAL_INTERRUPT() ? ~(IK_IRQPEND | IK_IRQ) : ~IK_IRQPEND))
130 /* ------------------------------------------------------------------------- */
131 /* Hook for interrupt address manipulation.  */
132 
133 #ifndef LOAD_INT_ADDR
134 #define LOAD_INT_ADDR(addr)                 \
135     do {                                    \
136         reg_pc = LOAD_LONG(addr);           \
137         reg_pc |= LOAD_LONG(addr + 1) << 8; \
138     } while (0)
139 #endif
140 
141 /* ------------------------------------------------------------------------- */
142 
143 #define LOCAL_SET_NZ(val, bits8)           \
144     do {                                   \
145         if (!bits8) {                      \
146             flag_n = (val >> 8);           \
147             flag_z = (val) | flag_n;       \
148         } else {                           \
149             flag_z = flag_n = ((uint8_t)val); \
150         }                                  \
151     } while (0)
152 
153 #define LOCAL_SET_OVERFLOW(val)   \
154     do {                          \
155         if (val) {                \
156             reg_p |= P_OVERFLOW;  \
157         } else {                  \
158             reg_p &= ~P_OVERFLOW; \
159         }                         \
160     } while (0)
161 
162 #define LOCAL_SET_BREAK(val)   \
163     do {                       \
164         if (val) {             \
165             reg_p |= P_BREAK;  \
166         } else {               \
167             reg_p &= ~P_BREAK; \
168         }                      \
169     } while (0)
170 
171 #define LOCAL_SET_DECIMAL(val)   \
172     do {                         \
173         if (val) {               \
174             reg_p |= P_DECIMAL;  \
175         } else {                 \
176             reg_p &= ~P_DECIMAL; \
177         }                        \
178     } while (0)
179 
180 #define LOCAL_SET_INTERRUPT(val)   \
181     do {                           \
182         if (val) {                 \
183             reg_p |= P_INTERRUPT;  \
184         } else {                   \
185             reg_p &= ~P_INTERRUPT; \
186         }                          \
187     } while (0)
188 
189 #define LOCAL_SET_CARRY(val)   \
190     do {                       \
191         if (val) {             \
192             reg_p |= P_CARRY;  \
193         } else {               \
194             reg_p &= ~P_CARRY; \
195         }                      \
196     } while (0)
197 
198 #define LOCAL_SET_65816_M(val)   \
199     do {                         \
200         if (val) {               \
201             reg_p |= P_65816_M;  \
202         } else {                 \
203             reg_p &= ~P_65816_M; \
204         }                        \
205     } while (0)
206 
207 #define LOCAL_SET_65816_X(val)   \
208     do {                         \
209         if (val) {               \
210             reg_p |= P_65816_X;  \
211         } else {                 \
212             reg_p &= ~P_65816_X; \
213         }                        \
214     } while (0)
215 
216 #define LOCAL_SET_SIGN(val)      (flag_n = (val) ? 0x80 : 0)
217 #define LOCAL_SET_ZERO(val)      (flag_z = !(val))
218 #define LOCAL_SET_STATUS(val)    (reg_p = ((val) & ~(P_ZERO | P_SIGN)), \
219                                   LOCAL_SET_ZERO((val) & P_ZERO),       \
220                                   flag_n = (val))
221 
222 #define LOCAL_OVERFLOW()         (reg_p & P_OVERFLOW)
223 #define LOCAL_BREAK()            (reg_p & P_BREAK)
224 #define LOCAL_DECIMAL()          (reg_p & P_DECIMAL)
225 #define LOCAL_INTERRUPT()        (reg_p & P_INTERRUPT)
226 #define LOCAL_CARRY()            (reg_p & P_CARRY)
227 #define LOCAL_SIGN()             (flag_n & 0x80)
228 #define LOCAL_ZERO()             (!flag_z)
229 #define LOCAL_STATUS()           (reg_p | (flag_n & 0x80) | P_UNUSED    \
230                                   | (LOCAL_ZERO() ? P_ZERO : 0))
231 
232 #define LOCAL_65816_M()          (reg_emul || (reg_p & P_65816_M))
233 #define LOCAL_65816_X()          (reg_emul || (reg_p & P_65816_X))
234 
235 #define LOCAL_65816_STATUS()     (reg_p | (flag_n & 0x80) | (LOCAL_ZERO() ? P_ZERO : 0))
236 
237 #ifdef LAST_OPCODE_INFO
238 
239 /* If requested, gather some info about the last executed opcode for timing
240    purposes.  */
241 
242 /* Remember the number of the last opcode.  By default, the opcode does not
243    delay interrupt and does not change the I flag.  */
244 #define SET_LAST_OPCODE(x) \
245     OPINFO_SET(LAST_OPCODE_INFO, (x), 0, 0, 0)
246 
247 /* Remember that the last opcode changed the I flag from 0 to 1, so we have
248    to dispatch an IRQ even if the I flag is 0 when we check it.  */
249 #define OPCODE_DISABLES_IRQ() \
250     OPINFO_SET_DISABLES_IRQ(LAST_OPCODE_INFO, 1)
251 
252 /* Remember that the last opcode changed the I flag from 1 to 0, so we must
253    not dispatch an IRQ even if the I flag is 1 when we check it.  */
254 #define OPCODE_ENABLES_IRQ() \
255     OPINFO_SET_ENABLES_IRQ(LAST_OPCODE_INFO, 1)
256 
257 #else
258 
259 /* Info about the last opcode is not needed.  */
260 #define SET_LAST_OPCODE(x)
261 #define OPCODE_DISABLES_IRQ()
262 #define OPCODE_ENABLES_IRQ()
263 
264 #endif
265 
266 #ifdef LAST_OPCODE_ADDR
267 #define SET_LAST_ADDR(x) LAST_OPCODE_ADDR = (x)
268 #else
269 #error "please define LAST_OPCODE_ADDR"
270 #endif
271 
272 /* Export the local version of the registers.  */
273 #define EXPORT_REGISTERS()         \
274   do {                             \
275       GLOBAL_REGS.pc = reg_pc;     \
276       GLOBAL_REGS.a = reg_a;       \
277       GLOBAL_REGS.b = reg_b;       \
278       GLOBAL_REGS.x = reg_x;       \
279       GLOBAL_REGS.y = reg_y;       \
280       GLOBAL_REGS.emul = reg_emul; \
281       GLOBAL_REGS.dpr = reg_dpr;   \
282       GLOBAL_REGS.pbr = reg_pbr;   \
283       GLOBAL_REGS.dbr = reg_dbr;   \
284       GLOBAL_REGS.sp = reg_sp;     \
285       GLOBAL_REGS.p = reg_p;       \
286       GLOBAL_REGS.n = flag_n;      \
287       GLOBAL_REGS.z = flag_z;      \
288   } while (0)
289 
290 /* Import the public version of the registers.  */
291 #define IMPORT_REGISTERS()                               \
292   do {                                                   \
293       reg_a = GLOBAL_REGS.a;                             \
294       reg_b = GLOBAL_REGS.b;                             \
295       reg_x = GLOBAL_REGS.x;                             \
296       reg_y = GLOBAL_REGS.y;                             \
297       reg_emul = GLOBAL_REGS.emul;                       \
298       reg_dpr = GLOBAL_REGS.dpr;                         \
299       reg_pbr = GLOBAL_REGS.pbr;                         \
300       reg_dbr = GLOBAL_REGS.dbr;                         \
301       reg_sp = GLOBAL_REGS.sp;                           \
302       reg_p = GLOBAL_REGS.p;                             \
303       flag_n = GLOBAL_REGS.n;                            \
304       flag_z = GLOBAL_REGS.z;                            \
305       if (reg_emul) { /* fixup emulation mode */         \
306           reg_x &= 0xff;                                 \
307           reg_y &= 0xff;                                 \
308           reg_sp = 0x100 | (reg_sp & 0xff);              \
309       }                                                  \
310       bank_start = bank_limit = 0; /* prevent caching */ \
311       EMULATION_MODE_CHANGED;                            \
312       JUMP(GLOBAL_REGS.pc);                              \
313   } while (0)
314 
315 /* Stack operations. */
316 
317 #ifndef PUSH
318 #define PUSH(val)                                 \
319   do {                                            \
320       STORE_LONG(reg_sp, val);                    \
321       if (reg_emul) {                             \
322           reg_sp = 0x100 | ((reg_sp - 1) & 0xff); \
323       } else {                                    \
324           reg_sp--;                               \
325       }                                           \
326   } while (0)
327 #endif
328 
329 #ifndef PULL
330 #define PULL() ((reg_sp = (reg_emul) ? 0x100 | ((reg_sp + 1) & 0xff) : reg_sp + 1), LOAD_LONG(reg_sp))
331 #endif
332 
333 #ifdef DEBUG
334 #define TRACE_NMI() \
335     do { if (TRACEFLG) debug_nmi(CPU_INT_STATUS, CLK); } while (0)
336 #define TRACE_IRQ() \
337     do { if (TRACEFLG) debug_irq(CPU_INT_STATUS, CLK); } while (0)
338 #define TRACE_BRK() do { if (TRACEFLG) debug_text("*** BRK"); } while (0)
339 #define TRACE_COP() do { if (TRACEFLG) debug_text("*** COP"); } while (0)
340 #else
341 #define TRACE_NMI()
342 #define TRACE_IRQ()
343 #define TRACE_BRK()
344 #define TRACE_COP()
345 #endif
346 
347 /* Perform the interrupts in `int_kind'.  If we have both NMI and IRQ,
348    execute NMI.  */
349 #define DO_INTERRUPT(ik)                                                       \
350     do {                                                                       \
351         if (ik & (IK_TRAP | IK_MONITOR | IK_DMA)) {                            \
352             if (ik & IK_TRAP) {                                                \
353                 EXPORT_REGISTERS();                                            \
354                 interrupt_do_trap(CPU_INT_STATUS, (uint16_t)reg_pc);               \
355                 IMPORT_REGISTERS();                                            \
356                 interrupt65816 &= ~IK_TRAP;                                    \
357             }                                                                  \
358             if (ik & IK_MONITOR) {                                             \
359                 if (monitor_force_import(CALLER)) {                            \
360                     IMPORT_REGISTERS();                                        \
361                 }                                                              \
362                 if (monitor_mask[CALLER]) {                                    \
363                     EXPORT_REGISTERS();                                        \
364                 }                                                              \
365                 if (monitor_mask[CALLER] & (MI_STEP)) {                        \
366                     monitor_check_icount((uint16_t)reg_pc);                        \
367                     IMPORT_REGISTERS();                                        \
368                 }                                                              \
369                 if (monitor_mask[CALLER] & (MI_BREAK)) {                       \
370                     if (monitor_check_breakpoints(CALLER, (uint16_t)reg_pc)) {     \
371                         monitor_startup(CALLER);                               \
372                         IMPORT_REGISTERS();                                    \
373                     }                                                          \
374                 }                                                              \
375                 if (monitor_mask[CALLER] & (MI_WATCH)) {                       \
376                     monitor_check_watchpoints(LAST_OPCODE_ADDR, (uint16_t)reg_pc); \
377                     IMPORT_REGISTERS();                                        \
378                 }                                                              \
379                 interrupt65816 &= ~IK_MONITOR;                                 \
380             }                                                                  \
381             if (ik & IK_DMA) {                                                 \
382                 EXPORT_REGISTERS();                                            \
383                 DMA_FUNC;                                                      \
384                 interrupt_ack_dma(CPU_INT_STATUS);                             \
385                 IMPORT_REGISTERS();                                            \
386                 JUMP(reg_pc);                                                  \
387                 interrupt65816 &= ~IK_DMA;                                     \
388             }                                                                  \
389         }                                                                      \
390     } while (0)
391 /* ------------------------------------------------------------------------- */
392 
393 /* Addressing modes.  For convenience, page boundary crossing cycles and
394    ``idle'' memory reads are handled here as well. */
395 
396 #define LOAD_PBR(addr) \
397     LOAD_LONG((addr) + (reg_pbr << 16))
398 
399 #define LOAD_BANK0(addr) \
400     LOAD_LONG((addr) & 0xffff)
401 
402 #define DPR_DELAY \
403       if (reg_dpr & 0xff) {                            \
404           FETCH_PARAM_DUMMY(reg_pc);                   \
405       }                                                \
406 
407 #ifndef FETCH_PARAM
408 #define FETCH_PARAM(addr) ((((int)(addr)) < bank_limit) ? (CLK_INC(CLK), bank_base[addr]) : LOAD_PBR(addr))
409 #endif
410 
411 /* s */
412 #define LOAD_STACK(var, bits8)     \
413     INC_PC(SIZE_1);                \
414     FETCH_PARAM_DUMMY(reg_pc);     \
415     if (bits8) {                   \
416         CHECK_INTERRUPT();         \
417         FETCH_PARAM_DUMMY(reg_pc); \
418         var = PULL();              \
419     } else {                       \
420         FETCH_PARAM_DUMMY(reg_pc); \
421         CHECK_INTERRUPT();         \
422         var = PULL();              \
423         var |= PULL() << 8;        \
424     }
425 
426 /* a */
427 #define LOAD_ACCU_RRW(var, bits8) \
428     INC_PC(SIZE_1);               \
429     FETCH_PARAM_DUMMY(reg_pc);    \
430     if (bits8) {                  \
431         var = reg_a;              \
432     } else {                      \
433         var = reg_c;              \
434     }
435 
436 /* # */
437 #define LOAD_IMMEDIATE_FUNC(var, bits8) \
438     INC_PC(SIZE_1);                     \
439     if (bits8) {                        \
440         p1 = FETCH_PARAM(reg_pc);       \
441         var = p1;                       \
442     } else {                            \
443         CHECK_INTERRUPT();              \
444         p1 = FETCH_PARAM(reg_pc);       \
445         INC_PC(SIZE_1);                 \
446         p2 = FETCH_PARAM(reg_pc) << 8;  \
447         var = p1 + p2;                  \
448     }                                   \
449     INC_PC(SIZE_1);
450 
451 /* $ff wrapping */
452 #define DIRECT_PAGE_FUNC(var, value, bits8, write) \
453   do {                                             \
454       unsigned int ea;                             \
455                                                    \
456       INC_PC(SIZE_1);                              \
457       if (bits8) {                                 \
458           if (reg_dpr & 0xff) {                    \
459               p1 = FETCH_PARAM(reg_pc);            \
460               CHECK_INTERRUPT();                   \
461               FETCH_PARAM_DUMMY(reg_pc);           \
462           } else {                                 \
463               CHECK_INTERRUPT();                   \
464               p1 = FETCH_PARAM(reg_pc);            \
465           }                                        \
466           ea = p1 + reg_dpr;                       \
467           if (write) {                             \
468               STORE_BANK0(ea, value);              \
469           } else {                                 \
470               var = LOAD_BANK0(ea);                \
471           }                                        \
472       } else {                                     \
473           p1 = FETCH_PARAM(reg_pc);                \
474           if (reg_dpr & 0xff) {                    \
475               FETCH_PARAM_DUMMY(reg_pc);           \
476           }                                        \
477           CHECK_INTERRUPT();                       \
478           ea = p1 + reg_dpr;                       \
479           if (write) {                             \
480               STORE_BANK0(ea, value);              \
481               STORE_BANK0(ea + 1, value >> 8);     \
482           } else {                                 \
483               var = LOAD_BANK0(ea);                \
484               var |= LOAD_BANK0(ea + 1) << 8;      \
485           }                                        \
486       }                                            \
487       INC_PC(SIZE_1);                              \
488   } while (0)
489 
490 /* $ff wrapping */
491 #define LOAD_DIRECT_PAGE_FUNC(var, bits8) DIRECT_PAGE_FUNC(var, 0, bits8, 0)
492 
493 /* $ff wrapping */
494 #define LOAD_DIRECT_PAGE_FUNC_RRW(var, bits8) \
495       unsigned int ea;                        \
496                                               \
497       INC_PC(SIZE_1);                         \
498       p1 = FETCH_PARAM(reg_pc);               \
499       DPR_DELAY                               \
500       INC_PC(SIZE_1);                         \
501       ea = (p1 + reg_dpr) & 0xffff;           \
502       var = LOAD_LONG(ea);                    \
503       if (reg_emul) {                         \
504           CHECK_INTERRUPT();                  \
505           STORE_LONG(ea, var);                \
506       } else {                                \
507           if (bits8) {                        \
508               CHECK_INTERRUPT();              \
509               LOAD_LONG_DUMMY(ea);            \
510           } else {                            \
511               ea = (ea + 1) & 0xffff;         \
512               var |= LOAD_LONG(ea) << 8;      \
513               LOAD_LONG_DUMMY(ea);            \
514               CHECK_INTERRUPT();              \
515           }                                   \
516       }
517 
518 /* $ff,r wrapping */
519 #define DIRECT_PAGE_R_FUNC(var, value, bits8, reg_r, write) \
520   do {                                                      \
521       unsigned int ea;                                      \
522                                                             \
523       INC_PC(SIZE_1);                                       \
524       p1 = FETCH_PARAM(reg_pc);                             \
525       DPR_DELAY                                             \
526       if (reg_emul) {                                       \
527           CHECK_INTERRUPT();                                \
528           FETCH_PARAM_DUMMY(reg_pc);                        \
529           if (reg_dpr & 0xff) {                             \
530               ea = p1 + reg_r + reg_dpr;                    \
531           } else {                                          \
532               ea = ((p1 + reg_r) & 0xff) + reg_dpr;         \
533           }                                                 \
534           if (write) {                                      \
535               STORE_BANK0(ea, value);                       \
536           } else {                                          \
537               var = LOAD_BANK0(ea);                         \
538           }                                                 \
539       } else {                                              \
540           ea = p1 + reg_dpr + reg_r;                        \
541           if (bits8) {                                      \
542               CHECK_INTERRUPT();                            \
543               FETCH_PARAM_DUMMY(reg_pc);                    \
544               if (write) {                                  \
545                   STORE_BANK0(ea, value);                   \
546               } else {                                      \
547                   var = LOAD_BANK0(ea);                     \
548               }                                             \
549           } else {                                          \
550               FETCH_PARAM_DUMMY(reg_pc);                    \
551               CHECK_INTERRUPT();                            \
552               if (write) {                                  \
553                   STORE_BANK0(ea, value);                   \
554                   STORE_BANK0(ea + 1, value >> 8);          \
555               } else {                                      \
556                   var = LOAD_BANK0(ea);                     \
557                   var |= LOAD_BANK0(ea + 1) << 8;           \
558               }                                             \
559           }                                                 \
560       }                                                     \
561       INC_PC(SIZE_1);                                       \
562   } while (0)
563 
564 /* $ff,x */
565 #define LOAD_DIRECT_PAGE_X_FUNC(var, bits8) DIRECT_PAGE_R_FUNC(var, 0, bits8, reg_x, 0)
566 
567 /* $ff,y */
568 #define LOAD_DIRECT_PAGE_Y_FUNC(var, bits8) DIRECT_PAGE_R_FUNC(var, 0, bits8, reg_y, 0)
569 
570 /* $ff,x wrapping */
571 #define LOAD_DIRECT_PAGE_X_FUNC_RRW(var, bits8)     \
572       unsigned int ea;                              \
573                                                     \
574       INC_PC(SIZE_1);                               \
575       p1 = FETCH_PARAM(reg_pc);                     \
576       DPR_DELAY                                     \
577       FETCH_PARAM_DUMMY(reg_pc);                    \
578       INC_PC(SIZE_1);                               \
579       if (reg_emul) {                               \
580           if (reg_dpr & 0xff) {                     \
581               ea = (p1 + reg_x + reg_dpr) & 0xffff; \
582           } else {                                  \
583               ea = ((p1 + reg_x) & 0xff) + reg_dpr; \
584           }                                         \
585           var = LOAD_LONG(ea);                      \
586           CHECK_INTERRUPT();                        \
587           STORE_LONG(ea, var);                      \
588       } else {                                      \
589           ea = (p1 + reg_dpr + reg_x) & 0xffff;     \
590           var = LOAD_LONG(ea);                      \
591           if (!bits8) {                             \
592               ea = (ea + 1) & 0xffff;               \
593               var |= LOAD_LONG(ea) << 8;            \
594           }                                         \
595           CHECK_INTERRUPT();                        \
596           LOAD_LONG_DUMMY(ea);                      \
597       }
598 
599 /* ($ff) no wrapping */
600 #define INDIRECT_FUNC(var, bits8, write)                      \
601   do {                                                        \
602       unsigned int ea, ea2;                                   \
603                                                               \
604       INC_PC(SIZE_1);                                         \
605       p1 = FETCH_PARAM(reg_pc);                               \
606       DPR_DELAY                                               \
607       INC_PC(SIZE_1);                                         \
608       ea2 = p1 + reg_dpr;                                     \
609       ea = LOAD_BANK0(ea2) | (reg_dbr << 16);                 \
610       if (!reg_emul || (reg_dpr & 0xff) || (p1 != 0xff)) {    \
611           if (bits8) {                                        \
612               CHECK_INTERRUPT();                              \
613               ea |= LOAD_BANK0(ea2 + 1) << 8;                 \
614               if (write) {                                    \
615                   STORE_LONG(ea, var);                        \
616               } else {                                        \
617                   var = LOAD_LONG(ea);                        \
618               }                                               \
619           } else {                                            \
620               ea |= LOAD_BANK0(ea2 + 1) << 8;                 \
621               CHECK_INTERRUPT();                              \
622               if (write) {                                    \
623                   STORE_LONG(ea, var);                        \
624                   STORE_LONG((ea + 1) & 0xffffff, var >> 8);  \
625               } else {                                        \
626                   var = LOAD_LONG(ea);                        \
627                   var |= LOAD_LONG((ea + 1) & 0xffffff) << 8; \
628               }                                               \
629           }                                                   \
630       } else {                                                \
631           CHECK_INTERRUPT();                                  \
632           ea |= LOAD_LONG(reg_dpr) << 8;                      \
633           if (write) {                                        \
634               STORE_LONG(ea, var);                            \
635           } else {                                            \
636               var = LOAD_LONG(ea);                            \
637           }                                                   \
638       }                                                       \
639   } while (0)
640 
641 /* ($ff) no wrapping */
642 #define LOAD_INDIRECT_FUNC(var, bits8) INDIRECT_FUNC(var, bits8, 0)
643 
644 /* ($ff,x) no wrapping */
645 #define INDIRECT_X_FUNC(var, bits8, write)                    \
646   do {                                                        \
647       unsigned int ea, ea2;                                   \
648                                                               \
649       INC_PC(SIZE_1);                                         \
650       p1 = FETCH_PARAM(reg_pc);                               \
651       DPR_DELAY                                               \
652       FETCH_PARAM_DUMMY(reg_pc);                              \
653       INC_PC(SIZE_1);                                         \
654       if (!reg_emul || (reg_dpr & 0xff)) {                    \
655           ea2 = p1 + reg_x + reg_dpr;                         \
656           ea = LOAD_BANK0(ea2) | (reg_dbr << 16);             \
657           if (bits8) {                                        \
658               CHECK_INTERRUPT();                              \
659               ea |= LOAD_BANK0(ea2 + 1) << 8;                 \
660               if (write) {                                    \
661                   STORE_LONG(ea, var);                        \
662               } else {                                        \
663                   var = LOAD_LONG(ea);                        \
664               }                                               \
665           } else {                                            \
666               ea |= LOAD_BANK0(ea2 + 1) << 8;                 \
667               CHECK_INTERRUPT();                              \
668               if (write) {                                    \
669                   STORE_LONG(ea, var);                        \
670                   STORE_LONG((ea + 1) & 0xffffff, var >> 8);  \
671               } else {                                        \
672                   var = LOAD_LONG(ea);                        \
673                   var |= LOAD_LONG((ea + 1) & 0xffffff) << 8; \
674               }                                               \
675           }                                                   \
676       } else {                                                \
677           ea2 = ((p1 + reg_x) & 0xff) + reg_dpr;              \
678           ea = LOAD_LONG(ea2) | (reg_dbr << 16);              \
679           CHECK_INTERRUPT();                                  \
680           ea2 = ((p1 + reg_x + 1) & 0xff) + reg_dpr;          \
681           ea |= LOAD_LONG(ea2) << 8;                          \
682           if (write) {                                        \
683               STORE_LONG(ea, var);                            \
684           } else {                                            \
685               var = LOAD_LONG(ea);                            \
686           }                                                   \
687       }                                                       \
688   } while (0)
689 
690 /* ($ff,x) no wrapping */
691 #define LOAD_INDIRECT_X_FUNC(var, bits8) INDIRECT_X_FUNC(var, bits8, 0)
692 
693 /* ($ff),y no wrapping */
694 #define INDIRECT_Y_FUNC(var, bits8, write)                            \
695   do {                                                                \
696       unsigned int ea, ea2;                                           \
697                                                                       \
698       INC_PC(SIZE_1);                                                 \
699       p1 = FETCH_PARAM(reg_pc);                                       \
700       DPR_DELAY                                                       \
701       INC_PC(SIZE_1);                                                 \
702       ea2 = p1 + reg_dpr;                                             \
703       ea = LOAD_BANK0(ea2);                                           \
704       if (!reg_emul || (reg_dpr & 0xff) || (p1 != 0xff)) {            \
705           if (bits8) {                                                \
706               if (write) {                                            \
707                   ea2 = (LOAD_BANK0(ea2 + 1) << 8) + (reg_dbr << 16); \
708                   CHECK_INTERRUPT();                                  \
709                   LOAD_LONG_DUMMY(((ea + reg_y) & 0xff) + ea2);       \
710                   ea = (ea + ea2 + reg_y) & 0xffffff;                 \
711                   STORE_LONG(ea, var);                                \
712               } else if (reg_y + ea > 0xff) {                         \
713                   ea |= LOAD_BANK0(ea2 + 1) << 8;                     \
714                   ea = (ea + reg_y + (reg_dbr << 16)) & 0xffffff;     \
715                   CHECK_INTERRUPT();                                  \
716                   LOAD_LONG_DUMMY((ea - 0x100) & 0xffffff);           \
717                   var = LOAD_LONG(ea);                                \
718               } else {                                                \
719                   CHECK_INTERRUPT();                                  \
720                   ea |= LOAD_BANK0(ea2 + 1) << 8;                     \
721                   ea = (ea + reg_y + (reg_dbr << 16)) & 0xffffff;     \
722                   var = LOAD_LONG(ea);                                \
723               }                                                       \
724           } else {                                                    \
725               if (write) {                                            \
726                   ea2 = (LOAD_BANK0(ea2 + 1) << 8) + (reg_dbr << 16); \
727                   LOAD_LONG_DUMMY(((ea + reg_y) & 0xff) + ea2);       \
728                   ea = (ea + ea2 + reg_y) & 0xffffff;                 \
729               } else if (reg_y + ea > 0xff) {                         \
730                   ea |= LOAD_BANK0(ea2 + 1) << 8;                     \
731                   ea = (ea + reg_y + (reg_dbr << 16)) & 0xffffff;     \
732                   LOAD_LONG_DUMMY((ea - 0x100) & 0xffffff);           \
733               } else {                                                \
734                   ea |= LOAD_BANK0(ea2 + 1) << 8;                     \
735                   ea = (ea + reg_y + (reg_dbr << 16)) & 0xffffff;     \
736               }                                                       \
737               CHECK_INTERRUPT();                                      \
738               if (write) {                                            \
739                   STORE_LONG(ea, var);                                \
740                   STORE_LONG((ea + 1) & 0xffffff, var >> 8);          \
741               } else {                                                \
742                   var = LOAD_LONG(ea);                                \
743                   var |= LOAD_LONG((ea + 1) & 0xffffff) << 8;         \
744               }                                                       \
745           }                                                           \
746       } else {                                                        \
747           if (write) {                                                \
748               ea2 = (LOAD_LONG(reg_dpr) << 8) + (reg_dbr << 16);      \
749               CHECK_INTERRUPT();                                      \
750               LOAD_LONG_DUMMY(((ea + reg_y) & 0xff) + ea2);           \
751               ea = (ea + ea2 + reg_y) & 0xffffff;                     \
752               STORE_LONG(ea, var);                                    \
753           } else if (reg_y + ea > 0xff) {                             \
754               ea |= LOAD_LONG(reg_dpr) << 8;                          \
755               CHECK_INTERRUPT();                                      \
756               ea = (ea + reg_y + (reg_dbr << 16)) & 0xffffff;         \
757               LOAD_LONG_DUMMY((ea - 0x100) & 0xffffff);               \
758               var = LOAD_LONG(ea);                                    \
759           } else {                                                    \
760               CHECK_INTERRUPT();                                      \
761               ea |= LOAD_LONG(reg_dpr) << 8;                          \
762               ea = (ea + reg_y + (reg_dbr << 16)) & 0xffffff;         \
763               var = LOAD_LONG(ea);                                    \
764           }                                                           \
765       }                                                               \
766   } while (0)
767 
768 /* ($ff),y no wrapping */
769 #define LOAD_INDIRECT_Y_FUNC(var, bits8) INDIRECT_Y_FUNC(var, bits8, 0)
770 
771 /* [$ff] no wrapping */
772 #define INDIRECT_LONG_FUNC(var, bits8, write)             \
773   do {                                                    \
774       unsigned int ea, ea2;                               \
775                                                           \
776       INC_PC(SIZE_1);                                     \
777       p1 = FETCH_PARAM(reg_pc);                           \
778       DPR_DELAY                                           \
779       ea2 = p1 + reg_dpr;                                 \
780       INC_PC(SIZE_1);                                     \
781       ea = LOAD_BANK0(ea2);                               \
782       ea |= LOAD_BANK0(ea2 + 1) << 8;                     \
783       if (bits8) {                                        \
784           CHECK_INTERRUPT();                              \
785           ea |= LOAD_BANK0(ea2 + 2) << 16;                \
786           if (write) {                                    \
787               STORE_LONG(ea, var);                        \
788           } else {                                        \
789               var = LOAD_LONG(ea);                        \
790           }                                               \
791       } else {                                            \
792           ea |= LOAD_BANK0(ea2 + 2) << 16;                \
793           CHECK_INTERRUPT();                              \
794           if (write) {                                    \
795               STORE_LONG(ea, var);                        \
796               STORE_LONG((ea + 1) & 0xffffff, var >> 8);  \
797           } else {                                        \
798               var = LOAD_LONG(ea);                        \
799               var |= LOAD_LONG((ea + 1) & 0xffffff) << 8; \
800           }                                               \
801       }                                                   \
802   } while (0)
803 
804 /* [$ff] no wrapping */
805 #define LOAD_INDIRECT_LONG_FUNC(var, bits8) INDIRECT_LONG_FUNC(var, bits8, 0)
806 
807 /* [$ff],y no wrapping */
808 #define INDIRECT_LONG_Y_FUNC(var, bits8, write)           \
809   do {                                                    \
810       unsigned int ea, ea2;                               \
811                                                           \
812       INC_PC(SIZE_1);                                     \
813       p1 = FETCH_PARAM(reg_pc);                           \
814       DPR_DELAY                                           \
815       ea2 = p1 + reg_dpr;                                 \
816       INC_PC(SIZE_1);                                     \
817       ea = LOAD_BANK0(ea2);                               \
818       ea |= LOAD_BANK0(ea2 + 1) << 8;                     \
819       if (bits8) {                                        \
820           CHECK_INTERRUPT();                              \
821           ea |= LOAD_BANK0(ea2 + 2) << 16;                \
822           ea = (ea + reg_y) & 0xffffff;                   \
823           if (write) {                                    \
824               STORE_LONG(ea, var);                        \
825           } else {                                        \
826               var = LOAD_LONG(ea);                        \
827           }                                               \
828       } else {                                            \
829           ea |= LOAD_BANK0(ea2 + 2) << 16;                \
830           CHECK_INTERRUPT();                              \
831           ea = (ea + reg_y) & 0xffffff;                   \
832           if (write) {                                    \
833               STORE_LONG(ea, var);                        \
834               STORE_LONG((ea + 1) & 0xffffff, var >> 8);  \
835           } else {                                        \
836               var = LOAD_LONG(ea);                        \
837               var |= LOAD_LONG((ea + 1) & 0xffffff) << 8; \
838           }                                               \
839       }                                                   \
840   } while (0)
841 
842 /* [$ff],y no wrapping */
843 #define LOAD_INDIRECT_LONG_Y_FUNC(var, bits8) INDIRECT_LONG_Y_FUNC(var, bits8, 0)
844 
845 /* $ffff no wrapping */
846 #define ABS_FUNC(var, value, bits8, write)                 \
847   do {                                                     \
848       unsigned int ea;                                     \
849                                                            \
850       INC_PC(SIZE_1);                                      \
851       p1 = FETCH_PARAM(reg_pc);                            \
852       INC_PC(SIZE_1);                                      \
853       if (bits8) {                                         \
854           CHECK_INTERRUPT();                               \
855           p2 = FETCH_PARAM(reg_pc) << 8;                   \
856           ea = p1 + p2 + (reg_dbr << 16);                  \
857           if (write) {                                     \
858               STORE_LONG(ea, value);                       \
859           } else {                                         \
860               var = LOAD_LONG(ea);                         \
861           }                                                \
862       } else {                                             \
863           p2 = FETCH_PARAM(reg_pc) << 8;                   \
864           CHECK_INTERRUPT();                               \
865           ea = p1 + p2 + (reg_dbr << 16);                  \
866           if (write) {                                     \
867               STORE_LONG(ea, value);                       \
868               STORE_LONG((ea + 1) & 0xffffff, value >> 8); \
869           } else {                                         \
870               var = LOAD_LONG(ea);                         \
871               var |= LOAD_LONG((ea + 1) & 0xffffff) << 8;  \
872           }                                                \
873       }                                                    \
874       INC_PC(SIZE_1);                                      \
875   } while (0)
876 
877 /* $ffff no wrapping */
878 #define LOAD_ABS_FUNC(var, bits8) ABS_FUNC(var, 0, bits8, 0)
879 
880 /* $ffff no wrapping */
881 #define LOAD_ABS_FUNC_RRW(var, bits8)    \
882       unsigned int ea;                   \
883                                          \
884       INC_PC(SIZE_1);                    \
885       p1 = FETCH_PARAM(reg_pc);          \
886       INC_PC(SIZE_1);                    \
887       p2 = FETCH_PARAM(reg_pc) << 8;     \
888       INC_PC(SIZE_1);                    \
889       ea = p1 + p2 + (reg_dbr << 16);    \
890       var = LOAD_LONG(ea);               \
891       if (reg_emul) {                    \
892           CHECK_INTERRUPT();             \
893           STORE_LONG(ea, var);           \
894       } else {                           \
895           if (!bits8) {                  \
896               ea = (ea + 1) & 0xffffff;  \
897               var |= LOAD_LONG(ea) << 8; \
898           }                              \
899           CHECK_INTERRUPT();             \
900           LOAD_LONG_DUMMY(ea);           \
901       }
902 
903 /* $ffff wrapping */
904 #define ABS2_FUNC(var, bits8, write)                                        \
905   do {                                                                      \
906       unsigned int ea;                                                      \
907                                                                             \
908       INC_PC(SIZE_1);                                                       \
909       p1 = FETCH_PARAM(reg_pc);                                             \
910       INC_PC(SIZE_1);                                                       \
911       if (bits8) {                                                          \
912           CHECK_INTERRUPT();                                                \
913           p2 = FETCH_PARAM(reg_pc) << 8;                                    \
914           ea = p1 + p2 + (reg_dbr << 16);                                   \
915           if (write) {                                                      \
916               STORE_LONG(ea, var);                                          \
917           } else {                                                          \
918               var = LOAD_LONG(ea);                                          \
919           }                                                                 \
920       } else {                                                              \
921           p2 = FETCH_PARAM(reg_pc) << 8;                                    \
922           ea = p1 + p2 + (reg_dbr << 16);                                   \
923           CHECK_INTERRUPT();                                                \
924           if (write) {                                                      \
925               STORE_LONG(ea, var);                                          \
926               STORE_LONG(((ea + 1) & 0xffff) + (reg_dbr << 16), var >> 8);  \
927           } else {                                                          \
928               var = LOAD_LONG(ea);                                          \
929               var |= LOAD_LONG(((ea + 1) & 0xffff) + (reg_dbr << 16)) << 8; \
930           }                                                                 \
931       }                                                                     \
932       INC_PC(SIZE_1);                                                       \
933   } while (0)
934 
935 /* $ffff wrapping */
936 #define LOAD_ABS2_FUNC(var, bits8) ABS2_FUNC(var, bits8, 0)
937 
938 /* $ffff wrapping */
939 #define LOAD_ABS2_FUNC_RRW(var, bits8)                    \
940       unsigned int ea;                                    \
941                                                           \
942       INC_PC(SIZE_1);                                     \
943       p1 = FETCH_PARAM(reg_pc);                           \
944       INC_PC(SIZE_1);                                     \
945       p2 = FETCH_PARAM(reg_pc) << 8;                      \
946       INC_PC(SIZE_1);                                     \
947       ea = p1 + p2 + (reg_dbr << 16);                     \
948       var = LOAD_LONG(ea);                                \
949       if (reg_emul) {                                     \
950           CHECK_INTERRUPT();                              \
951           STORE_LONG(ea, var);                            \
952       } else {                                            \
953           if (!bits8) {                                   \
954               ea = ((ea + 1) & 0xffff) + (reg_dbr << 16); \
955               var |= LOAD_LONG(ea) << 8;                  \
956           }                                               \
957           CHECK_INTERRUPT();                              \
958           LOAD_LONG_DUMMY(ea);                            \
959       }
960 
961 /* $ffff,r no wrapping */
962 #define ABS_R_FUNC(var, value, bits8, reg_r, write)                \
963   do {                                                             \
964       unsigned int ea;                                             \
965                                                                    \
966       INC_PC(SIZE_1);                                              \
967       p1 = FETCH_PARAM(reg_pc);                                    \
968       INC_PC(SIZE_1);                                              \
969       if (bits8) {                                                 \
970           if (write) {                                             \
971               p2 = FETCH_PARAM(reg_pc) << 8;                       \
972               ea = p2 + (reg_dbr << 16);                           \
973               CHECK_INTERRUPT();                                   \
974               LOAD_LONG_DUMMY(((p1 + reg_r) & 0xff) + ea);         \
975               ea = (p1 + reg_r + ea) & 0xffffff;                   \
976               STORE_LONG(ea, value);                               \
977           } else if (!LOCAL_65816_X() || (p1 + reg_r > 0xff)) {    \
978               p2 = FETCH_PARAM(reg_pc) << 8;                       \
979               ea = p2 + (reg_dbr << 16);                           \
980               CHECK_INTERRUPT();                                   \
981               LOAD_LONG_DUMMY(((p1 + reg_r) & 0xff) + ea);         \
982               ea = (p1 + reg_r + ea) & 0xffffff;                   \
983               var = LOAD_LONG(ea);                                 \
984           } else {                                                 \
985               CHECK_INTERRUPT();                                   \
986               p2 = FETCH_PARAM(reg_pc) << 8;                       \
987               ea = (p1 + p2 + reg_r + (reg_dbr << 16)) & 0xffffff; \
988               var = LOAD_LONG(ea);                                 \
989           }                                                        \
990       } else {                                                     \
991           p2 = FETCH_PARAM(reg_pc) << 8;                           \
992           ea = p2 + (reg_dbr << 16);                               \
993           if (write) {                                             \
994               LOAD_LONG_DUMMY(((p1 + reg_r) & 0xff) + ea);         \
995               CHECK_INTERRUPT();                                   \
996               ea = (p1 + reg_r + ea) & 0xffffff;                   \
997               STORE_LONG(ea, value);                               \
998               STORE_LONG((ea + 1) & 0xffffff, value >> 8);         \
999           } else {                                                 \
1000               if (!LOCAL_65816_X() || (p1 + reg_r > 0xff)) {       \
1001                   LOAD_LONG_DUMMY(((p1 + reg_r) & 0xff) + ea);     \
1002               }                                                    \
1003               CHECK_INTERRUPT();                                   \
1004               ea = (p1 + reg_r + ea) & 0xffffff;                   \
1005               var = LOAD_LONG(ea);                                 \
1006               var |= LOAD_LONG((ea + 1) & 0xffffff) << 8;          \
1007           }                                                        \
1008       }                                                            \
1009       INC_PC(SIZE_1);                                              \
1010   } while (0)
1011 
1012 /* $ffff,r no wrapping */
1013 #define LOAD_ABS_R_FUNC(var, bits8, reg_r) ABS_R_FUNC(var, 0, bits8, reg_r, 0)
1014 
1015 /* $ffff,x */
1016 #define LOAD_ABS_X_FUNC(var, bits8) \
1017     LOAD_ABS_R_FUNC(var, bits8, reg_x)
1018 
1019 /* $ffff,x */
1020 #define LOAD_ABS_Y_FUNC(var, bits8) \
1021     LOAD_ABS_R_FUNC(var, bits8, reg_y)
1022 
1023 /* $ffff,x no wrapping */
1024 #define LOAD_ABS_X_FUNC_RRW(var, bits8)                    \
1025       unsigned int ea;                                     \
1026                                                            \
1027       INC_PC(SIZE_1);                                      \
1028       p1 = FETCH_PARAM(reg_pc);                            \
1029       INC_PC(SIZE_1);                                      \
1030       p2 = FETCH_PARAM(reg_pc) << 8;                       \
1031       INC_PC(SIZE_1);                                      \
1032       ea = (p1 + p2 + reg_x + (reg_dbr << 16)) & 0xffffff; \
1033       LOAD_LONG_DUMMY(ea - ((p1 + reg_x) & 0x100));        \
1034       var = LOAD_LONG(ea);                                 \
1035       if (reg_emul) {                                      \
1036           CHECK_INTERRUPT();                               \
1037           STORE_LONG(ea, var);                             \
1038       } else {                                             \
1039           if (bits8) {                                     \
1040               CHECK_INTERRUPT();                           \
1041               LOAD_LONG_DUMMY(ea);                         \
1042           } else {                                         \
1043               ea = (ea + 1) & 0xffffff;                    \
1044               var |= LOAD_LONG(ea) << 8;                   \
1045               CHECK_INTERRUPT();                           \
1046               LOAD_LONG_DUMMY(ea);                         \
1047           }                                                                         \
1048       }
1049 
1050 /* $ffff,r wrapping */
1051 #define LOAD_ABS2_R_FUNC(var, bits8, reg_r)                                  \
1052   do {                                                                       \
1053       unsigned int ea;                                                       \
1054                                                                              \
1055       INC_PC(SIZE_1);                                                        \
1056       p1 = FETCH_PARAM(reg_pc);                                              \
1057       INC_PC(SIZE_1);                                                        \
1058       if (bits8) {                                                           \
1059           if (!LOCAL_65816_X() || ((p1 + reg_r) > 0xff)) {                   \
1060               p2 = FETCH_PARAM(reg_pc) << 8;                                 \
1061               CHECK_INTERRUPT();                                             \
1062               LOAD_LONG_DUMMY(((p1 + reg_r) & 0xff) + p2 + (reg_dbr << 16)); \
1063           } else {                                                           \
1064               CHECK_INTERRUPT();                                             \
1065               p2 = FETCH_PARAM(reg_pc) << 8;                                 \
1066           }                                                                  \
1067           ea = ((p1 + p2 + reg_r) & 0xffff) + (reg_dbr << 16);               \
1068           var = LOAD_LONG(ea);                                               \
1069       } else {                                                               \
1070           p2 = FETCH_PARAM(reg_pc) << 8;                                     \
1071           ea = ((p1 + p2 + reg_r) & 0xffff) + (reg_dbr << 16);               \
1072           if (!LOCAL_65816_X() || ((p1 + reg_r) > 0xff)) {                   \
1073               LOAD_LONG_DUMMY(ea - ((p1 + reg_r) & 0x100));                  \
1074           }                                                                  \
1075           CHECK_INTERRUPT();                                                 \
1076           var = LOAD_LONG(ea);                                               \
1077           var |= LOAD_LONG(((ea + 1) & 0xffff) + (reg_dbr << 16)) << 8;      \
1078       }                                                                      \
1079       INC_PC(SIZE_1);                                                        \
1080   } while (0)
1081 
1082 /* $ffff,x */
1083 #define LOAD_ABS2_X_FUNC(var, bits8) LOAD_ABS2_R_FUNC(var, bits8, reg_x)
1084 
1085 /* $ffff,y */
1086 #define LOAD_ABS2_Y_FUNC(var, bits8) LOAD_ABS2_R_FUNC(var, bits8, reg_y)
1087 
1088 /* $ffffff no wrapping */
1089 #define ABS_LONG_FUNC(var, bits8, write)                 \
1090   do {                                                   \
1091       unsigned int ea;                                   \
1092                                                          \
1093       INC_PC(SIZE_1);                                    \
1094       p1 = FETCH_PARAM(reg_pc);                          \
1095       INC_PC(SIZE_1);                                    \
1096       p2 = FETCH_PARAM(reg_pc) << 8;                     \
1097       INC_PC(SIZE_1);                                    \
1098       if (bits8) {                                       \
1099           CHECK_INTERRUPT();                             \
1100           p3 = FETCH_PARAM(reg_pc) << 16;                \
1101           ea = p1 + p2 + p3;                             \
1102           if (write) {                                   \
1103               STORE_LONG(ea, var);                       \
1104           } else {                                       \
1105               var = LOAD_LONG(ea);                       \
1106           }                                              \
1107       } else {                                           \
1108           p3 = FETCH_PARAM(reg_pc) << 16;                \
1109           CHECK_INTERRUPT();                             \
1110           ea = p1 + p2 + p3;                             \
1111           if (write) {                                   \
1112               STORE_LONG(ea, var);                       \
1113               STORE_LONG((ea + 1) & 0xffffff, var >> 8); \
1114           } else {                                       \
1115               var = LOAD_LONG(ea);                       \
1116               var |= LOAD_LONG((ea + 1) & 0xffffff) << 8;\
1117           }                                              \
1118       }                                                  \
1119       INC_PC(SIZE_1);                                    \
1120   } while (0)
1121 
1122 /* $ffffff no wrapping */
1123 #define LOAD_ABS_LONG_FUNC(var, bits8) ABS_LONG_FUNC(var, bits8, 0)
1124 
1125 /* $ffffff,x no wrapping */
1126 #define ABS_LONG_X_FUNC(var, bits8, write)                \
1127   do {                                                    \
1128       unsigned int ea;                                    \
1129                                                           \
1130       INC_PC(SIZE_1);                                     \
1131       p1 = FETCH_PARAM(reg_pc);                           \
1132       INC_PC(SIZE_1);                                     \
1133       p2 = FETCH_PARAM(reg_pc) << 8;                      \
1134       INC_PC(SIZE_1);                                     \
1135       if (bits8) {                                        \
1136           CHECK_INTERRUPT();                              \
1137           p3 = FETCH_PARAM(reg_pc) << 16;                 \
1138           ea = (p1 + p2 + p3 + reg_x) & 0xffffff;         \
1139           if (write) {                                    \
1140               STORE_LONG(ea, var);                        \
1141           } else {                                        \
1142               var = LOAD_LONG(ea);                        \
1143           }                                               \
1144       } else {                                            \
1145           p3 = FETCH_PARAM(reg_pc) << 16;                 \
1146           CHECK_INTERRUPT();                              \
1147           ea = (p1 + p2 + p3 + reg_x) & 0xffffff;         \
1148           if (write) {                                    \
1149               STORE_LONG(ea, var);                        \
1150               STORE_LONG((ea + 1) & 0xffffff, var >> 8);  \
1151           } else {                                        \
1152               var = LOAD_LONG(ea);                        \
1153               var |= LOAD_LONG((ea + 1) & 0xffffff) << 8; \
1154           }                                               \
1155       }                                                   \
1156       INC_PC(SIZE_1);                                     \
1157   } while (0)
1158 
1159 /* $ffffff no wrapping */
1160 #define LOAD_ABS_LONG_X_FUNC(var, bits8) ABS_LONG_X_FUNC(var, bits8, 0)
1161 
1162 /* $ff,s no wrapping */
1163 #define STACK_REL_FUNC(var, bits8, write)     \
1164   do {                                        \
1165       unsigned int ea;                        \
1166                                               \
1167       INC_PC(SIZE_1);                         \
1168       p1 = FETCH_PARAM(reg_pc);               \
1169       if (bits8) {                            \
1170           CHECK_INTERRUPT();                  \
1171           FETCH_PARAM_DUMMY(reg_pc);          \
1172           ea = p1 + reg_sp;                   \
1173           if (write) {                        \
1174               STORE_BANK0(ea, var);           \
1175           } else {                            \
1176               var = LOAD_BANK0(ea);           \
1177           }                                   \
1178       } else {                                \
1179           FETCH_PARAM_DUMMY(reg_pc);          \
1180           CHECK_INTERRUPT();                  \
1181           ea = p1 + reg_sp;                   \
1182           if (write) {                        \
1183               STORE_BANK0(ea, var);           \
1184               STORE_BANK0(ea + 1, var >> 8);  \
1185           } else {                            \
1186               var = LOAD_BANK0(ea);           \
1187               var |= LOAD_BANK0(ea + 1) << 8; \
1188           }                                   \
1189       }                                       \
1190       INC_PC(SIZE_1);                         \
1191   } while (0)
1192 
1193 #define LOAD_STACK_REL_FUNC(var, bits8) STACK_REL_FUNC(var, bits8, 0)
1194 
1195 /* ($ff,s),y no wrapping */
1196 #define STACK_REL_Y_FUNC(var, bits8, write)               \
1197   do {                                                    \
1198       unsigned int ea, ea2;                               \
1199                                                           \
1200       INC_PC(SIZE_1);                                     \
1201       p1 = FETCH_PARAM(reg_pc);                           \
1202       FETCH_PARAM_DUMMY(reg_pc);                          \
1203       INC_PC(SIZE_1);                                     \
1204       ea2 = p1 + reg_sp;                                  \
1205       ea = LOAD_BANK0(ea2);                               \
1206       ea |= LOAD_BANK0(ea2 + 1) << 8;                     \
1207       ea = (ea + reg_y + (reg_dbr << 16)) & 0xffffff;     \
1208       if (bits8) {                                        \
1209           CHECK_INTERRUPT();                              \
1210           LOAD_LONG_DUMMY((ea2 + 1) & 0xffff);            \
1211           if (write) {                                    \
1212               STORE_LONG(ea, var);                        \
1213           } else {                                        \
1214               var = LOAD_LONG(ea);                        \
1215           }                                               \
1216       } else {                                            \
1217           LOAD_LONG_DUMMY((ea2 + 1) & 0xffff);            \
1218           CHECK_INTERRUPT();                              \
1219           if (write) {                                    \
1220               STORE_LONG(ea, var);                        \
1221               STORE_LONG((ea + 1) & 0xffffff, var >> 8);  \
1222           } else {                                        \
1223               var = LOAD_LONG(ea);                        \
1224               var |= LOAD_LONG((ea + 1) & 0xffffff) << 8; \
1225           }                                               \
1226       }                                                   \
1227   } while (0)
1228 
1229 /* ($ff,s),y no wrapping */
1230 #define LOAD_STACK_REL_Y_FUNC(var, bits8) STACK_REL_Y_FUNC(var, bits8, 0)
1231 
1232 #define STORE_BANK0(addr, value) \
1233     STORE_LONG((addr) & 0xffff, value);
1234 
1235 /* s */
1236 #define STORE_STACK(value, bits8)    \
1237   do {                               \
1238       INC_PC(SIZE_1);                \
1239       if (bits8) {                   \
1240           CHECK_INTERRUPT();         \
1241           FETCH_PARAM_DUMMY(reg_pc); \
1242           PUSH(value);               \
1243       } else {                       \
1244           FETCH_PARAM_DUMMY(reg_pc); \
1245           CHECK_INTERRUPT();         \
1246           PUSH(value >> 8);          \
1247           PUSH(value);               \
1248       }                              \
1249   } while (0)
1250 
1251 /* a */
1252 #define STORE_ACCU_RRW(value, bits8) \
1253   do {                               \
1254       if (bits8) {                   \
1255           reg_a = value;             \
1256       } else {                       \
1257           reg_c = value;             \
1258       }                              \
1259   } while (0)
1260 
1261 /* $ff wrapping */
1262 #define STORE_DIRECT_PAGE(value, bits8) DIRECT_PAGE_FUNC(ea, value, bits8, 1)
1263 
1264 /* $ff wrapping */
1265 #define STORE_DIRECT_PAGE_RRW(value, bits8) \
1266   do {                                      \
1267       if (bits8) {                          \
1268           STORE_LONG(ea, value);            \
1269       } else {                              \
1270           STORE_LONG(ea, value >> 8);       \
1271           STORE_BANK0(ea - 1, value);       \
1272       }                                     \
1273   } while (0)
1274 
1275 /* $ff,x */
1276 #define STORE_DIRECT_PAGE_X(value, bits8) DIRECT_PAGE_R_FUNC(ea, value, bits8, reg_x, 1)
1277 
1278 /* $ff,y */
1279 #define STORE_DIRECT_PAGE_Y(value, bits8) DIRECT_PAGE_R_FUNC(ea, value, bits8, reg_y, 1)
1280 
1281 /* $ff,x wrapping */
1282 #define STORE_DIRECT_PAGE_X_RRW(value, bits8) STORE_DIRECT_PAGE_RRW(value, bits8)
1283 
1284 /* ($ff) no wrapping */
1285 #define STORE_INDIRECT(value, bits8) INDIRECT_FUNC(value, bits8, 1)
1286 
1287 /* ($ff,x) no wrapping */
1288 #define STORE_INDIRECT_X(value, bits8) INDIRECT_X_FUNC(value, bits8, 1)
1289 
1290 /* ($ff),y no wrapping */
1291 #define STORE_INDIRECT_Y(value, bits8) INDIRECT_Y_FUNC(value, bits8, 1)
1292 
1293 /* [$ff] no wrapping */
1294 #define STORE_INDIRECT_LONG(value, bits8) INDIRECT_LONG_FUNC(value, bits8, 1)
1295 
1296 /* [$ff],y no wrapping */
1297 #define STORE_INDIRECT_LONG_Y(value, bits8) INDIRECT_LONG_Y_FUNC(value, bits8, 1)
1298 
1299 /* $ffff no wrapping */
1300 #define STORE_ABS(value, bits8) ABS_FUNC(ea, value, bits8, 1)
1301 
1302 /* $ffff wrapping */
1303 #define STORE_ABS2(value, bits8) ABS2_FUNC(value, bits8, 1)
1304 
1305 /* $ffff no wrapping */
1306 #define STORE_ABS_RRW(value, bits8)               \
1307   do {                                            \
1308       if (bits8) {                                \
1309           STORE_LONG(ea, value);                  \
1310       } else {                                    \
1311           STORE_LONG(ea, value >> 8);             \
1312           STORE_LONG((ea - 1) & 0xffffff, value); \
1313       }                                           \
1314   } while (0)
1315 
1316 /* $ffff wrapping */
1317 #define STORE_ABS2_RRW(value, bits8)                                \
1318   do {                                                              \
1319       if (bits8) {                                                  \
1320           STORE_LONG(ea, value);                                    \
1321       } else {                                                      \
1322           STORE_LONG(ea, value >> 8);                               \
1323           STORE_LONG(((ea - 1) & 0xffff) + (reg_dbr << 16), value); \
1324       }                                                             \
1325   } while (0)
1326 
1327 /* $ffff,x no wrapping */
1328 #define STORE_ABS_X_RRW(value, bits8) STORE_ABS_RRW(value, bits8)
1329 
1330 /* $ffff,x */
1331 #define STORE_ABS_X(value, bits8) ABS_R_FUNC(ea, value, bits8, reg_x, 1)
1332 
1333 /* $ffff,y */
1334 #define STORE_ABS_Y(value, bits8) ABS_R_FUNC(ea, value, bits8, reg_y, 1)
1335 
1336 /* $ffffff no wrapping */
1337 #define STORE_ABS_LONG(value, bits8) ABS_LONG_FUNC(value, bits8, 1)
1338 
1339 /* $ffffff,x no wrapping */
1340 #define STORE_ABS_LONG_X(value, bits8) ABS_LONG_X_FUNC(value, bits8, 1)
1341 
1342 /* $ff,s no wrapping */
1343 #define STORE_STACK_REL(value, bits8) STACK_REL_FUNC(value, bits8, 1)
1344 
1345 /* ($ff,s),y no wrapping*/
1346 #define STORE_STACK_REL_Y(value, bits8) STACK_REL_Y_FUNC(value, bits8, 1)
1347 
1348 #define INC_PC(value)   (reg_pc = (reg_pc + (value)) & 0xffff)
1349 
1350 /* ------------------------------------------------------------------------- */
1351 
1352 /* Opcodes.  */
1353 
1354 /*
1355    A couple of caveats about PC:
1356 
1357    - the VIC-II emulation requires PC to be incremented before the first
1358      write access (this is not (very) important when writing to the zero
1359      page);
1360 
1361    - `p0', `p1' and `p2' can only be used *before* incrementing PC: some
1362      machines (eg. the C128) might depend on this.
1363 */
1364 
1365 #define ADC(load_func)                                                       \
1366   do {                                                                       \
1367       unsigned int tmp_value;                                                \
1368       unsigned int tmp, tmp2;                                                \
1369                                                                              \
1370       tmp = LOCAL_CARRY();                                                   \
1371       if (LOCAL_65816_M()) {                                                 \
1372           load_func(tmp_value, 1);                                           \
1373           if (LOCAL_DECIMAL()) {                                             \
1374               tmp2  = (reg_a & 0x0f) + (tmp_value & 0x0f) + tmp;             \
1375               tmp = (reg_a & 0xf0) + (tmp_value & 0xf0);                     \
1376               if (tmp2 > 0x9) {                                              \
1377                   tmp2 += 0x6;                                               \
1378                   tmp += 0x10;                                               \
1379               }                                                              \
1380               tmp |= (tmp2 & 0xf);                                           \
1381               LOCAL_SET_OVERFLOW(~(reg_a ^ tmp_value) & (reg_a ^ tmp) & 0x80);\
1382               if (tmp > 0x9f) {                                              \
1383                   tmp += 0x60;                                               \
1384               }                                                              \
1385           } else {                                                           \
1386               tmp += tmp_value + reg_a;                                      \
1387               LOCAL_SET_OVERFLOW(~(reg_a ^ tmp_value) & (reg_a ^ tmp) & 0x80);\
1388           }                                                                  \
1389           LOCAL_SET_CARRY(tmp > 0xff);                                       \
1390           LOCAL_SET_NZ(tmp, 1);                                              \
1391           reg_a = tmp;                                                       \
1392       } else {                                                               \
1393           load_func(tmp_value, 0);                                           \
1394           if (LOCAL_DECIMAL()) {                                             \
1395               tmp2 = (reg_c & 0x000f) + (tmp_value & 0x000f) + tmp;          \
1396               tmp = (reg_c & 0x00f0) + (tmp_value & 0x00f0);                 \
1397               if (tmp2 > 0x9) {                                              \
1398                   tmp2 += 0x6;                                               \
1399                   tmp += 0x10;                                               \
1400               }                                                              \
1401               tmp |= (tmp2 & 0xf);                                           \
1402               tmp2 = (reg_c & 0x0f00) + (tmp_value & 0x0f00);                \
1403               if (tmp > 0x9f) {                                              \
1404                   tmp += 0x60;                                               \
1405                   tmp2 += 0x100;                                             \
1406               }                                                              \
1407               tmp2 |= (tmp & 0xff);                                          \
1408               tmp = (reg_c & 0xf000) + (tmp_value & 0xf000);                 \
1409               if (tmp2 > 0x9ff) {                                            \
1410                   tmp2 += 0x600;                                             \
1411                   tmp += 0x1000;                                             \
1412               }                                                              \
1413               tmp |= (tmp2 & 0xfff);                                         \
1414               LOCAL_SET_OVERFLOW(~(reg_a ^ tmp_value) & (reg_a ^ tmp) & 0x8000);\
1415               if (tmp > 0x9fff) {                                            \
1416                   tmp += 0x6000;                                             \
1417               }                                                              \
1418           } else {                                                           \
1419               tmp += tmp_value + reg_c;                                      \
1420               LOCAL_SET_OVERFLOW(~(reg_c ^ tmp_value) & (reg_c ^ tmp) & 0x8000);\
1421           }                                                                  \
1422           LOCAL_SET_CARRY(tmp > 0xffff);                                     \
1423           LOCAL_SET_NZ(tmp, 0);                                              \
1424           reg_c = tmp;                                                       \
1425       }                                                                      \
1426   } while (0)
1427 
1428 #define LOGICAL(load_func, logic) \
1429   do {                            \
1430       unsigned int tmp;           \
1431                                   \
1432       if (LOCAL_65816_M()) {      \
1433           load_func(tmp, 1);      \
1434           reg_a logic (uint8_t)tmp;  \
1435           LOCAL_SET_NZ(reg_a, 1); \
1436       } else {                    \
1437           load_func(tmp, 0);      \
1438           reg_c logic (uint16_t)tmp;  \
1439           LOCAL_SET_NZ(reg_c, 0); \
1440       }                           \
1441   } while (0)
1442 
1443 #define AND(load_func) LOGICAL(load_func, &=)
1444 
1445 #define ASLROL(load_func, store_func, carry) \
1446   do {                                       \
1447       unsigned int tmp;                      \
1448                                              \
1449       if (LOCAL_65816_M()) {                 \
1450           load_func(tmp, 1);                 \
1451           tmp = (tmp << 1) | carry;          \
1452           LOCAL_SET_CARRY(tmp & 0x100);      \
1453           LOCAL_SET_NZ(tmp, 1);              \
1454           store_func(tmp, 1);                \
1455       } else {                               \
1456           load_func(tmp, 0);                 \
1457           tmp = (tmp << 1) | carry;          \
1458           LOCAL_SET_CARRY(tmp & 0x10000);    \
1459           LOCAL_SET_NZ(tmp, 0);              \
1460           store_func(tmp, 0);                \
1461       }                                      \
1462   } while (0)
1463 
1464 #define ASL(load_func, store_func) ASLROL(load_func, store_func, 0)
1465 
1466 #define BIT_IMM(load_func)                      \
1467   do {                                          \
1468       unsigned int tmp_value;                   \
1469                                                 \
1470       if (LOCAL_65816_M()) {                    \
1471           load_func(tmp_value, 1);              \
1472           LOCAL_SET_ZERO(!(tmp_value & reg_a)); \
1473       } else {                                  \
1474           load_func(tmp_value, 0);              \
1475           LOCAL_SET_ZERO(!(tmp_value & reg_c)); \
1476       }                                         \
1477   } while (0)
1478 
1479 #define BIT(load_func)                      \
1480   do {                                      \
1481       unsigned int tmp;                     \
1482                                             \
1483       if (LOCAL_65816_M()) {                \
1484           load_func(tmp, 1);                \
1485           LOCAL_SET_SIGN(tmp & 0x80);       \
1486           LOCAL_SET_OVERFLOW(tmp & 0x40);   \
1487           LOCAL_SET_ZERO(!(tmp & reg_a));   \
1488       } else {                              \
1489           load_func(tmp, 0);                \
1490           LOCAL_SET_SIGN(tmp & 0x8000);     \
1491           LOCAL_SET_OVERFLOW(tmp & 0x4000); \
1492           LOCAL_SET_ZERO(!(tmp & reg_c));   \
1493       }                                     \
1494   } while (0)
1495 
1496 #define BRANCH(cond)                                         \
1497   do {                                                       \
1498       unsigned int dest_addr;                                \
1499       INC_PC(SIZE_1);                                        \
1500                                                              \
1501       if (cond) {                                            \
1502           CHECK_INTERRUPT();                                 \
1503           p1 = FETCH_PARAM(reg_pc);                          \
1504           INC_PC(SIZE_1);                                    \
1505           dest_addr = (reg_pc + (signed char)(p1)) & 0xffff; \
1506                                                              \
1507           if (((reg_pc ^ dest_addr) & ~0xff) && reg_emul) {  \
1508               CHECK_INTERRUPT();                             \
1509               FETCH_PARAM_DUMMY(reg_pc);                     \
1510               FETCH_PARAM_DUMMY(dest_addr);                  \
1511           } else {                                           \
1512               FETCH_PARAM_DUMMY(reg_pc);                     \
1513           }                                                  \
1514           reg_pc = dest_addr;                                \
1515           JUMP(reg_pc);                                      \
1516       } else {                                               \
1517           p1 = FETCH_PARAM(reg_pc);                          \
1518           INC_PC(SIZE_1);                                    \
1519       }                                                      \
1520   } while (0)
1521 
1522 #define BRANCH_LONG()                \
1523   do {                               \
1524       INC_PC(SIZE_1);                \
1525       p1 = FETCH_PARAM(reg_pc);      \
1526       INC_PC(SIZE_1);                \
1527       CHECK_INTERRUPT();             \
1528       p2 = FETCH_PARAM(reg_pc) << 8; \
1529       FETCH_PARAM_DUMMY(reg_pc);     \
1530       INC_PC(p1 + p2 + 1);           \
1531       JUMP(reg_pc);                  \
1532   } while (0)
1533 
1534 #define BRK()                         \
1535   do {                                \
1536       EXPORT_REGISTERS();             \
1537       TRACE_BRK();                    \
1538       INC_PC(SIZE_1);                 \
1539       p1 = FETCH_PARAM(reg_pc);       \
1540       INC_PC(SIZE_1);                 \
1541       if (reg_emul) {                 \
1542           LOCAL_SET_BREAK(1);         \
1543           PUSH(reg_pc >> 8);          \
1544           PUSH(reg_pc);               \
1545           PUSH(LOCAL_STATUS());       \
1546           LOCAL_SET_DECIMAL(0);       \
1547           LOCAL_SET_INTERRUPT(1);     \
1548           CHECK_INTERRUPT();          \
1549           LOAD_INT_ADDR(0xfffe);      \
1550       } else {                        \
1551           PUSH(reg_pbr);              \
1552           PUSH(reg_pc >> 8);          \
1553           PUSH(reg_pc);               \
1554           PUSH(LOCAL_65816_STATUS()); \
1555           LOCAL_SET_DECIMAL(0);       \
1556           LOCAL_SET_INTERRUPT(1);     \
1557           CHECK_INTERRUPT();          \
1558           LOAD_INT_ADDR(0xffe6);      \
1559       }                               \
1560       reg_pbr = 0;                    \
1561       JUMP(reg_pc);                   \
1562   } while (0)
1563 
1564 #define CLC()                    \
1565   do {                           \
1566       INC_PC(SIZE_1);            \
1567       FETCH_PARAM_DUMMY(reg_pc); \
1568       LOCAL_SET_CARRY(0);        \
1569   } while (0)
1570 
1571 #define CLD()                    \
1572   do {                           \
1573       INC_PC(SIZE_1);            \
1574       FETCH_PARAM_DUMMY(reg_pc); \
1575       LOCAL_SET_DECIMAL(0);      \
1576   } while (0)
1577 
1578 #define CLI()                    \
1579   do {                           \
1580       INC_PC(SIZE_1);            \
1581       FETCH_PARAM_DUMMY(reg_pc); \
1582       LOCAL_SET_INTERRUPT(0);    \
1583   } while (0)
1584 
1585 #define CLV()                    \
1586   do {                           \
1587       INC_PC(SIZE_1);            \
1588       FETCH_PARAM_DUMMY(reg_pc); \
1589       LOCAL_SET_OVERFLOW(0);     \
1590   } while (0)
1591 
1592 #define CMP(load_func)                    \
1593   do {                                    \
1594       unsigned int tmp;                   \
1595       unsigned int value;                 \
1596                                           \
1597       if (LOCAL_65816_M()) {              \
1598           load_func(value, 1);            \
1599           tmp = reg_a - value;            \
1600           LOCAL_SET_CARRY(tmp < 0x100);   \
1601           LOCAL_SET_NZ(tmp, 1);           \
1602       } else {                            \
1603           load_func(value, 0);            \
1604           tmp = reg_c - value;            \
1605           LOCAL_SET_CARRY(tmp < 0x10000); \
1606           LOCAL_SET_NZ(tmp, 0);           \
1607       }                                   \
1608   } while (0)
1609 
1610 #define CMPI(load_func, reg_r)            \
1611   do {                                    \
1612       unsigned int tmp;                   \
1613       unsigned int value;                 \
1614                                           \
1615       if (LOCAL_65816_X()) {              \
1616           load_func(value, 1);            \
1617           tmp = reg_r - value;            \
1618           LOCAL_SET_CARRY(tmp < 0x100);   \
1619           LOCAL_SET_NZ(tmp, 1);           \
1620       } else {                            \
1621           load_func(value, 0);            \
1622           tmp = reg_r - value;            \
1623           LOCAL_SET_CARRY(tmp < 0x10000); \
1624           LOCAL_SET_NZ(tmp, 0);           \
1625       }                                   \
1626   } while (0)
1627 
1628 #define COP()                         \
1629   do {                                \
1630       EXPORT_REGISTERS();             \
1631       TRACE_COP();                    \
1632       INC_PC(SIZE_1);                 \
1633       p1 = FETCH_PARAM(reg_pc);       \
1634       INC_PC(SIZE_1);                 \
1635       if (reg_emul) {                 \
1636           LOCAL_SET_BREAK(1);         \
1637           PUSH(reg_pc >> 8);          \
1638           PUSH(reg_pc);               \
1639           PUSH(LOCAL_STATUS());       \
1640           LOCAL_SET_DECIMAL(0);       \
1641           LOCAL_SET_INTERRUPT(1);     \
1642           CHECK_INTERRUPT();          \
1643           LOAD_INT_ADDR(0xfff4);      \
1644       } else {                        \
1645           PUSH(reg_pbr);              \
1646           PUSH(reg_pc >> 8);          \
1647           PUSH(reg_pc);               \
1648           PUSH(LOCAL_65816_STATUS()); \
1649           LOCAL_SET_DECIMAL(0);       \
1650           LOCAL_SET_INTERRUPT(1);     \
1651           CHECK_INTERRUPT();          \
1652           LOAD_INT_ADDR(0xffe4);      \
1653       }                               \
1654       reg_pbr = 0;                    \
1655       JUMP(reg_pc);                   \
1656   } while (0)
1657 
1658 #define CPX(load_func) CMPI(load_func, reg_x)
1659 
1660 #define CPY(load_func) CMPI(load_func, reg_y)
1661 
1662 #define INCDEC(load_func, store_func, logic) \
1663   do {                                       \
1664       unsigned int tmp;                      \
1665                                              \
1666       if (LOCAL_65816_M()) {                 \
1667           load_func(tmp, 1);                 \
1668           tmp logic;                         \
1669           LOCAL_SET_NZ(tmp, 1);              \
1670           store_func(tmp, 1);                \
1671       } else {                               \
1672           load_func(tmp, 0);                 \
1673           tmp logic;                         \
1674           LOCAL_SET_NZ(tmp, 0);              \
1675           store_func(tmp, 0);                \
1676       }                                      \
1677   } while (0)
1678 
1679 #define DEC(load_func, store_func) INCDEC(load_func, store_func, --)
1680 
1681 #define INCDECI(reg_r, logic)     \
1682   do {                            \
1683       INC_PC(SIZE_1);             \
1684       FETCH_PARAM_DUMMY(reg_pc);  \
1685       reg_r logic;                \
1686       if (LOCAL_65816_X()) {      \
1687           reg_r &= 0xff;          \
1688           LOCAL_SET_NZ(reg_r, 1); \
1689       } else {                    \
1690           LOCAL_SET_NZ(reg_r, 0); \
1691       }                           \
1692   } while (0)
1693 
1694 #define DEX() INCDECI(reg_x, --)
1695 
1696 #define DEY() INCDECI(reg_y, --)
1697 
1698 #define EOR(load_func) LOGICAL(load_func, ^=)
1699 
1700 #define INC(load_func, store_func) INCDEC(load_func, store_func, ++)
1701 
1702 #define INX() INCDECI(reg_x, ++)
1703 
1704 #define INY() INCDECI(reg_y, ++)
1705 
1706 /* The 0x02 COP opcode is also used to patch the ROM.  The function trap_handler()
1707    returns nonzero if this is not a patch, but a `real' NOP instruction. */
1708 
1709 #define COP_02()                                                \
1710   do {                                                          \
1711       uint32_t trap_result;                                        \
1712       EXPORT_REGISTERS();                                       \
1713       if (!ROM_TRAP_ALLOWED()                                   \
1714           || (trap_result = ROM_TRAP_HANDLER()) == (uint32_t)-1) { \
1715           COP_65816(p1);                                        \
1716       } else {                                                  \
1717           if (trap_result) {                                    \
1718              SET_OPCODE(trap_result & 0xff);                    \
1719              IMPORT_REGISTERS();                                \
1720              goto trap_skipped;                                 \
1721           } else {                                              \
1722              IMPORT_REGISTERS();                                \
1723           }                                                     \
1724       }                                                         \
1725   } while (0)
1726 
1727 #define IRQ()                                 \
1728   do {                                        \
1729       TRACE_IRQ();                            \
1730       if (monitor_mask[CALLER] & (MI_STEP)) { \
1731           monitor_check_icount_interrupt();   \
1732       }                                       \
1733       interrupt_ack_irq(CPU_INT_STATUS);      \
1734       FETCH_PARAM(reg_pc);                    \
1735       FETCH_PARAM_DUMMY(reg_pc);              \
1736       if (reg_emul) {                         \
1737           LOCAL_SET_BREAK(0);                 \
1738           PUSH(reg_pc >> 8);                  \
1739           PUSH(reg_pc);                       \
1740           PUSH(LOCAL_STATUS());               \
1741           LOCAL_SET_INTERRUPT(1);             \
1742           LOCAL_SET_DECIMAL(0);               \
1743           CHECK_INTERRUPT();                  \
1744           LOAD_INT_ADDR(0xfffe);              \
1745       } else {                                \
1746           PUSH(reg_pbr);                      \
1747           PUSH(reg_pc >> 8);                  \
1748           PUSH(reg_pc);                       \
1749           PUSH(LOCAL_65816_STATUS());         \
1750           LOCAL_SET_INTERRUPT(1);             \
1751           LOCAL_SET_DECIMAL(0);               \
1752           CHECK_INTERRUPT();                  \
1753           LOAD_INT_ADDR(0xffee);              \
1754       }                                       \
1755       reg_pbr = 0;                            \
1756       JUMP(reg_pc);                           \
1757   } while (0)
1758 
1759 #define JMP()                        \
1760   do {                               \
1761       INC_PC(SIZE_1);                \
1762       CHECK_INTERRUPT();             \
1763       p1 = FETCH_PARAM(reg_pc);      \
1764       INC_PC(SIZE_1);                \
1765       p2 = FETCH_PARAM(reg_pc) << 8; \
1766       reg_pc = p1 + p2;              \
1767       JUMP(reg_pc);                  \
1768   } while (0)
1769 
1770 #define JMP_IND()                        \
1771   do {                                   \
1772       unsigned int ea;                   \
1773                                          \
1774       INC_PC(SIZE_1);                    \
1775       p1 = FETCH_PARAM(reg_pc);          \
1776       INC_PC(SIZE_1);                    \
1777       p2 = FETCH_PARAM(reg_pc) << 8;     \
1778       ea = p1 + p2;                      \
1779       CHECK_INTERRUPT();                 \
1780       reg_pc = LOAD_LONG(ea);            \
1781       reg_pc |= LOAD_BANK0(ea + 1) << 8; \
1782       JUMP(reg_pc);                      \
1783   } while (0)
1784 
1785 #define JMP_IND_LONG()                   \
1786   do {                                   \
1787       unsigned int ea;                   \
1788                                          \
1789       INC_PC(SIZE_1);                    \
1790       p1 = FETCH_PARAM(reg_pc);          \
1791       INC_PC(SIZE_1);                    \
1792       p2 = FETCH_PARAM(reg_pc) << 8;     \
1793       ea = p1 + p2;                      \
1794       reg_pc = LOAD_LONG(ea);            \
1795       CHECK_INTERRUPT();                 \
1796       reg_pc |= LOAD_BANK0(ea + 1) << 8; \
1797       reg_pbr = LOAD_BANK0(ea + 2);      \
1798       JUMP(reg_pc);                      \
1799   } while (0)
1800 
1801 #define JMP_IND_X()                                  \
1802   do {                                               \
1803       unsigned int ea;                               \
1804                                                      \
1805       INC_PC(SIZE_1);                                \
1806       p1 = FETCH_PARAM(reg_pc);                      \
1807       INC_PC(SIZE_1);                                \
1808       p2 = FETCH_PARAM(reg_pc) << 8;                 \
1809       ea = (p1 + p2 + reg_x) & 0xffff;               \
1810       FETCH_PARAM_DUMMY(reg_pc);                     \
1811       CHECK_INTERRUPT();                             \
1812       reg_pc = FETCH_PARAM(ea);                      \
1813       reg_pc |= FETCH_PARAM((ea + 1) & 0xffff) << 8; \
1814       JUMP(reg_pc);                                  \
1815   } while (0)
1816 
1817 #define JMP_LONG()                   \
1818   do {                               \
1819       INC_PC(SIZE_1);                \
1820       p1 = FETCH_PARAM(reg_pc);      \
1821       INC_PC(SIZE_1);                \
1822       CHECK_INTERRUPT();             \
1823       p2 = FETCH_PARAM(reg_pc) << 8; \
1824       INC_PC(SIZE_1);                \
1825       reg_pbr = FETCH_PARAM(reg_pc); \
1826       p3 = reg_pbr << 16;            \
1827       reg_pc = p1 + p2;              \
1828       JUMP(reg_pc);                  \
1829   } while (0)
1830 
1831 #define JSR()                        \
1832   do {                               \
1833       INC_PC(SIZE_1);                \
1834       p1 = FETCH_PARAM(reg_pc);      \
1835       INC_PC(SIZE_1);                \
1836       p2 = FETCH_PARAM(reg_pc) << 8; \
1837       FETCH_PARAM_DUMMY(reg_pc);     \
1838       CHECK_INTERRUPT();             \
1839       PUSH(reg_pc >> 8);             \
1840       PUSH(reg_pc);                  \
1841       reg_pc = p1 + p2;              \
1842       JUMP(reg_pc);                  \
1843   } while (0)
1844 
1845 #define JSR_IND_X()                                  \
1846   do {                                               \
1847       unsigned int ea;                               \
1848                                                      \
1849       INC_PC(SIZE_1);                                \
1850       p1 = FETCH_PARAM(reg_pc);                      \
1851       INC_PC(SIZE_1);                                \
1852       STORE_LONG(reg_sp, reg_pc >> 8);               \
1853       reg_sp--;                                      \
1854       PUSH(reg_pc);                                  \
1855       p2 = FETCH_PARAM(reg_pc) << 8;                 \
1856       ea = (p1 + p2 + reg_x) & 0xffff;               \
1857       FETCH_PARAM_DUMMY(reg_pc);                     \
1858       CHECK_INTERRUPT();                             \
1859       reg_pc = FETCH_PARAM(ea);                      \
1860       reg_pc |= FETCH_PARAM((ea + 1) & 0xffff) << 8; \
1861       JUMP(reg_pc);                                  \
1862   } while (0)
1863 
1864 #define JSR_LONG()                     \
1865   do {                                 \
1866       INC_PC(SIZE_1);                  \
1867       p1 = FETCH_PARAM(reg_pc);        \
1868       INC_PC(SIZE_1);                  \
1869       p2 = FETCH_PARAM(reg_pc) << 8;   \
1870       INC_PC(SIZE_1);                  \
1871       STORE_LONG(reg_sp, reg_pbr);     \
1872       LOAD_LONG_DUMMY(reg_sp);         \
1873       reg_sp--;                        \
1874       reg_pbr = FETCH_PARAM(reg_pc);   \
1875       p3 = reg_pbr << 16;              \
1876       CHECK_INTERRUPT();               \
1877       STORE_LONG(reg_sp, reg_pc >> 8); \
1878       reg_sp--;                        \
1879       PUSH(reg_pc);                    \
1880       reg_pc = p1 + p2;                \
1881       JUMP(reg_pc);                    \
1882   } while (0)
1883 
1884 #define LDA(load_func) LOGICAL(load_func, =)
1885 
1886 #define LDI(load_func, reg_r)     \
1887   do {                            \
1888       unsigned int value;         \
1889                                   \
1890       if (LOCAL_65816_X()) {      \
1891           load_func(value, 1);    \
1892           reg_r = value;          \
1893           LOCAL_SET_NZ(reg_r, 1); \
1894       } else {                    \
1895           load_func(value, 0);    \
1896           reg_r = value;          \
1897           LOCAL_SET_NZ(reg_r, 0); \
1898       }                           \
1899   } while (0)
1900 
1901 #define LDX(load_func) LDI(load_func, reg_x)
1902 
1903 #define LDY(load_func) LDI(load_func, reg_y)
1904 
1905 #define LSRROR(load_func, store_func, carry) \
1906   do {                                       \
1907       unsigned int tmp;                      \
1908                                              \
1909       if (LOCAL_65816_M()) {                 \
1910           load_func(tmp, 1);                 \
1911           tmp |= carry ? 0x100 : 0;          \
1912           LOCAL_SET_CARRY(tmp & 1);          \
1913           tmp >>= 1;                         \
1914           LOCAL_SET_NZ(tmp, 1);              \
1915           store_func(tmp, 1);                \
1916       } else {                               \
1917           load_func(tmp, 0);                 \
1918           tmp |= carry ? 0x10000 : 0;        \
1919           LOCAL_SET_CARRY(tmp & 1);          \
1920           tmp >>= 1;                         \
1921           LOCAL_SET_NZ(tmp, 0);              \
1922           store_func(tmp, 0);                \
1923       }                                      \
1924   } while (0)
1925 
1926 #define LSR(load_func, store_func) LSRROR(load_func, store_func, 0)
1927 
1928 #define MOVE(logic)                             \
1929   do {                                          \
1930       unsigned int tmp;                         \
1931                                                 \
1932       if (reg_c == 0) {                         \
1933           INC_PC(SIZE_1);                       \
1934           p1 = FETCH_PARAM(reg_pc);             \
1935           INC_PC(SIZE_1);                       \
1936           reg_dbr = FETCH_PARAM(reg_pc);        \
1937           INC_PC(SIZE_1);                       \
1938       } else {                                  \
1939           p1 = FETCH_PARAM(reg_pc + 1);         \
1940           reg_dbr = FETCH_PARAM(reg_pc + 2);    \
1941       }                                         \
1942       p2 = reg_dbr << 8;                        \
1943       tmp = LOAD_LONG(reg_x + (reg_dbr << 16)); \
1944       reg_dbr = p1;                             \
1945       STORE_LONG(reg_y + (reg_dbr << 16), tmp); \
1946       LOAD_LONG_DUMMY(reg_y + (reg_dbr << 16)); \
1947       LOAD_LONG_DUMMY(reg_y + (reg_dbr << 16)); \
1948       reg_x logic;                              \
1949       reg_y logic;                              \
1950       if (LOCAL_65816_X()) {                    \
1951           reg_x &= 0xff;                        \
1952           reg_y &= 0xff;                        \
1953       }                                         \
1954       reg_c--;                                  \
1955   } while (0)
1956 
1957 #define MVN() MOVE(++)
1958 
1959 #define MVP() MOVE(--)
1960 
1961 #define NMI()                                 \
1962   do {                                        \
1963       TRACE_NMI();                            \
1964       if (monitor_mask[CALLER] & (MI_STEP)) { \
1965           monitor_check_icount_interrupt();   \
1966       }                                       \
1967       interrupt_ack_nmi(CPU_INT_STATUS);      \
1968       FETCH_PARAM(reg_pc);                    \
1969       FETCH_PARAM_DUMMY(reg_pc);              \
1970       if (reg_emul) {                         \
1971           LOCAL_SET_BREAK(0);                 \
1972           PUSH(reg_pc >> 8);                  \
1973           PUSH(reg_pc);                       \
1974           PUSH(LOCAL_STATUS());               \
1975           LOCAL_SET_INTERRUPT(1);             \
1976           LOCAL_SET_DECIMAL(0);               \
1977           CHECK_INTERRUPT();                  \
1978           LOAD_INT_ADDR(0xfffa);              \
1979       } else {                                \
1980           PUSH(reg_pbr);                      \
1981           PUSH(reg_pc >> 8);                  \
1982           PUSH(reg_pc);                       \
1983           PUSH(LOCAL_65816_STATUS());         \
1984           LOCAL_SET_INTERRUPT(1);             \
1985           LOCAL_SET_DECIMAL(0);               \
1986           CHECK_INTERRUPT();                  \
1987           LOAD_INT_ADDR(0xffea);              \
1988       }                                       \
1989       reg_pbr = 0;                            \
1990       JUMP(reg_pc);                           \
1991   } while (0)
1992 
1993 #define NOP()                    \
1994   do {                           \
1995       INC_PC(SIZE_1);            \
1996       FETCH_PARAM_DUMMY(reg_pc); \
1997   } while (0)
1998 
1999 #define ORA(load_func) LOGICAL(load_func, |=)
2000 
2001 #define PEA()                        \
2002   do {                               \
2003       INC_PC(SIZE_1);                \
2004       p1 = FETCH_PARAM(reg_pc);      \
2005       INC_PC(SIZE_1);                \
2006       p2 = FETCH_PARAM(reg_pc) << 8; \
2007       INC_PC(SIZE_1);                \
2008       CHECK_INTERRUPT();             \
2009       STORE_LONG(reg_sp, p2 >> 8);   \
2010       reg_sp--;                      \
2011       PUSH(p1);                      \
2012   } while (0)
2013 
2014 #define PEI()                           \
2015   do {                                  \
2016       unsigned int value, ea;           \
2017                                         \
2018       INC_PC(SIZE_1);                   \
2019       p1 = FETCH_PARAM(reg_pc);         \
2020       DPR_DELAY                         \
2021       INC_PC(SIZE_1);                   \
2022       ea = p1 + reg_dpr;                \
2023       value = LOAD_BANK0(ea);           \
2024       value |= LOAD_BANK0(ea + 1) << 8; \
2025       CHECK_INTERRUPT();                \
2026       STORE_LONG(reg_sp, value >> 8);   \
2027       reg_sp--;                         \
2028       PUSH(value);                      \
2029   } while (0)
2030 
2031 #define PER()                             \
2032   do {                                    \
2033       unsigned int dest_addr;             \
2034       INC_PC(SIZE_1);                     \
2035       p1 = FETCH_PARAM(reg_pc);           \
2036       INC_PC(SIZE_1);                     \
2037       p2 = FETCH_PARAM(reg_pc) << 8;      \
2038       FETCH_PARAM_DUMMY(reg_pc);          \
2039       INC_PC(SIZE_1);                     \
2040                                           \
2041       dest_addr = reg_pc + p1 + p2;       \
2042       CHECK_INTERRUPT();                  \
2043       STORE_LONG(reg_sp, dest_addr >> 8); \
2044       reg_sp--;                           \
2045       PUSH(dest_addr);                    \
2046   } while (0)
2047 
2048 #define PHA(store_func)         \
2049   do {                          \
2050       if (LOCAL_65816_M()) {    \
2051           store_func(reg_a, 1); \
2052       } else {                  \
2053           store_func(reg_c, 0); \
2054       }                         \
2055   } while (0)
2056 
2057 #define PHB(store_func) store_func(reg_dbr, 1);
2058 
2059 #define PHD()                           \
2060   do {                                  \
2061       INC_PC(SIZE_1);                   \
2062       FETCH_PARAM_DUMMY(reg_pc);        \
2063       CHECK_INTERRUPT();                \
2064       STORE_LONG(reg_sp, reg_dpr >> 8); \
2065       reg_sp--;                         \
2066       PUSH(reg_dpr);                    \
2067   } while (0)
2068 
2069 #define PHK(store_func) store_func(reg_pbr, 1);
2070 
2071 #define PHP(store_func)                            \
2072   do {                                             \
2073       if (reg_emul) {                              \
2074           store_func(LOCAL_STATUS() | P_BREAK, 1); \
2075       } else {                                     \
2076           store_func(LOCAL_65816_STATUS(), 1);     \
2077       }                                            \
2078   } while (0)
2079 
2080 #define PHX(store_func) store_func(reg_x, LOCAL_65816_X())
2081 
2082 #define PHY(store_func) store_func(reg_y, LOCAL_65816_X())
2083 
2084 #define PLA(load_func)            \
2085   do {                            \
2086       if (LOCAL_65816_M()) {      \
2087           load_func(reg_a, 1);    \
2088           LOCAL_SET_NZ(reg_a, 1); \
2089       } else {                    \
2090           load_func(reg_c, 0);    \
2091           LOCAL_SET_NZ(reg_c, 0); \
2092       }                           \
2093   } while (0)
2094 
2095 #define PLB(load_func)          \
2096   do {                          \
2097       load_func(reg_dbr, 1);    \
2098       LOCAL_SET_NZ(reg_dbr, 1); \
2099   } while (0)
2100 
2101 #define PLD()                               \
2102   do {                                      \
2103       INC_PC(SIZE_1);                       \
2104       FETCH_PARAM_DUMMY(reg_pc);            \
2105       FETCH_PARAM_DUMMY(reg_pc);            \
2106       CHECK_INTERRUPT();                    \
2107       reg_sp++;                             \
2108       reg_dpr = LOAD_LONG(reg_sp);          \
2109       reg_sp++;                             \
2110       reg_dpr |= LOAD_LONG(reg_sp) << 8;    \
2111       if (reg_emul) {                       \
2112           reg_sp = (reg_sp & 0xff) | 0x100; \
2113       }                                     \
2114       LOCAL_SET_NZ(reg_dpr, 0);             \
2115   } while (0)
2116 
2117 #define PLP(load_func)       \
2118   do {                       \
2119       unsigned int s;        \
2120                              \
2121       load_func(s, 1);       \
2122       LOCAL_SET_STATUS(s);   \
2123       if (LOCAL_65816_X()) { \
2124           reg_x &= 0xff;     \
2125           reg_y &= 0xff;     \
2126       }                      \
2127   } while (0)
2128 
2129 #define PLI(load_func, reg_r)     \
2130   do {                            \
2131       if (LOCAL_65816_X()) {      \
2132           load_func(reg_r, 1);    \
2133           LOCAL_SET_NZ(reg_r, 1); \
2134       } else {                    \
2135           load_func(reg_r, 0);    \
2136           LOCAL_SET_NZ(reg_r, 0); \
2137       }                           \
2138   } while (0)
2139 
2140 #define PLX(load_func) PLI(load_func, reg_x)
2141 
2142 #define PLY(load_func) PLI(load_func, reg_y)
2143 
2144 #define REPSEP(load_func, v)             \
2145   do {                                   \
2146       unsigned int value;                \
2147                                          \
2148       INC_PC(SIZE_1);                    \
2149       CHECK_INTERRUPT();                 \
2150       p1 = FETCH_PARAM(reg_pc);          \
2151       value = p1;                        \
2152       INC_PC(SIZE_1);                    \
2153       FETCH_PARAM_DUMMY(reg_pc);         \
2154       if (value & 0x80) {                \
2155           LOCAL_SET_SIGN(v);             \
2156       }                                  \
2157       if (value & 0x40) {                \
2158           LOCAL_SET_OVERFLOW(v);         \
2159       }                                  \
2160       if ((value & 0x20) && !reg_emul) { \
2161           LOCAL_SET_65816_M(v);          \
2162       }                                  \
2163       if ((value & 0x10) && !reg_emul) { \
2164           LOCAL_SET_65816_X(v);          \
2165           if (v) {                       \
2166               reg_x &= 0xff;             \
2167               reg_y &= 0xff;             \
2168           }                              \
2169       }                                  \
2170       if (value & 0x08) {                \
2171           LOCAL_SET_DECIMAL(v);          \
2172       }                                  \
2173       if (value & 0x04) {                \
2174           LOCAL_SET_INTERRUPT(v);        \
2175       }                                  \
2176       if (value & 0x02) {                \
2177           LOCAL_SET_ZERO(v);             \
2178       }                                  \
2179       if (value & 0x01) {                \
2180           LOCAL_SET_CARRY(v);            \
2181       }                                  \
2182   } while (0)
2183 
2184 #define REP(load_func) REPSEP(load_func, 0)
2185 
2186 #define RES()                                            \
2187   do {                                                   \
2188       interrupt_ack_reset(CPU_INT_STATUS);               \
2189       cpu_reset();                                       \
2190       bank_start = bank_limit = 0; /* prevent caching */ \
2191       FETCH_PARAM(reg_pc);                               \
2192       FETCH_PARAM_DUMMY(reg_pc);                         \
2193       LOCAL_SET_BREAK(0);                                \
2194       reg_emul = 1;                                      \
2195       reg_x &= 0xff;                                     \
2196       reg_y &= 0xff;                                     \
2197       reg_sp = 0x100 | (reg_sp & 0xff);                  \
2198       reg_dpr = 0;                                       \
2199       reg_dbr = 0;                                       \
2200       reg_pbr = 0;                                       \
2201       EMULATION_MODE_CHANGED;                            \
2202       LOAD_LONG(reg_sp);                                 \
2203       reg_sp = 0x100 | ((reg_sp - 1) & 0xff);            \
2204       LOAD_LONG(reg_sp);                                 \
2205       reg_sp = 0x100 | ((reg_sp - 1) & 0xff);            \
2206       LOAD_LONG(reg_sp);                                 \
2207       reg_sp = 0x100 | ((reg_sp - 1) & 0xff);            \
2208       LOCAL_SET_INTERRUPT(1);                            \
2209       LOCAL_SET_DECIMAL(0);                              \
2210       CHECK_INTERRUPT();                                 \
2211       LOAD_INT_ADDR(0xfffc);                             \
2212       JUMP(reg_pc);                                      \
2213       DMA_ON_RESET;                                      \
2214   } while (0)
2215 
2216 #define ROL(load_func, store_func) ASLROL(load_func, store_func, LOCAL_CARRY())
2217 
2218 #define ROR(load_func, store_func) LSRROR(load_func, store_func, LOCAL_CARRY())
2219 
2220 #define RTI()                    \
2221   do {                           \
2222       unsigned int tmp;          \
2223                                  \
2224       INC_PC(SIZE_1);            \
2225       FETCH_PARAM_DUMMY(reg_pc); \
2226       FETCH_PARAM_DUMMY(reg_pc); \
2227       tmp = PULL();              \
2228       LOCAL_SET_STATUS(tmp);     \
2229       if (LOCAL_65816_X()) {     \
2230           reg_x &= 0xff;         \
2231           reg_y &= 0xff;         \
2232       }                          \
2233       if (reg_emul) {            \
2234           CHECK_INTERRUPT();     \
2235           reg_pc = PULL();       \
2236           reg_pc |= PULL() << 8; \
2237       } else {                   \
2238           reg_pc = PULL();       \
2239           CHECK_INTERRUPT();     \
2240           reg_pc |= PULL() << 8; \
2241           reg_pbr = PULL();      \
2242       }                          \
2243       JUMP(reg_pc);              \
2244   } while (0)
2245 
2246 #define RTL()                               \
2247   do {                                      \
2248       INC_PC(SIZE_1);                       \
2249       FETCH_PARAM_DUMMY(reg_pc);            \
2250       FETCH_PARAM_DUMMY(reg_pc);            \
2251       reg_sp++;                             \
2252       reg_pc = LOAD_LONG(reg_sp);           \
2253       reg_sp++;                             \
2254       CHECK_INTERRUPT();                    \
2255       reg_pc |= LOAD_LONG(reg_sp) << 8;     \
2256       reg_sp++;                             \
2257       reg_pbr = LOAD_LONG(reg_sp);          \
2258       if (reg_emul) {                       \
2259           reg_sp = (reg_sp & 0xff) | 0x100; \
2260       }                                     \
2261       INC_PC(SIZE_1);                       \
2262       JUMP(reg_pc);                         \
2263   } while (0)
2264 
2265 #define RTS()                    \
2266   do {                           \
2267       INC_PC(SIZE_1);            \
2268       FETCH_PARAM_DUMMY(reg_pc); \
2269       FETCH_PARAM_DUMMY(reg_pc); \
2270       reg_pc = PULL();           \
2271       CHECK_INTERRUPT();         \
2272       reg_pc |= PULL() << 8;     \
2273       LOAD_LONG_DUMMY(reg_sp);   \
2274       INC_PC(SIZE_1);            \
2275       JUMP(reg_pc);              \
2276   } while (0)
2277 
2278 #define SBC(load_func)                                                      \
2279   do {                                                                      \
2280       unsigned int tmp_value;                                               \
2281       unsigned int tmp, tmp2;                                               \
2282                                                                             \
2283       tmp = LOCAL_CARRY();                                                  \
2284       if (LOCAL_65816_M()) {                                                \
2285           load_func(tmp_value, 1);                                          \
2286           tmp += (tmp_value ^ 0xff) + reg_a;                                \
2287           LOCAL_SET_OVERFLOW((reg_a ^ tmp_value) & (reg_a ^ tmp) & 0x80);   \
2288           if (LOCAL_DECIMAL()) {                                            \
2289               tmp2 = (reg_a & 0x0f) + (0x0f & ~tmp_value) + LOCAL_CARRY();  \
2290               tmp = (tmp2 < 0x10 ? (tmp2 - 0x6) : tmp2) & 0xf;              \
2291               tmp2 = (reg_a & 0xff) + (0xff & ~tmp_value) + LOCAL_CARRY();  \
2292               tmp |= (tmp2 < 0x100 ? (tmp2 - 0x60) : tmp2) & 0xf0;          \
2293               LOCAL_SET_CARRY(tmp2 > 0xff);                                 \
2294           } else {                                                          \
2295               LOCAL_SET_CARRY(tmp > 0xff);                                  \
2296           }                                                                 \
2297           LOCAL_SET_NZ(tmp, 1);                                             \
2298           reg_a = tmp;                                                      \
2299       } else {                                                              \
2300           load_func(tmp_value, 0);                                          \
2301           tmp += (tmp_value ^ 0xffff) + reg_c;                              \
2302           LOCAL_SET_OVERFLOW((reg_c ^ tmp_value) & (reg_c ^ tmp) & 0x8000); \
2303           if (LOCAL_DECIMAL()) {                                            \
2304               tmp2 = (reg_a & 0x0f) + (0x0f & ~tmp_value) + LOCAL_CARRY();  \
2305               tmp = (tmp2 < 0x10 ? (tmp2 - 0x6) : tmp2) & 0xf;              \
2306               tmp2 = (reg_a & 0xff) + (0xff & ~tmp_value) + LOCAL_CARRY();  \
2307               tmp |= (tmp2 < 0x100 ? (tmp2 - 0x60) : tmp2) & 0xf0;          \
2308               tmp2 = (reg_a & 0xfff) + (0xfff & ~tmp_value) + LOCAL_CARRY();\
2309               tmp |= (tmp2 < 0x1000 ? (tmp2 - 0x600) : tmp2) & 0xf00;       \
2310               tmp2 = (reg_a & 0xffff) + (0xffff & ~tmp_value) + LOCAL_CARRY();\
2311               tmp |= (tmp2 < 0x10000 ? (tmp2 - 0x6000) : tmp2) & 0xf000;    \
2312               LOCAL_SET_CARRY(tmp2 > 0xffff);                               \
2313           } else {                                                          \
2314               LOCAL_SET_CARRY(tmp > 0xffff);                                \
2315           }                                                                 \
2316           LOCAL_SET_NZ(tmp, 0);                                             \
2317           reg_c = tmp;                                                      \
2318       }                                                                     \
2319   } while (0)
2320 
2321 #undef SEC    /* defined in time.h on SunOS. */
2322 #define SEC()                    \
2323   do {                           \
2324       INC_PC(SIZE_1);            \
2325       FETCH_PARAM_DUMMY(reg_pc); \
2326       LOCAL_SET_CARRY(1);        \
2327   } while (0)
2328 
2329 #define SED()                    \
2330   do {                           \
2331       INC_PC(SIZE_1);            \
2332       FETCH_PARAM_DUMMY(reg_pc); \
2333       LOCAL_SET_DECIMAL(1);      \
2334   } while (0)
2335 
2336 #define SEI()                    \
2337   do {                           \
2338       INC_PC(SIZE_1);            \
2339       FETCH_PARAM_DUMMY(reg_pc); \
2340       LOCAL_SET_INTERRUPT(1);    \
2341   } while (0)
2342 
2343 #define SEP(load_func) REPSEP(load_func, 1)
2344 
2345 #define STA(store_func) \
2346       store_func(reg_c, LOCAL_65816_M());
2347 
2348 #define STP()                                                         \
2349   do {                                                                \
2350       if (!(CPU_INT_STATUS->global_pending_int & IK_RESET)) {         \
2351           do {                                                        \
2352               DO_INTERRUPT(CPU_INT_STATUS->global_pending_int);       \
2353               CLK_INC(CLK);                                           \
2354           } while (!(CPU_INT_STATUS->global_pending_int & IK_RESET)); \
2355           CLK_INC(CLK);                                               \
2356       }                                                               \
2357       CHECK_INTERRUPT();                                              \
2358       INC_PC(SIZE_1);                                                 \
2359       FETCH_PARAM_DUMMY(reg_pc);                                      \
2360       FETCH_PARAM_DUMMY(reg_pc);                                      \
2361   } while (0)
2362 
2363 #define STX(store_func) \
2364       store_func(reg_x, LOCAL_65816_X())
2365 
2366 #define STY(store_func) \
2367       store_func(reg_y, LOCAL_65816_X())
2368 
2369 #define STZ(store_func) \
2370       store_func(0, LOCAL_65816_M())
2371 
2372 #define TRANSI(reg_s, reg_r)      \
2373   do {                            \
2374       INC_PC(SIZE_1);             \
2375       FETCH_PARAM_DUMMY(reg_pc);  \
2376       reg_r = reg_s;              \
2377       if (LOCAL_65816_X()) {      \
2378           reg_r &= 0xff;          \
2379           LOCAL_SET_NZ(reg_r, 1); \
2380       } else {                    \
2381           LOCAL_SET_NZ(reg_r, 0); \
2382       }                           \
2383   } while (0)
2384 
2385 #define TAX() TRANSI(reg_c, reg_x)
2386 #define TAY() TRANSI(reg_c, reg_y)
2387 
2388 #define TCD()                    \
2389   do {                           \
2390       INC_PC(SIZE_1);            \
2391       FETCH_PARAM_DUMMY(reg_pc); \
2392       reg_dpr = reg_c;           \
2393       LOCAL_SET_NZ(reg_dpr, 0);  \
2394   } while (0)
2395 
2396 #define TCS()                     \
2397   do {                            \
2398       INC_PC(SIZE_1);             \
2399       FETCH_PARAM_DUMMY(reg_pc);  \
2400       if (reg_emul) {             \
2401           reg_sp = 0x100 | reg_a; \
2402       } else {                    \
2403           reg_sp = reg_c;         \
2404       }                           \
2405   } while (0)
2406 
2407 #define TDC()                    \
2408   do {                           \
2409       INC_PC(SIZE_1);            \
2410       FETCH_PARAM_DUMMY(reg_pc); \
2411       reg_c = reg_dpr;           \
2412       LOCAL_SET_NZ(reg_c, 0);    \
2413   } while (0)
2414 
2415 #define TRBTSB(load_func, store_func, logic)    \
2416   do {                                          \
2417       unsigned int tmp_value;                   \
2418                                                 \
2419       if (LOCAL_65816_M()) {                    \
2420           load_func(tmp_value, 1);              \
2421           LOCAL_SET_ZERO(!(tmp_value & reg_a)); \
2422           tmp_value logic reg_a;                \
2423           store_func(tmp_value, 1);             \
2424       } else {                                  \
2425           load_func(tmp_value, 0);              \
2426           LOCAL_SET_ZERO(!(tmp_value & reg_c)); \
2427           tmp_value logic reg_c;                \
2428           store_func(tmp_value, 0);             \
2429       }                                         \
2430   } while (0)
2431 
2432 #define TRB(load_func, store_func) TRBTSB(load_func, store_func, &=~)
2433 
2434 #define TSB(load_func, store_func) TRBTSB(load_func, store_func, |=)
2435 
2436 #define TSC()                    \
2437   do {                           \
2438       INC_PC(SIZE_1);            \
2439       FETCH_PARAM_DUMMY(reg_pc); \
2440       reg_c = reg_sp;            \
2441       LOCAL_SET_NZ(reg_c, 0);    \
2442   } while (0)
2443 
2444 
2445 #define TSX() TRANSI(reg_sp, reg_x)
2446 
2447 #define TRANSA(reg_r)             \
2448   do {                            \
2449       INC_PC(SIZE_1);             \
2450       FETCH_PARAM_DUMMY(reg_pc);  \
2451       if (LOCAL_65816_M()) {      \
2452           reg_a = (uint8_t)reg_r;    \
2453           LOCAL_SET_NZ(reg_a, 1); \
2454       } else {                    \
2455           reg_c = reg_r;          \
2456           LOCAL_SET_NZ(reg_c, 0); \
2457       }                           \
2458   } while (0)
2459 
2460 #define TXA() TRANSA(reg_x)
2461 
2462 #define TXS()                     \
2463   do {                            \
2464       INC_PC(SIZE_1);             \
2465       FETCH_PARAM_DUMMY(reg_pc);  \
2466       if (reg_emul) {      \
2467           reg_sp = 0x100 | reg_x; \
2468       } else {                    \
2469           reg_sp = reg_x;         \
2470       }                           \
2471   } while (0)
2472 
2473 #define TXY()                               \
2474   do {                                      \
2475       INC_PC(SIZE_1);                       \
2476       FETCH_PARAM_DUMMY(reg_pc);            \
2477       reg_y = reg_x;                        \
2478       LOCAL_SET_NZ(reg_y, LOCAL_65816_X()); \
2479   } while (0)
2480 
2481 #define TYA() TRANSA(reg_y)
2482 
2483 #define TYX()                               \
2484   do {                                      \
2485       INC_PC(SIZE_1);                       \
2486       FETCH_PARAM_DUMMY(reg_pc);            \
2487       reg_x = reg_y;                        \
2488       LOCAL_SET_NZ(reg_x, LOCAL_65816_X()); \
2489   } while (0)
2490 
2491 #define WAI()                                                                             \
2492   do {                                                                                    \
2493       if (!(CPU_INT_STATUS->global_pending_int & (IK_RESET | IK_NMI | IK_IRQ))) {         \
2494           do {                                                                            \
2495               DO_INTERRUPT(CPU_INT_STATUS->global_pending_int);                           \
2496               CLK_INC(CLK);                                                               \
2497           } while (!(CPU_INT_STATUS->global_pending_int & (IK_RESET | IK_NMI | IK_IRQ))); \
2498           CLK_INC(CLK); /* yes, this is really this complicated with this extra cycle */  \
2499       }                                                                                   \
2500       CHECK_INTERRUPT();                                                                  \
2501       INC_PC(SIZE_1);                                                                     \
2502       FETCH_PARAM_DUMMY(reg_pc);                                                          \
2503       FETCH_PARAM_DUMMY(reg_pc);                                                          \
2504   } while (0)
2505 
2506 #define WDM()                    \
2507   do {                           \
2508       INC_PC(SIZE_1);            \
2509       FETCH_PARAM_DUMMY(reg_pc); \
2510       INC_PC(SIZE_1);            \
2511   } while (0)
2512 
2513 #define XBA()                    \
2514   do {                           \
2515       uint8_t tmp;                  \
2516                                  \
2517       INC_PC(SIZE_1);            \
2518       FETCH_PARAM_DUMMY(reg_pc); \
2519       FETCH_PARAM_DUMMY(reg_pc); \
2520       tmp = reg_a;               \
2521       reg_a = reg_b;             \
2522       reg_b = tmp;               \
2523   } while (0)
2524 
2525 #define XCE()                                   \
2526   do {                                          \
2527       INC_PC(SIZE_1);                           \
2528       FETCH_PARAM_DUMMY(reg_pc);                \
2529       if (LOCAL_CARRY() != reg_emul) {          \
2530           if (LOCAL_CARRY()) {                  \
2531               reg_emul = 1;                     \
2532               LOCAL_SET_CARRY(0);               \
2533               LOCAL_SET_BREAK(0);               \
2534               reg_x &= 0xff;                    \
2535               reg_y &= 0xff;                    \
2536               reg_sp = 0x100 | (reg_sp & 0xff); \
2537           } else {                              \
2538               reg_emul = 0;                     \
2539               LOCAL_SET_CARRY(1);               \
2540               LOCAL_SET_65816_M(1);             \
2541               LOCAL_SET_65816_X(1);             \
2542           }                                     \
2543           EMULATION_MODE_CHANGED;               \
2544       }                                         \
2545   } while (0)
2546 
2547 /* ------------------------------------------------------------------------ */
2548 
2549 /* Here, the CPU is emulated. */
2550 
2551 {
2552 
2553     {
2554         unsigned int p0 = 0;
2555         unsigned int p1 = 0;
2556         unsigned int p2 = 0;
2557         unsigned int p3 = 0;
2558 #ifdef DEBUG
2559         CLOCK debug_clk = 0;
2560         unsigned int debug_pc = 0;
2561         uint16_t debug_c = 0;
2562         uint16_t debug_x = 0;
2563         uint16_t debug_y = 0;
2564         uint16_t debug_sp = 0;
2565         uint8_t debug_pbr = 0;
2566 
2567         if (TRACEFLG) {
2568             debug_clk = maincpu_clk;
2569             debug_pc = reg_pc;
2570             debug_c = reg_c;
2571             debug_x = reg_x;
2572             debug_y = reg_y;
2573             debug_sp = reg_sp;
2574             debug_pbr = reg_pbr;
2575         }
2576 #endif
2577 
2578         if (interrupt65816 != IK_NONE) {
2579             DO_INTERRUPT(interrupt65816);
2580             if (interrupt65816 & IK_RESET) {
2581                 p0 = 0x102;
2582             } else if (interrupt65816 & IK_NMI) {
2583                 p0 = 0x101;
2584             } else if (interrupt65816 & IK_IRQ) {
2585                 p0 = 0x100;
2586             } else {
2587                 CHECK_INTERRUPT();
2588                 p0 = FETCH_PARAM(reg_pc);
2589             }
2590         } else {
2591             CHECK_INTERRUPT();
2592             p0 = FETCH_PARAM(reg_pc);
2593         }
2594         SET_LAST_ADDR(reg_pc);
2595 
2596 #ifdef DEBUG
2597         if (debug.perform_break_into_monitor)
2598         {
2599             monitor_startup_trap();
2600             debug.perform_break_into_monitor = 0;
2601         }
2602 #endif
2603 
2604 trap_skipped:
2605         SET_LAST_OPCODE(p0);
2606 
2607         switch (p0) {
2608 
2609           case 0x00:            /* BRK */
2610             BRK();
2611             break;
2612 
2613           case 0x01:            /* ORA ($nn,X) */
2614             ORA(LOAD_INDIRECT_X_FUNC);
2615             break;
2616 
2617           case 0x02:            /* NOP #$nn - also used for traps */
2618             STATIC_ASSERT(TRAP_OPCODE == 0x02);
2619             COP_02();
2620             break;
2621 
2622           case 0x03:            /* ORA $nn,S */
2623             ORA(LOAD_STACK_REL_FUNC);
2624             break;
2625 
2626           case 0x04:            /* TSB $nn */
2627             TSB(LOAD_DIRECT_PAGE_FUNC_RRW, STORE_DIRECT_PAGE_RRW);
2628             break;
2629 
2630           case 0x05:            /* ORA $nn */
2631             ORA(LOAD_DIRECT_PAGE_FUNC);
2632             break;
2633 
2634           case 0x06:            /* ASL $nn */
2635             ASL(LOAD_DIRECT_PAGE_FUNC_RRW, STORE_DIRECT_PAGE_RRW);
2636             break;
2637 
2638           case 0x07:            /* ORA [$nn] */
2639             ORA(LOAD_INDIRECT_LONG_FUNC);
2640             break;
2641 
2642           case 0x08:            /* PHP */
2643             PHP(STORE_STACK);
2644             break;
2645 
2646           case 0x09:            /* ORA #$nn */
2647             ORA(LOAD_IMMEDIATE_FUNC);
2648             break;
2649 
2650           case 0x0a:            /* ASL A */
2651             ASL(LOAD_ACCU_RRW, STORE_ACCU_RRW);
2652             break;
2653 
2654           case 0x0b:            /* PHD */
2655             PHD();
2656             break;
2657 
2658           case 0x0c:            /* TSB $nnnn */
2659             TSB(LOAD_ABS_FUNC_RRW, STORE_ABS_RRW);
2660             break;
2661 
2662           case 0x0d:            /* ORA $nnnn */
2663             ORA(LOAD_ABS_FUNC);
2664             break;
2665 
2666           case 0x0e:            /* ASL $nnnn */
2667             ASL(LOAD_ABS_FUNC_RRW, STORE_ABS_RRW);
2668             break;
2669 
2670           case 0x0f:            /* ORA $nnnnnn */
2671             ORA(LOAD_ABS_LONG_FUNC);
2672             break;
2673 
2674           case 0x10:            /* BPL $nnnn */
2675             BRANCH(!LOCAL_SIGN());
2676             break;
2677 
2678           case 0x11:            /* ORA ($nn),Y */
2679             ORA(LOAD_INDIRECT_Y_FUNC);
2680             break;
2681 
2682           case 0x12:            /* ORA ($nn) */
2683             ORA(LOAD_INDIRECT_FUNC);
2684             break;
2685 
2686           case 0x13:            /* ORA ($nn,S),Y */
2687             ORA(LOAD_STACK_REL_Y_FUNC);
2688             break;
2689 
2690           case 0x14:            /* TRB $nn */
2691             TRB(LOAD_DIRECT_PAGE_FUNC_RRW, STORE_DIRECT_PAGE_RRW);
2692             break;
2693 
2694           case 0x15:            /* ORA $nn,X */
2695             ORA(LOAD_DIRECT_PAGE_X_FUNC);
2696             break;
2697 
2698           case 0x16:            /* ASL $nn,X */
2699             ASL(LOAD_DIRECT_PAGE_X_FUNC_RRW, STORE_DIRECT_PAGE_X_RRW);
2700             break;
2701 
2702           case 0x17:            /* ORA [$nn],Y */
2703             ORA(LOAD_INDIRECT_LONG_Y_FUNC);
2704             break;
2705 
2706           case 0x18:            /* CLC */
2707             CLC();
2708             break;
2709 
2710           case 0x19:            /* ORA $nnnn,Y */
2711             ORA(LOAD_ABS_Y_FUNC);
2712             break;
2713 
2714           case 0x1a:            /* INA */
2715             INC(LOAD_ACCU_RRW, STORE_ACCU_RRW);
2716             break;
2717 
2718           case 0x1b:            /* TCS */
2719             TCS();
2720             break;
2721 
2722           case 0x1c:            /* TRB $nnnn */
2723             TRB(LOAD_ABS_FUNC_RRW, STORE_ABS_RRW);
2724             break;
2725 
2726           case 0x1d:            /* ORA $nnnn,X */
2727             ORA(LOAD_ABS_X_FUNC);
2728             break;
2729 
2730           case 0x1e:            /* ASL $nnnn,X */
2731             ASL(LOAD_ABS_X_FUNC_RRW, STORE_ABS_X_RRW);
2732             break;
2733 
2734           case 0x1f:            /* ORA $nnnnnn,X */
2735             ORA(LOAD_ABS_LONG_X_FUNC);
2736             break;
2737 
2738           case 0x20:            /* JSR $nnnn */
2739             JSR();
2740             break;
2741 
2742           case 0x21:            /* AND ($nn,X) */
2743             AND(LOAD_INDIRECT_X_FUNC);
2744             break;
2745 
2746           case 0x22:            /* JSR $nnnnnn */
2747             JSR_LONG();
2748             break;
2749 
2750           case 0x23:            /* AND $nn,S */
2751             AND(LOAD_STACK_REL_FUNC);
2752             break;
2753 
2754           case 0x24:            /* BIT $nn */
2755             BIT(LOAD_DIRECT_PAGE_FUNC);
2756             break;
2757 
2758           case 0x25:            /* AND $nn */
2759             AND(LOAD_DIRECT_PAGE_FUNC);
2760             break;
2761 
2762           case 0x26:            /* ROL $nn */
2763             ROL(LOAD_DIRECT_PAGE_FUNC_RRW, STORE_DIRECT_PAGE_RRW);
2764             break;
2765 
2766           case 0x27:            /* AND [$nn] */
2767             AND(LOAD_INDIRECT_LONG_FUNC);
2768             break;
2769 
2770           case 0x28:            /* PLP */
2771             PLP(LOAD_STACK);
2772             break;
2773 
2774           case 0x29:            /* AND #$nn */
2775             AND(LOAD_IMMEDIATE_FUNC);
2776             break;
2777 
2778           case 0x2a:            /* ROL A */
2779             ROL(LOAD_ACCU_RRW, STORE_ACCU_RRW);
2780             break;
2781 
2782           case 0x2b:            /* PLD */
2783             PLD();
2784             break;
2785 
2786           case 0x2c:            /* BIT $nnnn */
2787             BIT(LOAD_ABS_FUNC);
2788             break;
2789 
2790           case 0x2d:            /* AND $nnnn */
2791             AND(LOAD_ABS_FUNC);
2792             break;
2793 
2794           case 0x2e:            /* ROL $nnnn */
2795             ROL(LOAD_ABS_FUNC_RRW, STORE_ABS_RRW);
2796             break;
2797 
2798           case 0x2f:            /* AND $nnnnnn */
2799             AND(LOAD_ABS_LONG_FUNC);
2800             break;
2801 
2802           case 0x30:            /* BMI $nnnn */
2803             BRANCH(LOCAL_SIGN());
2804             break;
2805 
2806           case 0x31:            /* AND ($nn),Y */
2807             AND(LOAD_INDIRECT_Y_FUNC);
2808             break;
2809 
2810           case 0x32:            /* AND ($nn) */
2811             AND(LOAD_INDIRECT_FUNC);
2812             break;
2813 
2814           case 0x33:            /* AND ($nn,S),Y */
2815             AND(LOAD_STACK_REL_Y_FUNC);
2816             break;
2817 
2818           case 0x34:            /* BIT $nn,X */
2819             BIT(LOAD_DIRECT_PAGE_X_FUNC);
2820             break;
2821 
2822           case 0x35:            /* AND $nn,X */
2823             AND(LOAD_DIRECT_PAGE_X_FUNC);
2824             break;
2825 
2826           case 0x36:            /* ROL $nn,X */
2827             ROL(LOAD_DIRECT_PAGE_X_FUNC_RRW, STORE_DIRECT_PAGE_X_RRW);
2828             break;
2829 
2830           case 0x37:            /* AND [$nn],Y */
2831             AND(LOAD_INDIRECT_LONG_Y_FUNC);
2832             break;
2833 
2834           case 0x38:            /* SEC */
2835             SEC();
2836             break;
2837 
2838           case 0x39:            /* AND $nnnn,Y */
2839             AND(LOAD_ABS_Y_FUNC);
2840             break;
2841 
2842           case 0x3a:            /* DEA */
2843             DEC(LOAD_ACCU_RRW, STORE_ACCU_RRW);
2844             break;
2845 
2846           case 0x3b:            /* TSC */
2847             TSC();
2848             break;
2849 
2850           case 0x3c:            /* BIT $nnnn,X */
2851             BIT(LOAD_ABS_X_FUNC);
2852             break;
2853 
2854           case 0x3d:            /* AND $nnnn,X */
2855             AND(LOAD_ABS_X_FUNC);
2856             break;
2857 
2858           case 0x3e:            /* ROL $nnnn,X */
2859             ROL(LOAD_ABS_X_FUNC_RRW, STORE_ABS_X_RRW);
2860             break;
2861 
2862           case 0x3f:            /* AND $nnnnnn,X */
2863             AND(LOAD_ABS_LONG_X_FUNC);
2864             break;
2865 
2866           case 0x40:            /* RTI */
2867             RTI();
2868             break;
2869 
2870           case 0x41:            /* EOR ($nn,X) */
2871             EOR(LOAD_INDIRECT_X_FUNC);
2872             break;
2873 
2874           case 0x42:            /* WDM */
2875             WDM();
2876             break;
2877 
2878           case 0x43:            /* EOR $nn,S */
2879             EOR(LOAD_STACK_REL_FUNC);
2880             break;
2881 
2882           case 0x44:            /* MVP $nn,$nn */
2883             MVP();
2884             break;
2885 
2886           case 0x45:            /* EOR $nn */
2887             EOR(LOAD_DIRECT_PAGE_FUNC);
2888             break;
2889 
2890           case 0x46:            /* LSR $nn */
2891             LSR(LOAD_DIRECT_PAGE_FUNC_RRW, STORE_DIRECT_PAGE_RRW);
2892             break;
2893 
2894           case 0x47:            /* EOR [$nn] */
2895             EOR(LOAD_INDIRECT_LONG_FUNC);
2896             break;
2897 
2898           case 0x48:            /* PHA */
2899             PHA(STORE_STACK);
2900             break;
2901 
2902           case 0x49:            /* EOR #$nn */
2903             EOR(LOAD_IMMEDIATE_FUNC);
2904             break;
2905 
2906           case 0x4a:            /* LSR A */
2907             LSR(LOAD_ACCU_RRW, STORE_ACCU_RRW);
2908             break;
2909 
2910           case 0x4b:            /* PHK */
2911             PHK(STORE_STACK);
2912             break;
2913 
2914           case 0x4c:            /* JMP $nnnn */
2915             JMP();
2916             break;
2917 
2918           case 0x4d:            /* EOR $nnnn */
2919             EOR(LOAD_ABS_FUNC);
2920             break;
2921 
2922           case 0x4e:            /* LSR $nnnn */
2923             LSR(LOAD_ABS_FUNC_RRW, STORE_ABS_RRW);
2924             break;
2925 
2926           case 0x4f:            /* EOR $nnnnnn */
2927             EOR(LOAD_ABS_LONG_FUNC);
2928             break;
2929 
2930           case 0x50:            /* BVC $nnnn */
2931             BRANCH(!LOCAL_OVERFLOW());
2932             break;
2933 
2934           case 0x51:            /* EOR ($nn),Y */
2935             EOR(LOAD_INDIRECT_Y_FUNC);
2936             break;
2937 
2938           case 0x52:            /* EOR ($nn) */
2939             EOR(LOAD_INDIRECT_FUNC);
2940             break;
2941 
2942           case 0x53:            /* EOR ($nn,S),Y */
2943             EOR(LOAD_STACK_REL_Y_FUNC);
2944             break;
2945 
2946           case 0x54:            /* MVN $nn,$nn */
2947             MVN();
2948             break;
2949 
2950           case 0x55:            /* EOR $nn,X */
2951             EOR(LOAD_DIRECT_PAGE_X_FUNC);
2952             break;
2953 
2954           case 0x56:            /* LSR $nn,X */
2955             LSR(LOAD_DIRECT_PAGE_X_FUNC_RRW, STORE_DIRECT_PAGE_X_RRW);
2956             break;
2957 
2958           case 0x57:            /* EOR [$nn],Y */
2959             EOR(LOAD_INDIRECT_LONG_Y_FUNC);
2960             break;
2961 
2962           case 0x58:            /* CLI */
2963             CLI();
2964             break;
2965 
2966           case 0x59:            /* EOR $nnnn,Y */
2967             EOR(LOAD_ABS_Y_FUNC);
2968             break;
2969 
2970           case 0x5a:            /* PHY */
2971             PHY(STORE_STACK);
2972             break;
2973 
2974           case 0x5b:            /* TCD */
2975             TCD();
2976             break;
2977 
2978           case 0x5c:            /* JMP $nnnnnn */
2979             JMP_LONG();
2980             break;
2981 
2982           case 0x5d:            /* EOR $nnnn,X */
2983             EOR(LOAD_ABS_X_FUNC);
2984             break;
2985 
2986           case 0x5e:            /* LSR $nnnn,X */
2987             LSR(LOAD_ABS_X_FUNC_RRW, STORE_ABS_X_RRW);
2988             break;
2989 
2990           case 0x5f:            /* EOR $nnnnnn,X */
2991             EOR(LOAD_ABS_LONG_X_FUNC);
2992             break;
2993 
2994           case 0x60:            /* RTS */
2995             RTS();
2996             break;
2997 
2998           case 0x61:            /* ADC ($nn,X) */
2999             ADC(LOAD_INDIRECT_X_FUNC);
3000             break;
3001 
3002           case 0x62:            /* PER $nnnn */
3003             PER();
3004             break;
3005 
3006           case 0x63:            /* ADC $nn,S */
3007             ADC(LOAD_STACK_REL_FUNC);
3008             break;
3009 
3010           case 0x64:            /* STZ $nn */
3011             STZ(STORE_DIRECT_PAGE);
3012             break;
3013 
3014           case 0x65:            /* ADC $nn */
3015             ADC(LOAD_DIRECT_PAGE_FUNC);
3016             break;
3017 
3018           case 0x66:            /* ROR $nn */
3019             ROR(LOAD_DIRECT_PAGE_FUNC_RRW, STORE_DIRECT_PAGE_RRW);
3020             break;
3021 
3022           case 0x67:            /* ADC [$nn] */
3023             ADC(LOAD_INDIRECT_LONG_FUNC);
3024             break;
3025 
3026           case 0x68:            /* PLA */
3027             PLA(LOAD_STACK);
3028             break;
3029 
3030           case 0x69:            /* ADC #$nn */
3031             ADC(LOAD_IMMEDIATE_FUNC);
3032             break;
3033 
3034           case 0x6a:            /* ROR A */
3035             ROR(LOAD_ACCU_RRW, STORE_ACCU_RRW);
3036             break;
3037 
3038           case 0x6b:            /* RTL */
3039             RTL();
3040             break;
3041 
3042           case 0x6c:            /* JMP ($nnnn) */
3043             JMP_IND();
3044             break;
3045 
3046           case 0x6d:            /* ADC $nnnn */
3047             ADC(LOAD_ABS_FUNC);
3048             break;
3049 
3050           case 0x6e:            /* ROR $nnnn */
3051             ROR(LOAD_ABS_FUNC_RRW, STORE_ABS_RRW);
3052             break;
3053 
3054           case 0x6f:            /* ADC $nnnnnn */
3055             ADC(LOAD_ABS_LONG_FUNC);
3056             break;
3057 
3058           case 0x70:            /* BVS $nnnn */
3059             BRANCH(LOCAL_OVERFLOW());
3060             break;
3061 
3062           case 0x71:            /* ADC ($nn),Y */
3063             ADC(LOAD_INDIRECT_Y_FUNC);
3064             break;
3065 
3066           case 0x72:            /* ADC ($nn) */
3067             ADC(LOAD_INDIRECT_FUNC);
3068             break;
3069 
3070           case 0x73:            /* ADC ($nn,S),Y */
3071             ADC(LOAD_STACK_REL_Y_FUNC);
3072             break;
3073 
3074           case 0x74:            /* STZ $nn,X */
3075             STZ(STORE_DIRECT_PAGE_X);
3076             break;
3077 
3078           case 0x75:            /* ADC $nn,X */
3079             ADC(LOAD_DIRECT_PAGE_X_FUNC);
3080             break;
3081 
3082           case 0x76:            /* ROR $nn,X */
3083             ROR(LOAD_DIRECT_PAGE_X_FUNC_RRW, STORE_DIRECT_PAGE_X_RRW);
3084             break;
3085 
3086           case 0x77:            /* ADC [$nn],Y */
3087             ADC(LOAD_INDIRECT_LONG_Y_FUNC);
3088             break;
3089 
3090           case 0x78:            /* SEI */
3091             SEI();
3092             break;
3093 
3094           case 0x79:            /* ADC $nnnn,Y */
3095             ADC(LOAD_ABS_Y_FUNC);
3096             break;
3097 
3098           case 0x7a:            /* PLY */
3099             PLY(LOAD_STACK);
3100             break;
3101 
3102           case 0x7b:            /* TDC */
3103             TDC();
3104             break;
3105 
3106           case 0x7c:            /* JMP ($nnnn,X) */
3107             JMP_IND_X();
3108             break;
3109 
3110           case 0x7d:            /* ADC $nnnn,X */
3111             ADC(LOAD_ABS_X_FUNC);
3112             break;
3113 
3114           case 0x7e:            /* ROR $nnnn,X */
3115             ROR(LOAD_ABS_X_FUNC_RRW, STORE_ABS_X_RRW);
3116             break;
3117 
3118           case 0x7f:            /* ADC $nnnnnn,X */
3119             ADC(LOAD_ABS_LONG_X_FUNC);
3120             break;
3121 
3122           case 0x80:            /* BRA $nnnn */
3123             BRANCH(1);
3124             break;
3125 
3126           case 0x81:            /* STA ($nn,X) */
3127             STA(STORE_INDIRECT_X);
3128             break;
3129 
3130           case 0x82:            /* BRL $nnnn */
3131             BRANCH_LONG();
3132             break;
3133 
3134           case 0x83:            /* STA $nn,S */
3135             STA(STORE_STACK_REL);
3136             break;
3137 
3138           case 0x84:            /* STY $nn */
3139             STY(STORE_DIRECT_PAGE);
3140             break;
3141 
3142           case 0x85:            /* STA $nn */
3143             STA(STORE_DIRECT_PAGE);
3144             break;
3145 
3146           case 0x86:            /* STX $nn */
3147             STX(STORE_DIRECT_PAGE);
3148             break;
3149 
3150           case 0x87:            /* STA [$nn] */
3151             STA(STORE_INDIRECT_LONG);
3152             break;
3153 
3154           case 0x88:            /* DEY */
3155             DEY();
3156             break;
3157 
3158           case 0x89:            /* BIT #$nn */
3159             BIT_IMM(LOAD_IMMEDIATE_FUNC);
3160             break;
3161 
3162           case 0x8a:            /* TXA */
3163             TXA();
3164             break;
3165 
3166           case 0x8b:            /* PHB */
3167             PHB(STORE_STACK);
3168             break;
3169 
3170           case 0x8c:            /* STY $nnnn */
3171             STY(STORE_ABS);
3172             break;
3173 
3174           case 0x8d:            /* STA $nnnn */
3175             STA(STORE_ABS);
3176             break;
3177 
3178           case 0x8e:            /* STX $nnnn */
3179             STX(STORE_ABS);
3180             break;
3181 
3182           case 0x8f:            /* STA $nnnnnn */
3183             STA(STORE_ABS_LONG);
3184             break;
3185 
3186           case 0x90:            /* BCC $nnnn */
3187             BRANCH(!LOCAL_CARRY());
3188             break;
3189 
3190           case 0x91:            /* STA ($nn),Y */
3191             STA(STORE_INDIRECT_Y);
3192             break;
3193 
3194           case 0x92:            /* STA ($nn) */
3195             STA(STORE_INDIRECT);
3196             break;
3197 
3198           case 0x93:            /* STA ($nn,S),Y */
3199             STA(STORE_STACK_REL_Y);
3200             break;
3201 
3202           case 0x94:            /* STY $nn,X */
3203             STY(STORE_DIRECT_PAGE_X);
3204             break;
3205 
3206           case 0x95:            /* STA $nn,X */
3207             STA(STORE_DIRECT_PAGE_X);
3208             break;
3209 
3210           case 0x96:            /* STX $nn,Y */
3211             STX(STORE_DIRECT_PAGE_Y);
3212             break;
3213 
3214           case 0x97:            /* STA [$nn],Y */
3215             STA(STORE_INDIRECT_LONG_Y);
3216             break;
3217 
3218           case 0x98:            /* TYA */
3219             TYA();
3220             break;
3221 
3222           case 0x99:            /* STA $nnnn,Y */
3223             STA(STORE_ABS_Y);
3224             break;
3225 
3226           case 0x9a:            /* TXS */
3227             TXS();
3228             break;
3229 
3230           case 0x9b:            /* TXY */
3231             TXY();
3232             break;
3233 
3234           case 0x9c:            /* STZ $nnnn */
3235             STZ(STORE_ABS);
3236             break;
3237 
3238           case 0x9d:            /* STA $nnnn,X */
3239             STA(STORE_ABS_X);
3240             break;
3241 
3242           case 0x9e:            /* STZ $nnnn,X */
3243             STZ(STORE_ABS_X);
3244             break;
3245 
3246           case 0x9f:            /* STA $nnnnnn,X */
3247             STA(STORE_ABS_LONG_X);
3248             break;
3249 
3250           case 0xa0:            /* LDY #$nn */
3251             LDY(LOAD_IMMEDIATE_FUNC);
3252             break;
3253 
3254           case 0xa1:            /* LDA ($nn,X) */
3255             LDA(LOAD_INDIRECT_X_FUNC);
3256             break;
3257 
3258           case 0xa2:            /* LDX #$nn */
3259             LDX(LOAD_IMMEDIATE_FUNC);
3260             break;
3261 
3262           case 0xa3:            /* LDA $nn,S */
3263             LDA(LOAD_STACK_REL_FUNC);
3264             break;
3265 
3266           case 0xa4:            /* LDY $nn */
3267             LDY(LOAD_DIRECT_PAGE_FUNC);
3268             break;
3269 
3270           case 0xa5:            /* LDA $nn */
3271             LDA(LOAD_DIRECT_PAGE_FUNC);
3272             break;
3273 
3274           case 0xa6:            /* LDX $nn */
3275             LDX(LOAD_DIRECT_PAGE_FUNC);
3276             break;
3277 
3278           case 0xa7:            /* LDA [$nn] */
3279             LDA(LOAD_INDIRECT_LONG_FUNC);
3280             break;
3281 
3282           case 0xa8:            /* TAY */
3283             TAY();
3284             break;
3285 
3286           case 0xa9:            /* LDA #$nn */
3287             LDA(LOAD_IMMEDIATE_FUNC);
3288             break;
3289 
3290           case 0xaa:            /* TAX */
3291             TAX();
3292             break;
3293 
3294           case 0xab:            /* PLB */
3295             PLB(LOAD_STACK);
3296             break;
3297 
3298           case 0xac:            /* LDY $nnnn */
3299             LDY(LOAD_ABS_FUNC);
3300             break;
3301 
3302           case 0xad:            /* LDA $nnnn */
3303             LDA(LOAD_ABS_FUNC);
3304             break;
3305 
3306           case 0xae:            /* LDX $nnnn */
3307             LDX(LOAD_ABS_FUNC);
3308             break;
3309 
3310           case 0xaf:            /* LDA $nnnnnn */
3311             LDA(LOAD_ABS_LONG_FUNC);
3312             break;
3313 
3314           case 0xb0:            /* BCS $nnnn */
3315             BRANCH(LOCAL_CARRY());
3316             break;
3317 
3318           case 0xb1:            /* LDA ($nn),Y */
3319             LDA(LOAD_INDIRECT_Y_FUNC);
3320             break;
3321 
3322           case 0xb2:            /* LDA ($nn) */
3323             LDA(LOAD_INDIRECT_FUNC);
3324             break;
3325 
3326           case 0xb3:            /* LDA ($nn,S),Y */
3327             LDA(LOAD_STACK_REL_Y_FUNC);
3328             break;
3329 
3330           case 0xb4:            /* LDY $nn,X */
3331             LDY(LOAD_DIRECT_PAGE_X_FUNC);
3332             break;
3333 
3334           case 0xb5:            /* LDA $nn,X */
3335             LDA(LOAD_DIRECT_PAGE_X_FUNC);
3336             break;
3337 
3338           case 0xb6:            /* LDX $nn,Y */
3339             LDX(LOAD_DIRECT_PAGE_Y_FUNC);
3340             break;
3341 
3342           case 0xb7:            /* LDA [$nn],Y */
3343             LDA(LOAD_INDIRECT_LONG_Y_FUNC);
3344             break;
3345 
3346           case 0xb8:            /* CLV */
3347             CLV();
3348             break;
3349 
3350           case 0xb9:            /* LDA $nnnn,Y */
3351             LDA(LOAD_ABS_Y_FUNC);
3352             break;
3353 
3354           case 0xba:            /* TSX */
3355             TSX();
3356             break;
3357 
3358           case 0xbb:            /* TYX */
3359             TYX();
3360             break;
3361 
3362           case 0xbc:            /* LDY $nnnn,X */
3363             LDY(LOAD_ABS_X_FUNC);
3364             break;
3365 
3366           case 0xbd:            /* LDA $nnnn,X */
3367             LDA(LOAD_ABS_X_FUNC);
3368             break;
3369 
3370           case 0xbe:            /* LDX $nnnn,Y */
3371             LDX(LOAD_ABS_Y_FUNC);
3372             break;
3373 
3374           case 0xbf:            /* LDA $nnnnnn,X */
3375             LDA(LOAD_ABS_LONG_X_FUNC);
3376             break;
3377 
3378           case 0xc0:            /* CPY #$nn */
3379             CPY(LOAD_IMMEDIATE_FUNC);
3380             break;
3381 
3382           case 0xc1:            /* CMP ($nn,X) */
3383             CMP(LOAD_INDIRECT_X_FUNC);
3384             break;
3385 
3386           case 0xc2:            /* REP #$nn */
3387             REP(LOAD_IMMEDIATE_FUNC);
3388             break;
3389 
3390           case 0xc3:            /* CMP $nn,S */
3391             CMP(LOAD_STACK_REL_FUNC);
3392             break;
3393 
3394           case 0xc4:            /* CPY $nn */
3395             CPY(LOAD_DIRECT_PAGE_FUNC);
3396             break;
3397 
3398           case 0xc5:            /* CMP $nn */
3399             CMP(LOAD_DIRECT_PAGE_FUNC);
3400             break;
3401 
3402           case 0xc6:            /* DEC $nn */
3403             DEC(LOAD_DIRECT_PAGE_FUNC_RRW, STORE_DIRECT_PAGE_RRW);
3404             break;
3405 
3406           case 0xc7:            /* CMP [$nn] */
3407             CMP(LOAD_INDIRECT_LONG_FUNC);
3408             break;
3409 
3410           case 0xc8:            /* INY */
3411             INY();
3412             break;
3413 
3414           case 0xc9:            /* CMP #$nn */
3415             CMP(LOAD_IMMEDIATE_FUNC);
3416             break;
3417 
3418           case 0xca:            /* DEX */
3419             DEX();
3420             break;
3421 
3422           case 0xcb:            /* WAI */
3423             WAI_65816();
3424             break;
3425 
3426           case 0xcc:            /* CPY $nnnn */
3427             CPY(LOAD_ABS_FUNC);
3428             break;
3429 
3430           case 0xcd:            /* CMP $nnnn */
3431             CMP(LOAD_ABS_FUNC);
3432             break;
3433 
3434           case 0xce:            /* DEC $nnnn */
3435             DEC(LOAD_ABS_FUNC_RRW, STORE_ABS_RRW);
3436             break;
3437 
3438           case 0xcf:            /* CMP $nnnnnn */
3439             CMP(LOAD_ABS_LONG_FUNC);
3440             break;
3441 
3442           case 0xd0:            /* BNE $nnnn */
3443             BRANCH(!LOCAL_ZERO());
3444             break;
3445 
3446           case 0xd1:            /* CMP ($nn),Y */
3447             CMP(LOAD_INDIRECT_Y_FUNC);
3448             break;
3449 
3450           case 0xd2:            /* CMP ($nn) */
3451             CMP(LOAD_INDIRECT_FUNC);
3452             break;
3453 
3454           case 0xd3:            /* CMP ($nn,S),Y */
3455             CMP(LOAD_STACK_REL_Y_FUNC);
3456             break;
3457 
3458           case 0xd4:            /* PEI ($nn) */
3459             PEI();
3460             break;
3461 
3462           case 0xd5:            /* CMP $nn,X */
3463             CMP(LOAD_DIRECT_PAGE_X_FUNC);
3464             break;
3465 
3466           case 0xd6:            /* DEC $nn,X */
3467             DEC(LOAD_DIRECT_PAGE_X_FUNC_RRW, STORE_DIRECT_PAGE_X_RRW);
3468             break;
3469 
3470           case 0xd7:            /* CMP [$nn],Y */
3471             CMP(LOAD_INDIRECT_LONG_Y_FUNC);
3472             break;
3473 
3474           case 0xd8:            /* CLD */
3475             CLD();
3476             break;
3477 
3478           case 0xd9:            /* CMP $nnnn,Y */
3479             CMP(LOAD_ABS_Y_FUNC);
3480             break;
3481 
3482           case 0xda:            /* PHX */
3483             PHX(STORE_STACK);
3484             break;
3485 
3486           case 0xdb:            /* STP (WDC65C02) */
3487             STP_65816();
3488             break;
3489 
3490           case 0xdc:            /* JMP [$nnnn] */
3491             JMP_IND_LONG();
3492             break;
3493 
3494           case 0xdd:            /* CMP $nnnn,X */
3495             CMP(LOAD_ABS_X_FUNC);
3496             break;
3497 
3498           case 0xde:            /* DEC $nnnn,X */
3499             DEC(LOAD_ABS_X_FUNC_RRW, STORE_ABS_X_RRW);
3500             break;
3501 
3502           case 0xdf:            /* CMP $nnnnnn,X */
3503             CMP(LOAD_ABS_LONG_X_FUNC);
3504             break;
3505 
3506           case 0xe0:            /* CPX #$nn */
3507             CPX(LOAD_IMMEDIATE_FUNC);
3508             break;
3509 
3510           case 0xe1:            /* SBC ($nn,X) */
3511             SBC(LOAD_INDIRECT_X_FUNC);
3512             break;
3513 
3514           case 0xe2:            /* SEP #$nn */
3515             SEP(LOAD_IMMEDIATE_FUNC);
3516             break;
3517 
3518           case 0xe3:            /* SBC $nn,S */
3519             SBC(LOAD_STACK_REL_FUNC);
3520             break;
3521 
3522           case 0xe4:            /* CPX $nn */
3523             CPX(LOAD_DIRECT_PAGE_FUNC);
3524             break;
3525 
3526           case 0xe5:            /* SBC $nn */
3527             SBC(LOAD_DIRECT_PAGE_FUNC);
3528             break;
3529 
3530           case 0xe6:            /* INC $nn */
3531             INC(LOAD_DIRECT_PAGE_FUNC_RRW, STORE_DIRECT_PAGE_RRW);
3532             break;
3533 
3534           case 0xe7:            /* SBC [$nn] */
3535             SBC(LOAD_INDIRECT_LONG_FUNC);
3536             break;
3537 
3538           case 0xe8:            /* INX */
3539             INX();
3540             break;
3541 
3542           case 0xe9:            /* SBC #$nn */
3543             SBC(LOAD_IMMEDIATE_FUNC);
3544             break;
3545 
3546           case 0xea:            /* NOP */
3547             NOP();
3548             break;
3549 
3550           case 0xeb:            /* XBA */
3551             XBA();
3552             break;
3553 
3554           case 0xec:            /* CPX $nnnn */
3555             CPX(LOAD_ABS_FUNC);
3556             break;
3557 
3558           case 0xed:            /* SBC $nnnn */
3559             SBC(LOAD_ABS_FUNC);
3560             break;
3561 
3562           case 0xee:            /* INC $nnnn */
3563             INC(LOAD_ABS_FUNC_RRW, STORE_ABS_RRW);
3564             break;
3565 
3566           case 0xef:            /* SBC $nnnnnn */
3567             SBC(LOAD_ABS_LONG_FUNC);
3568             break;
3569 
3570           case 0xf0:            /* BEQ $nnnn */
3571             BRANCH(LOCAL_ZERO());
3572             break;
3573 
3574           case 0xf1:            /* SBC ($nn),Y */
3575             SBC(LOAD_INDIRECT_Y_FUNC);
3576             break;
3577 
3578           case 0xf2:            /* SBC ($nn) */
3579             SBC(LOAD_INDIRECT_FUNC);
3580             break;
3581 
3582           case 0xf3:            /* SBC ($nn,S),Y */
3583             SBC(LOAD_STACK_REL_Y_FUNC);
3584             break;
3585 
3586           case 0xf4:            /* PEA $nnnn */
3587             PEA();
3588             break;
3589 
3590           case 0xf5:            /* SBC $nn,X */
3591             SBC(LOAD_DIRECT_PAGE_X_FUNC);
3592             break;
3593 
3594           case 0xf6:            /* INC $nn,X */
3595             INC(LOAD_DIRECT_PAGE_X_FUNC_RRW, STORE_DIRECT_PAGE_X_RRW);
3596             break;
3597 
3598           case 0xf7:            /* SBC [$nn],Y */
3599             SBC(LOAD_INDIRECT_LONG_Y_FUNC);
3600             break;
3601 
3602           case 0xf8:            /* SED */
3603             SED();
3604             break;
3605 
3606           case 0xf9:            /* SBC $nnnn,Y */
3607             SBC(LOAD_ABS_Y_FUNC);
3608             break;
3609 
3610           case 0xfa:            /* PLX */
3611             PLX(LOAD_STACK);
3612             break;
3613 
3614           case 0xfb:            /* XCE */
3615             XCE();
3616             break;
3617 
3618           case 0xfc:            /* JSR ($nnnn,X) */
3619             JSR_IND_X();
3620             break;
3621 
3622           case 0xfd:            /* SBC $nnnn,X */
3623             SBC(LOAD_ABS_X_FUNC);
3624             break;
3625 
3626           case 0xfe:            /* INC $nnnn,X */
3627             INC(LOAD_ABS_X_FUNC_RRW, STORE_ABS_X_RRW);
3628             break;
3629 
3630           case 0xff:            /* SBC $nnnnnn,X */
3631             SBC(LOAD_ABS_LONG_X_FUNC);
3632             break;
3633 
3634           case 0x100:           /* IRQ */
3635             IRQ();
3636             break;
3637 
3638           case 0x101:           /* NMI */
3639             NMI();
3640             break;
3641 
3642           case 0x102:           /* RES */
3643             RES();
3644             break;
3645         }
3646 #ifdef DEBUG
3647         if (TRACEFLG && p0 < 0x100) {
3648             uint8_t op = (uint8_t)(p0);
3649             uint8_t lo = (uint8_t)(p1);
3650             uint8_t hi = (uint8_t)(p2 >> 8);
3651             uint8_t bk = (uint8_t)(p3 >> 16);
3652 
3653             debug_main65816cpu((uint32_t)(debug_pc), debug_clk,
3654                           mon_disassemble_to_string(e_comp_space,
3655                                                     debug_pc, op,
3656                                                     lo, hi, bk, 1, "65816"),
3657                           debug_c, debug_x, debug_y, debug_sp, debug_pbr);
3658         }
3659         if (debug.perform_break_into_monitor)
3660         {
3661             monitor_startup_trap();
3662             debug.perform_break_into_monitor = 0;
3663         }
3664 #endif
3665     }
3666 }
3667