uxn

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

commit 521be808a0ae99083414f9baf4b192f90c42b8be
parent 69d255bfff808ef63c270abe1ed56413b129b65b
Author: neauoire <aliceffekt@gmail.com>
Date:   Wed,  3 Feb 2021 21:53:56 -0800

Design progress

Diffstat:
MREADME.md | 25++++++++++++-------------
Mexamples/arithmetic.usm | 2+-
Dexamples/cond.usm | 16----------------
Aexamples/conditionals.usm | 13+++++++++++++
Mexamples/core.usm | 13++++++++++---
Mexamples/loop.usm | 2+-
Muxn.c | 20++++++++++----------
Muxnasm.c | 46++++++++++++++++++++++++++++++----------------
8 files changed, 77 insertions(+), 60 deletions(-)

diff --git a/README.md b/README.md @@ -10,17 +10,15 @@ cc uxn.c -std=c89 -Os -DNDEBUG -g0 -s -Wall -Wno-unknown-pragmas -o uxn ## Assembly Syntax +- `;variable`, a named address(zero-page) - `:label`, a named address -- `+literal`, a numeric value -- `.pointer`, pointer to a label +- `.pointer`, a pointer to a label +- `@0010`, a position in the program ``` < conditionals > -0302 ADD -05 EQU - -.there JMZ +.there ( 0a 05 GTH ) JMC :here < when not equal > @@ -35,10 +33,15 @@ cc uxn.c -std=c89 -Os -DNDEBUG -g0 -s -Wall -Wno-unknown-pragmas -o uxn ## Mission +### Assembler + +- Crash on missing label - Catch overflow/underflow +- Constants - Jumps should be relative -- constants -- variables + +### CPU + - Pointers/Literals - A Three-Way Decision Routine(http://www.6502.org/tutorials/compare_instructions.html) - Carry flag? @@ -47,7 +50,7 @@ cc uxn.c -std=c89 -Os -DNDEBUG -g0 -s -Wall -Wno-unknown-pragmas -o uxn - Detect mouse click - SDL Layer Emulator - Build PPU -- Interrupts +- Interrupts, vectors ### 16 Bit Missions @@ -56,10 +59,6 @@ cc uxn.c -std=c89 -Os -DNDEBUG -g0 -s -Wall -Wno-unknown-pragmas -o uxn - Implement addressing - Implement 16 bits operations -## Notes - -- Forth logic operators pop 2 items and add a bool to the stack, is that viable in uxn? - ## Refs https://code.9front.org/hg/plan9front/file/a7f9946e238f/sys/src/games/nes/cpu.c diff --git a/examples/arithmetic.usm b/examples/arithmetic.usm @@ -1,6 +1,6 @@ < arithmetic > -0203 LTH .true JMZ +0203 LTH .true JMC :false ee BRK :true ff BRK diff --git a/examples/cond.usm b/examples/cond.usm @@ -1,16 +0,0 @@ -< conditionals > - -0302 ADD -05 EQU - -.there JMZ - -:here - < when not equal > - ee - BRK - -:there - < when is equal > - ff - BRK diff --git a/examples/conditionals.usm b/examples/conditionals.usm @@ -0,0 +1,13 @@ +< conditionals > + +.there ( 0a 05 GTH ) JMC + +:here + < when not equal > + ee + BRK + +:there + < when is equal > + ff + BRK diff --git a/examples/core.usm b/examples/core.usm @@ -1,6 +1,13 @@ -< core > +< conditionals > -34 34 EQU .label JSZ ff BRK +.there ( 0a 05 GTH ) JMC -:label ee RTS +:here + < when not equal > + ee + BRK +:there + < when is equal > + ff + BRK diff --git a/examples/loop.usm b/examples/loop.usm @@ -4,5 +4,5 @@ :loop 01 ADD - 0f NEQ .loop JMZ + 0f NEQ .loop JMC RTS diff --git a/uxn.c b/uxn.c @@ -86,14 +86,14 @@ void op_dup() { wspush(wspeek()); } void op_swp() { Uint8 b = wspop(), a = wspop(); wspush(b); wspush(a); } void op_ovr() { wspush(cpu.wst.dat[cpu.wst.ptr - 2]); } void op_rot() { Uint8 c = wspop(),b = wspop(),a = wspop(); wspush(b); wspush(c); wspush(a); } -void op_jmi() { cpu.rom.ptr = wspop(); } -void op_jsi() { rspush(cpu.rom.ptr); cpu.rom.ptr = wspop(); } -void op_jmz() { Uint8 a = wspop(); if(getflag(FLAG_ZERO)){ cpu.rom.ptr = a; } setflag(FLAG_ZERO,0); } -void op_jsz() { Uint8 a = wspop(); if(getflag(FLAG_ZERO)){ rspush(cpu.rom.ptr); cpu.rom.ptr = a; } setflag(FLAG_ZERO,0); } -void op_equ() { setflag(FLAG_ZERO, wspop() == wspeek()); } -void op_neq() { setflag(FLAG_ZERO, wspop() != wspeek()); } -void op_gth() { setflag(FLAG_ZERO, wspop() < wspeek()); } -void op_lth() { setflag(FLAG_ZERO, wspop() > wspeek()); } +void op_jmu() { cpu.rom.ptr = wspop(); } +void op_jsu() { rspush(cpu.rom.ptr); cpu.rom.ptr = wspop(); } +void op_jmc() { if(wspop()) op_jmu(); } +void op_jsc() { if(wspop()) op_jsu(); } +void op_equ() { wspush(wspop() == wspop()); } +void op_neq() { wspush(wspop() != wspop()); } +void op_gth() { wspush(wspop() < wspop()); } +void op_lth() { wspush(wspop() > wspop()); } void op_and() { wspush(wspop() & wspop()); } void op_ora() { wspush(wspop() | wspop()); } void op_rol() { wspush(wspop() << 1); } @@ -105,12 +105,12 @@ void op_div() { wspush(wspop() / wspop()); } void (*ops[])(void) = { op_brk, op_rts, op_lit, op_drp, op_dup, op_swp, op_ovr, op_rot, - op_jmi, op_jsi, op_jmz, op_jsz, op_equ, op_neq, op_gth, op_lth, + op_jmu, op_jsu, op_jmc, op_jsc, op_equ, op_neq, op_gth, op_lth, op_and, op_ora, op_rol, op_ror, op_add, op_sub, op_mul, op_div}; Uint8 opr[][2] = { {0,0}, {0,0}, {0,0}, {1,0}, {0,1}, {1,1}, {0,1}, {3,3}, - {1,0}, {1,0}, {1,0}, {1,0}, {1,0}, {1,0}, {1,0}, {1,0}, + {2,0}, {2,0}, {2,0}, {2,0}, {2,1}, {2,1}, {2,1}, {2,1}, {1,0}, {1,0}, {1,0}, {1,0}, {2,1}, {0,0}, {0,0}, {0,0}, {2,1}, {2,1}, {2,1}, {2,1}, {2,1}, {2,1}, {2,1}, {2,1} }; diff --git a/uxnasm.c b/uxnasm.c @@ -17,7 +17,7 @@ WITH REGARD TO THIS SOFTWARE. typedef unsigned char Uint8; typedef struct { - int len; + int ptr; Uint8 data[PRGLEN]; } Program; @@ -33,7 +33,7 @@ Label labels[256]; char opcodes[][4] = { "BRK", "RTS", "LIT", "POP", "DUP", "SWP", "OVR", "ROT", - "JMI", "JSI", "JMZ", "JSZ", "EQU", "NEQ", "GTH", "LTH", + "JMU", "JSU", "JMC", "JSC", "EQU", "NEQ", "GTH", "LTH", "AND", "ORA", "ROL", "ROR", "ADD", "SUB", "MUL", "DIV"}; /* clang-format on */ @@ -112,7 +112,7 @@ shex(char *s) /* string to num */ void pushprg(Uint8 hex) { - p.data[p.len++] = hex; + p.data[p.ptr++] = hex; } void @@ -151,13 +151,13 @@ addlabel(char *id, Uint8 addr) Label *l = &labels[labelslen++]; scpy(suca(id), l->name, LABELIDLEN); l->addr = addr; - printf("new label: %s=%02x\n", l->name, l->addr); + printf("New label: %s[0x%02x]\n", l->name, l->addr); } void addconst(char *id, Uint8 value) { - printf("new const: %s=%02x\n", id, value); + printf("New const: %s[%02x]\n", id, value); } Label * @@ -181,18 +181,13 @@ findop(char *s) } int -getlength(char *w) +ismarker(char *w) { - if(findop(w) || scmp(w, "BRK")) return 1; - if(w[0] == '.') return 3; - if(w[0] == ':') return 0; - if(sihx(w)) { return slen(w) / 2 + 2; } - printf("Unknown length %s\n", w); - return 0; + return w[0] == '(' || w[0] == ')' || w[0] == '{' || w[0] == '}'; } int -comment(char *w, int *skip) +iscomment(char *w, int *skip) { if(w[0] == '>') { *skip = 0; @@ -203,15 +198,31 @@ comment(char *w, int *skip) return 0; } +int +getlength(char *w) +{ + if(findop(w) || scmp(w, "BRK")) return 1; + if(w[0] == '.') return 3; + if(w[0] == ':') return 0; + if(w[0] == ';') return 0; + if(w[0] == '@') return 0; + if(sihx(w)) { return slen(w) / 2 + 2; } + if(ismarker(w)) return 0; + printf("Unknown length %s\n", w); + return 0; +} + void pass1(FILE *f) { int skip = 0; int addr = 0; + int vars = 0; char word[64]; while(fscanf(f, "%s", word) == 1) { - if(comment(word, &skip)) continue; + if(iscomment(word, &skip)) continue; if(word[0] == ':') addlabel(word + 1, addr); + if(word[0] == ';') addlabel(word + 1, vars++); addr += getlength(word); } rewind(f); @@ -226,9 +237,12 @@ pass2(FILE *f) Uint8 op = 0; Label *l; if(word[0] == ':') continue; + if(word[0] == ';') continue; suca(word); - if(comment(word, &skip)) continue; - if((op = findop(word)) || scmp(word, "BRK")) + if(iscomment(word, &skip) || ismarker(word)) continue; + if(word[0] == '@') + p.ptr = shex(word + 1); + else if((op = findop(word)) || scmp(word, "BRK")) pushprg(op); else if((l = findlabel(word + 1))) pushlabel(l);