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