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