qc: import changes from charles forsyth

This commit is contained in:
cinap_lenrek 2015-10-07 09:40:48 +02:00
parent 4a916ba86e
commit 7c7acbef31
4 changed files with 140 additions and 98 deletions

View file

@ -4,6 +4,7 @@ static void cmpv(Node*, int, Node*);
static void testv(Node*, int); static void testv(Node*, int);
static void cgen64(Node*, Node*); static void cgen64(Node*, Node*);
static int isvconstable(int, vlong); static int isvconstable(int, vlong);
static void genasop(int, Node*, Node*, Node*);
void void
cgen(Node *n, Node *nn) cgen(Node *n, Node *nn)
@ -255,6 +256,8 @@ cgen(Node *n, Node *nn)
regfree(&nod2); regfree(&nod2);
break; break;
} }
genasop(o, l, r, nn);
break;
case OASLMUL: case OASLMUL:
case OASLDIV: case OASLDIV:
@ -264,31 +267,7 @@ cgen(Node *n, Node *nn)
case OASMOD: case OASMOD:
if(l->op == OBIT) if(l->op == OBIT)
goto asbitop; goto asbitop;
if(l->complex >= r->complex) { genasop(o, l, r, nn);
if(l->addable < INDEXED)
reglcgen(&nod2, l, Z);
else
nod2 = *l;
regalloc(&nod, r, Z);
cgen(r, &nod);
} else {
regalloc(&nod, r, Z);
cgen(r, &nod);
if(l->addable < INDEXED)
reglcgen(&nod2, l, Z);
else
nod2 = *l;
}
regalloc(&nod1, n, nn);
gopcode(OAS, &nod2, Z, &nod1);
gopcode(o, &nod, Z, &nod1);
gopcode(OAS, &nod1, Z, &nod2);
if(nn != Z)
gopcode(OAS, &nod1, Z, nn);
regfree(&nod);
regfree(&nod1);
if(l->addable < INDEXED)
regfree(&nod2);
break; break;
asbitop: asbitop:
@ -561,6 +540,43 @@ cgen(Node *n, Node *nn)
cursafe = curs; cursafe = curs;
} }
static void
genasop(int o, Node *l, Node *r, Node *nn)
{
Node nod, nod1, nod2;
int hardleft;
hardleft = l->addable < INDEXED || l->complex >= FNX;
if(l->complex >= r->complex) {
if(hardleft)
reglcgen(&nod2, l, Z);
else
nod2 = *l;
regalloc(&nod1, r, Z);
cgen(r, &nod1);
} else {
regalloc(&nod1, r, Z);
cgen(r, &nod1);
if(hardleft)
reglcgen(&nod2, l, Z);
else
nod2 = *l;
}
if(nod1.type == nod2.type || !typefd[nod1.type->etype])
regalloc(&nod, &nod2, nn);
else
regalloc(&nod, &nod1, Z);
gmove(&nod2, &nod);
gopcode(o, &nod1, Z, &nod);
gmove(&nod, &nod2);
if(nn != Z)
gmove(&nod2, nn);
regfree(&nod);
regfree(&nod1);
if(hardleft)
regfree(&nod2);
}
void void
reglcgen(Node *t, Node *n, Node *nn) reglcgen(Node *t, Node *n, Node *nn)
{ {

View file

@ -18,10 +18,12 @@ machcap(Node *n)
case OMUL: case OMUL:
case OLMUL: case OLMUL:
case OASMUL:
case OASLMUL: case OASLMUL:
return 1; return 1;
case OASMUL:
return !mixedasop(n->type, n->right->type);
case OLSHR: case OLSHR:
case OASHR: case OASHR:
case OASHL: case OASHL:
@ -58,6 +60,8 @@ machcap(Node *n)
case OASADD: case OASADD:
case OASSUB: case OASSUB:
return !mixedasop(n->type, n->right->type);
case OASAND: case OASAND:
case OASOR: case OASOR:
case OASXOR: case OASXOR:

View file

@ -657,8 +657,8 @@ maxround(long max, long v)
w = SZ_LONG; w = SZ_LONG;
if((debug['8'] || hasdoubled) && !debug['4']) if((debug['8'] || hasdoubled) && !debug['4'])
w = SZ_DOUBLE; w = SZ_DOUBLE;
v += w-1; v = round(v, w);
if(v > max) if(v > max)
max = round(v, w); return v;
return max; return max;
} }

View file

@ -622,12 +622,86 @@ fop(int as, int f1, int f2, Node *t)
regfree(&nod3); regfree(&nod3);
} }
static void
floattofix(Node *f, Node *t)
{
Node nod, fxrat;
regalloc(&nod, f, Z);
regsalloc(&fxrat, &fconstnode);
gins(AFCTIWZ, f, &nod);
gins(AFMOVD, &nod, &fxrat);
regfree(&nod);
fxrat.type = nodrat->type;
fxrat.etype = nodrat->etype;
fxrat.xoffset += 4;
gins(AMOVW, &fxrat, t);
gmove(t, t);
}
static void
fixtofloat(Node *f, Node *t)
{
int a, ft, tt;
Prog *p1;
Node nod, fxc0, fxc1, fxc2, fxrat;
ft = f->type->etype;
tt = t->type->etype;
/*
* rat[0] = 0x43300000; rat[1] = f^0x80000000;
* t = *(double*)rat - FREGCVI;
* is-unsigned(t) => if(t<0) t += 2^32;
* could be streamlined for int-to-float
*/
regalloc(&fxc0, f, Z);
regalloc(&fxc2, f, Z);
regsalloc(&fxrat, &fconstnode); /* should be type float */
gins(AMOVW, nodconst(0x43300000L), &fxc0);
gins(AMOVW, f, &fxc2);
gins(AMOVW, &fxc0, &fxrat);
gins(AXOR, nodconst(0x80000000L), &fxc2);
fxc1 = fxrat;
fxc1.type = nodrat->type;
fxc1.etype = nodrat->etype;
fxc1.xoffset += SZ_LONG;
gins(AMOVW, &fxc2, &fxc1);
regfree(&fxc2);
regfree(&fxc0);
regalloc(&nod, t, t); /* should be type float */
gins(AFMOVD, &fxrat, &nod);
nodreg(&fxc1, t, NREG+FREGCVI);
gins(AFSUB, &fxc1, &nod);
a = AFMOVD;
if(tt == TFLOAT)
a = AFRSP;
gins(a, &nod, t);
regfree(&nod);
if(ft == TULONG) {
regalloc(&nod, t, Z);
gins(AFCMPU, t, Z);
p->to.type = D_FREG;
p->to.reg = FREGZERO;
gins(ABGE, Z, Z);
p1 = p;
if(tt == TFLOAT) {
gins(AFMOVS, nodfconst(4294967296.), &nod);
gins(AFADDS, &nod, t);
} else {
gins(AFMOVD, nodfconst(4294967296.), &nod);
gins(AFADD, &nod, t);
}
patch(p1, pc);
regfree(&nod);
}
}
void void
gmove(Node *f, Node *t) gmove(Node *f, Node *t)
{ {
int ft, tt, a; int ft, tt, a;
Node nod, fxc0, fxc1, fxc2, fxrat; Node nod;
Prog *p1;
double d; double d;
ft = f->type->etype; ft = f->type->etype;
@ -727,7 +801,7 @@ gmove(Node *f, Node *t)
break; break;
} }
if(typev[ft]) { if(typev[ft]) {
if(typev[tt]) { if(typev[tt] || typefd[tt]) {
regalloc(&nod, f, t); regalloc(&nod, f, t);
/* low order first, because its value will be used first */ /* low order first, because its value will be used first */
f->xoffset += SZ_LONG; f->xoffset += SZ_LONG;
@ -832,16 +906,11 @@ gmove(Node *f, Node *t)
case TCHAR: case TCHAR:
case TUCHAR: case TUCHAR:
/* BUG: not right for unsigned long */ /* BUG: not right for unsigned long */
regalloc(&nod, f, Z); /* should be type float */ floattofix(f, t);
regsalloc(&fxrat, &fconstnode); return;
gins(AFCTIWZ, f, &nod); case TVLONG:
gins(AFMOVD, &nod, &fxrat); case TUVLONG:
regfree(&nod); diag(f, "unimplemented double->vlong");
fxrat.type = nodrat->type;
fxrat.etype = nodrat->etype;
fxrat.xoffset += 4;
gins(AMOVW, &fxrat, t);
gmove(t, t);
return; return;
} }
break; break;
@ -853,7 +922,8 @@ gmove(Node *f, Node *t)
switch(tt) { switch(tt) {
case TDOUBLE: case TDOUBLE:
case TFLOAT: case TFLOAT:
goto fxtofl; fixtofloat(f, t);
return;
case TINT: case TINT:
case TUINT: case TUINT:
case TLONG: case TLONG:
@ -871,7 +941,8 @@ gmove(Node *f, Node *t)
switch(tt) { switch(tt) {
case TDOUBLE: case TDOUBLE:
case TFLOAT: case TFLOAT:
goto fxtofl; fixtofloat(f, t);
return;
case TINT: case TINT:
case TUINT: case TUINT:
case TLONG: case TLONG:
@ -891,7 +962,8 @@ gmove(Node *f, Node *t)
switch(tt) { switch(tt) {
case TDOUBLE: case TDOUBLE:
case TFLOAT: case TFLOAT:
goto fxtofl; fixtofloat(f, t);
return;
case TINT: case TINT:
case TUINT: case TUINT:
case TLONG: case TLONG:
@ -911,7 +983,8 @@ gmove(Node *f, Node *t)
switch(tt) { switch(tt) {
case TDOUBLE: case TDOUBLE:
case TFLOAT: case TFLOAT:
goto fxtofl; fixtofloat(f, t);
return;
case TINT: case TINT:
case TUINT: case TUINT:
case TLONG: case TLONG:
@ -931,58 +1004,7 @@ gmove(Node *f, Node *t)
switch(tt) { switch(tt) {
case TDOUBLE: case TDOUBLE:
case TFLOAT: case TFLOAT:
fxtofl: fixtofloat(f, t);
/*
* rat[0] = 0x43300000; rat[1] = f^0x80000000;
* t = *(double*)rat - FREGCVI;
* is-unsigned(t) => if(t<0) t += 2^32;
* could be streamlined for int-to-float
*/
regalloc(&fxc0, f, Z);
regalloc(&fxc2, f, Z);
regsalloc(&fxrat, &fconstnode); /* should be type float */
gins(AMOVW, nodconst(0x43300000L), &fxc0);
gins(AMOVW, f, &fxc2);
gins(AMOVW, &fxc0, &fxrat);
gins(AXOR, nodconst(0x80000000L), &fxc2);
fxc1 = fxrat;
fxc1.type = nodrat->type;
fxc1.etype = nodrat->etype;
fxc1.xoffset += SZ_LONG;
gins(AMOVW, &fxc2, &fxc1);
regfree(&fxc2);
regfree(&fxc0);
regalloc(&nod, t, t); /* should be type float */
gins(AFMOVD, &fxrat, &nod);
nodreg(&fxc1, t, NREG+FREGCVI);
gins(AFSUB, &fxc1, &nod);
a = AFMOVD;
if(tt == TFLOAT)
a = AFRSP;
gins(a, &nod, t);
regfree(&nod);
if(ft == TULONG) {
regalloc(&nod, t, Z);
if(tt == TFLOAT) {
gins(AFCMPU, t, Z);
p->to.type = D_FREG;
p->to.reg = FREGZERO;
gins(ABGE, Z, Z);
p1 = p;
gins(AFMOVS, nodfconst(4294967296.), &nod);
gins(AFADDS, &nod, t);
} else {
gins(AFCMPU, t, Z);
p->to.type = D_FREG;
p->to.reg = FREGZERO;
gins(ABGE, Z, Z);
p1 = p;
gins(AFMOVD, nodfconst(4294967296.), &nod);
gins(AFADD, &nod, t);
}
patch(p1, pc);
regfree(&nod);
}
return; return;
case TINT: case TINT:
case TUINT: case TUINT:
@ -1522,7 +1544,7 @@ gopcode64(int o, Node *f1, Node *f2, Node *t)
if(a1 == AGOK || a2 == AGOK) if(a1 == AGOK || a2 == AGOK)
diag(Z, "bad in gopcode64 %O", o); diag(Z, "bad in gopcode64 %O", o);
if(f1->op == OCONST) { if(f1->op == OCONST) {
if(f2 != Z && f2 != t) if(f2 != Z & f2 != t)
diag(Z, "bad const in gopcode64 %O", o); diag(Z, "bad const in gopcode64 %O", o);
gins(a1, nod32const(f1->vconst), t->right); gins(a1, nod32const(f1->vconst), t->right);
gins(a2, nod32const(f1->vconst>>32), t->left); gins(a2, nod32const(f1->vconst>>32), t->left);