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