diff --git a/.gitignore b/.gitignore index ed1e496..9d863e8 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,5 @@ *png~ *gif~ *bmp~ -uxn -uxnasm +/bin *.rom \ No newline at end of file diff --git a/uxnasm.c b/assembler.c similarity index 100% rename from uxnasm.c rename to assembler.c diff --git a/build.sh b/build.sh index 859e0c2..ca8b9a6 100755 --- a/build.sh +++ b/build.sh @@ -1,20 +1,21 @@ #!/bin/bash -# format code -clang-format -i uxnasm.c -clang-format -i uxn.c -clang-format -i cpu.h -clang-format -i cpu.c +# Create bin folder +mkdir -p bin -# remove old -rm -f ./uxnasm -rm -f ./uxn +# Assembler +clang-format -i assembler.c +rm -f ./assembler rm -f ./boot.rom +cc -std=c89 -DDEBUG -Wall -Wno-unknown-pragmas -Wpedantic -Wshadow -Wextra -Werror=implicit-int -Werror=incompatible-pointer-types -Werror=int-conversion -Wvla -g -Og -fsanitize=address -fsanitize=undefined assembler.c -o bin/assembler +./bin/assembler examples/hello.usm bin/boot.rom -# debug(slow) -cc -std=c89 -DDEBUG -Wall -Wno-unknown-pragmas -Wpedantic -Wshadow -Wextra -Werror=implicit-int -Werror=incompatible-pointer-types -Werror=int-conversion -Wvla -g -Og -fsanitize=address -fsanitize=undefined uxnasm.c -o uxnasm -cc -std=c89 -DDEBUG -Wall -Wno-unknown-pragmas -Wpedantic -Wshadow -Wextra -Werror=implicit-int -Werror=incompatible-pointer-types -Werror=int-conversion -Wvla -g -Og -fsanitize=address -fsanitize=undefined cpu.c uxn.c -o uxn +# Emulator +clang-format -i emulator.c +clang-format -i uxn.h +clang-format -i uxn.c +rm -f ./uxn +cc -std=c89 -DDEBUG -Wall -Wno-unknown-pragmas -Wpedantic -Wshadow -Wextra -Werror=implicit-int -Werror=incompatible-pointer-types -Werror=int-conversion -Wvla -g -Og -fsanitize=address -fsanitize=undefined uxn.c emulator.c -o bin/emulator # run -./uxnasm examples/hello.usm boot.rom -./uxn boot.rom +./bin/emulator bin/boot.rom diff --git a/cpu.c b/cpu.c deleted file mode 100644 index a6055e7..0000000 --- a/cpu.c +++ /dev/null @@ -1,210 +0,0 @@ -#include - -/* -Copyright (c) 2021 Devine Lu Linvega - -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. -*/ - -#include "cpu.h" - -Cpu cpu; - -#pragma mark - Helpers - -void -setflag(Uint8 *status, char flag, int b) -{ - if(b) - *status |= flag; - else - *status &= (~flag); -} - -int -getflag(Uint8 *status, char flag) -{ - return *status & flag; -} - -#pragma mark - Operations - -/* clang-format off */ - -Uint16 bytes2short(Uint8 a, Uint8 b) { return (a << 8) + b; } -Uint16 mempeek16(Cpu *c, Uint16 s) { return (c->ram.dat[s] << 8) + (c->ram.dat[s+1] & 0xff); } -void wspush8(Cpu *c, Uint8 b) { c->wst.dat[c->wst.ptr++] = b; } -void wspush16(Cpu *c, Uint16 s) { wspush8(c,s >> 8); wspush8(c,s & 0xff); } -Uint8 wspop8(Cpu *c) { return c->wst.dat[--c->wst.ptr]; } -Uint16 wspop16(Cpu *c) { return wspop8(c) + (wspop8(c) << 8); } -Uint8 wspeek8(Cpu *c, Uint8 o) { return c->wst.dat[c->wst.ptr - o]; } -Uint16 wspeek16(Cpu *c, Uint8 o) { return bytes2short(c->wst.dat[c->wst.ptr - o], c->wst.dat[c->wst.ptr - o + 1]); } -Uint16 rspop16(Cpu *c) { return c->rst.dat[--c->rst.ptr]; } -void rspush16(Cpu *c, Uint16 a) { c->rst.dat[c->rst.ptr++] = a; } -/* I/O */ -void op_brk(Cpu *c) { setflag(&c->status,FLAG_HALT, 1); } -void op_lit(Cpu *c) { c->literal += c->ram.dat[c->ram.ptr++]; } -void op_nop(Cpu *c) { (void)c; printf("NOP");} -void op_ldr(Cpu *c) { wspush8(c, c->ram.dat[wspop16(c)]); } -void op_str(Cpu *c) { c->ram.dat[wspop16(c)] = wspop8(c); } -/* Logic */ -void op_jmp(Cpu *c) { c->ram.ptr = wspop16(c); } -void op_jsr(Cpu *c) { rspush16(c, c->ram.ptr); c->ram.ptr = wspop16(c); } -void op_rts(Cpu *c) { c->ram.ptr = rspop16(c); } -/* Stack */ -void op_pop(Cpu *c) { wspop8(c); } -void op_dup(Cpu *c) { wspush8(c,wspeek8(c,1)); } -void op_swp(Cpu *c) { Uint8 b = wspop8(c), a = wspop8(c); wspush8(c,b); wspush8(c,a); } -void op_ovr(Cpu *c) { Uint8 a = wspeek8(c,2); wspush8(c,a); } -void op_rot(Cpu *c) { Uint8 c1 = wspop8(c),b = wspop8(c),a = wspop8(c); wspush8(c,b); wspush8(c, c1); wspush8(c,a); } -void op_and(Cpu *c) { Uint8 a = wspop8(c), b = wspop8(c); wspush8(c,a & b); } -void op_ora(Cpu *c) { Uint8 a = wspop8(c), b = wspop8(c); wspush8(c,a | b); } -void op_rol(Cpu *c) { Uint8 a = wspop8(c), b = wspop8(c); wspush8(c,a << b); } -/* Arithmetic */ -void op_add(Cpu *c) { Uint8 a = wspop8(c), b = wspop8(c); wspush8(c,b + a); } -void op_sub(Cpu *c) { Uint8 a = wspop8(c), b = wspop8(c); wspush8(c,b - a); } -void op_mul(Cpu *c) { Uint8 a = wspop8(c), b = wspop8(c); wspush8(c,b * a); } -void op_div(Cpu *c) { Uint8 a = wspop8(c), b = wspop8(c); wspush8(c,b / a); } -void op_equ(Cpu *c) { Uint8 a = wspop8(c), b = wspop8(c); wspush8(c,b == a); } -void op_neq(Cpu *c) { Uint8 a = wspop8(c), b = wspop8(c); wspush8(c,b != a); } -void op_gth(Cpu *c) { Uint8 a = wspop8(c), b = wspop8(c); wspush8(c,b > a); } -void op_lth(Cpu *c) { Uint8 a = wspop8(c), b = wspop8(c); wspush8(c,b < a); } -/* Stack(16-bits) */ -void op_pop16(Cpu *c) { wspop16(c); } -void op_dup16(Cpu *c) { wspush16(c,wspeek16(c,2)); } -void op_swp16(Cpu *c) { Uint16 b = wspop16(c), a = wspop16(c); wspush16(c,b); wspush16(c,a); } -void op_ovr16(Cpu *c) { Uint16 a = wspeek16(c, 4); wspush16(c,a); } -void op_rot16(Cpu *c) { Uint16 c1 = wspop16(c), b = wspop16(c), a = wspop16(c); wspush16(c,b); wspush16(c, c1); wspush16(c,a); } -void op_and16(Cpu *c) { Uint16 a = wspop16(c), b = wspop16(c); wspush16(c,a & b); } -void op_ora16(Cpu *c) { Uint16 a = wspop16(c), b = wspop16(c); wspush16(c,a | b); } -void op_rol16(Cpu *c) { Uint16 a = wspop16(c), b = wspop16(c); wspush16(c,a << b); } -/* Arithmetic(16-bits) */ -void op_add16(Cpu *c) { Uint16 a = wspop16(c), b = wspop16(c); wspush16(c,b + a); } -void op_sub16(Cpu *c) { Uint16 a = wspop16(c), b = wspop16(c); wspush16(c,b - a); } -void op_mul16(Cpu *c) { Uint16 a = wspop16(c), b = wspop16(c); wspush16(c,b * a); } -void op_div16(Cpu *c) { Uint16 a = wspop16(c), b = wspop16(c); wspush16(c,b / a); } -void op_equ16(Cpu *c) { Uint16 a = wspop16(c), b = wspop16(c); wspush8(c,b == a); } -void op_neq16(Cpu *c) { Uint16 a = wspop16(c), b = wspop16(c); wspush8(c,b != a); } -void op_gth16(Cpu *c) { Uint16 a = wspop16(c), b = wspop16(c); wspush8(c,b > a); } -void op_lth16(Cpu *c) { Uint16 a = wspop16(c), b = wspop16(c); wspush8(c,b < a); } - -void (*ops[])(Cpu *c) = { - op_brk, op_lit, op_nop, op_nop, op_nop, op_nop, op_ldr, op_str, - op_jmp, op_jsr, op_nop, op_rts, op_nop, op_nop, op_nop, op_nop, - op_pop, op_dup, op_swp, op_ovr, op_rot, op_and, op_ora, op_rol, - op_add, op_sub, op_mul, op_div, op_equ, op_neq, op_gth, op_lth, - op_pop16, op_dup16, op_swp16, op_ovr16, op_rot16, op_and16, op_ora16, op_rol16, - op_add16, op_sub16, op_mul16, op_div16, op_equ16, op_neq16, op_gth16, op_lth16 -}; - -Uint8 opr[][2] = { - {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {2,1}, {3,0}, - {2,0}, {2,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, - {1,0}, {1,2}, {2,2}, {3,3}, {3,3}, {2,1}, {2,1}, {2,1}, - {2,1}, {2,1}, {2,1}, {2,1}, {2,1}, {2,1}, {2,1}, {2,1}, - {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, /* TODO */ - {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0} /* TODO */ -}; - -/* clang-format on */ - -int -error(Cpu *c, char *name, int id) -{ - printf("Error: %s#%04x, at 0x%04x\n", name, id, c->counter); - return 0; -} - -int -doliteral(Cpu *c, Uint8 instr) -{ - if(c->wst.ptr >= 255) - return error(c, "Stack overflow", instr); - wspush8(c, instr); - c->literal--; - return 1; -} - -int -dodevices(Cpu *c) /* experimental */ -{ - if(c->ram.dat[0xfff1]) { - printf("%c", c->ram.dat[0xfff1]); - c->ram.dat[0xfff1] = 0x00; - } - return 1; -} - -int -doopcode(Cpu *c, Uint8 instr) -{ - Uint8 op = instr & 0x1f; - setflag(&c->status, FLAG_SHORT, (instr >> 5) & 1); - setflag(&c->status, FLAG_SIGN, (instr >> 6) & 1); /* usused */ - setflag(&c->status, FLAG_COND, (instr >> 7) & 1); - if(getflag(&c->status, FLAG_SHORT)) - op += 16; - if(c->wst.ptr < opr[op][0]) - return error(c, "Stack underflow", op); - if(c->wst.ptr + opr[op][1] - opr[op][0] >= 255) - return error(c, "Stack overflow", instr); - if(!getflag(&c->status, FLAG_COND) || (getflag(&c->status, FLAG_COND) && wspop8(c))) - (*ops[op])(c); - dodevices(c); - return 1; -} - -int -eval(Cpu *c) -{ - Uint8 instr = c->ram.dat[c->ram.ptr++]; - if(c->literal > 0) - return doliteral(c, instr); - else - return doopcode(c, instr); - return 1; -} - -int -load(Cpu *c, char *filepath) -{ - FILE *f; - if(!(f = fopen(filepath, "rb"))) - return error(c, "Missing input.", 0); - fread(c->ram.dat, sizeof(c->ram.dat), 1, f); - return 1; -} - -void -reset(Cpu *c) -{ - size_t i; - char *cptr = (char *)c; - for(i = 0; i < sizeof c; i++) - cptr[i] = 0; -} - -int -boot(Cpu *c) -{ - reset(c); - c->vreset = mempeek16(c, 0xfffa); - c->vframe = mempeek16(c, 0xfffc); - c->verror = mempeek16(c, 0xfffe); - /* eval reset */ - c->ram.ptr = c->vreset; - setflag(&c->status, FLAG_HALT, 0); - while(!(c->status & FLAG_HALT) && eval(c)) - c->counter++; - /* eval frame */ - c->ram.ptr = c->vframe; - setflag(&c->status, FLAG_HALT, 0); - while(!(c->status & FLAG_HALT) && eval(c)) - c->counter++; - return 1; -} diff --git a/emulator.c b/emulator.c new file mode 100644 index 0000000..61b07bf --- /dev/null +++ b/emulator.c @@ -0,0 +1,67 @@ +#include +#include "uxn.h" + +/* +Copyright (c) 2021 Devine Lu Linvega + +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. +*/ + +void +echos(Stack8 *s, Uint8 len, char *name) +{ + int i; + printf("\n%s\n", name); + for(i = 0; i < len; ++i) { + if(i % 16 == 0) + printf("\n"); + printf("%02x%c", s->dat[i], s->ptr == i ? '<' : ' '); + } + printf("\n\n"); +} + +void +echom(Memory *m, Uint8 len, char *name) +{ + int i; + printf("\n%s\n", name); + for(i = 0; i < len; ++i) { + if(i % 16 == 0) + printf("\n"); + printf("%02x ", m->dat[i]); + } + printf("\n\n"); +} + +void +echof(Uxn *c) +{ + printf("ended @ %d steps | hf: %x sf: %x sf: %x cf: %x\n", + c->counter, + getflag(&c->status, FLAG_HALT) != 0, + getflag(&c->status, FLAG_SHORT) != 0, + getflag(&c->status, FLAG_SIGN) != 0, + getflag(&c->status, FLAG_COND) != 0); +} + +int +main(int argc, char *argv[]) +{ + Uxn cpu; + if(argc < 2) + return error(&cpu, "No input.", 0); + if(!load(&cpu, argv[1])) + return error(&cpu, "Load error", 0); + if(!boot(&cpu)) + return error(&cpu, "Boot error", 0); + /* print result */ + echos(&cpu.wst, 0x40, "stack"); + echom(&cpu.ram, 0x40, "ram"); + echof(&cpu); + return 0; +} diff --git a/uxn.c b/uxn.c index 4ce5d89..ab4b01d 100644 --- a/uxn.c +++ b/uxn.c @@ -1,5 +1,4 @@ #include -#include "cpu.h" /* Copyright (c) 2021 Devine Lu Linvega @@ -12,56 +11,200 @@ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE. */ -void -echos(Stack8 *s, Uint8 len, char *name) -{ - int i; - printf("\n%s\n", name); - for(i = 0; i < len; ++i) { - if(i % 16 == 0) - printf("\n"); - printf("%02x%c", s->dat[i], s->ptr == i ? '<' : ' '); - } - printf("\n\n"); -} +#include "uxn.h" + +Uxn cpu; + +#pragma mark - Helpers void -echom(Memory *m, Uint8 len, char *name) +setflag(Uint8 *status, char flag, int b) { - int i; - printf("\n%s\n", name); - for(i = 0; i < len; ++i) { - if(i % 16 == 0) - printf("\n"); - printf("%02x ", m->dat[i]); - } - printf("\n\n"); -} - -void -echof(Cpu *c) -{ - printf("ended @ %d steps | hf: %x sf: %x sf: %x cf: %x\n", - c->counter, - getflag(&c->status, FLAG_HALT) != 0, - getflag(&c->status, FLAG_SHORT) != 0, - getflag(&c->status, FLAG_SIGN) != 0, - getflag(&c->status, FLAG_COND) != 0); + if(b) + *status |= flag; + else + *status &= (~flag); } int -main(int argc, char *argv[]) +getflag(Uint8 *status, char flag) { - Cpu cpu; - if(argc < 2) - return error(&cpu, "No input.", 0); - if(!load(&cpu, argv[1])) - return error(&cpu, "Load error", 0); - if(!boot(&cpu)) - return error(&cpu, "Boot error", 0); - /* print result */ - echos(&cpu.wst, 0x40, "stack"); - echom(&cpu.ram, 0x40, "ram"); - echof(&cpu); + return *status & flag; +} + +#pragma mark - Operations + +/* clang-format off */ + +Uint16 bytes2short(Uint8 a, Uint8 b) { return (a << 8) + b; } +Uint16 mempeek16(Uxn *c, Uint16 s) { return (c->ram.dat[s] << 8) + (c->ram.dat[s+1] & 0xff); } +void wspush8(Uxn *c, Uint8 b) { c->wst.dat[c->wst.ptr++] = b; } +void wspush16(Uxn *c, Uint16 s) { wspush8(c,s >> 8); wspush8(c,s & 0xff); } +Uint8 wspop8(Uxn *c) { return c->wst.dat[--c->wst.ptr]; } +Uint16 wspop16(Uxn *c) { return wspop8(c) + (wspop8(c) << 8); } +Uint8 wspeek8(Uxn *c, Uint8 o) { return c->wst.dat[c->wst.ptr - o]; } +Uint16 wspeek16(Uxn *c, Uint8 o) { return bytes2short(c->wst.dat[c->wst.ptr - o], c->wst.dat[c->wst.ptr - o + 1]); } +Uint16 rspop16(Uxn *c) { return c->rst.dat[--c->rst.ptr]; } +void rspush16(Uxn *c, Uint16 a) { c->rst.dat[c->rst.ptr++] = a; } +/* I/O */ +void op_brk(Uxn *c) { setflag(&c->status,FLAG_HALT, 1); } +void op_lit(Uxn *c) { c->literal += c->ram.dat[c->ram.ptr++]; } +void op_nop(Uxn *c) { (void)c; printf("NOP");} +void op_ldr(Uxn *c) { wspush8(c, c->ram.dat[wspop16(c)]); } +void op_str(Uxn *c) { c->ram.dat[wspop16(c)] = wspop8(c); } +/* Logic */ +void op_jmp(Uxn *c) { c->ram.ptr = wspop16(c); } +void op_jsr(Uxn *c) { rspush16(c, c->ram.ptr); c->ram.ptr = wspop16(c); } +void op_rts(Uxn *c) { c->ram.ptr = rspop16(c); } +/* Stack */ +void op_pop(Uxn *c) { wspop8(c); } +void op_dup(Uxn *c) { wspush8(c,wspeek8(c,1)); } +void op_swp(Uxn *c) { Uint8 b = wspop8(c), a = wspop8(c); wspush8(c,b); wspush8(c,a); } +void op_ovr(Uxn *c) { Uint8 a = wspeek8(c,2); wspush8(c,a); } +void op_rot(Uxn *c) { Uint8 c1 = wspop8(c),b = wspop8(c),a = wspop8(c); wspush8(c,b); wspush8(c, c1); wspush8(c,a); } +void op_and(Uxn *c) { Uint8 a = wspop8(c), b = wspop8(c); wspush8(c,a & b); } +void op_ora(Uxn *c) { Uint8 a = wspop8(c), b = wspop8(c); wspush8(c,a | b); } +void op_rol(Uxn *c) { Uint8 a = wspop8(c), b = wspop8(c); wspush8(c,a << b); } +/* Arithmetic */ +void op_add(Uxn *c) { Uint8 a = wspop8(c), b = wspop8(c); wspush8(c,b + a); } +void op_sub(Uxn *c) { Uint8 a = wspop8(c), b = wspop8(c); wspush8(c,b - a); } +void op_mul(Uxn *c) { Uint8 a = wspop8(c), b = wspop8(c); wspush8(c,b * a); } +void op_div(Uxn *c) { Uint8 a = wspop8(c), b = wspop8(c); wspush8(c,b / a); } +void op_equ(Uxn *c) { Uint8 a = wspop8(c), b = wspop8(c); wspush8(c,b == a); } +void op_neq(Uxn *c) { Uint8 a = wspop8(c), b = wspop8(c); wspush8(c,b != a); } +void op_gth(Uxn *c) { Uint8 a = wspop8(c), b = wspop8(c); wspush8(c,b > a); } +void op_lth(Uxn *c) { Uint8 a = wspop8(c), b = wspop8(c); wspush8(c,b < a); } +/* Stack(16-bits) */ +void op_pop16(Uxn *c) { wspop16(c); } +void op_dup16(Uxn *c) { wspush16(c,wspeek16(c,2)); } +void op_swp16(Uxn *c) { Uint16 b = wspop16(c), a = wspop16(c); wspush16(c,b); wspush16(c,a); } +void op_ovr16(Uxn *c) { Uint16 a = wspeek16(c, 4); wspush16(c,a); } +void op_rot16(Uxn *c) { Uint16 c1 = wspop16(c), b = wspop16(c), a = wspop16(c); wspush16(c,b); wspush16(c, c1); wspush16(c,a); } +void op_and16(Uxn *c) { Uint16 a = wspop16(c), b = wspop16(c); wspush16(c,a & b); } +void op_ora16(Uxn *c) { Uint16 a = wspop16(c), b = wspop16(c); wspush16(c,a | b); } +void op_rol16(Uxn *c) { Uint16 a = wspop16(c), b = wspop16(c); wspush16(c,a << b); } +/* Arithmetic(16-bits) */ +void op_add16(Uxn *c) { Uint16 a = wspop16(c), b = wspop16(c); wspush16(c,b + a); } +void op_sub16(Uxn *c) { Uint16 a = wspop16(c), b = wspop16(c); wspush16(c,b - a); } +void op_mul16(Uxn *c) { Uint16 a = wspop16(c), b = wspop16(c); wspush16(c,b * a); } +void op_div16(Uxn *c) { Uint16 a = wspop16(c), b = wspop16(c); wspush16(c,b / a); } +void op_equ16(Uxn *c) { Uint16 a = wspop16(c), b = wspop16(c); wspush8(c,b == a); } +void op_neq16(Uxn *c) { Uint16 a = wspop16(c), b = wspop16(c); wspush8(c,b != a); } +void op_gth16(Uxn *c) { Uint16 a = wspop16(c), b = wspop16(c); wspush8(c,b > a); } +void op_lth16(Uxn *c) { Uint16 a = wspop16(c), b = wspop16(c); wspush8(c,b < a); } + +void (*ops[])(Uxn *c) = { + op_brk, op_lit, op_nop, op_nop, op_nop, op_nop, op_ldr, op_str, + op_jmp, op_jsr, op_nop, op_rts, op_nop, op_nop, op_nop, op_nop, + op_pop, op_dup, op_swp, op_ovr, op_rot, op_and, op_ora, op_rol, + op_add, op_sub, op_mul, op_div, op_equ, op_neq, op_gth, op_lth, + op_pop16, op_dup16, op_swp16, op_ovr16, op_rot16, op_and16, op_ora16, op_rol16, + op_add16, op_sub16, op_mul16, op_div16, op_equ16, op_neq16, op_gth16, op_lth16 +}; + +Uint8 opr[][2] = { + {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {2,1}, {3,0}, + {2,0}, {2,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, + {1,0}, {1,2}, {2,2}, {3,3}, {3,3}, {2,1}, {2,1}, {2,1}, + {2,1}, {2,1}, {2,1}, {2,1}, {2,1}, {2,1}, {2,1}, {2,1}, + {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, /* TODO */ + {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0} /* TODO */ +}; + +/* clang-format on */ + +int +error(Uxn *c, char *name, int id) +{ + printf("Error: %s#%04x, at 0x%04x\n", name, id, c->counter); return 0; } + +int +doliteral(Uxn *c, Uint8 instr) +{ + if(c->wst.ptr >= 255) + return error(c, "Stack overflow", instr); + wspush8(c, instr); + c->literal--; + return 1; +} + +int +dodevices(Uxn *c) /* experimental */ +{ + if(c->ram.dat[0xfff1]) { + printf("%c", c->ram.dat[0xfff1]); + c->ram.dat[0xfff1] = 0x00; + } + return 1; +} + +int +doopcode(Uxn *c, Uint8 instr) +{ + Uint8 op = instr & 0x1f; + setflag(&c->status, FLAG_SHORT, (instr >> 5) & 1); + setflag(&c->status, FLAG_SIGN, (instr >> 6) & 1); /* usused */ + setflag(&c->status, FLAG_COND, (instr >> 7) & 1); + if(getflag(&c->status, FLAG_SHORT)) + op += 16; + if(c->wst.ptr < opr[op][0]) + return error(c, "Stack underflow", op); + if(c->wst.ptr + opr[op][1] - opr[op][0] >= 255) + return error(c, "Stack overflow", instr); + if(!getflag(&c->status, FLAG_COND) || (getflag(&c->status, FLAG_COND) && wspop8(c))) + (*ops[op])(c); + dodevices(c); + return 1; +} + +int +eval(Uxn *c) +{ + Uint8 instr = c->ram.dat[c->ram.ptr++]; + if(c->literal > 0) + return doliteral(c, instr); + else + return doopcode(c, instr); + return 1; +} + +int +load(Uxn *c, char *filepath) +{ + FILE *f; + if(!(f = fopen(filepath, "rb"))) + return error(c, "Missing input.", 0); + fread(c->ram.dat, sizeof(c->ram.dat), 1, f); + return 1; +} + +void +reset(Uxn *c) +{ + size_t i; + char *cptr = (char *)c; + for(i = 0; i < sizeof c; i++) + cptr[i] = 0; +} + +int +boot(Uxn *c) +{ + reset(c); + c->vreset = mempeek16(c, 0xfffa); + c->vframe = mempeek16(c, 0xfffc); + c->verror = mempeek16(c, 0xfffe); + /* eval reset */ + c->ram.ptr = c->vreset; + setflag(&c->status, FLAG_HALT, 0); + while(!(c->status & FLAG_HALT) && eval(c)) + c->counter++; + /* eval frame */ + c->ram.ptr = c->vframe; + setflag(&c->status, FLAG_HALT, 0); + while(!(c->status & FLAG_HALT) && eval(c)) + c->counter++; + return 1; +} diff --git a/cpu.h b/uxn.h similarity index 90% rename from cpu.h rename to uxn.h index 5e05d22..a22468c 100644 --- a/cpu.h +++ b/uxn.h @@ -40,10 +40,10 @@ typedef struct { Stack8 wst; Stack16 rst; Memory ram; -} Cpu; +} Uxn; void setflag(Uint8 *status, char flag, int b); int getflag(Uint8 *status, char flag); -int error(Cpu *c, char *name, int id); -int load(Cpu *c, char *filepath); -int boot(Cpu *c); +int error(Uxn *c, char *name, int id); +int load(Uxn *c, char *filepath); +int boot(Uxn *c);