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