diff options
Diffstat (limited to 'utils/cc/pswt.c')
| -rw-r--r-- | utils/cc/pswt.c | 85 |
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; } |
