ref: 57f22f910c897fe3f07b88b1b7f1e62830115262
dir: /sys/src/games/v8e/cpu.c/
#include <u.h> #include <libc.h> #include "dat.h" #include "fns.h" u32int r[16]; u32int curpc; u32int ps; int trace; enum { ADD, SUB, MUL, DIV, CMP, TST, BIC, BIS, XOR, BIT, }; #define fetch8() memread8(r[15]++) static u16int fetch16(void) { u16int v; v = memread16(r[15]); r[15] += 2; return v; } static u32int fetch32(void) { u32int v; v = memread32(r[15]); r[15] += 4; return v; } static u32int sxt(u32int v, int s) { switch(s){ case 0: return (s8int) v; case 1: return (s16int) v; default: return v; } } static void nz(u32int v, int s) { int i; i = sxt(v, s); ps &= ~(FLAGN|FLAGZ); if(i == 0) ps |= FLAGZ; if(i < 0) ps |= FLAGN; } static void nz64(u64int v, int s) { if(s < 3) nz(v, s); else{ if(v == 0) ps |= FLAGZ; else if((s64int)v < 0) ps |= FLAGN; } } static void nzv(u32int v, int s) { nz(v, s); ps &= ~FLAGV; } u32int addrof(vlong v) { if(v < 0) sysfatal("addr of register or literal (pc=%.8ux)", curpc); return v; } vlong amode(int s) { u8int c; u32int v; s &= 0xf; c = fetch8(); switch(c >> 4){ case 0: case 1: case 2: case 3: return ~(vlong)(64 | c & 63); case 4: v = addrof(amode(s)); v += r[c & 15] << s; return v; case 5: return ~(vlong)(c & 15); case 6: return r[c & 15]; case 7: return r[c & 15] -= 1<<s; case 8: v = r[c & 15]; r[c & 15] += 1<<s; return v; case 9: v = r[c & 15]; r[c & 15] += 4; return memread32(v); case 10: v = fetch8(); return (u32int)(r[c & 15] + (s8int) v); case 11: v = fetch8(); return memread32(r[c & 15] + (s8int) v); case 12: v = fetch16(); return (u32int)(r[c & 15] + (s16int) v); case 13: v = fetch16(); return memread32(r[c & 15] + (s16int) v); case 14: v = fetch32(); return (u32int)(r[c & 15] + v); case 15: v = fetch32(); return memread32(r[c & 15] + v); default: sysfatal("unimplemented addressing mode %.2x", c); return -1; } } u32int readm(vlong a, int s) { vlong v; if(a < 0){ if(a <= ~64LL){ if(s >= 0x10) return (~a & 63) << 4 | 0x4000; return ~a & 63; } assert(a >= ~15LL); v = r[~a]; switch(s & 0xf){ case 0: return (uchar) v; case 1: return (ushort) v; case 2: return v; } } switch(s & 0xf){ case 0: return memread8(a); case 1: return memread16(a); case 2: return memread32(a); default: sysfatal("readm: unimplemented size %d (a=%.llx, pc=%.8x)", s, a, curpc); return -1; } } static vlong highw(vlong v) { if(v >= 0) return (u32int)(v + 4); if(v <= ~64LL) return ~64LL; return v - 1 | ~15LL; } u64int readm64(vlong a, int s) { u64int v; if((s & 0xf) == 3){ v = readm(a, s - 1); if(a > ~64LL) v |= (u64int)readm(highw(a), 2) << 32; return v; } return readm(a, s); } void writem(vlong a, u32int v, int s) { int n; assert(a >= ~15LL); s &= 0xf; if(a < 0){ switch(s){ case 0: r[~a] = r[~a] & ~0xff | v & 0xff; break; case 1: r[~a] = r[~a] & ~0xffff | v & 0xffff; break; case 2: r[~a] = v; break; default: sysfatal("writem: unimplemented size %d", s); } return; } switch(s){ case 0: n = (a & 3) << 3; memwrite(a & -4, v << n, 0xff << n); break; case 1: n = (a & 3) << 3; memwrite(a & -4, v << n, 0xffff << n); if(n == 24) memwrite(-(-a & -4), v >> 8, 0xff); break; case 2: n = (a & 3) << 3; memwrite(a & -4, v << n, -1 << n); if(n != 0) memwrite(-(-a & -4), v >> 32 - n, (u32int)-1 >> 32 - n); break; default: sysfatal("writem: unimplemented size %d", s); } } void writem64(vlong a, u64int v, int s) { if((s & 0xf) == 3){ writem(a, v, 2); writem(highw(a), v >> 32, 2); }else writem(a, v, s); } static u32int add(u32int a, u32int b, int s) { int v; ps &= ~(FLAGC|FLAGV); switch(s){ case 0: v = (u8int)a + (u8int)b; if(v >= 0x100) ps |= FLAGC; if(((a ^ ~b) & (v ^ a) & 0x80) != 0) ps |= FLAGV; return v; case 1: v = (u16int)a + (u16int)b; if(v >= 0x10000) ps |= FLAGC; if(((a ^ ~b) & (v ^ a) & 0x8000) != 0) ps |= FLAGV; return v; case 2: v = a + b; if((u32int)v < a) ps |= FLAGC; if(((a ^ ~b) & (v ^ a) & 0x80000000) != 0) ps |= FLAGV; return v; default: sysfatal("subtract: unimplemented size %d", s); return 0; } } static void adwc(void) { vlong ad; u32int a, b, v; u8int c; a = readm(amode(2), 2); ad = amode(2); b = readm(ad, 2); c = ps & FLAGC; ps &= ~15; v = a + b + c; if(v < a || c && v == a) ps |= FLAGC; if(((a ^ ~b) & (v ^ a) & 0x80000000) != 0) ps |= FLAGV; writem(ad, v, 2); nzv(v, 2); } static u32int subtract(u32int a, u32int b, int s) { int v; ps &= ~(FLAGC|FLAGV); switch(s){ case 0: v = (u8int)b - (u8int)a; if(v < 0) ps |= FLAGC; if(((a ^ b) & (v ^ a) & 0x80) != 0) ps |= FLAGV; return v; case 1: v = (u16int)b - (u16int)a; if(v < 0) ps |= FLAGC; if(((a ^ b) & (v ^ a) & 0x8000) != 0) ps |= FLAGV; return v; case 2: v = b - a; if((u32int)v > b) ps |= FLAGC; if(((a ^ b) & (v ^ a) & 0x80000000) != 0) ps |= FLAGV; return v; default: sysfatal("subtract: unimplemented size %d", s); return 0; } } static void sbwc(void) { vlong ad; u32int a, b, v; u8int c; a = readm(amode(2), 2); ad = amode(2); b = readm(ad, 2); c = ps & FLAGC; ps &= ~15; v = a - b - c; if(v > a || c && v == a) ps |= FLAGC; if(((a ^ b) & (v ^ a) & 0x80000000) != 0) ps |= FLAGV; writem(ad, v, 2); nzv(v, 2); } static void cmp(u32int a, u32int b, int s) { ps &= ~15; switch(s){ case 0: if((s8int) a < (s8int) b) ps |= FLAGN; if((u8int) a == (u8int) b) ps |= FLAGZ; if((u8int) a < (u8int) b) ps |= FLAGC; break; case 1: if((s16int) a < (s16int) b) ps |= FLAGN; if((u16int) a == (u16int) b) ps |= FLAGZ; if((u16int) a < (u16int) b) ps |= FLAGC; break; case 2: if((s32int) a < (s32int) b) ps |= FLAGN; if(a == b) ps |= FLAGZ; if(a < b) ps |= FLAGC; break; default: sysfatal("cmp: unimplemented size %d", s); } } static u32int mul(u32int a, u32int b, int s) { vlong v; ps &= ~(FLAGC|FLAGV); switch(s){ case 0: v = (s8int) a * (s8int) b; if((uvlong)(v + 0x80) > 0xff) ps |= FLAGV; return v; case 1: v = (s16int) a * (s16int) b; if((uvlong)(v + 0x8000) > 0xffff) ps |= FLAGV; return v; case 2: v = (s32int)a * (s32int) b; if((uvlong)(v + 0x80000000) > 0xffffffff) ps |= FLAGV; return v; default: sysfatal("mul: unimplemented size %d", s); return 0; } } static u32int div(u32int a, u32int b, int s) { vlong v; ps &= ~(FLAGC|FLAGV); switch(s){ case 0: if((s8int) a == 0 || (s8int) b == -0x80 && (s8int) a == -1){ ps |= FLAGV; return b; } v = (s8int) b / (s8int) a; return v; case 1: if((s16int) b == 0 || (s16int) b == -0x8000 && (s16int) a == -1){ ps |= FLAGV; return b; } v = (s16int) b / (s16int) a; return v; case 2: if(b == 0 || (s32int) b == -0x8000 && (s32int) a == -1){ ps |= FLAGV; return b; } v = (s32int) b / (s32int) a; return v; default: sysfatal("div: unimplemented size %d", s); return 0; } } static void alu(int o, int r, int s) { u32int a, b, v; vlong c; switch(r){ case 1: c = amode(s); if(o == ADD || o == SUB) a = 1; else a = 0; b = readm(c, s); break; case 2: a = readm(amode(s), s); c = amode(s); b = readm(c, s); break; case 3: a = readm(amode(s), s); b = readm(amode(s), s); c = amode(s); break; case 4: a = readm(amode(s), s); if(o == XOR) b = -1; else b = 0; c = amode(s); break; default: sysfatal("alu: unimplemented %d", r); return; } switch(o){ case ADD: v = add(a, b, s); break; case SUB: v = subtract(a, b, s); break; case MUL: v = mul(a, b, s); break; case DIV: v = div(a, b, s); break; case CMP: cmp(a, b, s); return; case TST: cmp(b, 0, s); return; case BIC: v = ~a & b; ps &= ~FLAGV; break; case BIS: v = a | b; ps &= ~FLAGV; break; case XOR: v = a ^ b; ps &= ~FLAGV; break; case BIT: nzv(a & b, s); return; default: sysfatal("unimplemented %d in alu", o); v = 0; } nz(v, s); writem(c, v, s); } static void ediv(void) { s32int divr; vlong divd; vlong q; s32int r; vlong quo, rem; divr = readm(amode(2), 2); divd = readm64(amode(3), 3); quo = amode(2); rem = amode(2); ps &= ~15; if(divr == 0){ nope: writem(quo, divd, 2); writem(rem, 0, 2); nz(divd, 2); return; } q = divd / divr; r = divd % divr; if((uvlong)(q + 0x80000000) > 0xffffffff) goto nope; writem(quo, q, 2); writem(rem, r, 2); nz(q, 2); } static void move(int s) { u32int v, w; vlong src, dst; src = amode(s); dst = amode(s); if(s != 3){ v = readm(src, s); writem(dst, v, s); nzv(v, s); }else{ v = readm(src, 2); w = readm(highw(src), 2); writem(dst, v, 2); writem(highw(dst), w, 2); nzv(w, 2); if(v != 0) ps &= ~FLAGZ; } } static void cvt(int s, int t) { u32int v; v = readm(amode(s), s); v = sxt(v, s); writem(amode(t), v, t); nzv(v, t); switch(t){ case 0: if((uvlong)(v + 0x80) > 0xff) ps |= FLAGV; break; case 1: if((uvlong)(v + 0x8000) > 0xffff) ps |= FLAGV; break; } ps &= ~FLAGC; } static void movez(int s, int t) { u32int v; v = readm(amode(s), s); writem(amode(t), v, t); nzv(v, t); } static void movea(int s) { vlong v; v = amode(s); if(v < 0) sysfatal("invalid movea (pc=%.8x)", curpc); writem(amode(2), v, 2); nzv(v, 2); } static void pusha(int s) { vlong v; v = amode(s); if(v < 0) sysfatal("invalid pusha (pc=%.8x)", curpc); writem(r[14] -= 4, v, 2); nzv(v, 2); } static void pushl(void) { u32int v; v = readm(amode(2), 2); writem(r[14] -= 4, v, 2); nzv(v, 2); } static void branch(int s, int c) { int off; if(s == 0) off = (s8int) fetch8(); else off = (s16int) fetch16(); if(c) r[15] += off; } static void calls(void) { u32int narg, sp; vlong dst; u16int m; int i; narg = readm(amode(2), 2); dst = amode(0); if(dst < 0) sysfatal("call to illegal location pc=%.8ux", curpc); writem(r[14] -= 4, narg, 2); sp = r[14]; r[14] &= -4; m = readm(dst, 1); for(i = 12; --i >= 0; ) if((m & 1<<i) != 0) writem(r[14] -= 4, r[i], 2); writem(r[14] -= 4, r[15], 2); writem(r[14] -= 4, r[13], 2); writem(r[14] -= 4, r[12], 2); ps &= ~0xf; writem(r[14] -= 4, (sp & 3)<<30|1<<29|(m & 0xfff)<<16|ps&~0x10, 2); ps &= ~0xc0; if((m & 0x8000) != 0) ps |= 0x80; if((m & 0x4000) != 0) ps |= 0x40; writem(r[14] -= 4, 0, 2); r[13] = r[14]; r[12] = sp; r[15] = dst + 2; } static void ret(void) { u32int m; u8int n; int i; r[14] = r[13] + 4; m = readm(r[14], 2); r[14] += 4; r[12] = readm(r[14], 2); r[14] += 4; r[13] = readm(r[14], 2); r[14] += 4; r[15] = readm(r[14], 2); r[14] += 4; for(i = 0; i < 12; i++) if((m & 1<<16+i) != 0){ r[i] = readm(r[14], 2); r[14] += 4; } r[14] += m >> 30; ps = (u16int) m; if((m & 1<<29) != 0){ n = readm(r[14], 2); r[14] += 4 + 4 * n; } } static void bbs(int inv, int new) { u32int pos; vlong base; s8int displ; u32int val; pos = readm(amode(2), 2); base = amode(0); displ = fetch8(); if(base < 0){ if(pos >= 32) sysfatal("invalid bbs (pc=%.8ux)", curpc); val = readm(base, 2); if((val >> pos & 1) != inv) r[15] += displ; if(new != 0){ if(new > 0) val |= 1<<pos; else val &= ~(1<<pos); writem(base, val, 2); } }else{ base += pos >> 3; pos &= 7; val = readm(base, 0); if((val >> pos & 1) != inv) r[15] += displ; if(new != 0){ if(new > 0) val |= 1<<pos; else val &= ~(1<<pos); writem(base, val, 0); } } } static void ashl(void) { s8int cnt; s32int v; cnt = readm(amode(0), 0); v = readm(amode(2), 2); ps &= ~15; if(cnt >= 32){ if(v != 0) ps |= FLAGV; v = 0; }else if(cnt >= 0){ if(v + (v & 1<<31 >> cnt) != 0) ps |= FLAGV; v <<= cnt; }else if(cnt > -32) v >>= -cnt; else v >>= 31; nz(v, 2); writem(amode(2), v, 2); } static void rotl(void) { s8int cnt; s32int v; cnt = readm(amode(0), 0); v = readm(amode(2), 2); ps &= ~FLAGV; cnt &= 31; v = v << cnt | v >> 32 - cnt; nz(v, 2); writem(amode(2), v, 2); } static void ashq(void) { s8int cnt; s64int v; cnt = readm(amode(0), 0); v = readm64(amode(3), 3); ps &= ~15; if(cnt >= 64){ if(v != 0) ps |= FLAGV; v = 0; }else if(cnt >= 0){ if(v + (v & 1ULL<<63 >> cnt) != 0) ps |= FLAGV; v <<= cnt; }else if(cnt > -64) v >>= -cnt; else v >>= 63; nz64(v, 3); writem64(amode(3), v, 3); } static void blb(int val) { u32int v; s8int disp; v = readm(amode(2), 2); disp = fetch8(); if((v & 1) == val) r[15] += disp; } static void sob(int geq) { vlong v; s32int i; s8int disp; v = amode(2); disp = fetch8(); i = readm(v, 2) - 1; writem(v, i, 2); nzv(i, 2); if(i == 0x7fffffff) ps |= FLAGV; if(i > 0 || i == 0 && geq) r[15] += disp; } static void aob(int leq) { s32int l, v; vlong a; s8int disp; l = readm(amode(2), 2); a = amode(2); disp = fetch8(); v = readm(a, 2) + 1; writem(a, v, 2); nzv(v, 2); if(v == 0x80000000) ps |= FLAGV; if(v < l || v == l && leq) r[15] += disp; } static void bsb(int s) { u32int v; switch(s){ case 0: v = fetch8(); writem(r[14] -= 4, r[15], 2); r[15] += (s8int) v; break; case 1: v = fetch16(); writem(r[14] -= 4, r[15], 2); r[15] += (s16int) v; break; case 2: v = addrof(amode(0)); writem(r[14] -= 4, r[15], 2); r[15] = v; break; } } static void casei(int s) { u32int sel, base, lim; sel = readm(amode(s), s); base = readm(amode(s), s); lim = readm(amode(s), s); sel -= base; if(sel <= lim) r[15] += (s16int) readm(r[15] + 2 * sel, 1); else r[15] += 2 * (lim + 1); } static void pushr(void) { u16int m; u32int sp; int i; m = readm(amode(1), 1); sp = r[14]; for(i = 15; --i >= 0; ) if((m & 1<<i) != 0) writem(sp -= 4, r[i], 2); r[14] = sp; } static void popr(void) { u16int m; u32int sp; int i; m = readm(amode(1), 1); sp = r[14]; for(i = 0; i < 15; i++) if((m & 1<<i) != 0){ r[i] = readm(sp, 2); sp += 4; } if((m & 1<<14) == 0) r[14] = sp; } static void acb(int s) { vlong a; s32int lim, n, v; s16int disp; int c; lim = readm(amode(s), s); n = readm(amode(s), s); a = amode(s); v = readm(a, s); disp = fetch16(); c = ps & FLAGC; v = add(v, n, s); nz(v, s); ps |= c; writem(a, v, s); if(n >= 0 && v <= lim || n < 0 && v >= lim) r[15] += disp; } static void extv(int sx) { u32int pos, v; u8int c; u8int size; int i, s; vlong base; vlong dst; pos = readm(amode(2), 2); size = readm(amode(0), 0); base = amode(0); dst = amode(2); if(size > 32 || pos >= 32 && base < 0) sysfatal("extv size=%d pos=%d (pc=%#.8ux)", size, pos, curpc); if(base < 0){ v = readm(base, 2) >> pos; if(size < 32) v &= (1<<size) - 1; }else{ base += pos >> 3; pos &= 7; v = 0; for(i = 0; i < size; i += s){ c = readm(base, 0); c >>= pos; s = 8 - pos; if(s > size) s = size; v |= (c & (1<<s) - 1) << i; base++; pos = 0; } } if(sx) v = (s32int)(v << 32 - size) >> 32 - size; writem(dst, v, 2); ps &= ~FLAGC; nzv(v, 2); } static void insv(void) { u32int src, pos; u8int size; vlong base; u32int v, m; int i, s; src = readm(amode(2), 2); pos = readm(amode(2), 2); size = readm(amode(0), 0); base = amode(0); if(size > 32 || pos >= 32 && base < 0) sysfatal("extv"); if(base < 0){ v = readm(base, 2); m = (size == 32 ? 0 : 1<<size) - 1 << pos; v = v & ~m | src << pos & m; writem(base, v, 2); }else{ base += pos >> 3; pos &= 7; for(i = 0; i < size; i += s){ v = readm(base, 0); s = 8 - pos; if(s > size) s = size; m = (1<<s) - 1 << pos; v = v & ~m | src << pos & m; writem(base, v, 0); src >>= s; base++; } } ps &= ~15; } void addp(int, int); void editpc(void); void cvtlp(void); void movp(void); void cmpp(int); void ashp(void); void alufp(int, int, int); void movefp(int, int); void cvtfp(int, int, int); void locc(int); void cmpc(int); void movc(int); void emod(int); void step(void) { uchar op; curpc = r[15]; op = fetch8(); if(trace || 0 && op >= 0x40 && op < 0x78) print("%.8ux %.2ux %.2ux %.8ux %.8ux %.8ux %.8ux\n", curpc, op, ps, r[14], r[0], r[1], r[5]); switch(op){ case 0x04: ret(); break; case 0x05: r[15] = readm(r[14], 2); r[14] += 4; break; case 0x10: bsb(0); break; case 0x11: branch(0, 1); break; case 0x12: branch(0, (ps & FLAGZ) == 0); break; case 0x13: branch(0, (ps & FLAGZ) != 0); break; case 0x14: branch(0, (ps & (FLAGZ|FLAGN)) == 0); break; case 0x15: branch(0, (ps & (FLAGZ|FLAGN)) != 0); break; case 0x16: bsb(2); break; case 0x17: r[15] = amode(0); break; case 0x18: branch(0, (ps & FLAGN) == 0); break; case 0x19: branch(0, (ps & FLAGN) != 0); break; case 0x1a: branch(0, (ps & (FLAGZ|FLAGC)) == 0); break; case 0x1b: branch(0, (ps & (FLAGZ|FLAGC)) != 0); break; case 0x1c: branch(0, (ps & FLAGV) == 0); break; case 0x1d: branch(0, (ps & FLAGV) != 0); break; case 0x1e: branch(0, (ps & FLAGC) == 0); break; case 0x1f: branch(0, (ps & FLAGC) != 0); break; case 0x20: addp(4, 0); break; case 0x21: addp(6, 0); break; case 0x22: addp(4, 1); break; case 0x23: addp(6, 1); break; case 0x28: movc(0); break; case 0x29: cmpc(0); break; case 0x2c: movc(1); break; case 0x2d: cmpc(1); break; case 0x30: bsb(1); break; case 0x31: branch(1, 1); break; case 0x32: cvt(1, 2); break; case 0x33: cvt(1, 0); break; case 0x34: movp(); break; case 0x35: cmpp(3); break; case 0x37: cmpp(4); break; case 0x38: editpc(); break; case 0x3a: locc(0); break; case 0x3b: locc(1); break; case 0x3c: movez(1, 2); break; case 0x3d: acb(1); break; case 0x3e: movea(1); break; case 0x3f: pusha(1); break; case 0x40: alufp(ADD, 2, 0x12); break; case 0x41: alufp(ADD, 3, 0x12); break; case 0x42: alufp(SUB, 2, 0x12); break; case 0x43: alufp(SUB, 3, 0x12); break; case 0x44: alufp(MUL, 2, 0x12); break; case 0x45: alufp(MUL, 3, 0x12); break; case 0x46: alufp(DIV, 2, 0x12); break; case 0x47: alufp(DIV, 3, 0x12); break; case 0x48: cvtfp(0x12, 0, 0); break; case 0x49: cvtfp(0x12, 1, 0); break; case 0x4a: cvtfp(0x12, 2, 0); break; case 0x4b: cvtfp(0x12, 2, 1); break; case 0x4c: cvtfp(0, 0x12, 0); break; case 0x4d: cvtfp(1, 0x12, 0); break; case 0x4e: cvtfp(2, 0x12, 0); break; case 0x50: movefp(0x12, 0); break; case 0x51: alufp(CMP, 2, 0x12); break; case 0x52: movefp(0x12, 1); break; case 0x53: alufp(CMP, 1, 0x12); break; case 0x54: emod(0x12); break; case 0x56: cvtfp(0x12, 0x13, 0); break; case 0x60: alufp(ADD, 2, 0x13); break; case 0x61: alufp(ADD, 3, 0x13); break; case 0x62: alufp(SUB, 2, 0x13); break; case 0x63: alufp(SUB, 3, 0x13); break; case 0x64: alufp(MUL, 2, 0x13); break; case 0x65: alufp(MUL, 3, 0x13); break; case 0x66: alufp(DIV, 2, 0x13); break; case 0x67: alufp(DIV, 3, 0x13); break; case 0x68: cvtfp(0x13, 0, 0); break; case 0x69: cvtfp(0x13, 1, 0); break; case 0x6a: cvtfp(0x13, 2, 0); break; case 0x6b: cvtfp(0x13, 2, 1); break; case 0x6c: cvtfp(0, 0x13, 0); break; case 0x6d: cvtfp(1, 0x13, 0); break; case 0x6e: cvtfp(2, 0x13, 0); break; case 0x70: movefp(0x13, 0); break; case 0x71: alufp(CMP, 2, 0x13); break; case 0x72: movefp(0x13, 1); break; case 0x73: alufp(CMP, 1, 0x13); break; case 0x74: emod(0x13); break; case 0x76: cvtfp(0x13, 0x12, 0); break; case 0x78: ashl(); break; case 0x79: ashq(); break; case 0x7b: ediv(); break; case 0x7c: writem64(amode(3), 0, 3); nzv(0, 0); break; case 0x7d: move(3); break; case 0x7e: movea(3); break; case 0x7f: pusha(3); break; case 0x80: alu(ADD, 2, 0); break; case 0x81: alu(ADD, 3, 0); break; case 0x82: alu(SUB, 2, 0); break; case 0x83: alu(SUB, 3, 0); break; case 0x84: alu(MUL, 2, 0); break; case 0x85: alu(MUL, 3, 0); break; case 0x86: alu(DIV, 2, 0); break; case 0x87: alu(DIV, 3, 0); break; case 0x88: alu(BIS, 2, 0); break; case 0x89: alu(BIS, 3, 0); break; case 0x8a: alu(BIC, 2, 0); break; case 0x8b: alu(BIC, 3, 0); break; case 0x8c: alu(XOR, 2, 0); break; case 0x8d: alu(XOR, 3, 0); break; case 0x8e: alu(SUB, 4, 0); break; case 0x8f: casei(0); break; case 0x90: move(0); break; case 0x91: alu(CMP, 2, 0); break; case 0x92: alu(XOR, 4, 0); break; case 0x93: alu(BIT, 2, 0); break; case 0x94: writem(amode(0), 0, 0); nzv(0, 0); break; case 0x95: alu(TST, 1, 0); break; case 0x96: alu(ADD, 1, 0); break; case 0x97: alu(SUB, 1, 0); break; case 0x98: cvt(0, 2); break; case 0x99: cvt(0, 1); break; case 0x9a: movez(0, 2); break; case 0x9b: movez(0, 1); break; case 0x9c: rotl(); break; case 0x9d: acb(0); break; case 0x9e: movea(0); break; case 0x9f: pusha(0); break; case 0xa0: alu(ADD, 2, 1); break; case 0xa1: alu(ADD, 3, 1); break; case 0xa2: alu(SUB, 2, 1); break; case 0xa3: alu(SUB, 3, 1); break; case 0xa4: alu(MUL, 2, 1); break; case 0xa5: alu(MUL, 3, 1); break; case 0xa6: alu(DIV, 2, 1); break; case 0xa7: alu(DIV, 3, 1); break; case 0xa8: alu(BIS, 2, 1); break; case 0xa9: alu(BIS, 3, 1); break; case 0xaa: alu(BIC, 2, 1); break; case 0xab: alu(BIC, 3, 1); break; case 0xac: alu(XOR, 2, 1); break; case 0xad: alu(XOR, 3, 1); break; case 0xae: alu(SUB, 4, 1); break; case 0xaf: casei(1); break; case 0xb0: move(1); break; case 0xb1: alu(CMP, 2, 1); break; case 0xb2: alu(XOR, 4, 1); break; case 0xb3: alu(BIT, 2, 1); break; case 0xb4: writem(amode(1), 0, 1); nzv(0, 1); break; case 0xb5: alu(TST, 1, 1); break; case 0xb6: alu(ADD, 1, 1); break; case 0xb7: alu(SUB, 1, 1); break; case 0xba: popr(); break; case 0xbb: pushr(); break; case 0xbc: syscall(readm(amode(1), 1)); break; case 0xc0: alu(ADD, 2, 2); break; case 0xc1: alu(ADD, 3, 2); break; case 0xc2: alu(SUB, 2, 2); break; case 0xc3: alu(SUB, 3, 2); break; case 0xc4: alu(MUL, 2, 2); break; case 0xc5: alu(MUL, 3, 2); break; case 0xc6: alu(DIV, 2, 2); break; case 0xc7: alu(DIV, 3, 2); break; case 0xc8: alu(BIS, 2, 2); break; case 0xc9: alu(BIS, 3, 2); break; case 0xca: alu(BIC, 2, 2); break; case 0xcb: alu(BIC, 3, 2); break; case 0xcc: alu(XOR, 2, 2); break; case 0xcd: alu(XOR, 3, 2); break; case 0xce: alu(SUB, 4, 2); break; case 0xcf: casei(2); break; case 0xd0: move(2); break; case 0xd1: alu(CMP, 2, 2); break; case 0xd2: alu(XOR, 4, 2); break; case 0xd3: alu(BIT, 2, 2); break; case 0xd4: writem(amode(2), 0, 2); nzv(0, 2); break; case 0xd5: alu(TST, 1, 2); break; case 0xd6: alu(ADD, 1, 2); break; case 0xd7: alu(SUB, 1, 2); break; case 0xd8: adwc(); break; case 0xd9: sbwc(); break; case 0xdd: pushl(); break; case 0xde: movea(2); break; case 0xdf: pusha(2); break; case 0xe0: bbs(0, 0); break; case 0xe1: bbs(1, 0); break; case 0xe2: bbs(0, 1); break; case 0xe3: bbs(1, 1); break; case 0xe4: bbs(0, -1); break; case 0xe5: bbs(1, -1); break; case 0xe8: blb(1); break; case 0xe9: blb(0); break; case 0xee: extv(1); break; case 0xef: extv(0); break; case 0xf0: insv(); break; case 0xf1: acb(2); break; case 0xf2: aob(0); break; case 0xf3: aob(1); break; case 0xf4: sob(1); break; case 0xf5: sob(0); break; case 0xf6: cvt(2, 0); break; case 0xf7: cvt(2, 1); break; case 0xf8: ashp(); break; case 0xf9: cvtlp(); break; case 0xfb: calls(); break; default: sysfatal("unimplemented op %.2x (pc=%.8x)", op, curpc); } }