xref: /inferno-os/utils/0c/txt.c (revision 74a4d8c26dd3c1e9febcb717cfd6cb6512991a7a)
1 #include "gc.h"
2 
3 void
ginit(void)4 ginit(void)
5 {
6 	int i;
7 	Type *t;
8 
9 	thechar = '0';
10 	thestring = "spim";
11 	exregoffset = REGEXT;
12 	exfregoffset = FREGEXT;
13 	listinit();
14 	nstring = 0;
15 	mnstring = 0;
16 	nrathole = 0;
17 	pc = 0;
18 	breakpc = -1;
19 	continpc = -1;
20 	cases = C;
21 	firstp = P;
22 	lastp = P;
23 	tfield = types[TLONG];
24 
25 	zprog.link = P;
26 	zprog.as = AGOK;
27 	zprog.reg = NREG;
28 	zprog.from.type = D_NONE;
29 	zprog.from.name = D_NONE;
30 	zprog.from.reg = NREG;
31 	zprog.to = zprog.from;
32 
33 	regnode.op = OREGISTER;
34 	regnode.class = CEXREG;
35 	regnode.reg = REGTMP;
36 	regnode.complex = 0;
37 	regnode.addable = 11;
38 	regnode.type = types[TLONG];
39 
40 	constnode.op = OCONST;
41 	constnode.class = CXXX;
42 	constnode.complex = 0;
43 	constnode.addable = 20;
44 	constnode.type = types[TLONG];
45 
46 	fconstnode.op = OCONST;
47 	fconstnode.class = CXXX;
48 	fconstnode.complex = 0;
49 	fconstnode.addable = 20;
50 	fconstnode.type = types[TDOUBLE];
51 
52 	nodsafe = new(ONAME, Z, Z);
53 	nodsafe->sym = slookup(".safe");
54 	nodsafe->type = types[TINT];
55 	nodsafe->etype = types[TINT]->etype;
56 	nodsafe->class = CAUTO;
57 	complex(nodsafe);
58 
59 	t = typ(TARRAY, types[TCHAR]);
60 	symrathole = slookup(".rathole");
61 	symrathole->class = CGLOBL;
62 	symrathole->type = t;
63 
64 	nodrat = new(ONAME, Z, Z);
65 	nodrat->sym = symrathole;
66 	nodrat->type = types[TIND];
67 	nodrat->etype = TVOID;
68 	nodrat->class = CGLOBL;
69 	complex(nodrat);
70 	nodrat->type = t;
71 
72 	nodret = new(ONAME, Z, Z);
73 	nodret->sym = slookup(".ret");
74 	nodret->type = types[TIND];
75 	nodret->etype = TIND;
76 	nodret->class = CPARAM;
77 	nodret = new(OIND, nodret, Z);
78 	complex(nodret);
79 
80 	for(i=0; i<nelem(reg); i++) {
81 		reg[i] = 0;
82 		if(i == REGZERO ||
83 		  (i >= NREG && ((i-NREG)&1)))
84 			reg[i] = 1;
85 	}
86 }
87 
88 void
gclean(void)89 gclean(void)
90 {
91 	int i;
92 	Sym *s;
93 
94 	for(i=0; i<NREG; i++)
95 		if(i != REGZERO)
96 			if(reg[i])
97 				diag(Z, "reg %d left allocated", i);
98 	for(i=NREG; i<NREG+NREG; i+=2)
99 		if(reg[i])
100 			diag(Z, "freg %d left allocated", i-NREG);
101 	while(mnstring)
102 		outstring("", 1L);
103 	symstring->type->width = nstring;
104 	symrathole->type->width = nrathole;
105 	for(i=0; i<NHASH; i++)
106 	for(s = hash[i]; s != S; s = s->link) {
107 		if(s->type == T)
108 			continue;
109 		if(s->type->width == 0)
110 			continue;
111 		if(s->class != CGLOBL && s->class != CSTATIC)
112 			continue;
113 		if(s->type == types[TENUM])
114 			continue;
115 		gpseudo(AGLOBL, s, nodconst(s->type->width));
116 	}
117 	nextpc();
118 	p->as = AEND;
119 	outcode();
120 }
121 
122 void
nextpc(void)123 nextpc(void)
124 {
125 
126 	p = alloc(sizeof(*p));
127 	*p = zprog;
128 	p->lineno = nearln;
129 	pc++;
130 	if(firstp == P) {
131 		firstp = p;
132 		lastp = p;
133 		return;
134 	}
135 	lastp->link = p;
136 	lastp = p;
137 }
138 
139 void
gargs(Node * n,Node * tn1,Node * tn2)140 gargs(Node *n, Node *tn1, Node *tn2)
141 {
142 	long regs;
143 	Node fnxargs[20], *fnxp;
144 
145 	regs = cursafe;
146 
147 	fnxp = fnxargs;
148 	garg1(n, tn1, tn2, 0, &fnxp);	/* compile fns to temps */
149 
150 	curarg = 0;
151 	fnxp = fnxargs;
152 	garg1(n, tn1, tn2, 1, &fnxp);	/* compile normal args and temps */
153 
154 	cursafe = regs;
155 }
156 
157 void
garg1(Node * n,Node * tn1,Node * tn2,int f,Node ** fnxp)158 garg1(Node *n, Node *tn1, Node *tn2, int f, Node **fnxp)
159 {
160 	Node nod;
161 
162 	if(n == Z)
163 		return;
164 	if(n->op == OLIST) {
165 		garg1(n->left, tn1, tn2, f, fnxp);
166 		garg1(n->right, tn1, tn2, f, fnxp);
167 		return;
168 	}
169 	if(f == 0) {
170 		if(n->complex >= FNX) {
171 			regsalloc(*fnxp, n);
172 			nod = znode;
173 			nod.op = OAS;
174 			nod.left = *fnxp;
175 			nod.right = n;
176 			nod.type = n->type;
177 			cgen(&nod, Z);
178 			(*fnxp)++;
179 		}
180 		return;
181 	}
182 	if(typesu[n->type->etype]) {
183 		regaalloc(tn2, n);
184 		if(n->complex >= FNX) {
185 			sugen(*fnxp, tn2, n->type->width);
186 			(*fnxp)++;
187 		} else
188 			sugen(n, tn2, n->type->width);
189 		return;
190 	}
191 	if(REGARG && curarg == 0 && typechlp[n->type->etype]) {
192 		regaalloc1(tn1, n);
193 		if(n->complex >= FNX) {
194 			cgen(*fnxp, tn1);
195 			(*fnxp)++;
196 		} else
197 			cgen(n, tn1);
198 		return;
199 	}
200 	if(vconst(n) == 0) {
201 		regaalloc(tn2, n);
202 		gopcode(OAS, n, Z, tn2);
203 		return;
204 	}
205 	regalloc(tn1, n, Z);
206 	if(n->complex >= FNX) {
207 		cgen(*fnxp, tn1);
208 		(*fnxp)++;
209 	} else
210 		cgen(n, tn1);
211 	regaalloc(tn2, n);
212 	gopcode(OAS, tn1, Z, tn2);
213 	regfree(tn1);
214 }
215 
216 Node*
nodconst(long v)217 nodconst(long v)
218 {
219 	constnode.vconst = v;
220 	return &constnode;
221 }
222 
223 Node*
nodfconst(double d)224 nodfconst(double d)
225 {
226 	fconstnode.fconst = d;
227 	return &fconstnode;
228 }
229 
230 void
nodreg(Node * n,Node * nn,int reg)231 nodreg(Node *n, Node *nn, int reg)
232 {
233 	*n = regnode;
234 	n->reg = reg;
235 	n->type = nn->type;
236 	n->lineno = nn->lineno;
237 }
238 
239 void
regret(Node * n,Node * nn)240 regret(Node *n, Node *nn)
241 {
242 	int r;
243 
244 	r = REGRET;
245 	if(typefd[nn->type->etype])
246 		r = FREGRET+NREG;
247 	nodreg(n, nn, r);
248 	reg[r]++;
249 }
250 
251 int
tmpreg(void)252 tmpreg(void)
253 {
254 	int i;
255 
256 	for(i=REGRET+1; i<NREG; i++)
257 		if(reg[i] == 0)
258 			return i;
259 	diag(Z, "out of fixed registers");
260 	return 0;
261 }
262 
263 void
regalloc(Node * n,Node * tn,Node * o)264 regalloc(Node *n, Node *tn, Node *o)
265 {
266 	int i, j;
267 	static int lasti;
268 
269 	switch(tn->type->etype) {
270 	case TCHAR:
271 	case TUCHAR:
272 	case TSHORT:
273 	case TUSHORT:
274 	case TINT:
275 	case TUINT:
276 	case TLONG:
277 	case TULONG:
278 	case TIND:
279 	case TUVLONG:
280 	case TVLONG:
281 		if(o != Z && o->op == OREGISTER) {
282 			i = o->reg;
283 			if(i > 0 && i < NREG)
284 				goto out;
285 		}
286 		j = lasti + REGRET+1;
287 		for(i=REGRET+1; i<NREG; i++) {
288 			if(j >= NREG)
289 				j = REGRET+1;
290 			if(reg[j] == 0) {
291 				i = j;
292 				goto out;
293 			}
294 			j++;
295 		}
296 		diag(tn, "out of fixed registers");
297 		goto err;
298 
299 	case TFLOAT:
300 	case TDOUBLE:
301 		if(o != Z && o->op == OREGISTER) {
302 			i = o->reg;
303 			if(i >= NREG && i < NREG+NREG)
304 				goto out;
305 		}
306 		j = 0*2 + NREG;
307 		for(i=NREG; i<NREG+NREG; i+=2) {
308 			if(j >= NREG+NREG)
309 				j = NREG;
310 			if(reg[j] == 0) {
311 				i = j;
312 				goto out;
313 			}
314 			j += 2;
315 		}
316 		diag(tn, "out of float registers");
317 		goto err;
318 	}
319 	diag(tn, "unknown type in regalloc: %T", tn->type);
320 err:
321 	i = 0;
322 out:
323 	if(i)
324 		reg[i]++;
325 	lasti++;
326 	if(lasti >= 5)
327 		lasti = 0;
328 	nodreg(n, tn, i);
329 }
330 
331 void
regialloc(Node * n,Node * tn,Node * o)332 regialloc(Node *n, Node *tn, Node *o)
333 {
334 	Node nod;
335 
336 	nod = *tn;
337 	nod.type = types[TIND];
338 	regalloc(n, &nod, o);
339 }
340 
341 void
regfree(Node * n)342 regfree(Node *n)
343 {
344 	int i;
345 
346 	i = 0;
347 	if(n->op != OREGISTER && n->op != OINDREG)
348 		goto err;
349 	i = n->reg;
350 	if(i < 0 || i >= sizeof(reg))
351 		goto err;
352 	if(reg[i] <= 0)
353 		goto err;
354 	reg[i]--;
355 	return;
356 err:
357 	diag(n, "error in regfree: %d", i);
358 }
359 
360 void
regsalloc(Node * n,Node * nn)361 regsalloc(Node *n, Node *nn)
362 {
363 	cursafe = align(cursafe, nn->type, Aaut3);
364 	maxargsafe = maxround(maxargsafe, cursafe+curarg);
365 	*n = *nodsafe;
366 	n->xoffset = -(stkoff + cursafe);
367 	n->type = nn->type;
368 	n->etype = nn->type->etype;
369 	n->lineno = nn->lineno;
370 }
371 
372 void
regaalloc1(Node * n,Node * nn)373 regaalloc1(Node *n, Node *nn)
374 {
375 	nodreg(n, nn, REGARG);
376 	reg[REGARG]++;
377 	curarg = align(curarg, nn->type, Aarg1);
378 	curarg = align(curarg, nn->type, Aarg2);
379 	maxargsafe = maxround(maxargsafe, cursafe+curarg);
380 }
381 
382 void
regaalloc(Node * n,Node * nn)383 regaalloc(Node *n, Node *nn)
384 {
385 	curarg = align(curarg, nn->type, Aarg1);
386 	*n = *nn;
387 	n->op = OINDREG;
388 	n->reg = REGSP;
389 	n->xoffset = curarg + SZ_VLONG;
390 	n->complex = 0;
391 	n->addable = 20;
392 	curarg = align(curarg, nn->type, Aarg2);
393 	maxargsafe = maxround(maxargsafe, cursafe+curarg);
394 }
395 
396 void
regind(Node * n,Node * nn)397 regind(Node *n, Node *nn)
398 {
399 
400 	if(n->op != OREGISTER) {
401 		diag(n, "regind not OREGISTER");
402 		return;
403 	}
404 	n->op = OINDREG;
405 	n->type = nn->type;
406 }
407 
408 void
raddr(Node * n,Prog * p)409 raddr(Node *n, Prog *p)
410 {
411 	Adr a;
412 
413 	naddr(n, &a);
414 	if(a.type == D_CONST && a.offset == 0) {
415 		a.type = D_REG;
416 		a.reg = 0;
417 	}
418 	if(a.type != D_REG && a.type != D_FREG) {
419 		if(n)
420 			diag(n, "bad in raddr: %O", n->op);
421 		else
422 			diag(n, "bad in raddr: <null>");
423 		p->reg = NREG;
424 	} else
425 		p->reg = a.reg;
426 }
427 
428 void
naddr(Node * n,Adr * a)429 naddr(Node *n, Adr *a)
430 {
431 	long v;
432 
433 	a->type = D_NONE;
434 	if(n == Z)
435 		return;
436 	switch(n->op) {
437 	default:
438 	bad:
439 		diag(n, "bad in naddr: %O", n->op);
440 		break;
441 
442 	case OREGISTER:
443 		a->type = D_REG;
444 		a->sym = S;
445 		a->reg = n->reg;
446 		if(a->reg >= NREG) {
447 			a->type = D_FREG;
448 			a->reg -= NREG;
449 		}
450 		break;
451 
452 	case OIND:
453 		naddr(n->left, a);
454 		if(a->type == D_REG) {
455 			a->type = D_OREG;
456 			break;
457 		}
458 		if(a->type == D_CONST) {
459 			a->type = D_OREG;
460 			break;
461 		}
462 		goto bad;
463 
464 	case OINDREG:
465 		a->type = D_OREG;
466 		a->sym = S;
467 		a->offset = n->xoffset;
468 		a->reg = n->reg;
469 		break;
470 
471 	case ONAME:
472 		a->etype = n->etype;
473 		a->type = D_OREG;
474 		a->name = D_STATIC;
475 		a->sym = n->sym;
476 		a->offset = n->xoffset;
477 		if(n->class == CSTATIC)
478 			break;
479 		if(n->class == CEXTERN || n->class == CGLOBL) {
480 			a->name = D_EXTERN;
481 			break;
482 		}
483 		if(n->class == CAUTO) {
484 			a->name = D_AUTO;
485 			break;
486 		}
487 		if(n->class == CPARAM) {
488 			a->name = D_PARAM;
489 			break;
490 		}
491 		goto bad;
492 
493 	case OCONST:
494 		a->sym = S;
495 		a->reg = NREG;
496 		if(typefd[n->type->etype]) {
497 			a->type = D_FCONST;
498 			a->dval = n->fconst;
499 		} else
500 		if(llconst(n)) {
501 			a->type = D_VCONST;
502 			a->vval = n->vconst;
503 		} else {
504 			a->type = D_CONST;
505 			a->offset = n->vconst;
506 		}
507 		break;
508 
509 	case OADDR:
510 		naddr(n->left, a);
511 		if(a->type == D_OREG) {
512 			a->type = D_CONST;
513 			break;
514 		}
515 		goto bad;
516 
517 	case OADD:
518 		if(n->left->op == OCONST) {
519 			naddr(n->left, a);
520 			v = a->offset;
521 			naddr(n->right, a);
522 		} else {
523 			naddr(n->right, a);
524 			v = a->offset;
525 			naddr(n->left, a);
526 		}
527 		a->offset += v;
528 		break;
529 
530 	}
531 }
532 
533 void
fop(int as,int f1,int f2,Node * t)534 fop(int as, int f1, int f2, Node *t)
535 {
536 	Node nod1, nod2, nod3;
537 
538 	nodreg(&nod1, t, NREG+f1);
539 	nodreg(&nod2, t, NREG+f2);
540 	regalloc(&nod3, t, t);
541 	gopcode(as, &nod1, &nod2, &nod3);
542 	gmove(&nod3, t);
543 	regfree(&nod3);
544 }
545 
546 void
gmove(Node * f,Node * t)547 gmove(Node *f, Node *t)
548 {
549 	int ft, tt, a;
550 	Node nod;
551 	Prog *p1;
552 	double d;
553 
554 	ft = f->type->etype;
555 	tt = t->type->etype;
556 
557 	if(ft == TDOUBLE && f->op == OCONST) {
558 		d = f->fconst;
559 		if(d == 0.0) {
560 			a = FREGZERO;
561 			goto ffreg;
562 		}
563 		if(d == 0.5) {
564 			a = FREGHALF;
565 			goto ffreg;
566 		}
567 		if(d == 1.0) {
568 			a = FREGONE;
569 			goto ffreg;
570 		}
571 		if(d == 2.0) {
572 			a = FREGTWO;
573 			goto ffreg;
574 		}
575 		if(d == -.5) {
576 			fop(OSUB, FREGHALF, FREGZERO, t);
577 			return;
578 		}
579 		if(d == -1.0) {
580 			fop(OSUB, FREGONE, FREGZERO, t);
581 			return;
582 		}
583 		if(d == -2.0) {
584 			fop(OSUB, FREGTWO, FREGZERO, t);
585 			return;
586 		}
587 		if(d == 1.5) {
588 			fop(OADD, FREGONE, FREGHALF, t);
589 			return;
590 		}
591 		if(d == 2.5) {
592 			fop(OADD, FREGTWO, FREGHALF, t);
593 			return;
594 		}
595 		if(d == 3.0) {
596 			fop(OADD, FREGTWO, FREGONE, t);
597 			return;
598 		}
599 	}
600 	if(ft == TFLOAT && f->op == OCONST) {
601 		d = f->fconst;
602 		if(d == 0) {
603 			a = FREGZERO;
604 		ffreg:
605 			nodreg(&nod, f, NREG+a);
606 			gmove(&nod, t);
607 			return;
608 		}
609 	}
610 	/*
611 	 * a load --
612 	 * put it into a register then
613 	 * worry what to do with it.
614 	 */
615 	if(f->op == ONAME || f->op == OINDREG || f->op == OIND) {
616 		switch(ft) {
617 		default:
618 			if(typefd[tt]) {
619 				/* special case can load mem to Freg */
620 				regalloc(&nod, t, t);
621 				gins(AMOVW, f, &nod);
622 				a = AMOVWD;
623 				if(tt == TFLOAT)
624 					a = AMOVWF;
625 				gins(a, &nod, &nod);
626 				gmove(&nod, t);
627 				regfree(&nod);
628 				return;
629 			}
630 			a = AMOVW;
631 			break;
632 		case TCHAR:
633 			a = AMOVB;
634 			break;
635 		case TUCHAR:
636 			a = AMOVBU;
637 			break;
638 		case TSHORT:
639 			a = AMOVH;
640 			break;
641 		case TUSHORT:
642 			a = AMOVHU;
643 			break;
644 		case TFLOAT:
645 			a = AMOVF;
646 			break;
647 		case TDOUBLE:
648 			a = AMOVD;
649 			break;
650 		case TUVLONG:
651 		case TVLONG:
652 			a = AMOVV;
653 			break;
654 		}
655 		if(typechlp[ft] && typeilp[tt])
656 			regalloc(&nod, t, t);
657 		else
658 			regalloc(&nod, f, t);
659 		gins(a, f, &nod);
660 		gmove(&nod, t);
661 		regfree(&nod);
662 		return;
663 	}
664 
665 	/*
666 	 * a store --
667 	 * put it into a register then
668 	 * store it.
669 	 */
670 	if(t->op == ONAME || t->op == OINDREG || t->op == OIND) {
671 		switch(tt) {
672 		default:
673 			a = AMOVW;
674 			break;
675 		case TUCHAR:
676 			a = AMOVBU;
677 			break;
678 		case TCHAR:
679 			a = AMOVB;
680 			break;
681 		case TUSHORT:
682 			a = AMOVHU;
683 			break;
684 		case TSHORT:
685 			a = AMOVH;
686 			break;
687 		case TFLOAT:
688 			a = AMOVF;
689 			break;
690 		case TDOUBLE:
691 			a = AMOVD;
692 			break;
693 		case TUVLONG:
694 		case TVLONG:
695 			a = AMOVV;
696 			break;
697 		}
698 		if(!typefd[ft] && vconst(f) == 0) {
699 			gins(a, f, t);
700 			return;
701 		}
702 		if(ft == tt)
703 			regalloc(&nod, t, f);
704 		else
705 			regalloc(&nod, t, Z);
706 		gmove(f, &nod);
707 		gins(a, &nod, t);
708 		regfree(&nod);
709 		return;
710 	}
711 
712 	/*
713 	 * type x type cross table
714 	 */
715 	a = AGOK;
716 	switch(ft) {
717 	case TUVLONG:
718 	case TVLONG:
719 		switch(tt) {
720 		case TUVLONG:
721 		case TVLONG:
722 			a = AMOVV;
723 			break;
724 		case TINT:
725 		case TUINT:
726 		case TLONG:
727 		case TULONG:
728 		case TIND:
729 		case TSHORT:
730 		case TUSHORT:
731 		case TCHAR:
732 		case TUCHAR:
733 			a = AMOVW;
734 			break;
735 		case TDOUBLE:
736 			gins(AMOVW, f, t);
737 			gins(AMOVWD, t, t);
738 			if(ft == TULONG || ft == TUINT) {
739 				regalloc(&nod, t, Z);
740 				gins(ACMPGED, t, Z);
741 				p->reg = FREGZERO;
742 				gins(ABFPT, Z, Z);
743 				p1 = p;
744 				gins(AMOVD, nodfconst(4294967296.), &nod);
745 				gins(AADDD, &nod, t);
746 				patch(p1, pc);
747 				regfree(&nod);
748 			}
749 			return;
750 		case TFLOAT:
751 			gins(AMOVW, f, t);
752 			gins(AMOVWF, t, t);
753 			if(ft == TULONG || ft == TUINT) {
754 				regalloc(&nod, t, Z);
755 				gins(ACMPGEF, t, Z);
756 				p->reg = FREGZERO;
757 				gins(ABFPT, Z, Z);
758 				p1 = p;
759 				gins(AMOVF, nodfconst(4294967296.), &nod);
760 				gins(AADDF, &nod, t);
761 				patch(p1, pc);
762 				regfree(&nod);
763 			}
764 			return;
765 		}
766 		break;
767 	case TDOUBLE:
768 	case TFLOAT:
769 		switch(tt) {
770 		case TDOUBLE:
771 			a = AMOVD;
772 			if(ft == TFLOAT)
773 				a = AMOVFD;
774 			break;
775 		case TFLOAT:
776 			a = AMOVDF;
777 			if(ft == TFLOAT)
778 				a = AMOVF;
779 			break;
780 		case TINT:
781 		case TUINT:
782 		case TLONG:
783 		case TULONG:
784 		case TIND:
785 		case TSHORT:
786 		case TUSHORT:
787 		case TCHAR:
788 		case TUCHAR:
789 			regalloc(&nod, f, Z);
790 			gins(ATRUNCDW, f, &nod);
791 			if(ft == TFLOAT)
792 				p->as = ATRUNCFW;
793 			gins(AMOVW, &nod, t);
794 			regfree(&nod);
795 			return;
796 		case TUVLONG:
797 		case TVLONG:
798 			regalloc(&nod, f, Z);
799 			gins(ATRUNCDV, f, &nod);
800 			if(ft == TFLOAT)
801 				p->as = ATRUNCFV;
802 			gins(AMOVV, &nod, t);
803 			regfree(&nod);
804 			return;
805 		}
806 		break;
807 	case TINT:
808 	case TUINT:
809 	case TLONG:
810 	case TULONG:
811 	case TIND:
812 		switch(tt) {
813 		case TDOUBLE:
814 			gins(AMOVW, f, t);
815 			gins(AMOVWD, t, t);
816 			if(ft == TULONG || ft == TUINT) {
817 				regalloc(&nod, t, Z);
818 				gins(ACMPGED, t, Z);
819 				p->reg = FREGZERO;
820 				gins(ABFPT, Z, Z);
821 				p1 = p;
822 				gins(AMOVD, nodfconst(4294967296.), &nod);
823 				gins(AADDD, &nod, t);
824 				patch(p1, pc);
825 				regfree(&nod);
826 			}
827 			return;
828 		case TFLOAT:
829 			gins(AMOVW, f, t);
830 			gins(AMOVWF, t, t);
831 			if(ft == TULONG || ft == TUINT) {
832 				regalloc(&nod, t, Z);
833 				gins(ACMPGEF, t, Z);
834 				p->reg = FREGZERO;
835 				gins(ABFPT, Z, Z);
836 				p1 = p;
837 				gins(AMOVF, nodfconst(4294967296.), &nod);
838 				gins(AADDF, &nod, t);
839 				patch(p1, pc);
840 				regfree(&nod);
841 			}
842 			return;
843 		case TUVLONG:
844 		case TVLONG:
845 			if(ft == TULONG || ft == TUINT) {
846 				a = AMOVWU;
847 				break;
848 			}
849 		case TINT:
850 		case TUINT:
851 		case TLONG:
852 		case TULONG:
853 		case TIND:
854 		case TSHORT:
855 		case TUSHORT:
856 		case TCHAR:
857 		case TUCHAR:
858 			a = AMOVW;
859 			break;
860 		}
861 		break;
862 	case TSHORT:
863 		switch(tt) {
864 		case TDOUBLE:
865 			regalloc(&nod, f, Z);
866 			gins(AMOVH, f, &nod);
867 			gins(AMOVW, &nod, t);
868 			gins(AMOVWD, t, t);
869 			regfree(&nod);
870 			return;
871 		case TFLOAT:
872 			regalloc(&nod, f, Z);
873 			gins(AMOVH, f, &nod);
874 			gins(AMOVW, &nod, t);
875 			gins(AMOVWF, t, t);
876 			regfree(&nod);
877 			return;
878 		case TINT:
879 		case TUINT:
880 		case TLONG:
881 		case TULONG:
882 		case TVLONG:
883 		case TUVLONG:
884 		case TIND:
885 			a = AMOVH;
886 			break;
887 		case TSHORT:
888 		case TUSHORT:
889 		case TCHAR:
890 		case TUCHAR:
891 			a = AMOVW;
892 			break;
893 		}
894 		break;
895 	case TUSHORT:
896 		switch(tt) {
897 		case TDOUBLE:
898 			regalloc(&nod, f, Z);
899 			gins(AMOVHU, f, &nod);
900 			gins(AMOVW, &nod, t);
901 			gins(AMOVWD, t, t);
902 			regfree(&nod);
903 			return;
904 		case TFLOAT:
905 			regalloc(&nod, f, Z);
906 			gins(AMOVHU, f, &nod);
907 			gins(AMOVW, &nod, t);
908 			gins(AMOVWF, t, t);
909 			regfree(&nod);
910 			return;
911 		case TINT:
912 		case TUINT:
913 		case TLONG:
914 		case TULONG:
915 		case TVLONG:
916 		case TUVLONG:
917 		case TIND:
918 			a = AMOVHU;
919 			break;
920 		case TSHORT:
921 		case TUSHORT:
922 		case TCHAR:
923 		case TUCHAR:
924 			a = AMOVW;
925 			break;
926 		}
927 		break;
928 	case TCHAR:
929 		switch(tt) {
930 		case TDOUBLE:
931 			regalloc(&nod, f, Z);
932 			gins(AMOVB, f, &nod);
933 			gins(AMOVW, &nod, t);
934 			gins(AMOVWD, t, t);
935 			regfree(&nod);
936 			return;
937 		case TFLOAT:
938 			regalloc(&nod, f, Z);
939 			gins(AMOVB, f, &nod);
940 			gins(AMOVW, &nod, t);
941 			gins(AMOVWF, t, t);
942 			regfree(&nod);
943 			return;
944 		case TINT:
945 		case TUINT:
946 		case TLONG:
947 		case TULONG:
948 		case TVLONG:
949 		case TUVLONG:
950 		case TIND:
951 		case TSHORT:
952 		case TUSHORT:
953 			a = AMOVB;
954 			break;
955 		case TCHAR:
956 		case TUCHAR:
957 			a = AMOVW;
958 			break;
959 		}
960 		break;
961 	case TUCHAR:
962 		switch(tt) {
963 		case TDOUBLE:
964 			regalloc(&nod, f, Z);
965 			gins(AMOVBU, f, &nod);
966 			gins(AMOVW, &nod, t);
967 			gins(AMOVWD, t, t);
968 			regfree(&nod);
969 			return;
970 		case TFLOAT:
971 			regalloc(&nod, f, Z);
972 			gins(AMOVBU, f, &nod);
973 			gins(AMOVW, &nod, t);
974 			gins(AMOVWF, t, t);
975 			regfree(&nod);
976 			return;
977 		case TINT:
978 		case TUINT:
979 		case TLONG:
980 		case TULONG:
981 		case TVLONG:
982 		case TUVLONG:
983 		case TIND:
984 		case TSHORT:
985 		case TUSHORT:
986 			a = AMOVBU;
987 			break;
988 		case TCHAR:
989 		case TUCHAR:
990 			a = AMOVW;
991 			break;
992 		}
993 		break;
994 	}
995 	if(a == AGOK)
996 		diag(Z, "bad opcode in gmove %T -> %T", f->type, t->type);
997 	if(a == AMOVW || a == AMOVF || a == AMOVD || a == AMOVV)
998 	if(samaddr(f, t))
999 		return;
1000 	gins(a, f, t);
1001 }
1002 
1003 void
gins(int a,Node * f,Node * t)1004 gins(int a, Node *f, Node *t)
1005 {
1006 
1007 	nextpc();
1008 	p->as = a;
1009 	if(f != Z)
1010 		naddr(f, &p->from);
1011 	if(t != Z)
1012 		naddr(t, &p->to);
1013 	if(debug['g'])
1014 		print("%P\n", p);
1015 }
1016 
1017 void
gopcode(int o,Node * f1,Node * f2,Node * t)1018 gopcode(int o, Node *f1, Node *f2, Node *t)
1019 {
1020 	int a, et, ett;
1021 	Adr ta;
1022 	Node nod;
1023 
1024 	et = TLONG;
1025 	if(f1 != Z && f1->type != T)
1026 		et = f1->type->etype;
1027 	ett = TLONG;
1028 	if(t != Z && t->type != T)
1029 		ett = t->type->etype;
1030 	if(llconst(f1) && o != OAS) {
1031 		regalloc(&nod, f1, Z);
1032 		gmove(f1, &nod);
1033 		gopcode(o, &nod, f2, t);
1034 		regfree(&nod);
1035 		return;
1036 	}
1037 	a = AGOK;
1038 	switch(o) {
1039 	case OAS:
1040 		gmove(f1, t);
1041 		return;
1042 
1043 	case OASADD:
1044 	case OADD:
1045 		a = AADDU;
1046 		if(et == TVLONG || et == TUVLONG)
1047 			a = AADDVU;
1048 		else
1049 		if(et == TFLOAT)
1050 			a = AADDF;
1051 		else
1052 		if(et == TDOUBLE)
1053 			a = AADDD;
1054 		break;
1055 
1056 	case OASSUB:
1057 	case OSUB:
1058 		a = ASUBU;
1059 		if(et == TVLONG || et == TUVLONG)
1060 			a = ASUBVU;
1061 		else
1062 		if(et == TFLOAT)
1063 			a = ASUBF;
1064 		else
1065 		if(et == TDOUBLE)
1066 			a = ASUBD;
1067 		break;
1068 
1069 	case OASOR:
1070 	case OOR:
1071 		a = AOR;
1072 		break;
1073 
1074 	case OASAND:
1075 	case OAND:
1076 		a = AAND;
1077 		break;
1078 
1079 	case OASXOR:
1080 	case OXOR:
1081 		a = AXOR;
1082 		break;
1083 
1084 	case OASLSHR:
1085 	case OLSHR:
1086 		a = ASRL;
1087 		if(ett == TVLONG || ett == TUVLONG)
1088 			a = ASRLV;
1089 		break;
1090 
1091 	case OASASHR:
1092 	case OASHR:
1093 		a = ASRA;
1094 		if(ett == TVLONG || ett == TUVLONG)
1095 			a = ASRAV;
1096 		break;
1097 
1098 	case OASASHL:
1099 	case OASHL:
1100 		a = ASLL;
1101 		if(ett == TVLONG || ett == TUVLONG)
1102 			a = ASLLV;
1103 		break;
1104 
1105 	case OFUNC:
1106 		a = AJAL;
1107 		break;
1108 
1109 	case OCOND:
1110 		a = ASGTU;
1111 		break;
1112 
1113 	case OCOMMA:
1114 		a = ASGT;
1115 		break;
1116 
1117 	case OASMUL:
1118 	case OMUL:
1119 		if(et == TFLOAT) {
1120 			a = AMULF;
1121 			break;
1122 		} else
1123 		if(et == TDOUBLE) {
1124 			a = AMULD;
1125 			break;
1126 		}
1127 		a = AMUL;
1128 		if(et == TVLONG || et == TUVLONG)
1129 			a = AMULV;
1130 		goto muldiv;
1131 
1132 	case OASDIV:
1133 	case ODIV:
1134 		if(et == TFLOAT) {
1135 			a = ADIVF;
1136 			break;
1137 		} else
1138 		if(et == TDOUBLE) {
1139 			a = ADIVD;
1140 			break;
1141 		}
1142 		a = ADIV;
1143 		if(et == TVLONG || et == TUVLONG)
1144 			a = ADIVV;
1145 		goto muldiv;
1146 
1147 	case OASMOD:
1148 	case OMOD:
1149 		a = ADIV;
1150 		o = OMOD;
1151 		if(et == TVLONG || et == TUVLONG)
1152 			a = ADIVV;
1153 		goto muldiv;
1154 
1155 	case OASLMUL:
1156 	case OLMUL:
1157 		a = AMULU;
1158 		if(et == TVLONG || et == TUVLONG)
1159 			a = AMULVU;
1160 		goto muldiv;
1161 
1162 	case OASLMOD:
1163 	case OLMOD:
1164 		o = OMOD;
1165 
1166 	case OASLDIV:
1167 	case OLDIV:
1168 		a = ADIVU;
1169 		if(et == TVLONG || et == TUVLONG)
1170 			a = ADIVVU;
1171 		goto muldiv;
1172 
1173 	muldiv:
1174 		nextpc();
1175 		naddr(f1, &p->from);
1176 		if(f2 == Z)
1177 			raddr(t, p);
1178 		else
1179 			raddr(f2, p);
1180 		p->as = a;
1181 		if(debug['g'])
1182 			print("%P\n", p);
1183 		nextpc();
1184 		p->as = AMOVW;
1185 		if(et == TVLONG || et == TUVLONG)
1186 			p->as = AMOVV;
1187 		a = D_LO;
1188 		if(o == OMOD)
1189 			a = D_HI;
1190 		p->from.type = a;
1191 		naddr(t, &p->to);
1192 		if(debug['g'])
1193 			print("%P\n", p);
1194 		return;
1195 
1196 	case OEQ:
1197 		if(!typefd[et]) {
1198 			a = ABEQ;
1199 			break;
1200 		}
1201 
1202 	case ONE:
1203 		if(!typefd[et]) {
1204 			a = ABNE;
1205 			break;
1206 		}
1207 
1208 	case OLT:
1209 	case OLE:
1210 	case OGE:
1211 	case OGT:
1212 		if(typefd[et]) {
1213 			nextpc();
1214 			if(et == TFLOAT) {
1215 				a = ACMPGTF;
1216 				if(o == OEQ || o == ONE)
1217 					a = ACMPEQF;
1218 				else
1219 				if(o == OLT || o == OGE)
1220 					a = ACMPGEF;
1221 			} else {
1222 				a = ACMPGTD;
1223 				if(o == OEQ || o == ONE)
1224 					a = ACMPEQD;
1225 				else
1226 				if(o == OLT || o == OGE)
1227 					a = ACMPGED;
1228 			}
1229 			p->as = a;
1230 			naddr(f1, &p->from);
1231 			raddr(f2, p);
1232 			if(debug['g'])
1233 				print("%P\n", p);
1234 			nextpc();
1235 			a = ABFPF;
1236 			if(o == OEQ || o == OGE || o == OGT)
1237 				a = ABFPT;
1238 			p->as = a;
1239 			if(debug['g'])
1240 				print("%P\n", p);
1241 			return;
1242 		}
1243 		if(vconst(f1) == 0 || vconst(f2) == 0) {
1244 			if(vconst(f1) == 0) {
1245 				o = invrel[relindex(o)];
1246 				f1 = f2;
1247 			}
1248 			switch(o) {
1249 			case OLT:
1250 				a = ABLTZ;
1251 				break;
1252 			case OLE:
1253 				a = ABLEZ;
1254 				break;
1255 			case OGE:
1256 				a = ABGEZ;
1257 				break;
1258 			case OGT:
1259 				a = ABGTZ;
1260 				break;
1261 			}
1262 			f2 = Z;
1263 			break;
1264 		}
1265 
1266 	case OLO:
1267 	case OLS:
1268 	case OHS:
1269 	case OHI:
1270 		nextpc();
1271 		if(o == OLE || o == OGT || o == OLS || o == OHI) {
1272 			naddr(f1, &p->from);
1273 			raddr(f2, p);
1274 		} else {
1275 			naddr(f2, &p->from);
1276 			raddr(f1, p);
1277 		}
1278 		naddr(&regnode, &p->to);
1279 		p->to.reg = tmpreg();
1280 		a = ASGT;
1281 		if(o == OLO || o == OLS || o == OHS || o == OHI)
1282 			a = ASGTU;
1283 		p->as = a;
1284 		if(debug['g'])
1285 			print("%P\n", p);
1286 
1287 		nextpc();
1288 		naddr(&regnode, &p->from);
1289 		p->from.reg = tmpreg();
1290 		a = ABEQ;
1291 		if(o == OLT || o == OGT || o == OLO || o == OHI)
1292 			a = ABNE;
1293 		p->as = a;
1294 		if(debug['g'])
1295 			print("%P\n", p);
1296 		return;
1297 	}
1298 	if(a == AGOK)
1299 		diag(Z, "bad in gopcode %O", o);
1300 	nextpc();
1301 	p->as = a;
1302 	if(f1 != Z)
1303 		naddr(f1, &p->from);
1304 	if(f2 != Z) {
1305 		naddr(f2, &ta);
1306 		p->reg = ta.reg;
1307 		if(ta.type == D_CONST && ta.offset == 0)
1308 			p->reg = REGZERO;
1309 	}
1310 	if(t != Z)
1311 		naddr(t, &p->to);
1312 	if(debug['g'])
1313 		print("%P\n", p);
1314 }
1315 
1316 int
samaddr(Node * f,Node * t)1317 samaddr(Node *f, Node *t)
1318 {
1319 
1320 	if(f->op != t->op)
1321 		return 0;
1322 	switch(f->op) {
1323 
1324 	case OREGISTER:
1325 		if(f->reg != t->reg)
1326 			break;
1327 		return 1;
1328 	}
1329 	return 0;
1330 }
1331 
1332 void
gbranch(int o)1333 gbranch(int o)
1334 {
1335 	int a;
1336 
1337 	a = AGOK;
1338 	switch(o) {
1339 	case ORETURN:
1340 		a = ARET;
1341 		break;
1342 	case OGOTO:
1343 		a = AJMP;
1344 		break;
1345 	}
1346 	nextpc();
1347 	if(a == AGOK) {
1348 		diag(Z, "bad in gbranch %O",  o);
1349 		nextpc();
1350 	}
1351 	p->as = a;
1352 }
1353 
1354 void
patch(Prog * op,long pc)1355 patch(Prog *op, long pc)
1356 {
1357 
1358 	op->to.offset = pc;
1359 	op->to.type = D_BRANCH;
1360 }
1361 
1362 void
gpseudo(int a,Sym * s,Node * n)1363 gpseudo(int a, Sym *s, Node *n)
1364 {
1365 
1366 	nextpc();
1367 	p->as = a;
1368 	p->from.type = D_OREG;
1369 	p->from.sym = s;
1370 	p->from.name = D_EXTERN;
1371 	if(s->class == CSTATIC)
1372 		p->from.name = D_STATIC;
1373 	naddr(n, &p->to);
1374 	if(a == ADATA || a == AGLOBL)
1375 		pc--;
1376 }
1377 
1378 int
sconst(Node * n)1379 sconst(Node *n)
1380 {
1381 	vlong vv;
1382 
1383 	if(n->op == OCONST) {
1384 		if(!typefd[n->type->etype]) {
1385 			vv = n->vconst;
1386 			if(vv >= (vlong)-32766 && vv < (vlong)32766)
1387 				return 1;
1388 		}
1389 	}
1390 	return 0;
1391 }
1392 
1393 int
llconst(Node * n)1394 llconst(Node *n)
1395 {
1396 	vlong vv;
1397 
1398 	if(n != Z && n->op == OCONST) {
1399 		if(typev[n->type->etype]) {
1400 			vv = n->vconst >> 32;
1401 			if(vv != 0 && vv != -1)
1402 				return 1;
1403 		}
1404 	}
1405 	return 0;
1406 }
1407 
1408 int
sval(long v)1409 sval(long v)
1410 {
1411 	if(v >= -32766L && v < 32766L)
1412 		return 1;
1413 	return 0;
1414 }
1415 
1416 long
exreg(Type * t)1417 exreg(Type *t)
1418 {
1419 	long o;
1420 
1421 	if(typechlp[t->etype]) {
1422 		if(exregoffset <= 16)
1423 			return 0;
1424 		o = exregoffset;
1425 		exregoffset--;
1426 		return o;
1427 	}
1428 	if(typefd[t->etype]) {
1429 		if(exfregoffset <= 16)
1430 			return 0;
1431 		o = exfregoffset + NREG;
1432 		exfregoffset--;
1433 		return o;
1434 	}
1435 	return 0;
1436 }
1437 
1438 schar	ewidth[NTYPE] =
1439 {
1440 	-1,		/*[TXXX]*/
1441 	SZ_CHAR,	/*[TCHAR]*/
1442 	SZ_CHAR,	/*[TUCHAR]*/
1443 	SZ_SHORT,	/*[TSHORT]*/
1444 	SZ_SHORT,	/*[TUSHORT]*/
1445 	SZ_INT,		/*[TINT]*/
1446 	SZ_INT,		/*[TUINT]*/
1447 	SZ_LONG,	/*[TLONG]*/
1448 	SZ_LONG,	/*[TULONG]*/
1449 	SZ_VLONG,	/*[TVLONG]*/
1450 	SZ_VLONG,	/*[TUVLONG]*/
1451 	SZ_FLOAT,	/*[TFLOAT]*/
1452 	SZ_DOUBLE,	/*[TDOUBLE]*/
1453 	SZ_IND,		/*[TIND]*/
1454 	0,		/*[TFUNC]*/
1455 	-1,		/*[TARRAY]*/
1456 	0,		/*[TVOID]*/
1457 	-1,		/*[TSTRUCT]*/
1458 	-1,		/*[TUNION]*/
1459 	SZ_INT,		/*[TENUM]*/
1460 };
1461 long	ncast[NTYPE] =
1462 {
1463 	0,				/*[TXXX]*/
1464 	BCHAR|BUCHAR,			/*[TCHAR]*/
1465 	BCHAR|BUCHAR,			/*[TUCHAR]*/
1466 	BSHORT|BUSHORT,			/*[TSHORT]*/
1467 	BSHORT|BUSHORT,			/*[TUSHORT]*/
1468 	BINT|BUINT|BLONG|BULONG|BIND,	/*[TINT]*/
1469 	BINT|BUINT|BLONG|BULONG|BIND,	/*[TUINT]*/
1470 	BINT|BUINT|BLONG|BULONG|BIND,	/*[TLONG]*/
1471 	BINT|BUINT|BLONG|BULONG|BIND,	/*[TULONG]*/
1472 	BVLONG|BUVLONG,			/*[TVLONG]*/
1473 	BVLONG|BUVLONG,			/*[TUVLONG]*/
1474 	BFLOAT,				/*[TFLOAT]*/
1475 	BDOUBLE,			/*[TDOUBLE]*/
1476 	BLONG|BULONG|BIND,		/*[TIND]*/
1477 	0,				/*[TFUNC]*/
1478 	0,				/*[TARRAY]*/
1479 	0,				/*[TVOID]*/
1480 	BSTRUCT,			/*[TSTRUCT]*/
1481 	BUNION,				/*[TUNION]*/
1482 	0,				/*[TENUM]*/
1483 };
1484