6502

minimal 6502 emulator written in C
Index Commits Files Refs README LICENSE
6502.c (22504B)
   1 #include "6502.h"
   2 
   3 #include <stdio.h>
   4 
   5 /* included for debugging purposes */
   6 #include <string.h>
   7 
   8 static CPU cpu;
   9 static MEM mem; /* 8 bit word */
  10 
  11 static uint8_t cyc;
  12 static uint8_t opc;
  13 
  14 static uint16_t  tmp;
  15 static uint16_t  addr_abs;
  16 static uint16_t  addr_rel;
  17 
  18 INS decode[0x100];
  19 static INS prev_ins;
  20 
  21 /* Cpu methods */
  22 void CPU_init(void) {
  23     cpu.ac = cpu.x = cpu.y = cpu.sp = cpu.st = 0;
  24     cyc = opc = tmp = 0;
  25     prev_ins = (INS) {"???", &NUL, &IMP, 7};
  26 }
  27 
  28 void CPU_reset(void) {
  29     cpu.sp = 0xFF;
  30     cpu.st = 0x00;
  31 
  32     /* little endian */
  33     uint16_t lo = MEM_read(0xFFFC);
  34     uint16_t hi = MEM_read(0xFFFD);
  35 
  36     cpu.pc = (hi << 8) | lo;
  37 
  38     addr_abs = addr_rel = opc = 0x0000;
  39 
  40     /* simulate 8 cycles needed to reset the cpu */
  41     cyc = 8;
  42 }
  43 
  44 void CPU_fetch(INS *ins) {
  45     *ins = decode[opc = MEM_read(cpu.pc)];
  46 }
  47 
  48 uint8_t CPU_exec(INS ins) {
  49     /* simulate instructions cycles */
  50     do {
  51         if (cyc == 0) {
  52             if (!strcmp(ins.name, "???")) {
  53                 /* printf("EXEC: invalid instruction reached\n"); */
  54                 return 1;
  55             } else if (!strcmp(ins.name, "BNE") && !(strcmp(prev_ins.name, "BNE"))) {
  56                 /* printf("EXEC: consecutive BNE reached\n"); */
  57                 return 1;
  58             }
  59 
  60             cpu.pc++;
  61             cyc = ins.cycles;
  62 
  63             uint8_t add_cyc_0 = ins.mode();
  64             uint8_t add_cyc_1 = ins.op();
  65 
  66             prev_ins = ins;
  67             cyc += add_cyc_0 & add_cyc_1;
  68         }
  69     } while(--cyc);
  70 
  71     return 0;
  72 }
  73 
  74 /* interrupt request */
  75 void CPU_irq(void) {
  76     if(!CPU_get_flag(I)) {
  77         /* save pc */
  78         MEM_write(0x100 + cpu.sp--, (cpu.pc >> 8) & 0x00FF);
  79         MEM_write(0x100 + cpu.sp--, cpu.pc & 0x00FF);
  80 
  81         /* save st */
  82         MEM_write(0x100 + cpu.sp--, cpu.st | (1 << 4) | (1 << 5));
  83 
  84         CPU_set_flag(I, 1);
  85 
  86         uint16_t lo = MEM_read(0xFFFE);
  87         uint16_t hi = MEM_read(0xFFFF);
  88 
  89         cpu.pc = ((hi << 8) & 0xFF00) | (lo & 0x00FF);
  90 
  91         cyc = 8;
  92     }
  93 }
  94 
  95 /* non maskeable interrupt request */
  96 void CPU_nm_irq(void) {
  97     /* save program counter to stack */
  98     MEM_write(0x100 + cpu.sp--, (cpu.pc >> 8) & 0x00FF);
  99     MEM_write(0x100 + cpu.sp--, cpu.pc & 0x00FF);
 100 
 101     /* save cpu status to stack */
 102     MEM_write(0x100 + cpu.sp--, cpu.st | (1 << 4) | (1 << 5));
 103     CPU_set_flag(I, 1);
 104 
 105     addr_abs = 0xFFFA;
 106     uint16_t lo = MEM_read(addr_abs + 0);
 107     uint16_t hi = MEM_read(addr_abs + 1);
 108 
 109     cpu.pc = (hi << 8) | lo;
 110 
 111     cyc = 8;
 112 }
 113 
 114 void CPU_branch(void) {
 115     cyc++;
 116     addr_abs = cpu.pc + addr_rel;
 117 
 118     /* if address changes page */
 119     if((addr_abs & 0xFF00) != (cpu.pc & 0xFF00))
 120         cyc++;
 121 
 122     cpu.pc = addr_abs;
 123 }
 124 
 125 void CPU_set_flag(ST_FLAG flag, uint8_t val) {
 126     cpu.st = val ? cpu.st | (1 << flag) : cpu.st & ~(1 << flag);
 127 }
 128 
 129 uint8_t CPU_get_flag(ST_FLAG flag) {
 130     return (cpu.st & (1 << flag)) >> flag;
 131 }
 132 
 133 void print_reg(uint8_t reg) {
 134     for(unsigned long i = ((sizeof(reg) * 8)); i > 0; i--) {
 135         putchar((reg & (0x01 << (i - 1))) ? '1' : '0');
 136         putchar(' ');
 137     }
 138     putchar('\n');
 139 }
 140 
 141 void CPU_dump(void) {
 142     INS aux = decode[MEM_read(cpu.pc)];
 143 
 144     printf("  a:   %02X (%3d)              N V - B D I Z C\n"
 145             "  x:   %02X (%3d)              ", cpu.ac, cpu.ac, cpu.x, cpu.x);
 146     print_reg(cpu.st);
 147     printf("  y:   %02X (%3d)\n"
 148             " sp:   %02X\n"
 149             " pc: %04X -> %02X (%s)(%s)\n"
 150             "\033[5A", cpu.y, cpu.y, cpu.sp, cpu.pc, mem.ram[cpu.pc], aux.name,
 151             CPU_mode_name(aux.mode));
 152 }
 153 
 154 uint16_t CPU_get_pc(void) {
 155     return cpu.pc;
 156 }
 157 
 158 /* Memory methods */
 159 void MEM_init(void) {
 160     for(uint16_t i = 0; i < 0xFFFF; i++)
 161         mem.ram[i] = 0;
 162 }
 163 
 164 void MEM_set_pc_start(uint16_t addr) {
 165     mem.ram[0xFFFC] = (addr & 0x00FF);
 166     mem.ram[0xFFFD] = ((addr & 0xFF00) >> 8);
 167 }
 168 
 169 int MEM_load_from_file(char *path) {
 170     FILE *fp;
 171 
 172     if(path == NULL) {
 173         return 1;
 174     }
 175 
 176     fp = fopen(path, "rb");
 177     if(fp == NULL) {
 178         fprintf(stderr, "ERROR: file \"%s\" not found.\n", path);
 179         return 2;
 180     }
 181 
 182     fread(mem.ram, 1, sizeof(mem.ram), fp);
 183     /* fread(mem.ram + 0x8000, 1, 0x7FFF - 0x6, fp); */
 184 
 185     fclose(fp);
 186     return 0;
 187 }
 188 
 189 uint8_t MEM_read(uint16_t addr) {
 190     return mem.ram[addr];
 191 }
 192 
 193 uint8_t MEM_write(uint16_t addr, uint8_t val) {
 194     mem.ram[addr] = val;
 195     return val;
 196 }
 197 
 198 void MEM_dump() {
 199     for(uint16_t i = 0; i < 0xF; i++)
 200         printf("%02X ", mem.ram[i]);
 201 
 202     putchar('\n');
 203 }
 204 
 205 void MEM_dump_page(uint16_t page) {
 206     uint16_t j = 1;
 207 
 208     printf("Page %04X:\n", page);
 209     for(uint16_t i = page; i <= (page + 0xFF); i++, j++)
 210         printf("%02X %s", mem.ram[i], (j % 0x1E) ? "" : "\n");
 211 
 212     putchar('\n');
 213 }
 214 
 215 void MEM_dump_last_six(void) {
 216     printf("Last six:\n");
 217     for(size_t i = 0xFFFA; i <= 0xFFFF; i++)
 218         printf("%02X ", mem.ram[i]);
 219 
 220     putchar('\n');
 221 }
 222 
 223 char *CPU_mode_name(uint8_t (*mode)(void)) {
 224     if(mode == &IMM) return "IMM";
 225     else if(mode == &ABS) return "ABS";
 226     else if(mode == &ABX) return "ABX";
 227     else if(mode == &ABY) return "ABY";
 228     else if(mode == &IMP) return "IMP";
 229     else if(mode == &IND) return "IND";
 230     else if(mode == &IZX) return "IZX";
 231     else if(mode == &IZY) return "IZY";
 232     else if(mode == &REL) return "REL";
 233     else if(mode == &ZP0) return "ZP0";
 234     else if(mode == &ZPX) return "ZPX";
 235     else if(mode == &ZPY) return "ZPY";
 236 
 237     return "NUL";
 238 }
 239 
 240 /* Addressing modes */
 241 uint8_t ABS(void) {
 242     uint16_t lo = MEM_read(cpu.pc++);
 243     uint16_t hi = MEM_read(cpu.pc++);
 244 
 245     addr_abs = (hi << 8) | lo;
 246 
 247     /* printf("Address: %04X -> (%02X)\n", addr_abs, MEM_read(addr_abs)); */
 248     return 0;
 249 }
 250 
 251 uint8_t ABX(void) {
 252     uint16_t lo = MEM_read(cpu.pc++);
 253     uint16_t hi = MEM_read(cpu.pc++);
 254 
 255     addr_abs = (hi << 8) | lo;
 256 
 257     /* printf("address fetched: %04X\nx register: %02X\nend address: %04X (%02X)\n", addr_abs, cpu.x, addr_abs + cpu.x, MEM_read(addr_abs + cpu.x)); */
 258 
 259     addr_abs += cpu.x;
 260     /* printf("Address: %04X -> (%02X)\n", addr_abs, MEM_read(addr_abs)); */
 261 
 262     return ((addr_abs & 0x00FF) != (hi << 8)) ? 1 : 0;
 263 }
 264 
 265 uint8_t ABY(void) {
 266     uint16_t lo = MEM_read(cpu.pc++);
 267     uint16_t hi = MEM_read(cpu.pc++);
 268 
 269     addr_abs = (hi << 8) | lo;
 270 
 271     /* printf("address fetched: %04X\ny register: %02X\nend address: %04X (%02X)\n", addr_abs, cpu.y, addr_abs + cpu.y, MEM_read(addr_abs + cpu.y)); */
 272 
 273     addr_abs += cpu.y;
 274     /* printf("Address: %04X -> (%02X)\n", addr_abs, MEM_read(addr_abs)); */
 275     return ((addr_abs & 0x00FF) != (hi << 8)) ? 1 : 0;
 276 }
 277 
 278 uint8_t IMM(void) {
 279     addr_abs = cpu.pc++;
 280     /* printf("Address: %04X -> (%02X)\n", addr_abs, MEM_read(addr_abs)); */
 281     return 0;
 282 }
 283 
 284 uint8_t IMP(void) {
 285     tmp = cpu.ac;
 286     return 0;
 287 }
 288 
 289 uint8_t IND(void) {
 290     /* get a direction from memory */
 291     uint16_t lo = MEM_read(cpu.pc++);
 292     uint16_t hi = MEM_read(cpu.pc++);
 293 
 294     /* assign the direction to ptr */
 295     uint16_t p = (hi << 8) | lo;
 296 
 297     /* get the address pointed by p
 298      * and simulate page boundary hardware bug */
 299     addr_abs = (MEM_read((lo == 0xFF) ? (p & 0xFF00) : p + 1) << 8) | MEM_read(p);
 300 
 301     /* printf("Address: %04X -> (%02X)\n", addr_abs, MEM_read(addr_abs)); */
 302     return 0;
 303 }
 304 
 305 uint8_t IZX(void) {
 306     uint8_t addr = MEM_read(cpu.pc++);
 307 
 308     /* get a direction from memory */
 309     uint16_t lo = MEM_read((addr + cpu.x) & 0xFF);
 310     uint16_t hi = MEM_read((addr + cpu.x + 1) & 0xFF);
 311 
 312     addr_abs = ((hi << 8) & 0xFF00) | lo;
 313 
 314     /* printf("Address: %04X -> (%02X)\n", addr_abs, MEM_read(addr_abs)); */
 315 
 316     return 0;
 317 }
 318 
 319 uint8_t IZY(void) {
 320     uint8_t addr = MEM_read(cpu.pc++);
 321 
 322     /* get a direction from memory */
 323     uint16_t lo = MEM_read(addr);
 324     uint16_t hi = MEM_read(addr + 1);
 325 
 326     addr_abs = ((hi << 8) & 0xFF00) | lo;
 327     addr_abs += cpu.y;
 328 
 329     /* printf("Address: %04X -> (%02X)\n", addr_abs, MEM_read(addr_abs)); */
 330 
 331     return ((addr_abs & 0xFF00) != (hi << 8)) ? 1 : 0;
 332 }
 333 
 334 uint8_t REL(void) {
 335     addr_rel = (MEM_read(cpu.pc++) & 0x00FF);
 336     /* printf("REL: offset: %02X (%d)\n", addr_rel, (int8_t)addr_rel); */
 337 
 338     /* signed byte */
 339     if (addr_rel & (1 << 7))
 340         addr_rel |= 0xFF00;
 341 
 342     return 0;
 343 }
 344 
 345 /* read only the offset of the zero page */
 346 uint8_t ZP0(void) {
 347     addr_abs = (MEM_read(cpu.pc++) & 0x00FF);
 348 
 349     /* printf("Address: %04X -> (%02X)\n", addr_abs, MEM_read(addr_abs)); */
 350     return 0;
 351 }
 352 
 353 uint8_t ZPX(void) {
 354     addr_abs = (MEM_read(cpu.pc++) + cpu.x) & 0x00FF;
 355 
 356     /* printf("Address: %04X -> (%02X)\n", addr_abs, MEM_read(addr_abs)); */
 357     return 0;
 358 }
 359 
 360 uint8_t ZPY(void) {
 361     addr_abs = (MEM_read(cpu.pc++) + cpu.y) & 0x00FF;
 362 
 363     /* printf("Address: %04X -> (%02X)\n", addr_abs, MEM_read(addr_abs)); */
 364     return 0;
 365 }
 366 
 367 
 368 /* Instructions */
 369 uint8_t ADC(void) {
 370     uint16_t data = MEM_read(addr_abs);
 371     uint16_t res = (cpu.ac + data + (uint16_t)CPU_get_flag(C));
 372 
 373     CPU_set_flag(N, res & (1 << 7));
 374     CPU_set_flag(Z, (res & 0x00FF) == 0);
 375     CPU_set_flag(C, ((res & 0xFF00) >> 7));
 376     CPU_set_flag(V, ((cpu.ac^res) & ~(cpu.ac^data)) & (1 << 7));
 377 
 378     cpu.ac = (uint8_t)(res & 0x00FF);
 379 
 380     return 1;
 381 }
 382 
 383 uint8_t AND(void) {
 384     cpu.ac &= MEM_read(addr_abs);
 385 
 386     CPU_set_flag(Z, cpu.ac == 0);
 387     CPU_set_flag(N, cpu.ac & (1 << 7));
 388 
 389     return 1;
 390 }
 391 
 392 uint8_t ASL(void) {
 393     if(decode[opc].mode == &IMP) {
 394         tmp = cpu.ac << 1;
 395         CPU_set_flag(C, (cpu.ac & (1 << 7)));
 396         cpu.ac = (tmp & 0x00FF);
 397     }
 398     else {
 399         tmp = MEM_read(addr_abs) << 1;
 400         CPU_set_flag(C, MEM_read(addr_abs) & (1 << 7));
 401         MEM_write(addr_abs, tmp & 0x00FF);
 402     }
 403 
 404     CPU_set_flag(Z, tmp == 0);
 405     CPU_set_flag(N, tmp & (1 << 7));
 406 
 407     return 0;
 408 }
 409 
 410 uint8_t BCC(void) {
 411     if(!CPU_get_flag(C))
 412         CPU_branch();
 413 
 414     return 0;
 415 }
 416 
 417 uint8_t BCS(void) {
 418     if(CPU_get_flag(C))
 419         CPU_branch();
 420 
 421     return 0;
 422 }
 423 
 424 uint8_t BEQ(void) {
 425     if(CPU_get_flag(Z))
 426         CPU_branch();
 427 
 428     return 0;
 429 }
 430 
 431 uint8_t BIT(void) {
 432     tmp = (MEM_read(addr_abs) & 0x00FF);
 433 
 434     CPU_set_flag(Z, (cpu.ac & tmp) == 0);
 435     CPU_set_flag(V, tmp & (1 << 6));
 436     CPU_set_flag(N, tmp & (1 << 7));
 437 
 438     return 0;
 439 }
 440 
 441 uint8_t BMI(void) {
 442     if(CPU_get_flag(N))
 443         CPU_branch();
 444 
 445     return 0;
 446 }
 447 
 448 uint8_t BNE(void) {
 449     if(!CPU_get_flag(Z))
 450         CPU_branch();
 451 
 452     return 0;
 453 }
 454 
 455 uint8_t BPL(void) {
 456     if(!CPU_get_flag(N))
 457         CPU_branch();
 458 
 459     return 0;
 460 }
 461 
 462 uint8_t BRK(void) {
 463     /* save program counter to stack */
 464     MEM_write(0x100 + cpu.sp--, (cpu.pc >> 8) & 0x00FF);
 465     MEM_write(0x100 + cpu.sp--, cpu.pc & 0x00FF);
 466 
 467     /* save cpu status to stack */
 468     MEM_write(0x100 + cpu.sp--, cpu.st | (1 << 4) | (1 << 5));
 469     CPU_set_flag(I, 1);
 470 
 471     uint16_t lo = MEM_read(0xFFFE);
 472     uint16_t hi = MEM_read(0xFFFF);
 473 
 474     cpu.pc = (hi << 8) | lo;
 475 
 476     return 0;
 477 }
 478 
 479 uint8_t BVC(void) {
 480     if(!CPU_get_flag(V))
 481         CPU_branch();
 482 
 483     return 0;
 484 }
 485 
 486 uint8_t BVS(void) {
 487     if(CPU_get_flag(V))
 488         CPU_branch();
 489 
 490     return 0;
 491 }
 492 
 493 uint8_t CLC(void) {
 494     CPU_set_flag(C, 0);
 495     return 0;
 496 }
 497 
 498 uint8_t CLD(void) {
 499     CPU_set_flag(D, 0);
 500     return 0;
 501 }
 502 
 503 uint8_t CLI(void) {
 504     CPU_set_flag(I, 0);
 505     return 0;
 506 }
 507 
 508 uint8_t CLV(void) {
 509     CPU_set_flag(V, 0);
 510     return 0;
 511 }
 512 
 513 uint8_t CMP(void) {
 514     tmp = (MEM_read(addr_abs) & 0x00FF);
 515 
 516     /* printf("cmp: %d, acc: %d\n", tmp, cpu.ac); */
 517 
 518     CPU_set_flag(C, cpu.ac >= tmp);
 519     CPU_set_flag(Z, cpu.ac == tmp);
 520     CPU_set_flag(N, (cpu.ac - tmp) & (1<<7));
 521 
 522     return 0;
 523 }
 524 
 525 uint8_t CPX(void) {
 526     tmp = (MEM_read(addr_abs) & 0x00FF);
 527 
 528     CPU_set_flag(C, cpu.x >= tmp);
 529     CPU_set_flag(Z, cpu.x == tmp);
 530     CPU_set_flag(N, (cpu.x - tmp) & (1<<7));
 531 
 532     return 0;
 533 }
 534 
 535 uint8_t CPY(void) {
 536     tmp = (MEM_read(addr_abs) & 0x00FF);
 537 
 538     CPU_set_flag(C, cpu.y >= tmp);
 539     CPU_set_flag(Z, cpu.y == tmp);
 540     CPU_set_flag(N, (cpu.y - tmp) & (1<<7));
 541 
 542     return 0;
 543 }
 544 
 545 uint8_t DEC(void) {
 546     tmp = MEM_write(addr_abs, MEM_read(addr_abs) - 1) & 0x00FF;
 547 
 548     CPU_set_flag(Z, tmp == 0);
 549     CPU_set_flag(N, tmp & (1 << 7));
 550 
 551     return 0;
 552 }
 553 
 554 /* Decrements X register */
 555 uint8_t DEX(void) {
 556     cpu.x -= 1;
 557 
 558     CPU_set_flag(Z, cpu.x == 0);
 559     CPU_set_flag(N, cpu.x & (1 << 7));
 560 
 561     return 0;
 562 }
 563 
 564 /* Decrements Y register */
 565 uint8_t DEY(void) {
 566     cpu.y -= 1;
 567 
 568     CPU_set_flag(Z, cpu.y == 0);
 569     CPU_set_flag(N, cpu.y & (1 << 7));
 570 
 571     return 0;
 572 }
 573 
 574 uint8_t EOR(void) {
 575     cpu.ac ^= MEM_read(addr_abs);
 576 
 577     CPU_set_flag(Z, cpu.ac == 0);
 578     CPU_set_flag(N, cpu.ac & (1 << 7));
 579 
 580     return 1;
 581 }
 582 
 583 uint8_t INC(void) {
 584     tmp = MEM_write(addr_abs, MEM_read(addr_abs) + 1) & 0x00FF;
 585 
 586     CPU_set_flag(Z, tmp == 0);
 587     CPU_set_flag(N, tmp & (1 << 7));
 588 
 589     return 0;
 590 }
 591 
 592 uint8_t INX(void) {
 593     cpu.x += 1;
 594 
 595     CPU_set_flag(Z, cpu.x == 0);
 596     CPU_set_flag(N, cpu.x & (1 << 7));
 597 
 598     return 0;
 599 }
 600 
 601 uint8_t INY(void) {
 602     cpu.y += 1;
 603 
 604     CPU_set_flag(Z, cpu.y == 0);
 605     CPU_set_flag(N, cpu.y & (1 << 7));
 606 
 607     return 0;
 608 }
 609 
 610 uint8_t JMP(void) {
 611     cpu.pc = addr_abs;
 612     return 0;
 613 }
 614 
 615 uint8_t JSR(void) {
 616     cpu.pc--;
 617 
 618     MEM_write(0x100 + cpu.sp--, (cpu.pc & 0xFF00) >> 8);
 619     MEM_write(0x100 + cpu.sp--, (cpu.pc & 0x00FF));
 620 
 621     cpu.pc = addr_abs;
 622 
 623     return 0;
 624 }
 625 
 626 uint8_t LDA(void) {
 627     cpu.ac = MEM_read(addr_abs);
 628 
 629     CPU_set_flag(Z, cpu.ac == 0);
 630     CPU_set_flag(N, cpu.ac & (1 << 7));
 631 
 632     return 1;
 633 }
 634 
 635 uint8_t LDX(void) {
 636     cpu.x = MEM_read(addr_abs);
 637 
 638     CPU_set_flag(Z, cpu.x == 0);
 639     CPU_set_flag(N, cpu.x & (1 << 7));
 640 
 641     return 1;
 642 }
 643 
 644 uint8_t LDY(void) {
 645     cpu.y = MEM_read(addr_abs);
 646 
 647     CPU_set_flag(Z, cpu.y == 0);
 648     CPU_set_flag(N, cpu.y & (1 << 7));
 649 
 650     return 1;
 651 }
 652 
 653 uint8_t LSR(void) {
 654     if(decode[opc].mode == &IMP) {
 655         tmp = (cpu.ac >> 1);
 656         CPU_set_flag(C, cpu.ac & 0x01);
 657         cpu.ac = (tmp & 0x00FF);
 658     }
 659     else {
 660         tmp = (MEM_read(addr_abs) >> 1);
 661         CPU_set_flag(C, MEM_read(addr_abs) & 0x01);
 662         MEM_write(addr_abs, tmp & 0x00FF);
 663     }
 664 
 665     CPU_set_flag(Z, tmp == 0);
 666     CPU_set_flag(N, tmp & (1 << 7));
 667 
 668     return 0;
 669 }
 670 
 671 uint8_t NOP(void) {
 672     return 0;
 673 }
 674 
 675 uint8_t ORA(void) {
 676     cpu.ac |= MEM_read(addr_abs);
 677 
 678     CPU_set_flag(Z, cpu.ac == 0);
 679     CPU_set_flag(N, cpu.ac & (1 << 7));
 680 
 681     return 1;
 682 }
 683 
 684 uint8_t PHA(void) {
 685     MEM_write(0x100 + cpu.sp--, cpu.ac);
 686 
 687     return 0;
 688 }
 689 
 690 uint8_t PHP(void) {
 691     MEM_write(0x100 + cpu.sp--, cpu.st | (1 << 4) | (1 << 5));
 692 
 693     return 0;
 694 }
 695 
 696 uint8_t PLA(void) {
 697     cpu.ac = MEM_read(0x100 + ++cpu.sp);
 698 
 699     CPU_set_flag(Z, (cpu.ac == 0));
 700     CPU_set_flag(N, cpu.ac & (1 << 7));
 701 
 702     return 0;
 703 }
 704 
 705 uint8_t PLP(void) {
 706     uint8_t B_is_set = CPU_get_flag(B);
 707     uint8_t U_is_set = CPU_get_flag(U);
 708 
 709     /* restore status */
 710     cpu.st = MEM_read(0x100 + ++cpu.sp);
 711 
 712     /* This two flags stay the same as before */
 713     CPU_set_flag(B, B_is_set);
 714     CPU_set_flag(U, U_is_set);
 715 
 716     return 0;
 717 }
 718 
 719 uint8_t ROL(void) {
 720     if(decode[opc].mode == &IMP) {
 721         tmp = (cpu.ac << 1) & 0xFE;
 722         tmp |= CPU_get_flag(C);
 723 
 724         CPU_set_flag(C, cpu.ac & (1 << 7));
 725         cpu.ac = (tmp & 0x00FF);
 726     }
 727     else {
 728         tmp = (MEM_read(addr_abs) << 1) & 0xFE;
 729         tmp |= CPU_get_flag(C);
 730 
 731         CPU_set_flag(C, MEM_read(addr_abs) & (1 << 7));
 732         MEM_write(addr_abs, tmp & 0x00FF);
 733     }
 734 
 735     CPU_set_flag(Z, tmp == 0);
 736     CPU_set_flag(N, tmp & (1 << 7));
 737 
 738     return 0;
 739 }
 740 
 741 uint8_t ROR(void) {
 742     if(decode[opc].mode == &IMP) {
 743         tmp = (cpu.ac >> 1) & 0x7F;
 744         tmp |= (CPU_get_flag(C) << 7);
 745 
 746         CPU_set_flag(C, cpu.ac & 0x01);
 747 
 748         cpu.ac = (tmp & 0x00FF);
 749     }
 750     else {
 751         tmp = (MEM_read(addr_abs) >> 1) & 0x7F;
 752         tmp |= (CPU_get_flag(C) << 7);
 753 
 754         CPU_set_flag(C, MEM_read(addr_abs) & 1);
 755         MEM_write(addr_abs, tmp & 0x00FF);
 756     }
 757 
 758     CPU_set_flag(Z, tmp == 0);
 759     CPU_set_flag(N, tmp & (1 << 7));
 760 
 761     return 0;
 762 }
 763 
 764 uint8_t RTI(void) {
 765     uint8_t B_is_set = CPU_get_flag(B);
 766     uint8_t U_is_set = CPU_get_flag(U);
 767 
 768     /* restore status */
 769     cpu.st = MEM_read(0x100 + ++cpu.sp);
 770 
 771     /* This two flags stay the same as before */
 772     CPU_set_flag(B, B_is_set);
 773     CPU_set_flag(U, U_is_set);
 774 
 775     /* restore pc */
 776     cpu.pc = MEM_read(0x100 + ++cpu.sp);
 777     cpu.pc |= (MEM_read(0x100 + ++cpu.sp) << 8);
 778 
 779     return 0;
 780 }
 781 
 782 uint8_t RTS(void) {
 783     cpu.pc = MEM_read(0x100 + ++cpu.sp);
 784     cpu.pc |= (MEM_read(0x100 + ++cpu.sp) << 8);
 785 
 786     CPU_set_flag(B, 0);
 787 
 788     cpu.pc++;
 789 
 790     return 0;
 791 }
 792 
 793 uint8_t SBC(void) {
 794     uint16_t data = MEM_read(addr_abs) ^ 0xFF;
 795     uint16_t res = (cpu.ac + data + (uint16_t)CPU_get_flag(C));
 796 
 797     CPU_set_flag(N, res & (1 << 7));
 798     CPU_set_flag(Z, (res & 0x00FF) == 0);
 799     CPU_set_flag(C, ((res & 0xFF00) >> 7));
 800     CPU_set_flag(V, ((cpu.ac^res) & ~(cpu.ac^data)) & (1 << 7));
 801 
 802     cpu.ac = (uint8_t)(res & 0x00FF);
 803 
 804     return 1;
 805 }
 806 
 807 uint8_t SEC(void) {
 808     CPU_set_flag(C, 1);
 809     return 0;
 810 }
 811 
 812 uint8_t SED(void) {
 813     CPU_set_flag(D, 1);
 814     return 0;
 815 }
 816 
 817 uint8_t SEI(void) {
 818     CPU_set_flag(I, 1);
 819     return 0;
 820 }
 821 
 822 uint8_t STA(void) {
 823     MEM_write(addr_abs, cpu.ac);
 824     return 0;
 825 }
 826 
 827 uint8_t STX(void) {
 828     MEM_write(addr_abs, cpu.x);
 829     return 0;
 830 }
 831 
 832 uint8_t STY(void) {
 833     MEM_write(addr_abs, cpu.y);
 834     return 0;
 835 }
 836 
 837 uint8_t TAX(void) {
 838     cpu.x = cpu.ac;
 839 
 840     CPU_set_flag(Z, cpu.x == 0);
 841     CPU_set_flag(N, cpu.x & (1 << 7));
 842 
 843     return 0;
 844 }
 845 
 846 uint8_t TAY(void) {
 847     cpu.y = cpu.ac;
 848 
 849     CPU_set_flag(Z, cpu.y == 0);
 850     CPU_set_flag(N, cpu.y & (1 << 7));
 851 
 852     return 0;
 853 }
 854 
 855 uint8_t TSX(void) {
 856     cpu.x = cpu.sp;
 857 
 858     CPU_set_flag(Z, cpu.x == 0);
 859     CPU_set_flag(N, cpu.x & (1 << 7));
 860 
 861     return 0;
 862 }
 863 
 864 uint8_t TXA(void) {
 865     cpu.ac = cpu.x;
 866 
 867     CPU_set_flag(Z, cpu.ac == 0);
 868     CPU_set_flag(N, cpu.ac & (1 << 7));
 869 
 870     return 0;
 871 }
 872 
 873 uint8_t TXS(void) {
 874     cpu.sp = cpu.x;
 875 
 876     return 0;
 877 }
 878 
 879 uint8_t TYA(void) {
 880     cpu.ac = cpu.y;
 881 
 882     CPU_set_flag(Z, cpu.ac == 0);
 883     CPU_set_flag(N, cpu.ac & (1 << 7));
 884 
 885     return 0;
 886 }
 887 
 888 uint8_t NUL(void) {
 889     return 0;
 890 }
 891 
 892 /* Lookup table */
 893 INS decode[0x100] = {
 894     {"BRK", &BRK, &IMM, 7}, {"ORA", &ORA, &IZX, 6}, {"???", &NUL, &IMP, 2},
 895     {"???", &NUL, &IMP, 8}, {"???", &NOP, &IMP, 3}, {"ORA", &ORA, &ZP0, 3},
 896     {"ASL", &ASL, &ZP0, 5}, {"???", &NUL, &IMP, 5}, {"PHP", &PHP, &IMP, 3},
 897     {"ORA", &ORA, &IMM, 2}, {"ASL", &ASL, &IMP, 2}, {"???", &NUL, &IMP, 2},
 898     {"???", &NOP, &IMP, 4}, {"ORA", &ORA, &ABS, 4}, {"ASL", &ASL, &ABS, 6},
 899     {"???", &NUL, &IMP, 6}, {"BPL", &BPL, &REL, 2}, {"ORA", &ORA, &IZY, 5},
 900     {"???", &NUL, &IMP, 2}, {"???", &NUL, &IMP, 8}, {"???", &NOP, &IMP, 4},
 901     {"ORA", &ORA, &ZPX, 4}, {"ASL", &ASL, &ZPX, 6}, {"???", &NUL, &IMP, 6},
 902     {"CLC", &CLC, &IMP, 2}, {"ORA", &ORA, &ABY, 4}, {"???", &NOP, &IMP, 2},
 903     {"???", &NUL, &IMP, 7}, {"???", &NOP, &IMP, 4}, {"ORA", &ORA, &ABX, 4},
 904     {"ASL", &ASL, &ABX, 7}, {"???", &NUL, &IMP, 7}, {"JSR", &JSR, &ABS, 6},
 905     {"AND", &AND, &IZX, 6}, {"???", &NUL, &IMP, 2}, {"???", &NUL, &IMP, 8},
 906     {"BIT", &BIT, &ZP0, 3}, {"AND", &AND, &ZP0, 3}, {"ROL", &ROL, &ZP0, 5},
 907     {"???", &NUL, &IMP, 5}, {"PLP", &PLP, &IMP, 4}, {"AND", &AND, &IMM, 2},
 908     {"ROL", &ROL, &IMP, 2}, {"???", &NUL, &IMP, 2}, {"BIT", &BIT, &ABS, 4},
 909     {"AND", &AND, &ABS, 4}, {"ROL", &ROL, &ABS, 6}, {"???", &NUL, &IMP, 6},
 910     {"BMI", &BMI, &REL, 2}, {"AND", &AND, &IZY, 5}, {"???", &NUL, &IMP, 2},
 911     {"???", &NUL, &IMP, 8}, {"???", &NOP, &IMP, 4}, {"AND", &AND, &ZPX, 4},
 912     {"ROL", &ROL, &ZPX, 6}, {"???", &NUL, &IMP, 6}, {"SEC", &SEC, &IMP, 2},
 913     {"AND", &AND, &ABY, 4}, {"???", &NOP, &IMP, 2}, {"???", &NUL, &IMP, 7},
 914     {"???", &NOP, &IMP, 4}, {"AND", &AND, &ABX, 4}, {"ROL", &ROL, &ABX, 7},
 915     {"???", &NUL, &IMP, 7}, {"RTI", &RTI, &IMP, 6}, {"EOR", &EOR, &IZX, 6},
 916     {"???", &NUL, &IMP, 2}, {"???", &NUL, &IMP, 8}, {"???", &NOP, &IMP, 3},
 917     {"EOR", &EOR, &ZP0, 3}, {"LSR", &LSR, &ZP0, 5}, {"???", &NUL, &IMP, 5},
 918     {"PHA", &PHA, &IMP, 3}, {"EOR", &EOR, &IMM, 2}, {"LSR", &LSR, &IMP, 2},
 919     {"???", &NUL, &IMP, 2}, {"JMP", &JMP, &ABS, 3}, {"EOR", &EOR, &ABS, 4},
 920     {"LSR", &LSR, &ABS, 6}, {"???", &NUL, &IMP, 6}, {"BVC", &BVC, &REL, 2},
 921     {"EOR", &EOR, &IZY, 5}, {"???", &NUL, &IMP, 2}, {"???", &NUL, &IMP, 8},
 922     {"???", &NOP, &IMP, 4}, {"EOR", &EOR, &ZPX, 4}, {"LSR", &LSR, &ZPX, 6},
 923     {"???", &NUL, &IMP, 6}, {"CLI", &CLI, &IMP, 2}, {"EOR", &EOR, &ABY, 4},
 924     {"???", &NOP, &IMP, 2}, {"???", &NUL, &IMP, 7}, {"???", &NOP, &IMP, 4},
 925     {"EOR", &EOR, &ABX, 4}, {"LSR", &LSR, &ABX, 7}, {"???", &NUL, &IMP, 7},
 926     {"RTS", &RTS, &IMP, 6}, {"ADC", &ADC, &IZX, 6}, {"???", &NUL, &IMP, 2},
 927     {"???", &NUL, &IMP, 8}, {"???", &NOP, &IMP, 3}, {"ADC", &ADC, &ZP0, 3},
 928     {"ROR", &ROR, &ZP0, 5}, {"???", &NUL, &IMP, 5}, {"PLA", &PLA, &IMP, 4},
 929     {"ADC", &ADC, &IMM, 2}, {"ROR", &ROR, &IMP, 2}, {"???", &NUL, &IMP, 2},
 930     {"JMP", &JMP, &IND, 5}, {"ADC", &ADC, &ABS, 4}, {"ROR", &ROR, &ABS, 6},
 931     {"???", &NUL, &IMP, 6}, {"BVS", &BVS, &REL, 2}, {"ADC", &ADC, &IZY, 5},
 932     {"???", &NUL, &IMP, 2}, {"???", &NUL, &IMP, 8}, {"???", &NOP, &IMP, 4},
 933     {"ADC", &ADC, &ZPX, 4}, {"ROR", &ROR, &ZPX, 6}, {"???", &NUL, &IMP, 6},
 934     {"SEI", &SEI, &IMP, 2}, {"ADC", &ADC, &ABY, 4}, {"???", &NOP, &IMP, 2},
 935     {"???", &NUL, &IMP, 7}, {"???", &NOP, &IMP, 4}, {"ADC", &ADC, &ABX, 4},
 936     {"ROR", &ROR, &ABX, 7}, {"???", &NUL, &IMP, 7}, {"???", &NOP, &IMP, 2},
 937     {"STA", &STA, &IZX, 6}, {"???", &NOP, &IMP, 2}, {"???", &NUL, &IMP, 6},
 938     {"STY", &STY, &ZP0, 3}, {"STA", &STA, &ZP0, 3}, {"STX", &STX, &ZP0, 3},
 939     {"???", &NUL, &IMP, 3}, {"DEY", &DEY, &IMP, 2}, {"???", &NOP, &IMP, 2},
 940     {"TXA", &TXA, &IMP, 2}, {"???", &NUL, &IMP, 2}, {"STY", &STY, &ABS, 4},
 941     {"STA", &STA, &ABS, 4}, {"STX", &STX, &ABS, 4}, {"???", &NUL, &IMP, 4},
 942     {"BCC", &BCC, &REL, 2}, {"STA", &STA, &IZY, 6}, {"???", &NUL, &IMP, 2},
 943     {"???", &NUL, &IMP, 6}, {"STY", &STY, &ZPX, 4}, {"STA", &STA, &ZPX, 4},
 944     {"STX", &STX, &ZPY, 4}, {"???", &NUL, &IMP, 4}, {"TYA", &TYA, &IMP, 2},
 945     {"STA", &STA, &ABY, 5}, {"TXS", &TXS, &IMP, 2}, {"???", &NUL, &IMP, 5},
 946     {"???", &NOP, &IMP, 5}, {"STA", &STA, &ABX, 5}, {"???", &NUL, &IMP, 5},
 947     {"???", &NUL, &IMP, 5}, {"LDY", &LDY, &IMM, 2}, {"LDA", &LDA, &IZX, 6},
 948     {"LDX", &LDX, &IMM, 2}, {"???", &NUL, &IMP, 6}, {"LDY", &LDY, &ZP0, 3},
 949     {"LDA", &LDA, &ZP0, 3}, {"LDX", &LDX, &ZP0, 3}, {"???", &NUL, &IMP, 3},
 950     {"TAY", &TAY, &IMP, 2}, {"LDA", &LDA, &IMM, 2}, {"TAX", &TAX, &IMP, 2},
 951     {"???", &NUL, &IMP, 2}, {"LDY", &LDY, &ABS, 4}, {"LDA", &LDA, &ABS, 4},
 952     {"LDX", &LDX, &ABS, 4}, {"???", &NUL, &IMP, 4}, {"BCS", &BCS, &REL, 2},
 953     {"LDA", &LDA, &IZY, 5}, {"???", &NUL, &IMP, 2}, {"???", &NUL, &IMP, 5},
 954     {"LDY", &LDY, &ZPX, 4}, {"LDA", &LDA, &ZPX, 4}, {"LDX", &LDX, &ZPY, 4},
 955     {"???", &NUL, &IMP, 4}, {"CLV", &CLV, &IMP, 2}, {"LDA", &LDA, &ABY, 4},
 956     {"TSX", &TSX, &IMP, 2}, {"???", &NUL, &IMP, 4}, {"LDY", &LDY, &ABX, 4},
 957     {"LDA", &LDA, &ABX, 4}, {"LDX", &LDX, &ABY, 4}, {"???", &NUL, &IMP, 4},
 958     {"CPY", &CPY, &IMM, 2}, {"CMP", &CMP, &IZX, 6}, {"???", &NOP, &IMP, 2},
 959     {"???", &NUL, &IMP, 8}, {"CPY", &CPY, &ZP0, 3}, {"CMP", &CMP, &ZP0, 3},
 960     {"DEC", &DEC, &ZP0, 5}, {"???", &NUL, &IMP, 5}, {"INY", &INY, &IMP, 2},
 961     {"CMP", &CMP, &IMM, 2}, {"DEX", &DEX, &IMP, 2}, {"???", &NUL, &IMP, 2},
 962     {"CPY", &CPY, &ABS, 4}, {"CMP", &CMP, &ABS, 4}, {"DEC", &DEC, &ABS, 6},
 963     {"???", &NUL, &IMP, 6}, {"BNE", &BNE, &REL, 2}, {"CMP", &CMP, &IZY, 5},
 964     {"???", &NUL, &IMP, 2}, {"???", &NUL, &IMP, 8}, {"???", &NOP, &IMP, 4},
 965     {"CMP", &CMP, &ZPX, 4}, {"DEC", &DEC, &ZPX, 6}, {"???", &NUL, &IMP, 6},
 966     {"CLD", &CLD, &IMP, 2}, {"CMP", &CMP, &ABY, 4}, {"NOP", &NOP, &IMP, 2},
 967     {"???", &NUL, &IMP, 7}, {"???", &NOP, &IMP, 4}, {"CMP", &CMP, &ABX, 4},
 968     {"DEC", &DEC, &ABX, 7}, {"???", &NUL, &IMP, 7}, {"CPX", &CPX, &IMM, 2},
 969     {"SBC", &SBC, &IZX, 6}, {"???", &NOP, &IMP, 2}, {"???", &NUL, &IMP, 8},
 970     {"CPX", &CPX, &ZP0, 3}, {"SBC", &SBC, &ZP0, 3}, {"INC", &INC, &ZP0, 5},
 971     {"???", &NUL, &IMP, 5}, {"INX", &INX, &IMP, 2}, {"SBC", &SBC, &IMM, 2},
 972     {"NOP", &NOP, &IMP, 2}, {"???", &SBC, &IMP, 2}, {"CPX", &CPX, &ABS, 4},
 973     {"SBC", &SBC, &ABS, 4}, {"INC", &INC, &ABS, 6}, {"???", &NUL, &IMP, 6},
 974     {"BEQ", &BEQ, &REL, 2}, {"SBC", &SBC, &IZY, 5}, {"???", &NUL, &IMP, 2},
 975     {"???", &NUL, &IMP, 8}, {"???", &NOP, &IMP, 4}, {"SBC", &SBC, &ZPX, 4},
 976     {"INC", &INC, &ZPX, 6}, {"???", &NUL, &IMP, 6}, {"SED", &SED, &IMP, 2},
 977     {"SBC", &SBC, &ABY, 4}, {"NOP", &NOP, &IMP, 2}, {"???", &NUL, &IMP, 7},
 978     {"???", &NOP, &IMP, 4}, {"SBC", &SBC, &ABX, 4}, {"INC", &INC, &ABX, 7},
 979     {"???", &NUL, &IMP, 7}
 980 };
 981