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