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 cgen64(Node*, Node*);
static int isvconstable(int, vlong);
static void genasop(int, Node*, Node*, Node*);
void
cgen(Node *n, Node *nn)
@ -255,6 +256,8 @@ cgen(Node *n, Node *nn)
regfree(&nod2);
break;
}
genasop(o, l, r, nn);
break;
case OASLMUL:
case OASLDIV:
@ -264,31 +267,7 @@ cgen(Node *n, Node *nn)
case OASMOD:
if(l->op == OBIT)
goto asbitop;
if(l->complex >= r->complex) {
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);
genasop(o, l, r, nn);
break;
asbitop:
@ -561,6 +540,43 @@ cgen(Node *n, Node *nn)
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
reglcgen(Node *t, Node *n, Node *nn)
{

View file

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

View file

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

View file

@ -622,12 +622,86 @@ fop(int as, int f1, int f2, Node *t)
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
gmove(Node *f, Node *t)
{
int ft, tt, a;
Node nod, fxc0, fxc1, fxc2, fxrat;
Prog *p1;
Node nod;
double d;
ft = f->type->etype;
@ -727,7 +801,7 @@ gmove(Node *f, Node *t)
break;
}
if(typev[ft]) {
if(typev[tt]) {
if(typev[tt] || typefd[tt]) {
regalloc(&nod, f, t);
/* low order first, because its value will be used first */
f->xoffset += SZ_LONG;
@ -832,16 +906,11 @@ gmove(Node *f, Node *t)
case TCHAR:
case TUCHAR:
/* BUG: not right for unsigned long */
regalloc(&nod, f, Z); /* should be type float */
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);
floattofix(f, t);
return;
case TVLONG:
case TUVLONG:
diag(f, "unimplemented double->vlong");
return;
}
break;
@ -853,7 +922,8 @@ gmove(Node *f, Node *t)
switch(tt) {
case TDOUBLE:
case TFLOAT:
goto fxtofl;
fixtofloat(f, t);
return;
case TINT:
case TUINT:
case TLONG:
@ -871,7 +941,8 @@ gmove(Node *f, Node *t)
switch(tt) {
case TDOUBLE:
case TFLOAT:
goto fxtofl;
fixtofloat(f, t);
return;
case TINT:
case TUINT:
case TLONG:
@ -891,7 +962,8 @@ gmove(Node *f, Node *t)
switch(tt) {
case TDOUBLE:
case TFLOAT:
goto fxtofl;
fixtofloat(f, t);
return;
case TINT:
case TUINT:
case TLONG:
@ -911,7 +983,8 @@ gmove(Node *f, Node *t)
switch(tt) {
case TDOUBLE:
case TFLOAT:
goto fxtofl;
fixtofloat(f, t);
return;
case TINT:
case TUINT:
case TLONG:
@ -931,58 +1004,7 @@ gmove(Node *f, Node *t)
switch(tt) {
case TDOUBLE:
case TFLOAT:
fxtofl:
/*
* 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);
}
fixtofloat(f, t);
return;
case TINT:
case TUINT:
@ -1522,7 +1544,7 @@ gopcode64(int o, Node *f1, Node *f2, Node *t)
if(a1 == AGOK || a2 == AGOK)
diag(Z, "bad in gopcode64 %O", o);
if(f1->op == OCONST) {
if(f2 != Z && f2 != t)
if(f2 != Z & f2 != t)
diag(Z, "bad const in gopcode64 %O", o);
gins(a1, nod32const(f1->vconst), t->right);
gins(a2, nod32const(f1->vconst>>32), t->left);