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