Browse code

Started implementing macros

neauoire authored on 14/03/2021 20:30:17
Showing 5 changed files
... ...
@@ -74,6 +74,14 @@ RTS
74 74
 - Jump helpers
75 75
 - Don't brk when return stack is not zeroed
76 76
 - LDRS should load from the zeropage?
77
+- Keep ref counts in macros
78
+
79
+### Macros
80
+
81
+```
82
+&RTS { RSW JMP } 
83
+&JSR { PRG WSR JMP }
84
+```
77 85
 
78 86
 ## Notes
79 87
 
... ...
@@ -16,6 +16,11 @@ typedef signed char Sint8;
16 16
 typedef unsigned short Uint16;
17 17
 typedef signed short Sint16;
18 18
 
19
+typedef struct {
20
+	char name[64], items[16][64];
21
+	Uint8 len;
22
+} Macro;
23
+
19 24
 typedef struct {
20 25
 	char name[64];
21 26
 	unsigned int size;
... ...
@@ -29,9 +34,10 @@ typedef struct {
29 34
 } Label;
30 35
 
31 36
 typedef struct {
32
-	Uint8 data[256 * 256], llen;
37
+	Uint8 data[256 * 256], llen, mlen;
33 38
 	Uint16 ptr;
34 39
 	Label labels[256];
40
+	Macro macros[256];
35 41
 } Program;
36 42
 
37 43
 Program p;
... ...
@@ -42,7 +48,7 @@ char ops[][4] = {
42 48
 	"BRK", "NOP", "LIT", "LDR", "STR", "JMP", "JSR", "RTS", 
43 49
 	"EQU", "NEQ", "GTH", "LTH", "AND", "XOR", "ROL", "ROR",
44 50
 	"POP", "DUP", "SWP", "OVR", "ROT", "---", "WSR", "RSW",
45
-	"ADD", "SUB", "MUL", "DIV", "---", "---", "---", "---"
51
+	"ADD", "SUB", "MUL", "DIV", "---", "---", "---", "PRG"
46 52
 };
47 53
 
48 54
 int   scin(char *s, char c) { int i = 0; while(s[i]) if(s[i++] == c) return i - 1; return -1; } /* string char index */
... ...
@@ -82,6 +88,16 @@ pushtext(char *s, int lit)
82 88
 	while((c = s[i++])) pushbyte(c, 0);
83 89
 }
84 90
 
91
+Macro *
92
+findmacro(char *name)
93
+{
94
+	int i;
95
+	for(i = 0; i < p.mlen; ++i)
96
+		if(scmp(p.macros[i].name, name, 64))
97
+			return &p.macros[i];
98
+	return NULL;
99
+}
100
+
85 101
 Label *
86 102
 findlabel(char *s)
87 103
 {
... ...
@@ -166,6 +182,28 @@ error(char *name, char *id)
166 182
 	return 0;
167 183
 }
168 184
 
185
+int
186
+makemacro(char *name, FILE *f)
187
+{
188
+	Macro *m;
189
+	char word[64];
190
+	if(findmacro(name))
191
+		return error("Macro duplicate", name);
192
+	if(sihx(name) && slen(name) % 2 == 0)
193
+		return error("Macro name is hex number", name);
194
+	if(findopcode(name))
195
+		return error("Macro name is invalid", name);
196
+	m = &p.macros[p.mlen++];
197
+	scpy(name, m->name, 64);
198
+	while(fscanf(f, "%s", word)) {
199
+		if(word[0] == '{') continue;
200
+		if(word[0] == '}') break;
201
+		scpy(word, m->items[m->len++], 64);
202
+	}
203
+	printf("New macro: %s(%d items)\n", m->name, m->len);
204
+	return 1;
205
+}
206
+
169 207
 int
170 208
 makelabel(char *name, Uint16 addr)
171 209
 {
... ...
@@ -197,8 +235,7 @@ makevariable(char *name, Uint16 *addr, FILE *f)
197 235
 		if(word[0] == '}') break;
198 236
 		scpy(word, l->map[l->maps].name, 64);
199 237
 		fscanf(f, "%u", &l->map[l->maps].size);
200
-		*addr += l->map[l->maps].size;
201
-		l->maps++;
238
+		*addr += l->map[l->maps++].size;
202 239
 	}
203 240
 	return 1;
204 241
 }
... ...
@@ -215,6 +252,119 @@ skipblock(char *w, int *cap, char a, char b)
215 252
 	return 0;
216 253
 }
217 254
 
255
+int
256
+walktoken(char *w)
257
+{
258
+	Macro *m;
259
+	if((m = findmacro(w))) {
260
+		int i, res = 0;
261
+		for(i = 0; i < m->len; ++i)
262
+			res += walktoken(m->items[i]);
263
+		return res;
264
+	}
265
+	if(findopcode(w) || scmp(w, "BRK", 4))
266
+		return 1;
267
+	switch(w[0]) {
268
+	case '=': return 4; /* STR helper (lit addr-hb addr-lb str) */
269
+	case '~': return 4; /* LDR helper (lit addr-hb addr-lb ldr) */
270
+	case ',': return 3; /* lit2 addr-hb addr-lb */
271
+	case '.': return 2; /* addr-hb addr-lb */
272
+	case '^': return 2; /* Relative jump: lit addr-offset */
273
+	case '+':           /* signed positive */
274
+	case '-':           /* signed negative */
275
+	case '#': return (slen(w + 1) == 2 ? 2 : 3);
276
+	}
277
+	return error("Unknown label in first pass", w);
278
+}
279
+
280
+int
281
+parsetoken(char *w)
282
+{
283
+	Uint8 op = 0;
284
+	Label *l;
285
+	Macro *m;
286
+
287
+	if(w[0] == '^' && (l = findlabel(w + 1))) {
288
+		int off = l->addr - p.ptr - 3;
289
+		if(off < -126 || off > 126) {
290
+			printf("Address %s is too far(%d).\n", w, off);
291
+			return 0;
292
+		}
293
+		pushbyte((Sint8)(l->addr - p.ptr - 3), 1);
294
+		l->refs++;
295
+		return 1;
296
+	}
297
+	if(w[0] == '=' && (l = findlabel(w + 1))) {
298
+		if(!findlabellen(w + 1) || findlabellen(w + 1) > 2)
299
+			return error("Invalid load helper", w);
300
+		pushshort(findlabeladdr(w + 1), 1);
301
+		pushbyte(findopcode(findlabellen(w + 1) == 2 ? "STR2" : "STR"), 0);
302
+		l->refs++;
303
+		return 1;
304
+	}
305
+	if(w[0] == '~' && (l = findlabel(w + 1))) {
306
+		if(!findlabellen(w + 1) || findlabellen(w + 1) > 2)
307
+			return error("Invalid load helper", w);
308
+		pushshort(findlabeladdr(w + 1), 1);
309
+		pushbyte(findopcode(findlabellen(w + 1) == 2 ? "LDR2" : "LDR"), 0);
310
+		l->refs++;
311
+		return 1;
312
+	}
313
+	if((op = findopcode(w)) || scmp(w, "BRK", 4)) {
314
+		pushbyte(op, 0);
315
+		return 1;
316
+	}
317
+	if(w[0] == '.' && (l = findlabel(w + 1))) {
318
+		pushshort(findlabeladdr(w + 1), 0);
319
+		l->refs++;
320
+		return 1;
321
+	}
322
+	if(w[0] == ',' && (l = findlabel(w + 1))) {
323
+		pushshort(findlabeladdr(w + 1), 1);
324
+		l->refs++;
325
+		return 1;
326
+	}
327
+	if(w[0] == '#' && sihx(w + 1)) {
328
+		if(slen(w + 1) == 2)
329
+			pushbyte(shex(w + 1), 1);
330
+		else if(slen(w + 1) == 4)
331
+			pushshort(shex(w + 1), 1);
332
+		else
333
+			return 0;
334
+		return 1;
335
+	}
336
+
337
+	if(w[0] == '+' && sihx(w + 1)) {
338
+		if(slen(w + 1) == 2)
339
+			pushbyte((Sint8)shex(w + 1), 1);
340
+		else if(slen(w + 1) == 4)
341
+			pushshort((Sint16)shex(w + 1), 1);
342
+		else
343
+			return 0;
344
+	}
345
+
346
+	if(w[0] == '-' && sihx(w + 1)) {
347
+		if(slen(w + 1) == 2)
348
+			pushbyte((Sint8)(shex(w + 1) * -1), 1);
349
+		else if(slen(w + 1) == 4)
350
+			pushshort((Sint16)(shex(w + 1) * -1), 1);
351
+		else
352
+			return 0;
353
+		return 1;
354
+	}
355
+
356
+	if((m = findmacro(w))) {
357
+		int i, res = 0;
358
+		for(i = 0; i < m->len; ++i) {
359
+			if(!parsetoken(m->items[i]))
360
+				return 0;
361
+		}
362
+		return 1;
363
+	}
364
+
365
+	return 0;
366
+}
367
+
218 368
 int
219 369
 pass1(FILE *f)
220 370
 {
... ...
@@ -231,6 +381,10 @@ pass1(FILE *f)
231 381
 				addr += slen(w) == 4 ? 2 : 1;
232 382
 			else
233 383
 				addr += slen(w);
384
+		} else if(w[0] == '%') {
385
+			if(!makemacro(w + 1, f))
386
+				return error("Pass1 failed", w);
387
+			scpy(w + 1, scope, 64);
234 388
 		} else if(w[0] == '@') {
235 389
 			if(!makelabel(w + 1, addr))
236 390
 				return error("Pass1 failed", w);
... ...
@@ -241,25 +395,12 @@ pass1(FILE *f)
241 395
 		} else if(w[0] == ';') {
242 396
 			if(!makevariable(w + 1, &addr, f))
243 397
 				return error("Pass1 failed", w);
244
-		} else if(findopcode(w) || scmp(w, "BRK", 4))
245
-			addr += 1;
246
-		else {
247
-			switch(w[0]) {
248
-			case '|':
249
-				if(shex(w + 1) < addr)
250
-					return error("Memory Overlap", w);
251
-				addr = shex(w + 1);
252
-				break;
253
-			case '=': addr += 4; break; /* STR helper (lit addr-hb addr-lb str) */
254
-			case '~': addr += 4; break; /* LDR helper (lit addr-hb addr-lb ldr) */
255
-			case ',': addr += 3; break;
256
-			case '.': addr += 2; break;
257
-			case '^': addr += 2; break; /* Relative jump: lit addr-offset */
258
-			case '+':                   /* signed positive */
259
-			case '-':                   /* signed negative */
260
-			case '#': addr += (slen(w + 1) == 2 ? 2 : 3); break;
261
-			default: return error("Unknown label in first pass", w);
262
-			}
398
+		} else if(w[0] == '|') {
399
+			if(shex(w + 1) < addr)
400
+				return error("Memory Overwrite", w);
401
+			addr = shex(w + 1);
402
+		} else {
403
+			addr += walktoken(w);
263 404
 		}
264 405
 	}
265 406
 	rewind(f);
... ...
@@ -273,52 +414,33 @@ pass2(FILE *f)
273 414
 	char w[64], scope[64], subw[64];
274 415
 	printf("Pass 2\n");
275 416
 	while(fscanf(f, "%s", w) == 1) {
276
-		Uint8 op = 0;
277
-		Label *l;
278 417
 		if(w[0] == ';') continue;
279 418
 		if(w[0] == '$') continue;
419
+		if(w[0] == '%') continue;
280 420
 		if(skipblock(w, &ccmnt, '(', ')')) continue;
281 421
 		if(skipblock(w, &ctemplate, '{', '}')) continue;
422
+		if(w[0] == '|') {
423
+			p.ptr = shex(w + 1);
424
+			continue;
425
+		}
282 426
 		if(w[0] == '@') {
283 427
 			scpy(w + 1, scope, 64);
284 428
 			continue;
285 429
 		}
286 430
 		if(w[1] == '$') {
287
-			sublabel(subw, scope, w + 2);
288
-			scpy(subw, w + 1, 64);
431
+			scpy(sublabel(subw, scope, w + 2), w + 1, 64);
289 432
 		}
290
-		/* clang-format off */
291 433
 		if(skipblock(w, &cbits, '[', ']')) {
292 434
 			if(w[0] == '[' || w[0] == ']') { continue; }
293
-			if(slen(w) == 4 && sihx(w)) pushshort(shex(w), 0); 
294
-			else if(slen(w) == 2 && sihx(w)) pushbyte(shex(w), 0); 
295
-			else pushtext(w, 0);
296
-		}
297
-		else if(w[0] == '^' && (l = findlabel(w + 1))) { 
298
-			int off = l->addr - p.ptr - 3;
299
-			if(off < -126 || off > 126){ printf("Address %s is too far(%d).\n", w, off); return 0; } 
300
-			pushbyte((Sint8)(l->addr - p.ptr - 3), 1); l->refs++; 
435
+			if(slen(w) == 4 && sihx(w))
436
+				pushshort(shex(w), 0);
437
+			else if(slen(w) == 2 && sihx(w))
438
+				pushbyte(shex(w), 0);
439
+			else
440
+				pushtext(w, 0);
441
+		} else if(!parsetoken(w)) {
442
+			return error("Unknown label in second pass", w);
301 443
 		}
302
-		else if(w[0] == '=' && (l = findlabel(w + 1))) { 
303
-			if(!findlabellen(w + 1) || findlabellen(w + 1) > 2)
304
-				return error("Invalid load helper", w);
305
-			pushshort(findlabeladdr(w + 1), 1); pushbyte(findopcode(findlabellen(w + 1) == 2 ? "STR2" : "STR"), 0); l->refs++;}
306
-		else if(w[0] == '~' && (l = findlabel(w + 1))) { 
307
-			if(!findlabellen(w + 1) || findlabellen(w + 1) > 2)
308
-				return error("Invalid load helper", w);
309
-			pushshort(findlabeladdr(w + 1), 1); pushbyte(findopcode(findlabellen(w + 1) == 2 ? "LDR2" : "LDR"), 0); l->refs++;}
310
-		else if(w[0] == '|') p.ptr = shex(w + 1);
311
-		else if((op = findopcode(w)) || scmp(w, "BRK", 4)) pushbyte(op, 0);
312
-		else if(w[0] == '.' && (l = findlabel(w + 1))) { pushshort(findlabeladdr(w + 1), 0); l->refs++; }
313
-		else if(w[0] == ',' && (l = findlabel(w + 1))) { pushshort(findlabeladdr(w + 1), 1); l->refs++; }
314
-		else if(w[0] == '#' && sihx(w + 1) && slen(w + 1) == 2) pushbyte(shex(w + 1), 1); 
315
-		else if(w[0] == '#' && sihx(w + 1) && slen(w + 1) == 4) pushshort(shex(w + 1), 1);
316
-		else if(w[0] == '+' && sihx(w + 1) && slen(w + 1) == 2) pushbyte((Sint8)shex(w + 1), 1);
317
-		else if(w[0] == '+' && sihx(w + 1) && slen(w + 1) == 4) pushshort((Sint16)shex(w + 1), 1);
318
-		else if(w[0] == '-' && sihx(w + 1) && slen(w + 1) == 2) pushbyte((Sint8)(shex(w + 1) * -1), 1);
319
-		else if(w[0] == '-' && sihx(w + 1) && slen(w + 1) == 4) pushshort((Sint16)(shex(w + 1) * -1), 1);
320
-		else return error("Unknown label in second pass", w);
321
-		/* clang-format on */
322 444
 	}
323 445
 	return 1;
324 446
 }
... ...
@@ -1,9 +1,12 @@
1 1
 ( tests/jump )
2 2
 
3
-|0100 @RESET 
3
+%RTS { RSW2 JMP }
4
+%JSR2 { PRG WSR2 JMP2 }
5
+%JMC { JMP2? POP2 }
4 6
 
7
+|0100 @RESET 
8
+	
5 9
 	,test1 JSR2
6
-	,test2 JSR2
7 10
 
8 11
 BRK
9 12
 
... ...
@@ -23,7 +26,7 @@ BRK
23 26
 
24 27
 	#33 =Console.byte
25 28
 
26
-	,skip1 #12 #34 LTH JMP2? POP2
29
+	,skip1 #12 #34 LTH JMC
27 30
 		#ff =Console.byte
28 31
 	@skip1
29 32
 
... ...
@@ -48,7 +51,6 @@ RTS
48 51
 
49 52
 	@end
50 53
 
51
-	^label1 JMPS
52 54
 RTS
53 55
 
54 56
 |c000 @FRAME
... ...
@@ -1,41 +1,46 @@
1
-( hello world )
1
+( Loop )
2 2
 
3
-&Console { pad 8 char 1 byte 1 short 2 }
4
-
5
-;a 1 ;b 1 ;c 1
3
+;a { byte 1 } ;b { byte 1 } ;c { byte 1 }
6 4
 
7 5
 |0100 @RESET 
8 6
 	
9
-	( type: padded muljmp )
10
-	@part1
7
+	,type1 JSR2
8
+	,type2 JSR2
9
+	,type3 JSR2
10
+
11
+BRK 
12
+
13
+@type1 ( type: padded muljmp )
14
+
11 15
 	$loop NOP
12 16
 		~a #01 ADD =a
13 17
 		~a #d0 LTH ^$loop MUL JMPS
18
+	~a =Console.byte
14 19
 
15
-	( type: jmppop )
20
+RTS
16 21
 
17
-	@part2
22
+@type2 ( type: jmppop )
23
+	
18 24
 	$loop
19 25
 		~b #01 ADD =b
20 26
 		,$loop ~b #d0 LTH JMP2? POP2
27
+	~b =Console.byte 
28
+
29
+RTS
21 30
 
22
-	( type: padded jmppop )
31
+@type3 ( type: padded jmppop )
23 32
 
24
-	@part3
25 33
 	$loop NOP
26 34
 		~c #01 ADD =c
27 35
 		~c #d0 LTH ^$loop SWP JMPS? POP
36
+	~c =Console.byte 
28 37
 
29
-	~a =dev/console.byte
30
-	~b =dev/console.byte 
31
-	~c =dev/console.byte 
32
-
33
-BRK               
38
+RTS
34 39
 
35 40
 |c000 @FRAME
36 41
 |d000 @ERROR 
37 42
 
38
-|FF00 ;dev/console Console
43
+|FF00 ;Console { pad 8 char 1 byte 1 short 2 }
39 44
 
40 45
 |FFF0 .RESET .FRAME .ERROR ( vectors )
41 46
 |FFF8 [ 13fd 1ef3 1bf2 ] ( palette )
42 47
\ No newline at end of file
... ...
@@ -34,6 +34,7 @@ void op_brk(Uxn *u) { setflag(&u->status, FLAG_HALT, 1); }
34 34
 void op_lit(Uxn *u) { u->literal += 1; }
35 35
 void op_nop(Uxn *u) { (void)u; }
36 36
 void op_jmp(Uxn *u) { Uint8 a = pop8(&u->wst); u->ram.ptr += getflag(&u->status, FLAG_SIGN) ? (Sint8)a : a; }
37
+void op_prg(Uxn *u) { push16(&u->wst, u->ram.ptr); }
37 38
 void op_jsr(Uxn *u) { Uint8 a = pop8(&u->wst); push16(&u->rst, u->ram.ptr); u->ram.ptr += getflag(&u->status, FLAG_SIGN) ? (Sint8)a : a; }
38 39
 void op_rts(Uxn *u) { u->ram.ptr = pop16(&u->rst); }
39 40
 void op_ldr(Uxn *u) { Uint16 a = pop16(&u->wst); push8(&u->wst, mempeek8(u, a)); }
... ...
@@ -95,7 +96,7 @@ void (*ops[])(Uxn *u) = {
95 96
 	op_pop, op_dup, op_swp, op_ovr, op_rot, op_nop, op_wsr, op_rsw,
96 97
 	op_add, op_sub, op_mul, op_div, op_nop, op_nop, op_nop, op_nop,
97 98
 	/* 16-bit */
98
-	op_brk,   op_nop16, op_lit16, op_ldr16, op_str16, op_jmp16, op_jsr16, op_rts,
99
+	op_brk,   op_nop16, op_lit16, op_ldr16, op_str16, op_jmp16, op_jsr16,   op_rts,
99 100
 	op_equ16, op_neq16, op_gth16, op_lth16, op_and16, op_xor16, op_rol16, op_ror16, 
100 101
 	op_pop16, op_dup16, op_swp16, op_ovr16, op_rot16, op_nop,   op_wsr16, op_rsw16,
101 102
 	op_add16, op_sub16, op_mul16, op_div16, op_nop,   op_nop,   op_nop,   op_nop