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