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 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)
|
||||
{
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue