]> git.lizzy.rs Git - plan9front.git/blob - sys/src/games/snes/spc.c
43c1b76959fdc1dbbda38069b30ddc9d5c378e15
[plan9front.git] / sys / src / games / snes / spc.c
1 #include <u.h>
2 #include <libc.h>
3 #include <thread.h>
4 #include "dat.h"
5 #include "fns.h"
6
7 u8int sA, sX, sY, sP, sS;
8 u16int spc, scurpc;
9 u8int spcmem[65536];
10 u8int spctimer[4];
11 static u8int ipl[64];
12
13 enum {
14         SPCN = 1<<7,
15         SPCV = 1<<6,
16         SPCP = 1<<5,
17         SPCB = 1<<4,
18         SPCH = 1<<3,
19         SPCI = 1<<2,
20         SPCZ = 1<<1,
21         SPCC = 1<<0,
22 };
23
24 static u8int
25 spcread(u16int p)
26 {
27         u8int v;
28
29         if(p >= 0xffc0 && (spcmem[0xf1] & 0x80) != 0)
30                 return ipl[p - 0xffc0];
31         if((p & 0xfff0) == 0x00f0)
32                 switch(p){
33                 case 0xf3:
34                         return dspread(spcmem[0xf2]);
35                 case 0xf4:
36                 case 0xf5:
37                 case 0xf6:
38                 case 0xf7:
39                         return reg[0x2140 | p & 3];
40                 case 0xfa:
41                 case 0xfb:
42                 case 0xfc:
43                         return 0;
44                 case 0xfd:
45                 case 0xfe:
46                 case 0xff:
47                         v = spcmem[p];
48                         spcmem[p] = 0;
49                         return v;
50                 }
51         return spcmem[p];
52 }
53
54 static void
55 spcwrite(u16int p, u8int v)
56 {
57         if((p & 0xfff0) == 0x00f0)
58                 switch(p){
59                 case 0xf0:
60                         if(v != 0x0a)
61                                 print("SPC test register set to value %#x != 0xa\n", v);
62                         return;
63                 case 0xf1:
64                         if((v & 0x10) != 0)
65                                 reg[0x2140] = reg[0x2141] = 0;
66                         if((v & 0x20) != 0)
67                                 reg[0x2142] = reg[0x2143] = 0;
68                         if((spcmem[0xf1] & 1) == 0 && (v & 1) != 0)
69                                 spctimer[0] = spcmem[0xfd] = 0;
70                         if((spcmem[0xf1] & 2) == 0 && (v & 2) != 0)
71                                 spctimer[1] = spcmem[0xfe] = 0;
72                         if((spcmem[0xf1] & 4) == 0 && (v & 4) != 0)
73                                 spctimer[2] = spcmem[0xff] = 0;
74                         break;
75                 case 0xf3:
76                         dspwrite(spcmem[0xf2], v);
77                         return;
78                 case 0xfd:
79                 case 0xfe:
80                 case 0xff:
81                         return;
82                 }
83         spcmem[p] = v;
84 }
85
86 void
87 spctimerstep(void)
88 {
89         u8int m;
90         
91         m = spcmem[0xf1];
92         if(spctimer[3] == 7){
93                 spctimer[3] = 0;
94                 if((m & 1) != 0 && ++spctimer[0] == spcmem[0xfa]){
95                         spctimer[0] = 0;
96                         spcmem[0xfd] = (spcmem[0xfd] + 1) & 0xf;
97                 }
98                 if((m & 2) != 0 && ++spctimer[1] == spcmem[0xfb]){
99                         spctimer[1] = 0;
100                         spcmem[0xfe] = (spcmem[0xfe] + 1) & 0xf;
101                 }
102         }else
103                 spctimer[3]++;
104         if((m & 4) != 0 && ++spctimer[2] == spcmem[0xfc]){
105                 spctimer[2] = 0;
106                 spcmem[0xff] = (spcmem[0xff] + 1) & 0xf;
107         }
108 }
109
110 static u8int
111 fetch8(void)
112 {
113         return spcread(spc++);
114 }
115
116 static u16int
117 fetch16(void)
118 {
119         int a;
120         
121         a = fetch8();
122         a |= fetch8() << 8;
123         return a;
124 }
125
126 static u16int
127 mem16(u16int p)
128 {
129         int a;
130
131         a = spcread(p++);
132         a |= spcread(p) << 8;
133         return a;
134 }
135
136 static u16int
137 memd16(u16int p)
138 {
139         int a;
140         
141         a = spcread(p);
142         if((p & 0xff) == 0xff)
143                 p &= ~0xff;
144         else
145                 p++;
146         a |= spcread(p) << 8;
147         return a;
148 }
149
150 static void
151 push8(u8int v)
152 {
153         spcwrite(0x100 | sS--, v);
154 }
155
156 static void
157 push16(u16int v)
158 {
159         spcwrite(0x100 | sS--, v>>8);
160         spcwrite(0x100 | sS--, v);
161 }
162
163 static u8int
164 pop8(void)
165 {
166         return spcread(0x100 | ++sS);
167 }
168
169 static u16int
170 pop16(void)
171 {
172         u16int v;
173         
174         v = spcread(0x100 | ++sS);
175         v |= spcread(0x100 | ++sS) << 8;
176         return v;
177 }
178
179 #define imm() fetch8()
180 #define dp ((sP&SPCP)<<3)
181 #define azp() (fetch8()|dp)
182 #define azpX() ((u8int)(fetch8()+sX)|dp)
183 #define azpY() ((u8int)(fetch8()+sY)|dp)
184 #define zp() spcread(azp())
185 #define zpX() spcread(azpX())
186 #define zpY() spcread(azpY())
187 #define abs() spcread(fetch16())
188 #define absX() spcread(fetch16()+sX)
189 #define absY() spcread(fetch16()+sY)
190 #define indX() spcread(aindX())
191 #define indY() spcread(aindY())
192
193 static u16int
194 aindX(void)
195 {
196         u8int r;
197         u16int a;
198         
199         r = fetch8() + sX;
200         a = spcread(r++ | dp);
201         a |= spcread(r | dp) << 8;
202         return a;
203 }
204
205 static u16int
206 aindY(void)
207 {
208         u8int r;
209         u16int a;
210         
211         r = fetch8();
212         a = spcread(r++ | dp) + sY;
213         a += spcread(r | dp) << 8;
214         return a;
215 }
216
217 static u8int
218 nz(u8int v)
219 {
220         sP &= ~(SPCN|SPCZ);
221         sP |= v & 0x80;
222         if(v == 0)
223                 sP |= SPCZ;
224         return v;
225 }
226
227 static void
228 nz16(void)
229 {
230         sP &= ~(SPCN|SPCZ);
231         if(sA == 0 && sY == 0)
232                 sP |= SPCZ;
233         if(sY & 0x80)
234                 sP |= SPCN;
235 }
236
237 static int
238 branch(int c, int n)
239 {
240         static char s;
241         u16int npc;
242         
243         if(!c){
244                 spc++;
245                 return n;
246         }
247         s = fetch8();
248         npc = spc + s;
249         if(((npc ^ spc) & 0xff00) != 0)
250                 n++;
251         spc = npc;
252         return ++n;     
253 }
254
255 static void
256 clrb(u16int a, int b)
257 {
258         spcwrite(a, spcread(a) & ~(1<<b));
259 }
260
261 static void
262 cmp(u8int a, u8int b)
263 {
264         sP &= ~(SPCZ|SPCN|SPCC);
265         if(a >= b)
266                 sP |= SPCC;
267         if(a == b)
268                 sP |= SPCZ;
269         if((a - b) & 0x80)
270                 sP |= SPCN;
271 }
272
273 static u8int
274 adc(u8int a, u8int b)
275 {
276         u16int r;
277         u8int r8;
278         
279         r8 = r = a + b + (sP & SPCC);
280         sP &= ~(SPCC|SPCZ|SPCH|SPCV|SPCN);
281         if(r >= 0x100)
282                 sP |= SPCC;
283         sP |= r8 & SPCN;
284         if((a ^ b ^ r) & 0x10)
285                 sP |= SPCH;
286         if((~(a ^ b) & (a ^ r)) & 0x80)
287                 sP |= SPCV;
288         if(r8 == 0)
289                 sP |= SPCZ;
290         return r8;
291 }
292
293 static void
294 inc(u16int a)
295 {
296         spcwrite(a, nz(spcread(a) + 1));
297 }
298
299 static void
300 jsr(u16int a)
301 {
302         push16(spc);
303         spc = a;
304 }
305 static void
306 asl(u16int a)
307 {
308         u8int v;
309         
310         v = spcread(a);
311         sP &= ~SPCC;
312         sP |= v >> 7 & 1;
313         spcwrite(a, nz(v << 1));
314 }
315
316 static void
317 lsr(u16int a)
318 {
319         u8int v;
320         
321         v = spcread(a);
322         sP &= ~SPCC;
323         sP |= v & 1;
324         spcwrite(a, nz(v >> 1));
325 }
326
327 static void
328 rol(u16int a)
329 {
330         u8int v, c;
331         
332         v = spcread(a);
333         c = sP & SPCC;
334         sP &= ~SPCC;
335         sP |= v >> 7 & 1;
336         v = v<<1 | c;
337         spcwrite(a, nz(v));
338 }
339
340 static void
341 inc16(u16int a, int c)
342 {
343         u16int v;
344
345         v = memd16(a) + c;
346         sP &= ~(SPCN|SPCZ);
347         if(v == 0)
348                 sP |= SPCZ;
349         if((v & 0x8000) != 0)
350                 sP |= SPCN;
351         spcwrite(a, v);
352         spcwrite(a+1, v>>8);
353 }
354
355 static void
356 ror(u16int a)
357 {
358         u8int v, c;
359         
360         v = spcread(a);
361         c = sP & SPCC;
362         sP &= ~SPCC;
363         sP |= v & 1;
364         v = v>>1 | c<<7;
365         spcwrite(a, nz(v));
366 }
367
368 static u8int
369 sbc(u8int a, u8int b)
370 {
371         return adc(a, ~b);
372 }
373
374 static void
375 setb(u16int a, int b)
376 {
377         spcwrite(a, spcread(a) | (1<<b));
378 }
379
380 static void
381 setnbit(u16int a, int c)
382 {
383         u8int v, b;
384         
385         b = a >> 13;
386         v = spcread(a & 0x1fff) & ~(1<<b);
387         if(c)
388                 v |= (1<<b);
389         spcwrite(a & 0x1fff, v);
390 }
391
392 static void
393 tset(u16int a, int set)
394 {
395         u8int v;
396         
397         v = spcread(a);
398         nz(sA - v);
399         if(set)
400                 v |= sA;
401         else
402                 v &= ~sA;
403         spcwrite(a, v);
404 }
405
406 static void
407 div(void)
408 {
409         u32int v, x;
410         int i;
411         
412         sP &= ~(SPCH|SPCV);
413         if((sX & 0xf) <= (sY & 0xf))
414                 sP |= SPCH;
415         v = sA | sY << 8;
416         x = sX << 9;
417         for(i = 0; i < 9; i++){
418                 v = (v << 1 | v >> 16) & 0x1ffff;
419                 if(v >= x)
420                         v ^= 1;
421                 if((v & 1) != 0)
422                         v = (v - x) & 0x1ffff;
423         }
424         nz(sA = v);
425         sY = v >> 9;
426         if((v & 0x100) != 0)
427                 sP |= SPCV;
428 }
429
430 void
431 spcreset(void)
432 {
433         spcmem[0xf0] = 0x0a;
434         spcmem[0xf1] = 0xb0;
435         spc = spcread(0xfffe) | spcread(0xffff) << 8;
436 }
437
438 int
439 spcstep(void)
440 {
441         static int ctr;
442         u8int op, a;
443         u16int b, c;
444
445         scurpc = spc;
446         op = fetch8();
447         if(trace)
448                 print("SPC %.4x %.2x A=%.2x X=%.2x Y=%.2x P=%.2x S=%.2x\n", spc-1, op, sA, sX, sY, sP, sS);
449         switch(op){
450         case 0x00: return 2;
451         case 0x01: jsr(mem16(0xffde)); return 8;
452         case 0x02: setb(azp(), 0); return 4;
453         case 0x03: return branch((zp() & 0x01) != 0, 5);
454         case 0x04: nz(sA |= zp()); return 3;
455         case 0x05: nz(sA |= abs()); return 4;
456         case 0x06: nz(sA |= spcread(sX|dp)); return 3;
457         case 0x07: nz(sA |= indX()); return 6;
458         case 0x08: nz(sA |= imm()); return 2;
459         case 0x09: b = zp(); c = azp(); spcwrite(c, nz(b | spcread(c))); return 6;
460         case 0x0A: b = fetch16(); sP |= (spcread(b & 0x1fff) >> (b >> 13)) & 1;  return 4;
461         case 0x0B: asl(azp()); return 5;
462         case 0x0C: asl(fetch16()); return 5;
463         case 0x0D: push8(sP); return 4;
464         case 0x0E: tset(fetch16(), 1); return 6;
465         case 0x10: return branch((sP & SPCN) == 0, 2);
466         case 0x11: jsr(mem16(0xffdc)); return 8;
467         case 0x12: clrb(azp(), 0); return 4;
468         case 0x13: return branch((zp() & 0x01) == 0, 5);
469         case 0x14: nz(sA |= zpX()); return 4;
470         case 0x15: nz(sA |= absX()); return 5;
471         case 0x16: nz(sA |= absY()); return 5;
472         case 0x17: nz(sA |= indY()); return 6;
473         case 0x18: a = imm(); b = azp(); spcwrite(b, nz(spcread(b) | a)); return 5;
474         case 0x19: spcwrite(sX|dp, nz(spcread(sX|dp) | spcread(sY|dp))); return 5;
475         case 0x1A: inc16(azp(), -1); return 6;
476         case 0x1B: asl(azpX()); return 5;
477         case 0x1C: sP &= ~SPCC; sP |= sA >> 7; nz(sA <<= 1); return 2;
478         case 0x1D: nz(--sX); return 2;
479         case 0x1E: cmp(sX, abs()); return 4;
480         case 0x1F: spc = mem16(fetch16() + sX); return 6;
481         case 0x20: sP &= ~SPCP; return 2;
482         case 0x21: jsr(mem16(0xffda)); return 8;
483         case 0x22: setb(azp(), 1); return 4;
484         case 0x23: return branch((zp() & 0x02) != 0, 5);
485         case 0x24: nz(sA &= zp()); return 3;
486         case 0x25: nz(sA &= abs()); return 4;
487         case 0x26: nz(sA &= spcread(sX|dp)); return 3;
488         case 0x27: nz(sA &= indX()); return 6;
489         case 0x28: nz(sA &= imm()); return 2;
490         case 0x29: b = zp(); c = azp(); spcwrite(c, nz(b & spcread(c))); return 6;
491         case 0x2A: b = fetch16(); sP |= (~spcread(b & 0x1fff) >> (b >> 13)) & 1;  return 4;
492         case 0x2B: rol(azp()); return 4;
493         case 0x2C: rol(fetch16()); return 5;
494         case 0x2D: push8(sA); return 4;
495         case 0x2E: return branch(sA != zp(), 5);
496         case 0x2F: return branch(1, 2);
497         case 0x30: return branch((sP & SPCN) != 0, 2);
498         case 0x31: jsr(mem16(0xffd8)); return 8;
499         case 0x32: clrb(azp(), 1); return 4;
500         case 0x33: return branch((zp() & 0x02) == 0, 5);
501         case 0x34: nz(sA &= zpX()); return 4;
502         case 0x35: nz(sA &= absX()); return 5;
503         case 0x36: nz(sA &= absY()); return 5;
504         case 0x37: nz(sA &= indY()); return 6;
505         case 0x38: a = imm(); b = azp(); spcwrite(b, nz(spcread(b) & a)); return 5;
506         case 0x39: spcwrite(sX|dp, nz(spcread(sX|dp) & spcread(sY|dp))); return 5;
507         case 0x3A: inc16(azp(), 1); return 6;
508         case 0x3B: rol(azpX()); return 5;
509         case 0x3C:
510                 a = sP & SPCC;
511                 sP &= ~SPCC;
512                 sP |= sA >> 7 & 1;
513                 sA = sA << 1 | a;
514                 nz(sA);
515                 return 2;
516         case 0x3D: nz(++sX); return 2;
517         case 0x3E: cmp(sX, zp()); return 3;
518         case 0x3F: jsr(fetch16()); return 8;
519         case 0x40: sP |= SPCP; return 2;
520         case 0x41: jsr(mem16(0xffd6)); return 8;
521         case 0x42: setb(azp(), 2); return 4;
522         case 0x43: return branch((zp() & 0x04) != 0, 5);
523         case 0x44: nz(sA ^= zp()); return 3;
524         case 0x45: nz(sA ^= abs()); return 4;
525         case 0x46: nz(sA ^= spcread(sX|dp)); return 3;
526         case 0x47: nz(sA ^= indX()); return 6;
527         case 0x48: nz(sA ^= imm()); return 2;
528         case 0x49: b = zp(); c = azp(); spcwrite(c, nz(b ^ spcread(c))); return 6;
529         case 0x4A: b = fetch16(); sP &= 0xfe | (spcread(b & 0x1fff) >> (b >> 13)) & 1;  return 4;
530         case 0x4B: lsr(azp()); return 4;
531         case 0x4C: lsr(fetch16()); return 5;
532         case 0x4D: push8(sX); return 4;
533         case 0x4E: tset(fetch16(), 0); return 5;
534         case 0x4F: jsr(0xff00 | fetch8()); return 6;
535         case 0x50: return branch((sP & SPCV) == 0, 2);
536         case 0x51: jsr(mem16(0xffd4)); return 8;
537         case 0x52: clrb(azp(), 2); return 4;
538         case 0x53: return branch((zp() & 0x04) == 0, 5);
539         case 0x54: nz(sA ^= zpX()); return 4;
540         case 0x55: nz(sA ^= absX()); return 5;
541         case 0x56: nz(sA ^= absY()); return 5;
542         case 0x57: nz(sA ^= indY()); return 6;
543         case 0x58: a = imm(); b = azp(); spcwrite(b, nz(spcread(b) ^ a)); return 5;
544         case 0x59: spcwrite(sX|dp, nz(spcread(sX|dp) ^ spcread(sY|dp))); return 5;
545         case 0x5A: 
546                 b = sA | sY << 8;
547                 c = memd16(azp());
548                 sP &= ~(SPCN|SPCZ|SPCC);
549                 if(b >= c)
550                         sP |= SPCC;
551                 if(b == c)
552                         sP |= SPCZ;
553                 if(((b - c) & 0x8000) != 0)
554                         sP |= SPCN;
555                 return 4;
556         case 0x5B: lsr(azpX()); return 4;
557         case 0x5C: sP &= ~SPCC; sP |= sA & 1; nz(sA >>= 1); return 2;
558         case 0x5D: nz(sX = sA); return 2;
559         case 0x5E: cmp(sY, abs()); return 4;
560         case 0x5F: spc = fetch16(); return 3;
561         case 0x60: sP &= ~SPCC; return 2;
562         case 0x61: jsr(mem16(0xffd2)); return 8;
563         case 0x62: setb(azp(), 3); return 4;
564         case 0x63: return branch((zp() & 0x08) != 0, 5);
565         case 0x64: cmp(sA, zp()); return 3;
566         case 0x65: cmp(sA, abs()); return 4;
567         case 0x66: cmp(sA, spcread(sX|dp)); return 3;
568         case 0x67: cmp(sA, indX()); return 6;
569         case 0x68: cmp(sA, imm()); return 2;
570         case 0x69: a = zp(); cmp(zp(), a); return 6;
571         case 0x6A: b = fetch16(); sP &= ~((spcread(b & 0x1fff) >> (b >> 13)) & 1);  return 4;
572         case 0x6B: ror(azp()); return 4;
573         case 0x6C: ror(fetch16()); return 5;
574         case 0x6D: push8(sY); return 4;
575         case 0x6E: b = azp(); a = spcread(b)-1; spcwrite(b, a); return branch(a != 0, 5);
576         case 0x6F: spc = pop16(); return 5;
577         case 0x70: return branch((sP & SPCV) != 0, 2);
578         case 0x72: clrb(azp(), 3); return 4;
579         case 0x71: jsr(mem16(0xffd0)); return 8;
580         case 0x73: return branch((zp() & 0x08) == 0, 5);
581         case 0x74: cmp(sA, zpX()); return 4;
582         case 0x75: cmp(sA, absX()); return 5;
583         case 0x76: cmp(sA, absY()); return 5;
584         case 0x77: cmp(sA, indY()); return 6;
585         case 0x78: a = imm(); cmp(zp(), a); return 5;
586         case 0x79: cmp(spcread(sX|dp), spcread(sY|dp)); return 5;
587         case 0x7A:
588                 b = memd16(azp());
589                 sP &= ~SPCC;
590                 sA = adc(sA, b);
591                 sY = adc(sY, b >> 8);
592                 if(sA != 0)
593                         sP &= ~SPCZ;
594                 return 5;
595         case 0x7B: ror(azpX()); return 5;
596         case 0x7C:
597                 a = sP & SPCC;
598                 sP &= ~SPCC;
599                 sP |= sA & 1;
600                 sA = sA >> 1 | a << 7;
601                 nz(sA);
602                 return 2;
603         case 0x7D: nz(sA = sX); return 2;
604         case 0x7E: cmp(sY, zp()); return 3;
605         case 0x7F: sP = pop8(); spc = pop16(); return 6;
606         case 0x80: sP |= SPCC; return 2;
607         case 0x81: jsr(mem16(0xffce)); return 8;
608         case 0x82: setb(azp(), 4); return 4;
609         case 0x83: return branch((zp() & 0x10) != 0, 5);
610         case 0x84: sA = adc(sA, zp()); return 3;
611         case 0x85: sA = adc(sA, abs()); return 4;
612         case 0x86: sA = adc(sA, spcread(sX|dp)); return 3;
613         case 0x87: sA = adc(sA, indX()); return 6;
614         case 0x88: sA = adc(sA, imm()); return 2;
615         case 0x89: b = zp(); c = azp(); spcwrite(c, adc(b, spcread(c))); return 6;
616         case 0x8A: b = fetch16(); sP ^= (spcread(b & 0x1fff) >> (b >> 13)) & 1;  return 4;
617         case 0x8B: b = azp(); spcwrite(b, nz(spcread(b)-1)); return 4;
618         case 0x8C: b = fetch16(); spcwrite(b, nz(spcread(b)-1)); return 4;
619         case 0x8D: nz(sY = imm()); return 2;
620         case 0x8E: sP = pop8(); return 2;
621         case 0x8F: a = fetch8(); spcwrite(azp(), a); return 5;
622         case 0x90: return branch((sP & SPCC) == 0, 2);
623         case 0x91: jsr(mem16(0xffcc)); return 8;
624         case 0x92: clrb(azp(), 4); return 4;
625         case 0x93: return branch((zp() & 0x10) == 0, 5);
626         case 0x94: sA = adc(sA, zpX()); return 4;
627         case 0x95: sA = adc(sA, absX()); return 5;
628         case 0x96: sA = adc(sA, absY()); return 5;
629         case 0x97: sA = adc(sA, indY()); return 6;
630         case 0x98: a = imm(); b = azp(); spcwrite(b, adc(spcread(b), a)); return 5;
631         case 0x99: spcwrite(sX|dp, adc(spcread(sX|dp), spcread(sY|dp))); return 5;
632         case 0x9A:
633                 b = memd16(azp());
634                 sP |= SPCC;
635                 sA = sbc(sA, b);
636                 sY = sbc(sY, b >> 8);
637                 if(sA != 0)
638                         sP &= ~SPCZ;
639                 return 5;
640         case 0x9B: b = azpX(); spcwrite(b, nz(spcread(b)-1)); return 4;
641         case 0x9C: nz(--sA); return 2;
642         case 0x9D: nz(sX = sS); return 2;
643         case 0x9E: div(); return 12;
644         case 0x9F: nz(sA = sA >> 4 | sA << 4); return 5;
645         case 0xA0: sP |= SPCI; return 2;
646         case 0xA1: jsr(mem16(0xffca)); return 8;
647         case 0xA2: setb(azp(), 5); return 4;
648         case 0xA3: return branch((zp() & 0x20) != 0, 5);
649         case 0xA4: sA = sbc(sA, zp()); return 3;
650         case 0xA5: sA = sbc(sA, abs()); return 4;
651         case 0xA6: sA = sbc(sA, spcread(sX|dp)); return 3;
652         case 0xA7: sA = sbc(sA, indX()); return 6;
653         case 0xA8: sA = sbc(sA, imm()); return 2;
654         case 0xA9: b = zp(); c = azp(); spcwrite(c, sbc(spcread(c), b)); return 6;
655         case 0xAA: b = fetch16(); sP &= ~1; sP |= (spcread(b & 0x1fff) >> (b >> 13)) & 1;  return 4;
656         case 0xAB: inc(azp()); return 4;
657         case 0xAC: inc(fetch16()); return 5;
658         case 0xAD: cmp(sY, imm()); return 2;
659         case 0xAE: sA = pop8(); return 2;
660         case 0xAF: spcwrite(sX++|dp, sA); return 4;
661         case 0xB0: return branch((sP & SPCC) != 0, 2);
662         case 0xB1: jsr(mem16(0xffc8)); return 8;
663         case 0xB2: clrb(azp(), 5); return 4;
664         case 0xB3: return branch((zp() & 0x20) == 0, 5);
665         case 0xB4: sA = sbc(sA, zpX()); return 4;
666         case 0xB5: sA = sbc(sA, absX()); return 5;
667         case 0xB6: sA = sbc(sA, absY()); return 5;
668         case 0xB7: sA = sbc(sA, indY()); return 6;
669         case 0xB8: a = imm(); b = azp(); spcwrite(b, sbc(spcread(b), a)); return 5;
670         case 0xB9: spcwrite(sX|dp, sbc(spcread(sX|dp), spcread(sY|dp))); return 5;
671         case 0xBA: a = fetch8(); sA = spcread(a++|dp); sY = spcread(a|dp); nz16(); return 5;
672         case 0xBB: inc(azpX()); return 4;
673         case 0xBC: nz(++sA); return 2;
674         case 0xBD: sS = sX; return 2;
675         case 0xBF: nz(sA = spcread(sX++|dp)); return 3;
676         case 0xC0: sP &= ~SPCI; return 2;
677         case 0xC1: jsr(mem16(0xffc6)); return 8;
678         case 0xC2: setb(azp(), 6); return 4;
679         case 0xC3: return branch((zp() & 0x40) != 0, 5);
680         case 0xC4: spcwrite(azp(), sA); return 4;
681         case 0xC5: spcwrite(fetch16(), sA); return 5;
682         case 0xC6: spcwrite(sX|dp, sA); return 4;
683         case 0xC7: spcwrite(aindX(), sA); return 7;
684         case 0xC8: cmp(sX, imm()); return 2;
685         case 0xC9: spcwrite(fetch16(), sX); return 5;
686         case 0xCA: b = fetch16(); setnbit(b, sP & SPCC); return 6;
687         case 0xCB: spcwrite(azp(), sY); return 4;
688         case 0xCC: spcwrite(fetch16(), sY); return 5;
689         case 0xCD: nz(sX = imm()); return 2;
690         case 0xCE: sX = pop8(); return 2;
691         case 0xCF: b = sY * sA; nz(sY = b >> 8); sA = b; return 9;
692         case 0xD0: return branch((sP & SPCZ) == 0, 2);
693         case 0xD1: jsr(mem16(0xffc4)); return 8;
694         case 0xD2: clrb(azp(), 6); return 4;
695         case 0xD3: return branch((zp() & 0x40) == 0, 5);
696         case 0xD4: spcwrite(azpX(), sA); return 4;
697         case 0xD5: spcwrite(fetch16() + sX, sA); return 6;
698         case 0xD6: spcwrite(fetch16() + sY, sA); return 6;
699         case 0xD7: spcwrite(aindY(), sA); return 7;
700         case 0xD8: spcwrite(azp(), sX); return 4;
701         case 0xD9: spcwrite(azpY(), sX); return 5;
702         case 0xDA: a = fetch8(); spcwrite(a++|dp, sA); spcwrite(a|dp, sY); return 5;
703         case 0xDB: spcwrite(azpX(), sY); return 5;
704         case 0xDC: nz(--sY); return 2;
705         case 0xDD: nz(sA = sY); return 2;
706         case 0xDE: return branch(sA != zpX(), 6);
707         case 0xE0: sP &= ~(SPCV|SPCH); return 2;
708         case 0xE1: jsr(mem16(0xffc2)); return 8;
709         case 0xE2: setb(azp(), 7); return 4;
710         case 0xE3: return branch((zp() & 0x80) != 0, 5);
711         case 0xE4: nz(sA = zp()); return 3;
712         case 0xE5: nz(sA = abs()); return 4;
713         case 0xE6: nz(sA = spcread(sX|dp)); return 3;
714         case 0xE7: nz(sA = indX()); return 6;
715         case 0xE8: nz(sA = imm()); return 2;
716         case 0xE9: nz(sX = abs()); return 4;
717         case 0xEA: b = fetch16(); spcwrite(b & 0x1fff, spcread(b & 0x1fff) ^ (1<<(b>>13))); return 6;
718         case 0xEB: nz(sY = zp()); return 3;
719         case 0xEC: nz(sY = abs()); return 4;
720         case 0xED: sP ^= SPCC; return 3;
721         case 0xEE: sY = pop8(); return 4;
722         case 0xF0: return branch((sP & SPCZ) != 0, 2);
723         case 0xF1: jsr(mem16(0xffc0)); return 8;
724         case 0xF2: clrb(azp(), 7); return 4;
725         case 0xF3: return branch((zp() & 0x80) == 0, 5);
726         case 0xF4: nz(sA = zpX()); return 4;
727         case 0xF5: nz(sA = absX()); return 5;
728         case 0xF6: nz(sA = absY()); return 5;
729         case 0xF7: nz(sA = indY()); return 6;
730         case 0xF8: nz(sX = zp()); return 3;
731         case 0xF9: nz(sX = zpY()); return 4;
732         case 0xFA: a = zp(); spcwrite(azp(), a); return 5;
733         case 0xFB: nz(sY = zpX()); return 4;
734         case 0xFC: nz(++sY); return 2;
735         case 0xFD: nz(sY = sA); return 2;
736         case 0xFE: return branch(--sY, 4);
737         default:
738                 print("undefined spc op %.2x at %.4x\n", op, spc-1);
739                 return 2;
740         }
741 }
742
743 static u8int ipl[64] = {
744         0xcd, 0xef, 0xbd, 0xe8, 0x00, 0xc6, 0x1d, 0xd0, 0xfc, 0x8f, 0xaa, 0xf4, 0x8f, 0xbb, 0xf5, 0x78,
745         0xcc, 0xf4, 0xd0, 0xfb, 0x2f, 0x19, 0xeb, 0xf4, 0xd0, 0xfc, 0x7e, 0xf4, 0xd0, 0x0b, 0xe4, 0xf5,
746         0xcb, 0xf4, 0xd7, 0x00, 0xfc, 0xd0, 0xf3, 0xab, 0x01, 0x10, 0xef, 0x7e, 0xf4, 0x10, 0xeb, 0xba,
747         0xf6, 0xda, 0x00, 0xba, 0xf4, 0xc4, 0xf4, 0xdd, 0x5d, 0xd0, 0xdb, 0x1f, 0x00, 0x00, 0xc0, 0xff,           
748 };