| ... | ... |
@@ -34,6 +34,8 @@ evaluxn(u, u->vframe); /* Each frame |
| 34 | 34 |
|
| 35 | 35 |
- `,literal`, push label value to stack, prefixed with `LIT LEN`. |
| 36 | 36 |
- `.pointer`, push label value to stack. |
| 37 |
+- `+1234`, push positive lit signed value to stack. |
|
| 38 |
+- `-abcd`, push negative lit signed value to stack. |
|
| 37 | 39 |
|
| 38 | 40 |
### Special |
| 39 | 41 |
|
| ... | ... |
@@ -82,14 +84,12 @@ BRK |
| 82 | 84 |
|
| 83 | 85 |
## TODOs |
| 84 | 86 |
|
| 85 |
-- Implement signed flag to operators. |
|
| 87 |
+- Line routine |
|
| 86 | 88 |
- On-screen debugger. |
| 87 | 89 |
- Auto-advance ldr? |
| 88 | 90 |
- Getting rid of IOR/IOW would be nice.. |
| 89 | 91 |
- Sending from the wst to the rst, balance mode/flag? |
| 90 | 92 |
- Device that works like an extra memory bank |
| 91 |
-- Line routine |
|
| 92 |
-- LineRect routine |
|
| 93 | 93 |
- Draw a chr sprite. |
| 94 | 94 |
|
| 95 | 95 |
## Refs |
| ... | ... |
@@ -12,7 +12,9 @@ WITH REGARD TO THIS SOFTWARE. |
| 12 | 12 |
*/ |
| 13 | 13 |
|
| 14 | 14 |
typedef unsigned char Uint8; |
| 15 |
+typedef signed char Sint8; |
|
| 15 | 16 |
typedef unsigned short Uint16; |
| 17 |
+typedef signed short Sint16; |
|
| 16 | 18 |
|
| 17 | 19 |
typedef struct {
|
| 18 | 20 |
int ptr; |
| ... | ... |
@@ -61,6 +63,7 @@ pushbyte(Uint8 b, int lit) |
| 61 | 63 |
void |
| 62 | 64 |
pushshort(Uint16 s, int lit) |
| 63 | 65 |
{
|
| 66 |
+ printf("%04x[%d]\n", s, lit);
|
|
| 64 | 67 |
if(lit) {
|
| 65 | 68 |
pushbyte(0x03, 0); |
| 66 | 69 |
pushbyte(0x02, 0); |
| ... | ... |
@@ -100,7 +103,7 @@ findoperator(char *s) |
| 100 | 103 |
continue; |
| 101 | 104 |
while(s[3 + m]) {
|
| 102 | 105 |
if(s[3 + m] == '^') i |= (1 << 5); /* mode: 16 bits */ |
| 103 |
- if(s[3 + m] == '~') i |= (1 << 6); /* mode: signed */ |
|
| 106 |
+ if(s[3 + m] == '!') i |= (1 << 6); /* mode: signed */ |
|
| 104 | 107 |
if(s[3 + m] == '?') i |= (1 << 7); /* mode: conditional */ |
| 105 | 108 |
m++; |
| 106 | 109 |
} |
| ... | ... |
@@ -124,6 +127,8 @@ makelabel(char *name, Uint16 addr) |
| 124 | 127 |
Label *l; |
| 125 | 128 |
if(findlabel(name)) |
| 126 | 129 |
return error("Label duplicate", name);
|
| 130 |
+ if(sihx(name)) |
|
| 131 |
+ return error("Label name is hex number", name);
|
|
| 127 | 132 |
l = &labels[labelslen++]; |
| 128 | 133 |
l->addr = addr; |
| 129 | 134 |
scpy(name, l->name, 64); |
| ... | ... |
@@ -176,6 +181,8 @@ pass1(FILE *f) |
| 176 | 181 |
case '"': addr += slen(w + 1) + 2; break; |
| 177 | 182 |
case '#': addr += 4; break; |
| 178 | 183 |
case '.': addr += 2; break; |
| 184 |
+ case '+': /* signed positive */ |
|
| 185 |
+ case '-': /* signed negative */ |
|
| 179 | 186 |
case ',': |
| 180 | 187 |
addr += (sihx(w + 1) && slen(w + 1) == 2 ? 1 : 2); |
| 181 | 188 |
addr += (sihx(w + 1) ? slen(w + 1) / 2 : 2); |
| ... | ... |
@@ -198,26 +205,22 @@ pass2(FILE *f) |
| 198 | 205 |
Label *l; |
| 199 | 206 |
if(w[0] == '@') continue; |
| 200 | 207 |
if(cmnt(w, &skip)) continue; |
| 201 |
- if(w[0] == '|') |
|
| 202 |
- p.ptr = shex(w + 1); |
|
| 203 |
- else if(w[0] == ':') |
|
| 204 |
- fscanf(f, "%s", w); |
|
| 205 |
- else if(w[0] == ';') |
|
| 206 |
- fscanf(f, "%s", w); |
|
| 207 |
- else if(w[0] == '"') |
|
| 208 |
- pushtext(w + 1); |
|
| 209 |
- else if(w[0] == '#') |
|
| 210 |
- pushshort(shex(w + 1) & 0xff, 1); |
|
| 211 |
- else if((l = findlabel(w + 1))) |
|
| 212 |
- pushshort(l->addr, w[0] == ','); |
|
| 213 |
- else if((op = findoperator(w)) || scmp(w, "BRK")) |
|
| 214 |
- pushbyte(op, 0); |
|
| 215 |
- else if(sihx(w + 1) && slen(w + 1) == 2) |
|
| 216 |
- pushbyte(shex(w + 1), w[0] == ','); |
|
| 217 |
- else if(sihx(w + 1) && slen(w + 1) == 4) |
|
| 218 |
- pushshort(shex(w + 1), w[0] == ','); |
|
| 219 |
- else |
|
| 220 |
- return error("Unknown label", w);
|
|
| 208 |
+ /* clang-format off */ |
|
| 209 |
+ if(w[0] == '|') p.ptr = shex(w + 1); |
|
| 210 |
+ else if(w[0] == ':') fscanf(f, "%s", w); |
|
| 211 |
+ else if(w[0] == ';') fscanf(f, "%s", w); |
|
| 212 |
+ else if(w[0] == '+' && sihx(w + 1) && slen(w + 1) == 2) pushbyte((Sint8)shex(w + 1), 1); |
|
| 213 |
+ else if(w[0] == '+' && sihx(w + 1) && slen(w + 1) == 4) pushshort((Sint16)shex(w + 1), 1); |
|
| 214 |
+ else if(w[0] == '-' && sihx(w + 1) && slen(w + 1) == 2) pushbyte((Sint8)(shex(w + 1) * -1), 1); |
|
| 215 |
+ else if(w[0] == '-' && sihx(w + 1) && slen(w + 1) == 4) pushshort((Sint16)(shex(w + 1) * -1), 1); |
|
| 216 |
+ else if(w[0] == '"') pushtext(w + 1); |
|
| 217 |
+ else if(w[0] == '#') pushshort(shex(w + 1) & 0xff, 1); |
|
| 218 |
+ else if((l = findlabel(w + 1))) pushshort(l->addr, w[0] == ','); |
|
| 219 |
+ else if((op = findoperator(w)) || scmp(w, "BRK")) pushbyte(op, 0); |
|
| 220 |
+ else if(sihx(w + 1) && slen(w + 1) == 2) pushbyte(shex(w + 1), w[0] == ','); |
|
| 221 |
+ else if(sihx(w + 1) && slen(w + 1) == 4) pushshort(shex(w + 1), w[0] == ','); |
|
| 222 |
+ else return error("Unknown label", w);
|
|
| 223 |
+ /* clang-format on */ |
|
| 221 | 224 |
} |
| 222 | 225 |
return 1; |
| 223 | 226 |
} |
| ... | ... |
@@ -24,5 +24,5 @@ rm -f ./bin/emulator |
| 24 | 24 |
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 |
| 25 | 25 |
|
| 26 | 26 |
# run |
| 27 |
-./bin/assembler examples/test.usm bin/boot.rom |
|
| 27 |
+./bin/assembler examples/line.usm bin/boot.rom |
|
| 28 | 28 |
./bin/emulator bin/boot.rom |
| ... | ... |
@@ -21,6 +21,12 @@ contexts: |
| 21 | 21 |
- match: '\|(\S+)\s?' |
| 22 | 22 |
scope: punctuation.definition |
| 23 | 23 |
pop: true |
| 24 |
+ - match: '\+(\S+)\s?' |
|
| 25 |
+ scope: keyword.control |
|
| 26 |
+ pop: true |
|
| 27 |
+ - match: '\-(\S+)\s?' |
|
| 28 |
+ scope: keyword.control |
|
| 29 |
+ pop: true |
|
| 24 | 30 |
|
| 25 | 31 |
strings: |
| 26 | 32 |
- match: '\:(\S+)\s?' |
| ... | ... |
@@ -35,6 +41,9 @@ contexts: |
| 35 | 41 |
- match: '\,(\S+)\s?' |
| 36 | 42 |
scope: keyword.control |
| 37 | 43 |
pop: true |
| 44 |
+ - match: '\#(\S+)\s?' |
|
| 45 |
+ scope: keyword.control |
|
| 46 |
+ pop: true |
|
| 38 | 47 |
- match: '\.(\S+)\s?' |
| 39 | 48 |
scope: keyword.control |
| 40 | 49 |
pop: true |
| ... | ... |
@@ -22,6 +22,18 @@ |
| 22 | 22 |
,1234 ,1233 GTH^ #0e STR |
| 23 | 23 |
,1234 ,1235 LTH^ #0f STR |
| 24 | 24 |
|
| 25 |
+BRK |
|
| 26 |
+ |
|
| 27 |
+@diff8 ( result of abs sub ) |
|
| 28 |
+ OVR OVR GTH ,diff8sub ROT JMP? POP^ |
|
| 29 |
+ SWP @diff8sub SUB |
|
| 30 |
+RTS |
|
| 31 |
+ |
|
| 32 |
+@diff16 ( result of abs sub16 ) |
|
| 33 |
+ OVR^ OVR^ GTH^ ,diff16sub ROT JMP? POP^ |
|
| 34 |
+ SWP^ @diff16sub SUB^ |
|
| 35 |
+RTS |
|
| 36 |
+ |
|
| 25 | 37 |
|c000 @FRAME BRK |
| 26 | 38 |
|d000 @ERROR BRK |
| 27 | 39 |
|FFFA .RESET .FRAME .ERROR |
| ... | ... |
@@ -5,6 +5,8 @@ |
| 5 | 5 |
|
| 6 | 6 |
;x_ 2 ;y_ 2 ;x0 2 ;y0 2 ;x1 2 ;y1 2 ;color 1 |
| 7 | 7 |
|
| 8 |
+;dx 2 ;dy 2 ;err 2 ;err2 2 |
|
| 9 |
+ |
|
| 8 | 10 |
|0100 @RESET |
| 9 | 11 |
|
| 10 | 12 |
( set dev/write to screen ) |
| ... | ... |
@@ -13,9 +15,10 @@ |
| 13 | 15 |
|
| 14 | 16 |
( init positions ) |
| 15 | 17 |
,0020 ,x0 STR^ ,0018 ,y0 STR^ |
| 16 |
- ,0030 ,x1 STR^ ,0048 ,y1 STR^ |
|
| 18 |
+ ,0060 ,x1 STR^ ,0048 ,y1 STR^ |
|
| 17 | 19 |
,x0 LDR^ ,x_ STR^ ,y0 LDR^ ,y_ STR^ |
| 18 | 20 |
|
| 21 |
+ |
|
| 19 | 22 |
( draw control points ) |
| 20 | 23 |
,02 ,color STR |
| 21 | 24 |
,x0 LDR^ ,y0 LDR^ ,putpixel JSR |
| ... | ... |
@@ -39,6 +42,11 @@ BRK |
| 39 | 42 |
,00 IOW ( redraw byte ) |
| 40 | 43 |
RTS |
| 41 | 44 |
|
| 45 |
+@diff16 |
|
| 46 |
+ OVR^ OVR^ GTH^ ,diff16sub ROT JMP? POP^ |
|
| 47 |
+ SWP^ @diff16sub SUB^ |
|
| 48 |
+RTS |
|
| 49 |
+ |
|
| 42 | 50 |
|c000 @FRAME BRK |
| 43 | 51 |
|d000 @ERROR BRK |
| 44 | 52 |
|FFFA .RESET .FRAME .ERROR |
| ... | ... |
@@ -3,13 +3,17 @@ |
| 3 | 3 |
:dev/r fff8 ( std read port ) |
| 4 | 4 |
:dev/w fff9 ( std write port ) |
| 5 | 5 |
|
| 6 |
+;x 2 |
|
| 7 |
+ |
|
| 6 | 8 |
|0100 @RESET |
| 7 | 9 |
|
| 8 |
- ,00 ,dev/w STR ( set dev/write to console ) |
|
| 10 |
+ ,00 ,dev/w STR ( set dev/write to console ) |
|
| 9 | 11 |
|
| 12 |
+ -12 +02 LTH! |
|
| 10 | 13 |
|
| 11 | 14 |
BRK |
| 12 | 15 |
|
| 16 |
+ |
|
| 13 | 17 |
|c000 @FRAME BRK |
| 14 | 18 |
|d000 @ERROR BRK |
| 15 | 19 |
|FFFA .RESET .FRAME .ERROR |
| ... | ... |
@@ -33,7 +33,7 @@ Uint16 peek16(St8 *s, Uint8 a) { return peek8(s, a * 2) + (peek8(s, a * 2 + 1) <
|
| 33 | 33 |
void op_brk(Uxn *u) { setflag(&u->status,FLAG_HALT, 1); }
|
| 34 | 34 |
void op_li1(Uxn *u) { u->literal += 1; }
|
| 35 | 35 |
void op_lix(Uxn *u) { u->literal += u->ram.dat[u->ram.ptr++]; }
|
| 36 |
-void op_nop(Uxn *u) { printf("%02x\n", pop8(&u->wst)); }
|
|
| 36 |
+void op_nop(Uxn *u) { printf("0x%02x ", pop8(&u->wst)); }
|
|
| 37 | 37 |
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))); }
|
| 38 | 38 |
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); }
|
| 39 | 39 |
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,
|
| 52 | 52 |
void op_ora(Uxn *u) { Uint8 a = pop8(&u->wst), b = pop8(&u->wst); push8(&u->wst, b | a); }
|
| 53 | 53 |
void op_rol(Uxn *u) { Uint8 a = pop8(&u->wst), b = pop8(&u->wst); push8(&u->wst, b << a); }
|
| 54 | 54 |
/* Arithmetic */ |
| 55 |
-void op_add(Uxn *u) { Uint8 a = pop8(&u->wst), b = pop8(&u->wst); push8(&u->wst, b + a); }
|
|
| 56 |
-void op_sub(Uxn *u) { Uint8 a = pop8(&u->wst), b = pop8(&u->wst); push8(&u->wst, b - a); }
|
|
| 57 |
-void op_mul(Uxn *u) { Uint8 a = pop8(&u->wst), b = pop8(&u->wst); push8(&u->wst, b * a); }
|
|
| 58 |
-void op_div(Uxn *u) { Uint8 a = pop8(&u->wst), b = pop8(&u->wst); push8(&u->wst, b / a); }
|
|
| 59 |
-void op_equ(Uxn *u) { Uint8 a = pop8(&u->wst), b = pop8(&u->wst); push8(&u->wst, b == a); }
|
|
| 60 |
-void op_neq(Uxn *u) { Uint8 a = pop8(&u->wst), b = pop8(&u->wst); push8(&u->wst, b != a); }
|
|
| 61 |
-void op_gth(Uxn *u) { Uint8 a = pop8(&u->wst), b = pop8(&u->wst); push8(&u->wst, b > a); }
|
|
| 62 |
-void op_lth(Uxn *u) { Uint8 a = pop8(&u->wst), b = pop8(&u->wst); push8(&u->wst, b < a); }
|
|
| 55 |
+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); }
|
|
| 56 |
+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); }
|
|
| 57 |
+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); }
|
|
| 58 |
+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); }
|
|
| 59 |
+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); }
|
|
| 60 |
+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); }
|
|
| 61 |
+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); }
|
|
| 62 |
+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); }
|
|
| 63 | 63 |
/* --- */ |
| 64 | 64 |
void op_nop16(Uxn *u) { printf("%04x\n", pop16(&u->wst)); }
|
| 65 | 65 |
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
|
| 76 | 76 |
void op_ora16(Uxn *u) { Uint16 a = pop16(&u->wst), b = pop16(&u->wst); push16(&u->wst, b | a); }
|
| 77 | 77 |
void op_rol16(Uxn *u) { Uint16 a = pop16(&u->wst), b = pop16(&u->wst); push16(&u->wst, b << a); }
|
| 78 | 78 |
/* Arithmetic(16-bits) */ |
| 79 |
-void op_add16(Uxn *u) { Uint16 a = pop16(&u->wst), b = pop16(&u->wst); push16(&u->wst, b + a); }
|
|
| 80 |
-void op_sub16(Uxn *u) { Uint16 a = pop16(&u->wst), b = pop16(&u->wst); push16(&u->wst, b - a); }
|
|
| 81 |
-void op_mul16(Uxn *u) { Uint16 a = pop16(&u->wst), b = pop16(&u->wst); push16(&u->wst, b * a); }
|
|
| 82 |
-void op_div16(Uxn *u) { Uint16 a = pop16(&u->wst), b = pop16(&u->wst); push16(&u->wst, b / a); }
|
|
| 83 |
-void op_equ16(Uxn *u) { Uint16 a = pop16(&u->wst), b = pop16(&u->wst); push8(&u->wst, b == a); }
|
|
| 84 |
-void op_neq16(Uxn *u) { Uint16 a = pop16(&u->wst), b = pop16(&u->wst); push8(&u->wst, b != a); }
|
|
| 85 |
-void op_gth16(Uxn *u) { Uint16 a = pop16(&u->wst), b = pop16(&u->wst); push8(&u->wst, b > a); }
|
|
| 86 |
-void op_lth16(Uxn *u) { Uint16 a = pop16(&u->wst), b = pop16(&u->wst); push8(&u->wst, b < a); }
|
|
| 79 |
+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); }
|
|
| 80 |
+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); }
|
|
| 81 |
+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); }
|
|
| 82 |
+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); }
|
|
| 83 |
+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); }
|
|
| 84 |
+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); }
|
|
| 85 |
+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); }
|
|
| 86 |
+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); }
|
|
| 87 | 87 |
|
| 88 | 88 |
void (*ops[])(Uxn *u) = {
|
| 89 | 89 |
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) |
| 133 | 133 |
{
|
| 134 | 134 |
Uint8 op = instr & 0x1f; |
| 135 | 135 |
setflag(&u->status, FLAG_SHORT, (instr >> 5) & 1); |
| 136 |
- setflag(&u->status, FLAG_SIGN, (instr >> 6) & 1); /* usused */ |
|
| 136 |
+ setflag(&u->status, FLAG_SIGN, (instr >> 6) & 1); |
|
| 137 | 137 |
setflag(&u->status, FLAG_COND, (instr >> 7) & 1); |
| 138 | 138 |
if(getflag(&u->status, FLAG_SHORT)) |
| 139 | 139 |
op += 32; |