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