qc: import changes from charles forsyth
This commit is contained in:
parent
4a916ba86e
commit
7c7acbef31
4 changed files with 140 additions and 98 deletions
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Reference in a new issue