xref: /plan9/sys/src/cmd/kc/txt.c (revision 5ede6b933ae6ff5cdb9c502ac6721ed717ce4cfb)
1 #include "gc.h"
2 
3 void
ginit(void)4 ginit(void)
5 {
6 	int i;
7 	Type *t;
8 
9 	thechar = 'k';
10 	thestring = "sparc";
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 = 0;
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 	com64init();
81 
82 	memset(reg, 0, sizeof(reg));
83 	reg[REGZERO] = 1;
84 	reg[REGLINK] = 1;
85 	reg[REGTMP] = 1;
86 	for(i=NREG; i<NREG+NREG; i+=2)
87 		reg[i+1] = 1;
88 }
89 
90 void
gclean(void)91 gclean(void)
92 {
93 	int i;
94 	Sym *s;
95 
96 	for(i=0; i<NREG; i++)
97 		if(i != REGZERO && i != REGTMP && i != REGLINK)
98 		if(reg[i])
99 			diag(Z, "reg %d left allocated", i);
100 	for(i=NREG; i<NREG+NREG; i+=2)
101 		if(reg[i])
102 			diag(Z, "freg %d left allocated", i-NREG);
103 	while(mnstring)
104 		outstring("", 1L);
105 	symstring->type->width = nstring;
106 	symrathole->type->width = nrathole;
107 	for(i=0; i<NHASH; i++)
108 	for(s = hash[i]; s != S; s = s->link) {
109 		if(s->type == T)
110 			continue;
111 		if(s->type->width == 0)
112 			continue;
113 		if(s->class != CGLOBL && s->class != CSTATIC)
114 			continue;
115 		if(s->type == types[TENUM])
116 			continue;
117 		gpseudo(AGLOBL, s, nodconst(s->type->width));
118 	}
119 	nextpc();
120 	p->as = AEND;
121 	outcode();
122 }
123 
124 void
nextpc(void)125 nextpc(void)
126 {
127 
128 	p = alloc(sizeof(*p));
129 	*p = zprog;
130 	p->lineno = nearln;
131 	pc++;
132 	if(firstp == P) {
133 		firstp = p;
134 		lastp = p;
135 		return;
136 	}
137 	lastp->link = p;
138 	lastp = p;
139 }
140 
141 void
gargs(Node * n,Node * tn1,Node * tn2)142 gargs(Node *n, Node *tn1, Node *tn2)
143 {
144 	long regs;
145 	Node fnxargs[20], *fnxp;
146 
147 	regs = cursafe;
148 
149 	fnxp = fnxargs;
150 	garg1(n, tn1, tn2, 0, &fnxp);	/* compile fns to temps */
151 
152 	curarg = 0;
153 	fnxp = fnxargs;
154 	garg1(n, tn1, tn2, 1, &fnxp);	/* compile normal args and temps */
155 
156 	cursafe = regs;
157 }
158 
159 void
garg1(Node * n,Node * tn1,Node * tn2,int f,Node ** fnxp)160 garg1(Node *n, Node *tn1, Node *tn2, int f, Node **fnxp)
161 {
162 	Node nod;
163 
164 	if(n == Z)
165 		return;
166 	if(n->op == OLIST) {
167 		garg1(n->left, tn1, tn2, f, fnxp);
168 		garg1(n->right, tn1, tn2, f, fnxp);
169 		return;
170 	}
171 	if(f == 0) {
172 		if(n->complex >= FNX) {
173 			regsalloc(*fnxp, n);
174 			nod = znode;
175 			nod.op = OAS;
176 			nod.left = *fnxp;
177 			nod.right = n;
178 			nod.type = n->type;
179 			cgen(&nod, Z);
180 			(*fnxp)++;
181 		}
182 		return;
183 	}
184 	if(typesuv[n->type->etype]) {
185 		regaalloc(tn2, n);
186 		if(n->complex >= FNX) {
187 			sugen(*fnxp, tn2, n->type->width);
188 			(*fnxp)++;
189 		} else
190 			sugen(n, tn2, n->type->width);
191 		return;
192 	}
193 	if(REGARG && curarg == 0 && typechlp[n->type->etype]) {
194 		regaalloc1(tn1, n);
195 		if(n->complex >= FNX) {
196 			cgen(*fnxp, tn1);
197 			(*fnxp)++;
198 		} else
199 			cgen(n, tn1);
200 		return;
201 	}
202 	if(vconst(n) == 0) {
203 		regaalloc(tn2, n);
204 		gopcode(OAS, n, Z, tn2);
205 		return;
206 	}
207 	regalloc(tn1, n, Z);
208 	if(n->complex >= FNX) {
209 		cgen(*fnxp, tn1);
210 		(*fnxp)++;
211 	} else
212 		cgen(n, tn1);
213 	regaalloc(tn2, n);
214 	gopcode(OAS, tn1, Z, tn2);
215 	regfree(tn1);
216 }
217 
218 Node*
nod32const(vlong v)219 nod32const(vlong v)
220 {
221 	constnode.vconst = v & MASK(32);
222 	return &constnode;
223 }
224 
225 Node*
nodconst(long v)226 nodconst(long v)
227 {
228 	constnode.vconst = v;
229 	return &constnode;
230 }
231 
232 Node*
nodfconst(double d)233 nodfconst(double d)
234 {
235 	fconstnode.fconst = d;
236 	return &fconstnode;
237 }
238 
239 void
nodreg(Node * n,Node * nn,int reg)240 nodreg(Node *n, Node *nn, int reg)
241 {
242 	*n = regnode;
243 	n->reg = reg;
244 	n->type = nn->type;
245 	n->lineno = nn->lineno;
246 }
247 
248 void
regret(Node * n,Node * nn)249 regret(Node *n, Node *nn)
250 {
251 	int r;
252 
253 	r = REGRET;
254 	if(typefd[nn->type->etype])
255 		r = FREGRET+NREG;
256 	nodreg(n, nn, r);
257 	reg[r]++;
258 }
259 
260 void
regalloc(Node * n,Node * tn,Node * o)261 regalloc(Node *n, Node *tn, Node *o)
262 {
263 	int i, j;
264 	static int lasti;
265 
266 	switch(tn->type->etype) {
267 	case TCHAR:
268 	case TUCHAR:
269 	case TSHORT:
270 	case TUSHORT:
271 	case TINT:
272 	case TUINT:
273 	case TLONG:
274 	case TULONG:
275 	case TIND:
276 		if(o != Z && o->op == OREGISTER) {
277 			i = o->reg;
278 			if(i > 0 && i < NREG)
279 				goto out;
280 		}
281 		j = lasti + REGRET+1;
282 		for(i=REGRET+1; i<NREG; i++) {
283 			if(j >= NREG)
284 				j = REGRET+1;
285 			if(reg[j] == 0) {
286 				i = j;
287 				goto out;
288 			}
289 			j++;
290 		}
291 		diag(tn, "out of fixed registers");
292 		goto err;
293 
294 	case TFLOAT:
295 	case TDOUBLE:
296 	case TVLONG:
297 		if(o != Z && o->op == OREGISTER) {
298 			i = o->reg;
299 			if(i >= NREG && i < NREG+NREG)
300 				goto out;
301 		}
302 		j = lasti*2 + NREG;
303 		for(i=NREG; i<NREG+NREG; i+=2) {
304 			if(j >= NREG+NREG)
305 				j = NREG;
306 			if(reg[j] == 0) {
307 				i = j;
308 				goto out;
309 			}
310 			j += 2;
311 		}
312 		diag(tn, "out of float registers");
313 		goto err;
314 	}
315 	diag(tn, "unknown type in regalloc: %T", tn->type);
316 err:
317 	i = 0;
318 out:
319 	if(i)
320 		reg[i]++;
321 	lasti++;
322 	if(lasti >= 5)
323 		lasti = 0;
324 	nodreg(n, tn, i);
325 }
326 
327 void
regialloc(Node * n,Node * tn,Node * o)328 regialloc(Node *n, Node *tn, Node *o)
329 {
330 	Node nod;
331 
332 	nod = *tn;
333 	nod.type = types[TIND];
334 	regalloc(n, &nod, o);
335 }
336 
337 void
regfree(Node * n)338 regfree(Node *n)
339 {
340 	int i;
341 
342 	i = 0;
343 	if(n->op != OREGISTER && n->op != OINDREG)
344 		goto err;
345 	i = n->reg;
346 	if(i < 0 || i >= sizeof(reg))
347 		goto err;
348 	if(reg[i] <= 0)
349 		goto err;
350 	reg[i]--;
351 	return;
352 err:
353 	diag(n, "error in regfree: %d", i);
354 }
355 
356 void
regsalloc(Node * n,Node * nn)357 regsalloc(Node *n, Node *nn)
358 {
359 	cursafe = align(cursafe, nn->type, Aaut3);
360 	maxargsafe = maxround(maxargsafe, cursafe+curarg);
361 	*n = *nodsafe;
362 	n->xoffset = -(stkoff + cursafe);
363 	n->type = nn->type;
364 	n->etype = nn->type->etype;
365 	n->lineno = nn->lineno;
366 }
367 
368 void
regaalloc1(Node * n,Node * nn)369 regaalloc1(Node *n, Node *nn)
370 {
371 	nodreg(n, nn, REGARG);
372 	reg[REGARG]++;
373 	curarg = align(curarg, nn->type, Aarg1);
374 	curarg = align(curarg, nn->type, Aarg2);
375 	maxargsafe = maxround(maxargsafe, cursafe+curarg);
376 }
377 
378 void
regaalloc(Node * n,Node * nn)379 regaalloc(Node *n, Node *nn)
380 {
381 	curarg = align(curarg, nn->type, Aarg1);
382 	*n = *nn;
383 	n->op = OINDREG;
384 	n->reg = REGSP;
385 	n->xoffset = curarg + SZ_LONG;
386 	n->complex = 0;
387 	n->addable = 20;
388 	curarg = align(curarg, nn->type, Aarg2);
389 	maxargsafe = maxround(maxargsafe, cursafe+curarg);
390 }
391 
392 void
regind(Node * n,Node * nn)393 regind(Node *n, Node *nn)
394 {
395 
396 	if(n->op != OREGISTER) {
397 		diag(n, "regind not OREGISTER");
398 		return;
399 	}
400 	n->op = OINDREG;
401 	n->type = nn->type;
402 }
403 
404 void
raddr(Node * n,Prog * p)405 raddr(Node *n, Prog *p)
406 {
407 	Adr a;
408 
409 	naddr(n, &a);
410 	if(a.type == D_CONST && a.offset == 0) {
411 		a.type = D_REG;
412 		a.reg = 0;
413 	}
414 	if(a.type != D_REG && a.type != D_FREG) {
415 		if(n)
416 			diag(n, "bad in raddr: %O", n->op);
417 		else
418 			diag(n, "bad in raddr: <null>");
419 		p->reg = NREG;
420 	} else
421 		p->reg = a.reg;
422 }
423 
424 void
naddr(Node * n,Adr * a)425 naddr(Node *n, Adr *a)
426 {
427 	long v;
428 
429 	a->type = D_NONE;
430 	if(n == Z)
431 		return;
432 	switch(n->op) {
433 	default:
434 	bad:
435 		diag(n, "bad in naddr: %O", n->op);
436 		break;
437 
438 	case OREGISTER:
439 		a->type = D_REG;
440 		a->sym = S;
441 		a->reg = n->reg;
442 		if(a->reg >= NREG) {
443 			a->type = D_FREG;
444 			a->reg -= NREG;
445 		}
446 		break;
447 
448 	case OIND:
449 		naddr(n->left, a);
450 		if(a->type == D_REG) {
451 			a->type = D_OREG;
452 			break;
453 		}
454 		if(a->type == D_CONST) {
455 			a->type = D_OREG;
456 			break;
457 		}
458 		goto bad;
459 
460 	case OINDREG:
461 		a->type = D_OREG;
462 		a->sym = S;
463 		a->offset = n->xoffset;
464 		a->reg = n->reg;
465 		break;
466 
467 	case ONAME:
468 		a->etype = n->etype;
469 		a->type = D_OREG;
470 		a->name = D_STATIC;
471 		a->sym = n->sym;
472 		a->offset = n->xoffset;
473 		if(n->class == CSTATIC)
474 			break;
475 		if(n->class == CEXTERN || n->class == CGLOBL) {
476 			a->name = D_EXTERN;
477 			break;
478 		}
479 		if(n->class == CAUTO) {
480 			a->name = D_AUTO;
481 			break;
482 		}
483 		if(n->class == CPARAM) {
484 			a->name = D_PARAM;
485 			break;
486 		}
487 		goto bad;
488 
489 	case OCONST:
490 		a->sym = S;
491 		a->reg = NREG;
492 		if(typefd[n->type->etype]) {
493 			a->type = D_FCONST;
494 			a->dval = n->fconst;
495 		} else {
496 			a->type = D_CONST;
497 			a->offset = n->vconst;
498 		}
499 		break;
500 
501 	case OADDR:
502 		naddr(n->left, a);
503 		if(a->type == D_OREG) {
504 			a->type = D_CONST;
505 			break;
506 		}
507 		goto bad;
508 
509 	case OADD:
510 		if(n->left->op == OCONST) {
511 			naddr(n->left, a);
512 			v = a->offset;
513 			naddr(n->right, a);
514 		} else {
515 			naddr(n->right, a);
516 			v = a->offset;
517 			naddr(n->left, a);
518 		}
519 		a->offset += v;
520 		break;
521 
522 	}
523 }
524 
525 void
fop(int as,int f1,int f2,Node * t)526 fop(int as, int f1, int f2, Node *t)
527 {
528 	Node nod1, nod2, nod3;
529 
530 	nodreg(&nod1, t, NREG+f1);
531 	nodreg(&nod2, t, NREG+f2);
532 	regalloc(&nod3, t, t);
533 	gopcode(as, &nod1, &nod2, &nod3);
534 	gmove(&nod3, t);
535 	regfree(&nod3);
536 }
537 
538 void
gmove(Node * f,Node * t)539 gmove(Node *f, Node *t)
540 {
541 	int ft, tt, a;
542 	Node nod;
543 	Prog *p1;
544 	double d;
545 
546 	ft = f->type->etype;
547 	tt = t->type->etype;
548 
549 	if(ft == TDOUBLE && f->op == OCONST) {
550 		d = f->fconst;
551 		if(d == 0.0) {
552 			a = FREGZERO;
553 			goto ffreg;
554 		}
555 		if(d == 0.5) {
556 			a = FREGHALF;
557 			goto ffreg;
558 		}
559 		if(d == 1.0) {
560 			a = FREGONE;
561 			goto ffreg;
562 		}
563 		if(d == 2.0) {
564 			a = FREGTWO;
565 			goto ffreg;
566 		}
567 		if(d == -.5) {
568 			fop(OSUB, FREGHALF, FREGZERO, t);
569 			return;
570 		}
571 		if(d == -1.0) {
572 			fop(OSUB, FREGONE, FREGZERO, t);
573 			return;
574 		}
575 		if(d == -2.0) {
576 			fop(OSUB, FREGTWO, FREGZERO, t);
577 			return;
578 		}
579 		if(d == 1.5) {
580 			fop(OADD, FREGONE, FREGHALF, t);
581 			return;
582 		}
583 		if(d == 2.5) {
584 			fop(OADD, FREGTWO, FREGHALF, t);
585 			return;
586 		}
587 		if(d == 3.0) {
588 			fop(OADD, FREGTWO, FREGONE, t);
589 			return;
590 		}
591 	}
592 	if(ft == TFLOAT && f->op == OCONST) {
593 		d = f->fconst;
594 		if(d == 0) {
595 			a = FREGZERO;
596 		ffreg:
597 			nodreg(&nod, f, NREG+a);
598 			gmove(&nod, t);
599 			return;
600 		}
601 	}
602 	/*
603 	 * a load --
604 	 * put it into a register then
605 	 * worry what to do with it.
606 	 */
607 	if(f->op == ONAME || f->op == OINDREG || f->op == OIND) {
608 		switch(ft) {
609 		default:
610 			if(typefd[tt]) {
611 				/* special case can load mem to Freg */
612 				regalloc(&nod, t, t);
613 				gins(AMOVW, f, &nod);
614 				a = AFMOVWD;
615 				if(tt == TFLOAT)
616 					a = AFMOVWF;
617 				gins(a, &nod, &nod);
618 				gmove(&nod, t);
619 				regfree(&nod);
620 				return;
621 			}
622 			a = AMOVW;
623 			break;
624 		case TFLOAT:
625 			a = AFMOVF;
626 			break;
627 		case TDOUBLE:
628 			a = AFMOVD;
629 			break;
630 		case TCHAR:
631 			a = AMOVB;
632 			break;
633 		case TUCHAR:
634 			a = AMOVBU;
635 			break;
636 		case TSHORT:
637 			a = AMOVH;
638 			break;
639 		case TUSHORT:
640 			a = AMOVHU;
641 			break;
642 		}
643 		regalloc(&nod, f, t);
644 		gins(a, f, &nod);
645 		gmove(&nod, t);
646 		regfree(&nod);
647 		return;
648 	}
649 
650 	/*
651 	 * a store --
652 	 * put it into a register then
653 	 * store it.
654 	 */
655 	if(t->op == ONAME || t->op == OINDREG || t->op == OIND) {
656 		switch(tt) {
657 		default:
658 			if(typefd[ft]) {
659 				/* special case can store mem from Freg */
660 				regalloc(&nod, f, Z);
661 				a = AFMOVDW;
662 				if(ft == TFLOAT)
663 					a = AFMOVFW;
664 				gins(a, f, &nod);
665 				gins(AMOVW, &nod, t);
666 				regfree(&nod);
667 				return;
668 			}
669 			a = AMOVW;
670 			break;
671 		case TUCHAR:
672 			a = AMOVBU;
673 			break;
674 		case TCHAR:
675 			a = AMOVB;
676 			break;
677 		case TUSHORT:
678 			a = AMOVHU;
679 			break;
680 		case TSHORT:
681 			a = AMOVH;
682 			break;
683 		case TFLOAT:
684 			a = AFMOVF;
685 			break;
686 		case TVLONG:
687 		case TDOUBLE:
688 			a = AFMOVD;
689 			break;
690 		}
691 		if(!typefd[ft] && vconst(f) == 0) {
692 			gins(a, f, t);
693 			return;
694 		}
695 		if(ft == tt)
696 			regalloc(&nod, t, f);
697 		else
698 			regalloc(&nod, t, Z);
699 		gmove(f, &nod);
700 		gins(a, &nod, t);
701 		regfree(&nod);
702 		return;
703 	}
704 
705 	/*
706 	 * type x type cross table
707 	 */
708 	a = AGOK;
709 	switch(ft) {
710 	case TDOUBLE:
711 	case TVLONG:
712 	case TFLOAT:
713 		switch(tt) {
714 		case TDOUBLE:
715 		case TVLONG:
716 			a = AFMOVD;
717 			if(ft == TFLOAT)
718 				a = AFMOVFD;
719 			break;
720 		case TFLOAT:
721 			a = AFMOVDF;
722 			if(ft == TFLOAT)
723 				a = AFMOVF;
724 			break;
725 		case TLONG:
726 		case TULONG:
727 		case TIND:
728 		case TINT:
729 		case TUINT:
730 		case TSHORT:
731 		case TUSHORT:
732 		case TCHAR:
733 		case TUCHAR:
734 			regalloc(&nod, f, Z);	/* should be type float */
735 			a = AFMOVDW;
736 			if(ft == TFLOAT)
737 				a = AFMOVFW;
738 			gins(a, f, &nod);
739 			gins(AFMOVF, &nod, nodrat);
740 			regfree(&nod);
741 			gins(AMOVW, nodrat, t);
742 			gmove(t, t);
743 			if(nrathole < SZ_LONG)
744 				nrathole = SZ_LONG;
745 			return;
746 		}
747 		break;
748 	case TINT:
749 	case TUINT:
750 	case TLONG:
751 	case TULONG:
752 	case TIND:
753 		switch(tt) {
754 		case TDOUBLE:
755 		case TVLONG:
756 		case TFLOAT:
757 			goto fxtofl;
758 		case TLONG:
759 		case TULONG:
760 		case TINT:
761 		case TUINT:
762 		case TIND:
763 		case TSHORT:
764 		case TUSHORT:
765 		case TCHAR:
766 		case TUCHAR:
767 			a = AMOVW;
768 			break;
769 		}
770 		break;
771 	case TSHORT:
772 		switch(tt) {
773 		case TDOUBLE:
774 		case TVLONG:
775 		case TFLOAT:
776 			goto fxtofl;
777 		case TUINT:
778 		case TINT:
779 		case TULONG:
780 		case TLONG:
781 		case TIND:
782 			a = AMOVH;
783 			break;
784 		case TSHORT:
785 		case TUSHORT:
786 		case TCHAR:
787 		case TUCHAR:
788 			a = AMOVW;
789 			break;
790 		}
791 		break;
792 	case TUSHORT:
793 		switch(tt) {
794 		case TDOUBLE:
795 		case TVLONG:
796 		case TFLOAT:
797 			goto fxtofl;
798 		case TINT:
799 		case TUINT:
800 		case TLONG:
801 		case TULONG:
802 		case TIND:
803 			a = AMOVHU;
804 			break;
805 		case TSHORT:
806 		case TUSHORT:
807 		case TCHAR:
808 		case TUCHAR:
809 			a = AMOVW;
810 			break;
811 		}
812 		break;
813 	case TCHAR:
814 		switch(tt) {
815 		case TDOUBLE:
816 		case TVLONG:
817 		case TFLOAT:
818 			goto fxtofl;
819 		case TINT:
820 		case TUINT:
821 		case TLONG:
822 		case TULONG:
823 		case TIND:
824 		case TSHORT:
825 		case TUSHORT:
826 			a = AMOVB;
827 			break;
828 		case TCHAR:
829 		case TUCHAR:
830 			a = AMOVW;
831 			break;
832 		}
833 		break;
834 	case TUCHAR:
835 		switch(tt) {
836 		case TDOUBLE:
837 		case TVLONG:
838 		case TFLOAT:
839 		fxtofl:
840 			regalloc(&nod, t, t);	/* should be type float */
841 			gins(AMOVW, f, nodrat);
842 			gins(AFMOVF, nodrat, &nod);
843 			a = AFMOVWD;
844 			if(tt == TFLOAT)
845 				a = AFMOVWF;
846 			gins(a, &nod, t);
847 			regfree(&nod);
848 			if(nrathole < SZ_LONG)
849 				nrathole = SZ_LONG;
850 			if(ft == TULONG) {
851 				regalloc(&nod, t, Z);
852 				if(tt == TFLOAT) {
853 					gins(AFCMPF, t, Z);
854 					p->to.type = D_FREG;
855 					p->to.reg = FREGZERO;
856 					gins(AFBGE, Z, Z);
857 					p1 = p;
858 					gins(AFMOVF, nodfconst(4294967296.), &nod);
859 					gins(AFADDF, &nod, t);
860 				} else {
861 					gins(AFCMPD, t, Z);
862 					p->to.type = D_FREG;
863 					p->to.reg = FREGZERO;
864 					gins(AFBGE, Z, Z);
865 					p1 = p;
866 					gins(AFMOVD, nodfconst(4294967296.), &nod);
867 					gins(AFADDD, &nod, t);
868 				}
869 				patch(p1, pc);
870 				regfree(&nod);
871 			}
872 			return;
873 		case TINT:
874 		case TUINT:
875 		case TLONG:
876 		case TULONG:
877 		case TIND:
878 		case TSHORT:
879 		case TUSHORT:
880 			a = AMOVBU;
881 			break;
882 		case TCHAR:
883 		case TUCHAR:
884 			a = AMOVW;
885 			break;
886 		}
887 		break;
888 	}
889 	if(a == AGOK)
890 		diag(Z, "bad opcode in gmove %T -> %T", f->type, t->type);
891 	if(a == AMOVW || a == AFMOVF || a == AFMOVD)
892 	if(samaddr(f, t))
893 		return;
894 	gins(a, f, t);
895 }
896 
897 void
gins(int a,Node * f,Node * t)898 gins(int a, Node *f, Node *t)
899 {
900 
901 	nextpc();
902 	p->as = a;
903 	if(f != Z)
904 		naddr(f, &p->from);
905 	if(t != Z)
906 		naddr(t, &p->to);
907 	if(debug['g'])
908 		print("%P\n", p);
909 }
910 
911 void
gopcode(int o,Node * f1,Node * f2,Node * t)912 gopcode(int o, Node *f1, Node *f2, Node *t)
913 {
914 	int a, et;
915 	Adr ta;
916 
917 	et = TLONG;
918 	if(f1 != Z && f1->type != T)
919 		et = f1->type->etype;
920 	a = AGOK;
921 	switch(o) {
922 	case OAS:
923 		gmove(f1, t);
924 		return;
925 
926 	case OASADD:
927 	case OADD:
928 		a = AADD;
929 		if(et == TFLOAT)
930 			a = AFADDF;
931 		else
932 		if(et == TDOUBLE || et == TVLONG)
933 			a = AFADDD;
934 		break;
935 
936 	case OASSUB:
937 	case OSUB:
938 		a = ASUB;
939 		if(et == TFLOAT)
940 			a = AFSUBF;
941 		else
942 		if(et == TDOUBLE || et == TVLONG)
943 			a = AFSUBD;
944 		break;
945 
946 	case OASOR:
947 	case OOR:
948 		a = AOR;
949 		break;
950 
951 	case OASAND:
952 	case OAND:
953 		a = AAND;
954 		break;
955 
956 	case OASXOR:
957 	case OXOR:
958 		a = AXOR;
959 		break;
960 
961 	case OASLSHR:
962 	case OLSHR:
963 		a = ASRL;
964 		break;
965 
966 	case OASASHR:
967 	case OASHR:
968 		a = ASRA;
969 		break;
970 
971 	case OASASHL:
972 	case OASHL:
973 		a = ASLL;
974 		break;
975 
976 	case OFUNC:
977 		a = AJMPL;
978 		break;
979 
980 	case OASLMUL:
981 	case OLMUL:
982 	case OASMUL:
983 	case OMUL:
984 		if(et == TFLOAT) {
985 			a = AFMULF;
986 			break;
987 		} else
988 		if(et == TDOUBLE || et == TVLONG) {
989 			a = AFMULD;
990 			break;
991 		}
992 		a = AMUL;
993 		break;
994 
995 	case OASDIV:
996 	case ODIV:
997 		if(et == TFLOAT) {
998 			a = AFDIVF;
999 			break;
1000 		} else
1001 		if(et == TDOUBLE || et == TVLONG) {
1002 			a = AFDIVD;
1003 			break;
1004 		}
1005 		a = ADIV;
1006 		break;
1007 
1008 	case OASMOD:
1009 	case OMOD:
1010 		a = AMOD;
1011 		break;
1012 
1013 	case OASLMOD:
1014 	case OLMOD:
1015 		a = AMODL;
1016 		break;
1017 
1018 	case OASLDIV:
1019 	case OLDIV:
1020 		a = ADIVL;
1021 		break;
1022 
1023 	case OEQ:
1024 		a = ABE;
1025 		if(typefd[et])
1026 			a = AFBE;
1027 		goto cmp;
1028 
1029 	case ONE:
1030 		a = ABNE;
1031 		if(typefd[et])
1032 			a = AFBLG;
1033 		goto cmp;
1034 
1035 	case OLT:
1036 		a = ABL;
1037 		if(typefd[et])
1038 			a = AFBL;
1039 		goto cmp;
1040 
1041 	case OLE:
1042 		a = ABLE;
1043 		if(typefd[et])
1044 			a = AFBLE;
1045 		goto cmp;
1046 
1047 	case OGE:
1048 		a = ABGE;
1049 		if(typefd[et])
1050 			a = AFBGE;
1051 		goto cmp;
1052 
1053 	case OGT:
1054 		a = ABG;
1055 		if(typefd[et])
1056 			a = AFBG;
1057 		goto cmp;
1058 
1059 	case OLO:
1060 		a = ABCS;
1061 		goto cmp;
1062 
1063 	case OLS:
1064 		a = ABLEU;
1065 		goto cmp;
1066 
1067 	case OHS:
1068 		a = ABCC;
1069 		goto cmp;
1070 
1071 	case OHI:
1072 		a = ABGU;
1073 		goto cmp;
1074 
1075 	cmp:
1076 		nextpc();
1077 		p->as = ACMP;
1078 		if(et == TFLOAT)
1079 			p->as = AFCMPF;
1080 		else
1081 		if(et == TDOUBLE || et == TVLONG)
1082 			p->as = AFCMPD;
1083 		if(f1 != Z)
1084 			naddr(f1, &p->from);
1085 		if(t != Z)
1086 			naddr(t, &p->to);
1087 		if(f1 == Z || t == Z || f2 != Z)
1088 			diag(Z, "bad cmp in gopcode %O", o);
1089 		if(debug['g'])
1090 			print("%P\n", p);
1091 		f1 = Z;
1092 		f2 = Z;
1093 		t = Z;
1094 		break;
1095 	}
1096 	if(a == AGOK)
1097 		diag(Z, "bad in gopcode %O", o);
1098 	nextpc();
1099 	p->as = a;
1100 	if(f1 != Z)
1101 		naddr(f1, &p->from);
1102 	if(f2 != Z) {
1103 		naddr(f2, &ta);
1104 		p->reg = ta.reg;
1105 		if(ta.type == D_CONST && ta.offset == 0)
1106 			p->reg = REGZERO;
1107 	}
1108 	if(t != Z)
1109 		naddr(t, &p->to);
1110 	if(debug['g'])
1111 		print("%P\n", p);
1112 }
1113 
samaddr(Node * f,Node * t)1114 samaddr(Node *f, Node *t)
1115 {
1116 
1117 	if(f->op != t->op)
1118 		return 0;
1119 	switch(f->op) {
1120 
1121 	case OREGISTER:
1122 		if(f->reg != t->reg)
1123 			break;
1124 		return 1;
1125 	}
1126 	return 0;
1127 }
1128 
1129 void
gbranch(int o)1130 gbranch(int o)
1131 {
1132 	int a;
1133 
1134 	a = AGOK;
1135 	switch(o) {
1136 	case ORETURN:
1137 		a = ARETURN;
1138 		break;
1139 	case OGOTO:
1140 		a = AJMP;
1141 		break;
1142 	}
1143 	nextpc();
1144 	if(a == AGOK) {
1145 		diag(Z, "bad in gbranch %O",  o);
1146 		nextpc();
1147 	}
1148 	p->as = a;
1149 }
1150 
1151 void
patch(Prog * op,long pc)1152 patch(Prog *op, long pc)
1153 {
1154 
1155 	op->to.offset = pc;
1156 	op->to.type = D_BRANCH;
1157 }
1158 
1159 void
gpseudo(int a,Sym * s,Node * n)1160 gpseudo(int a, Sym *s, Node *n)
1161 {
1162 
1163 	nextpc();
1164 	p->as = a;
1165 	p->from.type = D_OREG;
1166 	p->from.sym = s;
1167 	if(a == ATEXT)
1168 		p->reg = (profileflg ? 0 : NOPROF);
1169 	p->from.name = D_EXTERN;
1170 	if(s->class == CSTATIC)
1171 		p->from.name = D_STATIC;
1172 	naddr(n, &p->to);
1173 	if(a == ADATA || a == AGLOBL)
1174 		pc--;
1175 }
1176 
1177 int
sval(long v)1178 sval(long v)
1179 {
1180 
1181 	if(v >= -(1<<12) && v < (1<<12))
1182 		return 1;
1183 	return 0;
1184 }
1185 
1186 int
sconst(Node * n)1187 sconst(Node *n)
1188 {
1189 	vlong vv;
1190 
1191 	if(n->op == OCONST) {
1192 		if(!typefd[n->type->etype]) {
1193 			vv = n->vconst;
1194 			if(vv >= -(vlong)(1<<12) && vv < (vlong)(1<<12))
1195 				return 1;
1196 		}
1197 	}
1198 	return 0;
1199 }
1200 
1201 long
exreg(Type * t)1202 exreg(Type *t)
1203 {
1204 	long o;
1205 
1206 	if(typechlp[t->etype]) {
1207 		if(exregoffset <= 3)
1208 			return 0;
1209 		o = exregoffset;
1210 		exregoffset--;
1211 		return o;
1212 	}
1213 	if(typefd[t->etype]) {
1214 		if(exfregoffset <= 16)
1215 			return 0;
1216 		o = exfregoffset + NREG;
1217 		exfregoffset--;
1218 		return o;
1219 	}
1220 	return 0;
1221 }
1222 
1223 schar	ewidth[NTYPE] =
1224 {
1225 	-1,		/* [TXXX] */
1226 	SZ_CHAR,	/* [TCHAR] */
1227 	SZ_CHAR,	/* [TUCHAR] */
1228 	SZ_SHORT,	/* [TSHORT] */
1229 	SZ_SHORT,	/* [TUSHORT] */
1230 	SZ_INT,		/* [TINT] */
1231 	SZ_INT,		/* [TUINT] */
1232 	SZ_LONG,	/* [TLONG] */
1233 	SZ_LONG,	/* [TULONG] */
1234 	SZ_VLONG,	/* [TVLONG] */
1235 	SZ_VLONG,	/* [TUVLONG] */
1236 	SZ_FLOAT,	/* [TFLOAT] */
1237 	SZ_DOUBLE,	/* [TDOUBLE] */
1238 	SZ_IND,		/* [TIND] */
1239 	0,		/* [TFUNC] */
1240 	-1,		/* [TARRAY] */
1241 	0,		/* [TVOID] */
1242 	-1,		/* [TSTRUCT] */
1243 	-1,		/* [TUNION] */
1244 	SZ_INT,		/* [TENUM] */
1245 };
1246 
1247 long	ncast[NTYPE] =
1248 {
1249 	0,				/* [TXXX] */
1250 	BCHAR|BUCHAR,			/* [TCHAR] */
1251 	BCHAR|BUCHAR,			/* [TUCHAR] */
1252 	BSHORT|BUSHORT,			/* [TSHORT] */
1253 	BSHORT|BUSHORT,			/* [TUSHORT] */
1254 	BINT|BUINT|BLONG|BULONG|BIND,	/* [TINT] */
1255 	BINT|BUINT|BLONG|BULONG|BIND,	/* [TUINT] */
1256 	BINT|BUINT|BLONG|BULONG|BIND,	/* [TLONG] */
1257 	BINT|BUINT|BLONG|BULONG|BIND,	/* [TULONG] */
1258 	BVLONG|BUVLONG,			/* [TVLONG] */
1259 	BVLONG|BUVLONG,			/* [TUVLONG] */
1260 	BFLOAT,				/* [TFLOAT] */
1261 	BDOUBLE,			/* [TDOUBLE] */
1262 	BLONG|BULONG|BIND,		/* [TIND] */
1263 	0,				/* [TFUNC] */
1264 	0,				/* [TARRAY] */
1265 	0,				/* [TVOID] */
1266 	BSTRUCT,			/* [TSTRUCT] */
1267 	BUNION,				/* [TUNION] */
1268 	0,				/* [TENUM] */
1269 };
1270