xref: /plan9-contrib/sys/src/cmd/qa/lex.c (revision d46c239f8612929b7dbade67d0d071633df3a15d)
1 #include <u.h>
2 #include <libc.h>
3 #include <ctype.h>
4 #include <bio.h>
5 #include "../qc/q.out.h"
6 #include "a.h"
7 #include "y.tab.h"
8 
9 void
10 main(int argc, char *argv[])
11 {
12 	char *p;
13 	int nout, nproc, status, i, c;
14 
15 	thechar = 'q';
16 	thestring = "power";
17 	memset(debug, 0, sizeof(debug));
18 	cinit();
19 	outfile = 0;
20 	include[ninclude++] = ".";
21 	ARGBEGIN {
22 	default:
23 		c = ARGC();
24 		if(c >= 0 || c < sizeof(debug))
25 			debug[c] = 1;
26 		break;
27 
28 	case 'o':
29 		outfile = ARGF();
30 		break;
31 
32 	case 'D':
33 		p = ARGF();
34 		if(p)
35 			Dlist[nDlist++] = p;
36 		break;
37 
38 	case 'I':
39 		p = ARGF();
40 		setinclude(p);
41 		break;
42 	} ARGEND
43 	if(*argv == 0) {
44 		print("usage: %ca [-options] file.s\n", thechar);
45 		errorexit();
46 	}
47 	if(argc > 1 && systemtype(Windows)){
48 		print("can't assemble multiple files on windows\n");
49 		errorexit();
50 	}
51 	if(argc > 1 && !systemtype(Windows)) {
52 		nproc = 1;
53 		if(p = getenv("NPROC"))
54 			nproc = atol(p);	/* */
55 		c = 0;
56 		nout = 0;
57 		for(;;) {
58 			while(nout < nproc && argc > 0) {
59 				i = myfork();
60 				if(i < 0) {
61 					i = mywait(&status);
62 					if(i < 0)
63 						errorexit();
64 					if(status)
65 						c++;
66 					nout--;
67 					continue;
68 				}
69 				if(i == 0) {
70 					print("%s:\n", *argv);
71 					if(assemble(*argv))
72 						errorexit();
73 					exits(0);
74 				}
75 				nout++;
76 				argc--;
77 				argv++;
78 			}
79 			i = mywait(&status);
80 			if(i < 0) {
81 				if(c)
82 					errorexit();
83 				exits(0);
84 			}
85 			if(status)
86 				c++;
87 			nout--;
88 		}
89 	}
90 	if(assemble(argv[0]))
91 		errorexit();
92 	exits(0);
93 }
94 
95 int
96 assemble(char *file)
97 {
98 	char ofile[100], incfile[20], *p;
99 	int i, of;
100 
101 	strcpy(ofile, file);
102 	p = utfrrune(ofile, pathchar());
103 	if(p) {
104 		include[0] = ofile;
105 		*p++ = 0;
106 	} else
107 		p = ofile;
108 	if(outfile == 0) {
109 		outfile = p;
110 		if(outfile){
111 			p = utfrrune(outfile, '.');
112 			if(p)
113 				if(p[1] == 's' && p[2] == 0)
114 					p[0] = 0;
115 			p = utfrune(outfile, 0);
116 			p[0] = '.';
117 			p[1] = thechar;
118 			p[2] = 0;
119 		} else
120 			outfile = "/dev/null";
121 	}
122 	p = getenv("INCLUDE");
123 	if(p) {
124 		setinclude(p);
125 	} else {
126 		if(systemtype(Plan9)) {
127 			sprint(incfile,"/%s/include", thestring);
128 			setinclude(strdup(incfile));
129 		}
130 	}
131 
132 	of = mycreat(outfile, 0664);
133 	if(of < 0) {
134 		yyerror("%ca: cannot create %s", thechar, outfile);
135 		errorexit();
136 	}
137 	Binit(&obuf, of, OWRITE);
138 
139 	pass = 1;
140 	pinit(file);
141 	for(i=0; i<nDlist; i++)
142 		dodefine(Dlist[i]);
143 	yyparse();
144 	if(nerrors) {
145 		cclean();
146 		return nerrors;
147 	}
148 
149 	pass = 2;
150 	outhist();
151 	pinit(file);
152 	for(i=0; i<nDlist; i++)
153 		dodefine(Dlist[i]);
154 	yyparse();
155 	cclean();
156 	return nerrors;
157 }
158 
159 struct
160 {
161 	char	*name;
162 	ushort	type;
163 	ushort	value;
164 } itab[] =
165 {
166 	"SP",		LSP,	D_AUTO,
167 	"SB",		LSB,	D_EXTERN,
168 	"FP",		LFP,	D_PARAM,
169 	"PC",		LPC,	D_BRANCH,
170 
171 	"LR",		LLR,	D_LR,
172 	"CTR",		LCTR,	D_CTR,
173 
174 	"XER",		LSPREG,	D_XER,
175 	"MSR",		LMSR,	D_MSR,
176 	"FPSCR",	LFPSCR,	D_FPSCR,
177 	"SPR",		LSPR,	D_SPR,
178 
179 	"SEG",		LSEG,	D_SREG,
180 
181 	"CR",		LCR,	0,
182 	"CR0",		LCREG,	0,
183 	"CR1",		LCREG,	1,
184 	"CR2",		LCREG,	2,
185 	"CR3",		LCREG,	3,
186 	"CR4",		LCREG,	4,
187 	"CR5",		LCREG,	5,
188 	"CR6",		LCREG,	6,
189 	"CR7",		LCREG,	7,
190 
191 	"R",		LR,	0,
192 	"R0",		LREG,	0,
193 	"R1",		LREG,	1,
194 	"R2",		LREG,	2,
195 	"R3",		LREG,	3,
196 	"R4",		LREG,	4,
197 	"R5",		LREG,	5,
198 	"R6",		LREG,	6,
199 	"R7",		LREG,	7,
200 	"R8",		LREG,	8,
201 	"R9",		LREG,	9,
202 	"R10",		LREG,	10,
203 	"R11",		LREG,	11,
204 	"R12",		LREG,	12,
205 	"R13",		LREG,	13,
206 	"R14",		LREG,	14,
207 	"R15",		LREG,	15,
208 	"R16",		LREG,	16,
209 	"R17",		LREG,	17,
210 	"R18",		LREG,	18,
211 	"R19",		LREG,	19,
212 	"R20",		LREG,	20,
213 	"R21",		LREG,	21,
214 	"R22",		LREG,	22,
215 	"R23",		LREG,	23,
216 	"R24",		LREG,	24,
217 	"R25",		LREG,	25,
218 	"R26",		LREG,	26,
219 	"R27",		LREG,	27,
220 	"R28",		LREG,	28,
221 	"R29",		LREG,	29,
222 	"R30",		LREG,	30,
223 	"R31",		LREG,	31,
224 
225 	"F",		LF,	0,
226 	"F0",		LFREG,	0,
227 	"F1",		LFREG,	1,
228 	"F2",		LFREG,	2,
229 	"F3",		LFREG,	3,
230 	"F4",		LFREG,	4,
231 	"F5",		LFREG,	5,
232 	"F6",		LFREG,	6,
233 	"F7",		LFREG,	7,
234 	"F8",		LFREG,	8,
235 	"F9",		LFREG,	9,
236 	"F10",		LFREG,	10,
237 	"F11",		LFREG,	11,
238 	"F12",		LFREG,	12,
239 	"F13",		LFREG,	13,
240 	"F14",		LFREG,	14,
241 	"F15",		LFREG,	15,
242 	"F16",		LFREG,	16,
243 	"F17",		LFREG,	17,
244 	"F18",		LFREG,	18,
245 	"F19",		LFREG,	19,
246 	"F20",		LFREG,	20,
247 	"F21",		LFREG,	21,
248 	"F22",		LFREG,	22,
249 	"F23",		LFREG,	23,
250 	"F24",		LFREG,	24,
251 	"F25",		LFREG,	25,
252 	"F26",		LFREG,	26,
253 	"F27",		LFREG,	27,
254 	"F28",		LFREG,	28,
255 	"F29",		LFREG,	29,
256 	"F30",		LFREG,	30,
257 	"F31",		LFREG,	31,
258 
259 	"CREQV",	LCROP, ACREQV,
260 	"CRXOR",	LCROP, ACRXOR,
261 	"CRAND",	LCROP, ACRAND,
262 	"CROR",		LCROP, ACROR,
263 	"CRANDN",	LCROP, ACRANDN,
264 	"CRORN",	LCROP, ACRORN,
265 	"CRNAND",	LCROP, ACRNAND,
266 	"CRNOR",	LCROP, ACRNOR,
267 
268 	"ADD",		LADDW, AADD,
269 	"ADDV",		LADDW, AADDV,
270 	"ADDCC",	LADDW, AADDCC,
271 	"ADDVCC",	LADDW, AADDVCC,
272 	"ADDC",		LADDW, AADDC,
273 	"ADDCV",	LADDW, AADDCV,
274 	"ADDCCC",	LADDW, AADDCCC,
275 	"ADDCVCC",	LADDW, AADDCVCC,
276 	"ADDE",		LLOGW, AADDE,
277 	"ADDEV",	LLOGW, AADDEV,
278 	"ADDECC",	LLOGW, AADDECC,
279 	"ADDEVCC",	LLOGW, AADDEVCC,
280 
281 	"ADDME",	LABS, AADDME,
282 	"ADDMEV",	LABS, AADDMEV,
283 	"ADDMECC",	LABS, AADDMECC,
284 	"ADDMEVCC",	LABS, AADDMEVCC,
285 	"ADDZE",	LABS, AADDZE,
286 	"ADDZEV",	LABS, AADDZEV,
287 	"ADDZECC",	LABS, AADDZECC,
288 	"ADDZEVCC",	LABS, AADDZEVCC,
289 
290 	"SUB",		LADDW, ASUB,
291 	"SUBV",		LADDW, ASUBV,
292 	"SUBCC",	LADDW, ASUBCC,
293 	"SUBVCC",	LADDW, ASUBVCC,
294 	"SUBE",		LLOGW, ASUBE,
295 	"SUBECC",	LLOGW, ASUBECC,
296 	"SUBEV",	LLOGW, ASUBEV,
297 	"SUBEVCC",	LLOGW, ASUBEVCC,
298 	"SUBC",		LADDW, ASUBC,
299 	"SUBCCC",	LADDW, ASUBCCC,
300 	"SUBCV",	LADDW, ASUBCV,
301 	"SUBCVCC",	LADDW, ASUBCVCC,
302 
303 	"SUBME",	LABS, ASUBME,
304 	"SUBMEV",	LABS, ASUBMEV,
305 	"SUBMECC",	LABS, ASUBMECC,
306 	"SUBMEVCC",	LABS, ASUBMEVCC,
307 	"SUBZE",	LABS, ASUBZE,
308 	"SUBZEV",	LABS, ASUBZEV,
309 	"SUBZECC",	LABS, ASUBZECC,
310 	"SUBZEVCC",	LABS, ASUBZEVCC,
311 
312 	"AND",		LADDW, AAND,
313 	"ANDCC",	LADDW, AANDCC,	/* includes andil & andiu */
314 	"ANDN",		LLOGW, AANDN,
315 	"ANDNCC",	LLOGW, AANDNCC,
316 	"EQV",		LLOGW, AEQV,
317 	"EQVCC",	LLOGW, AEQVCC,
318 	"NAND",		LLOGW, ANAND,
319 	"NANDCC",	LLOGW, ANANDCC,
320 	"NOR",		LLOGW, ANOR,
321 	"NORCC",	LLOGW, ANORCC,
322 	"OR",		LADDW, AOR,	/* includes oril & oriu */
323 	"ORCC",		LADDW, AORCC,
324 	"ORN",		LLOGW, AORN,
325 	"ORNCC",	LLOGW, AORNCC,
326 	"XOR",		LADDW, AXOR,	/* includes xoril & xoriu */
327 	"XORCC",	LLOGW, AXORCC,
328 
329 	"EXTSB",	LABS,	AEXTSB,
330 	"EXTSBCC",	LABS,	AEXTSBCC,
331 	"EXTSH",	LABS, AEXTSH,
332 	"EXTSHCC",	LABS, AEXTSHCC,
333 
334 	"CNTLZW",	LABS, ACNTLZW,
335 	"CNTLZWCC",	LABS, ACNTLZWCC,
336 
337 	"RLWMI",	LRLWM, ARLWMI,
338 	"RLWMICC",	LRLWM, ARLWMICC,
339 	"RLWNM",	LRLWM, ARLWNM,
340 	"RLWNMCC", LRLWM, ARLWNMCC,
341 
342 	"SLW",		LSHW, ASLW,
343 	"SLWCC",	LSHW, ASLWCC,
344 	"SRW",		LSHW, ASRW,
345 	"SRWCC",	LSHW, ASRWCC,
346 	"SRAW",		LSHW, ASRAW,
347 	"SRAWCC",	LSHW, ASRAWCC,
348 
349 	"BR",		LBRA, ABR,
350 	"BC",		LBRA, ABC,
351 	"BCL",		LBRA, ABC,
352 	"BL",		LBRA, ABL,
353 	"BEQ",		LBRA, ABEQ,
354 	"BNE",		LBRA, ABNE,
355 	"BGT",		LBRA, ABGT,
356 	"BGE",		LBRA, ABGE,
357 	"BLT",		LBRA, ABLT,
358 	"BLE",		LBRA, ABLE,
359 	"BVC",		LBRA, ABVC,
360 	"BVS",		LBRA, ABVS,
361 
362 	"CMP",		LCMP, ACMP,
363 	"CMPU",		LCMP, ACMPU,
364 
365 	"DIVW",		LLOGW, ADIVW,
366 	"DIVWV",	LLOGW, ADIVWV,
367 	"DIVWCC",	LLOGW, ADIVWCC,
368 	"DIVWVCC",	LLOGW, ADIVWVCC,
369 	"DIVWU",	LLOGW, ADIVWU,
370 	"DIVWUV",	LLOGW, ADIVWUV,
371 	"DIVWUCC",	LLOGW, ADIVWUCC,
372 	"DIVWUVCC",	LLOGW, ADIVWUVCC,
373 
374 	"FABS",		LFCONV,	AFABS,
375 	"FABSCC",	LFCONV,	AFABSCC,
376 	"FNEG",		LFCONV,	AFNEG,
377 	"FNEGCC",	LFCONV,	AFNEGCC,
378 	"FNABS",	LFCONV,	AFNABS,
379 	"FNABSCC",	LFCONV,	AFNABSCC,
380 
381 	"FADD",		LFADD,	AFADD,
382 	"FADDCC",	LFADD,	AFADDCC,
383 	"FSUB",		LFADD,  AFSUB,
384 	"FSUBCC",	LFADD,	AFSUBCC,
385 	"FMUL",		LFADD,	AFMUL,
386 	"FMULCC",	LFADD,	AFMULCC,
387 	"FDIV",		LFADD,	AFDIV,
388 	"FDIVCC",	LFADD,	AFDIVCC,
389 	"FRSP",		LFCONV,	AFRSP,
390 	"FRSPCC",	LFCONV,	AFRSPCC,
391 
392 	"FMADD",	LFMA, AFMADD,
393 	"FMADDCC",	LFMA, AFMADDCC,
394 	"FMSUB",	LFMA, AFMSUB,
395 	"FMSUBCC",	LFMA, AFMSUBCC,
396 	"FNMADD",	LFMA, AFNMADD,
397 	"FNMADDCC",	LFMA, AFNMADDCC,
398 	"FNMSUB",	LFMA, AFNMSUB,
399 	"FNMSUBCC",	LFMA, AFNMSUBCC,
400 	"FMADDS",	LFMA, AFMADDS,
401 	"FMADDSCC",	LFMA, AFMADDSCC,
402 	"FMSUBS",	LFMA, AFMSUBS,
403 	"FMSUBSCC",	LFMA, AFMSUBSCC,
404 	"FNMADDS",	LFMA, AFNMADDS,
405 	"FNMADDSCC",	LFMA, AFNMADDSCC,
406 	"FNMSUBS",	LFMA, AFNMSUBS,
407 	"FNMSUBSCC",	LFMA, AFNMSUBSCC,
408 
409 	"FCMPU",	LFCMP, AFCMPU,
410 	"FCMPO",	LFCMP, AFCMPO,
411 	"MTFSB0",	LMTFSB, AMTFSB0,
412 	"MTFSB1",	LMTFSB,	AMTFSB1,
413 
414 	"FMOVD",	LFMOV, AFMOVD,
415 	"FMOVS",	LFMOV, AFMOVS,
416 	"FMOVDCC",	LFCONV,	AFMOVDCC,	/* fmr. */
417 
418 	"GLOBL",	LTEXT, AGLOBL,
419 
420 	"MOVB",		LMOVB, AMOVB,
421 	"MOVBZ",	LMOVB, AMOVBZ,
422 	"MOVBU",	LMOVB, AMOVBU,
423 	"MOVBZU", LMOVB, AMOVBZU,
424 	"MOVH",		LMOVB, AMOVH,
425 	"MOVHZ",	LMOVB, AMOVHZ,
426 	"MOVHU",	LMOVB, AMOVHU,
427 	"MOVHZU", LMOVB, AMOVHZU,
428 	"MOVHBR", 	LXMV, AMOVHBR,
429 	"MOVWBR",	LXMV, AMOVWBR,
430 	"MOVW",		LMOVW, AMOVW,
431 	"MOVWU",	LMOVW, AMOVWU,
432 	"MOVMW",	LMOVMW, AMOVMW,
433 	"MOVFL",	LMOVW,	AMOVFL,
434 
435 	"MULLW",	LADDW, AMULLW,		/* includes multiply immediate 10-139 */
436 	"MULLWV",	LLOGW, AMULLWV,
437 	"MULLWCC",	LLOGW, AMULLWCC,
438 	"MULLWVCC",	LLOGW, AMULLWVCC,
439 
440 	"MULHW",	LLOGW, AMULHW,
441 	"MULHWCC",	LLOGW, AMULHWCC,
442 	"MULHWU",	LLOGW, AMULHWU,
443 	"MULHWUCC",	LLOGW, AMULHWUCC,
444 
445 	"NEG",		LABS, ANEG,
446 	"NEGV",		LABS, ANEGV,
447 	"NEGCC",	LABS, ANEGCC,
448 	"NEGVCC",	LABS, ANEGVCC,
449 
450 	"NOP",		LNOP, ANOP,	/* ori 0,0,0 */
451 	"SYSCALL",	LNOP, ASYSCALL,
452 
453 	"RETURN",	LRETRN, ARETURN,
454 	"RFI",		LRETRN,	ARFI,
455 
456 	"DATA",		LDATA, ADATA,
457 	"END",		LEND, AEND,
458 	"TEXT",		LTEXT, ATEXT,
459 
460 /* special instructions */
461 	"DCBF",		LXOP,	ADCBF,
462 	"DCBI",		LXOP,	ADCBI,
463 	"DCBST",	LXOP,	ADCBST,
464 	"DCBT",		LXOP,	ADCBT,
465 	"DCBTST",	LXOP,	ADCBTST,
466 	"DCBZ",		LXOP,	ADCBZ,
467 	"ICBI",		LXOP,	AICBI,
468 
469 	"ECIWX",	LXLD,	AECIWX,
470 	"ECOWX",	LXST,	AECOWX,
471 	"LWAR", LXLD, ALWAR,
472 	"STWCCC", LXST, ASTWCCC,
473 	"EIEIO",	LRETRN,	AEIEIO,
474 	"TLBIE",	LNOP,	ATLBIE,
475 	"LSW",	LXLD, ALSW,
476 	"STSW",	LXST, ASTSW,
477 
478 	"ISYNC",	LRETRN, AISYNC,
479 	"SYNC",		LRETRN, ASYNC,
480 /*	"TW",		LADDW,	ATW,*/
481 
482 	"WORD",		LWORD, AWORD,
483 	"SCHED",	LSCHED, 0,
484 	"NOSCHED",	LSCHED,	0x80,
485 
486 	0
487 };
488 
489 void
490 cinit(void)
491 {
492 	Sym *s;
493 	int i;
494 
495 	nullgen.sym = S;
496 	nullgen.offset = 0;
497 	nullgen.type = D_NONE;
498 	nullgen.name = D_NONE;
499 	nullgen.reg = NREG;
500 	nullgen.xreg = NREG;
501 	if(FPCHIP)
502 		nullgen.dval = 0;
503 	for(i=0; i<sizeof(nullgen.sval); i++)
504 		nullgen.sval[i] = 0;
505 
506 	nerrors = 0;
507 	iostack = I;
508 	iofree = I;
509 	peekc = IGN;
510 	nhunk = 0;
511 	for(i=0; i<NHASH; i++)
512 		hash[i] = S;
513 	for(i=0; itab[i].name; i++) {
514 		s = slookup(itab[i].name);
515 		s->type = itab[i].type;
516 		s->value = itab[i].value;
517 	}
518 	ALLOCN(pathname, 0, 100);
519 	if(getwd(pathname, 99) == 0) {
520 		ALLOCN(pathname, 100, 900);
521 		if(getwd(pathname, 999) == 0)
522 			strcpy(pathname, "/???");
523 	}
524 }
525 
526 void
527 syminit(Sym *s)
528 {
529 
530 	s->type = LNAME;
531 	s->value = 0;
532 }
533 
534 void
535 cclean(void)
536 {
537 
538 	outcode(AEND, &nullgen, NREG, &nullgen);
539 	Bflush(&obuf);
540 }
541 
542 void
543 zname(char *n, int t, int s)
544 {
545 
546 	Bputc(&obuf, ANAME);
547 	Bputc(&obuf, t);	/* type */
548 	Bputc(&obuf, s);	/* sym */
549 	while(*n) {
550 		Bputc(&obuf, *n);
551 		n++;
552 	}
553 	Bputc(&obuf, 0);
554 }
555 
556 void
557 zaddr(Gen *a, int s)
558 {
559 	long l;
560 	int i;
561 	char *n;
562 	Ieee e;
563 
564 	Bputc(&obuf, a->type);
565 	Bputc(&obuf, a->reg);
566 	Bputc(&obuf, s);
567 	Bputc(&obuf, a->name);
568 	switch(a->type) {
569 	default:
570 		print("unknown type %d\n", a->type);
571 		exits("arg");
572 
573 	case D_NONE:
574 	case D_REG:
575 	case D_FREG:
576 	case D_CREG:
577 	case D_FPSCR:
578 	case D_MSR:
579 	case D_SREG:
580 	case D_OPT:
581 		break;
582 
583 	case D_SPR:
584 	case D_OREG:
585 	case D_CONST:
586 	case D_BRANCH:
587 		l = a->offset;
588 		Bputc(&obuf, l);
589 		Bputc(&obuf, l>>8);
590 		Bputc(&obuf, l>>16);
591 		Bputc(&obuf, l>>24);
592 		break;
593 
594 	case D_SCONST:
595 		n = a->sval;
596 		for(i=0; i<NSNAME; i++) {
597 			Bputc(&obuf, *n);
598 			n++;
599 		}
600 		break;
601 
602 	case D_FCONST:
603 		ieeedtod(&e, a->dval);
604 		Bputc(&obuf, e.l);
605 		Bputc(&obuf, e.l>>8);
606 		Bputc(&obuf, e.l>>16);
607 		Bputc(&obuf, e.l>>24);
608 		Bputc(&obuf, e.h);
609 		Bputc(&obuf, e.h>>8);
610 		Bputc(&obuf, e.h>>16);
611 		Bputc(&obuf, e.h>>24);
612 		break;
613 	}
614 }
615 
616 int
617 outsim(Gen *g)
618 {
619 	Sym *s;
620 	int sno, t;
621 
622 	s = g->sym;
623 	if(s == S)
624 		return 0;
625 	sno = s->sym;
626 	if(sno < 0 || sno >= NSYM)
627 		sno = 0;
628 	t = g->name;
629 	if(h[sno].type == t && h[sno].sym == s)
630 		return sno;
631 	zname(s->name, t, sym);
632 	s->sym = sym;
633 	h[sym].sym = s;
634 	h[sym].type = t;
635 	sno = sym;
636 	sym++;
637 	if(sym >= NSYM)
638 		sym = 1;
639 	return sno;
640 }
641 
642 void
643 outcode(int a, Gen *g1, int reg, Gen *g2)
644 {
645 	int sf, st;
646 
647 	if(a != AGLOBL && a != ADATA)
648 		pc++;
649 	if(pass == 1)
650 		return;
651 	if(g1->xreg != NREG) {
652 		if(reg != NREG || g2->xreg != NREG)
653 			yyerror("bad addressing modes");
654 		reg = g1->xreg;
655 	} else
656 	if(g2->xreg != NREG) {
657 		if(reg != NREG)
658 			yyerror("bad addressing modes");
659 		reg = g2->xreg;
660 	}
661 	do {
662 		sf = outsim(g1);
663 		st = outsim(g2);
664 	} while(sf != 0 && st == sf);
665 	Bputc(&obuf, a);
666 	Bputc(&obuf, reg|nosched);
667 	Bputc(&obuf, lineno);
668 	Bputc(&obuf, lineno>>8);
669 	Bputc(&obuf, lineno>>16);
670 	Bputc(&obuf, lineno>>24);
671 	zaddr(g1, sf);
672 	zaddr(g2, st);
673 }
674 
675 void
676 outgcode(int a, Gen *g1, int reg, Gen *g2, Gen *g3)
677 {
678 	int s1, s2, s3, flag;
679 
680 	if(a != AGLOBL && a != ADATA)
681 		pc++;
682 	if(pass == 1)
683 		return;
684 	do {
685 		s1 = outsim(g1);
686 		s2 = outsim(g2);
687 		s3 = outsim(g3);
688 	} while(s1 && (s2 && s1 == s2 || s3 && s1 == s3) || s2 && (s3 && s2 == s3));
689 	flag = 0;
690 	if(g2->type != D_NONE)
691 		flag = 0x40;	/* flags extra operand */
692 	Bputc(&obuf, a);
693 	Bputc(&obuf, reg | nosched | flag);
694 	Bputc(&obuf, lineno);
695 	Bputc(&obuf, lineno>>8);
696 	Bputc(&obuf, lineno>>16);
697 	Bputc(&obuf, lineno>>24);
698 	zaddr(g1, s1);
699 	if(flag)
700 		zaddr(g2, s2);
701 	zaddr(g3, s3);
702 }
703 
704 void
705 outhist(void)
706 {
707 	Gen g;
708 	Hist *h;
709 	char *p, *q, *op;
710 	int n;
711 
712 	g = nullgen;
713 	for(h = hist; h != H; h = h->link) {
714 		p = h->name;
715 		op = 0;
716 		if(p && p[0] != '/' && h->offset == 0 && pathname && pathname[0] == '/') {
717 			op = p;
718 			p = pathname;
719 		}
720 		while(p) {
721 			q = strchr(p, '/');
722 			if(q) {
723 				n = q-p;
724 				if(n == 0)
725 					n = 1;	/* leading "/" */
726 				q++;
727 			} else {
728 				n = strlen(p);
729 				q = 0;
730 			}
731 			if(n) {
732 				Bputc(&obuf, ANAME);
733 				Bputc(&obuf, D_FILE);	/* type */
734 				Bputc(&obuf, 1);	/* sym */
735 				Bputc(&obuf, '<');
736 				Bwrite(&obuf, p, n);
737 				Bputc(&obuf, 0);
738 			}
739 			p = q;
740 			if(p == 0 && op) {
741 				p = op;
742 				op = 0;
743 			}
744 		}
745 		g.offset = h->offset;
746 
747 		Bputc(&obuf, AHISTORY);
748 		Bputc(&obuf, 0);
749 		Bputc(&obuf, h->line);
750 		Bputc(&obuf, h->line>>8);
751 		Bputc(&obuf, h->line>>16);
752 		Bputc(&obuf, h->line>>24);
753 		zaddr(&nullgen, 0);
754 		zaddr(&g, 0);
755 	}
756 }
757 
758 void
759 praghjdicks(void)
760 {
761 	while(getnsc() != '\n')
762 		;
763 }
764 
765 void
766 pragvararg(void)
767 {
768 	while(getnsc() != '\n')
769 		;
770 }
771 
772 void
773 pragfpround(void)
774 {
775 	while(getnsc() != '\n')
776 		;
777 }
778 
779 #include "../cc/lexbody"
780 #include "../cc/macbody"
781 #include "../cc/compat"
782