xref: /plan9/sys/src/cmd/cc/pswt.c (revision 82726826a7b3d40fb66339b4b0e95b60314f98b9)
14ac975e2SDavid du Colombier #include "gc.h"
24ac975e2SDavid du Colombier 
34ac975e2SDavid du Colombier int
swcmp(const void * a1,const void * a2)44ac975e2SDavid du Colombier swcmp(const void *a1, const void *a2)
54ac975e2SDavid du Colombier {
64ac975e2SDavid du Colombier 	C1 *p1, *p2;
74ac975e2SDavid du Colombier 
84ac975e2SDavid du Colombier 	p1 = (C1*)a1;
94ac975e2SDavid du Colombier 	p2 = (C1*)a2;
104ac975e2SDavid du Colombier 	if(p1->val < p2->val)
114ac975e2SDavid du Colombier 		return -1;
124ac975e2SDavid du Colombier 	return p1->val > p2->val;
134ac975e2SDavid du Colombier }
144ac975e2SDavid du Colombier 
154ac975e2SDavid du Colombier void
doswit(Node * n)164ac975e2SDavid du Colombier doswit(Node *n)
174ac975e2SDavid du Colombier {
184ac975e2SDavid du Colombier 	Case *c;
193a276d32SDavid du Colombier 	C1 *q, *iq, *iqh, *iql;
203a276d32SDavid du Colombier 	long def, nc, i, j, isv, nh;
213a276d32SDavid du Colombier 	Prog *hsb;
223a276d32SDavid du Colombier 	Node *vr[2];
237fd2696aSDavid du Colombier 	int dup;
244ac975e2SDavid du Colombier 
254ac975e2SDavid du Colombier 	def = 0;
264ac975e2SDavid du Colombier 	nc = 0;
275ede6b93SDavid du Colombier 	isv = 0;
284ac975e2SDavid du Colombier 	for(c = cases; c->link != C; c = c->link) {
294ac975e2SDavid du Colombier 		if(c->def) {
304ac975e2SDavid du Colombier 			if(def)
314ac975e2SDavid du Colombier 				diag(n, "more than one default in switch");
324ac975e2SDavid du Colombier 			def = c->label;
334ac975e2SDavid du Colombier 			continue;
344ac975e2SDavid du Colombier 		}
355ede6b93SDavid du Colombier 		isv |= c->isv;
364ac975e2SDavid du Colombier 		nc++;
374ac975e2SDavid du Colombier 	}
383a276d32SDavid du Colombier 	if(typev[n->type->etype])
393a276d32SDavid du Colombier 		isv = 1;
403a276d32SDavid du Colombier 	else if(isv){
415ede6b93SDavid du Colombier 		warn(n, "32-bit switch expression with 64-bit case constant");
423a276d32SDavid du Colombier 		isv = 0;
433a276d32SDavid du Colombier 	}
444ac975e2SDavid du Colombier 
454ac975e2SDavid du Colombier 	iq = alloc(nc*sizeof(C1));
464ac975e2SDavid du Colombier 	q = iq;
474ac975e2SDavid du Colombier 	for(c = cases; c->link != C; c = c->link) {
484ac975e2SDavid du Colombier 		if(c->def)
494ac975e2SDavid du Colombier 			continue;
503a276d32SDavid du Colombier 		if(c->isv && !isv)
513a276d32SDavid du Colombier 			continue;	/* can never match */
524ac975e2SDavid du Colombier 		q->label = c->label;
535ede6b93SDavid du Colombier 		if(isv)
544ac975e2SDavid du Colombier 			q->val = c->val;
555ede6b93SDavid du Colombier 		else
565ede6b93SDavid du Colombier 			q->val = (long)c->val;	/* cast ensures correct value for 32-bit switch on 64-bit architecture */
574ac975e2SDavid du Colombier 		q++;
584ac975e2SDavid du Colombier 	}
594ac975e2SDavid du Colombier 	qsort(iq, nc, sizeof(C1), swcmp);
604faf3cb1SDavid du Colombier 	if(debug['K'])
614ac975e2SDavid du Colombier 	for(i=0; i<nc; i++)
624ac975e2SDavid du Colombier 		print("case %2ld: = %.8llux\n", i, (vlong)iq[i].val);
637fd2696aSDavid du Colombier 	dup = 0;
644ac975e2SDavid du Colombier 	for(i=0; i<nc-1; i++)
657fd2696aSDavid du Colombier 		if(iq[i].val == iq[i+1].val) {
664ac975e2SDavid du Colombier 			diag(n, "duplicate cases in switch %lld", (vlong)iq[i].val);
677fd2696aSDavid du Colombier 			dup = 1;
687fd2696aSDavid du Colombier 		}
697fd2696aSDavid du Colombier 	if(dup)
707fd2696aSDavid du Colombier 		return;
714ac975e2SDavid du Colombier 	if(def == 0) {
724ac975e2SDavid du Colombier 		def = breakpc;
734ac975e2SDavid du Colombier 		nbreak++;
744ac975e2SDavid du Colombier 	}
753a276d32SDavid du Colombier 	if(!isv || ewidth[TIND] > ewidth[TLONG] || n->op == OREGISTER) {
764ac975e2SDavid du Colombier 		swit1(iq, nc, def, n);
773a276d32SDavid du Colombier 		return;
783a276d32SDavid du Colombier 	}
793a276d32SDavid du Colombier 
803a276d32SDavid du Colombier 	/*
813a276d32SDavid du Colombier 	 * 64-bit case on 32-bit machine:
823a276d32SDavid du Colombier 	 * switch on high-order words, and
833a276d32SDavid du Colombier 	 * in each of those, switch on low-order words
843a276d32SDavid du Colombier 	 */
853a276d32SDavid du Colombier 	if(n->op != OREGPAIR)
863a276d32SDavid du Colombier 		fatal(n, "internal: expected register pair");
873a276d32SDavid du Colombier 	if(thechar == '8'){	/* TO DO: need an enquiry function */
883a276d32SDavid du Colombier 		vr[0] = n->left;	/* low */
893a276d32SDavid du Colombier 		vr[1] = n->right;	/* high */
903a276d32SDavid du Colombier 	}else{
913a276d32SDavid du Colombier 		vr[0] = n->right;
923a276d32SDavid du Colombier 		vr[1] = n->left;
933a276d32SDavid du Colombier 	}
943a276d32SDavid du Colombier 	vr[0]->type = types[TLONG];
953a276d32SDavid du Colombier 	vr[1]->type = types[TLONG];
963a276d32SDavid du Colombier 	gbranch(OGOTO);
973a276d32SDavid du Colombier 	hsb = p;
983a276d32SDavid du Colombier 	iqh = alloc(nc*sizeof(C1));
993a276d32SDavid du Colombier 	iql = alloc(nc*sizeof(C1));
1003a276d32SDavid du Colombier 	nh = 0;
1013a276d32SDavid du Colombier 	for(i=0; i<nc;){
1023a276d32SDavid du Colombier 		iqh[nh].val = iq[i].val >> 32;
1033a276d32SDavid du Colombier 		q = iql;
1043a276d32SDavid du Colombier 		/* iq is sorted, so equal top halves are adjacent */
1053a276d32SDavid du Colombier 		for(j = i; j < nc; j++){
1063a276d32SDavid du Colombier 			if((iq[j].val>>32) != iqh[nh].val)
1073a276d32SDavid du Colombier 				break;
1083a276d32SDavid du Colombier 			q->val = (long)iq[j].val;
1093a276d32SDavid du Colombier 			q->label = iq[j].label;
1103a276d32SDavid du Colombier 			q++;
1113a276d32SDavid du Colombier 		}
1123a276d32SDavid du Colombier 		qsort(iql,  q-iql, sizeof(C1), swcmp);
1133a276d32SDavid du Colombier if(0){for(int k=0; k<(q-iql); k++)print("nh=%ld k=%d h=%#llux l=%#llux lab=%ld\n", nh, k, (vlong)iqh[nh].val,  (vlong)iql[k].val, iql[k].label);}
1143a276d32SDavid du Colombier 		iqh[nh].label = pc;
1153a276d32SDavid du Colombier 		nh++;
1163a276d32SDavid du Colombier 		swit1(iql, q-iql, def, vr[0]);
1173a276d32SDavid du Colombier 		i = j;
1183a276d32SDavid du Colombier 	}
1193a276d32SDavid du Colombier 	patch(hsb, pc);
1203a276d32SDavid du Colombier if(0){for(int k=0; k<nh; k++)print("k*=%d h=%#llux lab=%ld\n", k, (vlong)iqh[k].val,  iqh[k].label);}
1213a276d32SDavid du Colombier 	swit1(iqh, nh, def, vr[1]);
1224ac975e2SDavid du Colombier }
1234ac975e2SDavid du Colombier 
1244ac975e2SDavid du Colombier void
casf(void)125ff4cd143SDavid du Colombier casf(void)
1264ac975e2SDavid du Colombier {
1274ac975e2SDavid du Colombier 	Case *c;
1284ac975e2SDavid du Colombier 
1294ac975e2SDavid du Colombier 	c = alloc(sizeof(*c));
1304ac975e2SDavid du Colombier 	c->link = cases;
1314ac975e2SDavid du Colombier 	cases = c;
1324ac975e2SDavid du Colombier }
1334ac975e2SDavid du Colombier 
134acfb0edcSDavid du Colombier long
outlstring(TRune * s,long n)135*82726826SDavid du Colombier outlstring(TRune *s, long n)
136acfb0edcSDavid du Colombier {
137*82726826SDavid du Colombier 	char buf[sizeof(TRune)];
138*82726826SDavid du Colombier 	uint c;
139*82726826SDavid du Colombier 	int i;
140acfb0edcSDavid du Colombier 	long r;
141acfb0edcSDavid du Colombier 
142acfb0edcSDavid du Colombier 	if(suppress)
143acfb0edcSDavid du Colombier 		return nstring;
144*82726826SDavid du Colombier 	while(nstring & (sizeof(TRune)-1))
145acfb0edcSDavid du Colombier 		outstring("", 1);
146acfb0edcSDavid du Colombier 	r = nstring;
147acfb0edcSDavid du Colombier 	while(n > 0) {
148acfb0edcSDavid du Colombier 		c = *s++;
149acfb0edcSDavid du Colombier 		if(align(0, types[TCHAR], Aarg1)) {
150*82726826SDavid du Colombier 			for(i = 0; i < sizeof(TRune); i++)
151*82726826SDavid du Colombier 				buf[i] = c>>(8*(sizeof(TRune) - i - 1));
152acfb0edcSDavid du Colombier 		} else {
153*82726826SDavid du Colombier 			for(i = 0; i < sizeof(TRune); i++)
154*82726826SDavid du Colombier 				buf[i] = c>>(8*i);
155acfb0edcSDavid du Colombier 		}
156*82726826SDavid du Colombier 		outstring(buf, sizeof(TRune));
157*82726826SDavid du Colombier 		n -= sizeof(TRune);
158acfb0edcSDavid du Colombier 	}
159acfb0edcSDavid du Colombier 	return r;
160acfb0edcSDavid du Colombier }
161acfb0edcSDavid du Colombier 
162acfb0edcSDavid du Colombier void
nullwarn(Node * l,Node * r)163acfb0edcSDavid du Colombier nullwarn(Node *l, Node *r)
164acfb0edcSDavid du Colombier {
165acfb0edcSDavid du Colombier 	warn(Z, "result of operation not used");
166acfb0edcSDavid du Colombier 	if(l != Z)
167acfb0edcSDavid du Colombier 		cgen(l, Z);
168acfb0edcSDavid du Colombier 	if(r != Z)
169acfb0edcSDavid du Colombier 		cgen(r, Z);
170acfb0edcSDavid du Colombier }
171acfb0edcSDavid du Colombier 
172acfb0edcSDavid du Colombier void
ieeedtod(Ieee * ieee,double native)173acfb0edcSDavid du Colombier ieeedtod(Ieee *ieee, double native)
174acfb0edcSDavid du Colombier {
175acfb0edcSDavid du Colombier 	double fr, ho, f;
176acfb0edcSDavid du Colombier 	int exp;
177acfb0edcSDavid du Colombier 
178acfb0edcSDavid du Colombier 	if(native < 0) {
179acfb0edcSDavid du Colombier 		ieeedtod(ieee, -native);
180acfb0edcSDavid du Colombier 		ieee->h |= 0x80000000L;
181acfb0edcSDavid du Colombier 		return;
182acfb0edcSDavid du Colombier 	}
183acfb0edcSDavid du Colombier 	if(native == 0) {
184acfb0edcSDavid du Colombier 		ieee->l = 0;
185acfb0edcSDavid du Colombier 		ieee->h = 0;
186acfb0edcSDavid du Colombier 		return;
187acfb0edcSDavid du Colombier 	}
188acfb0edcSDavid du Colombier 	fr = frexp(native, &exp);
189acfb0edcSDavid du Colombier 	f = 2097152L;		/* shouldnt use fp constants here */
190acfb0edcSDavid du Colombier 	fr = modf(fr*f, &ho);
191acfb0edcSDavid du Colombier 	ieee->h = ho;
192acfb0edcSDavid du Colombier 	ieee->h &= 0xfffffL;
193acfb0edcSDavid du Colombier 	ieee->h |= (exp+1022L) << 20;
194acfb0edcSDavid du Colombier 	f = 65536L;
195acfb0edcSDavid du Colombier 	fr = modf(fr*f, &ho);
196acfb0edcSDavid du Colombier 	ieee->l = ho;
197acfb0edcSDavid du Colombier 	ieee->l <<= 16;
198acfb0edcSDavid du Colombier 	ieee->l |= (long)(fr*f);
199acfb0edcSDavid du Colombier }
200