xref: /plan9/sys/src/cmd/va/lex.c (revision 911786034cac6871dcb40c81c4e19848e099a127)
1 #define	EXTERN
2 #include "a.h"
3 #include "y.tab.h"
4 #include <ctype.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 = 'v';
13 	thestring = "mips";
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  'L':			/* for little-endian mips */
40 		thechar = '0';
41 		thestring = "spim";
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
assemble(char * file)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 	"HI",		LHI,	D_HI,
172 	"LO",		LLO,	D_LO,
173 
174 	"R",		LR,	0,
175 	"R0",		LREG,	0,
176 	"R1",		LREG,	1,
177 	"R2",		LREG,	2,
178 	"R3",		LREG,	3,
179 	"R4",		LREG,	4,
180 	"R5",		LREG,	5,
181 	"R6",		LREG,	6,
182 	"R7",		LREG,	7,
183 	"R8",		LREG,	8,
184 	"R9",		LREG,	9,
185 	"R10",		LREG,	10,
186 	"R11",		LREG,	11,
187 	"R12",		LREG,	12,
188 	"R13",		LREG,	13,
189 	"R14",		LREG,	14,
190 	"R15",		LREG,	15,
191 	"R16",		LREG,	16,
192 	"R17",		LREG,	17,
193 	"R18",		LREG,	18,
194 	"R19",		LREG,	19,
195 	"R20",		LREG,	20,
196 	"R21",		LREG,	21,
197 	"R22",		LREG,	22,
198 	"R23",		LREG,	23,
199 	"R24",		LREG,	24,
200 	"R25",		LREG,	25,
201 	"R26",		LREG,	26,
202 	"R27",		LREG,	27,
203 	"R28",		LREG,	28,
204 	"R29",		LREG,	29,
205 	"R30",		LREG,	30,
206 	"R31",		LREG,	31,
207 
208 	"M",		LM,	0,
209 	"M0",		LMREG,	0,
210 	"M1",		LMREG,	1,
211 	"M2",		LMREG,	2,
212 	"M3",		LMREG,	3,
213 	"M4",		LMREG,	4,
214 	"M5",		LMREG,	5,
215 	"M6",		LMREG,	6,
216 	"M7",		LMREG,	7,
217 	"M8",		LMREG,	8,
218 	"M9",		LMREG,	9,
219 	"M10",		LMREG,	10,
220 	"M11",		LMREG,	11,
221 	"M12",		LMREG,	12,
222 	"M13",		LMREG,	13,
223 	"M14",		LMREG,	14,
224 	"M15",		LMREG,	15,
225 	"M16",		LMREG,	16,
226 	"M17",		LMREG,	17,
227 	"M18",		LMREG,	18,
228 	"M19",		LMREG,	19,
229 	"M20",		LMREG,	20,
230 	"M21",		LMREG,	21,
231 	"M22",		LMREG,	22,
232 	"M23",		LMREG,	23,
233 	"M24",		LMREG,	24,
234 	"M25",		LMREG,	25,
235 	"M26",		LMREG,	26,
236 	"M27",		LMREG,	27,
237 	"M28",		LMREG,	28,
238 	"M29",		LMREG,	29,
239 	"M30",		LMREG,	30,
240 	"M31",		LMREG,	31,
241 
242 	"F",		LF,	0,
243 
244 	"F0",		LFREG,	0,
245 	"F1",		LFREG,	1,
246 	"F2",		LFREG,	2,
247 	"F3",		LFREG,	3,
248 	"F4",		LFREG,	4,
249 	"F5",		LFREG,	5,
250 	"F6",		LFREG,	6,
251 	"F7",		LFREG,	7,
252 	"F8",		LFREG,	8,
253 	"F9",		LFREG,	9,
254 	"F10",		LFREG,	10,
255 	"F11",		LFREG,	11,
256 	"F12",		LFREG,	12,
257 	"F13",		LFREG,	13,
258 	"F14",		LFREG,	14,
259 	"F15",		LFREG,	15,
260 	"F16",		LFREG,	16,
261 	"F17",		LFREG,	17,
262 	"F18",		LFREG,	18,
263 	"F19",		LFREG,	19,
264 	"F20",		LFREG,	20,
265 	"F21",		LFREG,	21,
266 	"F22",		LFREG,	22,
267 	"F23",		LFREG,	23,
268 	"F24",		LFREG,	24,
269 	"F25",		LFREG,	25,
270 	"F26",		LFREG,	26,
271 	"F27",		LFREG,	27,
272 	"F28",		LFREG,	28,
273 	"F29",		LFREG,	29,
274 	"F30",		LFREG,	30,
275 	"F31",		LFREG,	31,
276 
277 	"FCR",		LFCR,	0,
278 	"FCR0",		LFCREG,	0,
279 	"FCR1",		LFCREG,	1,
280 	"FCR2",		LFCREG,	2,
281 	"FCR3",		LFCREG,	3,
282 	"FCR4",		LFCREG,	4,
283 	"FCR5",		LFCREG,	5,
284 	"FCR6",		LFCREG,	6,
285 	"FCR7",		LFCREG,	7,
286 	"FCR8",		LFCREG,	8,
287 	"FCR9",		LFCREG,	9,
288 	"FCR10",	LFCREG,	10,
289 	"FCR11",	LFCREG,	11,
290 	"FCR12",	LFCREG,	12,
291 	"FCR13",	LFCREG,	13,
292 	"FCR14",	LFCREG,	14,
293 	"FCR15",	LFCREG,	15,
294 	"FCR16",	LFCREG,	16,
295 	"FCR17",	LFCREG,	17,
296 	"FCR18",	LFCREG,	18,
297 	"FCR19",	LFCREG,	19,
298 	"FCR20",	LFCREG,	20,
299 	"FCR21",	LFCREG,	21,
300 	"FCR22",	LFCREG,	22,
301 	"FCR23",	LFCREG,	23,
302 	"FCR24",	LFCREG,	24,
303 	"FCR25",	LFCREG,	25,
304 	"FCR26",	LFCREG,	26,
305 	"FCR27",	LFCREG,	27,
306 	"FCR28",	LFCREG,	28,
307 	"FCR29",	LFCREG,	29,
308 	"FCR30",	LFCREG,	30,
309 	"FCR31",	LFCREG,	31,
310 
311 	"ADD",		LTYPE1, AADD,
312 	"ADDU",		LTYPE1, AADDU,
313 	"SUB",		LTYPE1, ASUB,	/* converted to ADD(-) in loader */
314 	"SUBU",		LTYPE1, ASUBU,
315 	"SGT",		LTYPE1, ASGT,
316 	"SGTU",		LTYPE1, ASGTU,
317 	"AND",		LTYPE1, AAND,
318 	"OR",		LTYPE1, AOR,
319 	"XOR",		LTYPE1, AXOR,
320 	"SLL",		LTYPE1, ASLL,
321 	"SRL",		LTYPE1, ASRL,
322 	"SRA",		LTYPE1, ASRA,
323 
324 	"ADDV",		LTYPE1, AADDV,
325 	"ADDVU",		LTYPE1, AADDVU,
326 	"SUBV",		LTYPE1, ASUBV,	/* converted to ADD(-) in loader */
327 	"SUBVU",		LTYPE1, ASUBVU,
328 	"SLLV",		LTYPE1, ASLLV,
329 	"SRLV",		LTYPE1, ASRLV,
330 	"SRAV",		LTYPE1, ASRAV,
331 
332 	"NOR",		LTYPE2, ANOR,
333 
334 	"MOVB",		LTYPE3, AMOVB,
335 	"MOVBU",	LTYPE3, AMOVBU,
336 	"MOVH",		LTYPE3, AMOVH,
337 	"MOVHU",	LTYPE3, AMOVHU,
338 	"MOVWL",	LTYPE3, AMOVWL,
339 	"MOVWR",	LTYPE3, AMOVWR,
340 	"MOVVL",	LTYPE3, AMOVVL,
341 	"MOVVR",	LTYPE3, AMOVVR,
342 
343 	"BREAK",	LTYPEJ, ABREAK,		/* overloaded CACHE opcode */
344 	"END",		LTYPE4, AEND,
345 	"REM",		LTYPE6, AREM,
346 	"REMU",		LTYPE6, AREMU,
347 	"RET",		LTYPE4, ARET,
348 	"SYSCALL",	LTYPE4, ASYSCALL,
349 	"TLBP",		LTYPE4, ATLBP,
350 	"TLBR",		LTYPE4, ATLBR,
351 	"TLBWI",	LTYPE4, ATLBWI,
352 	"TLBWR",	LTYPE4, ATLBWR,
353 
354 	"MOVW",		LTYPE5, AMOVW,
355 	"MOVV",		LTYPE5, AMOVV,
356 	"MOVD",		LTYPE5, AMOVD,
357 	"MOVF",		LTYPE5, AMOVF,
358 
359 	"DIV",		LTYPE6, ADIV,
360 	"DIVU",		LTYPE6, ADIVU,
361 	"MUL",		LTYPE6, AMUL,
362 	"MULU",		LTYPE6, AMULU,
363 	"DIVV",		LTYPE6, ADIVV,
364 	"DIVVU",		LTYPE6, ADIVVU,
365 	"MULV",		LTYPE6, AMULV,
366 	"MULVU",		LTYPE6, AMULVU,
367 
368 	"RFE",		LTYPE7, ARFE,
369 	"JMP",		LTYPE7, AJMP,
370 
371 	"JAL",		LTYPE8, AJAL,
372 
373 	"BEQ",		LTYPE9, ABEQ,
374 	"BNE",		LTYPE9, ABNE,
375 
376 	"BGEZ",		LTYPEA, ABGEZ,
377 	"BGEZAL",	LTYPEA, ABGEZAL,
378 	"BGTZ",		LTYPEA, ABGTZ,
379 	"BLEZ",		LTYPEA, ABLEZ,
380 	"BLTZ",		LTYPEA, ABLTZ,
381 	"BLTZAL",	LTYPEA, ABLTZAL,
382 
383 	"TEXT",		LTYPEB, ATEXT,
384 	"GLOBL",	LTYPEB, AGLOBL,
385 
386 	"DATA",		LTYPEC, ADATA,
387 
388 	"MOVDF",	LTYPE5, AMOVDF,
389 	"MOVDW",	LTYPE5, AMOVDW,
390 	"MOVFD",	LTYPE5, AMOVFD,
391 	"MOVFW",	LTYPE5, AMOVFW,
392 	"MOVWD",	LTYPE5, AMOVWD,
393 	"MOVWF",	LTYPE5, AMOVWF,
394 
395 	"ABSD",		LTYPED, AABSD,
396 	"ABSF",		LTYPED, AABSF,
397 	"ABSW",		LTYPED, AABSW,
398 	"NEGD",		LTYPED, ANEGD,
399 	"NEGF",		LTYPED, ANEGF,
400 	"NEGW",		LTYPED, ANEGW,
401 
402 	"CMPEQD",	LTYPEF, ACMPEQD,
403 	"CMPEQF",	LTYPEF, ACMPEQF,
404 	"CMPGED",	LTYPEF, ACMPGED,
405 	"CMPGEF",	LTYPEF, ACMPGEF,
406 	"CMPGTD",	LTYPEF, ACMPGTD,
407 	"CMPGTF",	LTYPEF, ACMPGTF,
408 
409 	"ADDD",		LTYPEE, AADDD,
410 	"ADDF",		LTYPEE, AADDF,
411 	"ADDW",		LTYPEE, AADDW,
412 	"DIVD",		LTYPEE, ADIVD,
413 	"DIVF",		LTYPEE, ADIVF,
414 	"DIVW",		LTYPEE, ADIVW,
415 	"MULD",		LTYPEE, AMULD,
416 	"MULF",		LTYPEE, AMULF,
417 	"MULW",		LTYPEE, AMULW,
418 	"SUBD",		LTYPEE, ASUBD,
419 	"SUBF",		LTYPEE, ASUBF,
420 	"SUBW",		LTYPEE, ASUBW,
421 
422 	"BFPT",		LTYPEG, ABFPT,
423 	"BFPF",		LTYPEG, ABFPF,
424 
425 	"WORD",		LTYPEH, AWORD,
426 	"NOP",		LTYPEI, ANOP,
427 	"SCHED",	LSCHED, 0,
428 	"NOSCHED",	LSCHED, 0x80,
429 	0
430 };
431 
432 void
cinit(void)433 cinit(void)
434 {
435 	Sym *s;
436 	int i;
437 
438 	nullgen.sym = S;
439 	nullgen.offset = 0;
440 	nullgen.type = D_NONE;
441 	nullgen.name = D_NONE;
442 	nullgen.reg = NREG;
443 	if(FPCHIP)
444 		nullgen.dval = 0;
445 	for(i=0; i<sizeof(nullgen.sval); i++)
446 		nullgen.sval[i] = 0;
447 
448 	nerrors = 0;
449 	iostack = I;
450 	iofree = I;
451 	peekc = IGN;
452 	nhunk = 0;
453 	for(i=0; i<NHASH; i++)
454 		hash[i] = S;
455 	for(i=0; itab[i].name; i++) {
456 		s = slookup(itab[i].name);
457 		s->type = itab[i].type;
458 		s->value = itab[i].value;
459 	}
460 
461 	pathname = allocn(pathname, 0, 100);
462 	if(mygetwd(pathname, 99) == 0) {
463 		pathname = allocn(pathname, 100, 900);
464 		if(mygetwd(pathname, 999) == 0)
465 			strcpy(pathname, "/???");
466 	}
467 }
468 
469 void
syminit(Sym * s)470 syminit(Sym *s)
471 {
472 
473 	s->type = LNAME;
474 	s->value = 0;
475 }
476 
477 int
isreg(Gen * g)478 isreg(Gen *g)
479 {
480 
481 	USED(g);
482 	return 1;
483 }
484 
485 void
cclean(void)486 cclean(void)
487 {
488 
489 	outcode(AEND, &nullgen, NREG, &nullgen);
490 	Bflush(&obuf);
491 }
492 
493 void
zname(char * n,int t,int s)494 zname(char *n, int t, int s)
495 {
496 
497 	Bputc(&obuf, ANAME);
498 	Bputc(&obuf, t);	/* type */
499 	Bputc(&obuf, s);	/* sym */
500 	while(*n) {
501 		Bputc(&obuf, *n);
502 		n++;
503 	}
504 	Bputc(&obuf, 0);
505 }
506 
507 void
zaddr(Gen * a,int s)508 zaddr(Gen *a, int s)
509 {
510 	long l;
511 	int i;
512 	char *n;
513 	Ieee e;
514 
515 	Bputc(&obuf, a->type);
516 	Bputc(&obuf, a->reg);
517 	Bputc(&obuf, s);
518 	Bputc(&obuf, a->name);
519 	switch(a->type) {
520 	default:
521 		print("unknown type %d\n", a->type);
522 		exits("arg");
523 
524 	case D_NONE:
525 	case D_REG:
526 	case D_FREG:
527 	case D_MREG:
528 	case D_FCREG:
529 	case D_LO:
530 	case D_HI:
531 		break;
532 
533 	case D_OREG:
534 	case D_CONST:
535 	case D_OCONST:
536 	case D_BRANCH:
537 		l = a->offset;
538 		Bputc(&obuf, l);
539 		Bputc(&obuf, l>>8);
540 		Bputc(&obuf, l>>16);
541 		Bputc(&obuf, l>>24);
542 		break;
543 
544 	case D_SCONST:
545 		n = a->sval;
546 		for(i=0; i<NSNAME; i++) {
547 			Bputc(&obuf, *n);
548 			n++;
549 		}
550 		break;
551 
552 	case D_FCONST:
553 		ieeedtod(&e, a->dval);
554 		Bputc(&obuf, e.l);
555 		Bputc(&obuf, e.l>>8);
556 		Bputc(&obuf, e.l>>16);
557 		Bputc(&obuf, e.l>>24);
558 		Bputc(&obuf, e.h);
559 		Bputc(&obuf, e.h>>8);
560 		Bputc(&obuf, e.h>>16);
561 		Bputc(&obuf, e.h>>24);
562 		break;
563 	}
564 }
565 
566 void
outcode(int a,Gen * g1,int reg,Gen * g2)567 outcode(int a, Gen *g1, int reg, Gen *g2)
568 {
569 	int sf, st, t;
570 	Sym *s;
571 
572 	if(pass == 1)
573 		goto out;
574 jackpot:
575 	sf = 0;
576 	s = g1->sym;
577 	while(s != S) {
578 		sf = s->sym;
579 		if(sf < 0 || sf >= NSYM)
580 			sf = 0;
581 		t = g1->name;
582 		if(h[sf].type == t)
583 		if(h[sf].sym == s)
584 			break;
585 		zname(s->name, t, sym);
586 		s->sym = sym;
587 		h[sym].sym = s;
588 		h[sym].type = t;
589 		sf = sym;
590 		sym++;
591 		if(sym >= NSYM)
592 			sym = 1;
593 		break;
594 	}
595 	st = 0;
596 	s = g2->sym;
597 	while(s != S) {
598 		st = s->sym;
599 		if(st < 0 || st >= NSYM)
600 			st = 0;
601 		t = g2->name;
602 		if(h[st].type == t)
603 		if(h[st].sym == s)
604 			break;
605 		zname(s->name, t, sym);
606 		s->sym = sym;
607 		h[sym].sym = s;
608 		h[sym].type = t;
609 		st = sym;
610 		sym++;
611 		if(sym >= NSYM)
612 			sym = 1;
613 		if(st == sf)
614 			goto jackpot;
615 		break;
616 	}
617 	Bputc(&obuf, a);
618 	Bputc(&obuf, reg|nosched);
619 	Bputc(&obuf, lineno);
620 	Bputc(&obuf, lineno>>8);
621 	Bputc(&obuf, lineno>>16);
622 	Bputc(&obuf, lineno>>24);
623 	zaddr(g1, sf);
624 	zaddr(g2, st);
625 
626 out:
627 	if(a != AGLOBL && a != ADATA)
628 		pc++;
629 }
630 
631 void
outhist(void)632 outhist(void)
633 {
634 	Gen g;
635 	Hist *h;
636 	char *p, *q, *op, c;
637 	int n;
638 
639 	g = nullgen;
640 	c = pathchar();
641 	for(h = hist; h != H; h = h->link) {
642 		p = h->name;
643 		op = 0;
644 		/* on windows skip drive specifier in pathname */
645 		if(systemtype(Windows) && p && p[1] == ':'){
646 			p += 2;
647 			c = *p;
648 		}
649 		if(p && p[0] != c && h->offset == 0 && pathname){
650 			/* on windows skip drive specifier in pathname */
651 			if(systemtype(Windows) && pathname[1] == ':') {
652 				op = p;
653 				p = pathname+2;
654 				c = *p;
655 			} else if(pathname[0] == c){
656 				op = p;
657 				p = pathname;
658 			}
659 		}
660 		while(p) {
661 			q = strchr(p, c);
662 			if(q) {
663 				n = q-p;
664 				if(n == 0){
665 					n = 1;	/* leading "/" */
666 					*p = '/';	/* don't emit "\" on windows */
667 				}
668 				q++;
669 			} else {
670 				n = strlen(p);
671 				q = 0;
672 			}
673 			if(n) {
674 				Bputc(&obuf, ANAME);
675 				Bputc(&obuf, D_FILE);	/* type */
676 				Bputc(&obuf, 1);	/* sym */
677 				Bputc(&obuf, '<');
678 				Bwrite(&obuf, p, n);
679 				Bputc(&obuf, 0);
680 			}
681 			p = q;
682 			if(p == 0 && op) {
683 				p = op;
684 				op = 0;
685 			}
686 		}
687 		g.offset = h->offset;
688 
689 		Bputc(&obuf, AHISTORY);
690 		Bputc(&obuf, 0);
691 		Bputc(&obuf, h->line);
692 		Bputc(&obuf, h->line>>8);
693 		Bputc(&obuf, h->line>>16);
694 		Bputc(&obuf, h->line>>24);
695 		zaddr(&nullgen, 0);
696 		zaddr(&g, 0);
697 	}
698 }
699 
700 #include "../cc/lexbody"
701 #include "../cc/macbody"
702 #include "../cc/compat"
703