summaryrefslogtreecommitdiff
path: root/utils/cc/pswt.c
diff options
context:
space:
mode:
Diffstat (limited to 'utils/cc/pswt.c')
-rw-r--r--utils/cc/pswt.c85
1 files changed, 69 insertions, 16 deletions
diff --git a/utils/cc/pswt.c b/utils/cc/pswt.c
index 6ef4f2fb..0471c10d 100644
--- a/utils/cc/pswt.c
+++ b/utils/cc/pswt.c
@@ -1,7 +1,7 @@
#include "gc.h"
int
-swcmp(const void *a1, const void *a2)
+swcmp(void *a1, void *a2)
{
C1 *p1, *p2;
@@ -16,8 +16,10 @@ void
doswit(Node *n)
{
Case *c;
- C1 *q, *iq;
- long def, nc, i, isv;
+ C1 *q, *iq, *iqh, *iql;
+ long def, nc, i, j, isv, nh;
+ Prog *hsb;
+ Node *vr[2];
int dup;
def = 0;
@@ -33,14 +35,20 @@ doswit(Node *n)
isv |= c->isv;
nc++;
}
- if(isv && !typev[n->type->etype])
+ if(typev[n->type->etype])
+ isv = 1;
+ else if(isv){
warn(n, "32-bit switch expression with 64-bit case constant");
+ isv = 0;
+ }
iq = alloc(nc*sizeof(C1));
q = iq;
for(c = cases; c->link != C; c = c->link) {
if(c->def)
continue;
+ if(c->isv && !isv)
+ continue; /* can never match */
q->label = c->label;
if(isv)
q->val = c->val;
@@ -49,7 +57,7 @@ doswit(Node *n)
q++;
}
qsort(iq, nc, sizeof(C1), swcmp);
- if(debug['W'])
+ if(debug['K'])
for(i=0; i<nc; i++)
print("case %2ld: = %.8llux\n", i, (vlong)iq[i].val);
dup = 0;
@@ -64,7 +72,51 @@ doswit(Node *n)
def = breakpc;
nbreak++;
}
- swit1(iq, nc, def, n);
+ if(!isv || ewidth[TIND] > ewidth[TLONG] || n->op == OREGISTER) {
+ swit1(iq, nc, def, n);
+ return;
+ }
+
+ /*
+ * 64-bit case on 32-bit machine:
+ * switch on high-order words, and
+ * in each of those, switch on low-order words
+ */
+ if(n->op != OREGPAIR)
+ fatal(n, "internal: expected register pair");
+ if(thechar == '8'){ /* TO DO: need an enquiry function */
+ vr[0] = n->left; /* low */
+ vr[1] = n->right; /* high */
+ }else{
+ vr[0] = n->right;
+ vr[1] = n->left;
+ }
+ vr[0]->type = types[TLONG];
+ vr[1]->type = types[TLONG];
+ gbranch(OGOTO);
+ hsb = p;
+ iqh = alloc(nc*sizeof(C1));
+ iql = alloc(nc*sizeof(C1));
+ nh = 0;
+ for(i=0; i<nc;){
+ iqh[nh].val = iq[i].val >> 32;
+ q = iql;
+ /* iq is sorted, so equal top halves are adjacent */
+ for(j = i; j < nc; j++){
+ if((iq[j].val>>32) != iqh[nh].val)
+ break;
+ q->val = (long)iq[j].val;
+ q->label = iq[j].label;
+ q++;
+ }
+ qsort(iql, q-iql, sizeof(C1), swcmp);
+ iqh[nh].label = pc;
+ nh++;
+ swit1(iql, q-iql, def, vr[0]);
+ i = j;
+ }
+ patch(hsb, pc);
+ swit1(iqh, nh, def, vr[1]);
}
void
@@ -78,28 +130,29 @@ casf(void)
}
long
-outlstring(ushort *s, long n)
+outlstring(TRune *s, long n)
{
- char buf[2];
- int c;
+ char buf[sizeof(TRune)];
+ uint c;
+ int i;
long r;
if(suppress)
return nstring;
- while(nstring & 1)
+ while(nstring & (sizeof(TRune)-1))
outstring("", 1);
r = nstring;
while(n > 0) {
c = *s++;
if(align(0, types[TCHAR], Aarg1)) {
- buf[0] = c>>8;
- buf[1] = c;
+ for(i = 0; i < sizeof(TRune); i++)
+ buf[i] = c>>(8*(sizeof(TRune) - i - 1));
} else {
- buf[0] = c;
- buf[1] = c>>8;
+ for(i = 0; i < sizeof(TRune); i++)
+ buf[i] = c>>(8*i);
}
- outstring(buf, 2);
- n -= sizeof(ushort);
+ outstring(buf, sizeof(TRune));
+ n -= sizeof(TRune);
}
return r;
}