... | ... |
@@ -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; |