xref: /plan9-contrib/sys/src/cmd/qc/txt.c (revision 40d015479ed36701ae6dcfd8814f849fc6285e8d)
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 static void
floattofix(Node * f,Node * t)626 floattofix(Node *f, Node *t)
627 {
628 	Node nod, fxrat;
629 
630 	regalloc(&nod, f, Z);
631 	regsalloc(&fxrat, &fconstnode);
632 	gins(AFCTIWZ, f, &nod);
633 	gins(AFMOVD, &nod, &fxrat);
634 	regfree(&nod);
635 	fxrat.type = nodrat->type;
636 	fxrat.etype = nodrat->etype;
637 	fxrat.xoffset += 4;
638 	gins(AMOVW, &fxrat, t);
639 	gmove(t, t);
640 }
641 
642 static void
fixtofloat(Node * f,Node * t)643 fixtofloat(Node *f, Node *t)
644 {
645 	int a, ft, tt;
646 	Prog *p1;
647 	Node nod, fxc0, fxc1, fxc2, fxrat;
648 
649 	ft = f->type->etype;
650 	tt = t->type->etype;
651 
652 	/*
653 	 * rat[0] = 0x43300000; rat[1] = f^0x80000000;
654 	 * t = *(double*)rat - FREGCVI;
655 	 * is-unsigned(t) => if(t<0) t += 2^32;
656 	 * could be streamlined for int-to-float
657 	 */
658 	regalloc(&fxc0, f, Z);
659 	regalloc(&fxc2, f, Z);
660 	regsalloc(&fxrat, &fconstnode);	/* should be type float */
661 	gins(AMOVW, nodconst(0x43300000L), &fxc0);
662 	gins(AMOVW, f, &fxc2);
663 	gins(AMOVW, &fxc0, &fxrat);
664 	gins(AXOR, nodconst(0x80000000L), &fxc2);
665 	fxc1 = fxrat;
666 	fxc1.type = nodrat->type;
667 	fxc1.etype = nodrat->etype;
668 	fxc1.xoffset += SZ_LONG;
669 	gins(AMOVW, &fxc2, &fxc1);
670 	regfree(&fxc2);
671 	regfree(&fxc0);
672 	regalloc(&nod, t, t);	/* should be type float */
673 	gins(AFMOVD, &fxrat, &nod);
674 	nodreg(&fxc1, t, NREG+FREGCVI);
675 	gins(AFSUB, &fxc1, &nod);
676 	a = AFMOVD;
677 	if(tt == TFLOAT)
678 		a = AFRSP;
679 	gins(a, &nod, t);
680 	regfree(&nod);
681 	if(ft == TULONG) {
682 		regalloc(&nod, t, Z);
683 		gins(AFCMPU, t, Z);
684 		p->to.type = D_FREG;
685 		p->to.reg = FREGZERO;
686 		gins(ABGE, Z, Z);
687 		p1 = p;
688 		if(tt == TFLOAT) {
689 			gins(AFMOVS, nodfconst(4294967296.), &nod);
690 			gins(AFADDS, &nod, t);
691 		} else {
692 			gins(AFMOVD, nodfconst(4294967296.), &nod);
693 			gins(AFADD, &nod, t);
694 		}
695 		patch(p1, pc);
696 		regfree(&nod);
697 	}
698 }
699 
700 void
gmove(Node * f,Node * t)701 gmove(Node *f, Node *t)
702 {
703 	int ft, tt, a;
704 	Node nod;
705 	double d;
706 
707 	ft = f->type->etype;
708 	tt = t->type->etype;
709 
710 	if(ft == TDOUBLE && f->op == OCONST) {
711 		d = f->fconst;
712 		if(d == 0.0) {
713 			a = FREGZERO;
714 			goto ffreg;
715 		}
716 		if(d == 0.5) {
717 			a = FREGHALF;
718 			goto ffreg;
719 		}
720 		if(d == 1.0) {
721 			a = FREGONE;
722 			goto ffreg;
723 		}
724 		if(d == 2.0) {
725 			a = FREGTWO;
726 			goto ffreg;
727 		}
728 		if(d == -.5) {
729 			fop(OSUB, FREGHALF, FREGZERO, t);
730 			return;
731 		}
732 		if(d == -1.0) {
733 			fop(OSUB, FREGONE, FREGZERO, t);
734 			return;
735 		}
736 		if(d == -2.0) {
737 			fop(OSUB, FREGTWO, FREGZERO, t);
738 			return;
739 		}
740 		if(d == 1.5) {
741 			fop(OADD, FREGONE, FREGHALF, t);
742 			return;
743 		}
744 		if(d == 2.5) {
745 			fop(OADD, FREGTWO, FREGHALF, t);
746 			return;
747 		}
748 		if(d == 3.0) {
749 			fop(OADD, FREGTWO, FREGONE, t);
750 			return;
751 		}
752 	}
753 	if(ft == TFLOAT && f->op == OCONST) {
754 		d = f->fconst;
755 		if(d == 0) {
756 			a = FREGZERO;
757 		ffreg:
758 			nodreg(&nod, f, NREG+a);
759 			gmove(&nod, t);
760 			return;
761 		}
762 	}
763 	if((ft == TVLONG || ft == TUVLONG) && f->op == OCONST && t->op == OREGPAIR) {
764 		if(align(0, types[TCHAR], Aarg1))	/* isbigendian */
765 			gmove(nod32const(f->vconst>>32), t->left);
766 		else
767 			gmove(nod32const(f->vconst), t->left);
768 		if(align(0, types[TCHAR], Aarg1))	/* isbigendian */
769 			gmove(nod32const(f->vconst), t->right);
770 		else
771 			gmove(nod32const(f->vconst>>32), t->right);
772 		return;
773 	}
774 	/*
775 	 * a load --
776 	 * put it into a register then
777 	 * worry what to do with it.
778 	 */
779 	if(f->op == ONAME || f->op == OINDREG || f->op == OIND) {
780 		switch(ft) {
781 		default:
782 			a = AMOVW;
783 			break;
784 		case TFLOAT:
785 			a = AFMOVS;
786 			break;
787 		case TDOUBLE:
788 			a = AFMOVD;
789 			break;
790 		case TCHAR:
791 			a = AMOVB;
792 			break;
793 		case TUCHAR:
794 			a = AMOVBZ;
795 			break;
796 		case TSHORT:
797 			a = AMOVH;
798 			break;
799 		case TUSHORT:
800 			a = AMOVHZ;
801 			break;
802 		}
803 		if(typev[ft]) {
804 			if(typev[tt] || typefd[tt]) {
805 				regalloc(&nod, f, t);
806 				/* low order first, because its value will be used first */
807 				f->xoffset += SZ_LONG;
808 				gins(AMOVW, f, nod.right);
809 				f->xoffset -= SZ_LONG;
810 				gins(AMOVW, f, nod.left);
811 			} else {
812 				/* assumed not float or double */
813 				regalloc(&nod, &regnode, t);
814 				f->xoffset += SZ_LONG;
815 				gins(AMOVW, f, &nod);
816 				f->xoffset -= SZ_LONG;
817 			}
818 		} else {
819 			regalloc(&nod, f, t);
820 			gins(a, f, &nod);
821 		}
822 		gmove(&nod, t);
823 		regfree(&nod);
824 		return;
825 	}
826 
827 	/*
828 	 * a store --
829 	 * put it into a register then
830 	 * store it.
831 	 */
832 	if(t->op == ONAME || t->op == OINDREG || t->op == OIND) {
833 		switch(tt) {
834 		default:
835 			a = AMOVW;
836 			break;
837 		case TUCHAR:
838 			a = AMOVBZ;
839 			break;
840 		case TCHAR:
841 			a = AMOVB;
842 			break;
843 		case TUSHORT:
844 			a = AMOVHZ;
845 			break;
846 		case TSHORT:
847 			a = AMOVH;
848 			break;
849 		case TFLOAT:
850 			a = AFMOVS;
851 			break;
852 		case TDOUBLE:
853 			a = AFMOVD;
854 			break;
855 		}
856 		if(R0ISZERO && !typefd[ft] && vconst(f) == 0) {
857 			gins(a, f, t);
858 			if(typev[tt]) {
859 				t->xoffset += SZ_LONG;
860 				gins(a, f, t);
861 				t->xoffset -= SZ_LONG;
862 			}
863 			return;
864 		}
865 		if(ft == tt)
866 			regalloc(&nod, t, f);
867 		else
868 			regalloc(&nod, t, Z);
869 		gmove(f, &nod);
870 		if(typev[tt]) {
871 			t->xoffset += SZ_LONG;
872 			gins(a, nod.right, t);
873 			t->xoffset -= SZ_LONG;
874 			gins(a, nod.left, t);
875 		} else
876 			gins(a, &nod, t);
877 		regfree(&nod);
878 		return;
879 	}
880 
881 	/*
882 	 * type x type cross table
883 	 */
884 	a = AGOK;
885 	switch(ft) {
886 	case TDOUBLE:
887 	case TFLOAT:
888 		switch(tt) {
889 		case TDOUBLE:
890 			a = AFMOVD;
891 			if(ft == TFLOAT)
892 				a = AFMOVS;	/* AFMOVSD */
893 			break;
894 		case TFLOAT:
895 			a = AFRSP;
896 			if(ft == TFLOAT)
897 				a = AFMOVS;
898 			break;
899 		case TINT:
900 		case TUINT:
901 		case TLONG:
902 		case TULONG:
903 		case TIND:
904 		case TSHORT:
905 		case TUSHORT:
906 		case TCHAR:
907 		case TUCHAR:
908 			/* BUG: not right for unsigned long */
909 			floattofix(f, t);
910 			return;
911 		case TVLONG:
912 		case TUVLONG:
913 			diag(f, "unimplemented double->vlong");
914 			return;
915 		}
916 		break;
917 	case TINT:
918 	case TUINT:
919 	case TLONG:
920 	case TULONG:
921 	case TIND:
922 		switch(tt) {
923 		case TDOUBLE:
924 		case TFLOAT:
925 			fixtofloat(f, t);
926 			return;
927 		case TINT:
928 		case TUINT:
929 		case TLONG:
930 		case TULONG:
931 		case TIND:
932 		case TSHORT:
933 		case TUSHORT:
934 		case TCHAR:
935 		case TUCHAR:
936 			a = AMOVW;
937 			break;
938 		}
939 		break;
940 	case TSHORT:
941 		switch(tt) {
942 		case TDOUBLE:
943 		case TFLOAT:
944 			fixtofloat(f, t);
945 			return;
946 		case TINT:
947 		case TUINT:
948 		case TLONG:
949 		case TULONG:
950 		case TIND:
951 			a = AMOVH;
952 			break;
953 		case TSHORT:
954 		case TUSHORT:
955 		case TCHAR:
956 		case TUCHAR:
957 			a = AMOVW;
958 			break;
959 		}
960 		break;
961 	case TUSHORT:
962 		switch(tt) {
963 		case TDOUBLE:
964 		case TFLOAT:
965 			fixtofloat(f, t);
966 			return;
967 		case TINT:
968 		case TUINT:
969 		case TLONG:
970 		case TULONG:
971 		case TIND:
972 			a = AMOVHZ;
973 			break;
974 		case TSHORT:
975 		case TUSHORT:
976 		case TCHAR:
977 		case TUCHAR:
978 			a = AMOVW;
979 			break;
980 		}
981 		break;
982 	case TCHAR:
983 		switch(tt) {
984 		case TDOUBLE:
985 		case TFLOAT:
986 			fixtofloat(f, t);
987 			return;
988 		case TINT:
989 		case TUINT:
990 		case TLONG:
991 		case TULONG:
992 		case TIND:
993 		case TSHORT:
994 		case TUSHORT:
995 			a = AMOVB;
996 			break;
997 		case TCHAR:
998 		case TUCHAR:
999 			a = AMOVW;
1000 			break;
1001 		}
1002 		break;
1003 	case TUCHAR:
1004 		switch(tt) {
1005 		case TDOUBLE:
1006 		case TFLOAT:
1007 			fixtofloat(f, t);
1008 			return;
1009 		case TINT:
1010 		case TUINT:
1011 		case TLONG:
1012 		case TULONG:
1013 		case TIND:
1014 		case TSHORT:
1015 		case TUSHORT:
1016 			a = AMOVBZ;
1017 			break;
1018 		case TCHAR:
1019 		case TUCHAR:
1020 			a = AMOVW;
1021 			break;
1022 		}
1023 		break;
1024 	case TVLONG:
1025 	case TUVLONG:
1026 		switch(tt) {
1027 		case TVLONG:
1028 		case TUVLONG:
1029 			a = AMOVW;
1030 			break;
1031 		}
1032 		break;
1033 	}
1034 	if(a == AGOK)
1035 		diag(Z, "bad opcode in gmove %T -> %T", f->type, t->type);
1036 	if(a == AMOVW || a == AFMOVS || a == AFMOVD)
1037 	if(samaddr(f, t))
1038 		return;
1039 	if(typev[ft]) {
1040 		if(f->op != OREGPAIR || t->op != OREGPAIR)
1041 			diag(Z, "bad vlong in gmove (%O->%O)", f->op, t->op);
1042 		gins(a, f->left, t->left);
1043 		gins(a, f->right, t->right);
1044 	} else
1045 		gins(a, f, t);
1046 }
1047 
1048 void
gins(int a,Node * f,Node * t)1049 gins(int a, Node *f, Node *t)
1050 {
1051 
1052 	nextpc();
1053 	p->as = a;
1054 	if(f != Z)
1055 		naddr(f, &p->from);
1056 	if(t != Z)
1057 		naddr(t, &p->to);
1058 	if(debug['g'])
1059 		print("%P\n", p);
1060 }
1061 
1062 void
gins3(int a,Node * f1,Node * f2,Node * t)1063 gins3(int a, Node *f1, Node *f2, Node *t)
1064 {
1065 	Adr ta;
1066 
1067 	nextpc();
1068 	p->as = a;
1069 	if(f1 != Z)
1070 		naddr(f1, &p->from);
1071 	if(f2 != Z && (f2->op != OREGISTER || !samaddr(f2, t))) {
1072 		ta = zprog.from;	/* TO DO */
1073 		naddr(f2, &ta);
1074 		p->reg = ta.reg;
1075 		if(ta.type == D_CONST && ta.offset == 0) {
1076 			if(R0ISZERO)
1077 				p->reg = REGZERO;
1078 			else
1079 				diag(Z, "REGZERO in gins3 %A", a);
1080 		}else if(ta.type == D_CONST)
1081 			p->from3 = ta;
1082 	}
1083 	if(t != Z)
1084 		naddr(t, &p->to);
1085 	if(debug['g'])
1086 		print("%P\n", p);
1087 }
1088 
1089 void
gins4(int a,Node * f1,Node * f2,Node * f3,Node * t)1090 gins4(int a, Node *f1, Node *f2, Node *f3, Node *t)
1091 {
1092 	Adr ta;
1093 
1094 	nextpc();
1095 	p->as = a;
1096 	naddr(f1, &p->from);
1097 	if(f2->op != OREGISTER && (f2->op != OCONST || vconst(f2) != 0))
1098 		diag(f2, "invalid gins4");
1099 	naddr(f2, &ta);
1100 	p->reg = ta.reg;
1101 	if(ta.type == D_CONST && ta.offset == 0)
1102 		p->reg = REGZERO;
1103 	naddr(f3, &p->from3);
1104 	naddr(t, &p->to);
1105 	if(debug['g'])
1106 		print("%P\n", p);
1107 }
1108 
1109 void
gopcode(int o,Node * f1,Node * f2,Node * t)1110 gopcode(int o, Node *f1, Node *f2, Node *t)
1111 {
1112 	int a, et, uns;
1113 
1114 	if(o == OAS) {
1115 		gmove(f1, t);
1116 		return;
1117 	}
1118 	et = TLONG;
1119 	if(f1 != Z && f1->type != T) {
1120 		if(f1->op == OCONST && t != Z && t->type != T)
1121 			et = t->type->etype;
1122 		else
1123 			et = f1->type->etype;
1124 	}
1125 	if((typev[et] || t->type != T && typev[t->type->etype]) && o != OFUNC) {
1126 		gopcode64(o, f1, f2, t);
1127 		return;
1128 	}
1129 	uns = 0;
1130 	a = AGOK;
1131 	switch(o) {
1132 
1133 	case OASADD:
1134 	case OADD:
1135 		a = AADD;
1136 		if(et == TFLOAT)
1137 			a = AFADDS;
1138 		else
1139 		if(et == TDOUBLE)
1140 			a = AFADD;
1141 		break;
1142 
1143 	case OASSUB:
1144 	case OSUB:
1145 		a = ASUB;
1146 		if(et == TFLOAT)
1147 			a = AFSUBS;
1148 		else
1149 		if(et == TDOUBLE)
1150 			a = AFSUB;
1151 		break;
1152 
1153 	case OASOR:
1154 	case OOR:
1155 		a = AOR;
1156 		break;
1157 
1158 	case OASAND:
1159 	case OAND:
1160 		a = AAND;
1161 		if(f1->op == OCONST)
1162 			a = AANDCC;
1163 		break;
1164 
1165 	case OASXOR:
1166 	case OXOR:
1167 		a = AXOR;
1168 		break;
1169 
1170 	case OASLSHR:
1171 	case OLSHR:
1172 		a = ASRW;
1173 		break;
1174 
1175 	case OASASHR:
1176 	case OASHR:
1177 		a = ASRAW;
1178 		break;
1179 
1180 	case OASASHL:
1181 	case OASHL:
1182 		a = ASLW;
1183 		break;
1184 
1185 	case OFUNC:
1186 		a = ABL;
1187 		break;
1188 
1189 	case OASLMUL:
1190 	case OLMUL:
1191 	case OASMUL:
1192 	case OMUL:
1193 		if(et == TFLOAT) {
1194 			a = AFMULS;
1195 			break;
1196 		} else
1197 		if(et == TDOUBLE) {
1198 			a = AFMUL;
1199 			break;
1200 		}
1201 		a = AMULLW;
1202 		break;
1203 
1204 	case OASDIV:
1205 	case ODIV:
1206 		if(et == TFLOAT) {
1207 			a = AFDIVS;
1208 			break;
1209 		} else
1210 		if(et == TDOUBLE) {
1211 			a = AFDIV;
1212 			break;
1213 		}
1214 		a = ADIVW;
1215 		break;
1216 
1217 	case OASMOD:
1218 	case OMOD:
1219 		a = AREM;
1220 		break;
1221 
1222 	case OASLMOD:
1223 	case OLMOD:
1224 		a = AREMU;
1225 		break;
1226 
1227 	case OASLDIV:
1228 	case OLDIV:
1229 		a = ADIVWU;
1230 		break;
1231 
1232 	case OCOM:
1233 		a = ANOR;
1234 		break;
1235 
1236 	case ONEG:
1237 		a = ANEG;
1238 		if(et == TFLOAT || et == TDOUBLE)
1239 			a = AFNEG;
1240 		break;
1241 
1242 	case OEQ:
1243 		a = ABEQ;
1244 		if(t->op == OCONST && t->vconst >= (1<<15))
1245 			goto cmpu;
1246 		goto cmp;
1247 
1248 	case ONE:
1249 		a = ABNE;
1250 		if(t->op == OCONST && t->vconst >= (1<<15))
1251 			goto cmpu;
1252 		goto cmp;
1253 
1254 	case OLT:
1255 		a = ABLT;
1256 		goto cmp;
1257 
1258 	case OLE:
1259 		a = ABLE;
1260 		goto cmp;
1261 
1262 	case OGE:
1263 		a = ABGE;
1264 		goto cmp;
1265 
1266 	case OGT:
1267 		a = ABGT;
1268 		goto cmp;
1269 
1270 	case OLO:
1271 		a = ABLT;
1272 		goto cmpu;
1273 
1274 	case OLS:
1275 		a = ABLE;
1276 		goto cmpu;
1277 
1278 	case OHS:
1279 		a = ABGE;
1280 		goto cmpu;
1281 
1282 	case OHI:
1283 		a = ABGT;
1284 		goto cmpu;
1285 
1286 	cmpu:
1287 		uns = 1;
1288 	cmp:
1289 		nextpc();
1290 		p->as = uns? ACMPU: ACMP;
1291 		if(et == TFLOAT)
1292 			p->as = AFCMPU;
1293 		else
1294 		if(et == TDOUBLE)
1295 			p->as = AFCMPU;
1296 		if(f1 != Z)
1297 			naddr(f1, &p->from);
1298 		if(t != Z)
1299 			naddr(t, &p->to);
1300 		if(f1 == Z || t == Z || f2 != Z)
1301 			diag(Z, "bad cmp in gopcode %O", o);
1302 		if(debug['g'])
1303 			print("%P\n", p);
1304 		f1 = Z;
1305 		f2 = Z;
1306 		t = Z;
1307 		break;
1308 	}
1309 	if(a == AGOK)
1310 		diag(Z, "bad in gopcode %O", o);
1311 	gins3(a, f1, f2, t);
1312 }
1313 
1314 static void
gopcode64(int o,Node * f1,Node * f2,Node * t)1315 gopcode64(int o, Node *f1, Node *f2, Node *t)
1316 {
1317 	int a1, a2;
1318 	Node nod, nod1, nod2, sh;
1319 	ulong m;
1320 	Prog *p1;
1321 
1322 	if(t->op != OREGPAIR || f2 != Z && f2->op != OREGPAIR) {
1323 		diag(Z, "bad f2/dest in gopcode64 %O", o);
1324 		return;
1325 	}
1326 	if(f1->op != OCONST &&
1327 	   (typev[f1->type->etype] && f1->op != OREGPAIR || !typev[f1->type->etype] && f1->op != OREGISTER)) {
1328 		diag(Z, "bad f1[%O] in gopcode64 %O", f1->op, o);
1329 		return;
1330 	}
1331 	/* a1 for low-order, a2 for high-order */
1332 	a1 = AGOK;
1333 	a2 = AGOK;
1334 	switch(o) {
1335 	case OASADD:
1336 	case OADD:
1337 		if(f1->op == OCONST && sconst(f1)) {
1338 			if(f2 == Z)
1339 				f2 = t;
1340 			gins3(AADDC, f1, f2->right, t->right);
1341 			if((f1->vconst>>32) == 0)
1342 				gins(AADDZE, f2->left, t->left);
1343 			else if((f1->vconst>>32) == -1)
1344 				gins(AADDME, f2->left, t->left);
1345 			else
1346 				diag(t, "odd vlong ADD: %lld", f1->vconst);
1347 			return;
1348 		}
1349 		a1 = AADDC;
1350 		a2 = AADDE;
1351 		break;
1352 
1353 	case OASSUB:
1354 	case OSUB:
1355 		a1 = ASUBC;
1356 		a2 = ASUBE;
1357 		break;
1358 
1359 	case OASOR:
1360 	case OOR:
1361 		if(f1->op == OCONST) {
1362 			gori64(AOR, f1, f2, t);
1363 			return;
1364 		}
1365 		a1 = a2 = AOR;
1366 		break;
1367 
1368 	case OASAND:
1369 	case OAND:
1370 		if(f1->op == OCONST) {
1371 			gandi64(AANDCC, f1, f2, t);
1372 			return;
1373 		}
1374 		a1 = a2 = AAND;
1375 		break;
1376 
1377 	case OASXOR:
1378 	case OXOR:
1379 		if(f1->op == OCONST) {
1380 			gori64(AXOR, f1, f2, t);
1381 			return;
1382 		}
1383 		a1 = a2 = AXOR;
1384 		break;
1385 
1386 	case OASLSHR:
1387 	case OLSHR:
1388 		if(f2 == Z)
1389 			f2 = t;
1390 		if(f1->op == OCONST) {
1391 			if(f1->vconst >= 32) {
1392 				if(f1->vconst == 32)
1393 					gmove(f2->left, t->right);
1394 				else if(f1->vconst < 64)
1395 					gins3(ASRW, nodconst(f1->vconst-32), f2->left, t->right);
1396 				else
1397 					gmove(nodconst(0), t->right);
1398 				gmove(nodconst(0), t->left);
1399 				return;
1400 			}
1401 			if(f1->vconst <= 0) {
1402 				if(f2 != t)
1403 					gmove(f2, t);
1404 				return;
1405 			}
1406 			sh = *nodconst(32 - f1->vconst);
1407 			m = 0xFFFFFFFFUL >> f1->vconst;
1408 			gins4(ARLWNM, &sh, f2->right, nodconst(m), t->right);
1409 			gins4(ARLWMI, &sh, f2->left, nodconst(~m), t->right);
1410 			gins4(ARLWNM, &sh, f2->left, nodconst(m), t->left);
1411 			return;
1412 		}
1413 		regalloc(&nod, &regnode, Z);
1414 		gins3(ASUBC, f1, nodconst(32), &nod);
1415 		gins3(ASRW, f1, f2->right, t->right);
1416 		regalloc(&nod1, &regnode, Z);
1417 		gins3(ASLW, &nod, f2->left, &nod1);
1418 		gins(AOR, &nod1, t->right);
1419 		gins3(AADD, nodconst(-32), f1, &nod);
1420 		gins3(ASRW, &nod, f2->left, &nod1);
1421 		gins(AOR, &nod1, t->right);
1422 		gins3(ASRW, f1, f2->left, t->left);
1423 		regfree(&nod);
1424 		regfree(&nod1);
1425 		return;
1426 
1427 	case OASASHR:
1428 	case OASHR:
1429 		if(f2 == Z)
1430 			f2 = t;
1431 		if(f1->op == OCONST) {
1432 			if(f1->vconst >= 32) {
1433 				if(f1->vconst == 32)
1434 					gmove(f2->left, t->right);
1435 				else if(f1->vconst < 64)
1436 					gins3(ASRAW, nodconst(f1->vconst-32), f2->left, t->right);
1437 				gins3(ASRAW, nodconst(31), f2->left, t->left);
1438 				if(f1->vconst >= 64) {
1439 					gmove(t->left, t->right);
1440 					return;
1441 				}
1442 				return;
1443 			}
1444 			if(f1->vconst <= 0) {
1445 				if(f2 != t)
1446 					gmove(f2, t);
1447 				return;
1448 			}
1449 			sh = *nodconst(32 - f1->vconst);
1450 			m = 0xFFFFFFFFUL >> f1->vconst;
1451 			gins4(ARLWNM, &sh, f2->right, nodconst(m), t->right);
1452 			gins4(ARLWMI, &sh, f2->left, nodconst(~m), t->right);
1453 			gins3(ASRAW, &sh, f2->left, t->left);
1454 			return;
1455 		}
1456 		regalloc(&nod, &regnode, Z);
1457 		gins3(ASUBC, f1, nodconst(32), &nod);
1458 		gins3(ASRW, f1, f2->right, t->right);
1459 		regalloc(&nod1, &regnode, Z);
1460 		gins3(ASLW, &nod, f2->left, &nod1);
1461 		gins(AOR, &nod1, t->right);
1462 		gins3(AADDCCC, nodconst(-32), f1, &nod);
1463 		gins3(ASRAW, &nod, f2->left, &nod1);
1464 		gins(ABLE, Z, Z);
1465 		p1 = p;
1466 		gins(AMOVW, &nod1, t->right);
1467 		patch(p1, pc);
1468 		gins3(ASRAW, f1, f2->left, t->left);
1469 		regfree(&nod);
1470 		regfree(&nod1);
1471 		return;
1472 
1473 	case OASASHL:
1474 	case OASHL:
1475 		if(f2 == Z)
1476 			f2 = t;
1477 		if(f1->op == OCONST) {
1478 			if(f1->vconst >= 32) {
1479 				if(f1->vconst == 32)
1480 					gmove(f2->right, t->left);
1481 				else if(f1->vconst >= 64)
1482 					gmove(nodconst(0), t->left);
1483 				else
1484 					gins3(ASLW, nodconst(f1->vconst-32), f2->right, t->left);
1485 				gmove(nodconst(0), t->right);
1486 				return;
1487 			}
1488 			if(f1->vconst <= 0) {
1489 				if(f2 != t)
1490 					gmove(f2, t);
1491 				return;
1492 			}
1493 			m = 0xFFFFFFFFUL << f1->vconst;
1494 			gins4(ARLWNM, f1, f2->left, nodconst(m), t->left);
1495 			gins4(ARLWMI, f1, f2->right, nodconst(~m), t->left);
1496 			gins4(ARLWNM, f1, f2->right, nodconst(m), t->right);
1497 			return;
1498 		}
1499 		regalloc(&nod, &regnode, Z);
1500 		gins3(ASUBC, f1, nodconst(32), &nod);
1501 		gins3(ASLW, f1, f2->left, t->left);
1502 		regalloc(&nod1, &regnode, Z);
1503 		gins3(ASRW, &nod, f2->right, &nod1);
1504 		gins(AOR, &nod1, t->left);
1505 		gins3(AADD, nodconst(-32), f1, &nod);
1506 		gins3(ASLW, &nod, f2->right, &nod1);
1507 		gins(AOR, &nod1, t->left);
1508 		gins3(ASLW, f1, f2->right, t->right);
1509 		regfree(&nod);
1510 		regfree(&nod1);
1511 		return;
1512 
1513 	case OASLMUL:
1514 	case OLMUL:
1515 	case OASMUL:
1516 	case OMUL:
1517 		if(f2 == Z)
1518 			f2 = t;
1519 		regalloc(&nod, &regnode, Z);
1520 		gins3(AMULLW, f1->right, f2->right, &nod);	/* lo(f2.low*f1.low) */
1521 		regalloc(&nod1, &regnode, Z);
1522 		gins3(AMULHWU, f1->right, f2->right, &nod1);		/* hi(f2.low*f1.low) */
1523 		regalloc(&nod2, &regnode, Z);
1524 		gins3(AMULLW, f2->right, f1->left, &nod2);	/* lo(f2.low*f1.high) */
1525 		gins(AADD, &nod2, &nod1);
1526 		gins3(AMULLW, f1->right, f2->left, &nod2);	/* lo(f2.high*f1.low) */
1527 		gins(AADD, &nod2, &nod1);
1528 		regfree(&nod2);
1529 		gmove(&nod, t->right);
1530 		gmove(&nod1, t->left);
1531 		regfree(&nod);
1532 		regfree(&nod1);
1533 		return;
1534 
1535 	case OCOM:
1536 		a1 = a2 = ANOR;
1537 		break;
1538 
1539 	case ONEG:
1540 		gins3(ASUBC, t->right, nodconst(0), t->right);
1541 		gins(ASUBZE, t->left, t->left);
1542 		return;
1543 	}
1544 	if(a1 == AGOK || a2 == AGOK)
1545 		diag(Z, "bad in gopcode64 %O", o);
1546 	if(f1->op == OCONST) {
1547 		if(f2 != Z & f2 != t)
1548 			diag(Z, "bad const in gopcode64 %O", o);
1549 		gins(a1, nod32const(f1->vconst), t->right);
1550 		gins(a2, nod32const(f1->vconst>>32), t->left);
1551 	} else {
1552 		if(f2 != Z && f2 != t) {
1553 			gins3(a1, f1->right, f2->right, t->right);
1554 			gins3(a2, f1->left, f2->left, t->left);
1555 		} else {
1556 			gins(a1, f1->right, t->right);
1557 			gins(a2, f1->left, t->left);
1558 		}
1559 	}
1560 }
1561 
samaddr(Node * f,Node * t)1562 samaddr(Node *f, Node *t)
1563 {
1564 
1565 	if(f->op != t->op)
1566 		return 0;
1567 	switch(f->op) {
1568 
1569 	case OREGISTER:
1570 		if(f->reg != t->reg)
1571 			break;
1572 		return 1;
1573 
1574 	case OREGPAIR:
1575 		return samaddr(f->left, t->left) && samaddr(f->right, t->right);
1576 	}
1577 	return 0;
1578 }
1579 
1580 static void
gori64(int a,Node * f1,Node * f2,Node * t)1581 gori64(int a, Node *f1, Node *f2, Node *t)
1582 {
1583 	ulong lo, hi;
1584 
1585 	if(f2 == Z)
1586 		f2 = t;
1587 	lo = f1->vconst & MASK(32);
1588 	hi = (f1->vconst >> 32) & MASK(32);
1589 	if(lo & 0xFFFF)
1590 		gins3(a, nodconst(lo & 0xFFFF), f2->right, t->right);
1591 	if((lo >> 16) != 0)
1592 		gins3(a, nodconst(lo & 0xFFFF0000UL), f2->right, t->right);
1593 	if(hi & 0xFFFF)
1594 		gins3(a, nodconst(hi & 0xFFFF), f2->left, t->left);
1595 	if((hi >> 16) != 0)
1596 		gins3(a, nodconst(hi & 0xFFFF0000UL), f2->left, t->left);
1597 }
1598 
1599 static void
gandi64(int a,Node * f1,Node * f2,Node * t)1600 gandi64(int a, Node *f1, Node *f2, Node *t)
1601 {
1602 	ulong lo, hi;
1603 
1604 	if(f2 == Z)
1605 		f2 = t;
1606 	lo = f1->vconst & MASK(32);
1607 	hi = (f1->vconst >> 32) & MASK(32);
1608 	if(lo == 0)
1609 		gins(AMOVW, nodconst(0), t->right);
1610 	else
1611 		gins3(a, nodconst(lo), f2->right, t->right);
1612 	if(hi == 0)
1613 		gins(AMOVW, nodconst(0), t->left);
1614 	else
1615 		gins3(a, nodconst(hi), f2->left, t->left);
1616 }
1617 
1618 void
gbranch(int o)1619 gbranch(int o)
1620 {
1621 	int a;
1622 
1623 	a = AGOK;
1624 	switch(o) {
1625 	case ORETURN:
1626 		a = ARETURN;
1627 		break;
1628 	case OGOTO:
1629 		a = ABR;
1630 		break;
1631 	}
1632 	nextpc();
1633 	if(a == AGOK) {
1634 		diag(Z, "bad in gbranch %O",  o);
1635 		nextpc();
1636 	}
1637 	p->as = a;
1638 }
1639 
1640 void
patch(Prog * op,long pc)1641 patch(Prog *op, long pc)
1642 {
1643 
1644 	op->to.offset = pc;
1645 	op->to.type = D_BRANCH;
1646 }
1647 
1648 void
gpseudo(int a,Sym * s,Node * n)1649 gpseudo(int a, Sym *s, Node *n)
1650 {
1651 
1652 	nextpc();
1653 	p->as = a;
1654 	p->from.type = D_OREG;
1655 	p->from.sym = s;
1656 	if(a == ATEXT)
1657 		p->reg = (profileflg ? 0 : NOPROF);
1658 	p->from.name = D_EXTERN;
1659 	if(s->class == CSTATIC)
1660 		p->from.name = D_STATIC;
1661 	naddr(n, &p->to);
1662 	if(a == ADATA || a == AGLOBL)
1663 		pc--;
1664 }
1665 
1666 int
sval(long v)1667 sval(long v)
1668 {
1669 
1670 	if(v >= -(1<<15) && v < (1<<15))
1671 		return 1;
1672 	return 0;
1673 }
1674 
1675 int
sconst(Node * n)1676 sconst(Node *n)
1677 {
1678 	vlong vv;
1679 
1680 	if(n->op == OCONST) {
1681 		if(!typefd[n->type->etype]) {
1682 			vv = n->vconst;
1683 			if(vv >= -(((vlong)1)<<15) && vv < (((vlong)1)<<15))
1684 				return 1;
1685 		}
1686 	}
1687 	return 0;
1688 }
1689 
1690 int
uconst(Node * n)1691 uconst(Node *n)
1692 {
1693 	vlong vv;
1694 
1695 	if(n->op == OCONST) {
1696 		if(!typefd[n->type->etype]) {
1697 			vv = n->vconst;
1698 			if(vv >= 0 && vv < (((vlong)1)<<16))
1699 				return 1;
1700 		}
1701 	}
1702 	return 0;
1703 }
1704 
1705 long
exreg(Type * t)1706 exreg(Type *t)
1707 {
1708 	long o;
1709 
1710 	if(typechlp[t->etype]) {
1711 		if(exregoffset <= 3)
1712 			return 0;
1713 		o = exregoffset;
1714 		exregoffset--;
1715 		return o;
1716 	}
1717 	if(typefd[t->etype]) {
1718 		if(exfregoffset <= 16)
1719 			return 0;
1720 		o = exfregoffset + NREG;
1721 		exfregoffset--;
1722 		return o;
1723 	}
1724 	return 0;
1725 }
1726 
1727 schar	ewidth[NTYPE] =
1728 {
1729 	-1,		/* [TXXX] */
1730 	SZ_CHAR,	/* [TCHAR] */
1731 	SZ_CHAR,	/* [TUCHAR] */
1732 	SZ_SHORT,	/* [TSHORT] */
1733 	SZ_SHORT,	/* [TUSHORT] */
1734 	SZ_INT,		/* [TINT] */
1735 	SZ_INT,		/* [TUINT] */
1736 	SZ_LONG,	/* [TLONG] */
1737 	SZ_LONG,	/* [TULONG] */
1738 	SZ_VLONG,	/* [TVLONG] */
1739 	SZ_VLONG,	/* [TUVLONG] */
1740 	SZ_FLOAT,	/* [TFLOAT] */
1741 	SZ_DOUBLE,	/* [TDOUBLE] */
1742 	SZ_IND,		/* [TIND] */
1743 	0,		/* [TFUNC] */
1744 	-1,		/* [TARRAY] */
1745 	0,		/* [TVOID] */
1746 	-1,		/* [TSTRUCT] */
1747 	-1,		/* [TUNION] */
1748 	SZ_INT,		/* [TENUM] */
1749 };
1750 long	ncast[NTYPE] =
1751 {
1752 	0,				/* [TXXX] */
1753 	BCHAR|BUCHAR,			/* [TCHAR] */
1754 	BCHAR|BUCHAR,			/* [TUCHAR] */
1755 	BSHORT|BUSHORT,			/* [TSHORT] */
1756 	BSHORT|BUSHORT,			/* [TUSHORT] */
1757 	BINT|BUINT|BLONG|BULONG|BIND,	/* [TINT] */
1758 	BINT|BUINT|BLONG|BULONG|BIND,	/* [TUINT] */
1759 	BINT|BUINT|BLONG|BULONG|BIND,	/* [TLONG] */
1760 	BINT|BUINT|BLONG|BULONG|BIND,	/* [TULONG] */
1761 	BVLONG|BUVLONG,			/* [TVLONG] */
1762 	BVLONG|BUVLONG,			/* [TUVLONG] */
1763 	BFLOAT,				/* [TFLOAT] */
1764 	BDOUBLE,			/* [TDOUBLE] */
1765 	BLONG|BULONG|BIND,		/* [TIND] */
1766 	0,				/* [TFUNC] */
1767 	0,				/* [TARRAY] */
1768 	0,				/* [TVOID] */
1769 	BSTRUCT,			/* [TSTRUCT] */
1770 	BUNION,				/* [TUNION] */
1771 	0,				/* [TENUM] */
1772 };
1773