commit 2d89b3ab4865005d79c19ff7af9f927c0f0dd195
parent c66d99ade72a01298f5dc7103ad2a14b4e9e7261
Author: Virgil Dupras <hsoft@hardcoded.net>
Date: Mon, 21 Nov 2022 11:31:01 -0500
app/uxn: hex formatting
Diffstat:
4 files changed, 138 insertions(+), 99 deletions(-)
diff --git a/fs/app/uxn/vm.c b/fs/app/uxn/vm.c
@@ -7,15 +7,15 @@
*/
struct Stack {
- // TODO: allow single line decl
- unsigned char ptr;
- unsigned char dat[$ff];
+ // TODO: allow single line decl
+ unsigned char ptr;
+ unsigned char dat[$ff];
};
struct Device {
- unsigned char dat[$10];
- unsigned char (*dei)(Device*, unsigned char);
- void (*deo)(Device*, unsigned char);
+ unsigned char dat[$10];
+ unsigned char (*dei)(Device*, unsigned char);
+ void (*deo)(Device*, unsigned char);
};
typedef void (*VMOP) ();
@@ -33,152 +33,178 @@ static unsigned char *sp; // pointer to current stack top
static unsigned char kptr; // holding value for keep mode
static void error(int code) {
- printf(code, "Error %d encountered\n");
- abort();
+ printf(code, "Error %d encountered\n");
+ abort();
}
+// TODO: have pointer arithmetics strong enough to use something like this:
+// static unsigned short gw(unsigned short *a) { return *a<<8|*(a+1); }
+// static void sw(unsigned short *a, unsigned short val) {
+// *a = val>>8; *(a+1) = val; }
static void push8(unsigned char val) {
- if (src->ptr == $ff) { error(2); } else { src->dat[src->ptr++] = val; }
+ if (src->ptr == $ff) { error(2); } else { src->dat[src->ptr++] = val; }
}
-static void push16(unsigned short val) {
- if (src->ptr >= $fe) { error(2); } else {
- src->dat[src->ptr] = val >> 8;
- src->dat[src->ptr+1] = val;
- src->ptr += 2 ;
- }
+static void push16(Stack *s, unsigned short val) {
+ if (s->ptr >= $fe) { error(2); } else {
+ s->dat[s->ptr] = val >> 8;
+ s->dat[s->ptr+1] = val;
+ s->ptr += 2 ;
+ }
}
-static void push(unsigned short val) { if (bs) push16(val); else push8(val); }
+static void push(unsigned short val) { if (bs) push16(src, val); else push8(val); }
static unsigned char pop8() {
- if (!*sp) { error(0); } else { return src->dat[--*sp]; }
+ if (!*sp) { error(0); } else { return src->dat[--*sp]; }
}
static unsigned short pop16() {
- unsigned short val;
- if (*sp <= 1) { error(0); } else {
- *sp -= 2;
- val = src->dat[*sp] << 8;
- val |= src->dat[*sp+1];
- return val;
- }
+ unsigned short val;
+ if (*sp <= 1) { error(0); } else {
+ *sp -= 2;
+ val = src->dat[*sp] << 8;
+ val |= src->dat[*sp+1];
+ return val;
+ }
}
static unsigned short pop() { if (bs) return pop16(); else return pop8(); }
static void poke(unsigned short addr, unsigned short val) {
- if (bs) {
- ram[addr] = val >> 8;
- ram[addr+1] = val;
- } else {
- ram[addr] = val;
- }
+ if (bs) {
+ ram[addr] = val >> 8;
+ ram[addr+1] = val;
+ } else {
+ ram[addr] = val;
+ }
}
static unsigned short peek(unsigned short addr) {
- if (bs) {
- return (ram[addr] << 8) | ram[addr+1];
- } else {
- return ram[addr];
- }
+ if (bs) {
+ return (ram[addr] << 8) | ram[addr+1];
+ } else {
+ return ram[addr];
+ }
}
static void warp(unsigned short addr) {
- if (bs) {
- pc = addr;
- } else {
- // TODO: allow sign-extending through typecasting
- if (addr >= $80) addr -= $100;
- pc += addr;
- }
+ if (bs) {
+ pc = addr;
+ } else {
+ // TODO: allow sign-extending through typecasting
+ if (addr >= $80) addr -= $100;
+ pc += addr;
+ }
}
static unsigned char nulldei(Device *d, unsigned char port) { return d->dat[port]; }
static void nulldeo(Device *d, unsigned char port) { }
/* Operations */
-static void _err() { error(42); }
static void LIT() { push(peek(pc++)); pc += bs; }
static void INC() { push(pop()+1); }
static void POP() { pop(); }
static void NIP() { unsigned short x = pop(); pop(); push(x); }
static void SWP() {
- unsigned short x = pop();
- unsigned short y = pop();
- push(x); push(y); }
+ unsigned short x = pop();
+ unsigned short y = pop();
+ push(x); push(y); }
static void ROT() {
- unsigned short x = pop();
- unsigned short y = pop();
- unsigned short z = pop();
- push(y); push(x); push(z); }
+ unsigned short x = pop();
+ unsigned short y = pop();
+ unsigned short z = pop();
+ push(y); push(x); push(z); }
static void DUP() { unsigned short x = pop(); push(x); push(x); }
static void OVR() {
- unsigned short x = pop();
- unsigned short y = pop();
- push(y); push(x); push(y); }
+ unsigned short x = pop();
+ unsigned short y = pop();
+ push(y); push(x); push(y); }
static void EQU() { push8(pop() == pop()); }
static void NEQ() { push8(pop() != pop()); }
static void GTH() {
- unsigned short a = pop();
- unsigned short b = pop();
- push8(b > a); }
+ unsigned short a = pop();
+ unsigned short b = pop();
+ push8(b > a); }
static void LTH() {
- unsigned short a = pop();
- unsigned short b = pop();
- push8(b < a); }
+ unsigned short a = pop();
+ unsigned short b = pop();
+ push8(b < a); }
static void JMP() { warp(pop()); }
static void JCN() { unsigned short a = pop(); if (pop8()) { warp(a); } }
+static void JSR() {
+ unsigned short a = pop();
+ push16(dst, pc); warp(a); }
static void LDA() { push(peek(pop16())); }
static void DEO() {
- unsigned char port = pop8();
- unsigned short val = pop();
- Device *d = &dev[port>>4];
- port &= $f;
- if (bs) {
- d->dat[port] = val >> 8; d->deo(d, port++);
- port &= $f;
- d->dat[port] = val; d->deo(d, port);
- } else {
- d->dat[port] = val; d->deo(d, port);
- }
+ unsigned char port = pop8();
+ unsigned short val = pop();
+ Device *d = &dev[port>>4];
+ port &= $f;
+ if (bs) {
+ d->dat[port] = val >> 8; d->deo(d, port++);
+ port &= $f;
+ d->dat[port] = val; d->deo(d, port);
+ } else {
+ d->dat[port] = val; d->deo(d, port);
+ }
}
static void ADD() { push(pop() + pop()); }
+static void MUL() { push(pop() * pop()); }
+static void AND() { push(pop() & pop()); }
+static void SFT() {
+ unsigned char shift = pop8();
+ unsigned short n = pop();
+ n >>= (shift & $0f);
+ n <<= (shift >> 4);
+ push(n);
+}
+
static VMOP ops[$20] = {
- LIT, INC, POP, NIP, SWP, ROT, DUP, OVR,
- EQU, NEQ, GTH, LTH, JMP, JCN, _err, _err,
- _err, _err, _err, _err, LDA, _err, _err, DEO,
- ADD, _err, _err, _err, _err, _err, _err, _err};
+ LIT, INC, POP, NIP, SWP, ROT, DUP, OVR,
+ EQU, NEQ, GTH, LTH, JMP, JCN, JSR, NULL,
+ NULL, NULL, NULL, NULL, LDA, NULL, NULL, DEO,
+ ADD, NULL, MUL, NULL, AND, NULL, NULL, SFT};
void uxn_exec() {
- unsigned char op;
- while (op = ram[pc++]) {
- bs = (op >> 5) & 1;
- if (op & $80) {
- kptr = src->ptr;
- sp = &kptr;
- } else {
- sp = &src->ptr;
- }
- op &= $1f;
- ops[op]();
- }
+ unsigned char op;
+ while (op = ram[pc++]) {
+ bs = (op >> 5) & 1;
+ if(op & $40) {
+ src = &rst; dst = &wst;
+ } else {
+ src = &wst; dst = &rst;
+ }
+ if (op & $80) {
+ kptr = src->ptr;
+ sp = &kptr;
+ } else {
+ sp = &src->ptr;
+ }
+ op &= $1f;
+ if (ops[op]) {
+ ops[op]();
+ } else {
+ printf(op, "unimplemented %b\n");
+ return;
+ }
+ }
}
/* Console */
void console_deo(Device *d, unsigned char port) {
- if (port == 8) stdout(d->dat[port]);
+ if (port == 8) stdout(d->dat[port]);
}
void uxn_init() {
- int i;
- pc = $100;
- wst.ptr = 0;
- rst.ptr = 0;
- src = &wst;
- dst = &rst;
- for (i=0; i<$10; i++) {
- dev[i].dei = nulldei;
- dev[i].deo = nulldeo;
- memset(dev[i].dat, 0, $10);
- }
- dev[1].deo = console_deo;
+ int i;
+ pc = $100;
+ wst.ptr = 0;
+ rst.ptr = 0;
+ src = &wst;
+ dst = &rst;
+ for (i=0; i<$10; i++) {
+ dev[i].dei = nulldei;
+ dev[i].deo = nulldeo;
+ memset(dev[i].dat, 0, $10);
+ }
+ dev[1].deo = console_deo;
}
unsigned int* uxn_ram() { return ram; }
diff --git a/fs/tests/app/uxn/hexfmt.bin b/fs/tests/app/uxn/hexfmt.bin
Binary files differ.
diff --git a/fs/tests/app/uxn/hexfmt.tal b/fs/tests/app/uxn/hexfmt.tal
@@ -0,0 +1,9 @@
+|0100 #1234 ,print-hex JSR #abcd ,print-hex JSR BRK
+
+@print-hex ( short* -- )
+
+ SWP ,&byte JSR
+ &byte ( byte -- ) DUP #04 SFT ,&char JSR
+ &char ( char -- ) #0f AND DUP #09 GTH #27 MUL ADD #30 ADD #18 DEO
+
+JMP2r
diff --git a/fs/tests/app/uxn/vm.fs b/fs/tests/app/uxn/vm.fs
@@ -17,4 +17,8 @@ create expected 47 nc,
$00 $59 $00 $90 $00 $e9 $01 $79 $02 $62 $03 $db $06 $3d $0a $18 $10 $55
$1a $6d $2a $c2 $45 $2f $6f $f1 $b5 $20
capture uxn_exec expected 47 []= #
+
+S" /tests/app/uxn/hexfmt.bin" _load
+uxn_init
+capture uxn_exec S" 1234abcd" #s=
testend