From 5d2025d7e8a0ac4dcc4ebea7d8e8b2ebd3ee49f1 Mon Sep 17 00:00:00 2001 From: neauoire Date: Sat, 6 Feb 2021 10:39:13 -0800 Subject: [PATCH] Hello world with strlen --- README.md | 4 +++ examples/core.usm | 17 ++++++---- examples/hello.usm | 32 ++++++++++++++++++ uxn.c | 81 +++++++++++++++++++++++++++++++--------------- uxnasm.c | 41 ++++++++++++++--------- 5 files changed, 127 insertions(+), 48 deletions(-) create mode 100644 examples/hello.usm diff --git a/README.md b/README.md index de053ee..85aa43f 100644 --- a/README.md +++ b/README.md @@ -27,6 +27,10 @@ cc uxn.c -std=c89 -Os -DNDEBUG -g0 -s -Wall -Wno-unknown-pragmas -o uxn - `|0010`, move to position in the program - `"hello`, push literal bytes for word "hello" +### Operator modes + +- `,1234 ,0001 ADD^`, 16-bits operators have the short flag `^`. + ``` ( hello world ) diff --git a/examples/core.usm b/examples/core.usm index ebc3f1b..3bebf29 100644 --- a/examples/core.usm +++ b/examples/core.usm @@ -6,14 +6,19 @@ |0100 @RESET -"hello +@word1 "hello_word ( len: 0x0b ) @loop - ,dev1w STR - ,incr JSU ( call incr ) - ,05 NEQ ,loop ROT JSC + ,dev1w STR ( write to stdout ) + ,incr JSU ( increment itr ) + ,word1 ,strlen JSU ( get strlen ) + NEQ ,loop ROT JSC ( loop != strlen ) -BRK ( RESET ) +BRK + +@strlen + ,0001 ADD^ PEK + RTS @incr ,iterator LDR @@ -21,7 +26,7 @@ BRK ( RESET ) ,iterator STR ,iterator LDR RTS - + |c000 @FRAME BRK |d000 @ERROR BRK |FFFA .RESET .FRAME .ERROR diff --git a/examples/hello.usm b/examples/hello.usm new file mode 100644 index 0000000..3bebf29 --- /dev/null +++ b/examples/hello.usm @@ -0,0 +1,32 @@ +( hello world ) + +;iterator +:dev1r FFF0 +:dev1w FFF1 + +|0100 @RESET + +@word1 "hello_word ( len: 0x0b ) + +@loop + ,dev1w STR ( write to stdout ) + ,incr JSU ( increment itr ) + ,word1 ,strlen JSU ( get strlen ) + NEQ ,loop ROT JSC ( loop != strlen ) + +BRK + +@strlen + ,0001 ADD^ PEK + RTS + +@incr + ,iterator LDR + ,01 ADD + ,iterator STR + ,iterator LDR + RTS + +|c000 @FRAME BRK +|d000 @ERROR BRK +|FFFA .RESET .FRAME .ERROR diff --git a/uxn.c b/uxn.c index 562399d..fd7c31b 100644 --- a/uxn.c +++ b/uxn.c @@ -12,7 +12,7 @@ WITH REGARD TO THIS SOFTWARE. */ #define FLAG_HALT 0x01 -#define FLAG_ZERO 0x02 +#define FLAG_SHORT 0x02 #define FLAG_CARRY 0x04 #define FLAG_TRAPS 0x08 @@ -96,6 +96,7 @@ Uint8 rampeek8(Uint16 s) { return cpu.ram.dat[s] & 0xff; } Uint8 mempeek8(Uint16 s) { return cpu.rom.dat[s]; } Uint16 mempeek16(Uint16 s) { return (cpu.rom.dat[s] << 8) + (cpu.rom.dat[s+1] & 0xff); } void wspush8(Uint8 b) { cpu.wst.dat[cpu.wst.ptr++] = b; } +void wspush16(Uint16 s) { wspush8(s >> 8); wspush8(s & 0xff); } Uint8 wspop8(void) { return cpu.wst.dat[--cpu.wst.ptr]; } Uint16 wspop16(void) { return wspop8() + (wspop8() << 8); } Uint8 wspeek8(void) { return cpu.wst.dat[cpu.wst.ptr - 1]; } @@ -116,24 +117,31 @@ void op_jmc() { if(wspop8()) op_jmu(); } void op_jsc() { if(wspop8()) op_jsu(); } void op_equ() { wspush8(wspop8() == wspop8()); } void op_neq() { wspush8(wspop8() != wspop8()); } -void op_gth() { wspush8(wspop8() < wspop8()); } -void op_lth() { wspush8(wspop8() > wspop8()); } -void op_and() { wspush8(wspop8() & wspop8()); } -void op_ora() { wspush8(wspop8() | wspop8()); } +void op_gth() { wspush8(wspop8() < wspop8()); } +void op_lth() { wspush8(wspop8() > wspop8()); } +void op_and() { wspush8(wspop8() & wspop8()); } +void op_ora() { wspush8(wspop8() | wspop8()); } void op_rol() { wspush8(wspop8() << 1); } void op_ror() { wspush8(wspop8() >> 1); } -void op_add() { wspush8(wspop8() + wspop8()); } +void op_add() { + if(getflag(FLAG_SHORT)) + wspush16(wspop16() + wspop16()); + else + wspush8(wspop8() + wspop8()); +} void op_sub() { wspush8(wspop8() - wspop8()); } void op_mul() { wspush8(wspop8() * wspop8()); } void op_div() { wspush8(wspop8() / wspop8()); } void op_ldr() { wspush8(cpu.ram.dat[wspop16()]); } void op_str() { cpu.ram.dat[wspop16()] = wspop8(); } +void op_pek() { wspush8(cpu.rom.dat[wspop16()]); } +void op_pok() { printf("TODO:\n");} -void (*ops[])(void) = { +void (*ops[])() = { op_brk, op_rts, op_lit, op_drp, op_dup, op_swp, op_ovr, op_rot, 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, - op_ldr, op_str, op_brk, op_brk, op_brk, op_brk, op_brk, op_brk + op_ldr, op_str, op_pek, op_pok, op_brk, op_brk, op_brk, op_brk }; Uint8 opr[][2] = { @@ -162,9 +170,9 @@ reset(void) } int -error(char *name) +error(char *name, int id) { - printf("Error: %s, at 0x%04x\n", name, cpu.counter); + printf("Error: %s[%04x], at 0x%04x\n", name, id, cpu.counter); return 0; } @@ -177,31 +185,48 @@ device1(Uint8 *read, Uint8 *write) return 0; } +void +opc(Uint8 src, Uint8 *op, Uint8 *mode) +{ + *op = src; + *op &= ~(1 << 5); + *op &= ~(1 << 6); + *op &= ~(1 << 7); + *mode = src; + *mode &= ~(1 << 0); + *mode &= ~(1 << 1); + *mode &= ~(1 << 2); + *mode &= ~(1 << 3); +} + int eval(void) { Uint8 instr = cpu.rom.dat[cpu.rom.ptr++]; + Uint8 op, opmode; + /* when literal */ if(cpu.literal > 0) { wspush8(instr); cpu.literal--; return 1; } - if(instr < 32) { - if(cpu.wst.ptr < opr[instr][0]) - return error("Stack underflow"); - /* TODO stack overflow */ - (*ops[instr])(); - } - if(instr > 0x10) - setflag(FLAG_ZERO, 0); - if(cpu.counter == 128) { - return error("Reached bounds"); - } + /* when opcode */ + opc(instr, &op, &opmode); + setflag(FLAG_SHORT, (instr >> 5) & 1); + if((instr >> 6) & 1) + printf("Unused flag: %02x\n", instr); + if((instr >> 7) & 1) + printf("Unused flag: %02x\n", instr); + /* TODO: setflag(FLAG_B, (instr >> 6) & 1); */ + /* TODO: setflag(FLAG_C, (instr >> 7) & 1); */ + if(cpu.wst.ptr < opr[op][0]) + return error("Stack underflow", op); + (*ops[op])(); cpu.counter++; return 1; } -void +int start(FILE *f) { reset(); @@ -216,6 +241,8 @@ start(FILE *f) /* experimental */ if(cpu.ram.dat[0xfff1]) device1(&cpu.ram.dat[0xfff0], &cpu.ram.dat[0xfff1]); + if(cpu.counter > 256) + return error("Reached bounds", cpu.counter); } /*eval frame */ printf("\nPhase: frame\n"); @@ -227,10 +254,11 @@ start(FILE *f) printf("ended @ %d steps | ", cpu.counter); printf("hf: %x zf: %x cf: %x tf: %x\n", getflag(FLAG_HALT) != 0, - getflag(FLAG_ZERO) != 0, + getflag(FLAG_SHORT) != 0, getflag(FLAG_CARRY) != 0, getflag(FLAG_TRAPS) != 0); printf("\n"); + return 1; } int @@ -238,10 +266,11 @@ main(int argc, char *argv[]) { FILE *f; if(argc < 2) - return error("No input."); + return error("No input.", 0); if(!(f = fopen(argv[1], "rb"))) - return error("Missing input."); - start(f); + return error("Missing input.", 0); + if(!start(f)) + return error("Program error", 0); /* print result */ echos(&cpu.wst, 0x40, "stack"); echom(&cpu.ram, 0x40, "ram"); diff --git a/uxnasm.c b/uxnasm.c index 2fe65a6..a95331e 100644 --- a/uxnasm.c +++ b/uxnasm.c @@ -29,11 +29,11 @@ Label labels[256]; /* clang-format off */ -char opcodes[][4] = { +char ops[][4] = { "BRK", "RTS", "LIT", "POP", "DUP", "SWP", "OVR", "ROT", "JMU", "JSU", "JMC", "JSC", "EQU", "NEQ", "GTH", "LTH", "AND", "ORA", "ROL", "ROR", "ADD", "SUB", "MUL", "DIV", - "LDR", "STR", "---", "---", "---", "---", "---", "---" + "LDR", "STR", "PEK", "POK", "---", "---", "---", "---" }; /* clang-format on */ @@ -162,6 +162,27 @@ findlabel(char *s) return NULL; } +Uint8 +findop(char *s) +{ + int i; + for(i = 0; i < 32; ++i) { + int m = 0; + if(ops[i][0] != s[0]) continue; + if(ops[i][1] != s[1]) continue; + if(ops[i][2] != s[2]) continue; + while(s[3 + m]) { + char c = s[3 + m]; + if(c == '^') i |= (1 << 5); /* mode: 16 bits */ + if(c == '&') i |= (1 << 6); /* mode: unused */ + if(c == '~') i |= (1 << 7); /* mode: unused */ + m++; + } + return i; + } + return 0; +} + #pragma mark - Parser int @@ -171,16 +192,6 @@ error(char *name, char *id) return 0; } -Uint8 -findop(char *s) -{ - int i; - for(i = 0; i < 32; ++i) - if(scmp(opcodes[i], s)) - return i; - return 0; -} - int makelabel(char *id, Uint16 addr) { @@ -210,7 +221,6 @@ pass1(FILE *f) char w[64]; while(fscanf(f, "%s", w) == 1) { if(iscomment(w, &skip)) continue; - suca(w); if(w[0] == '@' && !makelabel(w + 1, addr)) return error("Pass1 failed", w); if(w[0] == ';' && !makelabel(w + 1, vars++)) @@ -253,7 +263,6 @@ pass2(FILE *f) Label *l; if(w[0] == '@') continue; if(w[0] == ';') continue; - suca(w); if(iscomment(w, &skip)) continue; if(w[0] == '|') p.ptr = shex(w + 1); @@ -261,10 +270,10 @@ pass2(FILE *f) fscanf(f, "%s", w); else if(w[0] == '"') pushword(w + 1); - else if((op = findop(w)) || scmp(w, "BRK")) - pushbyte(op, 0); else if((l = findlabel(w + 1))) pushshort(l->addr, w[0] == ','); + else if((op = findop(w)) || scmp(w, "BRK")) + pushbyte(op, 0); else if(sihx(w + 1) && slen(w + 1) == 2) pushbyte(shex(w + 1), w[0] == ','); else if(sihx(w + 1) && slen(w + 1) == 4)