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