uxn

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

commit 1482e5662ddc1ce7973ee8ca22d8fcddad204f27
parent ba2e7aefa16de2488ff1e45f00a80ba5c1b767b7
Author: neauoire <aliceffekt@gmail.com>
Date:   Sat, 30 Jan 2021 21:31:49 -0800

Added return stack

Diffstat:
MREADME.md | 37+++++++++++++------------------------
Mexample.usm | 18++++++++++++++++--
Muxn.c | 94+++++++++++++++++++++++++++++++++++++++++++++++--------------------------------
Muxnasm.c | 75++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------
4 files changed, 153 insertions(+), 71 deletions(-)

diff --git a/README.md b/README.md @@ -10,6 +10,10 @@ cc uxn.c -std=c89 -Os -DNDEBUG -g0 -s -Wall -Wno-unknown-pragmas -o uxn ## Assembly Syntax +- `:label`, a named offset +- `+literal`, a numeric value +- `.pointer`, pointer to a label + ``` < comment > @@ -30,31 +34,16 @@ $01 < pointer8 > :label ADD RTS ``` -## Design - -### CPU - -- Build stack with pointer -- Print stack -- Build memory - -### PPU - -### Assembly - -#### Addressing - -- `label`, a named offset[TODO] -- `literal`, a numeric value -- `pointer`, pointer to an address[TODO] - -### Assembler - - -### Emulator - -- SDL Layer +## TODOs +- Implement addressing +- Implement 16 bits operations +- Jumps should be relative +- Catch overflow/underflow +- Implement literals like `[2]`, and `[ 2 3 ]`. +- Audo-detect literals length. +- SDL Layer Emulator +- Build PPU ## Refs diff --git a/example.usm b/example.usm @@ -1,5 +1,18 @@ < comment > -[3 1 2 3 ] pop dup swp ovr rot +.deep JSR [4 6 7 8 9 ] BRK -brk +:deep + [2 1 2 ] + .deeper JSR + RTS + +:deeper + [3 3 4 5 ] + .deeperyet JSR + RTS + +:deeperyet + [2 aa bb ] + RTS + +\ No newline at end of file diff --git a/uxn.c b/uxn.c @@ -24,8 +24,9 @@ typedef struct { Uint8 literal; Uint8 status, counter; Uint8 memory[STACK_DEPTH]; - Uint8 mptr, sptr; + Uint8 mptr, sptr, rsptr; Uint8 stack[STACK_DEPTH]; + Uint8 rstack[STACK_DEPTH]; Uint8 address[STACK_DEPTH]; } Computer; @@ -61,20 +62,66 @@ echo(Uint8 *s, Uint8 len, char *name) printf("\n\n"); } -#pragma mark - Operations +void +spush(Uint8 v) +{ + cpu.stack[cpu.sptr++] = v; +} + +Uint8 +spop(void) +{ + return cpu.stack[--cpu.sptr]; +} void -op_push(Uint8 *s, Uint8 *ptr, Uint8 v) +rspush(Uint8 v) { - s[(*ptr)++] = v; + cpu.rstack[cpu.rsptr++] = v; } Uint8 -op_pop(Uint8 *s, Uint8 *ptr) +rspop(void) { - return s[--*ptr]; + return cpu.rstack[--cpu.rsptr]; } +#pragma mark - Operations + +/* clang-format off */ + +void op_brk() { setflag(FLAG_HALT, 1); } +void op_lit() { cpu.literal += cpu.memory[cpu.mptr++]; } +void op_nop() { } +void op_drp() { spop(); } +void op_dup() { spush(cpu.stack[cpu.sptr - 1]); } +void op_swp() { Uint8 b = spop(), a = spop(); spush(b); spush(a); } +void op_ovr() { spush(cpu.stack[cpu.sptr - 2]); } +void op_rot() { Uint8 c = spop(),b = spop(),a = spop(); spush(b); spush(c); spush(a); } +void op_jmp() { cpu.mptr = spop(); } +void op_jsr() { rspush(cpu.mptr); cpu.mptr = spop(); } +void op_jeq() { if(getflag(FLAG_ZERO)) cpu.mptr = spop(); } +void op_rts() { cpu.mptr = rspop(); } +void op_equ() { setflag(FLAG_ZERO, spop() == spop()); } +void op_neq() { setflag(FLAG_ZERO, spop() != spop()); } +void op_lth() { setflag(FLAG_ZERO, spop() < spop()); } +void op_gth() { setflag(FLAG_ZERO, spop() > spop()); } +void op_and() { spush(spop() & spop()); } +void op_ora() { spush(spop() | spop()); } +void op_rol() { spush(spop() << 1); } +void op_ror() { spush(spop() >> 1); } +void op_add() { spush(spop() + spop()); } +void op_sub() { spush(spop() - spop()); } +void op_mul() { spush(spop() * spop()); } +void op_div() { spush(spop() / spop()); } + +void (*ops[])(void) = { + op_brk, op_lit, op_nop, op_drp, op_dup, op_swp, op_ovr, op_rot, + op_jmp, op_jsr, op_jeq, op_rts, op_equ, op_neq, op_gth, op_lth, + op_and, op_ora, op_rol, op_ror, op_add, op_sub, op_mul, op_div}; + +/* clang-format on */ + void reset(void) { @@ -105,42 +152,13 @@ void eval() { Uint8 instr = cpu.memory[cpu.mptr++]; - Uint8 a, b, c; if(cpu.literal > 0) { - printf("push: %02x[%d](%d)\n", instr, cpu.literal, cpu.sptr); - op_push(cpu.stack, &cpu.sptr, instr); + spush(instr); cpu.literal--; return; } - switch(instr) { - case 0x0: setflag(FLAG_HALT, 1); break; - case 0x1: cpu.literal += cpu.memory[cpu.mptr++]; break; - case 0x2: printf("??\n"); break; - case 0x3: /* pop */ - op_pop(cpu.stack, &cpu.sptr); - break; - case 0x4: /* dup */ - op_push(cpu.stack, &cpu.sptr, cpu.stack[cpu.sptr - 1]); - break; - case 0x5: /* swp */ - b = op_pop(cpu.stack, &cpu.sptr); - a = op_pop(cpu.stack, &cpu.sptr); - op_push(cpu.stack, &cpu.sptr, b); - op_push(cpu.stack, &cpu.sptr, a); - break; - case 0x6: /* ovr */ - op_push(cpu.stack, &cpu.sptr, cpu.stack[cpu.sptr - 2]); - break; - case 0x7: /* rot */ - c = op_pop(cpu.stack, &cpu.sptr); - b = op_pop(cpu.stack, &cpu.sptr); - a = op_pop(cpu.stack, &cpu.sptr); - op_push(cpu.stack, &cpu.sptr, b); - op_push(cpu.stack, &cpu.sptr, c); - op_push(cpu.stack, &cpu.sptr, a); - break; - default: printf("Unknown instruction: #%02x\n", instr); - } + if(instr < 24) + (*ops[instr])(); } void diff --git a/uxnasm.c b/uxnasm.c @@ -12,6 +12,7 @@ WITH REGARD TO THIS SOFTWARE. */ #define PRGLEN 256 +#define LABELIDLEN 32 typedef unsigned char Uint8; @@ -20,7 +21,13 @@ typedef struct { Uint8 data[PRGLEN]; } Program; -char labels[256][16]; +typedef struct { + Uint8 addr; + char name[LABELIDLEN]; +} Label; + +int labelslen; +Label labels[256]; char opcodes[][4] = { "BRK", @@ -40,6 +47,14 @@ char opcodes[][4] = { "NEQ", "LTH", "GTH", + "---", + "---", + "---", + "---", + "ADD", + "SUB", + "MUL", + "DIV" /* */}; Program p; @@ -57,6 +72,16 @@ scmp(char *a, char *b) /* string compare */ } char * +scpy(char *src, char *dst, int len) /* string copy */ +{ + int i = 0; + while((dst[i] = src[i]) && i < len - 2) + i++; + dst[i + 1] = '\0'; + return dst; +} + +char * suca(char *s) /* string to uppercase */ { int i = 0; @@ -72,7 +97,7 @@ sihx(char *s) int i = 0; char c; while((c = s[i++])) - if(!(c >= '0' && c <= '9') && !(c >= 'A' && c <= 'F')) + if(!(c >= '0' && c <= '9') && !(c >= 'a' && c <= 'f') && !(c >= 'A' && c <= 'F')) return 0; return 1; } @@ -87,6 +112,8 @@ shex(char *s) /* string to num */ n = n * 16 + (c - '0'); else if(c >= 'A' && c <= 'F') n = n * 16 + 10 + (c - 'A'); + else if(c >= 'a' && c <= 'f') + n = n * 16 + 10 + (c - 'f'); return n; } @@ -101,7 +128,10 @@ addprg(Uint8 hex) void addlabel(char *id, Uint8 addr) { - printf("new label: %s=%02x\n", id, addr); + Label *l = &labels[labelslen++]; + scpy(suca(id), l->name, LABELIDLEN); + l->addr = addr; + printf("new label: %s=%02x\n", l->name, l->addr); } void @@ -110,17 +140,40 @@ addconst(char *id, Uint8 value) printf("new const: %s=%02x\n", id, value); } +Label * +findlabel(char *s) +{ + int i; + for(i = 0; i < labelslen; ++i) + if(scmp(labels[i].name, s)) + return &labels[i]; + return NULL; +} + Uint8 findop(char *s) { int i; - for(i = 0; i < 16; ++i) + for(i = 0; i < 24; ++i) if(scmp(opcodes[i], s)) return i; 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 2; + if(sihx(w)) return 1; + if(w[0] == ']') return 0; + printf("Unknown length %s\n", w); + return 0; +} + +int comment(char *w, int *skip) { if(w[0] == '>') { @@ -136,10 +189,12 @@ void pass1(FILE *f) { int skip = 0; + int addr = 0; char word[64]; while(fscanf(f, "%s", word) == 1) { - if(comment(word, &skip)) - continue; + if(comment(word, &skip)) continue; + if(word[0] == ':') addlabel(word + 1, addr); + addr += getlength(word); } rewind(f); } @@ -151,6 +206,8 @@ pass2(FILE *f) char word[64]; while(fscanf(f, "%s", word) == 1) { Uint8 op; + Label *l; + if(word[0] == ':') continue; suca(word); if(comment(word, &skip)) continue; if(word[0] == ']') continue; @@ -167,7 +224,11 @@ pass2(FILE *f) addprg(shex(word)); else if(scmp(word, "BRK")) addprg(0x00); - else + else if((l = findlabel(word + 1))) { + addprg(0x01); + addprg(1); + addprg(l->addr); + } else printf("unknown: %s\n", word); } }