@@ 0,0 1,85 @@
+#include "uxn.h"
+
+/*
+Copyright (u) 2022-2023 Devine Lu Linvega, Andrew Alderwick, Andrew Richards
+
+Permission to use, copy, modify, and distribute this software for any
+purpose with or without fee is hereby granted, provided that the above
+copyright notice and this permission notice appear in all copies.
+
+THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+WITH REGARD TO THIS SOFTWARE.
+*/
+
+#define FLIP { s = ins & 0x40 ? &u->wst : &u->rst; }
+#define JUMP(x) { if(m2) pc = (x); else pc += (Sint8)(x); }
+#define POP1(o) { o = s->dat[--*sp]; }
+#define POP2(o) { o = s->dat[--*sp] | (s->dat[--*sp] << 0x8); }
+#define POPx(o) { if(m2) { POP2(o) } else POP1(o) }
+#define PUSH1(y) { s->dat[s->ptr++] = (y); }
+#define PUSH2(y) { tt = (y); s->dat[s->ptr++] = tt >> 0x8; s->dat[s->ptr++] = tt; }
+#define PUSHx(y) { if(m2) { PUSH2(y) } else PUSH1(y) }
+#define PEEK(o, x, r) { if(m2) { r = (x); o = ram[r++] << 8 | ram[r]; } else o = ram[(x)]; }
+#define POKE(x, y, r) { if(m2) { r = (x); ram[r++] = y >> 8; ram[r] = y; } else ram[(x)] = (y); }
+#define DEVR(o, p) { if(m2) { o = (emu_dei(u, p) << 8) | emu_dei(u, p + 1); } else o = emu_dei(u, p); }
+#define DEVW(p, y) { if(m2) { emu_deo(u, p, y >> 8); emu_deo(u, p + 1, y); } else emu_deo(u, p, y); }
+#define next { ins = ram[pc++]; \
+ m2 = ins & 0x20; \
+ s = ins & 0x40 ? &u->rst : &u->wst; \
+ if(ins & 0x80) kp = s->ptr, sp = &kp; else sp = &s->ptr; \
+ goto *lut[ins & 0x1f]; }
+
+int
+uxn_eval(Uxn *u, Uint16 pc)
+{
+ Uint8 t, kp, *sp, ins, m2, *ram = u->ram;
+ Uint16 tt, a, b, c;
+ Stack *s;
+ static void* lut[] = {
+ &&_imm, &&_inc, &&_pop, &&_nip, &&_swp, &&_rot, &&_dup, &&_ovr,
+ &&_equ, &&_neq, &&_gth, &&_lth, &&_jmp, &&_jcn, &&_jsr, &&_sth,
+ &&_ldz, &&_stz, &&_ldr, &&_str, &&_lda, &&_sta, &&_dei, &&_deo,
+ &&_add, &&_sub, &&_mul, &&_div, &&_and, &&_ora, &&_eor, &&_sft };
+ if(!pc || u->dev[0x0f]) return 0;
+ next
+ _imm:
+ switch(ins) {
+ case 0x00: /* BRK */ return 1;
+ case 0x20: /* JCI */ POP1(b) if(!b) { pc += 2; break; }
+ case 0x40: /* JMI */ a = ram[pc++] << 8 | ram[pc++]; pc += a; break;
+ case 0x60: /* JSI */ PUSH2(pc + 2) a = ram[pc++] << 8 | ram[pc++]; pc += a; break;
+ case 0x80: case 0xc0: /* LIT */ PUSH1(ram[pc++]) break;
+ case 0xa0: case 0xe0: /* LIT2 */ PUSH1(ram[pc++]) PUSH1(ram[pc++]) break;
+ } next
+ _inc: POPx(a) PUSHx(a + 1) next
+ _pop: POPx(a) next
+ _nip: POPx(a) POPx(b) PUSHx(a) next
+ _swp: POPx(a) POPx(b) PUSHx(a) PUSHx(b) next
+ _rot: POPx(a) POPx(b) POPx(c) PUSHx(b) PUSHx(a) PUSHx(c) next
+ _dup: POPx(a) PUSHx(a) PUSHx(a) next
+ _ovr: POPx(a) POPx(b) PUSHx(b) PUSHx(a) PUSHx(b) next
+ _equ: POPx(a) POPx(b) PUSH1(b == a) next
+ _neq: POPx(a) POPx(b) PUSH1(b != a) next
+ _gth: POPx(a) POPx(b) PUSH1(b > a) next
+ _lth: POPx(a) POPx(b) PUSH1(b < a) next
+ _jmp: POPx(a) JUMP(a) next
+ _jcn: POPx(a) POP1(b) if(b) JUMP(a) next
+ _jsr: POPx(a) FLIP PUSH2(pc) JUMP(a) next
+ _sth: POPx(a) FLIP PUSHx(a) next
+ _ldz: POP1(a) PEEK(b, a, t) PUSHx(b) next
+ _stz: POP1(a) POPx(b) POKE(a, b, t) next
+ _ldr: POP1(a) PEEK(b, pc + (Sint8)a, tt) PUSHx(b) next
+ _str: POP1(a) POPx(b) POKE(pc + (Sint8)a, b, tt) next
+ _lda: POP2(a) PEEK(b, a, tt) PUSHx(b) next
+ _sta: POP2(a) POPx(b) POKE(a, b, tt) next
+ _dei: POP1(a) DEVR(b, a) PUSHx(b) next
+ _deo: POP1(a) POPx(b) DEVW(a, b) next
+ _add: POPx(a) POPx(b) PUSHx(b + a) next
+ _sub: POPx(a) POPx(b) PUSHx(b - a) next
+ _mul: POPx(a) POPx(b) PUSHx(b * a) next
+ _div: POPx(a) POPx(b) PUSHx(a ? b / a : 0) next
+ _and: POPx(a) POPx(b) PUSHx(b & a) next
+ _ora: POPx(a) POPx(b) PUSHx(b | a) next
+ _eor: POPx(a) POPx(b) PUSHx(b ^ a) next
+ _sft: POP1(a) POPx(b) PUSHx(b >> (a & 0xf) << (a >> 4)) next
+}<
\ No newline at end of file