xref: /inferno-os/utils/5a/lex.c (revision e45fa0eb0763b57d6fb0649c064bc3b95ccdea6c)
1 #define	EXTERN
2 #include "a.h"
3 #include "y.tab.h"
4 #include <ctype.h>
5 
6 void
7 main(int argc, char *argv[])
8 {
9 	char *p;
10 	int nout, nproc, status, i, c;
11 
12 	thechar = '5';
13 	thestring = "arm";
14 	memset(debug, 0, sizeof(debug));
15 	cinit();
16 	outfile = 0;
17 	include[ninclude++] = ".";
18 	ARGBEGIN {
19 	default:
20 		c = ARGC();
21 		if(c >= 0 || c < sizeof(debug))
22 			debug[c] = 1;
23 		break;
24 
25 	case 'o':
26 		outfile = ARGF();
27 		break;
28 
29 	case 'D':
30 		p = ARGF();
31 		if(p)
32 			Dlist[nDlist++] = p;
33 		break;
34 
35 	case 'I':
36 		p = ARGF();
37 		setinclude(p);
38 		break;
39 	case 't':
40 		thechar = 't';
41 		thestring = "thumb";
42 		break;
43 	} ARGEND
44 	if(*argv == 0) {
45 		print("usage: %ca [-options] file.s\n", thechar);
46 		errorexit();
47 	}
48 	if(argc > 1 && systemtype(Windows)){
49 		print("can't assemble multiple files on windows\n");
50 		errorexit();
51 	}
52 	if(argc > 1 && !systemtype(Windows)) {
53 		nproc = 1;
54 		if(p = getenv("NPROC"))
55 			nproc = atol(p);	/* */
56 		c = 0;
57 		nout = 0;
58 		for(;;) {
59 			while(nout < nproc && argc > 0) {
60 				i = myfork();
61 				if(i < 0) {
62 					i = mywait(&status);
63 					if(i < 0)
64 						errorexit();
65 					if(status)
66 						c++;
67 					nout--;
68 					continue;
69 				}
70 				if(i == 0) {
71 					print("%s:\n", *argv);
72 					if(assemble(*argv))
73 						errorexit();
74 					exits(0);
75 				}
76 				nout++;
77 				argc--;
78 				argv++;
79 			}
80 			i = mywait(&status);
81 			if(i < 0) {
82 				if(c)
83 					errorexit();
84 				exits(0);
85 			}
86 			if(status)
87 				c++;
88 			nout--;
89 		}
90 	}
91 	if(assemble(argv[0]))
92 		errorexit();
93 	exits(0);
94 }
95 
96 int
97 assemble(char *file)
98 {
99 	char ofile[100], incfile[20], *p;
100 	int i, of;
101 
102 	strcpy(ofile, file);
103 	p = utfrrune(ofile, pathchar());
104 	if(p) {
105 		include[0] = ofile;
106 		*p++ = 0;
107 	} else
108 		p = ofile;
109 	if(outfile == 0) {
110 		outfile = p;
111 		if(outfile){
112 			p = utfrrune(outfile, '.');
113 			if(p)
114 				if(p[1] == 's' && p[2] == 0)
115 					p[0] = 0;
116 			p = utfrune(outfile, 0);
117 			p[0] = '.';
118 			p[1] = thechar;
119 			p[2] = 0;
120 		} else
121 			outfile = "/dev/null";
122 	}
123 	p = getenv("INCLUDE");
124 	if(p) {
125 		setinclude(p);
126 	} else {
127 		if(systemtype(Plan9)) {
128 			sprint(incfile,"/%s/include", thestring);
129 			setinclude(strdup(incfile));
130 		}
131 	}
132 
133 	of = mycreat(outfile, 0664);
134 	if(of < 0) {
135 		yyerror("%ca: cannot create %s", thechar, outfile);
136 		errorexit();
137 	}
138 	Binit(&obuf, of, OWRITE);
139 
140 	pass = 1;
141 	pinit(file);
142 	for(i=0; i<nDlist; i++)
143 		dodefine(Dlist[i]);
144 	yyparse();
145 	if(nerrors) {
146 		cclean();
147 		return nerrors;
148 	}
149 
150 	pass = 2;
151 	outhist();
152 	pinit(file);
153 	for(i=0; i<nDlist; i++)
154 		dodefine(Dlist[i]);
155 	yyparse();
156 	cclean();
157 	return nerrors;
158 }
159 
160 struct
161 {
162 	char	*name;
163 	ushort	type;
164 	ushort	value;
165 } itab[] =
166 {
167 	"SP",		LSP,	D_AUTO,
168 	"SB",		LSB,	D_EXTERN,
169 	"FP",		LFP,	D_PARAM,
170 	"PC",		LPC,	D_BRANCH,
171 
172 	"R",		LR,	0,
173 	"R0",		LREG,	0,
174 	"R1",		LREG,	1,
175 	"R2",		LREG,	2,
176 	"R3",		LREG,	3,
177 	"R4",		LREG,	4,
178 	"R5",		LREG,	5,
179 	"R6",		LREG,	6,
180 	"R7",		LREG,	7,
181 	"R8",		LREG,	8,
182 	"R9",		LREG,	9,
183 	"R10",		LREG,	10,
184 	"R11",		LREG,	11,
185 	"R12",		LREG,	12,
186 	"R13",		LREG,	13,
187 	"R14",		LREG,	14,
188 	"R15",		LREG,	15,
189 
190 	"F",		LF,	0,
191 
192 	"F0",		LFREG,	0,
193 	"F1",		LFREG,	1,
194 	"F2",		LFREG,	2,
195 	"F3",		LFREG,	3,
196 	"F4",		LFREG,	4,
197 	"F5",		LFREG,	5,
198 	"F6",		LFREG,	6,
199 	"F7",		LFREG,	7,
200 	"F8",		LFREG,	8,
201 	"F9",		LFREG,	9,
202 	"F10",		LFREG,	10,
203 	"F11",		LFREG,	11,
204 	"F12",		LFREG,	12,
205 	"F13",		LFREG,	13,
206 	"F14",		LFREG,	14,
207 	"F15",		LFREG,	15,
208 
209 	"C",		LC,	0,
210 
211 	"C0",		LCREG,	0,
212 	"C1",		LCREG,	1,
213 	"C2",		LCREG,	2,
214 	"C3",		LCREG,	3,
215 	"C4",		LCREG,	4,
216 	"C5",		LCREG,	5,
217 	"C6",		LCREG,	6,
218 	"C7",		LCREG,	7,
219 	"C8",		LCREG,	8,
220 	"C9",		LCREG,	9,
221 	"C10",		LCREG,	10,
222 	"C11",		LCREG,	11,
223 	"C12",		LCREG,	12,
224 	"C13",		LCREG,	13,
225 	"C14",		LCREG,	14,
226 	"C15",		LCREG,	15,
227 
228 	"CPSR",		LPSR,	0,
229 	"SPSR",		LPSR,	1,
230 
231 	"FPSR",		LFCR,	0,
232 	"FPCR",		LFCR,	1,
233 
234 	".EQ",		LCOND,	0,
235 	".NE",		LCOND,	1,
236 	".CS",		LCOND,	2,
237 	".HS",		LCOND,	2,
238 	".CC",		LCOND,	3,
239 	".LO",		LCOND,	3,
240 	".MI",		LCOND,	4,
241 	".PL",		LCOND,	5,
242 	".VS",		LCOND,	6,
243 	".VC",		LCOND,	7,
244 	".HI",		LCOND,	8,
245 	".LS",		LCOND,	9,
246 	".GE",		LCOND,	10,
247 	".LT",		LCOND,	11,
248 	".GT",		LCOND,	12,
249 	".LE",		LCOND,	13,
250 	".AL",		LCOND,	Always,
251 
252 	".U",		LS,	C_UBIT,
253 	".S",		LS,	C_SBIT,
254 	".W",		LS,	C_WBIT,
255 	".P",		LS,	C_PBIT,
256 	".PW",		LS,	C_WBIT|C_PBIT,
257 	".WP",		LS,	C_WBIT|C_PBIT,
258 
259 	".F",		LS,	C_FBIT,
260 
261 	".IBW",		LS,	C_WBIT|C_PBIT|C_UBIT,
262 	".IAW",		LS,	C_WBIT|C_UBIT,
263 	".DBW",		LS,	C_WBIT|C_PBIT,
264 	".DAW",		LS,	C_WBIT,
265 	".IB",		LS,	C_PBIT|C_UBIT,
266 	".IA",		LS,	C_UBIT,
267 	".DB",		LS,	C_PBIT,
268 	".DA",		LS,	0,
269 
270 	"@",		LAT,	0,
271 
272 	"AND",		LTYPE1,	AAND,
273 	"EOR",		LTYPE1,	AEOR,
274 	"SUB",		LTYPE1,	ASUB,
275 	"RSB",		LTYPE1,	ARSB,
276 	"ADD",		LTYPE1,	AADD,
277 	"ADC",		LTYPE1,	AADC,
278 	"SBC",		LTYPE1,	ASBC,
279 	"RSC",		LTYPE1,	ARSC,
280 	"ORR",		LTYPE1,	AORR,
281 	"BIC",		LTYPE1,	ABIC,
282 
283 	"SLL",		LTYPE1,	ASLL,
284 	"SRL",		LTYPE1,	ASRL,
285 	"SRA",		LTYPE1,	ASRA,
286 
287 	"MUL",		LTYPE1, AMUL,
288 	"MULA",		LTYPEN, AMULA,
289 	"DIV",		LTYPE1,	ADIV,
290 	"MOD",		LTYPE1,	AMOD,
291 
292 	"MULL",		LTYPEM, AMULL,
293 	"MULAL",	LTYPEM, AMULAL,
294 	"MULLU",	LTYPEM, AMULLU,
295 	"MULALU",	LTYPEM, AMULALU,
296 
297 	"MVN",		LTYPE2, AMVN,	/* op2 ignored */
298 
299 	"MOVB",		LTYPE3, AMOVB,
300 	"MOVBU",	LTYPE3, AMOVBU,
301 	"MOVH",		LTYPE3, AMOVH,
302 	"MOVHU",	LTYPE3, AMOVHU,
303 	"MOVW",		LTYPE3, AMOVW,
304 
305 	"MOVD",		LTYPE3, AMOVD,
306 	"MOVDF",		LTYPE3, AMOVDF,
307 	"MOVDW",	LTYPE3, AMOVDW,
308 	"MOVF",		LTYPE3, AMOVF,
309 	"MOVFD",		LTYPE3, AMOVFD,
310 	"MOVFW",		LTYPE3, AMOVFW,
311 	"MOVWD",	LTYPE3, AMOVWD,
312 	"MOVWF",		LTYPE3, AMOVWF,
313 
314 	"LDREX",		LTYPE3, ALDREX,
315 	"LDREXD",		LTYPE3, ALDREXD,
316 	"STREX",		LTYPE9, ASTREX,
317 	"STREXD",		LTYPE9, ASTREXD,
318 
319 /*
320 	"ABSF",		LTYPEI, AABSF,
321 	"ABSD",		LTYPEI, AABSD,
322 	"NEGF",		LTYPEI, ANEGF,
323 	"NEGD",		LTYPEI, ANEGD,
324 	"SQTF",		LTYPEI,	ASQTF,
325 	"SQTD",		LTYPEI,	ASQTD,
326 	"RNDF",		LTYPEI,	ARNDF,
327 	"RNDD",		LTYPEI,	ARNDD,
328 	"URDF",		LTYPEI,	AURDF,
329 	"URDD",		LTYPEI,	AURDD,
330 	"NRMF",		LTYPEI,	ANRMF,
331 	"NRMD",		LTYPEI,	ANRMD,
332 */
333 
334 	"SQRTF",	LTYPEI, ASQRTF,
335 	"SQRTD",	LTYPEI, ASQRTD,
336 	"CMPF",		LTYPEL, ACMPF,
337 	"CMPD",		LTYPEL, ACMPD,
338 	"ADDF",		LTYPEK,	AADDF,
339 	"ADDD",		LTYPEK,	AADDD,
340 	"SUBF",		LTYPEK,	ASUBF,
341 	"SUBD",		LTYPEK,	ASUBD,
342 	"MULF",		LTYPEK,	AMULF,
343 	"MULD",		LTYPEK,	AMULD,
344 	"DIVF",		LTYPEK,	ADIVF,
345 	"DIVD",		LTYPEK,	ADIVD,
346 
347 	"B",		LTYPE4, AB,
348 	"BL",		LTYPE4, ABL,
349 	"BX",		LTYPEBX,	ABX,
350 
351 	"BEQ",		LTYPE5,	ABEQ,
352 	"BNE",		LTYPE5,	ABNE,
353 	"BCS",		LTYPE5,	ABCS,
354 	"BHS",		LTYPE5,	ABHS,
355 	"BCC",		LTYPE5,	ABCC,
356 	"BLO",		LTYPE5,	ABLO,
357 	"BMI",		LTYPE5,	ABMI,
358 	"BPL",		LTYPE5,	ABPL,
359 	"BVS",		LTYPE5,	ABVS,
360 	"BVC",		LTYPE5,	ABVC,
361 	"BHI",		LTYPE5,	ABHI,
362 	"BLS",		LTYPE5,	ABLS,
363 	"BGE",		LTYPE5,	ABGE,
364 	"BLT",		LTYPE5,	ABLT,
365 	"BGT",		LTYPE5,	ABGT,
366 	"BLE",		LTYPE5,	ABLE,
367 	"BCASE",	LTYPE5,	ABCASE,
368 
369 	"SWI",		LTYPE6, ASWI,
370 
371 	"CMP",		LTYPE7,	ACMP,
372 	"TST",		LTYPE7,	ATST,
373 	"TEQ",		LTYPE7,	ATEQ,
374 	"CMN",		LTYPE7,	ACMN,
375 
376 	"MOVM",		LTYPE8, AMOVM,
377 
378 	"SWPBU",	LTYPE9, ASWPBU,
379 	"SWPW",		LTYPE9, ASWPW,
380 
381 	"RET",		LTYPEA, ARET,
382 	"RFE",		LTYPEA, ARFE,
383 
384 	"TEXT",		LTYPEB, ATEXT,
385 	"GLOBL",	LTYPEB, AGLOBL,
386 	"DATA",		LTYPEC, ADATA,
387 	"CASE",		LTYPED, ACASE,
388 	"END",		LTYPEE, AEND,
389 	"WORD",		LTYPEH, AWORD,
390 	"NOP",		LTYPEI, ANOP,
391 
392 	"MCR",		LTYPEJ, 0,
393 	"MRC",		LTYPEJ, 1,
394 	0
395 };
396 
397 void
398 cinit(void)
399 {
400 	Sym *s;
401 	int i;
402 
403 	nullgen.sym = S;
404 	nullgen.offset = 0;
405 	nullgen.type = D_NONE;
406 	nullgen.name = D_NONE;
407 	nullgen.reg = NREG;
408 	if(FPCHIP)
409 		nullgen.dval = 0;
410 	for(i=0; i<sizeof(nullgen.sval); i++)
411 		nullgen.sval[i] = 0;
412 
413 	nerrors = 0;
414 	iostack = I;
415 	iofree = I;
416 	peekc = IGN;
417 	nhunk = 0;
418 	for(i=0; i<NHASH; i++)
419 		hash[i] = S;
420 	for(i=0; itab[i].name; i++) {
421 		s = slookup(itab[i].name);
422 		s->type = itab[i].type;
423 		s->value = itab[i].value;
424 	}
425 
426 	pathname = allocn(pathname, 0, 100);
427 	if(getwd(pathname, 99) == 0) {
428 		pathname = allocn(pathname, 100, 900);
429 		if(getwd(pathname, 999) == 0)
430 			strcpy(pathname, "/?");
431 	}
432 }
433 
434 void
435 syminit(Sym *s)
436 {
437 
438 	s->type = LNAME;
439 	s->value = 0;
440 }
441 
442 int
443 isreg(Gen *g)
444 {
445 
446 	USED(g);
447 	return 1;
448 }
449 
450 void
451 cclean(void)
452 {
453 
454 	outcode(AEND, Always, &nullgen, NREG, &nullgen);
455 	Bflush(&obuf);
456 }
457 
458 void
459 zname(char *n, int t, int s)
460 {
461 
462 	Bputc(&obuf, ANAME);
463 	Bputc(&obuf, t);	/* type */
464 	Bputc(&obuf, s);	/* sym */
465 	while(*n) {
466 		Bputc(&obuf, *n);
467 		n++;
468 	}
469 	Bputc(&obuf, 0);
470 }
471 
472 void
473 zaddr(Gen *a, int s)
474 {
475 	long l;
476 	int i;
477 	char *n;
478 	Ieee e;
479 
480 	Bputc(&obuf, a->type);
481 	Bputc(&obuf, a->reg);
482 	Bputc(&obuf, s);
483 	Bputc(&obuf, a->name);
484 	switch(a->type) {
485 	default:
486 		print("unknown type %d\n", a->type);
487 		exits("arg");
488 
489 	case D_NONE:
490 	case D_REG:
491 	case D_FREG:
492 	case D_PSR:
493 	case D_FPCR:
494 		break;
495 
496 	case D_REGREG:
497 		Bputc(&obuf, a->offset);
498 		break;
499 
500 	case D_OREG:
501 	case D_CONST:
502 	case D_BRANCH:
503 	case D_SHIFT:
504 		l = a->offset;
505 		Bputc(&obuf, l);
506 		Bputc(&obuf, l>>8);
507 		Bputc(&obuf, l>>16);
508 		Bputc(&obuf, l>>24);
509 		break;
510 
511 	case D_SCONST:
512 		n = a->sval;
513 		for(i=0; i<NSNAME; i++) {
514 			Bputc(&obuf, *n);
515 			n++;
516 		}
517 		break;
518 
519 	case D_FCONST:
520 		ieeedtod(&e, a->dval);
521 		Bputc(&obuf, e.l);
522 		Bputc(&obuf, e.l>>8);
523 		Bputc(&obuf, e.l>>16);
524 		Bputc(&obuf, e.l>>24);
525 		Bputc(&obuf, e.h);
526 		Bputc(&obuf, e.h>>8);
527 		Bputc(&obuf, e.h>>16);
528 		Bputc(&obuf, e.h>>24);
529 		break;
530 	}
531 }
532 
533 static int bcode[] =
534 {
535 	ABEQ,
536 	ABNE,
537 	ABCS,
538 	ABCC,
539 	ABMI,
540 	ABPL,
541 	ABVS,
542 	ABVC,
543 	ABHI,
544 	ABLS,
545 	ABGE,
546 	ABLT,
547 	ABGT,
548 	ABLE,
549 	AB,
550 	ANOP,
551 };
552 
553 void
554 outcode(int a, int scond, Gen *g1, int reg, Gen *g2)
555 {
556 	int sf, st, t;
557 	Sym *s;
558 
559 	/* hack to make B.NE etc. work: turn it into the corresponding conditional */
560 	if(a == AB){
561 		a = bcode[scond&0xf];
562 		scond = (scond & ~0xf) | Always;
563 	}
564 
565 	if(pass == 1)
566 		goto out;
567 jackpot:
568 	sf = 0;
569 	s = g1->sym;
570 	while(s != S) {
571 		sf = s->sym;
572 		if(sf < 0 || sf >= NSYM)
573 			sf = 0;
574 		t = g1->name;
575 		if(h[sf].type == t)
576 		if(h[sf].sym == s)
577 			break;
578 		zname(s->name, t, sym);
579 		s->sym = sym;
580 		h[sym].sym = s;
581 		h[sym].type = t;
582 		sf = sym;
583 		sym++;
584 		if(sym >= NSYM)
585 			sym = 1;
586 		break;
587 	}
588 	st = 0;
589 	s = g2->sym;
590 	while(s != S) {
591 		st = s->sym;
592 		if(st < 0 || st >= NSYM)
593 			st = 0;
594 		t = g2->name;
595 		if(h[st].type == t)
596 		if(h[st].sym == s)
597 			break;
598 		zname(s->name, t, sym);
599 		s->sym = sym;
600 		h[sym].sym = s;
601 		h[sym].type = t;
602 		st = sym;
603 		sym++;
604 		if(sym >= NSYM)
605 			sym = 1;
606 		if(st == sf)
607 			goto jackpot;
608 		break;
609 	}
610 	Bputc(&obuf, a);
611 	Bputc(&obuf, scond);
612 	Bputc(&obuf, reg);
613 	Bputc(&obuf, lineno);
614 	Bputc(&obuf, lineno>>8);
615 	Bputc(&obuf, lineno>>16);
616 	Bputc(&obuf, lineno>>24);
617 	zaddr(g1, sf);
618 	zaddr(g2, st);
619 
620 out:
621 	if(a != AGLOBL && a != ADATA)
622 		pc++;
623 }
624 
625 void
626 outhist(void)
627 {
628 	Gen g;
629 	Hist *h;
630 	char *p, *q, *op, c;
631 	int n;
632 
633 	g = nullgen;
634 	c = pathchar();
635 	for(h = hist; h != H; h = h->link) {
636 		p = h->name;
637 		op = 0;
638 		/* on windows skip drive specifier in pathname */
639 		if(systemtype(Windows) && p && p[1] == ':'){
640 			p += 2;
641 			c = *p;
642 		}
643 		if(p && p[0] != c && h->offset == 0 && pathname){
644 			/* on windows skip drive specifier in pathname */
645 			if(systemtype(Windows) && pathname[1] == ':') {
646 				op = p;
647 				p = pathname+2;
648 				c = *p;
649 			} else if(pathname[0] == c){
650 				op = p;
651 				p = pathname;
652 			}
653 		}
654 		while(p) {
655 			q = strchr(p, c);
656 			if(q) {
657 				n = q-p;
658 				if(n == 0){
659 					n = 1;	/* leading "/" */
660 					*p = '/';	/* don't emit "\" on windows */
661 				}
662 				q++;
663 			} else {
664 				n = strlen(p);
665 				q = 0;
666 			}
667 			if(n) {
668 				Bputc(&obuf, ANAME);
669 				Bputc(&obuf, D_FILE);	/* type */
670 				Bputc(&obuf, 1);	/* sym */
671 				Bputc(&obuf, '<');
672 				Bwrite(&obuf, p, n);
673 				Bputc(&obuf, 0);
674 			}
675 			p = q;
676 			if(p == 0 && op) {
677 				p = op;
678 				op = 0;
679 			}
680 		}
681 		g.offset = h->offset;
682 
683 		Bputc(&obuf, AHISTORY);
684 		Bputc(&obuf, Always);
685 		Bputc(&obuf, 0);
686 		Bputc(&obuf, h->line);
687 		Bputc(&obuf, h->line>>8);
688 		Bputc(&obuf, h->line>>16);
689 		Bputc(&obuf, h->line>>24);
690 		zaddr(&nullgen, 0);
691 		zaddr(&g, 0);
692 	}
693 }
694 
695 #include "../cc/lexbody"
696 #include "../cc/macbody"
697