commit 1482e5662ddc1ce7973ee8ca22d8fcddad204f27
parent ba2e7aefa16de2488ff1e45f00a80ba5c1b767b7
Author: neauoire <aliceffekt@gmail.com>
Date: Sat, 30 Jan 2021 21:31:49 -0800
Added return stack
Diffstat:
M | README.md | | | 37 | +++++++++++++------------------------ |
M | example.usm | | | 18 | ++++++++++++++++-- |
M | uxn.c | | | 94 | +++++++++++++++++++++++++++++++++++++++++++++++-------------------------------- |
M | uxnasm.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);
}
}