commit 24e67d34dace3205a92778028bcb75701492a0af
parent 34d4695db40066de60ca1bcb889c0fb62a10e15f
Author: neauoire <aliceffekt@gmail.com>
Date: Fri, 12 Feb 2021 16:18:52 -0800
Started implementing signed operations
Diffstat:
9 files changed, 83 insertions(+), 45 deletions(-)
diff --git 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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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