7 u8int sA, sX, sY, sP, sS;
29 if(p >= 0xffc0 && (spcmem[0xf1] & 0x80) != 0)
30 return ipl[p - 0xffc0];
31 if((p & 0xfff0) == 0x00f0)
37 return reg[0x2140 | p & 3];
53 spcwrite(u16int p, u8int v)
55 if((p & 0xfff0) == 0x00f0)
59 print("SPC test register set to value %#x != 0xa\n", v);
63 reg[0x2140] = reg[0x2141] = 0;
65 reg[0x2142] = reg[0x2143] = 0;
66 if((spcmem[0xf1] & 1) == 0 && (v & 1) != 0)
67 spctimer[0] = spcmem[0xfd] = 0;
68 if((spcmem[0xf1] & 2) == 0 && (v & 2) != 0)
69 spctimer[1] = spcmem[0xfe] = 0;
70 if((spcmem[0xf1] & 4) == 0 && (v & 4) != 0)
71 spctimer[2] = spcmem[0xff] = 0;
89 if((m & 1) != 0 && ++spctimer[0] == spcmem[0xfa]){
91 spcmem[0xfd] = (spcmem[0xfd] + 1) & 0xf;
93 if((m & 2) != 0 && ++spctimer[1] == spcmem[0xfb]){
95 spcmem[0xfe] = (spcmem[0xfe] + 1) & 0xf;
99 if((m & 4) != 0 && ++spctimer[2] == spcmem[0xfc]){
101 spcmem[0xff] = (spcmem[0xff] + 1) & 0xf;
108 return spcread(spc++);
127 a |= spcread(p) << 8;
137 if((p & 0xff) == 0xff)
141 a |= spcread(p) << 8;
148 spcwrite(0x100 | sS--, v);
154 spcwrite(0x100 | sS--, v>>8);
155 spcwrite(0x100 | sS--, v);
161 return spcread(0x100 | ++sS);
169 v = spcread(0x100 | ++sS);
170 v |= spcread(0x100 | ++sS) << 8;
174 #define imm() fetch8()
175 #define dp ((sP&SPCP)<<3)
176 #define azp() (fetch8()|dp)
177 #define azpX() ((u8int)(fetch8()+sX)|dp)
178 #define azpY() ((u8int)(fetch8()+sY)|dp)
179 #define zp() spcread(azp())
180 #define zpX() spcread(azpX())
181 #define zpY() spcread(azpY())
182 #define abs() spcread(fetch16())
183 #define absX() spcread(fetch16()+sX)
184 #define absY() spcread(fetch16()+sY)
185 #define indX() spcread(aindX())
186 #define indY() spcread(aindY())
195 a = spcread(r++ | dp);
196 a |= spcread(r | dp) << 8;
207 a = spcread(r++ | dp) + sY;
208 a += spcread(r | dp) << 8;
226 if(sA == 0 && sY == 0)
244 if(((npc ^ spc) & 0xff00) != 0)
251 clrb(u16int a, int b)
253 spcwrite(a, spcread(a) & ~(1<<b));
257 cmp(u8int a, u8int b)
259 sP &= ~(SPCZ|SPCN|SPCC);
269 adc(u8int a, u8int b)
274 r8 = r = a + b + (sP & SPCC);
275 sP &= ~(SPCC|SPCZ|SPCH|SPCV|SPCN);
279 if((a ^ b ^ r) & 0x10)
281 if((~(a ^ b) & (a ^ r)) & 0x80)
291 spcwrite(a, nz(spcread(a) + 1));
308 spcwrite(a, nz(v << 1));
319 spcwrite(a, nz(v >> 1));
336 inc16(u16int a, int c)
344 if((v & 0x8000) != 0)
364 sbc(u8int a, u8int b)
370 setb(u16int a, int b)
372 spcwrite(a, spcread(a) | (1<<b));
376 setnbit(u16int a, int c)
381 v = spcread(a & 0x1fff) & ~(1<<b);
384 spcwrite(a & 0x1fff, v);
388 tset(u16int a, int set)
408 if((sX & 0xf) <= (sY & 0xf))
412 for(i = 0; i < 9; i++){
413 v = (v << 1 | v >> 16) & 0x1ffff;
417 v = (v - x) & 0x1ffff;
430 spc = spcread(0xfffe) | spcread(0xffff) << 8;
443 print("SPC %.4x %.2x A=%.2x X=%.2x Y=%.2x P=%.2x S=%.2x\n", spc-1, op, sA, sX, sY, sP, sS);
446 case 0x01: jsr(mem16(0xffde)); return 8;
447 case 0x02: setb(azp(), 0); return 4;
448 case 0x03: return branch((zp() & 0x01) != 0, 5);
449 case 0x04: nz(sA |= zp()); return 3;
450 case 0x05: nz(sA |= abs()); return 4;
451 case 0x06: nz(sA |= spcread(sX|dp)); return 3;
452 case 0x07: nz(sA |= indX()); return 6;
453 case 0x08: nz(sA |= imm()); return 2;
454 case 0x09: b = zp(); c = azp(); spcwrite(c, nz(b | spcread(c))); return 6;
455 case 0x0A: b = fetch16(); sP |= (spcread(b & 0x1fff) >> (b >> 13)) & 1; return 4;
456 case 0x0B: asl(azp()); return 5;
457 case 0x0C: asl(fetch16()); return 5;
458 case 0x0D: push8(sP); return 4;
459 case 0x0E: tset(fetch16(), 1); return 6;
460 case 0x10: return branch((sP & SPCN) == 0, 2);
461 case 0x11: jsr(mem16(0xffdc)); return 8;
462 case 0x12: clrb(azp(), 0); return 4;
463 case 0x13: return branch((zp() & 0x01) == 0, 5);
464 case 0x14: nz(sA |= zpX()); return 4;
465 case 0x15: nz(sA |= absX()); return 5;
466 case 0x16: nz(sA |= absY()); return 5;
467 case 0x17: nz(sA |= indY()); return 6;
468 case 0x18: a = imm(); b = azp(); spcwrite(b, nz(spcread(b) | a)); return 5;
469 case 0x19: spcwrite(sX|dp, nz(spcread(sX|dp) | spcread(sY|dp))); return 5;
470 case 0x1A: inc16(azp(), -1); return 6;
471 case 0x1B: asl(azpX()); return 5;
472 case 0x1C: sP &= ~SPCC; sP |= sA >> 7; nz(sA <<= 1); return 2;
473 case 0x1D: nz(--sX); return 2;
474 case 0x1E: cmp(sX, abs()); return 4;
475 case 0x1F: spc = mem16(fetch16() + sX); return 6;
476 case 0x20: sP &= ~SPCP; return 2;
477 case 0x21: jsr(mem16(0xffda)); return 8;
478 case 0x22: setb(azp(), 1); return 4;
479 case 0x23: return branch((zp() & 0x02) != 0, 5);
480 case 0x24: nz(sA &= zp()); return 3;
481 case 0x25: nz(sA &= abs()); return 4;
482 case 0x26: nz(sA &= spcread(sX|dp)); return 3;
483 case 0x27: nz(sA &= indX()); return 6;
484 case 0x28: nz(sA &= imm()); return 2;
485 case 0x29: b = zp(); c = azp(); spcwrite(c, nz(b & spcread(c))); return 6;
486 case 0x2A: b = fetch16(); sP |= (~spcread(b & 0x1fff) >> (b >> 13)) & 1; return 4;
487 case 0x2B: rol(azp()); return 4;
488 case 0x2C: rol(fetch16()); return 5;
489 case 0x2D: push8(sA); return 4;
490 case 0x2E: return branch(sA != zp(), 5);
491 case 0x2F: return branch(1, 2);
492 case 0x30: return branch((sP & SPCN) != 0, 2);
493 case 0x31: jsr(mem16(0xffd8)); return 8;
494 case 0x32: clrb(azp(), 1); return 4;
495 case 0x33: return branch((zp() & 0x02) == 0, 5);
496 case 0x34: nz(sA &= zpX()); return 4;
497 case 0x35: nz(sA &= absX()); return 5;
498 case 0x36: nz(sA &= absY()); return 5;
499 case 0x37: nz(sA &= indY()); return 6;
500 case 0x38: a = imm(); b = azp(); spcwrite(b, nz(spcread(b) & a)); return 5;
501 case 0x39: spcwrite(sX|dp, nz(spcread(sX|dp) & spcread(sY|dp))); return 5;
502 case 0x3A: inc16(azp(), 1); return 6;
503 case 0x3B: rol(azpX()); return 5;
511 case 0x3D: nz(++sX); return 2;
512 case 0x3E: cmp(sX, zp()); return 3;
513 case 0x3F: jsr(fetch16()); return 8;
514 case 0x40: sP |= SPCP; return 2;
515 case 0x41: jsr(mem16(0xffd6)); return 8;
516 case 0x42: setb(azp(), 2); return 4;
517 case 0x43: return branch((zp() & 0x04) != 0, 5);
518 case 0x44: nz(sA ^= zp()); return 3;
519 case 0x45: nz(sA ^= abs()); return 4;
520 case 0x46: nz(sA ^= spcread(sX|dp)); return 3;
521 case 0x47: nz(sA ^= indX()); return 6;
522 case 0x48: nz(sA ^= imm()); return 2;
523 case 0x49: b = zp(); c = azp(); spcwrite(c, nz(b ^ spcread(c))); return 6;
524 case 0x4A: b = fetch16(); sP &= 0xfe | (spcread(b & 0x1fff) >> (b >> 13)) & 1; return 4;
525 case 0x4B: lsr(azp()); return 4;
526 case 0x4C: lsr(fetch16()); return 5;
527 case 0x4D: push8(sX); return 4;
528 case 0x4E: tset(fetch16(), 0); return 5;
529 case 0x4F: jsr(0xff00 | fetch8()); return 6;
530 case 0x50: return branch((sP & SPCV) == 0, 2);
531 case 0x51: jsr(mem16(0xffd4)); return 8;
532 case 0x52: clrb(azp(), 2); return 4;
533 case 0x53: return branch((zp() & 0x04) == 0, 5);
534 case 0x54: nz(sA ^= zpX()); return 4;
535 case 0x55: nz(sA ^= absX()); return 5;
536 case 0x56: nz(sA ^= absY()); return 5;
537 case 0x57: nz(sA ^= indY()); return 6;
538 case 0x58: a = imm(); b = azp(); spcwrite(b, nz(spcread(b) ^ a)); return 5;
539 case 0x59: spcwrite(sX|dp, nz(spcread(sX|dp) ^ spcread(sY|dp))); return 5;
543 sP &= ~(SPCN|SPCZ|SPCC);
548 if(((b - c) & 0x8000) != 0)
551 case 0x5B: lsr(azpX()); return 4;
552 case 0x5C: sP &= ~SPCC; sP |= sA & 1; nz(sA >>= 1); return 2;
553 case 0x5D: nz(sX = sA); return 2;
554 case 0x5E: cmp(sY, abs()); return 4;
555 case 0x5F: spc = fetch16(); return 3;
556 case 0x60: sP &= ~SPCC; return 2;
557 case 0x61: jsr(mem16(0xffd2)); return 8;
558 case 0x62: setb(azp(), 3); return 4;
559 case 0x63: return branch((zp() & 0x08) != 0, 5);
560 case 0x64: cmp(sA, zp()); return 3;
561 case 0x65: cmp(sA, abs()); return 4;
562 case 0x66: cmp(sA, spcread(sX|dp)); return 3;
563 case 0x67: cmp(sA, indX()); return 6;
564 case 0x68: cmp(sA, imm()); return 2;
565 case 0x69: a = zp(); cmp(zp(), a); return 6;
566 case 0x6A: b = fetch16(); sP &= ~((spcread(b & 0x1fff) >> (b >> 13)) & 1); return 4;
567 case 0x6B: ror(azp()); return 4;
568 case 0x6C: ror(fetch16()); return 5;
569 case 0x6D: push8(sY); return 4;
570 case 0x6E: b = azp(); a = spcread(b)-1; spcwrite(b, a); return branch(a != 0, 5);
571 case 0x6F: spc = pop16(); return 5;
572 case 0x70: return branch((sP & SPCV) != 0, 2);
573 case 0x72: clrb(azp(), 3); return 4;
574 case 0x71: jsr(mem16(0xffd0)); return 8;
575 case 0x73: return branch((zp() & 0x08) == 0, 5);
576 case 0x74: cmp(sA, zpX()); return 4;
577 case 0x75: cmp(sA, absX()); return 5;
578 case 0x76: cmp(sA, absY()); return 5;
579 case 0x77: cmp(sA, indY()); return 6;
580 case 0x78: a = imm(); cmp(zp(), a); return 5;
581 case 0x79: cmp(spcread(sX|dp), spcread(sY|dp)); return 5;
585 sY = adc(sY, b >> 8);
589 case 0x7B: ror(azpX()); return 5;
594 sA = sA >> 1 | a << 7;
597 case 0x7D: nz(sA = sX); return 2;
598 case 0x7E: cmp(sY, zp()); return 3;
599 case 0x7F: sP = pop8(); spc = pop16(); return 6;
600 case 0x80: sP |= SPCC; return 2;
601 case 0x81: jsr(mem16(0xffce)); return 8;
602 case 0x82: setb(azp(), 4); return 4;
603 case 0x83: return branch((zp() & 0x10) != 0, 5);
604 case 0x84: sA = adc(sA, zp()); return 3;
605 case 0x85: sA = adc(sA, abs()); return 4;
606 case 0x86: sA = adc(sA, spcread(sX|dp)); return 3;
607 case 0x87: sA = adc(sA, indX()); return 6;
608 case 0x88: sA = adc(sA, imm()); return 2;
609 case 0x89: b = zp(); c = azp(); spcwrite(c, adc(b, spcread(c))); return 6;
610 case 0x8A: b = fetch16(); sP ^= (spcread(b & 0x1fff) >> (b >> 13)) & 1; return 4;
611 case 0x8B: b = azp(); spcwrite(b, nz(spcread(b)-1)); return 4;
612 case 0x8C: b = fetch16(); spcwrite(b, nz(spcread(b)-1)); return 4;
613 case 0x8D: nz(sY = imm()); return 2;
614 case 0x8E: sP = pop8(); return 2;
615 case 0x8F: a = fetch8(); spcwrite(azp(), a); return 5;
616 case 0x90: return branch((sP & SPCC) == 0, 2);
617 case 0x91: jsr(mem16(0xffcc)); return 8;
618 case 0x92: clrb(azp(), 4); return 4;
619 case 0x93: return branch((zp() & 0x10) == 0, 5);
620 case 0x94: sA = adc(sA, zpX()); return 4;
621 case 0x95: sA = adc(sA, absX()); return 5;
622 case 0x96: sA = adc(sA, absY()); return 5;
623 case 0x97: sA = adc(sA, indY()); return 6;
624 case 0x98: a = imm(); b = azp(); spcwrite(b, adc(spcread(b), a)); return 5;
625 case 0x99: spcwrite(sX|dp, adc(spcread(sX|dp), spcread(sY|dp))); return 5;
629 sY = sbc(sY, b >> 8);
633 case 0x9B: b = azpX(); spcwrite(b, nz(spcread(b)-1)); return 4;
634 case 0x9C: nz(--sA); return 2;
635 case 0x9D: nz(sX = sS); return 2;
636 case 0x9E: div(); return 12;
637 case 0x9F: nz(sA = sA >> 4 | sA << 4); return 5;
638 case 0xA0: sP |= SPCI; return 2;
639 case 0xA1: jsr(mem16(0xffca)); return 8;
640 case 0xA2: setb(azp(), 5); return 4;
641 case 0xA3: return branch((zp() & 0x20) != 0, 5);
642 case 0xA4: sA = sbc(sA, zp()); return 3;
643 case 0xA5: sA = sbc(sA, abs()); return 4;
644 case 0xA6: sA = sbc(sA, spcread(sX|dp)); return 3;
645 case 0xA7: sA = sbc(sA, indX()); return 6;
646 case 0xA8: sA = sbc(sA, imm()); return 2;
647 case 0xA9: b = zp(); c = azp(); spcwrite(c, sbc(spcread(c), b)); return 6;
648 case 0xAA: b = fetch16(); sP &= ~1; sP |= (spcread(b & 0x1fff) >> (b >> 13)) & 1; return 4;
649 case 0xAB: inc(azp()); return 4;
650 case 0xAC: inc(fetch16()); return 5;
651 case 0xAD: cmp(sY, imm()); return 2;
652 case 0xAE: sA = pop8(); return 2;
653 case 0xAF: spcwrite(sX++|dp, sA); return 4;
654 case 0xB0: return branch((sP & SPCC) != 0, 2);
655 case 0xB1: jsr(mem16(0xffc8)); return 8;
656 case 0xB2: clrb(azp(), 5); return 4;
657 case 0xB3: return branch((zp() & 0x20) == 0, 5);
658 case 0xB4: sA = sbc(sA, zpX()); return 4;
659 case 0xB5: sA = sbc(sA, absX()); return 5;
660 case 0xB6: sA = sbc(sA, absY()); return 5;
661 case 0xB7: sA = sbc(sA, indY()); return 6;
662 case 0xB8: a = imm(); b = azp(); spcwrite(b, sbc(spcread(b), a)); return 5;
663 case 0xB9: spcwrite(sX|dp, sbc(spcread(sX|dp), spcread(sY|dp))); return 5;
664 case 0xBA: a = fetch8(); sA = spcread(a++|dp); sY = spcread(a|dp); nz16(); return 5;
665 case 0xBB: inc(azpX()); return 4;
666 case 0xBC: nz(++sA); return 2;
667 case 0xBD: sS = sX; return 2;
668 case 0xBF: nz(sA = spcread(sX++|dp)); return 3;
669 case 0xC0: sP &= ~SPCI; return 2;
670 case 0xC1: jsr(mem16(0xffc6)); return 8;
671 case 0xC2: setb(azp(), 6); return 4;
672 case 0xC3: return branch((zp() & 0x40) != 0, 5);
673 case 0xC4: spcwrite(azp(), sA); return 4;
674 case 0xC5: spcwrite(fetch16(), sA); return 5;
675 case 0xC6: spcwrite(sX|dp, sA); return 4;
676 case 0xC7: spcwrite(aindX(), sA); return 7;
677 case 0xC8: cmp(sX, imm()); return 2;
678 case 0xC9: spcwrite(fetch16(), sX); return 5;
679 case 0xCA: b = fetch16(); setnbit(b, sP & SPCC); return 6;
680 case 0xCB: spcwrite(azp(), sY); return 4;
681 case 0xCC: spcwrite(fetch16(), sY); return 5;
682 case 0xCD: nz(sX = imm()); return 2;
683 case 0xCE: sX = pop8(); return 2;
684 case 0xCF: b = sY * sA; nz(sY = b >> 8); sA = b; return 9;
685 case 0xD0: return branch((sP & SPCZ) == 0, 2);
686 case 0xD1: jsr(mem16(0xffc4)); return 8;
687 case 0xD2: clrb(azp(), 6); return 4;
688 case 0xD3: return branch((zp() & 0x40) == 0, 5);
689 case 0xD4: spcwrite(azpX(), sA); return 4;
690 case 0xD5: spcwrite(fetch16() + sX, sA); return 6;
691 case 0xD6: spcwrite(fetch16() + sY, sA); return 6;
692 case 0xD7: spcwrite(aindY(), sA); return 7;
693 case 0xD8: spcwrite(azp(), sX); return 4;
694 case 0xD9: spcwrite(azpY(), sX); return 5;
695 case 0xDA: a = fetch8(); spcwrite(a++|dp, sA); spcwrite(a|dp, sY); return 5;
696 case 0xDB: spcwrite(azpX(), sY); return 5;
697 case 0xDC: nz(--sY); return 2;
698 case 0xDD: nz(sA = sY); return 2;
699 case 0xDE: return branch(sA != zpX(), 6);
700 case 0xE0: sP &= ~(SPCV|SPCH); return 2;
701 case 0xE1: jsr(mem16(0xffc2)); return 8;
702 case 0xE2: setb(azp(), 7); return 4;
703 case 0xE3: return branch((zp() & 0x80) != 0, 5);
704 case 0xE4: nz(sA = zp()); return 3;
705 case 0xE5: nz(sA = abs()); return 4;
706 case 0xE6: nz(sA = spcread(sX|dp)); return 3;
707 case 0xE7: nz(sA = indX()); return 6;
708 case 0xE8: nz(sA = imm()); return 2;
709 case 0xE9: nz(sX = abs()); return 4;
710 case 0xEA: b = fetch16(); spcwrite(b & 0x1fff, spcread(b & 0x1fff) ^ (1<<(b>>13))); return 6;
711 case 0xEB: nz(sY = zp()); return 3;
712 case 0xEC: nz(sY = abs()); return 4;
713 case 0xED: sP ^= SPCC; return 3;
714 case 0xEE: sY = pop8(); return 4;
715 case 0xF0: return branch((sP & SPCZ) != 0, 2);
716 case 0xF1: jsr(mem16(0xffc0)); return 8;
717 case 0xF2: clrb(azp(), 7); return 4;
718 case 0xF3: return branch((zp() & 0x80) == 0, 5);
719 case 0xF4: nz(sA = zpX()); return 4;
720 case 0xF5: nz(sA = absX()); return 5;
721 case 0xF6: nz(sA = absY()); return 5;
722 case 0xF7: nz(sA = indY()); return 6;
723 case 0xF8: nz(sX = zp()); return 3;
724 case 0xF9: nz(sX = zpY()); return 4;
725 case 0xFA: a = zp(); spcwrite(azp(), a); return 5;
726 case 0xFB: nz(sY = zpX()); return 4;
727 case 0xFC: nz(++sY); return 2;
728 case 0xFD: nz(sY = sA); return 2;
729 case 0xFE: return branch(--sY, 4);
731 print("undefined spc op %.2x at %.4x\n", op, spc-1);
736 static u8int ipl[64] = {
737 0xcd, 0xef, 0xbd, 0xe8, 0x00, 0xc6, 0x1d, 0xd0, 0xfc, 0x8f, 0xaa, 0xf4, 0x8f, 0xbb, 0xf5, 0x78,
738 0xcc, 0xf4, 0xd0, 0xfb, 0x2f, 0x19, 0xeb, 0xf4, 0xd0, 0xfc, 0x7e, 0xf4, 0xd0, 0x0b, 0xe4, 0xf5,
739 0xcb, 0xf4, 0xd7, 0x00, 0xfc, 0xd0, 0xf3, 0xab, 0x01, 0x10, 0xef, 0x7e, 0xf4, 0x10, 0xeb, 0xba,
740 0xf6, 0xda, 0x00, 0xba, 0xf4, 0xc4, 0xf4, 0xdd, 0x5d, 0xd0, 0xdb, 0x1f, 0x00, 0x00, 0xc0, 0xff,