xref: /plan9/sys/src/cmd/vc/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 = 'v';
10 	thestring = "mips";
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 	com64init();
81 
82 	for(i=0; i<nelem(reg); i++) {
83 		reg[i] = 0;
84 		if(i == REGZERO ||
85 		  (i >= NREG && ((i-NREG)&1)))
86 			reg[i] = 1;
87 	}
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)
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*
nodconst(long v)219 nodconst(long v)
220 {
221 	constnode.vconst = v;
222 	return &constnode;
223 }
224 
225 Node*
nod32const(vlong v)226 nod32const(vlong v)
227 {
228 	constnode.vconst = v & MASK(32);
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 int
tmpreg(void)261 tmpreg(void)
262 {
263 	int i;
264 
265 	for(i=REGRET+1; i<NREG; i++)
266 		if(reg[i] == 0)
267 			return i;
268 	diag(Z, "out of fixed registers");
269 	return 0;
270 }
271 
272 void
regalloc(Node * n,Node * tn,Node * o)273 regalloc(Node *n, Node *tn, Node *o)
274 {
275 	int i, j;
276 	static int lasti;
277 
278 	switch(tn->type->etype) {
279 	case TCHAR:
280 	case TUCHAR:
281 	case TSHORT:
282 	case TUSHORT:
283 	case TINT:
284 	case TUINT:
285 	case TLONG:
286 	case TULONG:
287 	case TIND:
288 		if(o != Z && o->op == OREGISTER) {
289 			i = o->reg;
290 			if(i > 0 && i < NREG)
291 				goto out;
292 		}
293 		j = lasti + REGRET+1;
294 		for(i=REGRET+1; i<NREG; i++) {
295 			if(j >= NREG)
296 				j = REGRET+1;
297 			if(reg[j] == 0) {
298 				i = j;
299 				goto out;
300 			}
301 			j++;
302 		}
303 		diag(tn, "out of fixed registers");
304 		goto err;
305 
306 	case TFLOAT:
307 	case TDOUBLE:
308 	case TVLONG:
309 		if(o != Z && o->op == OREGISTER) {
310 			i = o->reg;
311 			if(i >= NREG && i < NREG+NREG)
312 				goto out;
313 		}
314 		j = 0*2 + NREG;
315 		for(i=NREG; i<NREG+NREG; i+=2) {
316 			if(j >= NREG+NREG)
317 				j = NREG;
318 			if(reg[j] == 0) {
319 				i = j;
320 				goto out;
321 			}
322 			j += 2;
323 		}
324 		diag(tn, "out of float registers");
325 		goto err;
326 	}
327 	diag(tn, "unknown type in regalloc: %T", tn->type);
328 err:
329 	nodreg(n, tn, 0);
330 	return;
331 out:
332 	reg[i]++;
333 	lasti++;
334 	if(lasti >= 5)
335 		lasti = 0;
336 	nodreg(n, tn, i);
337 }
338 
339 void
regialloc(Node * n,Node * tn,Node * o)340 regialloc(Node *n, Node *tn, Node *o)
341 {
342 	Node nod;
343 
344 	nod = *tn;
345 	nod.type = types[TIND];
346 	regalloc(n, &nod, o);
347 }
348 
349 void
regfree(Node * n)350 regfree(Node *n)
351 {
352 	int i;
353 
354 	i = 0;
355 	if(n->op != OREGISTER && n->op != OINDREG)
356 		goto err;
357 	i = n->reg;
358 	if(i < 0 || i >= sizeof(reg))
359 		goto err;
360 	if(reg[i] <= 0)
361 		goto err;
362 	reg[i]--;
363 	return;
364 err:
365 	diag(n, "error in regfree: %d", i);
366 }
367 
368 void
regsalloc(Node * n,Node * nn)369 regsalloc(Node *n, Node *nn)
370 {
371 	cursafe = align(cursafe, nn->type, Aaut3);
372 	maxargsafe = maxround(maxargsafe, cursafe+curarg);
373 	*n = *nodsafe;
374 	n->xoffset = -(stkoff + cursafe);
375 	n->type = nn->type;
376 	n->etype = nn->type->etype;
377 	n->lineno = nn->lineno;
378 }
379 
380 void
regaalloc1(Node * n,Node * nn)381 regaalloc1(Node *n, Node *nn)
382 {
383 	nodreg(n, nn, REGARG);
384 	reg[REGARG]++;
385 	curarg = align(curarg, nn->type, Aarg1);
386 	curarg = align(curarg, nn->type, Aarg2);
387 	maxargsafe = maxround(maxargsafe, cursafe+curarg);
388 }
389 
390 void
regaalloc(Node * n,Node * nn)391 regaalloc(Node *n, Node *nn)
392 {
393 	curarg = align(curarg, nn->type, Aarg1);
394 	*n = *nn;
395 	n->op = OINDREG;
396 	n->reg = REGSP;
397 	n->xoffset = curarg + SZ_LONG;
398 	n->complex = 0;
399 	n->addable = 20;
400 	curarg = align(curarg, nn->type, Aarg2);
401 	maxargsafe = maxround(maxargsafe, cursafe+curarg);
402 }
403 
404 void
regind(Node * n,Node * nn)405 regind(Node *n, Node *nn)
406 {
407 
408 	if(n->op != OREGISTER) {
409 		diag(n, "regind not OREGISTER");
410 		return;
411 	}
412 	n->op = OINDREG;
413 	n->type = nn->type;
414 }
415 
416 void
raddr(Node * n,Prog * p)417 raddr(Node *n, Prog *p)
418 {
419 	Adr a;
420 
421 	naddr(n, &a);
422 	if(a.type == D_CONST && a.offset == 0) {
423 		a.type = D_REG;
424 		a.reg = 0;
425 	}
426 	if(a.type != D_REG && a.type != D_FREG) {
427 		if(n)
428 			diag(n, "bad in raddr: %O", n->op);
429 		else
430 			diag(n, "bad in raddr: <null>");
431 		p->reg = NREG;
432 	} else
433 		p->reg = a.reg;
434 }
435 
436 void
naddr(Node * n,Adr * a)437 naddr(Node *n, Adr *a)
438 {
439 	long v;
440 
441 	a->type = D_NONE;
442 	if(n == Z)
443 		return;
444 	switch(n->op) {
445 	default:
446 	bad:
447 		diag(n, "bad in naddr: %O", n->op);
448 		break;
449 
450 	case OREGISTER:
451 		a->type = D_REG;
452 		a->sym = S;
453 		a->reg = n->reg;
454 		if(a->reg >= NREG) {
455 			a->type = D_FREG;
456 			a->reg -= NREG;
457 		}
458 		break;
459 
460 	case OIND:
461 		naddr(n->left, a);
462 		if(a->type == D_REG) {
463 			a->type = D_OREG;
464 			break;
465 		}
466 		if(a->type == D_CONST) {
467 			a->type = D_OREG;
468 			break;
469 		}
470 		goto bad;
471 
472 	case OINDREG:
473 		a->type = D_OREG;
474 		a->sym = S;
475 		a->offset = n->xoffset;
476 		a->reg = n->reg;
477 		break;
478 
479 	case ONAME:
480 		a->etype = n->etype;
481 		a->type = D_OREG;
482 		a->name = D_STATIC;
483 		a->sym = n->sym;
484 		a->offset = n->xoffset;
485 		if(n->class == CSTATIC)
486 			break;
487 		if(n->class == CEXTERN || n->class == CGLOBL) {
488 			a->name = D_EXTERN;
489 			break;
490 		}
491 		if(n->class == CAUTO) {
492 			a->name = D_AUTO;
493 			break;
494 		}
495 		if(n->class == CPARAM) {
496 			a->name = D_PARAM;
497 			break;
498 		}
499 		goto bad;
500 
501 	case OCONST:
502 		a->sym = S;
503 		a->reg = NREG;
504 		if(typefd[n->type->etype]) {
505 			a->type = D_FCONST;
506 			a->dval = n->fconst;
507 		} else {
508 			a->type = D_CONST;
509 			a->offset = n->vconst;
510 		}
511 		break;
512 
513 	case OADDR:
514 		naddr(n->left, a);
515 		if(a->type == D_OREG) {
516 			a->type = D_CONST;
517 			break;
518 		}
519 		goto bad;
520 
521 	case OADD:
522 		if(n->left->op == OCONST) {
523 			naddr(n->left, a);
524 			v = a->offset;
525 			naddr(n->right, a);
526 		} else {
527 			naddr(n->right, a);
528 			v = a->offset;
529 			naddr(n->left, a);
530 		}
531 		a->offset += v;
532 		break;
533 
534 	}
535 }
536 
537 void
fop(int as,int f1,int f2,Node * t)538 fop(int as, int f1, int f2, Node *t)
539 {
540 	Node nod1, nod2, nod3;
541 
542 	nodreg(&nod1, t, NREG+f1);
543 	nodreg(&nod2, t, NREG+f2);
544 	regalloc(&nod3, t, t);
545 	gopcode(as, &nod1, &nod2, &nod3);
546 	gmove(&nod3, t);
547 	regfree(&nod3);
548 }
549 
550 void
gmove(Node * f,Node * t)551 gmove(Node *f, Node *t)
552 {
553 	int ft, tt, a;
554 	Node nod, nod1, nod2;
555 	Prog *p1;
556 	double d;
557 
558 	ft = f->type->etype;
559 	tt = t->type->etype;
560 
561 	if(ft == TDOUBLE && f->op == OCONST) {
562 		d = f->fconst;
563 		if(d == 0.0) {
564 			a = FREGZERO;
565 			goto ffreg;
566 		}
567 		if(d == 0.5) {
568 			a = FREGHALF;
569 			goto ffreg;
570 		}
571 		if(d == 1.0) {
572 			a = FREGONE;
573 			goto ffreg;
574 		}
575 		if(d == 2.0) {
576 			a = FREGTWO;
577 			goto ffreg;
578 		}
579 		if(d == -.5) {
580 			fop(OSUB, FREGHALF, FREGZERO, t);
581 			return;
582 		}
583 		if(d == -1.0) {
584 			fop(OSUB, FREGONE, FREGZERO, t);
585 			return;
586 		}
587 		if(d == -2.0) {
588 			fop(OSUB, FREGTWO, FREGZERO, t);
589 			return;
590 		}
591 		if(d == 1.5) {
592 			fop(OADD, FREGONE, FREGHALF, t);
593 			return;
594 		}
595 		if(d == 2.5) {
596 			fop(OADD, FREGTWO, FREGHALF, t);
597 			return;
598 		}
599 		if(d == 3.0) {
600 			fop(OADD, FREGTWO, FREGONE, t);
601 			return;
602 		}
603 	}
604 	if(ft == TFLOAT && f->op == OCONST) {
605 		d = f->fconst;
606 		if(d == 0) {
607 			a = FREGZERO;
608 		ffreg:
609 			nodreg(&nod, f, NREG+a);
610 			gmove(&nod, t);
611 			return;
612 		}
613 	}
614 	/*
615 	 * a load --
616 	 * put it into a register then
617 	 * worry what to do with it.
618 	 */
619 	if(f->op == ONAME || f->op == OINDREG || f->op == OIND) {
620 		switch(ft) {
621 		default:
622 			if(typefd[tt]) {
623 				/* special case can load mem to Freg */
624 				regalloc(&nod, t, t);
625 				gins(AMOVW, f, &nod);
626 				a = AMOVWD;
627 				if(tt == TFLOAT)
628 					a = AMOVWF;
629 				gins(a, &nod, &nod);
630 				gmove(&nod, t);
631 				regfree(&nod);
632 				return;
633 			}
634 			a = AMOVW;
635 			break;
636 		case TFLOAT:
637 			a = AMOVF;
638 			break;
639 		case TDOUBLE:
640 			a = AMOVD;
641 			break;
642 		case TCHAR:
643 			a = AMOVB;
644 			break;
645 		case TUCHAR:
646 			a = AMOVBU;
647 			break;
648 		case TSHORT:
649 			a = AMOVH;
650 			break;
651 		case TUSHORT:
652 			a = AMOVHU;
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 		}
694 		if(!typefd[ft] && vconst(f) == 0) {
695 			gins(a, f, t);
696 			return;
697 		}
698 		if(ft == tt)
699 			regalloc(&nod, t, f);
700 		else
701 			regalloc(&nod, t, Z);
702 		gmove(f, &nod);
703 		gins(a, &nod, t);
704 		regfree(&nod);
705 		return;
706 	}
707 
708 	/*
709 	 * type x type cross table
710 	 */
711 	a = AGOK;
712 	switch(ft) {
713 	case TDOUBLE:
714 	case TVLONG:
715 	case TFLOAT:
716 		switch(tt) {
717 		case TDOUBLE:
718 		case TVLONG:
719 			a = AMOVD;
720 			if(ft == TFLOAT)
721 				a = AMOVFD;
722 			break;
723 		case TFLOAT:
724 			a = AMOVDF;
725 			if(ft == TFLOAT)
726 				a = AMOVF;
727 			break;
728 		case TINT:
729 		case TUINT:
730 		case TLONG:
731 		case TULONG:
732 		case TIND:
733 		case TSHORT:
734 		case TUSHORT:
735 		case TCHAR:
736 		case TUCHAR:
737 			if(fproundflg) {
738 				/* convert f, t */
739 				regalloc(&nod, f, Z);
740 				gins(AMOVDW, f, &nod);
741 				if(ft == TFLOAT)
742 					p->as = AMOVFW;
743 				gins(AMOVW, &nod, t);
744 				regfree(&nod);
745 				gins(AMOVW, t, t);
746 				return;
747 			}
748 			regalloc(&nod1, &regnode, Z);
749 			regalloc(&nod2, &regnode, Z);
750 
751 			/* movw fcr, rx */
752 			gins(AMOVW, Z, &nod1);
753 			p->from.type = D_FCREG;
754 			p->from.reg = 31;
755 
756 			/* nop */
757 			gins(ANOR, nodconst(0), nodconst(0));
758 			p->to.type = D_REG;
759 			p->to.reg = 0;
760 
761 			/* nop */
762 			gins(ANOR, nodconst(0), nodconst(0));
763 			p->to.type = D_REG;
764 			p->to.reg = 0;
765 
766 			/* or $3, rx, ry */
767 			gins(AOR, nodconst(3), &nod2);
768 			p->reg = nod1.reg;
769 
770 			/* xor $2, ry */
771 			gins(AXOR, nodconst(2), &nod2);
772 
773 			/* movw ry, fcr */
774 			gins(AMOVW, &nod2, Z);
775 			p->to.type = D_FCREG;
776 			p->to.reg = 31;
777 
778 			/* nop */
779 			gins(ANOR, nodconst(0), nodconst(0));
780 			p->to.type = D_REG;
781 			p->to.reg = 0;
782 
783 			/* nop */
784 			gins(ANOR, nodconst(0), nodconst(0));
785 			p->to.type = D_REG;
786 			p->to.reg = 0;
787 
788 			/* convert f, t */
789 			regalloc(&nod, f, Z);
790 			gins(AMOVDW, f, &nod);
791 			if(ft == TFLOAT)
792 				p->as = AMOVFW;
793 			gins(AMOVW, &nod, t);
794 			regfree(&nod);
795 			gins(AMOVW, t, t);
796 
797 			/* movw rx, fcr */
798 			gins(AMOVW, &nod1, Z);
799 			p->to.type = D_FCREG;
800 			p->to.reg = 31;
801 
802 			/* nop */
803 			gins(ANOR, nodconst(0), nodconst(0));
804 			p->to.type = D_REG;
805 			p->to.reg = 0;
806 
807 			/* nop */
808 			gins(ANOR, nodconst(0), nodconst(0));
809 			p->to.type = D_REG;
810 			p->to.reg = 0;
811 
812 			regfree(&nod1);
813 			regfree(&nod2);
814 			return;
815 		}
816 		break;
817 	case TINT:
818 	case TUINT:
819 	case TLONG:
820 	case TULONG:
821 	case TIND:
822 		switch(tt) {
823 		case TDOUBLE:
824 		case TVLONG:
825 			gins(AMOVW, f, t);
826 			gins(AMOVWD, t, t);
827 			if(ft == TULONG || ft == TUINT) {
828 				regalloc(&nod, t, Z);
829 				gins(ACMPGED, t, Z);
830 				p->reg = FREGZERO;
831 				gins(ABFPT, Z, Z);
832 				p1 = p;
833 				gins(AMOVD, nodfconst(4294967296.), &nod);
834 				gins(AADDD, &nod, t);
835 				patch(p1, pc);
836 				regfree(&nod);
837 			}
838 			return;
839 		case TFLOAT:
840 			gins(AMOVW, f, t);
841 			gins(AMOVWF, t, t);
842 			if(ft == TULONG || ft == TUINT) {
843 				regalloc(&nod, t, Z);
844 				gins(ACMPGEF, t, Z);
845 				p->reg = FREGZERO;
846 				gins(ABFPT, Z, Z);
847 				p1 = p;
848 				gins(AMOVF, nodfconst(4294967296.), &nod);
849 				gins(AADDF, &nod, t);
850 				patch(p1, pc);
851 				regfree(&nod);
852 			}
853 			return;
854 		case TINT:
855 		case TUINT:
856 		case TLONG:
857 		case TULONG:
858 		case TIND:
859 		case TSHORT:
860 		case TUSHORT:
861 		case TCHAR:
862 		case TUCHAR:
863 			a = AMOVW;
864 			break;
865 		}
866 		break;
867 	case TSHORT:
868 		switch(tt) {
869 		case TDOUBLE:
870 		case TVLONG:
871 			regalloc(&nod, f, Z);
872 			gins(AMOVH, f, &nod);
873 			gins(AMOVW, &nod, t);
874 			gins(AMOVWD, t, t);
875 			regfree(&nod);
876 			return;
877 		case TFLOAT:
878 			regalloc(&nod, f, Z);
879 			gins(AMOVH, f, &nod);
880 			gins(AMOVW, &nod, t);
881 			gins(AMOVWF, t, t);
882 			regfree(&nod);
883 			return;
884 		case TINT:
885 		case TUINT:
886 		case TLONG:
887 		case TULONG:
888 		case TIND:
889 			a = AMOVH;
890 			break;
891 		case TSHORT:
892 		case TUSHORT:
893 		case TCHAR:
894 		case TUCHAR:
895 			a = AMOVW;
896 			break;
897 		}
898 		break;
899 	case TUSHORT:
900 		switch(tt) {
901 		case TDOUBLE:
902 		case TVLONG:
903 			regalloc(&nod, f, Z);
904 			gins(AMOVHU, f, &nod);
905 			gins(AMOVW, &nod, t);
906 			gins(AMOVWD, t, t);
907 			regfree(&nod);
908 			return;
909 		case TFLOAT:
910 			regalloc(&nod, f, Z);
911 			gins(AMOVHU, f, &nod);
912 			gins(AMOVW, &nod, t);
913 			gins(AMOVWF, t, t);
914 			regfree(&nod);
915 			return;
916 		case TINT:
917 		case TUINT:
918 		case TLONG:
919 		case TULONG:
920 		case TIND:
921 			a = AMOVHU;
922 			break;
923 		case TSHORT:
924 		case TUSHORT:
925 		case TCHAR:
926 		case TUCHAR:
927 			a = AMOVW;
928 			break;
929 		}
930 		break;
931 	case TCHAR:
932 		switch(tt) {
933 		case TDOUBLE:
934 		case TVLONG:
935 			regalloc(&nod, f, Z);
936 			gins(AMOVB, f, &nod);
937 			gins(AMOVW, &nod, t);
938 			gins(AMOVWD, t, t);
939 			regfree(&nod);
940 			return;
941 		case TFLOAT:
942 			regalloc(&nod, f, Z);
943 			gins(AMOVB, f, &nod);
944 			gins(AMOVW, &nod, t);
945 			gins(AMOVWF, t, t);
946 			regfree(&nod);
947 			return;
948 		case TINT:
949 		case TUINT:
950 		case TLONG:
951 		case TULONG:
952 		case TIND:
953 		case TSHORT:
954 		case TUSHORT:
955 			a = AMOVB;
956 			break;
957 		case TCHAR:
958 		case TUCHAR:
959 			a = AMOVW;
960 			break;
961 		}
962 		break;
963 	case TUCHAR:
964 		switch(tt) {
965 		case TDOUBLE:
966 		case TVLONG:
967 			regalloc(&nod, f, Z);
968 			gins(AMOVBU, f, &nod);
969 			gins(AMOVW, &nod, t);
970 			gins(AMOVWD, t, t);
971 			regfree(&nod);
972 			return;
973 		case TFLOAT:
974 			regalloc(&nod, f, Z);
975 			gins(AMOVBU, f, &nod);
976 			gins(AMOVW, &nod, t);
977 			gins(AMOVWF, t, t);
978 			regfree(&nod);
979 			return;
980 		case TINT:
981 		case TUINT:
982 		case TLONG:
983 		case TULONG:
984 		case TIND:
985 		case TSHORT:
986 		case TUSHORT:
987 			a = AMOVBU;
988 			break;
989 		case TCHAR:
990 		case TUCHAR:
991 			a = AMOVW;
992 			break;
993 		}
994 		break;
995 	}
996 	if(a == AGOK)
997 		diag(Z, "bad opcode in gmove %T -> %T", f->type, t->type);
998 	if(a == AMOVW || a == AMOVF || a == AMOVD)
999 	if(samaddr(f, t))
1000 		return;
1001 	gins(a, f, t);
1002 }
1003 
1004 void
gins(int a,Node * f,Node * t)1005 gins(int a, Node *f, Node *t)
1006 {
1007 
1008 	nextpc();
1009 	p->as = a;
1010 	if(f != Z)
1011 		naddr(f, &p->from);
1012 	if(t != Z)
1013 		naddr(t, &p->to);
1014 	if(debug['g'])
1015 		print("%P\n", p);
1016 }
1017 
1018 void
gopcode(int o,Node * f1,Node * f2,Node * t)1019 gopcode(int o, Node *f1, Node *f2, Node *t)
1020 {
1021 	int a, et;
1022 	Adr ta;
1023 
1024 	et = TLONG;
1025 	if(f1 != Z && f1->type != T)
1026 		et = f1->type->etype;
1027 	a = AGOK;
1028 	switch(o) {
1029 	case OAS:
1030 		gmove(f1, t);
1031 		return;
1032 
1033 	case OASADD:
1034 	case OADD:
1035 		a = AADDU;
1036 		if(et == TFLOAT)
1037 			a = AADDF;
1038 		else
1039 		if(et == TDOUBLE || et == TVLONG)
1040 			a = AADDD;
1041 		break;
1042 
1043 	case OASSUB:
1044 	case OSUB:
1045 		a = ASUBU;
1046 		if(et == TFLOAT)
1047 			a = ASUBF;
1048 		else
1049 		if(et == TDOUBLE || et == TVLONG)
1050 			a = ASUBD;
1051 		break;
1052 
1053 	case OASOR:
1054 	case OOR:
1055 		a = AOR;
1056 		break;
1057 
1058 	case OASAND:
1059 	case OAND:
1060 		a = AAND;
1061 		break;
1062 
1063 	case OASXOR:
1064 	case OXOR:
1065 		a = AXOR;
1066 		break;
1067 
1068 	case OASLSHR:
1069 	case OLSHR:
1070 		a = ASRL;
1071 		break;
1072 
1073 	case OASASHR:
1074 	case OASHR:
1075 		a = ASRA;
1076 		break;
1077 
1078 	case OASASHL:
1079 	case OASHL:
1080 		a = ASLL;
1081 		break;
1082 
1083 	case OFUNC:
1084 		a = AJAL;
1085 		break;
1086 
1087 	case OCOND:
1088 		a = ASGTU;
1089 		break;
1090 
1091 	case OCOMMA:
1092 		a = ASGT;
1093 		break;
1094 
1095 	case OASMUL:
1096 	case OMUL:
1097 		if(et == TFLOAT) {
1098 			a = AMULF;
1099 			break;
1100 		} else
1101 		if(et == TDOUBLE || et == TVLONG) {
1102 			a = AMULD;
1103 			break;
1104 		}
1105 		a = AMUL;
1106 		goto muldiv;
1107 
1108 	case OASDIV:
1109 	case ODIV:
1110 		if(et == TFLOAT) {
1111 			a = ADIVF;
1112 			break;
1113 		} else
1114 		if(et == TDOUBLE || et == TVLONG) {
1115 			a = ADIVD;
1116 			break;
1117 		}
1118 		a = ADIV;
1119 		goto muldiv;
1120 
1121 	case OASMOD:
1122 	case OMOD:
1123 		a = ADIV;
1124 		o = OMOD;
1125 		goto muldiv;
1126 
1127 	case OASLMUL:
1128 	case OLMUL:
1129 		a = AMULU;
1130 		goto muldiv;
1131 
1132 	case OASLMOD:
1133 	case OLMOD:
1134 		a = ADIVU;
1135 		o = OMOD;
1136 		goto muldiv;
1137 
1138 	case OASLDIV:
1139 	case OLDIV:
1140 		a = ADIVU;
1141 		goto muldiv;
1142 
1143 	muldiv:
1144 		nextpc();
1145 		naddr(f1, &p->from);
1146 		if(f2 == Z)
1147 			raddr(t, p);
1148 		else
1149 			raddr(f2, p);
1150 		p->as = a;
1151 		if(debug['g'])
1152 			print("%P\n", p);
1153 
1154 		nextpc();
1155 		p->as = AMOVW;
1156 		a = D_LO;
1157 		if(o == OMOD)
1158 			a = D_HI;
1159 		p->from.type = a;
1160 		naddr(t, &p->to);
1161 		if(debug['g'])
1162 			print("%P\n", p);
1163 		return;
1164 
1165 	case OEQ:
1166 		if(!typefd[et]) {
1167 			a = ABEQ;
1168 			break;
1169 		}
1170 
1171 	case ONE:
1172 		if(!typefd[et]) {
1173 			a = ABNE;
1174 			break;
1175 		}
1176 
1177 	case OLT:
1178 	case OLE:
1179 	case OGE:
1180 	case OGT:
1181 		if(typefd[et]) {
1182 			nextpc();
1183 			if(et == TFLOAT) {
1184 				a = ACMPGTF;
1185 				if(o == OEQ || o == ONE)
1186 					a = ACMPEQF;
1187 				else
1188 				if(o == OLT || o == OGE)
1189 					a = ACMPGEF;
1190 			} else {
1191 				a = ACMPGTD;
1192 				if(o == OEQ || o == ONE)
1193 					a = ACMPEQD;
1194 				else
1195 				if(o == OLT || o == OGE)
1196 					a = ACMPGED;
1197 			}
1198 			p->as = a;
1199 			naddr(f1, &p->from);
1200 			raddr(f2, p);
1201 			if(debug['g'])
1202 				print("%P\n", p);
1203 			nextpc();
1204 			a = ABFPF;
1205 			if(o == OEQ || o == OGE || o == OGT)
1206 				a = ABFPT;
1207 			p->as = a;
1208 			if(debug['g'])
1209 				print("%P\n", p);
1210 			return;
1211 		}
1212 		if(vconst(f1) == 0 || vconst(f2) == 0) {
1213 			if(vconst(f1) == 0) {
1214 				o = invrel[relindex(o)];
1215 				f1 = f2;
1216 			}
1217 			switch(o) {
1218 			case OLT:
1219 				a = ABLTZ;
1220 				break;
1221 			case OLE:
1222 				a = ABLEZ;
1223 				break;
1224 			case OGE:
1225 				a = ABGEZ;
1226 				break;
1227 			case OGT:
1228 				a = ABGTZ;
1229 				break;
1230 			}
1231 			f2 = Z;
1232 			break;
1233 		}
1234 
1235 	case OLO:
1236 	case OLS:
1237 	case OHS:
1238 	case OHI:
1239 		nextpc();
1240 		if(o == OLE || o == OGT || o == OLS || o == OHI) {
1241 			naddr(f1, &p->from);
1242 			raddr(f2, p);
1243 		} else {
1244 			naddr(f2, &p->from);
1245 			raddr(f1, p);
1246 		}
1247 		naddr(&regnode, &p->to);
1248 		p->to.reg = tmpreg();
1249 		a = ASGT;
1250 		if(o == OLO || o == OLS || o == OHS || o == OHI)
1251 			a = ASGTU;
1252 		p->as = a;
1253 		if(debug['g'])
1254 			print("%P\n", p);
1255 
1256 		nextpc();
1257 		naddr(&regnode, &p->from);
1258 		p->from.reg = tmpreg();
1259 		a = ABEQ;
1260 		if(o == OLT || o == OGT || o == OLO || o == OHI)
1261 			a = ABNE;
1262 		p->as = a;
1263 		if(debug['g'])
1264 			print("%P\n", p);
1265 		return;
1266 	}
1267 	if(a == AGOK)
1268 		diag(Z, "bad in gopcode %O", o);
1269 	nextpc();
1270 	p->as = a;
1271 	if(f1 != Z)
1272 		naddr(f1, &p->from);
1273 	if(f2 != Z) {
1274 		naddr(f2, &ta);
1275 		p->reg = ta.reg;
1276 		if(ta.type == D_CONST && ta.offset == 0)
1277 			p->reg = REGZERO;
1278 	}
1279 	if(t != Z)
1280 		naddr(t, &p->to);
1281 	if(debug['g'])
1282 		print("%P\n", p);
1283 }
1284 
1285 int
samaddr(Node * f,Node * t)1286 samaddr(Node *f, Node *t)
1287 {
1288 
1289 	if(f->op != t->op)
1290 		return 0;
1291 	switch(f->op) {
1292 
1293 	case OREGISTER:
1294 		if(f->reg != t->reg)
1295 			break;
1296 		return 1;
1297 	}
1298 	return 0;
1299 }
1300 
1301 void
gbranch(int o)1302 gbranch(int o)
1303 {
1304 	int a;
1305 
1306 	a = AGOK;
1307 	switch(o) {
1308 	case ORETURN:
1309 		a = ARET;
1310 		break;
1311 	case OGOTO:
1312 		a = AJMP;
1313 		break;
1314 	}
1315 	nextpc();
1316 	if(a == AGOK) {
1317 		diag(Z, "bad in gbranch %O",  o);
1318 		nextpc();
1319 	}
1320 	p->as = a;
1321 }
1322 
1323 void
patch(Prog * op,long pc)1324 patch(Prog *op, long pc)
1325 {
1326 
1327 	op->to.offset = pc;
1328 	op->to.type = D_BRANCH;
1329 }
1330 
1331 void
gpseudo(int a,Sym * s,Node * n)1332 gpseudo(int a, Sym *s, Node *n)
1333 {
1334 
1335 	nextpc();
1336 	p->as = a;
1337 	p->from.type = D_OREG;
1338 	p->from.sym = s;
1339 	if(a == ATEXT)
1340 		p->reg = (profileflg ? 0 : NOPROF);
1341 	p->from.name = D_EXTERN;
1342 	if(s->class == CSTATIC)
1343 		p->from.name = D_STATIC;
1344 	naddr(n, &p->to);
1345 	if(a == ADATA || a == AGLOBL)
1346 		pc--;
1347 }
1348 
1349 int
sconst(Node * n)1350 sconst(Node *n)
1351 {
1352 	vlong vv;
1353 
1354 	if(n->op == OCONST) {
1355 		if(!typefd[n->type->etype]) {
1356 			vv = n->vconst;
1357 			if(vv >= (vlong)(-32766) && vv < (vlong)32766)
1358 				return 1;
1359 		}
1360 	}
1361 	return 0;
1362 }
1363 
1364 int
sval(long v)1365 sval(long v)
1366 {
1367 	if(v >= -32766L && v < 32766L)
1368 		return 1;
1369 	return 0;
1370 }
1371 
1372 long
exreg(Type * t)1373 exreg(Type *t)
1374 {
1375 	long o;
1376 
1377 	if(typechlp[t->etype]) {
1378 		if(exregoffset <= 16)
1379 			return 0;
1380 		o = exregoffset;
1381 		exregoffset--;
1382 		return o;
1383 	}
1384 	if(typefd[t->etype]) {
1385 		if(exfregoffset <= 16)
1386 			return 0;
1387 		o = exfregoffset + NREG;
1388 		exfregoffset--;
1389 		return o;
1390 	}
1391 	return 0;
1392 }
1393 
1394 schar	ewidth[NTYPE] =
1395 {
1396 	-1,		/* [TXXX] */
1397 	SZ_CHAR,	/* [TCHAR] */
1398 	SZ_CHAR,	/* [TUCHAR] */
1399 	SZ_SHORT,	/* [TSHORT] */
1400 	SZ_SHORT,	/* [TUSHORT] */
1401 	SZ_INT,		/* [TINT] */
1402 	SZ_INT,		/* [TUINT] */
1403 	SZ_LONG,	/* [TLONG] */
1404 	SZ_LONG,	/* [TULONG] */
1405 	SZ_VLONG,	/* [TVLONG] */
1406 	SZ_VLONG,	/* [TUVLONG] */
1407 	SZ_FLOAT,	/* [TFLOAT] */
1408 	SZ_DOUBLE,	/* [TDOUBLE] */
1409 	SZ_IND,		/* [TIND] */
1410 	0,		/* [TFUNC] */
1411 	-1,		/* [TARRAY] */
1412 	0,		/* [TVOID] */
1413 	-1,		/* [TSTRUCT] */
1414 	-1,		/* [TUNION] */
1415 	SZ_INT,		/* [TENUM] */
1416 };
1417 
1418 long	ncast[NTYPE] =
1419 {
1420 	0,				/* [TXXX] */
1421 	BCHAR|BUCHAR,			/* [TCHAR] */
1422 	BCHAR|BUCHAR,			/* [TUCHAR] */
1423 	BSHORT|BUSHORT,			/* [TSHORT] */
1424 	BSHORT|BUSHORT,			/* [TUSHORT] */
1425 	BINT|BUINT|BLONG|BULONG|BIND,	/* [TINT] */
1426 	BINT|BUINT|BLONG|BULONG|BIND,	/* [TUINT] */
1427 	BINT|BUINT|BLONG|BULONG|BIND,	/* [TLONG] */
1428 	BINT|BUINT|BLONG|BULONG|BIND,	/* [TULONG] */
1429 	BVLONG|BUVLONG,			/* [TVLONG] */
1430 	BVLONG|BUVLONG,			/* [TUVLONG] */
1431 	BFLOAT,				/* [TFLOAT] */
1432 	BDOUBLE,			/* [TDOUBLE] */
1433 	BLONG|BULONG|BIND,		/* [TIND] */
1434 	0,				/* [TFUNC] */
1435 	0,				/* [TARRAY] */
1436 	0,				/* [TVOID] */
1437 	BSTRUCT,			/* [TSTRUCT] */
1438 	BUNION,				/* [TUNION] */
1439 	0,				/* [TENUM] */
1440 };
1441