xref: /plan9/sys/src/cmd/5c/txt.c (revision 7d7728c9ff780bb29e70ac5c0f1bb4c0d6187a9b)
1 #include "gc.h"
2 
3 static	char	resvreg[nelem(reg)];
4 
5 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
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
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
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
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*
220 nodconst(long v)
221 {
222 	constnode.vconst = v;
223 	return &constnode;
224 }
225 
226 Node*
227 nod32const(vlong v)
228 {
229 	constnode.vconst = v & MASK(32);
230 	return &constnode;
231 }
232 
233 Node*
234 nodfconst(double d)
235 {
236 	fconstnode.fconst = d;
237 	return &fconstnode;
238 }
239 
240 void
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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 			gins(AMOVF, nodfconst(2147483648.), &nod);
725 			gins(AADDF, &nod, t);
726 			regfree(&nod);
727 			patch(p1, pc);
728 			return;
729 		}
730 		// fall through
731 
732 	case TINT:
733 	case TLONG:
734 	case TIND:
735 		switch(tt) {
736 		case TDOUBLE:
737 			gins(AMOVWD, f, t);
738 			return;
739 		case TFLOAT:
740 			gins(AMOVWF, f, t);
741 			return;
742 		case TINT:
743 		case TUINT:
744 		case TLONG:
745 		case TULONG:
746 		case TIND:
747 		case TSHORT:
748 		case TUSHORT:
749 		case TCHAR:
750 		case TUCHAR:
751 			a = AMOVW;
752 			break;
753 		}
754 		break;
755 	case TSHORT:
756 		switch(tt) {
757 		case TDOUBLE:
758 			regalloc(&nod, f, Z);
759 			gins(AMOVH, f, &nod);
760 			gins(AMOVWD, &nod, t);
761 			regfree(&nod);
762 			return;
763 		case TFLOAT:
764 			regalloc(&nod, f, Z);
765 			gins(AMOVH, f, &nod);
766 			gins(AMOVWF, &nod, t);
767 			regfree(&nod);
768 			return;
769 		case TUINT:
770 		case TINT:
771 		case TULONG:
772 		case TLONG:
773 		case TIND:
774 			a = AMOVH;
775 			break;
776 		case TSHORT:
777 		case TUSHORT:
778 		case TCHAR:
779 		case TUCHAR:
780 			a = AMOVW;
781 			break;
782 		}
783 		break;
784 	case TUSHORT:
785 		switch(tt) {
786 		case TDOUBLE:
787 			regalloc(&nod, f, Z);
788 			gins(AMOVHU, f, &nod);
789 			gins(AMOVWD, &nod, t);
790 			regfree(&nod);
791 			return;
792 		case TFLOAT:
793 			regalloc(&nod, f, Z);
794 			gins(AMOVHU, f, &nod);
795 			gins(AMOVWF, &nod, t);
796 			regfree(&nod);
797 			return;
798 		case TINT:
799 		case TUINT:
800 		case TLONG:
801 		case TULONG:
802 		case TIND:
803 			a = AMOVHU;
804 			break;
805 		case TSHORT:
806 		case TUSHORT:
807 		case TCHAR:
808 		case TUCHAR:
809 			a = AMOVW;
810 			break;
811 		}
812 		break;
813 	case TCHAR:
814 		switch(tt) {
815 		case TDOUBLE:
816 			regalloc(&nod, f, Z);
817 			gins(AMOVB, f, &nod);
818 			gins(AMOVWD, &nod, t);
819 			regfree(&nod);
820 			return;
821 		case TFLOAT:
822 			regalloc(&nod, f, Z);
823 			gins(AMOVB, f, &nod);
824 			gins(AMOVWF, &nod, t);
825 			regfree(&nod);
826 			return;
827 		case TINT:
828 		case TUINT:
829 		case TLONG:
830 		case TULONG:
831 		case TIND:
832 		case TSHORT:
833 		case TUSHORT:
834 			a = AMOVB;
835 			break;
836 		case TCHAR:
837 		case TUCHAR:
838 			a = AMOVW;
839 			break;
840 		}
841 		break;
842 	case TUCHAR:
843 		switch(tt) {
844 		case TDOUBLE:
845 			regalloc(&nod, f, Z);
846 			gins(AMOVBU, f, &nod);
847 			gins(AMOVWD, &nod, t);
848 			regfree(&nod);
849 			return;
850 		case TFLOAT:
851 			regalloc(&nod, f, Z);
852 			gins(AMOVBU, f, &nod);
853 			gins(AMOVWF, &nod, t);
854 			regfree(&nod);
855 			return;
856 		case TINT:
857 		case TUINT:
858 		case TLONG:
859 		case TULONG:
860 		case TIND:
861 		case TSHORT:
862 		case TUSHORT:
863 			a = AMOVBU;
864 			break;
865 		case TCHAR:
866 		case TUCHAR:
867 			a = AMOVW;
868 			break;
869 		}
870 		break;
871 	}
872 	if(a == AGOK)
873 		diag(Z, "bad opcode in gmove %T -> %T", f->type, t->type);
874 	if(a == AMOVW || a == AMOVF || a == AMOVD)
875 	if(samaddr(f, t))
876 		return;
877 	gins(a, f, t);
878 }
879 
880 void
881 gmover(Node *f, Node *t)
882 {
883 	int ft, tt, a;
884 
885 	ft = f->type->etype;
886 	tt = t->type->etype;
887 	a = AGOK;
888 	if(typechlp[ft] && typechlp[tt] && ewidth[ft] >= ewidth[tt]){
889 		switch(tt){
890 		case TSHORT:
891 			a = AMOVH;
892 			break;
893 		case TUSHORT:
894 			a = AMOVHU;
895 			break;
896 		case TCHAR:
897 			a = AMOVB;
898 			break;
899 		case TUCHAR:
900 			a = AMOVBU;
901 			break;
902 		}
903 	}
904 	if(a == AGOK)
905 		gmove(f, t);
906 	else
907 		gins(a, f, t);
908 }
909 
910 void
911 gins(int a, Node *f, Node *t)
912 {
913 
914 	nextpc();
915 	p->as = a;
916 	if(f != Z)
917 		naddr(f, &p->from);
918 	if(t != Z)
919 		naddr(t, &p->to);
920 	if(debug['g'])
921 		print("%P\n", p);
922 }
923 
924 void
925 gopcode(int o, Node *f1, Node *f2, Node *t)
926 {
927 	int a, et;
928 	Adr ta;
929 
930 	et = TLONG;
931 	if(f1 != Z && f1->type != T)
932 		et = f1->type->etype;
933 	a = AGOK;
934 	switch(o) {
935 	case OAS:
936 		gmove(f1, t);
937 		return;
938 
939 	case OASADD:
940 	case OADD:
941 		a = AADD;
942 		if(et == TFLOAT)
943 			a = AADDF;
944 		else
945 		if(et == TDOUBLE || et == TVLONG)
946 			a = AADDD;
947 		break;
948 
949 	case OASSUB:
950 	case OSUB:
951 		if(f2 && f2->op == OCONST) {
952 			Node *t = f1;
953 			f1 = f2;
954 			f2 = t;
955 			a = ARSB;
956 		} else
957 			a = ASUB;
958 		if(et == TFLOAT)
959 			a = ASUBF;
960 		else
961 		if(et == TDOUBLE || et == TVLONG)
962 			a = ASUBD;
963 		break;
964 
965 	case OASOR:
966 	case OOR:
967 		a = AORR;
968 		break;
969 
970 	case OASAND:
971 	case OAND:
972 		a = AAND;
973 		break;
974 
975 	case OASXOR:
976 	case OXOR:
977 		a = AEOR;
978 		break;
979 
980 	case OASLSHR:
981 	case OLSHR:
982 		a = ASRL;
983 		break;
984 
985 	case OASASHR:
986 	case OASHR:
987 		a = ASRA;
988 		break;
989 
990 	case OASASHL:
991 	case OASHL:
992 		a = ASLL;
993 		break;
994 
995 	case OFUNC:
996 		a = ABL;
997 		break;
998 
999 	case OASMUL:
1000 	case OMUL:
1001 		a = AMUL;
1002 		if(et == TFLOAT)
1003 			a = AMULF;
1004 		else
1005 		if(et == TDOUBLE || et == TVLONG)
1006 			a = AMULD;
1007 		break;
1008 
1009 	case OASDIV:
1010 	case ODIV:
1011 		a = ADIV;
1012 		if(et == TFLOAT)
1013 			a = ADIVF;
1014 		else
1015 		if(et == TDOUBLE || et == TVLONG)
1016 			a = ADIVD;
1017 		break;
1018 
1019 	case OASMOD:
1020 	case OMOD:
1021 		a = AMOD;
1022 		break;
1023 
1024 	case OASLMUL:
1025 	case OLMUL:
1026 		a = AMULU;
1027 		break;
1028 
1029 	case OASLMOD:
1030 	case OLMOD:
1031 		a = AMODU;
1032 		break;
1033 
1034 	case OASLDIV:
1035 	case OLDIV:
1036 		a = ADIVU;
1037 		break;
1038 
1039 	case OCASE:
1040 	case OEQ:
1041 	case ONE:
1042 	case OLT:
1043 	case OLE:
1044 	case OGE:
1045 	case OGT:
1046 	case OLO:
1047 	case OLS:
1048 	case OHS:
1049 	case OHI:
1050 		a = ACMP;
1051 		if(et == TFLOAT)
1052 			a = ACMPF;
1053 		else
1054 		if(et == TDOUBLE || et == TVLONG)
1055 			a = ACMPD;
1056 		nextpc();
1057 		p->as = a;
1058 		naddr(f1, &p->from);
1059 		if(a == ACMP && f1->op == OCONST && p->from.offset < 0) {
1060 			p->as = ACMN;
1061 			p->from.offset = -p->from.offset;
1062 		}
1063 		raddr(f2, p);
1064 		switch(o) {
1065 		case OEQ:
1066 			a = ABEQ;
1067 			break;
1068 		case ONE:
1069 			a = ABNE;
1070 			break;
1071 		case OLT:
1072 			a = ABLT;
1073 			break;
1074 		case OLE:
1075 			a = ABLE;
1076 			break;
1077 		case OGE:
1078 			a = ABGE;
1079 			break;
1080 		case OGT:
1081 			a = ABGT;
1082 			break;
1083 		case OLO:
1084 			a = ABLO;
1085 			break;
1086 		case OLS:
1087 			a = ABLS;
1088 			break;
1089 		case OHS:
1090 			a = ABHS;
1091 			break;
1092 		case OHI:
1093 			a = ABHI;
1094 			break;
1095 		case OCASE:
1096 			nextpc();
1097 			p->as = ACASE;
1098 			p->scond = 0x9;
1099 			naddr(f2, &p->from);
1100 			a = ABHI;
1101 			break;
1102 		}
1103 		f1 = Z;
1104 		f2 = Z;
1105 		break;
1106 	}
1107 	if(a == AGOK)
1108 		diag(Z, "bad in gopcode %O", o);
1109 	nextpc();
1110 	p->as = a;
1111 	if(f1 != Z)
1112 		naddr(f1, &p->from);
1113 	if(f2 != Z) {
1114 		naddr(f2, &ta);
1115 		p->reg = ta.reg;
1116 	}
1117 	if(t != Z)
1118 		naddr(t, &p->to);
1119 	if(debug['g'])
1120 		print("%P\n", p);
1121 }
1122 
1123 samaddr(Node *f, Node *t)
1124 {
1125 
1126 	if(f->op != t->op)
1127 		return 0;
1128 	switch(f->op) {
1129 
1130 	case OREGISTER:
1131 		if(f->reg != t->reg)
1132 			break;
1133 		return 1;
1134 	}
1135 	return 0;
1136 }
1137 
1138 void
1139 gbranch(int o)
1140 {
1141 	int a;
1142 
1143 	a = AGOK;
1144 	switch(o) {
1145 	case ORETURN:
1146 		a = ARET;
1147 		break;
1148 	case OGOTO:
1149 		a = AB;
1150 		break;
1151 	}
1152 	nextpc();
1153 	if(a == AGOK) {
1154 		diag(Z, "bad in gbranch %O",  o);
1155 		nextpc();
1156 	}
1157 	p->as = a;
1158 }
1159 
1160 void
1161 patch(Prog *op, long pc)
1162 {
1163 
1164 	op->to.offset = pc;
1165 	op->to.type = D_BRANCH;
1166 }
1167 
1168 void
1169 gpseudo(int a, Sym *s, Node *n)
1170 {
1171 
1172 	nextpc();
1173 	p->as = a;
1174 	p->from.type = D_OREG;
1175 	p->from.sym = s;
1176 	p->from.name = D_EXTERN;
1177 	if(a == ATEXT)
1178 		p->reg = (profileflg ? 0 : NOPROF);
1179 	if(s->class == CSTATIC)
1180 		p->from.name = D_STATIC;
1181 	naddr(n, &p->to);
1182 	if(a == ADATA || a == AGLOBL)
1183 		pc--;
1184 }
1185 
1186 int
1187 sconst(Node *n)
1188 {
1189 	vlong vv;
1190 
1191 	if(n->op == OCONST) {
1192 		if(!typefd[n->type->etype]) {
1193 			vv = n->vconst;
1194 			if(vv >= (vlong)(-32766) && vv < (vlong)32766)
1195 				return 1;
1196 			/*
1197 			 * should be specialised for constant values which will
1198 			 * fit in different instructionsl; for now, let 5l
1199 			 * sort it out
1200 			 */
1201 			return 1;
1202 		}
1203 	}
1204 	return 0;
1205 }
1206 
1207 int
1208 sval(long v)
1209 {
1210 	int i;
1211 
1212 	for(i=0; i<16; i++) {
1213 		if((v & ~0xff) == 0)
1214 			return 1;
1215 		if((~v & ~0xff) == 0)
1216 			return 1;
1217 		v = (v<<2) | ((ulong)v>>30);
1218 	}
1219 	return 0;
1220 }
1221 
1222 long
1223 exreg(Type *t)
1224 {
1225 	long o;
1226 
1227 	if(typechlp[t->etype]) {
1228 		if(exregoffset <= REGEXT-2)
1229 			return 0;
1230 		o = exregoffset;
1231 		if(reg[o] && !resvreg[o])
1232 			return 0;
1233 		resvreg[o] = reg[o] = 1;
1234 		exregoffset--;
1235 		return o;
1236 	}
1237 	if(typefd[t->etype]) {
1238 		if(exfregoffset <= NFREG-1)
1239 			return 0;
1240 		o = exfregoffset + NREG;
1241 		if(reg[o] && !resvreg[o])
1242 			return 0;
1243 		resvreg[o] = reg[o] = 1;
1244 		exfregoffset--;
1245 		return o;
1246 	}
1247 	return 0;
1248 }
1249 
1250 schar	ewidth[NTYPE] =
1251 {
1252 	-1,		/* [TXXX] */
1253 	SZ_CHAR,	/* [TCHAR] */
1254 	SZ_CHAR,	/* [TUCHAR] */
1255 	SZ_SHORT,	/* [TSHORT] */
1256 	SZ_SHORT,	/* [TUSHORT] */
1257 	SZ_INT,		/* [TINT] */
1258 	SZ_INT,		/* [TUINT] */
1259 	SZ_LONG,	/* [TLONG] */
1260 	SZ_LONG,	/* [TULONG] */
1261 	SZ_VLONG,	/* [TVLONG] */
1262 	SZ_VLONG,	/* [TUVLONG] */
1263 	SZ_FLOAT,	/* [TFLOAT] */
1264 	SZ_DOUBLE,	/* [TDOUBLE] */
1265 	SZ_IND,		/* [TIND] */
1266 	0,		/* [TFUNC] */
1267 	-1,		/* [TARRAY] */
1268 	0,		/* [TVOID] */
1269 	-1,		/* [TSTRUCT] */
1270 	-1,		/* [TUNION] */
1271 	SZ_INT,		/* [TENUM] */
1272 };
1273 
1274 long	ncast[NTYPE] =
1275 {
1276 	0,				/* [TXXX] */
1277 	BCHAR|BUCHAR,			/* [TCHAR] */
1278 	BCHAR|BUCHAR,			/* [TUCHAR] */
1279 	BSHORT|BUSHORT,			/* [TSHORT] */
1280 	BSHORT|BUSHORT,			/* [TUSHORT] */
1281 	BINT|BUINT|BLONG|BULONG|BIND,	/* [TINT] */
1282 	BINT|BUINT|BLONG|BULONG|BIND,	/* [TUINT] */
1283 	BINT|BUINT|BLONG|BULONG|BIND,	/* [TLONG] */
1284 	BINT|BUINT|BLONG|BULONG|BIND,	/* [TULONG] */
1285 	BVLONG|BUVLONG,			/* [TVLONG] */
1286 	BVLONG|BUVLONG,			/* [TUVLONG] */
1287 	BFLOAT,				/* [TFLOAT] */
1288 	BDOUBLE,			/* [TDOUBLE] */
1289 	BLONG|BULONG|BIND,		/* [TIND] */
1290 	0,				/* [TFUNC] */
1291 	0,				/* [TARRAY] */
1292 	0,				/* [TVOID] */
1293 	BSTRUCT,			/* [TSTRUCT] */
1294 	BUNION,				/* [TUNION] */
1295 	0,				/* [TENUM] */
1296 };
1297