xref: /plan9/sys/src/cmd/qc/txt.c (revision 3a276d325f04ac257b9c43368cb5f1a9617308f0)
1 #include "gc.h"
2 
3 static	int	resvreg[nelem(reg)];
4 
5 static	void	gopcode64(int, Node*, Node*, Node*);
6 static	void	gori64(int, Node*, Node*, Node*);
7 static	void	gandi64(int, Node*, Node*, Node*);
8 
9 void
ginit(void)10 ginit(void)
11 {
12 	Type *t;
13 
14 	thechar = 'q';
15 	thestring = "power";
16 	exregoffset = REGEXT;
17 	exfregoffset = FREGEXT;
18 	newvlongcode = 1;
19 	listinit();
20 	nstring = 0;
21 	mnstring = 0;
22 	nrathole = 0;
23 	pc = 0;
24 	breakpc = -1;
25 	continpc = -1;
26 	cases = C;
27 	firstp = P;
28 	lastp = P;
29 	tfield = types[TLONG];
30 
31 	typeswitch = typechlv;
32 
33 	zprog.link = P;
34 	zprog.as = AGOK;
35 	zprog.reg = NREG;
36 	zprog.from.type = D_NONE;
37 	zprog.from.name = D_NONE;
38 	zprog.from.reg = NREG;
39 	zprog.from3 = zprog.from;
40 	zprog.to = zprog.from;
41 
42 	regnode.op = OREGISTER;
43 	regnode.class = CEXREG;
44 	regnode.reg = 0;
45 	regnode.complex = 0;
46 	regnode.addable = 11;
47 	regnode.type = types[TLONG];
48 
49 	constnode.op = OCONST;
50 	constnode.class = CXXX;
51 	constnode.complex = 0;
52 	constnode.addable = 20;
53 	constnode.type = types[TLONG];
54 
55 	fconstnode.op = OCONST;
56 	fconstnode.class = CXXX;
57 	fconstnode.complex = 0;
58 	fconstnode.addable = 20;
59 	fconstnode.type = types[TDOUBLE];
60 
61 	nodsafe = new(ONAME, Z, Z);
62 	nodsafe->sym = slookup(".safe");
63 	nodsafe->type = types[TINT];
64 	nodsafe->etype = types[TINT]->etype;
65 	nodsafe->class = CAUTO;
66 	complex(nodsafe);
67 
68 	t = typ(TARRAY, types[TCHAR]);
69 	symrathole = slookup(".rathole");
70 	symrathole->class = CGLOBL;
71 	symrathole->type = t;
72 
73 	nodrat = new(ONAME, Z, Z);
74 	nodrat->sym = symrathole;
75 	nodrat->type = types[TIND];
76 	nodrat->etype = TVOID;
77 	nodrat->class = CGLOBL;
78 	complex(nodrat);
79 	nodrat->type = t;
80 
81 	com64init();
82 
83 	memset(reg, 0, sizeof(reg));
84 	reg[REGZERO] = 1;	/* don't use */
85 	reg[REGTMP] = 1;
86 	reg[FREGCVI+NREG] = 1;
87 	reg[FREGZERO+NREG] = 1;
88 	reg[FREGHALF+NREG] = 1;
89 	reg[FREGONE+NREG] = 1;
90 	reg[FREGTWO+NREG] = 1;
91 	memmove(resvreg, reg, sizeof(reg));
92 }
93 
94 void
gclean(void)95 gclean(void)
96 {
97 	int i;
98 	Sym *s;
99 
100 	for(i=0; i<NREG; i++)
101 		if(reg[i] && !resvreg[i])
102 			diag(Z, "reg %d left allocated", i);
103 	for(i=NREG; i<NREG+NREG; i++)
104 		if(reg[i] && !resvreg[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(typesuv[n->type->etype]) {
188 		regaalloc(tn2, n);
189 		if(n->complex >= FNX) {
190 			cgen(*fnxp, tn2);
191 			(*fnxp)++;
192 		} else
193 			cgen(n, tn2);
194 		return;
195 	}
196 	if(REGARG && curarg == 0 && typechlp[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*
nod32const(vlong v)222 nod32const(vlong v)
223 {
224 	constnode.vconst = v & MASK(32);
225 	return &constnode;
226 }
227 
228 Node*
nodconst(long v)229 nodconst(long v)
230 {
231 	constnode.vconst = v;
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 void
regalloc(Node * n,Node * tn,Node * o)264 regalloc(Node *n, Node *tn, Node *o)
265 {
266 	int i, j;
267 	static int lasti;
268 
269 	switch(tn->type->etype) {
270 	case TCHAR:
271 	case TUCHAR:
272 	case TSHORT:
273 	case TUSHORT:
274 	case TINT:
275 	case TUINT:
276 	case TLONG:
277 	case TULONG:
278 	case TIND:
279 		if(o != Z && o->op == OREGISTER) {
280 			i = o->reg;
281 			if(i > 0 && i < NREG)
282 				goto out;
283 		}
284 		j = lasti + REGRET+1;
285 		for(i=REGRET+1; i<NREG; i++) {
286 			if(j >= NREG)
287 				j = REGRET+1;
288 			if(reg[j] == 0) {
289 				i = j;
290 				goto out;
291 			}
292 			j++;
293 		}
294 		diag(tn, "out of fixed registers");
295 		goto err;
296 
297 	case TFLOAT:
298 	case TDOUBLE:
299 		if(o != Z && o->op == OREGISTER) {
300 			i = o->reg;
301 			if(i >= NREG && i < NREG+NREG)
302 				goto out;
303 		}
304 		j = lasti + NREG;
305 		for(i=NREG; i<NREG+NREG; i++) {
306 			if(j >= NREG+NREG)
307 				j = NREG;
308 			if(reg[j] == 0) {
309 				i = j;
310 				goto out;
311 			}
312 			j++;
313 		}
314 		diag(tn, "out of float registers");
315 		goto err;
316 
317 	case TVLONG:
318 	case TUVLONG:
319 		n->op = OREGPAIR;
320 		n->complex = 0;	/* already in registers */
321 		n->addable = 11;
322 		n->type = tn->type;
323 		n->lineno = nearln;
324 		n->left = alloc(sizeof(Node));
325 		n->right = alloc(sizeof(Node));
326 		if(o != Z && o->op == OREGPAIR) {
327 			regalloc(n->left, &regnode, o->left);
328 			regalloc(n->right, &regnode, o->right);
329 		} else {
330 			regalloc(n->left, &regnode, Z);
331 			regalloc(n->right, &regnode, Z);
332 		}
333 		n->right->type = types[TULONG];
334 		if(tn->type->etype == TUVLONG)
335 			n->left->type = types[TULONG];	/* TO DO: is this a bad idea? */
336 		return;
337 	}
338 	diag(tn, "unknown type in regalloc: %T", tn->type);
339 err:
340 	i = 0;
341 out:
342 	if(i)
343 		reg[i]++;
344 	lasti++;
345 	if(lasti >= 5)
346 		lasti = 0;
347 	nodreg(n, tn, i);
348 }
349 
350 void
regialloc(Node * n,Node * tn,Node * o)351 regialloc(Node *n, Node *tn, Node *o)
352 {
353 	Node nod;
354 
355 	nod = *tn;
356 	nod.type = types[TIND];
357 	regalloc(n, &nod, o);
358 }
359 
360 void
regfree(Node * n)361 regfree(Node *n)
362 {
363 	int i;
364 
365 	if(n->op == OREGPAIR) {
366 		regfree(n->left);
367 		regfree(n->right);
368 		return;
369 	}
370 	i = 0;
371 	if(n->op != OREGISTER && n->op != OINDREG)
372 		goto err;
373 	i = n->reg;
374 	if(i < 0 || i >= sizeof(reg))
375 		goto err;
376 	if(reg[i] <= 0)
377 		goto err;
378 	reg[i]--;
379 	return;
380 err:
381 	diag(n, "error in regfree: %d [%d]", i, reg[i]);
382 	prtree(n, "regfree");
383 }
384 
385 void
regsalloc(Node * n,Node * nn)386 regsalloc(Node *n, Node *nn)
387 {
388 	cursafe = align(cursafe+stkoff, nn->type, Aaut3)-stkoff;
389 	maxargsafe = maxround(maxargsafe, cursafe+curarg);
390 //	if(nn->type->etype == TDOUBLE || nn->type->etype == TVLONG){
391 //		extern int hasdoubled;
392 //		fprint(2, "stkoff=%ld cursafe=%ld curarg=%ld %d\n", stkoff, cursafe, curarg, hasdoubled);
393 //	}
394 	*n = *nodsafe;
395 	n->xoffset = -(stkoff + cursafe);
396 	n->type = nn->type;
397 	n->etype = nn->type->etype;
398 	n->lineno = nn->lineno;
399 }
400 
401 void
regaalloc1(Node * n,Node * nn)402 regaalloc1(Node *n, Node *nn)
403 {
404 	nodreg(n, nn, REGARG);
405 	reg[REGARG]++;
406 	curarg = align(curarg, nn->type, Aarg1);
407 	curarg = align(curarg, nn->type, Aarg2);
408 	maxargsafe = maxround(maxargsafe, cursafe+curarg);
409 }
410 
411 void
regaalloc(Node * n,Node * nn)412 regaalloc(Node *n, Node *nn)
413 {
414 	curarg = align(curarg, nn->type, Aarg1);
415 	*n = *nn;
416 	n->op = OINDREG;
417 	n->reg = REGSP;
418 	n->xoffset = curarg + SZ_LONG;
419 	n->complex = 0;
420 	n->addable = 20;
421 	curarg = align(curarg, nn->type, Aarg2);
422 	maxargsafe = maxround(maxargsafe, cursafe+curarg);
423 }
424 
425 void
regind(Node * n,Node * nn)426 regind(Node *n, Node *nn)
427 {
428 
429 	if(n->op != OREGISTER) {
430 		diag(n, "regind not OREGISTER");
431 		return;
432 	}
433 	n->op = OINDREG;
434 	n->type = nn->type;
435 }
436 
437 void
raddr(Node * n,Prog * p)438 raddr(Node *n, Prog *p)
439 {
440 	Adr a;
441 
442 	naddr(n, &a);
443 	if(R0ISZERO && a.type == D_CONST && a.offset == 0) {
444 		a.type = D_REG;
445 		a.reg = REGZERO;
446 	}
447 	if(a.type != D_REG && a.type != D_FREG) {
448 		if(n)
449 			diag(n, "bad in raddr: %O", n->op);
450 		else
451 			diag(n, "bad in raddr: <null>");
452 		p->reg = NREG;
453 	} else
454 		p->reg = a.reg;
455 }
456 
457 void
naddr(Node * n,Adr * a)458 naddr(Node *n, Adr *a)
459 {
460 	long v;
461 
462 	a->type = D_NONE;
463 	if(n == Z)
464 		return;
465 	switch(n->op) {
466 	default:
467 	bad:
468 		diag(n, "bad in naddr: %O", n->op);
469 		break;
470 
471 	case OREGISTER:
472 		a->type = D_REG;
473 		a->sym = S;
474 		a->reg = n->reg;
475 		if(a->reg >= NREG) {
476 			a->type = D_FREG;
477 			a->reg -= NREG;
478 		}
479 		break;
480 
481 	case OIND:
482 		naddr(n->left, a);
483 		a->offset += n->xoffset;	/* little hack for reglcgenv */
484 		if(a->type == D_REG) {
485 			a->type = D_OREG;
486 			break;
487 		}
488 		if(a->type == D_CONST) {
489 			a->type = D_OREG;
490 			break;
491 		}
492 		goto bad;
493 
494 	case OINDREG:
495 		a->type = D_OREG;
496 		a->sym = S;
497 		a->offset = n->xoffset;
498 		a->reg = n->reg;
499 		break;
500 
501 	case ONAME:
502 		a->etype = n->etype;
503 		a->type = D_OREG;
504 		a->name = D_STATIC;
505 		a->sym = n->sym;
506 		a->offset = n->xoffset;
507 		if(n->class == CSTATIC)
508 			break;
509 		if(n->class == CEXTERN || n->class == CGLOBL) {
510 			a->name = D_EXTERN;
511 			break;
512 		}
513 		if(n->class == CAUTO) {
514 			a->name = D_AUTO;
515 			break;
516 		}
517 		if(n->class == CPARAM) {
518 			a->name = D_PARAM;
519 			break;
520 		}
521 		goto bad;
522 
523 	case OCONST:
524 		a->sym = S;
525 		a->reg = NREG;
526 		if(typefd[n->type->etype]) {
527 			a->type = D_FCONST;
528 			a->dval = n->fconst;
529 		} else {
530 			a->type = D_CONST;
531 			a->offset = n->vconst;
532 		}
533 		break;
534 
535 	case OADDR:
536 		naddr(n->left, a);
537 		if(a->type == D_OREG) {
538 			a->type = D_CONST;
539 			break;
540 		}
541 		goto bad;
542 
543 	case OADD:
544 		if(n->left->op == OCONST) {
545 			naddr(n->left, a);
546 			v = a->offset;
547 			naddr(n->right, a);
548 		} else {
549 			naddr(n->right, a);
550 			v = a->offset;
551 			naddr(n->left, a);
552 		}
553 		a->offset += v;
554 		break;
555 
556 	}
557 }
558 
559 void
gloadhi(Node * f,Node * t,int c)560 gloadhi(Node *f, Node *t, int c)
561 {
562 	Type *ot;
563 
564 	if(f->op == OCONST){
565 		f = nodconst((long)(f->vconst>>32));
566 		if(c==1 && sconst(f) || c==2 && uconst(f)){
567 			if(t->op == OREGISTER)
568 				regfree(t);
569 			*t = *f;
570 			return;
571 		}
572 	}
573 	if(f->op == OREGPAIR) {
574 		gmove(f->left, t);
575 		return;
576 	}
577 	ot = f->type;
578 	f->type = types[TLONG];
579 	gmove(f, t);
580 	f->type = ot;
581 }
582 
583 void
gloadlo(Node * f,Node * t,int c)584 gloadlo(Node *f, Node *t, int c)
585 {
586 	Type *ot;
587 
588 	if(f->op == OCONST){
589 		f = nodconst((long)f->vconst);
590 		if(c && uconst(f)){
591 			if(t->op == OREGISTER)
592 				regfree(t);
593 			*t = *f;
594 			return;
595 		}
596 	}
597 	if(f->op == OREGPAIR) {
598 		gmove(f->right, t);
599 		return;
600 	}
601 	ot = f->type;
602 	f->type = types[TLONG];
603 	f->xoffset += SZ_LONG;
604 	if(0){
605 		prtree(f, "gloadlo f"); prtree(t, "gloadlo t");
606 	}
607 	gmove(f, t);
608 	f->xoffset -= SZ_LONG;
609 	f->type = ot;
610 }
611 
612 void
fop(int as,int f1,int f2,Node * t)613 fop(int as, int f1, int f2, Node *t)
614 {
615 	Node nod1, nod2, nod3;
616 
617 	nodreg(&nod1, t, NREG+f1);
618 	nodreg(&nod2, t, NREG+f2);
619 	regalloc(&nod3, t, t);
620 	gopcode(as, &nod1, &nod2, &nod3);
621 	gmove(&nod3, t);
622 	regfree(&nod3);
623 }
624 
625 void
gmove(Node * f,Node * t)626 gmove(Node *f, Node *t)
627 {
628 	int ft, tt, a;
629 	Node nod, fxc0, fxc1, fxc2, fxrat;
630 	Prog *p1;
631 	double d;
632 
633 	ft = f->type->etype;
634 	tt = t->type->etype;
635 
636 	if(ft == TDOUBLE && f->op == OCONST) {
637 		d = f->fconst;
638 		if(d == 0.0) {
639 			a = FREGZERO;
640 			goto ffreg;
641 		}
642 		if(d == 0.5) {
643 			a = FREGHALF;
644 			goto ffreg;
645 		}
646 		if(d == 1.0) {
647 			a = FREGONE;
648 			goto ffreg;
649 		}
650 		if(d == 2.0) {
651 			a = FREGTWO;
652 			goto ffreg;
653 		}
654 		if(d == -.5) {
655 			fop(OSUB, FREGHALF, FREGZERO, t);
656 			return;
657 		}
658 		if(d == -1.0) {
659 			fop(OSUB, FREGONE, FREGZERO, t);
660 			return;
661 		}
662 		if(d == -2.0) {
663 			fop(OSUB, FREGTWO, FREGZERO, t);
664 			return;
665 		}
666 		if(d == 1.5) {
667 			fop(OADD, FREGONE, FREGHALF, t);
668 			return;
669 		}
670 		if(d == 2.5) {
671 			fop(OADD, FREGTWO, FREGHALF, t);
672 			return;
673 		}
674 		if(d == 3.0) {
675 			fop(OADD, FREGTWO, FREGONE, t);
676 			return;
677 		}
678 	}
679 	if(ft == TFLOAT && f->op == OCONST) {
680 		d = f->fconst;
681 		if(d == 0) {
682 			a = FREGZERO;
683 		ffreg:
684 			nodreg(&nod, f, NREG+a);
685 			gmove(&nod, t);
686 			return;
687 		}
688 	}
689 	if((ft == TVLONG || ft == TUVLONG) && f->op == OCONST && t->op == OREGPAIR) {
690 		if(align(0, types[TCHAR], Aarg1))	/* isbigendian */
691 			gmove(nod32const(f->vconst>>32), t->left);
692 		else
693 			gmove(nod32const(f->vconst), t->left);
694 		if(align(0, types[TCHAR], Aarg1))	/* isbigendian */
695 			gmove(nod32const(f->vconst), t->right);
696 		else
697 			gmove(nod32const(f->vconst>>32), t->right);
698 		return;
699 	}
700 	/*
701 	 * a load --
702 	 * put it into a register then
703 	 * worry what to do with it.
704 	 */
705 	if(f->op == ONAME || f->op == OINDREG || f->op == OIND) {
706 		switch(ft) {
707 		default:
708 			a = AMOVW;
709 			break;
710 		case TFLOAT:
711 			a = AFMOVS;
712 			break;
713 		case TDOUBLE:
714 			a = AFMOVD;
715 			break;
716 		case TCHAR:
717 			a = AMOVB;
718 			break;
719 		case TUCHAR:
720 			a = AMOVBZ;
721 			break;
722 		case TSHORT:
723 			a = AMOVH;
724 			break;
725 		case TUSHORT:
726 			a = AMOVHZ;
727 			break;
728 		}
729 		if(typev[ft]) {
730 			if(typev[tt]) {
731 				regalloc(&nod, f, t);
732 				/* low order first, because its value will be used first */
733 				f->xoffset += SZ_LONG;
734 				gins(AMOVW, f, nod.right);
735 				f->xoffset -= SZ_LONG;
736 				gins(AMOVW, f, nod.left);
737 			} else {
738 				/* assumed not float or double */
739 				regalloc(&nod, &regnode, t);
740 				f->xoffset += SZ_LONG;
741 				gins(AMOVW, f, &nod);
742 				f->xoffset -= SZ_LONG;
743 			}
744 		} else {
745 			regalloc(&nod, f, t);
746 			gins(a, f, &nod);
747 		}
748 		gmove(&nod, t);
749 		regfree(&nod);
750 		return;
751 	}
752 
753 	/*
754 	 * a store --
755 	 * put it into a register then
756 	 * store it.
757 	 */
758 	if(t->op == ONAME || t->op == OINDREG || t->op == OIND) {
759 		switch(tt) {
760 		default:
761 			a = AMOVW;
762 			break;
763 		case TUCHAR:
764 			a = AMOVBZ;
765 			break;
766 		case TCHAR:
767 			a = AMOVB;
768 			break;
769 		case TUSHORT:
770 			a = AMOVHZ;
771 			break;
772 		case TSHORT:
773 			a = AMOVH;
774 			break;
775 		case TFLOAT:
776 			a = AFMOVS;
777 			break;
778 		case TDOUBLE:
779 			a = AFMOVD;
780 			break;
781 		}
782 		if(R0ISZERO && !typefd[ft] && vconst(f) == 0) {
783 			gins(a, f, t);
784 			if(typev[tt]) {
785 				t->xoffset += SZ_LONG;
786 				gins(a, f, t);
787 				t->xoffset -= SZ_LONG;
788 			}
789 			return;
790 		}
791 		if(ft == tt)
792 			regalloc(&nod, t, f);
793 		else
794 			regalloc(&nod, t, Z);
795 		gmove(f, &nod);
796 		if(typev[tt]) {
797 			t->xoffset += SZ_LONG;
798 			gins(a, nod.right, t);
799 			t->xoffset -= SZ_LONG;
800 			gins(a, nod.left, t);
801 		} else
802 			gins(a, &nod, t);
803 		regfree(&nod);
804 		return;
805 	}
806 
807 	/*
808 	 * type x type cross table
809 	 */
810 	a = AGOK;
811 	switch(ft) {
812 	case TDOUBLE:
813 	case TFLOAT:
814 		switch(tt) {
815 		case TDOUBLE:
816 			a = AFMOVD;
817 			if(ft == TFLOAT)
818 				a = AFMOVS;	/* AFMOVSD */
819 			break;
820 		case TFLOAT:
821 			a = AFRSP;
822 			if(ft == TFLOAT)
823 				a = AFMOVS;
824 			break;
825 		case TINT:
826 		case TUINT:
827 		case TLONG:
828 		case TULONG:
829 		case TIND:
830 		case TSHORT:
831 		case TUSHORT:
832 		case TCHAR:
833 		case TUCHAR:
834 			/* BUG: not right for unsigned long */
835 			regalloc(&nod, f, Z);	/* should be type float */
836 			regsalloc(&fxrat, &fconstnode);
837 			gins(AFCTIWZ, f, &nod);
838 			gins(AFMOVD, &nod, &fxrat);
839 			regfree(&nod);
840 			fxrat.type = nodrat->type;
841 			fxrat.etype = nodrat->etype;
842 			fxrat.xoffset += 4;
843 			gins(AMOVW, &fxrat, t);
844 			gmove(t, t);
845 			return;
846 		}
847 		break;
848 	case TINT:
849 	case TUINT:
850 	case TLONG:
851 	case TULONG:
852 	case TIND:
853 		switch(tt) {
854 		case TDOUBLE:
855 		case TFLOAT:
856 			goto fxtofl;
857 		case TINT:
858 		case TUINT:
859 		case TLONG:
860 		case TULONG:
861 		case TIND:
862 		case TSHORT:
863 		case TUSHORT:
864 		case TCHAR:
865 		case TUCHAR:
866 			a = AMOVW;
867 			break;
868 		}
869 		break;
870 	case TSHORT:
871 		switch(tt) {
872 		case TDOUBLE:
873 		case TFLOAT:
874 			goto fxtofl;
875 		case TINT:
876 		case TUINT:
877 		case TLONG:
878 		case TULONG:
879 		case TIND:
880 			a = AMOVH;
881 			break;
882 		case TSHORT:
883 		case TUSHORT:
884 		case TCHAR:
885 		case TUCHAR:
886 			a = AMOVW;
887 			break;
888 		}
889 		break;
890 	case TUSHORT:
891 		switch(tt) {
892 		case TDOUBLE:
893 		case TFLOAT:
894 			goto fxtofl;
895 		case TINT:
896 		case TUINT:
897 		case TLONG:
898 		case TULONG:
899 		case TIND:
900 			a = AMOVHZ;
901 			break;
902 		case TSHORT:
903 		case TUSHORT:
904 		case TCHAR:
905 		case TUCHAR:
906 			a = AMOVW;
907 			break;
908 		}
909 		break;
910 	case TCHAR:
911 		switch(tt) {
912 		case TDOUBLE:
913 		case TFLOAT:
914 			goto fxtofl;
915 		case TINT:
916 		case TUINT:
917 		case TLONG:
918 		case TULONG:
919 		case TIND:
920 		case TSHORT:
921 		case TUSHORT:
922 			a = AMOVB;
923 			break;
924 		case TCHAR:
925 		case TUCHAR:
926 			a = AMOVW;
927 			break;
928 		}
929 		break;
930 	case TUCHAR:
931 		switch(tt) {
932 		case TDOUBLE:
933 		case TFLOAT:
934 		fxtofl:
935 			/*
936 			 * rat[0] = 0x43300000; rat[1] = f^0x80000000;
937 			 * t = *(double*)rat - FREGCVI;
938 			 * is-unsigned(t) => if(t<0) t += 2^32;
939 			 * could be streamlined for int-to-float
940 			 */
941 			regalloc(&fxc0, f, Z);
942 			regalloc(&fxc2, f, Z);
943 			regsalloc(&fxrat, &fconstnode);	/* should be type float */
944 			gins(AMOVW, nodconst(0x43300000L), &fxc0);
945 			gins(AMOVW, f, &fxc2);
946 			gins(AMOVW, &fxc0, &fxrat);
947 			gins(AXOR, nodconst(0x80000000L), &fxc2);
948 			fxc1 = fxrat;
949 			fxc1.type = nodrat->type;
950 			fxc1.etype = nodrat->etype;
951 			fxc1.xoffset += SZ_LONG;
952 			gins(AMOVW, &fxc2, &fxc1);
953 			regfree(&fxc2);
954 			regfree(&fxc0);
955 			regalloc(&nod, t, t);	/* should be type float */
956 			gins(AFMOVD, &fxrat, &nod);
957 			nodreg(&fxc1, t, NREG+FREGCVI);
958 			gins(AFSUB, &fxc1, &nod);
959 			a = AFMOVD;
960 			if(tt == TFLOAT)
961 				a = AFRSP;
962 			gins(a, &nod, t);
963 			regfree(&nod);
964 			if(ft == TULONG) {
965 				regalloc(&nod, t, Z);
966 				if(tt == TFLOAT) {
967 					gins(AFCMPU, t, Z);
968 					p->to.type = D_FREG;
969 					p->to.reg = FREGZERO;
970 					gins(ABGE, Z, Z);
971 					p1 = p;
972 					gins(AFMOVS, nodfconst(4294967296.), &nod);
973 					gins(AFADDS, &nod, t);
974 				} else {
975 					gins(AFCMPU, t, Z);
976 					p->to.type = D_FREG;
977 					p->to.reg = FREGZERO;
978 					gins(ABGE, Z, Z);
979 					p1 = p;
980 					gins(AFMOVD, nodfconst(4294967296.), &nod);
981 					gins(AFADD, &nod, t);
982 				}
983 				patch(p1, pc);
984 				regfree(&nod);
985 			}
986 			return;
987 		case TINT:
988 		case TUINT:
989 		case TLONG:
990 		case TULONG:
991 		case TIND:
992 		case TSHORT:
993 		case TUSHORT:
994 			a = AMOVBZ;
995 			break;
996 		case TCHAR:
997 		case TUCHAR:
998 			a = AMOVW;
999 			break;
1000 		}
1001 		break;
1002 	case TVLONG:
1003 	case TUVLONG:
1004 		switch(tt) {
1005 		case TVLONG:
1006 		case TUVLONG:
1007 			a = AMOVW;
1008 			break;
1009 		}
1010 		break;
1011 	}
1012 	if(a == AGOK)
1013 		diag(Z, "bad opcode in gmove %T -> %T", f->type, t->type);
1014 	if(a == AMOVW || a == AFMOVS || a == AFMOVD)
1015 	if(samaddr(f, t))
1016 		return;
1017 	if(typev[ft]) {
1018 		if(f->op != OREGPAIR || t->op != OREGPAIR)
1019 			diag(Z, "bad vlong in gmove (%O->%O)", f->op, t->op);
1020 		gins(a, f->left, t->left);
1021 		gins(a, f->right, t->right);
1022 	} else
1023 		gins(a, f, t);
1024 }
1025 
1026 void
gins(int a,Node * f,Node * t)1027 gins(int a, Node *f, Node *t)
1028 {
1029 
1030 	nextpc();
1031 	p->as = a;
1032 	if(f != Z)
1033 		naddr(f, &p->from);
1034 	if(t != Z)
1035 		naddr(t, &p->to);
1036 	if(debug['g'])
1037 		print("%P\n", p);
1038 }
1039 
1040 void
gins3(int a,Node * f1,Node * f2,Node * t)1041 gins3(int a, Node *f1, Node *f2, Node *t)
1042 {
1043 	Adr ta;
1044 
1045 	nextpc();
1046 	p->as = a;
1047 	if(f1 != Z)
1048 		naddr(f1, &p->from);
1049 	if(f2 != Z && (f2->op != OREGISTER || !samaddr(f2, t))) {
1050 		ta = zprog.from;	/* TO DO */
1051 		naddr(f2, &ta);
1052 		p->reg = ta.reg;
1053 		if(ta.type == D_CONST && ta.offset == 0) {
1054 			if(R0ISZERO)
1055 				p->reg = REGZERO;
1056 			else
1057 				diag(Z, "REGZERO in gins3 %A", a);
1058 		}else if(ta.type == D_CONST)
1059 			p->from3 = ta;
1060 	}
1061 	if(t != Z)
1062 		naddr(t, &p->to);
1063 	if(debug['g'])
1064 		print("%P\n", p);
1065 }
1066 
1067 void
gins4(int a,Node * f1,Node * f2,Node * f3,Node * t)1068 gins4(int a, Node *f1, Node *f2, Node *f3, Node *t)
1069 {
1070 	Adr ta;
1071 
1072 	nextpc();
1073 	p->as = a;
1074 	naddr(f1, &p->from);
1075 	if(f2->op != OREGISTER && (f2->op != OCONST || vconst(f2) != 0))
1076 		diag(f2, "invalid gins4");
1077 	naddr(f2, &ta);
1078 	p->reg = ta.reg;
1079 	if(ta.type == D_CONST && ta.offset == 0)
1080 		p->reg = REGZERO;
1081 	naddr(f3, &p->from3);
1082 	naddr(t, &p->to);
1083 	if(debug['g'])
1084 		print("%P\n", p);
1085 }
1086 
1087 void
gopcode(int o,Node * f1,Node * f2,Node * t)1088 gopcode(int o, Node *f1, Node *f2, Node *t)
1089 {
1090 	int a, et, uns;
1091 
1092 	if(o == OAS) {
1093 		gmove(f1, t);
1094 		return;
1095 	}
1096 	et = TLONG;
1097 	if(f1 != Z && f1->type != T) {
1098 		if(f1->op == OCONST && t != Z && t->type != T)
1099 			et = t->type->etype;
1100 		else
1101 			et = f1->type->etype;
1102 	}
1103 	if((typev[et] || t->type != T && typev[t->type->etype]) && o != OFUNC) {
1104 		gopcode64(o, f1, f2, t);
1105 		return;
1106 	}
1107 	uns = 0;
1108 	a = AGOK;
1109 	switch(o) {
1110 
1111 	case OASADD:
1112 	case OADD:
1113 		a = AADD;
1114 		if(et == TFLOAT)
1115 			a = AFADDS;
1116 		else
1117 		if(et == TDOUBLE)
1118 			a = AFADD;
1119 		break;
1120 
1121 	case OASSUB:
1122 	case OSUB:
1123 		a = ASUB;
1124 		if(et == TFLOAT)
1125 			a = AFSUBS;
1126 		else
1127 		if(et == TDOUBLE)
1128 			a = AFSUB;
1129 		break;
1130 
1131 	case OASOR:
1132 	case OOR:
1133 		a = AOR;
1134 		break;
1135 
1136 	case OASAND:
1137 	case OAND:
1138 		a = AAND;
1139 		if(f1->op == OCONST)
1140 			a = AANDCC;
1141 		break;
1142 
1143 	case OASXOR:
1144 	case OXOR:
1145 		a = AXOR;
1146 		break;
1147 
1148 	case OASLSHR:
1149 	case OLSHR:
1150 		a = ASRW;
1151 		break;
1152 
1153 	case OASASHR:
1154 	case OASHR:
1155 		a = ASRAW;
1156 		break;
1157 
1158 	case OASASHL:
1159 	case OASHL:
1160 		a = ASLW;
1161 		break;
1162 
1163 	case OFUNC:
1164 		a = ABL;
1165 		break;
1166 
1167 	case OASLMUL:
1168 	case OLMUL:
1169 	case OASMUL:
1170 	case OMUL:
1171 		if(et == TFLOAT) {
1172 			a = AFMULS;
1173 			break;
1174 		} else
1175 		if(et == TDOUBLE) {
1176 			a = AFMUL;
1177 			break;
1178 		}
1179 		a = AMULLW;
1180 		break;
1181 
1182 	case OASDIV:
1183 	case ODIV:
1184 		if(et == TFLOAT) {
1185 			a = AFDIVS;
1186 			break;
1187 		} else
1188 		if(et == TDOUBLE) {
1189 			a = AFDIV;
1190 			break;
1191 		}
1192 		a = ADIVW;
1193 		break;
1194 
1195 	case OASMOD:
1196 	case OMOD:
1197 		a = AREM;
1198 		break;
1199 
1200 	case OASLMOD:
1201 	case OLMOD:
1202 		a = AREMU;
1203 		break;
1204 
1205 	case OASLDIV:
1206 	case OLDIV:
1207 		a = ADIVWU;
1208 		break;
1209 
1210 	case OCOM:
1211 		a = ANOR;
1212 		break;
1213 
1214 	case ONEG:
1215 		a = ANEG;
1216 		if(et == TFLOAT || et == TDOUBLE)
1217 			a = AFNEG;
1218 		break;
1219 
1220 	case OEQ:
1221 		a = ABEQ;
1222 		if(t->op == OCONST && t->vconst >= (1<<15))
1223 			goto cmpu;
1224 		goto cmp;
1225 
1226 	case ONE:
1227 		a = ABNE;
1228 		if(t->op == OCONST && t->vconst >= (1<<15))
1229 			goto cmpu;
1230 		goto cmp;
1231 
1232 	case OLT:
1233 		a = ABLT;
1234 		goto cmp;
1235 
1236 	case OLE:
1237 		a = ABLE;
1238 		goto cmp;
1239 
1240 	case OGE:
1241 		a = ABGE;
1242 		goto cmp;
1243 
1244 	case OGT:
1245 		a = ABGT;
1246 		goto cmp;
1247 
1248 	case OLO:
1249 		a = ABLT;
1250 		goto cmpu;
1251 
1252 	case OLS:
1253 		a = ABLE;
1254 		goto cmpu;
1255 
1256 	case OHS:
1257 		a = ABGE;
1258 		goto cmpu;
1259 
1260 	case OHI:
1261 		a = ABGT;
1262 		goto cmpu;
1263 
1264 	cmpu:
1265 		uns = 1;
1266 	cmp:
1267 		nextpc();
1268 		p->as = uns? ACMPU: ACMP;
1269 		if(et == TFLOAT)
1270 			p->as = AFCMPU;
1271 		else
1272 		if(et == TDOUBLE)
1273 			p->as = AFCMPU;
1274 		if(f1 != Z)
1275 			naddr(f1, &p->from);
1276 		if(t != Z)
1277 			naddr(t, &p->to);
1278 		if(f1 == Z || t == Z || f2 != Z)
1279 			diag(Z, "bad cmp in gopcode %O", o);
1280 		if(debug['g'])
1281 			print("%P\n", p);
1282 		f1 = Z;
1283 		f2 = Z;
1284 		t = Z;
1285 		break;
1286 	}
1287 	if(a == AGOK)
1288 		diag(Z, "bad in gopcode %O", o);
1289 	gins3(a, f1, f2, t);
1290 }
1291 
1292 static void
gopcode64(int o,Node * f1,Node * f2,Node * t)1293 gopcode64(int o, Node *f1, Node *f2, Node *t)
1294 {
1295 	int a1, a2;
1296 	Node nod, nod1, nod2, sh;
1297 	ulong m;
1298 	Prog *p1;
1299 
1300 	if(t->op != OREGPAIR || f2 != Z && f2->op != OREGPAIR) {
1301 		diag(Z, "bad f2/dest in gopcode64 %O", o);
1302 		return;
1303 	}
1304 	if(f1->op != OCONST &&
1305 	   (typev[f1->type->etype] && f1->op != OREGPAIR || !typev[f1->type->etype] && f1->op != OREGISTER)) {
1306 		diag(Z, "bad f1[%O] in gopcode64 %O", f1->op, o);
1307 		return;
1308 	}
1309 	/* a1 for low-order, a2 for high-order */
1310 	a1 = AGOK;
1311 	a2 = AGOK;
1312 	switch(o) {
1313 	case OASADD:
1314 	case OADD:
1315 		if(f1->op == OCONST && sconst(f1)) {
1316 			if(f2 == Z)
1317 				f2 = t;
1318 			gins3(AADDC, f1, f2->right, t->right);
1319 			if((f1->vconst>>32) == 0)
1320 				gins(AADDZE, f2->left, t->left);
1321 			else if((f1->vconst>>32) == -1)
1322 				gins(AADDME, f2->left, t->left);
1323 			else
1324 				diag(t, "odd vlong ADD: %lld", f1->vconst);
1325 			return;
1326 		}
1327 		a1 = AADDC;
1328 		a2 = AADDE;
1329 		break;
1330 
1331 	case OASSUB:
1332 	case OSUB:
1333 		a1 = ASUBC;
1334 		a2 = ASUBE;
1335 		break;
1336 
1337 	case OASOR:
1338 	case OOR:
1339 		if(f1->op == OCONST) {
1340 			gori64(AOR, f1, f2, t);
1341 			return;
1342 		}
1343 		a1 = a2 = AOR;
1344 		break;
1345 
1346 	case OASAND:
1347 	case OAND:
1348 		if(f1->op == OCONST) {
1349 			gandi64(AANDCC, f1, f2, t);
1350 			return;
1351 		}
1352 		a1 = a2 = AAND;
1353 		break;
1354 
1355 	case OASXOR:
1356 	case OXOR:
1357 		if(f1->op == OCONST) {
1358 			gori64(AXOR, f1, f2, t);
1359 			return;
1360 		}
1361 		a1 = a2 = AXOR;
1362 		break;
1363 
1364 	case OASLSHR:
1365 	case OLSHR:
1366 		if(f2 == Z)
1367 			f2 = t;
1368 		if(f1->op == OCONST) {
1369 			if(f1->vconst >= 32) {
1370 				if(f1->vconst == 32)
1371 					gmove(f2->left, t->right);
1372 				else if(f1->vconst < 64)
1373 					gins3(ASRW, nodconst(f1->vconst-32), f2->left, t->right);
1374 				else
1375 					gmove(nodconst(0), t->right);
1376 				gmove(nodconst(0), t->left);
1377 				return;
1378 			}
1379 			if(f1->vconst <= 0) {
1380 				if(f2 != t)
1381 					gmove(f2, t);
1382 				return;
1383 			}
1384 			sh = *nodconst(32 - f1->vconst);
1385 			m = 0xFFFFFFFFUL >> f1->vconst;
1386 			gins4(ARLWNM, &sh, f2->right, nodconst(m), t->right);
1387 			gins4(ARLWMI, &sh, f2->left, nodconst(~m), t->right);
1388 			gins4(ARLWNM, &sh, f2->left, nodconst(m), t->left);
1389 			return;
1390 		}
1391 		regalloc(&nod, &regnode, Z);
1392 		gins3(ASUBC, f1, nodconst(32), &nod);
1393 		gins3(ASRW, f1, f2->right, t->right);
1394 		regalloc(&nod1, &regnode, Z);
1395 		gins3(ASLW, &nod, f2->left, &nod1);
1396 		gins(AOR, &nod1, t->right);
1397 		gins3(AADD, nodconst(-32), f1, &nod);
1398 		gins3(ASRW, &nod, f2->left, &nod1);
1399 		gins(AOR, &nod1, t->right);
1400 		gins3(ASRW, f1, f2->left, t->left);
1401 		regfree(&nod);
1402 		regfree(&nod1);
1403 		return;
1404 
1405 	case OASASHR:
1406 	case OASHR:
1407 		if(f2 == Z)
1408 			f2 = t;
1409 		if(f1->op == OCONST) {
1410 			if(f1->vconst >= 32) {
1411 				if(f1->vconst == 32)
1412 					gmove(f2->left, t->right);
1413 				else if(f1->vconst < 64)
1414 					gins3(ASRAW, nodconst(f1->vconst-32), f2->left, t->right);
1415 				gins3(ASRAW, nodconst(31), f2->left, t->left);
1416 				if(f1->vconst >= 64) {
1417 					gmove(t->left, t->right);
1418 					return;
1419 				}
1420 				return;
1421 			}
1422 			if(f1->vconst <= 0) {
1423 				if(f2 != t)
1424 					gmove(f2, t);
1425 				return;
1426 			}
1427 			sh = *nodconst(32 - f1->vconst);
1428 			m = 0xFFFFFFFFUL >> f1->vconst;
1429 			gins4(ARLWNM, &sh, f2->right, nodconst(m), t->right);
1430 			gins4(ARLWMI, &sh, f2->left, nodconst(~m), t->right);
1431 			gins3(ASRAW, &sh, f2->left, t->left);
1432 			return;
1433 		}
1434 		regalloc(&nod, &regnode, Z);
1435 		gins3(ASUBC, f1, nodconst(32), &nod);
1436 		gins3(ASRW, f1, f2->right, t->right);
1437 		regalloc(&nod1, &regnode, Z);
1438 		gins3(ASLW, &nod, f2->left, &nod1);
1439 		gins(AOR, &nod1, t->right);
1440 		gins3(AADDCCC, nodconst(-32), f1, &nod);
1441 		gins3(ASRAW, &nod, f2->left, &nod1);
1442 		gins(ABLE, Z, Z);
1443 		p1 = p;
1444 		gins(AMOVW, &nod1, t->right);
1445 		patch(p1, pc);
1446 		gins3(ASRAW, f1, f2->left, t->left);
1447 		regfree(&nod);
1448 		regfree(&nod1);
1449 		return;
1450 
1451 	case OASASHL:
1452 	case OASHL:
1453 		if(f2 == Z)
1454 			f2 = t;
1455 		if(f1->op == OCONST) {
1456 			if(f1->vconst >= 32) {
1457 				if(f1->vconst == 32)
1458 					gmove(f2->right, t->left);
1459 				else if(f1->vconst >= 64)
1460 					gmove(nodconst(0), t->left);
1461 				else
1462 					gins3(ASLW, nodconst(f1->vconst-32), f2->right, t->left);
1463 				gmove(nodconst(0), t->right);
1464 				return;
1465 			}
1466 			if(f1->vconst <= 0) {
1467 				if(f2 != t)
1468 					gmove(f2, t);
1469 				return;
1470 			}
1471 			m = 0xFFFFFFFFUL << f1->vconst;
1472 			gins4(ARLWNM, f1, f2->left, nodconst(m), t->left);
1473 			gins4(ARLWMI, f1, f2->right, nodconst(~m), t->left);
1474 			gins4(ARLWNM, f1, f2->right, nodconst(m), t->right);
1475 			return;
1476 		}
1477 		regalloc(&nod, &regnode, Z);
1478 		gins3(ASUBC, f1, nodconst(32), &nod);
1479 		gins3(ASLW, f1, f2->left, t->left);
1480 		regalloc(&nod1, &regnode, Z);
1481 		gins3(ASRW, &nod, f2->right, &nod1);
1482 		gins(AOR, &nod1, t->left);
1483 		gins3(AADD, nodconst(-32), f1, &nod);
1484 		gins3(ASLW, &nod, f2->right, &nod1);
1485 		gins(AOR, &nod1, t->left);
1486 		gins3(ASLW, f1, f2->right, t->right);
1487 		regfree(&nod);
1488 		regfree(&nod1);
1489 		return;
1490 
1491 	case OASLMUL:
1492 	case OLMUL:
1493 	case OASMUL:
1494 	case OMUL:
1495 		if(f2 == Z)
1496 			f2 = t;
1497 		regalloc(&nod, &regnode, Z);
1498 		gins3(AMULLW, f1->right, f2->right, &nod);	/* lo(f2.low*f1.low) */
1499 		regalloc(&nod1, &regnode, Z);
1500 		gins3(AMULHWU, f1->right, f2->right, &nod1);		/* hi(f2.low*f1.low) */
1501 		regalloc(&nod2, &regnode, Z);
1502 		gins3(AMULLW, f2->right, f1->left, &nod2);	/* lo(f2.low*f1.high) */
1503 		gins(AADD, &nod2, &nod1);
1504 		gins3(AMULLW, f1->right, f2->left, &nod2);	/* lo(f2.high*f1.low) */
1505 		gins(AADD, &nod2, &nod1);
1506 		regfree(&nod2);
1507 		gmove(&nod, t->right);
1508 		gmove(&nod1, t->left);
1509 		regfree(&nod);
1510 		regfree(&nod1);
1511 		return;
1512 
1513 	case OCOM:
1514 		a1 = a2 = ANOR;
1515 		break;
1516 
1517 	case ONEG:
1518 		gins3(ASUBC, t->right, nodconst(0), t->right);
1519 		gins(ASUBZE, t->left, t->left);
1520 		return;
1521 	}
1522 	if(a1 == AGOK || a2 == AGOK)
1523 		diag(Z, "bad in gopcode64 %O", o);
1524 	if(f1->op == OCONST) {
1525 		if(f2 != Z & f2 != t)
1526 			diag(Z, "bad const in gopcode64 %O", o);
1527 		gins(a1, nod32const(f1->vconst), t->right);
1528 		gins(a2, nod32const(f1->vconst>>32), t->left);
1529 	} else {
1530 		if(f2 != Z && f2 != t) {
1531 			gins3(a1, f1->right, f2->right, t->right);
1532 			gins3(a2, f1->left, f2->left, t->left);
1533 		} else {
1534 			gins(a1, f1->right, t->right);
1535 			gins(a2, f1->left, t->left);
1536 		}
1537 	}
1538 }
1539 
samaddr(Node * f,Node * t)1540 samaddr(Node *f, Node *t)
1541 {
1542 
1543 	if(f->op != t->op)
1544 		return 0;
1545 	switch(f->op) {
1546 
1547 	case OREGISTER:
1548 		if(f->reg != t->reg)
1549 			break;
1550 		return 1;
1551 
1552 	case OREGPAIR:
1553 		return samaddr(f->left, t->left) && samaddr(f->right, t->right);
1554 	}
1555 	return 0;
1556 }
1557 
1558 static void
gori64(int a,Node * f1,Node * f2,Node * t)1559 gori64(int a, Node *f1, Node *f2, Node *t)
1560 {
1561 	ulong lo, hi;
1562 
1563 	if(f2 == Z)
1564 		f2 = t;
1565 	lo = f1->vconst & MASK(32);
1566 	hi = (f1->vconst >> 32) & MASK(32);
1567 	if(lo & 0xFFFF)
1568 		gins3(a, nodconst(lo & 0xFFFF), f2->right, t->right);
1569 	if((lo >> 16) != 0)
1570 		gins3(a, nodconst(lo & 0xFFFF0000UL), f2->right, t->right);
1571 	if(hi & 0xFFFF)
1572 		gins3(a, nodconst(hi & 0xFFFF), f2->left, t->left);
1573 	if((hi >> 16) != 0)
1574 		gins3(a, nodconst(hi & 0xFFFF0000UL), f2->left, t->left);
1575 }
1576 
1577 static void
gandi64(int a,Node * f1,Node * f2,Node * t)1578 gandi64(int a, Node *f1, Node *f2, Node *t)
1579 {
1580 	ulong lo, hi;
1581 
1582 	if(f2 == Z)
1583 		f2 = t;
1584 	lo = f1->vconst & MASK(32);
1585 	hi = (f1->vconst >> 32) & MASK(32);
1586 	if(lo == 0)
1587 		gins(AMOVW, nodconst(0), t->right);
1588 	else
1589 		gins3(a, nodconst(lo), f2->right, t->right);
1590 	if(hi == 0)
1591 		gins(AMOVW, nodconst(0), t->left);
1592 	else
1593 		gins3(a, nodconst(hi), f2->left, t->left);
1594 }
1595 
1596 void
gbranch(int o)1597 gbranch(int o)
1598 {
1599 	int a;
1600 
1601 	a = AGOK;
1602 	switch(o) {
1603 	case ORETURN:
1604 		a = ARETURN;
1605 		break;
1606 	case OGOTO:
1607 		a = ABR;
1608 		break;
1609 	}
1610 	nextpc();
1611 	if(a == AGOK) {
1612 		diag(Z, "bad in gbranch %O",  o);
1613 		nextpc();
1614 	}
1615 	p->as = a;
1616 }
1617 
1618 void
patch(Prog * op,long pc)1619 patch(Prog *op, long pc)
1620 {
1621 
1622 	op->to.offset = pc;
1623 	op->to.type = D_BRANCH;
1624 }
1625 
1626 void
gpseudo(int a,Sym * s,Node * n)1627 gpseudo(int a, Sym *s, Node *n)
1628 {
1629 
1630 	nextpc();
1631 	p->as = a;
1632 	p->from.type = D_OREG;
1633 	p->from.sym = s;
1634 	if(a == ATEXT)
1635 		p->reg = (profileflg ? 0 : NOPROF);
1636 	p->from.name = D_EXTERN;
1637 	if(s->class == CSTATIC)
1638 		p->from.name = D_STATIC;
1639 	naddr(n, &p->to);
1640 	if(a == ADATA || a == AGLOBL)
1641 		pc--;
1642 }
1643 
1644 int
sval(long v)1645 sval(long v)
1646 {
1647 
1648 	if(v >= -(1<<15) && v < (1<<15))
1649 		return 1;
1650 	return 0;
1651 }
1652 
1653 int
sconst(Node * n)1654 sconst(Node *n)
1655 {
1656 	vlong vv;
1657 
1658 	if(n->op == OCONST) {
1659 		if(!typefd[n->type->etype]) {
1660 			vv = n->vconst;
1661 			if(vv >= -(((vlong)1)<<15) && vv < (((vlong)1)<<15))
1662 				return 1;
1663 		}
1664 	}
1665 	return 0;
1666 }
1667 
1668 int
uconst(Node * n)1669 uconst(Node *n)
1670 {
1671 	vlong vv;
1672 
1673 	if(n->op == OCONST) {
1674 		if(!typefd[n->type->etype]) {
1675 			vv = n->vconst;
1676 			if(vv >= 0 && vv < (((vlong)1)<<16))
1677 				return 1;
1678 		}
1679 	}
1680 	return 0;
1681 }
1682 
1683 long
exreg(Type * t)1684 exreg(Type *t)
1685 {
1686 	long o;
1687 
1688 	if(typechlp[t->etype]) {
1689 		if(exregoffset <= 3)
1690 			return 0;
1691 		o = exregoffset;
1692 		exregoffset--;
1693 		return o;
1694 	}
1695 	if(typefd[t->etype]) {
1696 		if(exfregoffset <= 16)
1697 			return 0;
1698 		o = exfregoffset + NREG;
1699 		exfregoffset--;
1700 		return o;
1701 	}
1702 	return 0;
1703 }
1704 
1705 schar	ewidth[NTYPE] =
1706 {
1707 	-1,		/* [TXXX] */
1708 	SZ_CHAR,	/* [TCHAR] */
1709 	SZ_CHAR,	/* [TUCHAR] */
1710 	SZ_SHORT,	/* [TSHORT] */
1711 	SZ_SHORT,	/* [TUSHORT] */
1712 	SZ_INT,		/* [TINT] */
1713 	SZ_INT,		/* [TUINT] */
1714 	SZ_LONG,	/* [TLONG] */
1715 	SZ_LONG,	/* [TULONG] */
1716 	SZ_VLONG,	/* [TVLONG] */
1717 	SZ_VLONG,	/* [TUVLONG] */
1718 	SZ_FLOAT,	/* [TFLOAT] */
1719 	SZ_DOUBLE,	/* [TDOUBLE] */
1720 	SZ_IND,		/* [TIND] */
1721 	0,		/* [TFUNC] */
1722 	-1,		/* [TARRAY] */
1723 	0,		/* [TVOID] */
1724 	-1,		/* [TSTRUCT] */
1725 	-1,		/* [TUNION] */
1726 	SZ_INT,		/* [TENUM] */
1727 };
1728 long	ncast[NTYPE] =
1729 {
1730 	0,				/* [TXXX] */
1731 	BCHAR|BUCHAR,			/* [TCHAR] */
1732 	BCHAR|BUCHAR,			/* [TUCHAR] */
1733 	BSHORT|BUSHORT,			/* [TSHORT] */
1734 	BSHORT|BUSHORT,			/* [TUSHORT] */
1735 	BINT|BUINT|BLONG|BULONG|BIND,	/* [TINT] */
1736 	BINT|BUINT|BLONG|BULONG|BIND,	/* [TUINT] */
1737 	BINT|BUINT|BLONG|BULONG|BIND,	/* [TLONG] */
1738 	BINT|BUINT|BLONG|BULONG|BIND,	/* [TULONG] */
1739 	BVLONG|BUVLONG,			/* [TVLONG] */
1740 	BVLONG|BUVLONG,			/* [TUVLONG] */
1741 	BFLOAT,				/* [TFLOAT] */
1742 	BDOUBLE,			/* [TDOUBLE] */
1743 	BLONG|BULONG|BIND,		/* [TIND] */
1744 	0,				/* [TFUNC] */
1745 	0,				/* [TARRAY] */
1746 	0,				/* [TVOID] */
1747 	BSTRUCT,			/* [TSTRUCT] */
1748 	BUNION,				/* [TUNION] */
1749 	0,				/* [TENUM] */
1750 };
1751