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