]> Untitled Git - pico1541.git/commitdiff
Implement most 6502 illegals + some timing fixes
authorMaxwell Beck <max@rastertail.net>
Sat, 28 Dec 2024 22:19:19 +0000 (16:19 -0600)
committerMaxwell Beck <max@rastertail.net>
Sat, 28 Dec 2024 22:19:19 +0000 (16:19 -0600)
src/6502.c

index 06ba198a6b086b1c0a6a11200bdc6d95ef41a900..5d38029fc99600631527214a648b4d23ce9d674c 100644 (file)
                } \
        } while (0)
 
+#define R_INDY_RMW() \
+       do { \
+               cpu->pc++; \
+               ea = bus_read(operand, cycles); \
+               cycles++; \
+               ea += cpu->y; \
+               uint16_t carry = ea & 0x0100; \
+               ea &= 0xff; \
+               ea |= bus_read((operand + 1) & 0xff, cycles) << 8; \
+               cycles++; \
+               a = bus_read(ea, cycles); \
+               cycles++; \
+               if (carry) { \
+                       ea += 0x100; \
+               } \
+               a = bus_read(ea, cycles); \
+               cycles++; \
+       } while (0)
+
 #define W_R(r) \
        do { \
                cpu->r = a; \
                ea |= bus_read(cpu->pc, cycles) << 8; \
                cpu->pc++; \
                cycles++; \
-               if (!carry) { \
-                       bus_write(ea, a, cycles); \
-                       cycles++; \
-               } else { \
-                       bus_read(ea, cycles); \
-                       cycles++; \
+               bus_read(ea, cycles); \
+               cycles++; \
+               if (carry) { \
                        ea += 0x100; \
-                       bus_write(ea, a, cycles); \
-                       cycles++; \
                } \
+               bus_write(ea, a, cycles); \
+               cycles++; \
        } while (0)
 
 #define W_ABSX() W_ABSI(x)
                ea &= 0xff; \
                ea |= bus_read((operand + 1) & 0xff, cycles) << 8; \
                cycles++; \
-               if (!carry) { \
-                       bus_write(ea, a, cycles); \
-                       cycles++; \
-               } else { \
-                       bus_read(ea, cycles); \
-                       cycles++; \
+               bus_read(ea, cycles); \
+               cycles++; \
+               if (carry) { \
                        ea += 0x100; \
-                       bus_write(ea, a, cycles); \
-                       cycles++; \
                } \
+               bus_write(ea, a, cycles); \
+               cycles++; \
        } while (0)
 
 #define W_EA() \
 
 #define LOAD() r = a
 
+#define ALR() \
+       do { \
+               r = r & a; \
+               FLAG_SET(C, r & 1); \
+               r = r >> 1; \
+       } while (0) \
+
+#define ANC() \
+       do { \
+               r = r & a; \
+               FLAG_SET(C, (r & 0x80) >> 7); \
+       } while (0) \
+
+#define ARR() \
+       do { \
+               uint8_t c = FLAG_GET(C); \
+               r = r & a; \
+               uint16_t res = r + a + c; \
+               FLAG_SET(N, (res & 0x100) >> 8); \
+               FLAG_SET(V, ((r ^ res) & (a ^ res) & 0x80) >> 7); \
+               FLAG_SET(C, r & 1); \
+               r = (r >> 1) | (r << 7); \
+       } while (0);
+
+#define DCP(src, dst) \
+       do { \
+               uint8_t a; \
+               uint16_t ea = 0; \
+               src(); \
+               dst(); \
+               a = a - 1; \
+               uint16_t res = cpu->a - a; \
+               FLAG_SET(C, (~res & 0x100) >> 8); \
+               FLAG_SET(N, (res & 0x80) >> 7); \
+               FLAG_SET(Z, ((res & 0xff) == 0) ? 1 : 0); \
+               dst(); \
+       } while (0); break
+
+#define ISC(src, dst) \
+       do { \
+               uint8_t a; \
+               uint16_t ea = 0; \
+               src(); \
+               dst(); \
+               a = a + 1; \
+               dst(); \
+               uint8_t r = cpu->a; \
+               SBC(); \
+               FLAG_SET(N, (r & 0x80) >> 7); \
+               FLAG_SET(Z, (r == 0) ? 1 : 0); \
+               cpu->a = r; \
+       } while (0); break
+
+#define LAX(src) \
+       do { \
+               uint8_t r = cpu->a; \
+               uint16_t ea = 0; \
+               uint8_t a; \
+               src(); \
+               LOAD(); \
+               FLAG_SET(N, (r & 0x80) >> 7); \
+               FLAG_SET(Z, (r == 0) ? 1 : 0); \
+               cpu->a = r; \
+               cpu->x = r; \
+       } while (0); break
+
+#define RLA(src, dst) \
+       do { \
+               uint8_t a; \
+               uint16_t ea = 0; \
+               src(); \
+               dst(); \
+               ROL(); \
+               dst(); \
+               uint8_t r = cpu->a & a; \
+               FLAG_SET(N, (r & 0x80) >> 7); \
+               FLAG_SET(Z, (r == 0) ? 1 : 0); \
+               cpu->a = r; \
+       } while (0); break
+
+#define RRA(src, dst) \
+       do { \
+               uint8_t a; \
+               uint16_t ea = 0; \
+               src(); \
+               dst(); \
+               ROR(); \
+               dst(); \
+               uint8_t r = cpu->a; \
+               ADC(); \
+               FLAG_SET(N, (r & 0x80) >> 7); \
+               FLAG_SET(Z, (r == 0) ? 1 : 0); \
+               cpu->a = r; \
+       } while (0); break
+
+#define SAX(dst) \
+       do { \
+               uint8_t a = cpu-> a & cpu->x; \
+               dst(); \
+       } while (0); break
+
+#define SLO(src, dst) \
+       do { \
+               uint8_t a; \
+               uint16_t ea = 0; \
+               src(); \
+               dst(); \
+               ASL(); \
+               dst(); \
+               uint8_t r = cpu->a | a; \
+               FLAG_SET(N, (r & 0x80) >> 7); \
+               FLAG_SET(Z, (r == 0) ? 1 : 0); \
+               cpu->a = r; \
+       } while (0); break
+
+#define SRE(src, dst) \
+       do { \
+               uint8_t a; \
+               uint16_t ea = 0; \
+               src(); \
+               dst(); \
+               LSR(); \
+               dst(); \
+               uint8_t r = cpu->a ^ a; \
+               FLAG_SET(N, (r & 0x80) >> 7); \
+               FLAG_SET(Z, (r == 0) ? 1 : 0); \
+               cpu->a = r; \
+       } while (0); break
+
 void cpu_reset(cpu_t *cpu) {
        cpu->a = 0;
        cpu->x = 0;
@@ -471,6 +613,7 @@ uint8_t cpu_step(cpu_t *cpu) {
                case 0x71: OP(a, R_INDY, ADC);
 
                // SBC
+               case 0xeb:
                case 0xe9: OP(a, R_IMM, SBC);
                case 0xe5: OP(a, R_ZP, SBC);
                case 0xf5: OP(a, R_ZPX, SBC);
@@ -714,13 +857,202 @@ uint8_t cpu_step(cpu_t *cpu) {
 
                case 0x9a: cpu->sp = cpu->x; break;
 
-               // NOP
-               case 0xea: break;
+               // NOPs
+               case 0x1a:
+               case 0x3a:
+               case 0x5a:
+               case 0x7a:
+               case 0xda:
+               case 0xea:
+               case 0xfa:
+                       break;
+
+               case 0x80:
+               case 0x82:
+               case 0x89:
+               case 0xc2:
+               case 0xe2:
+                       do {
+                               uint8_t a;
+                               R_IMM();
+                       } while (0);
+                       break;
+
+               case 0x04:
+               case 0x44:
+               case 0x64:
+                       do {
+                               uint8_t a;
+                               uint16_t ea;
+                               R_ZP();
+                       } while (0);
+                       break;
+
+               case 0x14:
+               case 0x34:
+               case 0x54:
+               case 0x74:
+               case 0xd4:
+               case 0xf4:
+                       do {
+                               uint8_t a;
+                               uint16_t ea;
+                               R_ZPX();
+                       } while (0);
+                       break;
+
+               case 0x0c:
+                       do {
+                               uint8_t a;
+                               uint16_t ea;
+                               R_ABS();
+                       } while (0);
+                       break;
+
+               case 0x1c:
+               case 0x3c:
+               case 0x5c:
+               case 0x7c:
+               case 0xdc:
+               case 0xfc:
+                       do {
+                               uint8_t a;
+                               uint16_t ea;
+                               R_ABSX();
+                       } while (0);
+                       break;
 
                // BIT
                case 0x24: BIT(R_ZP);
                case 0x2C: BIT(R_ABS);
 
+               // Illegals
+
+               // ALR
+               case 0x4b: OP(a, R_IMM, ALR);
+
+               // ANC
+               case 0x0b:
+               case 0x2b:
+                       OP(a, R_IMM, ANC);
+
+               // SKIP ANE
+
+               // ARR (FIXME INCORRECT FLAGS)
+               case 0x6b:
+                       do {
+                               uint8_t r = cpu->a;
+                               uint16_t ea = 0;
+                               uint8_t a;
+                               R_IMM();
+                               ARR();
+                               FLAG_SET(Z, (r == 0) ? 1 : 0);
+                               cpu->a = r;
+                       } while (0);
+                       break;
+
+               // DCP
+               case 0xc7: DCP(R_ZP, W_EA);
+               case 0xd7: DCP(R_ZPX, W_EA);
+               case 0xcf: DCP(R_ABS, W_EA);
+               case 0xdf: DCP(R_ABSX, W_EA);
+               case 0xdb: DCP(R_ABSY, W_EA);
+               case 0xc3: DCP(R_INDX, W_EA);
+               case 0xd3: DCP(R_INDY_RMW, W_EA);
+
+               // ISC
+               case 0xe7: ISC(R_ZP, W_EA);
+               case 0xf7: ISC(R_ZPX, W_EA);
+               case 0xef: ISC(R_ABS, W_EA);
+               case 0xff: ISC(R_ABSX, W_EA);
+               case 0xfb: ISC(R_ABSY, W_EA);
+               case 0xe3: ISC(R_INDX, W_EA);
+               case 0xf3: ISC(R_INDY_RMW, W_EA);
+
+               // LAS
+               case 0xbb:
+                       do {
+                               uint16_t ea = 0;
+                               uint8_t a;
+                               R_ABSY();
+                               uint8_t r = a & cpu->sp;
+                               FLAG_SET(N, (r & 0x80) >> 7);
+                               FLAG_SET(Z, (r == 0) ? 1 : 0);
+                               cpu->a = r;
+                               cpu->x = r;
+                               cpu->sp = r;
+                       } while (0);
+                       break;
+
+               // LAX
+               case 0xa7: LAX(R_ZP);
+               case 0xb7: LAX(R_ZPY);
+               case 0xaf: LAX(R_ABS);
+               case 0xbf: LAX(R_ABSY);
+               case 0xa3: LAX(R_INDX);
+               case 0xb3: LAX(R_INDY);
+
+               // SKIP LXA
+
+               // RLA
+               case 0x27: RLA(R_ZP, W_EA);
+               case 0x37: RLA(R_ZPX, W_EA);
+               case 0x2f: RLA(R_ABS, W_EA);
+               case 0x3f: RLA(R_ABSX, W_EA);
+               case 0x3b: RLA(R_ABSY, W_EA);
+               case 0x23: RLA(R_INDX, W_EA);
+               case 0x33: RLA(R_INDY_RMW, W_EA);
+
+               // RRA
+               case 0x67: RRA(R_ZP, W_EA);
+               case 0x77: RRA(R_ZPX, W_EA);
+               case 0x6f: RRA(R_ABS, W_EA);
+               case 0x7f: RRA(R_ABSX, W_EA);
+               case 0x7b: RRA(R_ABSY, W_EA);
+               case 0x63: RRA(R_INDX, W_EA);
+               case 0x73: RRA(R_INDY_RMW, W_EA);
+
+               // SAX
+               case 0x87: SAX(W_ZP);
+               case 0x97: SAX(W_ZPY);
+               case 0x8f: SAX(W_ABS);
+               case 0x83: SAX(W_INDX);
+
+               // SBX
+               case 0xcb:
+                       do { \
+                               uint8_t a; \
+                               R_IMM(); \
+                               uint16_t res = (cpu->a & cpu->x) - a; \
+                               FLAG_SET(C, (~res & 0x100) >> 8); \
+                               FLAG_SET(N, (res & 0x80) >> 7); \
+                               FLAG_SET(Z, ((res & 0xff) == 0) ? 1 : 0); \
+                               cpu->x = res;
+                       } while (0);
+                       break;
+
+               // SKIP SHA, SHX, SHY
+
+               // SLO
+               case 0x07: SLO(R_ZP, W_EA);
+               case 0x17: SLO(R_ZPX, W_EA);
+               case 0x0f: SLO(R_ABS, W_EA);
+               case 0x1f: SLO(R_ABSX, W_EA);
+               case 0x1b: SLO(R_ABSY, W_EA);
+               case 0x03: SLO(R_INDX, W_EA);
+               case 0x13: SLO(R_INDY_RMW, W_EA);
+
+               // SRE
+               case 0x47: SRE(R_ZP, W_EA);
+               case 0x57: SRE(R_ZPX, W_EA);
+               case 0x4f: SRE(R_ABS, W_EA);
+               case 0x5f: SRE(R_ABSX, W_EA);
+               case 0x5b: SRE(R_ABSY, W_EA);
+               case 0x43: SRE(R_INDX, W_EA);
+               case 0x53: SRE(R_INDY_RMW, W_EA);
+
+               // SKIP TAS
+
                // Jam on everything else
                default:
                        cpu->jammed = true;