cpu.cpp
1 /* 2 Copyright Mike Chambers, Frank Bösing, 2017 3 Parts of this file are based on "Fake6502 CPU emulator core v1.1" by Mike Chambers 4 5 6 This file is part of Teensy64. 7 8 Teensy64 is free software: you can redistribute it and/or modify 9 it under the terms of the GNU General Public License as published by 10 the Free Software Foundation, either version 3 of the License, or 11 (at your option) any later version. 12 13 Teensy64 is distributed in the hope that it will be useful, 14 but WITHOUT ANY WARRANTY; without even the implied warranty of 15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 GNU General Public License for more details. 17 18 You should have received a copy of the GNU General Public License 19 along with Teensy64. If not, see <http://www.gnu.org/licenses/>. 20 21 Diese Datei ist Teil von Teensy64. 22 23 Teensy64 ist Freie Software: Sie können es unter den Bedingungen 24 der GNU General Public License, wie von der Free Software Foundation, 25 Version 3 der Lizenz oder (nach Ihrer Wahl) jeder späteren 26 veröffentlichten Version, weiterverbreiten und/oder modifizieren. 27 28 Teensy64 wird in der Hoffnung, dass es nützlich sein wird, aber 29 OHNE JEDE GEWÄHRLEISTUNG, bereitgestellt; sogar ohne die implizite 30 Gewährleistung der MARKTFÄHIGKEIT oder EIGNUNG FÜR EINEN BESTIMMTEN ZWECK. 31 Siehe die GNU General Public License für weitere Details. 32 33 Sie sollten eine Kopie der GNU General Public License zusammen mit diesem 34 Programm erhalten haben. Wenn nicht, siehe <http://www.gnu.org/licenses/>. 35 36 */ 37 38 /* Fake6502 CPU emulator core v1.1 ******************* 39 * (c)2011 Mike Chambers (miker00lz@gmail.com) * 40 ***************************************************** 41 * LICENSE: This source code is released into the * 42 * public domain, but if you use it please do give * 43 * credit. I put a lot of effort into writing this! * 44 * * 45 ***************************************************** 46 */ 47 48 #include "cpu.h" 49 50 #define FLAG_CARRY 0x01 51 #define FLAG_ZERO 0x02 52 #define FLAG_INTERRUPT 0x04 53 #define FLAG_DECIMAL 0x08 54 #define FLAG_BREAK 0x10 55 #define FLAG_CONSTANT 0x20 56 #define FLAG_OVERFLOW 0x40 57 #define FLAG_SIGN 0x80 58 59 //flag modifier macros 60 #define setcarry() cpu.cpustatus |= FLAG_CARRY 61 #define clearcarry() cpu.cpustatus &= (~FLAG_CARRY) 62 #define setzero() cpu.cpustatus |= FLAG_ZERO 63 #define clearzero() cpu.cpustatus &= (~FLAG_ZERO) 64 #define setinterrupt() cpu.cpustatus |= FLAG_INTERRUPT 65 #define clearinterrupt() cpu.cpustatus &= (~FLAG_INTERRUPT) 66 #define setdecimal() cpu.cpustatus |= FLAG_DECIMAL 67 #define cleardecimal() cpu.cpustatus &= (~FLAG_DECIMAL) 68 #define setoverflow() cpu.cpustatus |= FLAG_OVERFLOW 69 #define clearoverflow() cpu.cpustatus &= (~FLAG_OVERFLOW) 70 #define setsign() cpu.cpustatus |= FLAG_SIGN 71 #define clearsign() cpu.cpustatus &= (~FLAG_SIGN) 72 73 74 //flag calculation macros 75 #define zerocalc(n) { if ((n) & 0x00FF) clearzero(); else setzero(); } 76 //#define signcalc(n) { if ((n) & 0x0080) setsign(); else clearsign(); } 77 #define signcalc(n) { cpu.cpustatus =( cpu.cpustatus & 0x7f) | (n & 0x80); } 78 #define carrycalc(n) { if ((n) & 0xFF00) setcarry(); else clearcarry(); } 79 //#define carrycalc(n) {cpu.cpustatus =( cpu.cpustatus & 0xfe) | (n >> 8); } 80 #define overflowcalc(n, m, o) { if (((n) ^ (uint16_t)(m)) & ((n) ^ (o)) & 0x0080) setoverflow(); else clearoverflow(); } 81 82 #define saveaccum(n) cpu.a = (uint8_t)((n) & 0x00FF) 83 84 #define UNSUPPORTED { printf("Unsupported Opcode\n"); while(1){;} } 85 86 void logAddr(const uint32_t address, const uint8_t value, const uint8_t rw) { 87 if (rw) printf("Write "); else printf("Read "); 88 printf("0x%d=0x%d\n",address,value); 89 90 } 91 struct tcpu cpu; 92 struct tio io; 93 94 void reset6502(); 95 void cpu_nmi(); 96 static inline void cpu_irq(); 97 98 INLINEOP uint8_t read6502(const uint32_t address) __attribute__ ((hot)); 99 INLINEOP uint8_t read6502(const uint32_t address) { 100 return (*cpu.plamap_r)[address >> 8](address); 101 } 102 103 INLINEOP uint8_t read6502ZP(const uint32_t address) __attribute__ ((hot)); //Zeropage 104 INLINEOP uint8_t read6502ZP(const uint32_t address) { 105 return cpu.RAM[address & 0xff]; 106 } 107 108 /* Ein Schreibzugriff auf einen ROM-Bereich speichert das Byte im „darunterliegenden” RAM. */ 109 INLINEOP void write6502(const uint32_t address, const uint8_t value) __attribute__ ((hot)); 110 INLINEOP void write6502(const uint32_t address, const uint8_t value) { 111 (*cpu.plamap_w)[address>>8](address, value); 112 } 113 114 //a few general functions used by various other functions 115 INLINEOP void push16(const uint16_t pushval) { 116 cpu.RAM[BASE_STACK + cpu.sp] = (pushval >> 8) & 0xFF; 117 cpu.RAM[BASE_STACK + ((cpu.sp - 1) & 0xFF)] = pushval & 0xFF; 118 cpu.sp -= 2; 119 } 120 121 INLINEOP uint16_t pull16() { 122 uint16_t temp16; 123 temp16 = cpu.RAM[BASE_STACK + ((cpu.sp + 1) & 0xFF)] | ((uint16_t)cpu.RAM[BASE_STACK + ((cpu.sp + 2) & 0xFF)] << 8); 124 cpu.sp += 2; 125 return(temp16); 126 } 127 128 INLINEOP void push8(uint8_t pushval) { 129 cpu.RAM[BASE_STACK + (cpu.sp--)] = pushval; 130 131 } 132 133 INLINEOP uint8_t pull8() { 134 return cpu.RAM[BASE_STACK + (++cpu.sp)]; 135 } 136 137 /********************************************************************************************************************/ 138 /*addressing mode functions, calculates effective addresses */ 139 /********************************************************************************************************************/ 140 141 INLINEOP void imp() { //implied 142 } 143 144 INLINEOP void acc() { //accumulator 145 } 146 147 INLINEOP void imm() { //immediate 148 cpu.ea = cpu.pc++; 149 } 150 151 INLINEOP void zp() { //zero-page 152 cpu.ea = read6502(cpu.pc++) & 0xFF; 153 } 154 155 INLINEOP void zpx() { //zero-page,X 156 cpu.ea = (read6502(cpu.pc++) + cpu.x) & 0xFF; //zero-page wraparound 157 } 158 159 INLINEOP void zpy() { //zero-page,Y 160 cpu.ea = (read6502(cpu.pc++) + cpu.y) & 0xFF; //zero-page wraparound 161 } 162 163 INLINEOP void rel() { //relative for branch ops (8-bit immediate value, sign-extended) 164 cpu.reladdr = read6502(cpu.pc++); 165 if (cpu.reladdr & 0x80) cpu.reladdr |= 0xFF00; 166 } 167 168 INLINEOP void abso() { //absolute 169 cpu.ea = read6502(cpu.pc) | (read6502(cpu.pc + 1) << 8); 170 cpu.pc += 2; 171 } 172 173 INLINEOP void absx() { //absolute,X 174 cpu.ea = (read6502(cpu.pc) | (read6502(cpu.pc + 1) << 8)) + cpu.x; 175 cpu.pc += 2; 176 } 177 178 INLINEOP void absx_t() { //absolute,X with extra cycle 179 uint16_t h = read6502(cpu.pc) + cpu.x; 180 if (h & 0x100) cpu.ticks += 1; 181 cpu.ea = h + (read6502(cpu.pc + 1) << 8); 182 cpu.pc += 2; 183 } 184 185 INLINEOP void absy() { //absolute,Y 186 cpu.ea = (read6502(cpu.pc) + (read6502(cpu.pc + 1) << 8)) + cpu.y; 187 cpu.pc += 2; 188 } 189 190 INLINEOP void absy_t() { //absolute,Y with extra cycle 191 uint16_t h = read6502(cpu.pc) + cpu.y; 192 if (h & 0x100) cpu.ticks += 1; 193 cpu.ea = h + (read6502(cpu.pc + 1) << 8); 194 cpu.pc += 2; 195 } 196 197 INLINEOP void ind() { //indirect 198 uint16_t eahelp, eahelp2; 199 eahelp = read6502(cpu.pc) | (read6502(cpu.pc + 1) << 8); 200 eahelp2 = (eahelp & 0xFF00) | ((eahelp + 1) & 0x00FF); //replicate 6502 page-boundary wraparound bug 201 cpu.ea = read6502(eahelp) | (read6502(eahelp2) << 8); 202 cpu.pc += 2; 203 } 204 205 INLINEOP void indx() { // (indirect,X) 206 uint32_t eahelp; 207 eahelp = (read6502(cpu.pc++) + cpu.x) & 0xFF; //zero-page wraparound for table pointer 208 cpu.ea = read6502ZP((uint8_t)eahelp) | (read6502ZP((uint8_t)(eahelp + 1)) << 8); 209 } 210 211 INLINEOP void indy() { // (zeropage indirect),Y 212 uint8_t zp = read6502(cpu.pc++); 213 cpu.ea = read6502ZP((uint16_t) zp++); 214 cpu.ea += (uint16_t) read6502ZP((uint16_t) zp) << 8; 215 cpu.ea += cpu.y; 216 } 217 218 INLINEOP void indy_t() { // (zeropage indirect),Y with extra cycle 219 uint8_t zp = read6502(cpu.pc++); 220 uint16_t h; 221 h = read6502ZP((uint16_t) zp++); 222 h += (uint16_t) read6502ZP((uint16_t) zp) << 8; 223 if (((h + cpu.y) & 0xff) != (h & 0xff)) cpu.ticks += 1; 224 cpu.ea = h + cpu.y; 225 } 226 227 INLINEOP uint32_t getvalue() __attribute__ ((hot)); 228 INLINEOP uint32_t getvalue() { 229 return read6502(cpu.ea); 230 } 231 232 INLINEOP uint32_t getvalueZP() __attribute__ ((hot)); 233 INLINEOP uint32_t getvalueZP() { 234 return read6502ZP(cpu.ea); 235 } 236 237 INLINEOP void putvalue(const uint8_t saveval) __attribute__ ((hot)); 238 INLINEOP void putvalue(const uint8_t saveval) { 239 write6502(cpu.ea, saveval); 240 } 241 242 243 /********************************************************************************************************************/ 244 /* instruction handler functions */ 245 /********************************************************************************************************************/ 246 247 /* 248 Aliases used in other illegal opcode sources: 249 250 SLO = ASO 251 SRE = LSE 252 ISC = ISB 253 ALR = ASR 254 SHX = A11 (A11 was a result of only having tested this one on adress $1000) 255 SHY = A11 256 LAS = LAR 257 KIL = JAM, HLT 258 */ 259 260 #define SETFLAGS(data) \ 261 { \ 262 if (!(data)) \ 263 cpu.cpustatus = (cpu.cpustatus & ~FLAG_SIGN) | FLAG_ZERO; \ 264 else \ 265 cpu.cpustatus = (cpu.cpustatus & ~(FLAG_SIGN|FLAG_ZERO)) | \ 266 ((data) & FLAG_SIGN); \ 267 } 268 269 270 INLINEOP void _adc(unsigned data) { 271 unsigned tempval = data; 272 unsigned temp; 273 if (cpu.cpustatus & FLAG_DECIMAL) { 274 temp = (cpu.a & 0x0f) + (tempval & 0x0f) + (cpu.cpustatus & FLAG_CARRY); 275 if (temp > 9) temp += 6; 276 if (temp <= 0x0f) 277 temp = (temp & 0xf) + (cpu.a & 0xf0) + (tempval & 0xf0); 278 else 279 temp = (temp & 0xf) + (cpu.a & 0xf0) + (tempval & 0xf0) + 0x10; 280 if (!((cpu.a + tempval + (cpu.cpustatus & FLAG_CARRY)) & 0xff)) 281 setzero(); 282 else 283 clearzero(); 284 signcalc(temp); 285 if (((cpu.a ^ temp) & 0x80) && !((cpu.a ^ tempval) & 0x80)) 286 setoverflow(); 287 else 288 clearoverflow(); 289 if ((temp & 0x1f0) > 0x90) temp += 0x60; 290 if ((temp & 0xff0) > 0xf0) 291 setcarry(); 292 else 293 clearcarry(); 294 } else { 295 temp = tempval + cpu.a + (cpu.cpustatus & FLAG_CARRY); 296 SETFLAGS(temp & 0xff); 297 if (!((cpu.a ^ tempval) & 0x80) && ((cpu.a ^ temp) & 0x80)) 298 setoverflow(); 299 else 300 clearoverflow(); 301 if (temp > 0xff) 302 setcarry(); 303 else 304 clearcarry(); 305 } 306 saveaccum(temp); 307 } 308 309 INLINEOP void _sbc(unsigned data) { 310 unsigned tempval = data; 311 unsigned temp; 312 313 temp = cpu.a - tempval - ((cpu.cpustatus & FLAG_CARRY) ^ FLAG_CARRY); 314 315 if (cpu.cpustatus & FLAG_DECIMAL) { 316 unsigned tempval2; 317 tempval2 = (cpu.a & 0x0f) - (tempval & 0x0f) - ((cpu.cpustatus & FLAG_CARRY) ^ FLAG_CARRY); 318 if (tempval2 & 0x10) 319 tempval2 = ((tempval2 - 6) & 0xf) | ((cpu.a & 0xf0) - (tempval & 0xf0) - 0x10); 320 else 321 tempval2 = (tempval2 & 0xf) | ((cpu.a & 0xf0) - (tempval & 0xf0)); 322 if (tempval2 & 0x100) 323 tempval2 -= 0x60; 324 if (temp < 0x100) 325 setcarry(); 326 else 327 clearcarry(); 328 SETFLAGS(temp & 0xff); 329 if (((cpu.a ^ temp) & 0x80) && ((cpu.a ^ tempval) & 0x80)) 330 setoverflow(); 331 else 332 clearoverflow(); 333 saveaccum(tempval2); 334 } else { 335 SETFLAGS(temp & 0xff); 336 if (temp < 0x100) 337 setcarry(); 338 else 339 clearcarry(); 340 if (((cpu.a ^ temp) & 0x80) && ((cpu.a ^ tempval) & 0x80)) 341 setoverflow(); 342 else 343 clearoverflow(); 344 saveaccum(temp); 345 } 346 347 } 348 349 INLINEOP void adc() { 350 unsigned data = getvalue(); 351 _adc(data); 352 } 353 354 INLINEOP void adcZP() { 355 unsigned data = getvalueZP(); 356 _adc(data); 357 358 } 359 360 INLINEOP void op_and() { 361 uint32_t result = cpu.a & getvalue(); 362 zerocalc(result); 363 signcalc(result); 364 saveaccum(result); 365 } 366 367 INLINEOP void op_andZP() { 368 uint32_t result = cpu.a & getvalueZP(); 369 zerocalc(result); 370 signcalc(result); 371 saveaccum(result); 372 } 373 374 INLINEOP void asl() { 375 uint32_t result = getvalue(); 376 result <<=1; 377 carrycalc(result); 378 zerocalc(result); 379 signcalc(result); 380 putvalue(result); 381 } 382 383 INLINEOP void aslZP() { 384 uint32_t result = getvalueZP(); 385 result <<=1; 386 carrycalc(result); 387 zerocalc(result); 388 signcalc(result); 389 putvalue(result); 390 } 391 392 INLINEOP void asla() { 393 uint32_t result = cpu.a << 1; 394 carrycalc(result); 395 zerocalc(result); 396 signcalc(result); 397 saveaccum(result); 398 } 399 400 INLINEOP void bcc() { 401 if ((cpu.cpustatus & FLAG_CARRY) == 0) { 402 uint32_t oldpc = cpu.pc; 403 cpu.pc += cpu.reladdr; 404 if ((oldpc & 0xFF00) != (cpu.pc & 0xFF00)) cpu.ticks += 2; //check if jump crossed a page boundary 405 else cpu.ticks++; 406 } 407 } 408 409 INLINEOP void bcs() { 410 if ((cpu.cpustatus & FLAG_CARRY) == FLAG_CARRY) { 411 uint32_t oldpc = cpu.pc; 412 cpu.pc += cpu.reladdr; 413 if ((oldpc & 0xFF00) != (cpu.pc & 0xFF00)) cpu.ticks += 2; //check if jump crossed a page boundary 414 else cpu.ticks++; 415 } 416 } 417 418 INLINEOP void beq() { 419 if ((cpu.cpustatus & FLAG_ZERO) == FLAG_ZERO) { 420 uint32_t oldpc = cpu.pc; 421 cpu.pc += cpu.reladdr; 422 if ((oldpc & 0xFF00) != (cpu.pc & 0xFF00)) cpu.ticks += 2; //check if jump crossed a page boundary 423 else cpu.ticks++; 424 } 425 } 426 427 INLINEOP void op_bit() { 428 unsigned value = getvalue(); 429 cpu.cpustatus = (cpu.cpustatus & ~(FLAG_SIGN|FLAG_OVERFLOW)) | (value & (FLAG_SIGN|FLAG_OVERFLOW)); 430 if (!(value & cpu.a)) 431 setzero(); 432 else 433 clearzero(); 434 /* 435 uint32_t value = getvalue(); 436 uint32_t result = (uint16_t)cpu.a & value; 437 438 zerocalc(result); 439 cpu.cpustatus = (cpu.cpustatus & 0x3F) | (uint8_t)(value & 0xC0); 440 */ 441 } 442 443 INLINEOP void op_bitZP() { 444 unsigned value = getvalueZP(); 445 cpu.cpustatus = (cpu.cpustatus & ~(FLAG_SIGN|FLAG_OVERFLOW)) | (value & (FLAG_SIGN|FLAG_OVERFLOW)); 446 if (!(value & cpu.a)) 447 setzero(); 448 else 449 clearzero(); 450 } 451 452 INLINEOP void bmi() { 453 if ((cpu.cpustatus & FLAG_SIGN) == FLAG_SIGN) { 454 uint32_t oldpc = cpu.pc; 455 cpu.pc += cpu.reladdr; 456 if ((oldpc & 0xFF00) != (cpu.pc & 0xFF00)) cpu.ticks += 2; //check if jump crossed a page boundary 457 else cpu.ticks++; 458 } 459 } 460 461 INLINEOP void bne() { 462 if ((cpu.cpustatus & FLAG_ZERO) == 0) { 463 uint32_t oldpc = cpu.pc; 464 cpu.pc += cpu.reladdr; 465 if ((oldpc & 0xFF00) != (cpu.pc & 0xFF00)) cpu.ticks += 2; //check if jump crossed a page boundary 466 else cpu.ticks++; 467 } 468 } 469 470 INLINEOP void bpl() { 471 if ((cpu.cpustatus & FLAG_SIGN) == 0) { 472 uint32_t oldpc = cpu.pc; 473 cpu.pc += cpu.reladdr; 474 if ((oldpc & 0xFF00) != (cpu.pc & 0xFF00)) cpu.ticks += 2; //check if jump crossed a page boundary 475 else cpu.ticks++; 476 } 477 } 478 479 INLINEOP void brk() { 480 cpu.pc++; 481 push16(cpu.pc); //push next instruction address onto stack 482 push8(cpu.cpustatus | FLAG_BREAK); //push CPU cpustatus to stack 483 setinterrupt(); //set interrupt flag 484 cpu.pc = read6502(0xFFFE) | (read6502(0xFFFF) << 8); 485 } 486 487 INLINEOP void bvc() { 488 if ((cpu.cpustatus & FLAG_OVERFLOW) == 0) { 489 uint32_t oldpc = cpu.pc; 490 cpu.pc += cpu.reladdr; 491 if ((oldpc & 0xFF00) != (cpu.pc & 0xFF00)) cpu.ticks += 2; //check if jump crossed a page boundary 492 else cpu.ticks++; 493 } 494 } 495 496 INLINEOP void bvs() { 497 if ((cpu.cpustatus & FLAG_OVERFLOW) == FLAG_OVERFLOW) { 498 uint32_t oldpc = cpu.pc; 499 cpu.pc += cpu.reladdr; 500 if ((oldpc & 0xFF00) != (cpu.pc & 0xFF00)) cpu.ticks += 2; //check if jump crossed a page boundary 501 else cpu.ticks++; 502 } 503 } 504 505 INLINEOP void clc() { 506 clearcarry(); 507 } 508 509 INLINEOP void cld() { 510 cleardecimal(); 511 } 512 513 INLINEOP void cli_() { 514 clearinterrupt(); 515 } 516 517 INLINEOP void clv() { 518 clearoverflow(); 519 } 520 521 INLINEOP void cmp() { 522 uint16_t value = getvalue(); 523 uint32_t result = (uint16_t)cpu.a - value; 524 525 if (cpu.a >= (uint8_t)(value & 0x00FF)) setcarry(); 526 else clearcarry(); 527 if (cpu.a == (uint8_t)(value & 0x00FF)) setzero(); 528 else clearzero(); 529 signcalc(result); 530 } 531 532 INLINEOP void cmpZP() { 533 uint16_t value = getvalueZP(); 534 uint32_t result = (uint16_t)cpu.a - value; 535 536 if (cpu.a >= (uint8_t)(value & 0x00FF)) setcarry(); 537 else clearcarry(); 538 if (cpu.a == (uint8_t)(value & 0x00FF)) setzero(); 539 else clearzero(); 540 signcalc(result); 541 } 542 543 INLINEOP void cpx() { 544 uint16_t value = getvalue(); 545 uint16_t result = (uint16_t)cpu.x - value; 546 547 if (cpu.x >= (uint8_t)(value & 0x00FF)) setcarry(); 548 else clearcarry(); 549 if (cpu.x == (uint8_t)(value & 0x00FF)) setzero(); 550 else clearzero(); 551 signcalc(result); 552 } 553 554 INLINEOP void cpxZP() { 555 uint16_t value = getvalueZP(); 556 uint16_t result = (uint16_t)cpu.x - value; 557 558 if (cpu.x >= (uint8_t)(value & 0x00FF)) setcarry(); 559 else clearcarry(); 560 if (cpu.x == (uint8_t)(value & 0x00FF)) setzero(); 561 else clearzero(); 562 signcalc(result); 563 } 564 565 INLINEOP void cpy() { 566 uint16_t value = getvalue(); 567 uint16_t result = (uint16_t)cpu.y - value; 568 569 if (cpu.y >= (uint8_t)(value & 0x00FF)) setcarry(); 570 else clearcarry(); 571 if (cpu.y == (uint8_t)(value & 0x00FF)) setzero(); 572 else clearzero(); 573 signcalc(result); 574 } 575 576 INLINEOP void cpyZP() { 577 uint16_t value = getvalueZP(); 578 uint16_t result = (uint16_t)cpu.y - value; 579 580 if (cpu.y >= (uint8_t)(value & 0x00FF)) setcarry(); 581 else clearcarry(); 582 if (cpu.y == (uint8_t)(value & 0x00FF)) setzero(); 583 else clearzero(); 584 signcalc(result); 585 } 586 587 INLINEOP void dec() { 588 uint32_t result = getvalue() - 1; 589 590 zerocalc(result); 591 signcalc(result); 592 593 putvalue(result); 594 } 595 596 INLINEOP void decZP() { 597 uint32_t result = getvalueZP() - 1; 598 599 zerocalc(result); 600 signcalc(result); 601 602 putvalue(result); 603 } 604 605 INLINEOP void dex() { 606 cpu.x--; 607 608 zerocalc(cpu.x); 609 signcalc(cpu.x); 610 } 611 612 INLINEOP void dey() { 613 cpu.y--; 614 615 zerocalc(cpu.y); 616 signcalc(cpu.y); 617 } 618 619 INLINEOP void eor() { 620 uint32_t result = cpu.a ^ getvalue(); 621 622 zerocalc(result); 623 signcalc(result); 624 625 saveaccum(result); 626 } 627 628 INLINEOP void eorZP() { 629 uint32_t result = cpu.a ^ getvalueZP(); 630 631 zerocalc(result); 632 signcalc(result); 633 634 saveaccum(result); 635 } 636 637 INLINEOP void inc() { 638 uint32_t result = getvalue() + 1; 639 640 zerocalc(result); 641 signcalc(result); 642 643 putvalue(result); 644 } 645 646 INLINEOP void incZP() { 647 uint32_t result = getvalueZP() + 1; 648 649 zerocalc(result); 650 signcalc(result); 651 652 putvalue(result); 653 } 654 655 INLINEOP void inx() { 656 cpu.x++; 657 658 zerocalc(cpu.x); 659 signcalc(cpu.x); 660 } 661 662 INLINEOP void iny() { 663 cpu.y++; 664 665 zerocalc(cpu.y); 666 signcalc(cpu.y); 667 } 668 669 INLINEOP void jmp() { 670 cpu.pc = cpu.ea; 671 } 672 673 INLINEOP void jsr() { 674 push16(cpu.pc - 1); 675 cpu.pc = cpu.ea; 676 } 677 678 INLINEOP void lda() { 679 cpu.a = getvalue(); 680 681 zerocalc(cpu.a); 682 signcalc(cpu.a); 683 } 684 685 INLINEOP void ldaZP() { 686 cpu.a = getvalueZP(); 687 688 zerocalc(cpu.a); 689 signcalc(cpu.a); 690 } 691 692 INLINEOP void ldx() { 693 cpu.x = getvalue(); 694 695 zerocalc(cpu.x); 696 signcalc(cpu.x); 697 } 698 699 INLINEOP void ldxZP() { 700 cpu.x = getvalue(); 701 702 zerocalc(cpu.x); 703 signcalc(cpu.x); 704 } 705 706 INLINEOP void ldy() { 707 cpu.y = getvalue(); 708 709 zerocalc(cpu.y); 710 signcalc(cpu.y); 711 } 712 713 INLINEOP void ldyZP() { 714 cpu.y = getvalueZP(); 715 716 zerocalc(cpu.y); 717 signcalc(cpu.y); 718 } 719 720 INLINEOP void lsr() { 721 uint32_t value = getvalue(); 722 uint32_t result = value >> 1; 723 724 if (value & 1) setcarry(); 725 else clearcarry(); 726 zerocalc(result); 727 //clearsign(); 728 signcalc(result); 729 730 putvalue(result); 731 } 732 733 INLINEOP void lsrZP() { 734 uint32_t value = getvalue(); 735 uint32_t result = value >> 1; 736 737 if (value & 1) setcarry(); 738 else clearcarry(); 739 zerocalc(result); 740 //clearsign(); 741 signcalc(result); 742 743 putvalue(result); 744 } 745 746 INLINEOP void lsra() { 747 uint8_t value = cpu.a; 748 uint8_t result = value >> 1; 749 750 if (value & 1) setcarry(); 751 else clearcarry(); 752 zerocalc(result); 753 //clearsign(); 754 signcalc(result); 755 saveaccum(result); 756 } 757 758 INLINEOP void ora() { 759 760 uint32_t result = cpu.a | getvalue(); 761 762 zerocalc(result); 763 signcalc(result); 764 765 saveaccum(result); 766 } 767 768 INLINEOP void oraZP() { 769 770 uint32_t result = cpu.a | getvalueZP(); 771 772 zerocalc(result); 773 signcalc(result); 774 775 saveaccum(result); 776 } 777 778 INLINEOP void pha() { 779 push8(cpu.a); 780 } 781 782 INLINEOP void php() { 783 push8(cpu.cpustatus | FLAG_BREAK); 784 } 785 786 INLINEOP void pla() { 787 cpu.a = pull8(); 788 789 zerocalc(cpu.a); 790 signcalc(cpu.a); 791 } 792 793 INLINEOP void plp() { 794 cpu.cpustatus = (pull8() & 0xef) | FLAG_CONSTANT; 795 } 796 797 INLINEOP void rol() { 798 uint16_t value = getvalue(); 799 uint16_t result = (value << 1) | (cpu.cpustatus & FLAG_CARRY); 800 801 carrycalc(result); 802 zerocalc(result); 803 signcalc(result); 804 805 putvalue(result); 806 } 807 808 INLINEOP void rolZP() { 809 uint16_t value = getvalueZP(); 810 uint16_t result = (value << 1) | (cpu.cpustatus & FLAG_CARRY); 811 812 carrycalc(result); 813 zerocalc(result); 814 signcalc(result); 815 816 putvalue(result); 817 } 818 819 INLINEOP void rola() { 820 uint16_t value = cpu.a; 821 uint16_t result = (value << 1) | (cpu.cpustatus & FLAG_CARRY); 822 823 carrycalc(result); 824 zerocalc(result); 825 signcalc(result); 826 saveaccum(result); 827 } 828 829 INLINEOP void ror() { 830 uint32_t value = getvalue(); 831 uint16_t result = (value >> 1) | ((cpu.cpustatus & FLAG_CARRY) << 7); 832 833 if (value & 1) setcarry(); 834 else clearcarry(); 835 zerocalc(result); 836 signcalc(result); 837 838 putvalue(result); 839 } 840 841 INLINEOP void rorZP() { 842 uint32_t value = getvalueZP(); 843 uint16_t result = (value >> 1) | ((cpu.cpustatus & FLAG_CARRY) << 7); 844 845 if (value & 1) setcarry(); 846 else clearcarry(); 847 zerocalc(result); 848 signcalc(result); 849 850 putvalue(result); 851 } 852 853 INLINEOP void rora() { 854 uint32_t value = cpu.a; 855 uint16_t result = (value >> 1) | ((cpu.cpustatus & FLAG_CARRY) << 7); 856 857 if (value & 1) setcarry(); 858 else clearcarry(); 859 zerocalc(result); 860 signcalc(result); 861 saveaccum(result); 862 } 863 864 865 INLINEOP void rti() { 866 cpu.cpustatus = pull8(); 867 cpu.pc = pull16(); 868 } 869 870 INLINEOP void rts() { 871 cpu.pc = pull16() + 1; 872 } 873 874 INLINEOP void sbc() { 875 unsigned data = getvalue(); 876 _sbc(data); 877 } 878 879 INLINEOP void sbcZP() { 880 unsigned data = getvalueZP(); 881 _sbc(data); 882 } 883 884 885 INLINEOP void sec() { 886 setcarry(); 887 } 888 889 INLINEOP void sed() { 890 setdecimal(); 891 } 892 893 INLINEOP void sei_() { 894 setinterrupt(); 895 } 896 897 INLINEOP void sta() { 898 putvalue(cpu.a); 899 } 900 901 INLINEOP void stx() { 902 putvalue(cpu.x); 903 } 904 905 INLINEOP void sty() { 906 putvalue(cpu.y); 907 } 908 909 INLINEOP void tax() { 910 cpu.x = cpu.a; 911 912 zerocalc(cpu.x); 913 signcalc(cpu.x); 914 } 915 916 INLINEOP void tay() { 917 cpu.y = cpu.a; 918 919 zerocalc(cpu.y); 920 signcalc(cpu.y); 921 } 922 923 INLINEOP void tsx() { 924 925 cpu.x = cpu.sp; 926 927 zerocalc(cpu.x); 928 signcalc(cpu.x); 929 930 } 931 932 INLINEOP void txa() { 933 cpu.a = cpu.x; 934 935 zerocalc(cpu.a); 936 signcalc(cpu.a); 937 } 938 939 INLINEOP void txs() { 940 cpu.sp = cpu.x; 941 } 942 943 INLINEOP void tya() { 944 cpu.a = cpu.y; 945 946 zerocalc(cpu.a); 947 signcalc(cpu.a); 948 } 949 950 951 //undocumented instructions 952 INLINEOP void lax() { 953 lda(); 954 ldx(); 955 } 956 957 INLINEOP void sax() { 958 sta(); 959 stx(); 960 putvalue(cpu.a & cpu.x); 961 } 962 963 INLINEOP void dcp() { 964 dec(); 965 cmp(); 966 } 967 968 INLINEOP void isb() { 969 inc(); 970 sbc(); 971 } 972 973 INLINEOP void slo() { 974 asl(); 975 ora(); 976 } 977 978 INLINEOP void rla() { 979 rol(); 980 op_and(); 981 } 982 983 INLINEOP void sre() { 984 lsr(); 985 eor(); 986 } 987 988 INLINEOP void rra() { 989 ror(); 990 adc(); 991 } 992 993 INLINEOP void alr() { // (FB) 994 995 uint32_t result = cpu.a & getvalue() ; 996 997 if (result & 1) setcarry(); 998 else clearcarry(); 999 1000 result = result / 2; 1001 1002 clearsign(); 1003 zerocalc(result); 1004 saveaccum(result); 1005 } 1006 1007 INLINEOP void arr() { //This one took me hours.. finally taken from VICE (FB) 1008 uint32_t result; 1009 result = cpu.a & getvalue(); 1010 if (!(cpu.cpustatus & FLAG_DECIMAL)) { 1011 result >>= 1; 1012 result |= ((cpu.cpustatus & FLAG_CARRY) << 7); 1013 signcalc(result); 1014 zerocalc(result); 1015 if (result & 0x40) setcarry(); else clearcarry(); 1016 if ((result & 0x40) ^ ((result & 0x20)<<1)) setoverflow(); else clearoverflow(); 1017 saveaccum(result); 1018 } else { 1019 uint32_t t2 = result; 1020 t2 >>= 1; 1021 t2 |= ((cpu.cpustatus & FLAG_CARRY) << 7); 1022 if (cpu.cpustatus & FLAG_CARRY) setsign(); else clearsign(); 1023 zerocalc(t2); 1024 if ((t2 ^ result) & 0x40) setoverflow(); else clearoverflow(); 1025 if (((result & 0xf) + (result & 0x1)) > 0x5) { 1026 t2 = (t2 & 0xf0) | ((t2 + 0x6) & 0xf); 1027 } 1028 if (((result & 0xf0) + (result & 0x10)) > 0x50) { 1029 t2 = (t2 & 0x0f) | ((t2 + 0x60) & 0xf0); 1030 setcarry(); 1031 } else { 1032 clearcarry(); 1033 } 1034 saveaccum(t2); 1035 } 1036 1037 } 1038 1039 INLINEOP void xaa() { // AKA ANE 1040 const uint32_t val = 0xee; // VICE uses 0xff - but this results in an error in the testsuite (FB) 1041 uint32_t result = (cpu.a | val) & cpu.x & getvalue(); 1042 signcalc(result); 1043 zerocalc(result); 1044 saveaccum(result); 1045 } 1046 1047 INLINEOP void lxa() { 1048 const uint32_t val = 0xee; 1049 uint32_t result = (cpu.a | val) & getvalue(); 1050 signcalc(result); 1051 zerocalc(result); 1052 cpu.x = result; 1053 saveaccum(result); 1054 } 1055 1056 INLINEOP void axs() { //aka SBX 1057 uint32_t result = getvalue(); 1058 result = (cpu.a & cpu.x) - result; 1059 cpu.x = result; 1060 if (result < 0x100) setcarry(); else clearcarry(); 1061 zerocalc(cpu.x); 1062 signcalc(cpu.x); 1063 } 1064 1065 INLINEOP void ahx() { //todo (is unstable) 1066 UNSUPPORTED 1067 } 1068 1069 INLINEOP void anc() { 1070 uint32_t result = cpu.a & getvalue(); 1071 signcalc(result) 1072 zerocalc(result); 1073 if (cpu.cpustatus & FLAG_SIGN) setcarry(); else clearcarry(); 1074 saveaccum(result); 1075 } 1076 1077 INLINEOP void las() { 1078 uint32_t result = cpu.sp & getvalue(); 1079 signcalc(result); 1080 zerocalc(result); 1081 cpu.sp = result; 1082 cpu.x = result; 1083 saveaccum(result); 1084 } 1085 1086 /********************************************************************************************************************/ 1087 /* OPCODES */ 1088 /********************************************************************************************************************/ 1089 1090 OPCODE void opKIL(void) { 1091 printf("CPU JAM @ $%d\n",cpu.pc); 1092 cpu_reset(); 1093 } 1094 1095 OPCODE void op0x0(void) { 1096 cpu.ticks = 7; 1097 imp(); 1098 brk(); 1099 } 1100 1101 OPCODE void op0x1(void) { 1102 cpu.ticks = 6; 1103 indx(); 1104 ora(); 1105 } 1106 1107 OPCODE void op0x3(void) { //undocumented 1108 cpu.ticks = 8; 1109 indx(); 1110 slo(); 1111 } 1112 1113 OPCODE void op0x4(void) { //nop read zeropage 1114 cpu.ticks = 3; 1115 zp(); 1116 } 1117 1118 OPCODE void op0x5(void) { 1119 cpu.ticks = 3; 1120 zp(); 1121 oraZP(); 1122 } 1123 1124 OPCODE void op0x6(void) { 1125 cpu.ticks = 5; 1126 zp(); 1127 aslZP(); 1128 } 1129 1130 OPCODE void op0x7(void) { //undocumented SLO 1131 cpu.ticks = 5; 1132 zp(); 1133 slo(); 1134 } 1135 1136 OPCODE void op0x8(void) { 1137 cpu.ticks = 3; 1138 imp(); 1139 php(); 1140 } 1141 1142 OPCODE void op0x9(void) { 1143 cpu.ticks = 2; 1144 imm(); 1145 ora(); 1146 } 1147 1148 OPCODE void op0xA(void) { 1149 cpu.ticks = 2; 1150 //acc(); 1151 asla(); 1152 } 1153 1154 OPCODE void op0xB(void) { //undocumented 1155 cpu.ticks = 2; 1156 imm(); 1157 anc(); 1158 } 1159 1160 OPCODE void op0xC(void) { //nop 1161 cpu.ticks = 4; 1162 abso(); 1163 } 1164 1165 OPCODE void op0xD(void) { 1166 cpu.ticks = 4; 1167 abso(); 1168 ora(); 1169 } 1170 1171 OPCODE void op0xE(void) { 1172 cpu.ticks = 6; 1173 abso(); 1174 asl(); 1175 } 1176 1177 OPCODE void op0xF(void) { //undocumented 1178 cpu.ticks = 6; 1179 abso(); 1180 slo(); 1181 } 1182 1183 OPCODE void op0x10(void) { 1184 cpu.ticks = 2; 1185 rel(); 1186 bpl(); 1187 } 1188 1189 OPCODE void op0x11(void) { 1190 cpu.ticks = 5; 1191 indy_t(); 1192 ora(); 1193 } 1194 1195 OPCODE void op0x13(void) { //undocumented 1196 cpu.ticks = 8; 1197 indy(); 1198 slo(); 1199 } 1200 1201 OPCODE void op0x14(void) { //nop 1202 cpu.ticks = 4; 1203 zpx(); 1204 } 1205 1206 OPCODE void op0x15(void) { 1207 cpu.ticks = 4; 1208 zpx(); 1209 ora(); 1210 } 1211 1212 OPCODE void op0x16(void) { 1213 cpu.ticks = 6; 1214 zpx(); 1215 asl(); 1216 } 1217 1218 OPCODE void op0x17(void) { //undocumented 1219 cpu.ticks = 6; 1220 //zpy(); bug 1221 zpx(); 1222 slo(); 1223 } 1224 1225 OPCODE void op0x18(void) { 1226 cpu.ticks = 2; 1227 imp(); 1228 clc(); 1229 } 1230 1231 OPCODE void op0x19(void) { 1232 cpu.ticks = 4; 1233 absy_t(); 1234 ora(); 1235 } 1236 1237 OPCODE void op0x1A(void) { //nop 1238 cpu.ticks = 2; 1239 } 1240 1241 OPCODE void op0x1B(void) { //undocumented 1242 cpu.ticks = 7; 1243 absy(); 1244 slo(); 1245 } 1246 1247 OPCODE void op0x1C(void) { //nop 1248 cpu.ticks = 4; 1249 //(); 1250 } 1251 1252 OPCODE void op0x1D(void) { 1253 cpu.ticks = 4; 1254 absx_t(); 1255 ora(); 1256 } 1257 1258 OPCODE void op0x1E(void) { 1259 cpu.ticks = 7; 1260 absx(); 1261 asl(); 1262 } 1263 1264 1265 OPCODE void op0x1F(void) { //undocumented 1266 cpu.ticks = 7; 1267 absx(); 1268 slo(); 1269 } 1270 1271 OPCODE void op0x20(void) { 1272 cpu.ticks = 6; 1273 abso(); 1274 jsr(); 1275 } 1276 1277 OPCODE void op0x21(void) { 1278 cpu.ticks = 6; 1279 indx(); 1280 op_and(); 1281 } 1282 1283 OPCODE void op0x23(void) { //undocumented 1284 cpu.ticks = 8; 1285 indx(); 1286 rla(); 1287 } 1288 1289 OPCODE void op0x24(void) { 1290 cpu.ticks = 3; 1291 zp(); 1292 op_bitZP(); 1293 } 1294 1295 OPCODE void op0x25(void) { 1296 cpu.ticks = 3; 1297 zp(); 1298 op_and(); 1299 } 1300 1301 OPCODE void op0x26(void) { 1302 cpu.ticks = 5; 1303 zp(); 1304 rolZP(); 1305 } 1306 1307 OPCODE void op0x27(void) { //undocumented 1308 cpu.ticks = 5; 1309 zp(); 1310 rla(); 1311 } 1312 1313 OPCODE void op0x28(void) { 1314 cpu.ticks = 4; 1315 imp(); 1316 plp(); 1317 } 1318 1319 OPCODE void op0x29(void) { 1320 cpu.ticks = 2; 1321 imm(); 1322 op_and(); 1323 } 1324 1325 OPCODE void op0x2A(void) { 1326 cpu.ticks = 2; 1327 //acc(); 1328 rola(); 1329 } 1330 1331 OPCODE void op0x2B(void) { //undocumented 1332 cpu.ticks = 2; 1333 imm(); 1334 anc(); 1335 } 1336 1337 OPCODE void op0x2C(void) { 1338 cpu.ticks = 4; 1339 abso(); 1340 op_bit(); 1341 } 1342 1343 OPCODE void op0x2D(void) { 1344 cpu.ticks = 4; 1345 abso(); 1346 op_and(); 1347 } 1348 1349 OPCODE void op0x2E(void) { 1350 cpu.ticks = 6; 1351 abso(); 1352 rol(); 1353 } 1354 1355 OPCODE void op0x2F(void) { //undocumented 1356 cpu.ticks = 6; 1357 abso(); 1358 rla(); 1359 } 1360 1361 OPCODE void op0x30(void) { 1362 cpu.ticks = 2; 1363 rel(); 1364 bmi(); 1365 } 1366 1367 OPCODE void op0x31(void) { 1368 cpu.ticks = 5; 1369 indy_t(); 1370 op_and(); 1371 } 1372 1373 OPCODE void op0x33(void) { //undocumented 1374 cpu.ticks = 8; 1375 indy(); 1376 rla(); 1377 } 1378 1379 OPCODE void op0x34(void) { //nop 1380 cpu.ticks = 4; 1381 zpx(); 1382 } 1383 1384 OPCODE void op0x35(void) { 1385 cpu.ticks = 4; 1386 zpx(); 1387 op_and(); 1388 } 1389 1390 OPCODE void op0x36(void) { 1391 cpu.ticks = 6; 1392 zpx(); 1393 rol(); 1394 } 1395 1396 OPCODE void op0x37(void) { //undocumented 1397 cpu.ticks = 6; 1398 zpx(); 1399 rla(); 1400 } 1401 1402 OPCODE void op0x38(void) { 1403 cpu.ticks = 2; 1404 imp(); 1405 sec(); 1406 } 1407 1408 OPCODE void op0x39(void) { 1409 cpu.ticks = 4; 1410 absy_t(); 1411 op_and(); 1412 } 1413 1414 OPCODE void op0x3A(void) { //nop 1415 cpu.ticks = 2; 1416 } 1417 1418 OPCODE void op0x3B(void) { //undocumented 1419 cpu.ticks = 7; 1420 absy(); 1421 rla(); 1422 } 1423 1424 OPCODE void op0x3C(void) { //nop 1425 cpu.ticks = 4; 1426 absx_t(); 1427 } 1428 1429 OPCODE void op0x3D(void) { 1430 cpu.ticks = 4; 1431 absx_t(); 1432 op_and(); 1433 } 1434 1435 OPCODE void op0x3E(void) { 1436 cpu.ticks = 7; 1437 absx(); 1438 rol(); 1439 } 1440 1441 OPCODE void op0x3F(void) { //undocumented 1442 cpu.ticks = 7; 1443 absx(); 1444 rla(); 1445 } 1446 1447 OPCODE void op0x40(void) { 1448 cpu.ticks = 6; 1449 imp(); 1450 rti(); 1451 } 1452 1453 OPCODE void op0x41(void) { 1454 cpu.ticks = 6; 1455 indx(); 1456 eor(); 1457 } 1458 1459 OPCODE void op0x43(void) { //undocumented 1460 cpu.ticks = 8; 1461 indx(); 1462 sre(); 1463 } 1464 1465 OPCODE void op0x44(void) { //nop 1466 cpu.ticks = 3; 1467 zp(); 1468 } 1469 1470 OPCODE void op0x45(void) { 1471 cpu.ticks = 3; 1472 zp(); 1473 eorZP(); 1474 } 1475 1476 OPCODE void op0x46(void) { 1477 cpu.ticks = 5; 1478 zp(); 1479 lsrZP(); 1480 } 1481 1482 OPCODE void op0x47(void) { //undocumented 1483 cpu.ticks = 5; 1484 zp(); 1485 sre(); 1486 } 1487 1488 OPCODE void op0x48(void) { 1489 cpu.ticks = 3; 1490 imp(); 1491 pha(); 1492 } 1493 1494 OPCODE void op0x49(void) { 1495 cpu.ticks = 2; 1496 imm(); 1497 eor(); 1498 } 1499 1500 OPCODE void op0x4A(void) { 1501 cpu.ticks = 2; 1502 // acc(); 1503 lsra(); 1504 } 1505 1506 OPCODE void op0x4B(void) { //undocumented 1507 cpu.ticks = 2; 1508 imm(); 1509 alr(); 1510 } 1511 1512 OPCODE void op0x4C(void) { 1513 cpu.ticks = 3; 1514 abso(); 1515 jmp(); 1516 } 1517 1518 OPCODE void op0x4D(void) { 1519 cpu.ticks = 4; 1520 abso(); 1521 eor(); 1522 } 1523 1524 OPCODE void op0x4E(void) { 1525 cpu.ticks = 6; 1526 abso(); 1527 lsr(); 1528 } 1529 1530 OPCODE void op0x4F(void) { //undocumented 1531 cpu.ticks = 6; 1532 abso(); 1533 sre(); 1534 } 1535 1536 OPCODE void op0x50(void) { 1537 cpu.ticks = 2; 1538 rel(); 1539 bvc(); 1540 } 1541 1542 OPCODE void op0x51(void) { 1543 cpu.ticks = 5; 1544 indy_t(); 1545 eor(); 1546 } 1547 1548 OPCODE void op0x53(void) { //undocumented 1549 cpu.ticks = 8; 1550 //zp(); BUG 1551 indy(); 1552 sre(); 1553 } 1554 1555 OPCODE void op0x54(void) { //nop 1556 cpu.ticks = 4; 1557 zpx(); 1558 } 1559 1560 OPCODE void op0x55(void) { 1561 cpu.ticks = 4; 1562 zpx(); 1563 eor(); 1564 } 1565 1566 OPCODE void op0x56(void) { 1567 cpu.ticks = 6; 1568 zpx(); 1569 lsr(); 1570 } 1571 1572 OPCODE void op0x57(void) { //undocumented 1573 cpu.ticks = 6; 1574 zpx(); 1575 sre(); 1576 } 1577 1578 OPCODE void op0x58(void) { 1579 cpu.ticks = 2; 1580 imp(); 1581 cli_(); 1582 } 1583 1584 OPCODE void op0x59(void) { 1585 cpu.ticks = 4; 1586 absy_t(); 1587 eor(); 1588 } 1589 1590 OPCODE void op0x5A(void) { //nop 1591 cpu.ticks = 2; 1592 } 1593 1594 OPCODE void op0x5B(void) { //undocumented 1595 cpu.ticks = 7; 1596 absy(); 1597 sre(); 1598 } 1599 1600 OPCODE void op0x5C(void) { //nop 1601 cpu.ticks = 4; 1602 absx_t(); 1603 } 1604 1605 OPCODE void op0x5D(void) { 1606 cpu.ticks = 4; 1607 absx_t(); 1608 eor(); 1609 } 1610 1611 OPCODE void op0x5E(void) { 1612 cpu.ticks = 7; 1613 absx(); 1614 lsr(); 1615 } 1616 1617 OPCODE void op0x5F(void) { //undocumented 1618 cpu.ticks = 7; 1619 absx(); 1620 sre(); 1621 } 1622 1623 OPCODE void op0x60(void) { 1624 cpu.ticks = 6; 1625 imp(); 1626 rts(); 1627 } 1628 1629 OPCODE void op0x61(void) { 1630 cpu.ticks = 6; 1631 indx(); 1632 adc(); 1633 } 1634 1635 OPCODE void op0x63(void) { //undocumented 1636 cpu.ticks = 8; 1637 indx(); 1638 rra(); 1639 } 1640 1641 OPCODE void op0x64(void) { 1642 cpu.ticks = 3; 1643 zp(); 1644 } 1645 1646 OPCODE void op0x65(void) { 1647 cpu.ticks = 3; 1648 zp(); 1649 adcZP(); 1650 } 1651 1652 OPCODE void op0x66(void) { 1653 cpu.ticks = 5; 1654 zp(); 1655 rorZP(); 1656 } 1657 1658 OPCODE void op0x67(void) { //undocumented 1659 cpu.ticks = 5; 1660 zp(); 1661 rra(); 1662 } 1663 1664 OPCODE void op0x68(void) { 1665 cpu.ticks = 4; 1666 imp(); 1667 pla(); 1668 } 1669 1670 OPCODE void op0x69(void) { 1671 cpu.ticks = 2; 1672 imm(); 1673 adc(); 1674 } 1675 1676 OPCODE void op0x6A(void) { 1677 cpu.ticks = 2; 1678 // acc(); 1679 rora(); 1680 } 1681 1682 OPCODE void op0x6B(void) { //undocumented 1683 cpu.ticks = 2; 1684 imm(); 1685 arr(); 1686 } 1687 1688 OPCODE void op0x6C(void) { 1689 cpu.ticks = 5; 1690 ind(); 1691 jmp(); 1692 } 1693 1694 OPCODE void op0x6D(void) { 1695 cpu.ticks = 4; 1696 abso(); 1697 adc(); 1698 } 1699 1700 OPCODE void op0x6E(void) { 1701 cpu.ticks = 6; 1702 abso(); 1703 ror(); 1704 } 1705 1706 OPCODE void op0x6F(void) { //undocumented 1707 cpu.ticks = 6; 1708 abso(); 1709 rra(); 1710 } 1711 1712 OPCODE void op0x70(void) { 1713 cpu.ticks = 2; 1714 rel(); 1715 bvs(); 1716 } 1717 1718 OPCODE void op0x71(void) { 1719 cpu.ticks = 5; 1720 indy_t(); 1721 adc(); 1722 } 1723 1724 OPCODE void op0x73(void) { //undocumented 1725 cpu.ticks = 8; 1726 indy(); 1727 rra(); 1728 } 1729 1730 OPCODE void op0x74(void) { //nop 1731 cpu.ticks = 4; 1732 zpx(); 1733 } 1734 1735 OPCODE void op0x75(void) { 1736 cpu.ticks = 4; 1737 zpx(); 1738 adc(); 1739 } 1740 1741 OPCODE void op0x76(void) { 1742 cpu.ticks = 6; 1743 zpx(); 1744 ror(); 1745 } 1746 1747 OPCODE void op0x77(void) { //undocumented 1748 cpu.ticks = 6; 1749 zpx(); 1750 rra(); 1751 } 1752 1753 OPCODE void op0x78(void) { 1754 cpu.ticks = 2; 1755 imp(); 1756 sei_(); 1757 } 1758 1759 OPCODE void op0x79(void) { 1760 cpu.ticks = 4; 1761 absy_t(); 1762 adc(); 1763 } 1764 1765 OPCODE void op0x7A(void) { //nop 1766 cpu.ticks = 2; 1767 } 1768 1769 OPCODE void op0x7B(void) { //undocumented 1770 cpu.ticks = 7; 1771 absy(); 1772 rra(); 1773 } 1774 1775 OPCODE void op0x7C(void) { //nop 1776 cpu.ticks = 4; 1777 absx_t(); 1778 } 1779 1780 OPCODE void op0x7D(void) { 1781 cpu.ticks = 4; 1782 absx_t(); 1783 adc(); 1784 } 1785 1786 OPCODE void op0x7E(void) { 1787 cpu.ticks = 7; 1788 absx(); 1789 ror(); 1790 } 1791 1792 OPCODE void op0x7F(void) { //undocumented 1793 cpu.ticks = 7; 1794 absx(); 1795 rra(); 1796 } 1797 1798 OPCODE void op0x80(void) { //nop 1799 cpu.ticks = 2; 1800 imm(); 1801 } 1802 1803 OPCODE void op0x81(void) { 1804 cpu.ticks = 6; 1805 indx(); 1806 sta(); 1807 } 1808 1809 OPCODE void op0x82(void) { //nop 1810 cpu.ticks = 2; 1811 imm(); 1812 } 1813 1814 OPCODE void op0x83(void) { //undocumented 1815 cpu.ticks = 6; 1816 indx(); 1817 sax(); 1818 } 1819 1820 OPCODE void op0x84(void) { 1821 cpu.ticks = 3; 1822 zp(); 1823 sty(); 1824 } 1825 1826 OPCODE void op0x85(void) { 1827 cpu.ticks = 3; 1828 zp(); 1829 sta(); 1830 } 1831 1832 OPCODE void op0x86(void) { 1833 cpu.ticks = 3; 1834 zp(); 1835 stx(); 1836 } 1837 1838 OPCODE void op0x87(void) { //undocumented 1839 cpu.ticks = 3; 1840 zp(); 1841 sax(); 1842 } 1843 1844 OPCODE void op0x88(void) { 1845 cpu.ticks = 2; 1846 imp(); 1847 dey(); 1848 } 1849 1850 OPCODE void op0x89(void) { //nop 1851 cpu.ticks = 2; 1852 imm(); 1853 } 1854 1855 OPCODE void op0x8A(void) { 1856 cpu.ticks = 2; 1857 imp(); 1858 txa(); 1859 } 1860 1861 OPCODE void op0x8B(void) { //undocumented 1862 cpu.ticks = 2; 1863 imm(); 1864 xaa(); 1865 } 1866 1867 OPCODE void op0x8C(void) { 1868 cpu.ticks = 4; 1869 abso(); 1870 sty(); 1871 } 1872 1873 OPCODE void op0x8D(void) { 1874 cpu.ticks = 4; 1875 abso(); 1876 sta(); 1877 } 1878 1879 OPCODE void op0x8E(void) { 1880 cpu.ticks = 4; 1881 abso(); 1882 stx(); 1883 } 1884 1885 OPCODE void op0x8F(void) { //undocumented 1886 cpu.ticks = 4; 1887 abso(); 1888 sax(); 1889 } 1890 1891 OPCODE void op0x90(void) { 1892 cpu.ticks = 2; 1893 rel(); 1894 bcc(); 1895 } 1896 1897 OPCODE void op0x91(void) { 1898 cpu.ticks = 6; 1899 indy(); 1900 sta(); 1901 } 1902 1903 OPCODE void op0x93(void) { //undocumented 1904 cpu.ticks = 6; 1905 indy(); 1906 ahx(); 1907 } 1908 1909 OPCODE void op0x94(void) { 1910 cpu.ticks = 4; 1911 zpx(); 1912 sty(); 1913 } 1914 1915 OPCODE void op0x95(void) { 1916 cpu.ticks = 4; 1917 zpx(); 1918 sta(); 1919 } 1920 1921 OPCODE void op0x96(void) { 1922 cpu.ticks = 4; 1923 zpy(); 1924 stx(); 1925 } 1926 1927 OPCODE void op0x97(void) { //undocumented 1928 cpu.ticks = 4; 1929 zpy(); 1930 sax(); 1931 } 1932 1933 OPCODE void op0x98(void) { 1934 cpu.ticks = 2; 1935 imp(); 1936 tya(); 1937 } 1938 1939 OPCODE void op0x99(void) { 1940 cpu.ticks = 5; 1941 absy(); 1942 sta(); 1943 } 1944 1945 OPCODE void op0x9A(void) { 1946 cpu.ticks = 2; 1947 imp(); 1948 txs(); 1949 } 1950 1951 OPCODE void op0x9B(void) { //undocumented 1952 cpu.ticks = 5; 1953 absy(); 1954 //tas(); 1955 UNSUPPORTED; 1956 } 1957 1958 OPCODE void op0x9C(void) { //undocumented 1959 cpu.ticks = 5; 1960 absy(); 1961 //shy(); 1962 UNSUPPORTED; 1963 } 1964 1965 OPCODE void op0x9D(void) { 1966 cpu.ticks = 5; 1967 absx(); 1968 sta(); 1969 } 1970 1971 OPCODE void op0x9E(void) { //undocumented 1972 cpu.ticks = 5; 1973 absx(); 1974 //shx(); 1975 } 1976 1977 OPCODE void op0x9F(void) { //undocumented 1978 cpu.ticks = 5; 1979 absx(); 1980 ahx(); 1981 } 1982 1983 OPCODE void op0xA0(void) { 1984 cpu.ticks = 2; 1985 imm(); 1986 ldy(); 1987 } 1988 1989 OPCODE void op0xA1(void) { 1990 cpu.ticks = 6; 1991 indx(); 1992 lda(); 1993 } 1994 1995 OPCODE void op0xA2(void) { 1996 cpu.ticks = 2; 1997 imm(); 1998 ldx(); 1999 } 2000 2001 OPCODE void op0xA3(void) { //undocumented 2002 cpu.ticks = 6; 2003 indx(); 2004 lax(); 2005 } 2006 2007 OPCODE void op0xA4(void) { 2008 cpu.ticks = 3; 2009 zp(); 2010 ldyZP(); 2011 } 2012 2013 OPCODE void op0xA5(void) { 2014 cpu.ticks = 3; 2015 zp(); 2016 ldaZP(); 2017 } 2018 2019 OPCODE void op0xA6(void) { 2020 cpu.ticks = 3; 2021 zp(); 2022 ldxZP(); 2023 } 2024 2025 OPCODE void op0xA7(void) { //undocumented 2026 cpu.ticks = 3; 2027 zp(); 2028 lax(); 2029 } 2030 2031 OPCODE void op0xA8(void) { 2032 cpu.ticks = 2; 2033 imp(); 2034 tay(); 2035 } 2036 2037 OPCODE void op0xA9(void) { 2038 cpu.ticks = 2; 2039 imm(); 2040 lda(); 2041 } 2042 2043 OPCODE void op0xAA(void) { 2044 cpu.ticks = 2; 2045 imp(); 2046 tax(); 2047 } 2048 2049 OPCODE void op0xAB(void) { //undocumented 2050 cpu.ticks = 2; 2051 imm(); 2052 lxa(); 2053 } 2054 2055 OPCODE void op0xAC(void) { 2056 cpu.ticks = 4; 2057 abso(); 2058 ldy(); 2059 } 2060 2061 OPCODE void op0xAD(void) { 2062 cpu.ticks = 4; 2063 abso(); 2064 lda(); 2065 } 2066 2067 OPCODE void op0xAE(void) { 2068 cpu.ticks = 4; 2069 abso(); 2070 ldx(); 2071 } 2072 2073 OPCODE void op0xAF(void) { //undocumented 2074 cpu.ticks = 4; 2075 abso(); 2076 lax(); 2077 } 2078 2079 OPCODE void op0xB0(void) { 2080 cpu.ticks = 2; 2081 rel(); 2082 bcs(); 2083 } 2084 2085 OPCODE void op0xB1(void) { 2086 cpu.ticks = 5; 2087 indy_t(); 2088 lda(); 2089 } 2090 2091 OPCODE void op0xB3(void) { //undocumented 2092 cpu.ticks = 5; 2093 indy_t(); 2094 lax(); 2095 } 2096 2097 OPCODE void op0xB4(void) { 2098 cpu.ticks = 4; 2099 zpx(); 2100 ldy(); 2101 } 2102 2103 OPCODE void op0xB5(void) { 2104 cpu.ticks = 4; 2105 zpx(); 2106 lda(); 2107 } 2108 2109 OPCODE void op0xB6(void) { 2110 cpu.ticks = 4; 2111 zpy(); 2112 ldx(); 2113 } 2114 2115 OPCODE void op0xB7(void) { //undocumented 2116 cpu.ticks = 4; 2117 zpy(); 2118 lax(); 2119 } 2120 2121 OPCODE void op0xB8(void) { 2122 cpu.ticks = 2; 2123 imp(); 2124 clv(); 2125 } 2126 2127 OPCODE void op0xB9(void) { 2128 cpu.ticks = 4; 2129 absy_t(); 2130 lda(); 2131 } 2132 2133 OPCODE void op0xBA(void) { 2134 cpu.ticks = 2; 2135 imp(); 2136 tsx(); 2137 } 2138 2139 OPCODE void op0xBB(void) { //undocumented 2140 cpu.ticks = 4; 2141 absy_t(); 2142 las(); 2143 } 2144 2145 OPCODE void op0xBC(void) { 2146 cpu.ticks = 4; 2147 absx_t(); 2148 ldy(); 2149 } 2150 2151 OPCODE void op0xBD(void) { 2152 cpu.ticks = 4; 2153 absx_t(); 2154 lda(); 2155 } 2156 2157 OPCODE void op0xBE(void) { 2158 cpu.ticks = 4; 2159 absy_t(); 2160 ldx(); 2161 } 2162 2163 OPCODE void op0xBF(void) { //undocumented 2164 cpu.ticks = 4; 2165 absy_t(); 2166 lax(); 2167 } 2168 2169 OPCODE void op0xC0(void) { 2170 cpu.ticks = 2; 2171 imm(); 2172 cpy(); 2173 } 2174 2175 OPCODE void op0xC1(void) { 2176 cpu.ticks = 6; 2177 indx(); 2178 cmp(); 2179 } 2180 2181 OPCODE void op0xC2(void) { //nop 2182 cpu.ticks = 2; 2183 imm(); 2184 } 2185 2186 OPCODE void op0xC3(void) { //undocumented 2187 cpu.ticks = 8; 2188 indx(); 2189 dcp(); 2190 } 2191 2192 OPCODE void op0xC4(void) { 2193 cpu.ticks = 3; 2194 zp(); 2195 cpyZP(); 2196 } 2197 2198 OPCODE void op0xC5(void) { 2199 cpu.ticks = 3; 2200 zp(); 2201 cmpZP(); 2202 } 2203 2204 OPCODE void op0xC6(void) { 2205 cpu.ticks = 5; 2206 zp(); 2207 decZP(); 2208 } 2209 2210 OPCODE void op0xC7(void) { //undocumented 2211 cpu.ticks = 5; 2212 zp(); 2213 dcp(); 2214 } 2215 2216 OPCODE void op0xC8(void) { 2217 cpu.ticks = 2; 2218 imp(); 2219 iny(); 2220 } 2221 2222 OPCODE void op0xC9(void) { 2223 cpu.ticks = 2; 2224 imm(); 2225 cmp(); 2226 } 2227 2228 OPCODE void op0xCA(void) { 2229 cpu.ticks = 2; 2230 imp(); 2231 dex(); 2232 } 2233 2234 OPCODE void op0xCB(void) { //undocumented 2235 cpu.ticks = 2; 2236 imm(); 2237 axs(); 2238 } 2239 2240 OPCODE void op0xCC(void) { 2241 cpu.ticks = 4; 2242 abso(); 2243 cpy(); 2244 } 2245 2246 OPCODE void op0xCD(void) { 2247 cpu.ticks = 4; 2248 abso(); 2249 cmp(); 2250 } 2251 2252 OPCODE void op0xCE(void) { 2253 cpu.ticks = 6; 2254 abso(); 2255 dec(); 2256 } 2257 2258 OPCODE void op0xCF(void) { //undocumented 2259 cpu.ticks = 6; 2260 abso(); 2261 dcp(); 2262 } 2263 2264 OPCODE void op0xD0(void) { 2265 cpu.ticks = 2; 2266 rel(); 2267 bne(); 2268 } 2269 2270 OPCODE void op0xD1(void) { 2271 cpu.ticks = 5; 2272 indy_t(); 2273 cmp(); 2274 } 2275 2276 OPCODE void op0xD3(void) { //undocumented 2277 cpu.ticks = 8; 2278 indy(); 2279 dcp(); 2280 } 2281 2282 OPCODE void op0xD4(void) { //nop 2283 cpu.ticks = 4; 2284 zpx(); 2285 } 2286 2287 OPCODE void op0xD5(void) { 2288 cpu.ticks = 4; 2289 zpx(); 2290 cmp(); 2291 } 2292 2293 OPCODE void op0xD6(void) { 2294 cpu.ticks = 6; 2295 zpx(); 2296 dec(); 2297 } 2298 2299 OPCODE void op0xD7(void) { //undocumented 2300 cpu.ticks = 6; 2301 zpx(); 2302 dcp(); 2303 } 2304 2305 OPCODE void op0xD8(void) { 2306 cpu.ticks = 2; 2307 imp(); 2308 cld(); 2309 } 2310 2311 OPCODE void op0xD9(void) { 2312 cpu.ticks = 4; 2313 absy_t(); 2314 cmp(); 2315 } 2316 2317 OPCODE void op0xDA(void) { //nop 2318 cpu.ticks = 2; 2319 } 2320 2321 OPCODE void op0xDB(void) { //undocumented 2322 cpu.ticks = 7; 2323 absy(); 2324 dcp(); 2325 } 2326 2327 OPCODE void op0xDC(void) { //nop 2328 cpu.ticks = 4; 2329 absx_t(); 2330 } 2331 2332 OPCODE void op0xDD(void) { 2333 cpu.ticks = 4; 2334 absx_t(); 2335 cmp(); 2336 } 2337 2338 OPCODE void op0xDE(void) { 2339 cpu.ticks = 7; 2340 absx(); 2341 dec(); 2342 } 2343 2344 OPCODE void op0xDF(void) { //undocumented 2345 cpu.ticks = 7; 2346 absx(); 2347 dcp(); 2348 } 2349 2350 OPCODE void op0xE0(void) { 2351 cpu.ticks = 2; 2352 imm(); 2353 cpx(); 2354 } 2355 2356 OPCODE void op0xE1(void) { 2357 cpu.ticks = 5; 2358 indx(); 2359 sbc(); 2360 } 2361 2362 OPCODE void op0xE2(void) { //NOP 2363 cpu.ticks = 2; 2364 imm(); 2365 } 2366 2367 OPCODE void op0xE3(void) { //undocumented 2368 cpu.ticks = 8; 2369 indx(); 2370 isb(); 2371 } 2372 2373 OPCODE void op0xE4(void) { 2374 cpu.ticks = 3; 2375 zp(); 2376 cpxZP(); 2377 } 2378 2379 OPCODE void op0xE5(void) { 2380 cpu.ticks = 3; 2381 zp(); 2382 sbcZP(); 2383 } 2384 2385 OPCODE void op0xE6(void) { 2386 cpu.ticks = 5; 2387 zp(); 2388 incZP(); 2389 } 2390 2391 OPCODE void op0xE7(void) { //undocumented 2392 cpu.ticks = 5; 2393 zp(); 2394 isb(); 2395 } 2396 2397 OPCODE void op0xE8(void) { 2398 cpu.ticks = 2; 2399 imp(); 2400 inx(); 2401 } 2402 2403 OPCODE void op0xE9(void) { 2404 cpu.ticks = 2; 2405 imm(); 2406 sbc(); 2407 } 2408 2409 OPCODE void op0xEA(void) { 2410 cpu.ticks = 2; 2411 } 2412 2413 OPCODE void op0xEB(void) { 2414 cpu.ticks = 2; 2415 imm(); 2416 sbc(); 2417 } 2418 2419 OPCODE void op0xEC(void) { 2420 cpu.ticks = 4; 2421 abso(); 2422 cpx(); 2423 } 2424 2425 OPCODE void op0xED(void) { 2426 cpu.ticks = 4; 2427 abso(); 2428 sbc(); 2429 } 2430 2431 OPCODE void op0xEE(void) { 2432 cpu.ticks = 6; 2433 abso(); 2434 inc(); 2435 } 2436 2437 OPCODE void op0xEF(void) { //undocumented 2438 cpu.ticks = 6; 2439 abso(); 2440 isb(); 2441 } 2442 2443 OPCODE void op0xF0(void) { 2444 cpu.ticks = 2; 2445 rel(); 2446 beq(); 2447 } 2448 2449 OPCODE void op0xF1(void) { 2450 cpu.ticks = 5; 2451 indy_t(); 2452 sbc(); 2453 } 2454 2455 OPCODE void op0xF3(void) { //undocumented 2456 cpu.ticks = 8; 2457 indy(); 2458 isb(); 2459 } 2460 2461 OPCODE void op0xF4(void) { //nop 2462 cpu.ticks = 4; 2463 zpx(); 2464 } 2465 2466 OPCODE void op0xF5(void) { 2467 cpu.ticks = 4; 2468 zpx(); 2469 sbc(); 2470 } 2471 2472 OPCODE void op0xF6(void) { 2473 cpu.ticks = 6; 2474 zpx(); 2475 inc(); 2476 } 2477 2478 OPCODE void op0xF7(void) { //undocumented 2479 cpu.ticks = 6; 2480 zpx(); 2481 isb(); 2482 } 2483 2484 OPCODE void op0xF8(void) { 2485 cpu.ticks = 2; 2486 imp(); 2487 sed(); 2488 } 2489 2490 OPCODE void op0xF9(void) { 2491 cpu.ticks = 4; 2492 absy_t(); 2493 sbc(); 2494 } 2495 2496 OPCODE void op0xFA(void) { //nop 2497 cpu.ticks = 2; 2498 } 2499 2500 OPCODE void op0xFB(void) { //undocumented 2501 cpu.ticks = 7; 2502 absy(); 2503 isb(); 2504 } 2505 2506 OPCODE void op0xFC(void) { //nop 2507 cpu.ticks = 4; 2508 absx_t(); 2509 } 2510 2511 OPCODE void op0xFD(void) { 2512 cpu.ticks = 4; 2513 absx_t(); 2514 sbc(); 2515 } 2516 2517 OPCODE void op0xFE(void) { 2518 cpu.ticks = 7; 2519 absx(); 2520 inc(); 2521 } 2522 2523 OPCODE void op0xFF(void) { //undocumented 2524 cpu.ticks = 7; 2525 absx(); 2526 isb(); 2527 } 2528 2529 OPCODE void opPATCHD2(void) { 2530 #if APPLY_PATCHES 2531 patchLOAD(); 2532 #else 2533 opKIL(); 2534 #endif 2535 } 2536 2537 OPCODE void opPATCHF2(void) { 2538 #if APPLY_PATCHES 2539 patchSAVE(); 2540 #else 2541 opKIL(); 2542 #endif 2543 } 2544 2545 typedef void (*op_ptr_t)( void ); 2546 2547 static const op_ptr_t opcodetable[256] = { 2548 /* 0 1 2 3 4 5 6 7 8 9 A B C D E F */ 2549 /* 0 */ op0x0 , op0x1, opKIL , op0x3, op0x4 , op0x5, op0x6, op0x7, op0x8, op0x9, op0xA, op0xB , op0xC , op0xD , op0xE , op0xF, 2550 /* 1 */ op0x10, op0x11, opKIL , op0x13, op0x14, op0x15, op0x16, op0x17, op0x18, op0x19, op0x1A, op0x1B, op0x1C, op0x1D, op0x1E, op0x1F, 2551 /* 2 */ op0x20, op0x21, opKIL , op0x23, op0x24, op0x25, op0x26, op0x27, op0x28, op0x29, op0x2A, op0x2B, op0x2C, op0x2D, op0x2E, op0x2F, 2552 /* 3 */ op0x30, op0x31, opKIL , op0x33, op0x34, op0x35, op0x36, op0x37, op0x38, op0x39, op0x3A, op0x3B, op0x3C, op0x3D, op0x3E, op0x3F, 2553 /* 4 */ op0x40, op0x41, opKIL , op0x43, op0x44, op0x45, op0x46, op0x47, op0x48, op0x49, op0x4A, op0x4B, op0x4C, op0x4D, op0x4E, op0x4F, 2554 /* 5 */ op0x50, op0x51, opKIL , op0x53, op0x54, op0x55, op0x56, op0x57, op0x58, op0x59, op0x5A, op0x5B, op0x5C, op0x5D, op0x5E, op0x5F, 2555 /* 6 */ op0x60, op0x61, opKIL , op0x63, op0x64, op0x65, op0x66, op0x67, op0x68, op0x69, op0x6A, op0x6B, op0x6C, op0x6D, op0x6E, op0x6F, 2556 /* 7 */ op0x70, op0x71, opKIL , op0x73, op0x74, op0x75, op0x76, op0x77, op0x78, op0x79, op0x7A, op0x7B, op0x7C, op0x7D, op0x7E, op0x7F, 2557 /* 8 */ op0x80, op0x81, op0x82, op0x83, op0x84, op0x85, op0x86, op0x87, op0x88, op0x89, op0x8A, op0x8B, op0x8C, op0x8D, op0x8E, op0x8F, 2558 /* 9 */ op0x90, op0x91, opKIL , op0x93, op0x94, op0x95, op0x96, op0x97, op0x98, op0x99, op0x9A, op0x9B, op0x9C, op0x9D, op0x9E, op0x9F, 2559 /* A */ op0xA0, op0xA1, op0xA2, op0xA3, op0xA4, op0xA5, op0xA6, op0xA7, op0xA8, op0xA9, op0xAA, op0xAB, op0xAC, op0xAD, op0xAE, op0xAF, 2560 /* B */ op0xB0, op0xB1, opKIL , op0xB3, op0xB4, op0xB5, op0xB6, op0xB7, op0xB8, op0xB9, op0xBA, op0xBB, op0xBC, op0xBD, op0xBE, op0xBF, 2561 /* C */ op0xC0, op0xC1, op0xC2, op0xC3, op0xC4, op0xC5, op0xC6, op0xC7, op0xC8, op0xC9, op0xCA, op0xCB, op0xCC, op0xCD, op0xCE, op0xCF, 2562 /* D */ op0xD0, op0xD1, opPATCHD2 , op0xD3, op0xD4, op0xD5, op0xD6, op0xD7, op0xD8, op0xD9, op0xDA, op0xDB, op0xDC, op0xDD, op0xDE, op0xDF, 2563 /* E */ op0xE0, op0xE1, op0xE2, op0xE3, op0xE4, op0xE5, op0xE6, op0xE7, op0xE8, op0xE9, op0xEA, op0xEB, op0xEC, op0xED, op0xEE, op0xEF, 2564 /* F */ op0xF0, op0xF1, opPATCHF2 , op0xF3, op0xF4, op0xF5, op0xF6, op0xF7, op0xF8, op0xF9, op0xFA, op0xFB, op0xFC, op0xFD, op0xFE, op0xFF 2565 }; 2566 2567 static const uint8_t cyclesTable[256] = 2568 { 2569 7, 6, 2, 8, 3, 3, 5, 5, 3, 2, 2, 2, 4, 4, 6, 6, // $00 2570 2, 5, 2, 8, 4, 4, 6, 6, 2, 4, 2, 7, 5, 5, 7, 7, // $10 2571 6, 6, 2, 8, 3, 3, 5, 5, 4, 2, 2, 2, 4, 4, 6, 6, // $20 2572 2, 5, 2, 8, 4, 4, 6, 6, 2, 4, 2, 7, 5, 5, 7, 7, // $30 2573 6, 6, 2, 8, 3, 3, 5, 5, 3, 2, 2, 2, 3, 4, 6, 6, // $40 2574 2, 5, 2, 8, 4, 4, 6, 6, 2, 4, 2, 7, 5, 5, 7, 7, // $50 2575 6, 6, 2, 8, 3, 3, 5, 5, 4, 2, 2, 2, 5, 4, 6, 6, // $60 2576 2, 5, 2, 8, 4, 4, 6, 6, 2, 4, 2, 7, 5, 5, 7, 7, // $70 2577 2, 6, 2, 6, 3, 3, 3, 3, 2, 2, 2, 2, 4, 4, 4, 4, // $80 2578 2, 6, 2, 6, 4, 4, 4, 4, 2, 5, 2, 5, 5, 5, 5, 5, // $90 2579 2, 6, 2, 6, 3, 3, 3, 3, 2, 2, 2, 2, 4, 4, 4, 4, // $A0 2580 2, 5, 2, 5, 4, 4, 4, 4, 2, 4, 2, 5, 4, 4, 4, 4, // $B0 2581 2, 6, 2, 8, 3, 3, 5, 5, 2, 2, 2, 2, 4, 4, 6, 6, // $C0 2582 2, 5, 2, 8, 4, 4, 6, 6, 2, 4, 2, 7, 5, 5, 7, 7, // $D0 2583 2, 6, 2, 8, 3, 3, 5, 5, 2, 2, 2, 2, 4, 4, 6, 6, // $E0 2584 2, 5, 2, 8, 4, 4, 6, 6, 2, 4, 2, 7, 5, 5, 7, 7 // $F0 2585 }; 2586 2587 static const uint8_t writeCycleTable[256] = 2588 { 2589 3, 0, 0, 2, 0, 0, 2, 2, 1, 0, 0, 0, 0, 0, 2, 2, // $00 2590 0, 0, 0, 2, 0, 0, 2, 2, 0, 0, 0, 2, 0, 0, 2, 2, // $10 2591 2, 0, 0, 2, 0, 0, 2, 2, 0, 0, 0, 0, 0, 0, 2, 2, // $20 2592 0, 0, 0, 2, 0, 0, 2, 2, 0, 0, 0, 2, 0, 0, 2, 2, // $30 2593 0, 0, 0, 2, 0, 0, 2, 2, 1, 0, 0, 0, 0, 0, 2, 2, // $40 2594 0, 0, 0, 2, 0, 0, 2, 2, 0, 0, 0, 2, 0, 0, 2, 2, // $50 2595 0, 0, 0, 2, 0, 0, 2, 2, 0, 0, 0, 0, 0, 0, 2, 2, // $60 2596 0, 0, 0, 2, 0, 0, 2, 2, 0, 0, 0, 2, 0, 0, 2, 2, // $70 2597 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, // $80 2598 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, // $90 2599 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // $A0 2600 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // $B0 2601 0, 0, 0, 2, 0, 0, 2, 2, 0, 0, 0, 0, 0, 0, 2, 2, // $C0 2602 0, 0, 0, 2, 0, 0, 2, 2, 0, 0, 0, 2, 0, 0, 2, 2, // $D0 2603 0, 0, 0, 2, 0, 0, 2, 2, 0, 0, 0, 0, 0, 0, 2, 2, // $E0 2604 0, 0, 0, 2, 0, 0, 2, 2, 0, 0, 0, 2, 0, 0, 2, 2 // $F0 2605 }; 2606 2607 2608 void cpu_nmi() { 2609 cpu.nmiLine = 1; 2610 printf("nmiLine=1\n"); 2611 } 2612 void cpu_clearNmi() { 2613 cpu.nmi = 0; 2614 } 2615 2616 void cpu_nmi_do() { 2617 if (cpu.nmi) return; 2618 cpu.nmi = 1; 2619 cpu.nmiLine = 0; 2620 push16(cpu.pc); 2621 push8(cpu.cpustatus & ~FLAG_BREAK); 2622 cpu.cpustatus |= FLAG_INTERRUPT; 2623 cpu.pc = read6502(0xFFFA) | (read6502(0xFFFB) << 8); 2624 cpu.ticks = 7; 2625 } 2626 2627 static inline void cpu_irq() { 2628 push16(cpu.pc); 2629 push8(cpu.cpustatus & ~FLAG_BREAK); 2630 cpu.cpustatus |= FLAG_INTERRUPT; 2631 cpu.pc = read6502(0xFFFE) | (read6502(0xFFFF) << 8); 2632 cpu.ticks = 7; 2633 } 2634 2635 inline void cia_clock(void) __attribute__((always_inline)); 2636 2637 void cia_clock(void) { 2638 cia1_clock(1); 2639 cia2_clock(1); 2640 } 2641 2642 void cia_clockt(int ticks) { 2643 cia1_clock(ticks); 2644 cia2_clock(ticks); 2645 } 2646 2647 void cpu_clock(int cycles) { 2648 static int c = 0; 2649 static int writeCycles = 0; 2650 cpu.lineCyclesAbs += cycles; 2651 c+=cycles; 2652 while (c > 0) { 2653 2654 uint8_t opcode ; 2655 cpu.ticks = 0; 2656 2657 //NMI 2658 2659 if (!cpu.nmi && ((cpu.cia2.R[0x0D] & 0x80) | cpu.nmiLine)) { 2660 cpu_nmi_do(); 2661 goto noOpcode; 2662 } 2663 2664 if (!(cpu.cpustatus & FLAG_INTERRUPT)) { 2665 if (((cpu.vic.R[0x19] | cpu.cia1.R[0x0D]) & 0x80)) { 2666 cpu_irq(); 2667 goto noOpcode; 2668 } 2669 } 2670 2671 cpu.cpustatus |= FLAG_CONSTANT; 2672 opcode = read6502(cpu.pc++); 2673 opcodetable[opcode](); 2674 writeCycles = writeCycleTable[opcode]; 2675 noOpcode: 2676 2677 cia_clockt(cpu.ticks); 2678 c-= cpu.ticks; 2679 cpu.lineCycles += cpu.ticks; 2680 2681 if (cpu.exactTiming) { 2682 uint32_t t = cpu.lineCycles * MCU_C64_RATIO; 2683 //while (ARM_DWT_CYCCNT - cpu.lineStartTime < t){;} 2684 } 2685 2686 }; 2687 2688 return; 2689 } 2690 2691 //Enable "ExactTiming" Mode 2692 void cpu_setExactTiming() { 2693 if (!cpu.exactTiming) { 2694 //enable exact timing 2695 setAudioOff(); 2696 vic_displaySimpleModeScreen(); 2697 2698 } 2699 cpu.exactTiming = 1; 2700 //cpu.exactTimingStartTime = ARM_DWT_CYCCNT; 2701 cpu.exactTiming = 0; 2702 } 2703 2704 //Disable "ExactTiming" Mode 2705 void cpu_disableExactTiming() { 2706 cpu.exactTiming = 0; 2707 setAudioOn(); 2708 } 2709 2710 void cpu_reset() { 2711 enableCycleCounter(); 2712 cpu.exactTiming = 0; 2713 cpu.nmi = 0; 2714 cpu.cpustatus = FLAG_CONSTANT; 2715 cpu.pc = read6502(0xFFFC) | (read6502(0xFFFD) << 8); 2716 cpu.sp = 0xFD; 2717 }