]> git.lizzy.rs Git - plan9front.git/blob - sys/src/games/snes/spc.c
merge
[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 0xf4:
34                 case 0xf5:
35                 case 0xf6:
36                 case 0xf7:
37                         return reg[0x2140 | p & 3];
38                 case 0xfa:
39                 case 0xfb:
40                 case 0xfc:
41                         return 0;
42                 case 0xfd:
43                 case 0xfe:
44                 case 0xff:
45                         v = spcmem[p];
46                         spcmem[p] = 0;
47                         return v;
48                 }
49         return spcmem[p];
50 }
51
52 static void
53 spcwrite(u16int p, u8int v)
54 {
55         if((p & 0xfff0) == 0x00f0)
56                 switch(p){
57                 case 0xf0:
58                         if(v != 0x0a)
59                                 print("SPC test register set to value %#x != 0xa\n", v);
60                         return;
61                 case 0xf1:
62                         if((v & 0x10) != 0)
63                                 reg[0x2140] = reg[0x2141] = 0;
64                         if((v & 0x20) != 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;
72                         break;
73                 case 0xfd:
74                 case 0xfe:
75                 case 0xff:
76                         return;
77                 }
78         spcmem[p] = v;
79 }
80
81 void
82 spctimerstep(void)
83 {
84         u8int m;
85         
86         m = spcmem[0xf1];
87         if(spctimer[3] == 7){
88                 spctimer[3] = 0;
89                 if((m & 1) != 0 && ++spctimer[0] == spcmem[0xfa]){
90                         spctimer[0] = 0;
91                         spcmem[0xfd] = (spcmem[0xfd] + 1) & 0xf;
92                 }
93                 if((m & 2) != 0 && ++spctimer[1] == spcmem[0xfb]){
94                         spctimer[1] = 0;
95                         spcmem[0xfe] = (spcmem[0xfe] + 1) & 0xf;
96                 }
97         }else
98                 spctimer[3]++;
99         if((m & 4) != 0 && ++spctimer[2] == spcmem[0xfc]){
100                 spctimer[2] = 0;
101                 spcmem[0xff] = (spcmem[0xff] + 1) & 0xf;
102         }
103 }
104
105 static u8int
106 fetch8(void)
107 {
108         return spcread(spc++);
109 }
110
111 static u16int
112 fetch16(void)
113 {
114         int a;
115         
116         a = fetch8();
117         a |= fetch8() << 8;
118         return a;
119 }
120
121 static u16int
122 mem16(u16int p)
123 {
124         int a;
125
126         a = spcread(p++);
127         a |= spcread(p) << 8;
128         return a;
129 }
130
131 static u16int
132 memd16(u16int p)
133 {
134         int a;
135         
136         a = spcread(p);
137         if((p & 0xff) == 0xff)
138                 p &= ~0xff;
139         else
140                 p++;
141         a |= spcread(p) << 8;
142         return a;
143 }
144
145 static void
146 push8(u8int v)
147 {
148         spcwrite(0x100 | sS--, v);
149 }
150
151 static void
152 push16(u16int v)
153 {
154         spcwrite(0x100 | sS--, v>>8);
155         spcwrite(0x100 | sS--, v);
156 }
157
158 static u8int
159 pop8(void)
160 {
161         return spcread(0x100 | ++sS);
162 }
163
164 static u16int
165 pop16(void)
166 {
167         u16int v;
168         
169         v = spcread(0x100 | ++sS);
170         v |= spcread(0x100 | ++sS) << 8;
171         return v;
172 }
173
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())
187
188 static u16int
189 aindX(void)
190 {
191         u8int r;
192         u16int a;
193         
194         r = fetch8() + sX;
195         a = spcread(r++ | dp);
196         a |= spcread(r | dp) << 8;
197         return a;
198 }
199
200 static u16int
201 aindY(void)
202 {
203         u8int r;
204         u16int a;
205         
206         r = fetch8();
207         a = spcread(r++ | dp) + sY;
208         a += spcread(r | dp) << 8;
209         return a;
210 }
211
212 static u8int
213 nz(u8int v)
214 {
215         sP &= ~(SPCN|SPCZ);
216         sP |= v & 0x80;
217         if(v == 0)
218                 sP |= SPCZ;
219         return v;
220 }
221
222 static void
223 nz16(void)
224 {
225         sP &= ~(SPCN|SPCZ);
226         if(sA == 0 && sY == 0)
227                 sP |= SPCZ;
228         if(sY & 0x80)
229                 sP |= SPCN;
230 }
231
232 static int
233 branch(int c, int n)
234 {
235         static char s;
236         u16int npc;
237         
238         if(!c){
239                 spc++;
240                 return n;
241         }
242         s = fetch8();
243         npc = spc + s;
244         if(((npc ^ spc) & 0xff00) != 0)
245                 n++;
246         spc = npc;
247         return ++n;     
248 }
249
250 static void
251 clrb(u16int a, int b)
252 {
253         spcwrite(a, spcread(a) & ~(1<<b));
254 }
255
256 static void
257 cmp(u8int a, u8int b)
258 {
259         sP &= ~(SPCZ|SPCN|SPCC);
260         if(a >= b)
261                 sP |= SPCC;
262         if(a == b)
263                 sP |= SPCZ;
264         if((a - b) & 0x80)
265                 sP |= SPCN;
266 }
267
268 static u8int
269 adc(u8int a, u8int b)
270 {
271         u16int r;
272         u8int r8;
273         
274         r8 = r = a + b + (sP & SPCC);
275         sP &= ~(SPCC|SPCZ|SPCH|SPCV|SPCN);
276         if(r >= 0x100)
277                 sP |= SPCC;
278         sP |= r8 & SPCN;
279         if((a ^ b ^ r) & 0x10)
280                 sP |= SPCH;
281         if((~(a ^ b) & (a ^ r)) & 0x80)
282                 sP |= SPCV;
283         if(r8 == 0)
284                 sP |= SPCZ;
285         return r8;
286 }
287
288 static void
289 inc(u16int a)
290 {
291         spcwrite(a, nz(spcread(a) + 1));
292 }
293
294 static void
295 jsr(u16int a)
296 {
297         push16(spc);
298         spc = a;
299 }
300 static void
301 asl(u16int a)
302 {
303         u8int v;
304         
305         v = spcread(a);
306         sP &= ~SPCC;
307         sP |= v >> 7 & 1;
308         spcwrite(a, nz(v << 1));
309 }
310
311 static void
312 lsr(u16int a)
313 {
314         u8int v;
315         
316         v = spcread(a);
317         sP &= ~SPCC;
318         sP |= v & 1;
319         spcwrite(a, nz(v >> 1));
320 }
321
322 static void
323 rol(u16int a)
324 {
325         u8int v, c;
326         
327         v = spcread(a);
328         c = sP & SPCC;
329         sP &= ~SPCC;
330         sP |= v >> 7 & 1;
331         v = v<<1 | c;
332         spcwrite(a, nz(v));
333 }
334
335 static void
336 inc16(u16int a, int c)
337 {
338         u16int v;
339
340         v = memd16(a) + c;
341         sP &= ~(SPCN|SPCZ);
342         if(v == 0)
343                 sP |= SPCZ;
344         if((v & 0x8000) != 0)
345                 sP |= SPCN;
346         spcwrite(a, v);
347         spcwrite(a+1, v>>8);
348 }
349
350 static void
351 ror(u16int a)
352 {
353         u8int v, c;
354         
355         v = spcread(a);
356         c = sP & SPCC;
357         sP &= ~SPCC;
358         sP |= v & 1;
359         v = v>>1 | c<<7;
360         spcwrite(a, nz(v));
361 }
362
363 static u8int
364 sbc(u8int a, u8int b)
365 {
366         return adc(a, ~b);
367 }
368
369 static void
370 setb(u16int a, int b)
371 {
372         spcwrite(a, spcread(a) | (1<<b));
373 }
374
375 static void
376 setnbit(u16int a, int c)
377 {
378         u8int v, b;
379         
380         b = a >> 13;
381         v = spcread(a & 0x1fff) & ~(1<<b);
382         if(c)
383                 v |= (1<<b);
384         spcwrite(a & 0x1fff, v);
385 }
386
387 static void
388 tset(u16int a, int set)
389 {
390         u8int v;
391         
392         v = spcread(a);
393         nz(sA - v);
394         if(set)
395                 v |= sA;
396         else
397                 v &= ~sA;
398         spcwrite(a, v);
399 }
400
401 static void
402 div(void)
403 {
404         u32int v, x;
405         int i;
406         
407         sP &= ~(SPCH|SPCV);
408         if((sX & 0xf) <= (sY & 0xf))
409                 sP |= SPCH;
410         v = sA | sY << 8;
411         x = sX << 9;
412         for(i = 0; i < 9; i++){
413                 v = (v << 1 | v >> 16) & 0x1ffff;
414                 if(v >= x)
415                         v ^= 1;
416                 if((v & 1) != 0)
417                         v = (v - x) & 0x1ffff;
418         }
419         nz(sA = v);
420         sY = v >> 9;
421         if((v & 0x100) != 0)
422                 sP |= SPCV;
423 }
424
425 void
426 spcreset(void)
427 {
428         spcmem[0xf0] = 0x0a;
429         spcmem[0xf1] = 0xb0;
430         spc = spcread(0xfffe) | spcread(0xffff) << 8;
431 }
432
433 int
434 spcstep(void)
435 {
436         static int ctr;
437         u8int op, a;
438         u16int b, c;
439
440         scurpc = spc;
441         op = fetch8();
442         if(trace)
443                 print("SPC %.4x %.2x A=%.2x X=%.2x Y=%.2x P=%.2x S=%.2x\n", spc-1, op, sA, sX, sY, sP, sS);
444         switch(op){
445         case 0x00: return 2;
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;
504         case 0x3C:
505                 a = sP & SPCC;
506                 sP &= ~SPCC;
507                 sP |= sA >> 7 & 1;
508                 sA = sA << 1 | a;
509                 nz(sA);
510                 return 2;
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;
540         case 0x5A: 
541                 b = sA | sY << 8;
542                 c = memd16(azp());
543                 sP &= ~(SPCN|SPCZ|SPCC);
544                 if(b >= c)
545                         sP |= SPCC;
546                 if(b == c)
547                         sP |= SPCZ;
548                 if(((b - c) & 0x8000) != 0)
549                         sP |= SPCN;
550                 return 4;
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;
582         case 0x7A:
583                 b = memd16(azp());
584                 sA = adc(sA, b);
585                 sY = adc(sY, b >> 8);
586                 if(sA != 0)
587                         sP &= ~SPCZ;
588                 return 5;
589         case 0x7B: ror(azpX()); return 5;
590         case 0x7C:
591                 a = sP & SPCC;
592                 sP &= ~SPCC;
593                 sP |= sA & 1;
594                 sA = sA >> 1 | a << 7;
595                 nz(sA);
596                 return 2;
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;
626         case 0x9A:
627                 b = memd16(azp());
628                 sA = sbc(sA, b);
629                 sY = sbc(sY, b >> 8);
630                 if(sA != 0)
631                         sP &= ~SPCZ;
632                 return 5;
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);
730         default:
731                 print("undefined spc op %.2x at %.4x\n", op, spc-1);
732                 return 2;
733         }
734 }
735
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,           
741 };