xref: /plan9-contrib/sys/src/cmd/ia/lex.c (revision ce95e1b3727b9cb1c223ffbed69aff21a8ced255)
1 #include <ctype.h>
2 #define	EXTERN
3 #include "a.h"
4 #include "y.tab.h"
5 
6 void
main(int argc,char * argv[])7 main(int argc, char *argv[])
8 {
9 	char *p;
10 	int nout, nproc, status, i, c;
11 
12 	thechar = 'i';
13 	p = strrchr(argv[0], '/');
14 	if(p == nil)
15 		p = argv[0];
16 	else
17 		p++;
18 	if(*p == 'j')
19 		thechar = 'j';
20 	memset(debug, 0, sizeof(debug));
21 	cinit();
22 	outfile = 0;
23 	include[ninclude++] = ".";
24 	ARGBEGIN {
25 	default:
26 		c = ARGC();
27 		if(c >= 0 || c < sizeof(debug))
28 			debug[c] = 1;
29 		break;
30 
31 	case 'o':
32 		outfile = ARGF();
33 		break;
34 
35 	case 'D':
36 		p = ARGF();
37 		if(p)
38 			Dlist[nDlist++] = p;
39 		break;
40 
41 	case 'I':
42 		p = ARGF();
43 		setinclude(p);
44 		break;
45 
46 	} ARGEND
47 	if(*argv == 0) {
48 		print("usage: %ca [-options] file.s\n", thechar);
49 		errorexit();
50 	}
51 	if(debug['j'])
52 		thechar = 'j';
53 	thestring = (thechar == 'j'? "riscv64" : "riscv");
54 	if(argc > 1 && systemtype(Windows)){
55 		print("can't assemble multiple files on windows\n");
56 		errorexit();
57 	}
58 	if(argc > 1 && !systemtype(Windows)) {
59 		nproc = 1;
60 		if(p = getenv("NPROC"))
61 			nproc = atol(p);	/* */
62 		c = 0;
63 		nout = 0;
64 		for(;;) {
65 			while(nout < nproc && argc > 0) {
66 				i = myfork();
67 				if(i < 0) {
68 					i = mywait(&status);
69 					if(i < 0)
70 						errorexit();
71 					if(status)
72 						c++;
73 					nout--;
74 					continue;
75 				}
76 				if(i == 0) {
77 					print("%s:\n", *argv);
78 					if(assemble(*argv))
79 						errorexit();
80 					exits(0);
81 				}
82 				nout++;
83 				argc--;
84 				argv++;
85 			}
86 			i = mywait(&status);
87 			if(i < 0) {
88 				if(c)
89 					errorexit();
90 				exits(0);
91 			}
92 			if(status)
93 				c++;
94 			nout--;
95 		}
96 	}
97 	if(assemble(argv[0]))
98 		errorexit();
99 	exits(0);
100 }
101 
102 int
assemble(char * file)103 assemble(char *file)
104 {
105 	char ofile[100], incfile[20], *p;
106 	int i, of;
107 
108 	strcpy(ofile, file);
109 	p = utfrrune(ofile, pathchar());
110 	if(p) {
111 		include[0] = ofile;
112 		*p++ = 0;
113 	} else
114 		p = ofile;
115 	if(outfile == 0) {
116 		outfile = p;
117 		if(outfile){
118 			p = utfrrune(outfile, '.');
119 			if(p)
120 				if(p[1] == 's' && p[2] == 0)
121 					p[0] = 0;
122 			p = utfrune(outfile, 0);
123 			p[0] = '.';
124 			p[1] = thechar;
125 			p[2] = 0;
126 		} else
127 			outfile = "/dev/null";
128 	}
129 	p = getenv("INCLUDE");
130 	if(p) {
131 		setinclude(p);
132 	} else {
133 		if(systemtype(Plan9)) {
134 			sprint(incfile,"/%s/include", thestring);
135 			setinclude(strdup(incfile));
136 		}
137 	}
138 
139 	of = mycreat(outfile, 0664);
140 	if(of < 0) {
141 		yyerror("%ca: cannot create %s", thechar, outfile);
142 		errorexit();
143 	}
144 	Binit(&obuf, of, OWRITE);
145 
146 	pass = 1;
147 	pinit(file);
148 	if(thechar == 'j')
149 		dodefine("XLEN=8");
150 	else
151 		dodefine("XLEN=4");
152 	for(i=0; i<nDlist; i++)
153 		dodefine(Dlist[i]);
154 	yyparse();
155 	if(nerrors) {
156 		cclean();
157 		return nerrors;
158 	}
159 
160 	pass = 2;
161 	outhist();
162 	pinit(file);
163 	if(thechar == 'j')
164 		dodefine("XLEN=8");
165 	else
166 		dodefine("XLEN=4");
167 	for(i=0; i<nDlist; i++)
168 		dodefine(Dlist[i]);
169 	yyparse();
170 	cclean();
171 	return nerrors;
172 }
173 
174 struct
175 {
176 	char	*name;
177 	ushort	type;
178 	ushort	value;
179 } itab[] =
180 {
181 	"SP",		LSP,	D_AUTO,
182 	"SB",		LSB,	D_EXTERN,
183 	"FP",		LFP,	D_PARAM,
184 	"PC",		LPC,	D_BRANCH,
185 
186 	"R",		LR,	0,
187 	"R0",		LREG,	0,
188 	"R1",		LREG,	1,
189 	"R2",		LREG,	2,
190 	"R3",		LREG,	3,
191 	"R4",		LREG,	4,
192 	"R5",		LREG,	5,
193 	"R6",		LREG,	6,
194 	"R7",		LREG,	7,
195 	"R8",		LREG,	8,
196 	"R9",		LREG,	9,
197 	"R10",		LREG,	10,
198 	"R11",		LREG,	11,
199 	"R12",		LREG,	12,
200 	"R13",		LREG,	13,
201 	"R14",		LREG,	14,
202 	"R15",		LREG,	15,
203 	"R16",		LREG,	16,
204 	"R17",		LREG,	17,
205 	"R18",		LREG,	18,
206 	"R19",		LREG,	19,
207 	"R20",		LREG,	20,
208 	"R21",		LREG,	21,
209 	"R22",		LREG,	22,
210 	"R23",		LREG,	23,
211 	"R24",		LREG,	24,
212 	"R25",		LREG,	25,
213 	"R26",		LREG,	26,
214 	"R27",		LREG,	27,
215 	"R28",		LREG,	28,
216 	"R29",		LREG,	29,
217 	"R30",		LREG,	30,
218 	"R31",		LREG,	31,
219 
220 	"F",		FR,	0,
221 	"F0",		LFREG,	0,
222 	"F1",		LFREG,	1,
223 	"F2",		LFREG,	2,
224 	"F3",		LFREG,	3,
225 	"F4",		LFREG,	4,
226 	"F5",		LFREG,	5,
227 	"F6",		LFREG,	6,
228 	"F7",		LFREG,	7,
229 	"F8",		LFREG,	8,
230 	"F9",		LFREG,	9,
231 	"F10",		LFREG,	10,
232 	"F11",		LFREG,	11,
233 	"F12",		LFREG,	12,
234 	"F13",		LFREG,	13,
235 	"F14",		LFREG,	14,
236 	"F15",		LFREG,	15,
237 	"F16",		LFREG,	16,
238 	"F17",		LFREG,	17,
239 	"F18",		LFREG,	18,
240 	"F19",		LFREG,	19,
241 	"F20",		LFREG,	20,
242 	"F21",		LFREG,	21,
243 	"F22",		LFREG,	22,
244 	"F23",		LFREG,	23,
245 	"F24",		LFREG,	24,
246 	"F25",		LFREG,	25,
247 	"F26",		LFREG,	26,
248 	"F27",		LFREG,	27,
249 	"F28",		LFREG,	28,
250 	"F29",		LFREG,	29,
251 	"F30",		LFREG,	30,
252 	"F31",		LFREG,	31,
253 
254 	"CSR",		LCTL,	0,
255 
256 	"ADD",		LADD,	AADD,
257 	"SLL",		LADD,	ASLL,
258 	"SLT",		LADD,	ASLT,
259 	"SLTU",		LADD,	ASLTU,
260 	"XOR",		LADD,	AXOR,
261 	"SRL",		LADD,	ASRL,
262 	"OR",		LADD,	AOR,
263 	"AND",		LADD,	AAND,
264 	"SRA",		LADD,	ASRA,
265 	"ADDW",		LADD,	AADDW,
266 	"SLLW",		LADD,	ASLLW,
267 	"SRLW",		LADD,	ASRLW,
268 	"SRAW",		LADD,	ASRAW,
269 	"SUB",		LADD,	ASUB,
270 	"SUBW",		LADD,	ASUBW,
271 
272 	"MUL",		LMUL,	AMUL,
273 	"MULH",		LMUL,	AMULH,
274 	"MULHSU",	LMUL,	AMULHSU,
275 	"MULHU",	LMUL,	AMULHU,
276 	"DIV",		LMUL,	ADIV,
277 	"DIVU",		LMUL,	ADIVU,
278 	"REM",		LMUL,	AREM,
279 	"REMU",		LMUL,	AREMU,
280 	"MULW",		LMUL,	AMULW,
281 	"DIVW",		LMUL,	ADIVW,
282 	"DIVUW",	LMUL,	ADIVUW,
283 	"REMW",		LMUL,	AREMW,
284 	"REMUW",	LMUL,	AREMUW,
285 
286 	"BEQ",		LBEQ,	ABEQ,
287 	"BNE",		LBEQ,	ABNE,
288 	"BLT",		LBEQ,	ABLT,
289 	"BGE",		LBEQ,	ABGE,
290 	"BLTU",		LBEQ,	ABLTU,
291 	"BGEU",		LBEQ,	ABGEU,
292 	"BGT",		LBEQ,	ABGT,
293 	"BGTU",		LBEQ,	ABGTU,
294 	"BLE",		LBEQ,	ABLE,
295 	"BLEU",		LBEQ,	ABLEU,
296 
297 	"JMP",		LBR,	AJMP,
298 
299 	"RET",		LBRET,	ARET,
300 	"FENCE_I",	LBRET,	AFENCE_I,
301 	"NOP",		LBRET,	ANOP,
302 	"END",		LBRET,	AEND,
303 
304 	"JAL",		LCALL,	AJAL,
305 	"JALR",		LCALL,	AJAL,
306 
307 	"MOVB",		LMOVB,	AMOVB,
308 	"MOVH",		LMOVB,	AMOVH,
309 
310 	"MOVF",		LMOVF,	AMOVF,
311 	"MOVD",		LMOVF,	AMOVD,
312 
313 	"MOVBU",	LMOVBU,	AMOVBU,
314 	"MOVHU",	LMOVBU,	AMOVHU,
315 
316 	"MOVW",		LMOVW,	AMOVW,
317 
318 	"MOVFD",	LFLT2,	AMOVFD,
319 	"MOVDF",	LFLT2,	AMOVDF,
320 	"MOVWF",	LFLT2,	AMOVWF,
321 	"MOVUF",	LFLT2,	AMOVUF,
322 	"MOVFW",	LFLT2,	AMOVFW,
323 	"MOVWD",	LFLT2,	AMOVWD,
324 	"MOVUD",	LFLT2,	AMOVUD,
325 	"MOVDW",	LFLT2,	AMOVDW,
326 	"ADDF",		LFLT3,	AADDF,
327 	"ADDD",		LFLT3,	AADDD,
328 	"SUBF",		LFLT3,	ASUBF,
329 	"SUBD",		LFLT3,	ASUBD,
330 	"MULF",		LFLT3,	AMULF,
331 	"MULD",		LFLT3,	AMULD,
332 	"DIVF",		LFLT3,	ADIVF,
333 	"DIVD",		LFLT3,	ADIVD,
334 	"CMPLTF",	LFLT3,	ACMPLTF,
335 	"CMPLTD",	LFLT3,	ACMPLTD,
336 	"CMPEQF",	LFLT3,	ACMPEQF,
337 	"CMPEQD",	LFLT3,	ACMPEQD,
338 	"CMPLEF",	LFLT3,	ACMPLEF,
339 	"CMPLED",	LFLT3,	ACMPLED,
340 
341 	"LUI",		LLUI,	ALUI,
342 
343 	"SYS",		LSYS,	ASYS,
344 	"ECALL",	LSYS0,	0,
345 	"EBREAK",	LSYS0,	1,
346 	"CSRRW",	LCSR,	ACSRRW,
347 	"CSRRS",	LCSR,	ACSRRS,
348 	"CSRRC",	LCSR,	ACSRRC,
349 
350 	"SWAP_W",	LSWAP,	ASWAP_W,
351 	"SWAP_D",	LSWAP,	ASWAP_D,
352 	"LR_W",		LSWAP,	ALR_W,
353 	"LR_D",		LSWAP,	ALR_D,
354 	"SC_W",		LSWAP,	ASC_W,
355 	"SC_D",		LSWAP,	ASC_D,
356 
357 	"AMO_W",	LAMO,	AAMO_W,
358 	"AMO_D",	LAMO,	AAMO_D,
359 
360 	"DATA",		LDATA, 		ADATA,
361 	"GLOBL",	LTEXT, 		AGLOBL,
362 	"TEXT",		LTEXT, 		ATEXT,
363 	"WORD",		LWORD,		AWORD,
364 	"DWORD",	LWORD,		ADWORD,
365 
366 	"MOV",		LMOVW,		AMOV,
367 	"MOVWU",	LMOVBU,		AMOVWU,
368 
369 	0
370 };
371 
372 void
cinit(void)373 cinit(void)
374 {
375 	Sym *s;
376 	int i;
377 
378 	nullgen.sym = S;
379 	nullgen.offset = 0;
380 	nullgen.type = D_NONE;
381 	nullgen.name = D_NONE;
382 	nullgen.reg = NREG;
383 	if(FPCHIP)
384 		nullgen.dval = 0;
385 	for(i=0; i<sizeof(nullgen.sval); i++)
386 		nullgen.sval[i] = 0;
387 
388 	nerrors = 0;
389 	iostack = I;
390 	iofree = I;
391 	peekc = IGN;
392 	nhunk = 0;
393 	for(i=0; i<NHASH; i++)
394 		hash[i] = S;
395 	for(i=0; itab[i].name; i++) {
396 		s = slookup(itab[i].name);
397 		s->type = itab[i].type;
398 		s->value = itab[i].value;
399 	}
400 
401 	pathname = allocn(pathname, 0, 100);
402 	if(mygetwd(pathname, 99) == 0) {
403 		pathname = allocn(pathname, 100, 900);
404 		if(mygetwd(pathname, 999) == 0)
405 			strcpy(pathname, "/???");
406 	}
407 }
408 
409 void
syminit(Sym * s)410 syminit(Sym *s)
411 {
412 
413 	s->type = LNAME;
414 	s->value = 0;
415 }
416 
417 void
cclean(void)418 cclean(void)
419 {
420 
421 	outcode(AEND, &nullgen, NREG, &nullgen);
422 	Bflush(&obuf);
423 }
424 
425 void
zname(char * n,int t,int s)426 zname(char *n, int t, int s)
427 {
428 
429 	Bputc(&obuf, ANAME);
430 	Bputc(&obuf, t);	/* type */
431 	Bputc(&obuf, s);	/* sym */
432 	while(*n) {
433 		Bputc(&obuf, *n);
434 		n++;
435 	}
436 	Bputc(&obuf, 0);
437 }
438 
439 void
zaddr(Gen * a,int s)440 zaddr(Gen *a, int s)
441 {
442 	vlong v;
443 	long l;
444 	int i;
445 	char *n;
446 	Ieee e;
447 
448 	Bputc(&obuf, a->type);
449 	Bputc(&obuf, a->reg);
450 	Bputc(&obuf, s);
451 	Bputc(&obuf, a->name);
452 	switch(a->type) {
453 	default:
454 		print("unknown type %d\n", a->type);
455 		exits("arg");
456 
457 	case D_NONE:
458 	case D_REG:
459 	case D_FREG:
460 		break;
461 
462 	case D_CTLREG:
463 	case D_OREG:
464 	case D_CONST:
465 	case D_BRANCH:
466 		l = a->offset;
467 		Bputc(&obuf, l);
468 		Bputc(&obuf, l>>8);
469 		Bputc(&obuf, l>>16);
470 		Bputc(&obuf, l>>24);
471 		break;
472 
473 	case D_VCONST:
474 		v = a->vval;
475 		Bputc(&obuf, v);
476 		Bputc(&obuf, v>>8);
477 		Bputc(&obuf, v>>16);
478 		Bputc(&obuf, v>>24);
479 		Bputc(&obuf, v>>32);
480 		Bputc(&obuf, v>>40);
481 		Bputc(&obuf, v>>48);
482 		Bputc(&obuf, v>>56);
483 		break;
484 
485 	case D_SCONST:
486 		n = a->sval;
487 		for(i=0; i<NSNAME; i++) {
488 			Bputc(&obuf, *n);
489 			n++;
490 		}
491 		break;
492 
493 	case D_FCONST:
494 		ieeedtod(&e, a->dval);
495 		Bputc(&obuf, e.l);
496 		Bputc(&obuf, e.l>>8);
497 		Bputc(&obuf, e.l>>16);
498 		Bputc(&obuf, e.l>>24);
499 		Bputc(&obuf, e.h);
500 		Bputc(&obuf, e.h>>8);
501 		Bputc(&obuf, e.h>>16);
502 		Bputc(&obuf, e.h>>24);
503 		break;
504 	}
505 }
506 
507 void
outcode(int a,Gen * g1,int reg,Gen * g2)508 outcode(int a, Gen *g1, int reg, Gen *g2)
509 {
510 	int sf, st, t;
511 	Sym *s;
512 
513 	if(pass == 1)
514 		goto out;
515 jackpot:
516 	sf = 0;
517 	s = g1->sym;
518 	while(s != S) {
519 		sf = s->sym;
520 		if(sf < 0 || sf >= NSYM)
521 			sf = 0;
522 		t = g1->name;
523 		if(h[sf].type == t)
524 		if(h[sf].sym == s)
525 			break;
526 		zname(s->name, t, sym);
527 		s->sym = sym;
528 		h[sym].sym = s;
529 		h[sym].type = t;
530 		sf = sym;
531 		sym++;
532 		if(sym >= NSYM)
533 			sym = 1;
534 		break;
535 	}
536 	st = 0;
537 	s = g2->sym;
538 	while(s != S) {
539 		st = s->sym;
540 		if(st < 0 || st >= NSYM)
541 			st = 0;
542 		t = g2->name;
543 		if(h[st].type == t)
544 		if(h[st].sym == s)
545 			break;
546 		zname(s->name, t, sym);
547 		s->sym = sym;
548 		h[sym].sym = s;
549 		h[sym].type = t;
550 		st = sym;
551 		sym++;
552 		if(sym >= NSYM)
553 			sym = 1;
554 		if(st == sf)
555 			goto jackpot;
556 		break;
557 	}
558 	Bputc(&obuf, a);
559 	Bputc(&obuf, reg);
560 	Bputc(&obuf, lineno);
561 	Bputc(&obuf, lineno>>8);
562 	Bputc(&obuf, lineno>>16);
563 	Bputc(&obuf, lineno>>24);
564 	zaddr(g1, sf);
565 	zaddr(g2, st);
566 
567 out:
568 	if(a != AGLOBL && a != ADATA)
569 		pc++;
570 }
571 
572 void
outhist(void)573 outhist(void)
574 {
575 	Gen g;
576 	Hist *h;
577 	char *p, *q, *op, c;
578 	int n;
579 
580 	g = nullgen;
581 	c = pathchar();
582 	for(h = hist; h != H; h = h->link) {
583 		p = h->name;
584 		op = 0;
585 		/* on windows skip drive specifier in pathname */
586 		if(systemtype(Windows) && p && p[1] == ':'){
587 			p += 2;
588 			c = *p;
589 		}
590 		if(p && p[0] != c && h->offset == 0 && pathname){
591 			/* on windows skip drive specifier in pathname */
592 			if(systemtype(Windows) && pathname[1] == ':') {
593 				op = p;
594 				p = pathname+2;
595 				c = *p;
596 			} else if(pathname[0] == c){
597 				op = p;
598 				p = pathname;
599 			}
600 		}
601 		while(p) {
602 			q = strchr(p, c);
603 			if(q) {
604 				n = q-p;
605 				if(n == 0){
606 					n = 1;	/* leading "/" */
607 					*p = '/';	/* don't emit "\" on windows */
608 				}
609 				q++;
610 			} else {
611 				n = strlen(p);
612 				q = 0;
613 			}
614 			if(n) {
615 				Bputc(&obuf, ANAME);
616 				Bputc(&obuf, D_FILE);	/* type */
617 				Bputc(&obuf, 1);	/* sym */
618 				Bputc(&obuf, '<');
619 				Bwrite(&obuf, p, n);
620 				Bputc(&obuf, 0);
621 			}
622 			p = q;
623 			if(p == 0 && op) {
624 				p = op;
625 				op = 0;
626 			}
627 		}
628 		g.offset = h->offset;
629 
630 		Bputc(&obuf, AHISTORY);
631 		Bputc(&obuf, 0);
632 		Bputc(&obuf, h->line);
633 		Bputc(&obuf, h->line>>8);
634 		Bputc(&obuf, h->line>>16);
635 		Bputc(&obuf, h->line>>24);
636 		zaddr(&nullgen, 0);
637 		zaddr(&g, 0);
638 	}
639 }
640 
641 #include "../cc/lexbody"
642 #include "../cc/macbody"
643 #include "../cc/compat"
644