diff --git a/README.md b/README.md index 38fef20..5764636 100644 --- a/README.md +++ b/README.md @@ -34,6 +34,8 @@ evaluxn(u, u->vframe); /* Each frame - `,literal`, push label value to stack, prefixed with `LIT LEN`. - `.pointer`, push label value to stack. +- `+1234`, push positive lit signed value to stack. +- `-abcd`, push negative lit signed value to stack. ### Special @@ -82,14 +84,12 @@ BRK ## TODOs -- Implement signed flag to operators. +- Line routine - On-screen debugger. - Auto-advance ldr? - Getting rid of IOR/IOW would be nice.. - Sending from the wst to the rst, balance mode/flag? - Device that works like an extra memory bank -- Line routine -- LineRect routine - Draw a chr sprite. ## Refs diff --git a/assembler.c b/assembler.c index 4f02b7e..7bf7928 100644 --- a/assembler.c +++ b/assembler.c @@ -12,7 +12,9 @@ WITH REGARD TO THIS SOFTWARE. */ typedef unsigned char Uint8; +typedef signed char Sint8; typedef unsigned short Uint16; +typedef signed short Sint16; typedef struct { int ptr; @@ -61,6 +63,7 @@ pushbyte(Uint8 b, int lit) void pushshort(Uint16 s, int lit) { + printf("%04x[%d]\n", s, lit); if(lit) { pushbyte(0x03, 0); pushbyte(0x02, 0); @@ -100,7 +103,7 @@ findoperator(char *s) continue; while(s[3 + m]) { if(s[3 + m] == '^') i |= (1 << 5); /* mode: 16 bits */ - if(s[3 + m] == '~') i |= (1 << 6); /* mode: signed */ + if(s[3 + m] == '!') i |= (1 << 6); /* mode: signed */ if(s[3 + m] == '?') i |= (1 << 7); /* mode: conditional */ m++; } @@ -124,6 +127,8 @@ makelabel(char *name, Uint16 addr) Label *l; if(findlabel(name)) return error("Label duplicate", name); + if(sihx(name)) + return error("Label name is hex number", name); l = &labels[labelslen++]; l->addr = addr; scpy(name, l->name, 64); @@ -176,6 +181,8 @@ pass1(FILE *f) case '"': addr += slen(w + 1) + 2; break; case '#': addr += 4; break; case '.': addr += 2; break; + case '+': /* signed positive */ + case '-': /* signed negative */ case ',': addr += (sihx(w + 1) && slen(w + 1) == 2 ? 1 : 2); addr += (sihx(w + 1) ? slen(w + 1) / 2 : 2); @@ -198,26 +205,22 @@ pass2(FILE *f) Label *l; if(w[0] == '@') continue; if(cmnt(w, &skip)) continue; - if(w[0] == '|') - p.ptr = shex(w + 1); - else if(w[0] == ':') - fscanf(f, "%s", w); - else if(w[0] == ';') - fscanf(f, "%s", w); - else if(w[0] == '"') - pushtext(w + 1); - else if(w[0] == '#') - pushshort(shex(w + 1) & 0xff, 1); - else if((l = findlabel(w + 1))) - pushshort(l->addr, w[0] == ','); - else if((op = findoperator(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) - pushshort(shex(w + 1), w[0] == ','); - else - return error("Unknown label", w); + /* clang-format off */ + if(w[0] == '|') p.ptr = shex(w + 1); + else if(w[0] == ':') fscanf(f, "%s", w); + else if(w[0] == ';') fscanf(f, "%s", w); + else if(w[0] == '+' && sihx(w + 1) && slen(w + 1) == 2) pushbyte((Sint8)shex(w + 1), 1); + else if(w[0] == '+' && sihx(w + 1) && slen(w + 1) == 4) pushshort((Sint16)shex(w + 1), 1); + else if(w[0] == '-' && sihx(w + 1) && slen(w + 1) == 2) pushbyte((Sint8)(shex(w + 1) * -1), 1); + else if(w[0] == '-' && sihx(w + 1) && slen(w + 1) == 4) pushshort((Sint16)(shex(w + 1) * -1), 1); + else if(w[0] == '"') pushtext(w + 1); + else if(w[0] == '#') pushshort(shex(w + 1) & 0xff, 1); + else if((l = findlabel(w + 1))) pushshort(l->addr, w[0] == ','); + else if((op = findoperator(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) pushshort(shex(w + 1), w[0] == ','); + else return error("Unknown label", w); + /* clang-format on */ } return 1; } diff --git a/build.sh b/build.sh index fe00044..eba54f1 100755 --- a/build.sh +++ b/build.sh @@ -24,5 +24,5 @@ rm -f ./bin/emulator 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 -L/usr/local/lib -lSDL2 -o bin/emulator # run -./bin/assembler examples/test.usm bin/boot.rom +./bin/assembler examples/line.usm bin/boot.rom ./bin/emulator bin/boot.rom diff --git a/etc/usm.sublime-syntax b/etc/usm.sublime-syntax index 6f484a9..3c288b8 100644 --- a/etc/usm.sublime-syntax +++ b/etc/usm.sublime-syntax @@ -21,6 +21,12 @@ contexts: - match: '\|(\S+)\s?' scope: punctuation.definition pop: true + - match: '\+(\S+)\s?' + scope: keyword.control + pop: true + - match: '\-(\S+)\s?' + scope: keyword.control + pop: true strings: - match: '\:(\S+)\s?' @@ -35,6 +41,9 @@ contexts: - match: '\,(\S+)\s?' scope: keyword.control pop: true + - match: '\#(\S+)\s?' + scope: keyword.control + pop: true - match: '\.(\S+)\s?' scope: keyword.control pop: true diff --git a/examples/benchmark.usm b/examples/benchmark.usm index d9963bd..8ad7b56 100644 --- a/examples/benchmark.usm +++ b/examples/benchmark.usm @@ -22,6 +22,18 @@ ,1234 ,1233 GTH^ #0e STR ,1234 ,1235 LTH^ #0f STR +BRK + +@diff8 ( result of abs sub ) + OVR OVR GTH ,diff8sub ROT JMP? POP^ + SWP @diff8sub SUB +RTS + +@diff16 ( result of abs sub16 ) + OVR^ OVR^ GTH^ ,diff16sub ROT JMP? POP^ + SWP^ @diff16sub SUB^ +RTS + |c000 @FRAME BRK |d000 @ERROR BRK |FFFA .RESET .FRAME .ERROR diff --git a/examples/line.usm b/examples/line.usm index c7bebe4..bc053c5 100644 --- a/examples/line.usm +++ b/examples/line.usm @@ -5,6 +5,8 @@ ;x_ 2 ;y_ 2 ;x0 2 ;y0 2 ;x1 2 ;y1 2 ;color 1 +;dx 2 ;dy 2 ;err 2 ;err2 2 + |0100 @RESET ( set dev/write to screen ) @@ -13,9 +15,10 @@ ( init positions ) ,0020 ,x0 STR^ ,0018 ,y0 STR^ - ,0030 ,x1 STR^ ,0048 ,y1 STR^ + ,0060 ,x1 STR^ ,0048 ,y1 STR^ ,x0 LDR^ ,x_ STR^ ,y0 LDR^ ,y_ STR^ + ( draw control points ) ,02 ,color STR ,x0 LDR^ ,y0 LDR^ ,putpixel JSR @@ -39,6 +42,11 @@ BRK ,00 IOW ( redraw byte ) RTS +@diff16 + OVR^ OVR^ GTH^ ,diff16sub ROT JMP? POP^ + SWP^ @diff16sub SUB^ +RTS + |c000 @FRAME BRK |d000 @ERROR BRK |FFFA .RESET .FRAME .ERROR diff --git a/examples/test.usm b/examples/test.usm index ef17d85..31d1282 100644 --- a/examples/test.usm +++ b/examples/test.usm @@ -3,13 +3,17 @@ :dev/r fff8 ( std read port ) :dev/w fff9 ( std write port ) +;x 2 + |0100 @RESET - ,00 ,dev/w STR ( set dev/write to console ) + ,00 ,dev/w STR ( set dev/write to console ) + -12 +02 LTH! BRK + |c000 @FRAME BRK |d000 @ERROR BRK |FFFA .RESET .FRAME .ERROR diff --git a/uxn.c b/uxn.c index 31c9a0f..6d284da 100644 --- a/uxn.c +++ b/uxn.c @@ -33,7 +33,7 @@ Uint16 peek16(St8 *s, Uint8 a) { return peek8(s, a * 2) + (peek8(s, a * 2 + 1) < void op_brk(Uxn *u) { setflag(&u->status,FLAG_HALT, 1); } void op_li1(Uxn *u) { u->literal += 1; } void op_lix(Uxn *u) { u->literal += u->ram.dat[u->ram.ptr++]; } -void op_nop(Uxn *u) { printf("%02x\n", pop8(&u->wst)); } +void op_nop(Uxn *u) { printf("0x%02x ", pop8(&u->wst)); } void op_ior(Uxn *u) { Device *dev = &u->dev[mempeek8(&u->ram, u->devr)]; if(dev) push8(&u->wst, dev->read(dev, pop8(&u->wst))); } void op_iow(Uxn *u) { Uint8 a = pop8(&u->wst); Device *dev = &u->dev[mempeek8(&u->ram, u->devw)]; if(dev) dev->write(dev, a); } void op_ldr(Uxn *u) { Uint16 a = pop16(&u->wst); push8(&u->wst, mempeek8(&u->ram, a)); } @@ -52,14 +52,14 @@ void op_and(Uxn *u) { Uint8 a = pop8(&u->wst), b = pop8(&u->wst); push8(&u->wst, void op_ora(Uxn *u) { Uint8 a = pop8(&u->wst), b = pop8(&u->wst); push8(&u->wst, b | a); } void op_rol(Uxn *u) { Uint8 a = pop8(&u->wst), b = pop8(&u->wst); push8(&u->wst, b << a); } /* Arithmetic */ -void op_add(Uxn *u) { Uint8 a = pop8(&u->wst), b = pop8(&u->wst); push8(&u->wst, b + a); } -void op_sub(Uxn *u) { Uint8 a = pop8(&u->wst), b = pop8(&u->wst); push8(&u->wst, b - a); } -void op_mul(Uxn *u) { Uint8 a = pop8(&u->wst), b = pop8(&u->wst); push8(&u->wst, b * a); } -void op_div(Uxn *u) { Uint8 a = pop8(&u->wst), b = pop8(&u->wst); push8(&u->wst, b / a); } -void op_equ(Uxn *u) { Uint8 a = pop8(&u->wst), b = pop8(&u->wst); push8(&u->wst, b == a); } -void op_neq(Uxn *u) { Uint8 a = pop8(&u->wst), b = pop8(&u->wst); push8(&u->wst, b != a); } -void op_gth(Uxn *u) { Uint8 a = pop8(&u->wst), b = pop8(&u->wst); push8(&u->wst, b > a); } -void op_lth(Uxn *u) { Uint8 a = pop8(&u->wst), b = pop8(&u->wst); push8(&u->wst, b < a); } +void op_add(Uxn *u) { Uint8 a = pop8(&u->wst), b = pop8(&u->wst); push8(&u->wst, getflag(&u->status, FLAG_SIGN) ? (Sint8)b + (Sint8)a : b + a); } +void op_sub(Uxn *u) { Uint8 a = pop8(&u->wst), b = pop8(&u->wst); push8(&u->wst, getflag(&u->status, FLAG_SIGN) ? (Sint8)b - (Sint8)a : b - a); } +void op_mul(Uxn *u) { Uint8 a = pop8(&u->wst), b = pop8(&u->wst); push8(&u->wst, getflag(&u->status, FLAG_SIGN) ? (Sint8)b * (Sint8)a : b * a); } +void op_div(Uxn *u) { Uint8 a = pop8(&u->wst), b = pop8(&u->wst); push8(&u->wst, getflag(&u->status, FLAG_SIGN) ? (Sint8)b / (Sint8)a : b / a); } +void op_equ(Uxn *u) { Uint8 a = pop8(&u->wst), b = pop8(&u->wst); push8(&u->wst, getflag(&u->status, FLAG_SIGN) ? (Sint8)b == (Sint8)a : b == a); } +void op_neq(Uxn *u) { Uint8 a = pop8(&u->wst), b = pop8(&u->wst); push8(&u->wst, getflag(&u->status, FLAG_SIGN) ? (Sint8)b != (Sint8)a : b != a); } +void op_gth(Uxn *u) { Uint8 a = pop8(&u->wst), b = pop8(&u->wst); push8(&u->wst, getflag(&u->status, FLAG_SIGN) ? (Sint8)b > (Sint8)a : b > a); } +void op_lth(Uxn *u) { Uint8 a = pop8(&u->wst), b = pop8(&u->wst); push8(&u->wst, getflag(&u->status, FLAG_SIGN) ? (Sint8)b < (Sint8)a : b < a); } /* --- */ void op_nop16(Uxn *u) { printf("%04x\n", pop16(&u->wst)); } void op_ior16(Uxn *u) { Uint8 a = pop8(&u->wst); Device *dev = &u->dev[mempeek8(&u->ram, u->devr)]; if(dev) push16(&u->wst, (dev->read(dev, a) << 8) + dev->read(dev, a + 1)); } @@ -76,14 +76,14 @@ void op_and16(Uxn *u) { Uint16 a = pop16(&u->wst), b = pop16(&u->wst); push16(&u void op_ora16(Uxn *u) { Uint16 a = pop16(&u->wst), b = pop16(&u->wst); push16(&u->wst, b | a); } void op_rol16(Uxn *u) { Uint16 a = pop16(&u->wst), b = pop16(&u->wst); push16(&u->wst, b << a); } /* Arithmetic(16-bits) */ -void op_add16(Uxn *u) { Uint16 a = pop16(&u->wst), b = pop16(&u->wst); push16(&u->wst, b + a); } -void op_sub16(Uxn *u) { Uint16 a = pop16(&u->wst), b = pop16(&u->wst); push16(&u->wst, b - a); } -void op_mul16(Uxn *u) { Uint16 a = pop16(&u->wst), b = pop16(&u->wst); push16(&u->wst, b * a); } -void op_div16(Uxn *u) { Uint16 a = pop16(&u->wst), b = pop16(&u->wst); push16(&u->wst, b / a); } -void op_equ16(Uxn *u) { Uint16 a = pop16(&u->wst), b = pop16(&u->wst); push8(&u->wst, b == a); } -void op_neq16(Uxn *u) { Uint16 a = pop16(&u->wst), b = pop16(&u->wst); push8(&u->wst, b != a); } -void op_gth16(Uxn *u) { Uint16 a = pop16(&u->wst), b = pop16(&u->wst); push8(&u->wst, b > a); } -void op_lth16(Uxn *u) { Uint16 a = pop16(&u->wst), b = pop16(&u->wst); push8(&u->wst, b < a); } +void op_add16(Uxn *u) { Uint16 a = pop16(&u->wst), b = pop16(&u->wst); push16(&u->wst, getflag(&u->status, FLAG_SIGN) ? (Sint8)b + (Sint8)a : b + a); } +void op_sub16(Uxn *u) { Uint16 a = pop16(&u->wst), b = pop16(&u->wst); push16(&u->wst, getflag(&u->status, FLAG_SIGN) ? (Sint8)b - (Sint8)a : b - a); } +void op_mul16(Uxn *u) { Uint16 a = pop16(&u->wst), b = pop16(&u->wst); push16(&u->wst, getflag(&u->status, FLAG_SIGN) ? (Sint8)b * (Sint8)a : b * a); } +void op_div16(Uxn *u) { Uint16 a = pop16(&u->wst), b = pop16(&u->wst); push16(&u->wst, getflag(&u->status, FLAG_SIGN) ? (Sint8)b / (Sint8)a : b / a); } +void op_equ16(Uxn *u) { Uint16 a = pop16(&u->wst), b = pop16(&u->wst); push8(&u->wst, getflag(&u->status, FLAG_SIGN) ? (Sint8)b == (Sint8)a : b == a); } +void op_neq16(Uxn *u) { Uint16 a = pop16(&u->wst), b = pop16(&u->wst); push8(&u->wst, getflag(&u->status, FLAG_SIGN) ? (Sint8)b != (Sint8)a : b != a); } +void op_gth16(Uxn *u) { Uint16 a = pop16(&u->wst), b = pop16(&u->wst); push8(&u->wst, getflag(&u->status, FLAG_SIGN) ? (Sint8)b > (Sint8)a : b > a); } +void op_lth16(Uxn *u) { Uint16 a = pop16(&u->wst), b = pop16(&u->wst); push8(&u->wst, getflag(&u->status, FLAG_SIGN) ? (Sint8)b < (Sint8)a : b < a); } void (*ops[])(Uxn *u) = { op_brk, op_nop, op_li1, op_lix, op_ior, op_iow, op_ldr, op_str, @@ -133,7 +133,7 @@ opcuxn(Uxn *u, Uint8 instr) { Uint8 op = instr & 0x1f; setflag(&u->status, FLAG_SHORT, (instr >> 5) & 1); - setflag(&u->status, FLAG_SIGN, (instr >> 6) & 1); /* usused */ + setflag(&u->status, FLAG_SIGN, (instr >> 6) & 1); setflag(&u->status, FLAG_COND, (instr >> 7) & 1); if(getflag(&u->status, FLAG_SHORT)) op += 32; diff --git a/uxn.h b/uxn.h index 142b15f..5bf33d3 100644 --- a/uxn.h +++ b/uxn.h @@ -12,7 +12,9 @@ WITH REGARD TO THIS SOFTWARE. */ typedef unsigned char Uint8; +typedef signed char Sint8; typedef unsigned short Uint16; +typedef signed short Sint16; #define FLAG_HALT 0x01 #define FLAG_SHORT 0x02