uxn

Varvara Ordinator, written in ANSI C(SDL2)
git clone https://git.eamoncaddigan.net/uxn.git
Log | Files | Refs | README | LICENSE

uxn.c (4249B)


      1 #include "uxn.h"
      2 
      3 /*
      4 Copyright (u) 2022-2024 Devine Lu Linvega, Andrew Alderwick, Andrew Richards
      5 
      6 Permission to use, copy, modify, and distribute this software for any
      7 purpose with or without fee is hereby granted, provided that the above
      8 copyright notice and this permission notice appear in all copies.
      9 
     10 THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
     11 WITH REGARD TO THIS SOFTWARE.
     12 */
     13 
     14 #define OPC(opc, init, body) {\
     15 	case 0x00|opc: {const int _2=0,_r=0;init body;} break;\
     16 	case 0x20|opc: {const int _2=1,_r=0;init body;} break;\
     17 	case 0x40|opc: {const int _2=0,_r=1;init body;} break;\
     18 	case 0x60|opc: {const int _2=1,_r=1;init body;} break;\
     19 	case 0x80|opc: {const int _2=0,_r=0,k=uxn.wst.ptr;init uxn.wst.ptr=k;body;} break;\
     20 	case 0xa0|opc: {const int _2=1,_r=0,k=uxn.wst.ptr;init uxn.wst.ptr=k;body;} break;\
     21 	case 0xc0|opc: {const int _2=0,_r=1,k=uxn.rst.ptr;init uxn.rst.ptr=k;body;} break;\
     22 	case 0xe0|opc: {const int _2=1,_r=1,k=uxn.rst.ptr;init uxn.rst.ptr=k;body;} break;\
     23 }
     24 
     25 /* Microcode */
     26 
     27 #define JMI a = uxn.ram[pc] << 8 | uxn.ram[pc + 1], pc += a + 2;
     28 #define REM if(_r) uxn.rst.ptr -= 1 + _2; else uxn.wst.ptr -= 1 + _2;
     29 #define INC(s) uxn.s.dat[uxn.s.ptr++]
     30 #define DEC(s) uxn.s.dat[--uxn.s.ptr]
     31 #define JMP(x) { if(_2) pc = x; else pc += (Sint8)x; }
     32 #define PO1(o) { o = _r ? DEC(rst) : DEC(wst);}
     33 #define PO2(o) { if(_r) o = DEC(rst), o |= DEC(rst) << 8; else o = DEC(wst), o |= DEC(wst) << 8; }
     34 #define POx(o) { if(_2) PO2(o) else PO1(o) }
     35 #define PU1(i) { if(_r) INC(rst) = i; else INC(wst) = i; }
     36 #define RP1(i) { if(_r) INC(wst) = i; else INC(rst) = i; }
     37 #define PUx(i) { if(_2) { c = (i); PU1(c >> 8) PU1(c) } else PU1(i) }
     38 #define GET(o) { if(_2) PO1(o[1]) PO1(o[0]) }
     39 #define PUT(i) { PU1(i[0]) if(_2) PU1(i[1]) }
     40 #define DEI(i,o) o[0] = emu_dei(i); if(_2) o[1] = emu_dei(i + 1); PUT(o)
     41 #define DEO(i,j) emu_deo(i, j[0]); if(_2) emu_deo(i + 1, j[1]);
     42 #define PEK(i,o,m) o[0] = uxn.ram[i]; if(_2) o[1] = uxn.ram[(i + 1) & m]; PUT(o)
     43 #define POK(i,j,m) uxn.ram[i] = j[0]; if(_2) uxn.ram[(i + 1) & m] = j[1];
     44 
     45 int
     46 uxn_eval(Uint16 pc)
     47 {
     48 	unsigned int a, b, c, x[2], y[2], z[2], step;
     49 	if(!pc || uxn.dev[0x0f]) return 0;
     50 	for(step = STEP_MAX; step; step--) {
     51 		switch(uxn.ram[pc++]) {
     52 		/* BRK */ case 0x00: return 1;
     53 		/* JCI */ case 0x20: if(DEC(wst)) { JMI break; } pc += 2; break;
     54 		/* JMI */ case 0x40: JMI break;
     55 		/* JSI */ case 0x60: c = pc + 2; INC(rst) = c >> 8; INC(rst) = c; JMI break;
     56 		/* LI2 */ case 0xa0: INC(wst) = uxn.ram[pc++]; /* fall-through */
     57 		/* LIT */ case 0x80: INC(wst) = uxn.ram[pc++]; break;
     58 		/* L2r */ case 0xe0: INC(rst) = uxn.ram[pc++]; /* fall-through */
     59 		/* LIr */ case 0xc0: INC(rst) = uxn.ram[pc++]; break;
     60 		/* INC */ OPC(0x01,POx(a),PUx(a + 1))
     61 		/* POP */ OPC(0x02,REM   ,{})
     62 		/* NIP */ OPC(0x03,GET(x) REM   ,PUT(x))
     63 		/* SWP */ OPC(0x04,GET(x) GET(y),PUT(x) PUT(y))
     64 		/* ROT */ OPC(0x05,GET(x) GET(y) GET(z),PUT(y) PUT(x) PUT(z))
     65 		/* DUP */ OPC(0x06,GET(x),PUT(x) PUT(x))
     66 		/* OVR */ OPC(0x07,GET(x) GET(y),PUT(y) PUT(x) PUT(y))
     67 		/* EQU */ OPC(0x08,POx(a) POx(b),PU1(b == a))
     68 		/* NEQ */ OPC(0x09,POx(a) POx(b),PU1(b != a))
     69 		/* GTH */ OPC(0x0a,POx(a) POx(b),PU1(b > a))
     70 		/* LTH */ OPC(0x0b,POx(a) POx(b),PU1(b < a))
     71 		/* JMP */ OPC(0x0c,POx(a),JMP(a))
     72 		/* JCN */ OPC(0x0d,POx(a) PO1(b),if(b) JMP(a))
     73 		/* JSR */ OPC(0x0e,POx(a),RP1(pc >> 8) RP1(pc) JMP(a))
     74 		/* STH */ OPC(0x0f,GET(x),RP1(x[0]) if(_2) RP1(x[1]))
     75 		/* LDZ */ OPC(0x10,PO1(a),PEK(a, x, 0xff))
     76 		/* STZ */ OPC(0x11,PO1(a) GET(y),POK(a, y, 0xff))
     77 		/* LDR */ OPC(0x12,PO1(a),PEK(pc + (Sint8)a, x, 0xffff))
     78 		/* STR */ OPC(0x13,PO1(a) GET(y),POK(pc + (Sint8)a, y, 0xffff))
     79 		/* LDA */ OPC(0x14,PO2(a),PEK(a, x, 0xffff))
     80 		/* STA */ OPC(0x15,PO2(a) GET(y),POK(a, y, 0xffff))
     81 		/* DEI */ OPC(0x16,PO1(a),DEI(a, x))
     82 		/* DEO */ OPC(0x17,PO1(a) GET(y),DEO(a, y))
     83 		/* ADD */ OPC(0x18,POx(a) POx(b),PUx(b + a))
     84 		/* SUB */ OPC(0x19,POx(a) POx(b),PUx(b - a))
     85 		/* MUL */ OPC(0x1a,POx(a) POx(b),PUx(b * a))
     86 		/* DIV */ OPC(0x1b,POx(a) POx(b),PUx(a ? b / a : 0))
     87 		/* AND */ OPC(0x1c,POx(a) POx(b),PUx(b & a))
     88 		/* ORA */ OPC(0x1d,POx(a) POx(b),PUx(b | a))
     89 		/* EOR */ OPC(0x1e,POx(a) POx(b),PUx(b ^ a))
     90 		/* SFT */ OPC(0x1f,PO1(a) POx(b),PUx(b >> (a & 0xf) << (a >> 4)))
     91 		}
     92 	}
     93 	return 0;
     94 }