]> git.lizzy.rs Git - plan9front.git/blob - sys/src/games/c64/cpu.c
cafd8e33328662b40532039dd1b9c05388dc1252
[plan9front.git] / sys / src / games / c64 / cpu.c
1 #include <u.h>
2 #include <libc.h>
3 #include <emu.h>
4 #include "dat.h"
5 #include "fns.h"
6
7 u16int pc, curpc;
8 u8int rA, rX, rY, rS, rP;
9 int nrdy, irq, nmi, nmi0, irqen, nmien;
10
11 static u8int
12 fetch8(void)
13 {
14         return memread(pc++);
15 }
16
17 static u16int
18 fetch16(void)
19 {
20         u16int r;
21         
22         r = memread(pc++);
23         r |= memread(pc++) << 8;
24         return r;
25 }
26
27 static void
28 push8(u8int v)
29 {
30         memwrite(0x100 | rS--, v);
31 }
32
33 static void
34 push16(u16int v)
35 {
36         memwrite(0x100 | rS--, v >> 8);
37         memwrite(0x100 | rS--, v);
38 }
39
40 static u8int
41 pop8(void)
42 {
43         return memread(0x100 | ++rS);
44 }
45
46 static u16int
47 pop16(void)
48 {
49         u16int v;
50
51         v = memread(0x100 | ++rS);
52         v |= memread(0x100 | ++rS) << 8;
53         return v;
54 }
55
56 #define imm() fetch8()
57 #define zp() memread(fetch8())
58 #define zpX() memread(azpX(rX))
59 #define zpY() memread(azpX(rY))
60 #define abso() memread(fetch16())
61 #define absX() memread(aabsX(rX, 0))
62 #define absY() memread(aabsX(rY, 0))
63 #define indX() memread(aindX())
64 #define indY() memread(aindY(0))
65
66 static u16int
67 azpX(u8int a)
68 {
69         u8int v;
70         
71         v = fetch8();
72         memread(v);
73         return v + a;
74 }
75
76 static u16int
77 aabsX(u8int a, int wr)
78 {
79         u16int v, c;
80         
81         v = fetch16();
82         c = (u8int)v + a & 0x100;
83         v += a;
84         if(c != 0 || wr)
85                 memread(v - c);
86         return v;
87 }
88
89 static u16int
90 aindX(void)
91 {
92         u8int r;
93         u16int a;
94         
95         r = fetch8();
96         memread(r);
97         r += rX;
98         a = memread(r++);
99         a |= memread(r) << 8;
100         return a;
101 }
102
103 static u16int
104 aindY(int wr)
105 {
106         u8int r;
107         u16int a, c;
108         
109         r = fetch8();
110         a = memread(r++) + rY;
111         c = a & 0x100;
112         a += memread(r) << 8;
113         if(c != 0 || wr)
114                 memread(a - c);
115         return a;
116 }
117
118 static void
119 adc(u8int d)
120 {
121         int r;
122         
123         if((rP & FLAGD) != 0){
124                 r = (rA & 0xf) + (d & 0xf) + (rP & FLAGC);
125                 if(r > 0x09)
126                         r += 0x06;
127                 if(r > 0x1f)
128                         r -= 0x10;
129                 r += (rA & 0xf0) + (d & 0xf0);
130         }else
131                 r = rA + d + (rP & FLAGC);
132         rP &= ~(FLAGN | FLAGZ | FLAGV | FLAGC);
133         if((~(rA ^ d) & (rA ^ r)) & 0x80) rP |= FLAGV;
134         if((rP & FLAGD) != 0 && r > 0x9f)
135                 r += 0x60;
136         if(r > 0xFF) rP |= FLAGC;
137         if(r & 0x80) rP |= FLAGN;
138         rA = r;
139         if(rA == 0) rP |= FLAGZ;
140 }
141
142 static u8int
143 nz(u8int d)
144 {
145         rP &= ~(FLAGN | FLAGZ);
146         if(d & 0x80) rP |= FLAGN;
147         if(d == 0) rP |= FLAGZ;
148         return d;
149 }
150
151 static void
152 asl(u16int a)
153 {
154         u8int v;
155
156         rP &= ~(FLAGN | FLAGZ | FLAGC);
157         v = memread(a);
158         memwrite(a, v);
159         if(v & 0x80) rP |= FLAGC;
160         v <<= 1;
161         if(v == 0) rP |= FLAGZ;
162         if(v & 0x80) rP |= FLAGN;
163         memwrite(a, v);
164 }
165
166 static void
167 lsr(u16int a)
168 {
169         u8int v;
170
171         rP &= ~(FLAGN | FLAGZ | FLAGC);
172         v = memread(a);
173         memwrite(a, v);
174         rP |= v & 1;
175         v >>= 1;
176         if(v == 0) rP |= FLAGZ;
177         if(v & 0x80) rP |= FLAGN;
178         memwrite(a, v);
179 }
180
181 static void
182 branch(void)
183 {
184         s8int t;
185         u16int npc;
186         
187         t = fetch8();
188         memread(pc);
189         npc = pc + t;
190         if((npc ^ pc) >> 8)
191                 memread(pc & 0xff00 | npc & 0xff);
192         pc = npc;
193 }
194
195 static void
196 cmp(u8int a, u8int d)
197 {
198         rP &= ~(FLAGN | FLAGZ | FLAGC);
199         if(a == d) rP |= FLAGZ;
200         if(a >= d) rP |= FLAGC;
201         if((a - d) & 0x80) rP |= FLAGN;
202 }
203
204 static void
205 dec(u16int a)
206 {
207         u8int v;
208
209         v = memread(a);
210         memwrite(a, v);
211         memwrite(a, nz(v - 1));
212 }
213
214 static void
215 inc(u16int a)
216 {
217         u8int v;
218
219         v = memread(a);
220         memwrite(a, v);
221         v = nz(v + 1);
222         memwrite(a, v);
223 }
224
225 static void
226 rol(u16int a)
227 {
228         u8int v, b;
229         
230         v = memread(a);
231         memwrite(a, v);
232         b = rP & FLAGC;
233         rP &= ~(FLAGC | FLAGN | FLAGZ);
234         if(v & 0x80) rP |= FLAGC;
235         v = (v << 1) | b;
236         if(v & 0x80) rP |= FLAGN;
237         if(v == 0) rP |= FLAGZ;
238         memwrite(a, v);
239 }
240
241 static void
242 ror(u16int a)
243 {
244         u8int v, b;
245         
246         v = memread(a);
247         memwrite(a, v);
248         b = rP & FLAGC;
249         rP &= ~(FLAGC | FLAGN | FLAGZ);
250         rP |= v & 1;
251         v = (v >> 1) | (b << 7);
252         if(v & 0x80) rP |= FLAGN;
253         if(v == 0) rP |= FLAGZ;
254         memwrite(a, v);
255 }
256
257 static void
258 sbc(u8int d)
259 {
260         int r;
261         
262         if((rP & FLAGD) != 0){
263                 d = ~d;
264                 r = (rA & 0xf) + (d & 0xf) + (rP & FLAGC);
265                 if(r < 0x10) r -= 0x06;
266                 if(r < 0) r += 0x10;
267                 r += (rA & 0xf0) + (d & 0xf0);
268         }else
269                 r = rA + (u8int)~d + (rP & FLAGC);
270         rP &= ~(FLAGZ | FLAGV | FLAGC | FLAGN);
271         if(((rA ^ d) & (rA ^ r)) & 0x80) rP |= FLAGV;
272         if(r > 0xFF) rP |= FLAGC;
273         else if((rP & FLAGD) != 0)
274                 r -= 0x60;
275         rA = r;
276         if(rA == 0) rP |= FLAGZ;
277         if(rA & 0x80) rP |= FLAGN;
278 }
279
280 static void
281 interrupt(int nmi, int brk)
282 {
283         memread(pc);
284         if(brk)
285                 pc++;
286         push16(pc);
287         push8(rP | 0x20 | (brk << 4));
288         pc = memread(0xFFFA | (!nmi << 2));
289         pc |= memread(0xFFFB | (!nmi << 2)) << 8;
290         rP |= FLAGI;
291 }
292
293 void
294 step(void)
295 {
296         u8int op;
297         u16int a, v;
298         
299         if(nrdy){
300                 io();
301                 return;
302         }
303         if((nmi & nmien) != 0 && (nmi0 & nmien) == 0){
304                 nmi0 = nmi;
305                 interrupt(1, 0);
306                 return;
307         }
308         nmi0 = nmi;
309         if((irq & irqen) != 0 && (rP & FLAGI) == 0){
310                 interrupt(0, 0);
311                 return;
312         }
313         curpc = pc;
314         op = fetch8();
315         if(trace)
316                 print("%.4x %.2x | %.2x %.2x %.2x | %.2x %.2x | %3d %3d %.6x %.6x\n", curpc, op, rA, rX, rY, rS, rP, ppux-3, ppuy, irq, nmi);
317         switch(op){
318         case 0x00: fetch8(); interrupt(0, 1); return;
319         case 0x01: nz(rA |= indX()); return;
320         case 0x05: nz(rA |= zp()); return;
321         case 0x06: asl(fetch8()); return;
322         case 0x08: memread(pc); push8(rP | 0x30); return;
323         case 0x09: nz(rA |= imm()); return;
324         case 0x0A:
325                 rP &= ~(FLAGN | FLAGZ | FLAGC);
326                 if(rA & 0x80) rP |= FLAGC;
327                 rA <<= 1;
328                 if(rA == 0) rP |= FLAGZ;
329                 if(rA & 0x80) rP |= FLAGN;
330                 memread(pc);
331                 return;
332         case 0x0D: nz(rA |= abso()); return;
333         case 0x0E: asl(fetch16()); return;
334         case 0x10: if((rP & FLAGN) == 0) branch(); else fetch8(); return;
335         case 0x11: nz(rA |= indY()); return;
336         case 0x15: nz(rA |= zpX()); return;
337         case 0x16: asl(azpX(rX)); return;
338         case 0x18: rP &= ~FLAGC; memread(pc); return;
339         case 0x19: nz(rA |= absY()); return;
340         case 0x1D: nz(rA |= absX()); return;
341         case 0x1E: asl(aabsX(rX, 1)); return;
342         case 0x20: v = fetch8(); memread(rS|0x100); push16(pc); pc = fetch8() << 8 | v; return;
343         case 0x21: nz(rA &= indX()); return;
344         case 0x24:
345                 a = memread(fetch8());
346                 rP &= ~(FLAGN | FLAGZ | FLAGV);
347                 rP |= a & 0xC0;
348                 if((a & rA) == 0) rP |= FLAGZ;
349                 return;
350         case 0x25: nz(rA &= zp()); return;
351         case 0x26: rol(fetch8()); return;
352         case 0x28: memread(pc); memread(0x100|rS); rP = pop8() & 0xcf; return;
353         case 0x29: nz(rA &= imm()); return;
354         case 0x2A:
355                 a = rP & FLAGC;
356                 rP &= ~(FLAGC | FLAGZ | FLAGN);
357                 if(rA & 0x80) rP |= FLAGC;
358                 rA = (rA << 1) | a;
359                 if(rA & 0x80) rP |= FLAGN;
360                 if(rA == 0) rP |= FLAGZ;
361                 memread(pc);
362                 return;
363         case 0x2C:
364                 a = memread(fetch16());
365                 rP &= ~(FLAGN | FLAGZ | FLAGV);
366                 rP |= a & 0xC0;
367                 if((a & rA) == 0) rP |= FLAGZ;
368                 return;
369         case 0x2D: nz(rA &= abso()); return;
370         case 0x2E: rol(fetch16()); return;
371         case 0x30: if((rP & FLAGN) != 0) branch(); else fetch8(); return;
372         case 0x31: nz(rA &= indY()); return;
373         case 0x35: nz(rA &= zpX()); return;
374         case 0x36: rol(azpX(rX)); return;
375         case 0x38: rP |= FLAGC; memread(pc); return;
376         case 0x39: nz(rA &= absY()); return;
377         case 0x3E: rol(aabsX(rX, 1)); return;
378         case 0x3D: nz(rA &= absX()); return;
379         case 0x40: fetch8(); memread(rS|0x100); rP = pop8() & 0xcf; pc = pop16(); return;
380         case 0x41: nz(rA ^= indX()); return;
381         case 0x45: nz(rA ^= zp()); return;
382         case 0x46: lsr(fetch8()); return;
383         case 0x48: memread(pc); push8(rA); return;
384         case 0x49: nz(rA ^= imm()); return;
385         case 0x4A:
386                 rP &= ~(FLAGN | FLAGZ | FLAGC);
387                 rP |= rA & 1;
388                 rA >>= 1;
389                 if(rA == 0) rP |= FLAGZ;
390                 if(rA & 0x80) rP |= FLAGN;
391                 memread(pc);
392                 return;
393         case 0x4C: pc = fetch16(); return;
394         case 0x4D: nz(rA ^= abso()); return;
395         case 0x4E: lsr(fetch16()); return;
396         case 0x51: nz(rA ^= indY()); return;
397         case 0x56: lsr(azpX(rX)); return;
398         case 0x58: rP &= ~FLAGI; memread(pc); return;
399         case 0x50: if((rP & FLAGV) == 0) branch(); else fetch8(); return;
400         case 0x55: nz(rA ^= zpX()); return;
401         case 0x59: nz(rA ^= absY()); return;
402         case 0x5D: nz(rA ^= absX()); return;
403         case 0x5E: lsr(aabsX(rX, 1)); return;
404         case 0x60: fetch8(); memread(rS | 0x100); pc = pop16(); fetch8(); return;
405         case 0x61: adc(indX()); return;
406         case 0x65: adc(zp()); return;
407         case 0x66: ror(fetch8()); return;
408         case 0x68: memread(pc); memread(0x100|rS); nz(rA = pop8()); return;
409         case 0x69: adc(imm()); return;
410         case 0x6A:
411                 a = rP & FLAGC;
412                 rP &= ~(FLAGC | FLAGN | FLAGZ);
413                 rP |= rA & 1;
414                 rA = (rA >> 1) | (a << 7);
415                 if(rA & 0x80) rP |= FLAGN;
416                 if(rA == 0) rP |= FLAGZ;
417                 memread(pc);
418                 return;
419         case 0x6C: v = fetch16(); pc = memread(v) | (memread((v & 0xFF00) | (u8int)(v+1)) << 8); return;
420         case 0x6D: adc(abso()); return;
421         case 0x6E: ror(fetch16()); return;
422         case 0x70: if((rP & FLAGV) != 0) branch(); else fetch8(); return;
423         case 0x71: adc(indY()); return;
424         case 0x75: adc(zpX()); return;
425         case 0x76: ror(azpX(rX)); return;
426         case 0x78: rP |= FLAGI; memread(pc); return;
427         case 0x79: adc(absY()); return;
428         case 0x7D: adc(absX()); return;
429         case 0x7E: ror(aabsX(rX, 1)); return;
430         case 0x81: memwrite(aindX(), rA); return;
431         case 0x84: memwrite(fetch8(), rY); return;
432         case 0x85: memwrite(fetch8(), rA); return;
433         case 0x86: memwrite(fetch8(), rX); return;
434         case 0x88: nz(--rY); memread(pc); return;
435         case 0x8A: nz(rA = rX); memread(pc); return;
436         case 0x8C: memwrite(fetch16(), rY); return;
437         case 0x8D: memwrite(fetch16(), rA); return;
438         case 0x8E: memwrite(fetch16(), rX); return;
439         case 0x90: if((rP & FLAGC) == 0) branch(); else fetch8(); return;
440         case 0x91: memwrite(aindY(1), rA); return;
441         case 0x94: memwrite(azpX(rX), rY); return;
442         case 0x95: memwrite(azpX(rX), rA); return;
443         case 0x96: memwrite(azpX(rY), rX); return;
444         case 0x98: nz(rA = rY); memread(pc); return;
445         case 0x99: memwrite(aabsX(rY, 1), rA); return;
446         case 0x9A: rS = rX; memread(pc); return;
447         case 0x9D: memwrite(aabsX(rX, 1), rA); return;
448         case 0xA0: nz(rY = imm()); return;
449         case 0xA1: nz(rA = indX()); return;
450         case 0xA2: nz(rX = imm()); return;
451         case 0xA4: nz(rY = zp()); return;
452         case 0xA5: nz(rA = zp()); return;
453         case 0xA6: nz(rX = zp()); return;
454         case 0xA8: nz(rY = rA); memread(pc); return;
455         case 0xA9: nz(rA = imm()); return;
456         case 0xAA: nz(rX = rA); memread(pc); return;
457         case 0xAC: nz(rY = abso()); return;
458         case 0xAE: nz(rX = abso()); return;
459         case 0xAD: nz(rA = abso()); return;
460         case 0xB0: if((rP & FLAGC) != 0) branch(); else fetch8(); return;
461         case 0xB1: nz(rA = indY()); return;
462         case 0xB4: nz(rY = zpX()); return;
463         case 0xB5: nz(rA = zpX()); return;
464         case 0xB6: nz(rX = zpY()); return;
465         case 0xB8: rP &= ~FLAGV; memread(pc); return;
466         case 0xB9: nz(rA = absY()); return;
467         case 0xBA: nz(rX = rS); memread(pc); return;
468         case 0xBC: nz(rY = absX()); return;
469         case 0xBD: nz(rA = absX()); return;
470         case 0xBE: nz(rX = absY()); return;
471         case 0xC1: cmp(rA, indX()); return;
472         case 0xC5: cmp(rA, zp()); return;
473         case 0xC9: cmp(rA, imm()); return;
474         case 0xCD: cmp(rA, abso()); return;
475         case 0xD0: if((rP & FLAGZ) == 0) branch(); else fetch8(); return;
476         case 0xD1: cmp(rA, indY()); return;
477         case 0xD5: cmp(rA, zpX()); return;
478         case 0xD8: rP &= ~FLAGD; memread(pc); return;
479         case 0xD9: cmp(rA, absY()); return;
480         case 0xDD: cmp(rA, absX()); return;
481         case 0xC0: cmp(rY, imm()); return;
482         case 0xC4: cmp(rY, zp()); return;
483         case 0xC6: dec(fetch8()); return;
484         case 0xC8: nz(++rY); memread(pc); return;
485         case 0xCA: nz(--rX); memread(pc); return;
486         case 0xCC: cmp(rY, abso()); return;
487         case 0xCE: dec(fetch16()); return;
488         case 0xD6: dec(azpX(rX)); return;
489         case 0xDE: dec(aabsX(rX, 1)); return;
490         case 0xE0: cmp(rX, imm()); return;
491         case 0xE1: sbc(indX()); return;
492         case 0xE4: cmp(rX, zp()); return;
493         case 0xE5: sbc(zp()); return;
494         case 0xE6: inc(fetch8()); return;
495         case 0xE8: nz(++rX); memread(pc); return;
496         case 0xE9: sbc(imm()); return;
497         case 0xEA: memread(pc); return;
498         case 0xEC: cmp(rX, abso()); return;
499         case 0xED: sbc(abso()); return;
500         case 0xEE: inc(fetch16()); return;
501         case 0xF0: if((rP & FLAGZ) != 0) branch(); else fetch8(); return;
502         case 0xF1: sbc(indY()); return;
503         case 0xF5: sbc(zpX()); return;
504         case 0xF6: inc(azpX(rX)); return;
505         case 0xF8: rP |= FLAGD; memread(pc); return;
506         case 0xF9: sbc(absY()); return;
507         case 0xFD: sbc(absX()); return;
508         case 0xFE: inc(aabsX(rX, 1)); return;
509         default:
510                 print("undefined %#x (pc %#x)\n", op, curpc);
511                 return;
512         }
513 }