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