5c: support for bit ROL, native 64 bit arithmetic
This commit is contained in:
parent
57ff297cc0
commit
5bf09937da
10 changed files with 585 additions and 66 deletions
|
@ -158,6 +158,8 @@ enum as
|
|||
|
||||
ACLREX,
|
||||
|
||||
AROR,
|
||||
|
||||
ALAST,
|
||||
};
|
||||
|
||||
|
|
|
@ -180,6 +180,7 @@ cgenrel(Node *n, Node *nn, int inrel)
|
|||
case OAND:
|
||||
case OOR:
|
||||
case OXOR:
|
||||
case OROL:
|
||||
case OLSHR:
|
||||
case OASHL:
|
||||
case OASHR:
|
||||
|
@ -410,6 +411,10 @@ cgenrel(Node *n, Node *nn, int inrel)
|
|||
break;
|
||||
}
|
||||
}
|
||||
if(typev[l->type->etype]) {
|
||||
cgen64(n, nn);
|
||||
break;
|
||||
}
|
||||
regalloc(&nod, l, nn);
|
||||
cgen(l, &nod);
|
||||
regalloc(&nod1, n, &nod);
|
||||
|
@ -858,11 +863,320 @@ boolgen(Node *n, int true, Node *nn)
|
|||
cursafe = curs;
|
||||
}
|
||||
|
||||
static void
|
||||
freepair(Node *n)
|
||||
{
|
||||
n->left->xoffset = reg[n->left->reg];
|
||||
reg[n->left->reg] = 0;
|
||||
n->right->xoffset = reg[n->right->reg];
|
||||
reg[n->right->reg] = 0;
|
||||
}
|
||||
static void
|
||||
unfreepair(Node *n)
|
||||
{
|
||||
reg[n->left->reg] = n->left->xoffset;
|
||||
n->left->xoffset = 0;
|
||||
reg[n->right->reg] = n->right->xoffset;
|
||||
n->right->xoffset = 0;
|
||||
}
|
||||
|
||||
int
|
||||
cgen64(Node *n, Node *nn)
|
||||
{
|
||||
Node nod0, nod1, nod2, nod3, *l, *r;
|
||||
int o, a, ml, mr, nnsaved;
|
||||
long curs;
|
||||
|
||||
if(!machcap(n))
|
||||
return 0;
|
||||
|
||||
if(debug['g']){
|
||||
prtree(nn, "cgen64 nn");
|
||||
prtree(n, "cgen64 n");
|
||||
}
|
||||
|
||||
if(nn != Z && nn->op != OREGPAIR && typev[n->type->etype]){
|
||||
if(nn->complex > n->complex){
|
||||
reglpcgen(&nod0, nn, 1);
|
||||
nod0.type = n->type;
|
||||
regalloc(&nod1, n, Z);
|
||||
cgen(n, &nod1);
|
||||
cgen(&nod1, &nod0);
|
||||
regfree(&nod0);
|
||||
regfree(&nod1);
|
||||
} else {
|
||||
regalloc(&nod1, n, Z);
|
||||
cgen(n, &nod1);
|
||||
cgen(&nod1, nn);
|
||||
regfree(&nod1);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
nnsaved = 0;
|
||||
curs = cursafe;
|
||||
o = n->op;
|
||||
l = n->left;
|
||||
r = n->right;
|
||||
switch(o){
|
||||
default:
|
||||
return 0;
|
||||
|
||||
case OCAST:
|
||||
if(typeilp[n->type->etype] && typev[l->type->etype]){
|
||||
if(l->op == ONAME || l->op == OINDREG)
|
||||
nod0 = *l;
|
||||
else if((l->op == OLSHR || l->op == OASHR)
|
||||
&& (l->right->op == OCONST && l->right->vconst == 32)
|
||||
&& (l->left->op == ONAME || l->left->op == OINDREG)){
|
||||
nod0 = *l->left;
|
||||
nod0.xoffset += SZ_LONG;
|
||||
} else {
|
||||
if(nn->complex > l->complex){
|
||||
reglpcgen(&nod0, nn, 1);
|
||||
regalloc(&nod1, l, Z);
|
||||
cgen(l, &nod1);
|
||||
cgen(nod1.left, &nod0);
|
||||
regfree(&nod0);
|
||||
regfree(&nod1);
|
||||
} else {
|
||||
regalloc(&nod0, l, Z);
|
||||
cgen(l, &nod0);
|
||||
cgen(nod0.left, nn);
|
||||
regfree(&nod0);
|
||||
}
|
||||
goto Out;
|
||||
}
|
||||
nod0.type = n->type;
|
||||
cgen(&nod0, nn);
|
||||
goto Out;
|
||||
}
|
||||
if(typev[n->type->etype] && typeilp[l->type->etype]){
|
||||
regalloc(&nod1, l, nn->left);
|
||||
a = reg[nn->right->reg];
|
||||
reg[nn->right->reg] = 0;
|
||||
cgen(l, &nod1);
|
||||
reg[nn->right->reg] = a;
|
||||
if(typeu[n->type->etype] || typeu[l->type->etype])
|
||||
gmove(nodconst(0), nn->right);
|
||||
else
|
||||
gopcode(OASHR, nodconst(31), &nod1, nn->right);
|
||||
regfree(&nod1);
|
||||
goto Out;
|
||||
}
|
||||
return 0;
|
||||
|
||||
case OASASHL: o = OASHL; goto asop;
|
||||
case OASASHR: o = OASHR; goto asop;
|
||||
case OASLSHR: o = OLSHR; goto asop;
|
||||
|
||||
case OASADD: o = OADD; goto asop;
|
||||
case OASSUB: o = OSUB; goto asop;
|
||||
case OASAND: o = OAND; goto asop;
|
||||
case OASXOR: o = OXOR; goto asop;
|
||||
case OASOR: o = OOR; goto asop;
|
||||
asop:
|
||||
nod0 = *n;
|
||||
nod0.op = o;
|
||||
nod0.left = &nod1;
|
||||
nod1 = *l;
|
||||
if(side(l)){
|
||||
nod1.op = OIND;
|
||||
nod1.left = &nod3;
|
||||
nod1.right = Z;
|
||||
nod1.complex = 1;
|
||||
|
||||
nod1.type = typ(TIND, l->type);
|
||||
regsalloc(&nod3, &nod1);
|
||||
nod1.type = l->type;
|
||||
|
||||
regalloc(&nod2, &nod3, nn != Z ? nn->left : Z);
|
||||
lcgen(l, &nod2);
|
||||
gmove(&nod2, &nod3);
|
||||
regfree(&nod2);
|
||||
}
|
||||
if(nn == Z)
|
||||
cgen(&nod0, &nod1);
|
||||
else {
|
||||
cgen(&nod0, nn);
|
||||
cgen(nn, &nod1);
|
||||
}
|
||||
goto Out;
|
||||
|
||||
case OASHL:
|
||||
cgen(l, nn);
|
||||
assert(r->op == OCONST);
|
||||
a = r->vconst & 63;
|
||||
if(a == 0)
|
||||
goto Out;
|
||||
if(a == 1){
|
||||
gins(AADD, nn->left, nn->left);
|
||||
p->scond |= C_SBIT;
|
||||
gins(AADC, nn->right, nn->right);
|
||||
goto Out;
|
||||
}
|
||||
if(a < 32){
|
||||
gopcode(OASHL, nodconst(a), Z, nn->right);
|
||||
gopcode(OOR, nn->left, Z, nn->right);
|
||||
p->from.offset = nn->left->reg | (32-a)<<7 | 1<<5;
|
||||
p->from.reg = NREG;
|
||||
p->from.type = D_SHIFT;
|
||||
gopcode(OASHL, nodconst(a), Z, nn->left);
|
||||
goto Out;
|
||||
}
|
||||
if(a == 32)
|
||||
gmove(nn->left, nn->right);
|
||||
else
|
||||
gopcode(o, nodconst(a-32), nn->left, nn->right);
|
||||
gmove(nodconst(0), nn->left);
|
||||
goto Out;
|
||||
|
||||
case OLSHR:
|
||||
case OASHR:
|
||||
cgen(l, nn);
|
||||
assert(r->op == OCONST);
|
||||
a = r->vconst & 63;
|
||||
if(a == 0)
|
||||
goto Out;
|
||||
if(a < 32){
|
||||
gopcode(OLSHR, nodconst(a), Z, nn->left);
|
||||
gopcode(OOR, nn->right, Z, nn->left);
|
||||
p->from.offset = nn->right->reg | (32-a)<<7;
|
||||
p->from.reg = NREG;
|
||||
p->from.type = D_SHIFT;
|
||||
gopcode(o, nodconst(a), Z, nn->right);
|
||||
goto Out;
|
||||
}
|
||||
if(a == 32)
|
||||
gmove(nn->right, nn->left);
|
||||
else
|
||||
gopcode(o, nodconst(a-32), nn->right, nn->left);
|
||||
if(o == OASHR)
|
||||
gopcode(o, nodconst(31), Z, nn->right);
|
||||
else
|
||||
gmove(nodconst(0), nn->right);
|
||||
goto Out;
|
||||
|
||||
case OADD:
|
||||
case OSUB:
|
||||
case OAND:
|
||||
case OXOR:
|
||||
case OOR:
|
||||
ml = o == OADD && l->op == OLMUL && machcap(l);
|
||||
mr = o == OADD && r->op == OLMUL && machcap(r);
|
||||
if(ml && !mr){
|
||||
cgen(r, nn);
|
||||
n = l;
|
||||
} else if(mr && !ml){
|
||||
cgen(l, nn);
|
||||
n = r;
|
||||
} else {
|
||||
if(r->complex > l->complex){
|
||||
cgen(r, nn);
|
||||
n = l;
|
||||
} else {
|
||||
cgen(l, nn);
|
||||
n = r;
|
||||
}
|
||||
}
|
||||
if(n->complex >= FNX){
|
||||
regsalloc(&nod0, nn);
|
||||
gmove(nn, &nod0);
|
||||
nnsaved = 1;
|
||||
}
|
||||
if(ml || mr){
|
||||
l = n->left;
|
||||
r = n->right;
|
||||
a = AMULALU;
|
||||
break;
|
||||
}
|
||||
regalloc(&nod1, n, Z);
|
||||
if(nnsaved) freepair(nn);
|
||||
cgen(n, &nod1);
|
||||
if(nnsaved){
|
||||
unfreepair(nn);
|
||||
gmove(&nod0, nn);
|
||||
}
|
||||
|
||||
switch(o){
|
||||
case OADD:
|
||||
gins(AADD, nod1.left, nn->left);
|
||||
p->scond |= C_SBIT;
|
||||
gins(AADC, nod1.right, nn->right);
|
||||
break;
|
||||
case OSUB:
|
||||
if(n == r){
|
||||
gins(ASUB, nod1.left, nn->left);
|
||||
p->scond |= C_SBIT;
|
||||
gins(ASBC, nod1.right, nn->right);
|
||||
} else {
|
||||
gins(ASUB, nn->left, nn->left);
|
||||
p->reg = nod1.left->reg;
|
||||
p->scond |= C_SBIT;
|
||||
gins(ASBC, nn->right, nn->right);
|
||||
p->reg = nod1.right->reg;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
gopcode(o, nod1.left, Z, nn->left);
|
||||
gopcode(o, nod1.right, Z, nn->right);
|
||||
}
|
||||
regfree(&nod1);
|
||||
goto Out;
|
||||
|
||||
case OMUL:
|
||||
a = AMULL;
|
||||
break;
|
||||
|
||||
case OLMUL:
|
||||
a = AMULLU;
|
||||
break;
|
||||
}
|
||||
|
||||
if(r->complex > l->complex) {
|
||||
l = r;
|
||||
r = n->left;
|
||||
}
|
||||
|
||||
regalloc(&nod1, l, Z);
|
||||
if(nnsaved) freepair(nn);
|
||||
cgen(l, &nod1);
|
||||
if(nnsaved) unfreepair(nn);
|
||||
if(r->complex >= FNX) {
|
||||
regsalloc(&nod3, &nod1);
|
||||
gmove(&nod1, &nod3);
|
||||
if(nnsaved) freepair(nn);
|
||||
cgen(r, &nod1);
|
||||
if(nnsaved) unfreepair(nn);
|
||||
regalloc(&nod2, &nod3, Z);
|
||||
gmove(&nod3, &nod2);
|
||||
} else {
|
||||
regalloc(&nod2, r, Z);
|
||||
if(nnsaved) freepair(nn);
|
||||
cgen(r, &nod2);
|
||||
if(nnsaved) unfreepair(nn);
|
||||
}
|
||||
if(nnsaved)
|
||||
gmove(&nod0, nn);
|
||||
|
||||
gins(a, &nod1, nn->right);
|
||||
p->reg = nod2.reg;
|
||||
p->to.type = D_REGREG;
|
||||
p->to.offset = nn->left->reg;
|
||||
|
||||
regfree(&nod1);
|
||||
regfree(&nod2);
|
||||
|
||||
Out:
|
||||
cursafe = curs;
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
sugen(Node *n, Node *nn, long w)
|
||||
{
|
||||
Prog *p1;
|
||||
Node nod0, nod1, nod2, nod3, nod4, *l, *r;
|
||||
Node nod0, nod1, nod2, nod3, nod4, *l, *r, *d;
|
||||
Type *t;
|
||||
long pc1;
|
||||
int i, m, c;
|
||||
|
@ -893,11 +1207,13 @@ sugen(Node *n, Node *nn, long w)
|
|||
break;
|
||||
}
|
||||
|
||||
t = nn->type;
|
||||
nn->type = types[TLONG];
|
||||
reglcgen(&nod1, nn, Z);
|
||||
nn->type = t;
|
||||
if(nn->op == OREGPAIR){
|
||||
gopcode(OAS, nod32const(n->vconst), Z, nn->left);
|
||||
gopcode(OAS, nod32const(n->vconst>>32), Z, nn->right);
|
||||
break;
|
||||
}
|
||||
|
||||
reglpcgen(&nod1, nn, 1);
|
||||
if(align(0, types[TCHAR], Aarg1)) /* isbigendian */
|
||||
gopcode(OAS, nod32const(n->vconst>>32), Z, &nod1);
|
||||
else
|
||||
|
@ -907,7 +1223,6 @@ sugen(Node *n, Node *nn, long w)
|
|||
gopcode(OAS, nod32const(n->vconst), Z, &nod1);
|
||||
else
|
||||
gopcode(OAS, nod32const(n->vconst>>32), Z, &nod1);
|
||||
|
||||
regfree(&nod1);
|
||||
break;
|
||||
}
|
||||
|
@ -1021,16 +1336,27 @@ sugen(Node *n, Node *nn, long w)
|
|||
break;
|
||||
}
|
||||
if(nn->op != OIND) {
|
||||
nn = new1(OADDR, nn, Z);
|
||||
nn->type = types[TIND];
|
||||
nn->addable = 0;
|
||||
if(nn->op == OREGPAIR) {
|
||||
regsalloc(&nod1, nn);
|
||||
d = &nod1;
|
||||
}else
|
||||
d = nn;
|
||||
d = new1(OADDR, d, Z);
|
||||
d->type = types[TIND];
|
||||
d->addable = 0;
|
||||
} else
|
||||
nn = nn->left;
|
||||
n = new(OFUNC, n->left, new(OLIST, nn, n->right));
|
||||
d = nn->left;
|
||||
n = new(OFUNC, n->left, new(OLIST, d, n->right));
|
||||
n->complex = FNX;
|
||||
n->type = types[TVOID];
|
||||
n->left->type = types[TVOID];
|
||||
cgen(n, Z);
|
||||
if(nn->op == OREGPAIR){
|
||||
freepair(nn);
|
||||
cgen(n, Z);
|
||||
unfreepair(nn);
|
||||
gmove(&nod1, nn);
|
||||
} else
|
||||
cgen(n, Z);
|
||||
break;
|
||||
|
||||
case OCOND:
|
||||
|
@ -1052,8 +1378,7 @@ sugen(Node *n, Node *nn, long w)
|
|||
return;
|
||||
|
||||
copy:
|
||||
if(nn == Z)
|
||||
return;
|
||||
if(nn != Z)
|
||||
if(n->complex >= FNX && nn->complex >= FNX) {
|
||||
t = nn->type;
|
||||
nn->type = types[TLONG];
|
||||
|
@ -1079,43 +1404,39 @@ copy:
|
|||
}
|
||||
|
||||
w /= SZ_LONG;
|
||||
if(w <= 2) {
|
||||
if(w == 2 && cgen64(n, nn))
|
||||
return;
|
||||
|
||||
if(nn == Z)
|
||||
return;
|
||||
|
||||
if(w == 2) {
|
||||
if(n->complex > nn->complex) {
|
||||
reglpcgen(&nod1, n, 1);
|
||||
reglpcgen(&nod2, nn, 1);
|
||||
if(n->op != OREGPAIR && n->op != ONAME && n->op != OINDREG)
|
||||
reglpcgen(&nod1, n, 1);
|
||||
else
|
||||
nod1 = *n;
|
||||
if(nn->op != OREGPAIR && nn->op != ONAME && nn->op != OINDREG)
|
||||
reglpcgen(&nod2, nn, 1);
|
||||
else
|
||||
nod2 = *nn;
|
||||
} else {
|
||||
reglpcgen(&nod2, nn, 1);
|
||||
reglpcgen(&nod1, n, 1);
|
||||
if(nn->op != OREGPAIR && nn->op != ONAME && nn->op != OINDREG)
|
||||
reglpcgen(&nod2, nn, 1);
|
||||
else
|
||||
nod2 = *nn;
|
||||
if(n->op != OREGPAIR && n->op != ONAME && n->op != OINDREG)
|
||||
reglpcgen(&nod1, n, 1);
|
||||
else
|
||||
nod1 = *n;
|
||||
}
|
||||
regalloc(&nod3, ®node, Z);
|
||||
regalloc(&nod4, ®node, Z);
|
||||
if(nod3.reg > nod4.reg){
|
||||
/* code below assumes nod3 loaded first */
|
||||
Node t = nod3; nod3 = nod4; nod4 = t;
|
||||
}
|
||||
nod0 = *nodconst((1<<nod3.reg)|(1<<nod4.reg));
|
||||
if(w == 2 && nod1.xoffset == 0)
|
||||
gmovm(&nod1, &nod0, 0);
|
||||
else {
|
||||
gmove(&nod1, &nod3);
|
||||
if(w == 2) {
|
||||
nod1.xoffset += SZ_LONG;
|
||||
gmove(&nod1, &nod4);
|
||||
}
|
||||
}
|
||||
if(w == 2 && nod2.xoffset == 0)
|
||||
gmovm(&nod0, &nod2, 0);
|
||||
else {
|
||||
gmove(&nod3, &nod2);
|
||||
if(w == 2) {
|
||||
nod2.xoffset += SZ_LONG;
|
||||
gmove(&nod4, &nod2);
|
||||
}
|
||||
}
|
||||
regfree(&nod1);
|
||||
regfree(&nod2);
|
||||
regfree(&nod3);
|
||||
regfree(&nod4);
|
||||
nod1.type = types[TVLONG];
|
||||
nod2.type = types[TVLONG];
|
||||
gmove(&nod1, &nod2);
|
||||
if(n->op != OREGPAIR && n->op != ONAME && n->op != OINDREG)
|
||||
regfree(&nod1);
|
||||
if(nn->op != OREGPAIR && nn->op != ONAME && nn->op != OINDREG)
|
||||
regfree(&nod2);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -226,6 +226,7 @@ void bcgen(Node*, int);
|
|||
void boolgen(Node*, int, Node*);
|
||||
void sugen(Node*, Node*, long);
|
||||
void layout(Node*, Node*, int, int, Node*);
|
||||
int cgen64(Node*, Node*);
|
||||
|
||||
/*
|
||||
* txt.c
|
||||
|
|
|
@ -64,6 +64,9 @@ Pconv(Fmt *fp)
|
|||
strcat(sc, ".W");
|
||||
if(s & C_UBIT) /* ambiguous with FBIT */
|
||||
strcat(sc, ".U");
|
||||
if(a == AMULL || a == AMULAL || a == AMULLU || a == AMULALU)
|
||||
snprint(str, sizeof str, " %A%s %D,R%d,%D", a, sc, &p->from, p->reg, &p->to);
|
||||
else
|
||||
if(a == AMOVM) {
|
||||
if(p->from.type == D_CONST)
|
||||
snprint(str, sizeof str, " %A%s %R,%D", a, sc, &p->from, &p->to);
|
||||
|
@ -148,6 +151,10 @@ Dconv(Fmt *fp)
|
|||
snprint(str, sizeof str, "%N", a);
|
||||
break;
|
||||
|
||||
case D_REGREG:
|
||||
snprint(str, sizeof str, "(R%d,R%d)", a->reg, (char)a->offset);
|
||||
break;
|
||||
|
||||
case D_REG:
|
||||
snprint(str, sizeof str, "R%d", a->reg);
|
||||
if(a->name != D_NONE || a->sym != S)
|
||||
|
|
49
sys/src/cmd/5c/machcap.c
Normal file
49
sys/src/cmd/5c/machcap.c
Normal file
|
@ -0,0 +1,49 @@
|
|||
#include "gc.h"
|
||||
|
||||
int
|
||||
machcap(Node *n)
|
||||
{
|
||||
if(n == Z)
|
||||
return 0; /* test */
|
||||
switch(n->op) {
|
||||
case OASADD:
|
||||
case OASSUB:
|
||||
case OASAND:
|
||||
case OASXOR:
|
||||
case OASOR:
|
||||
case OADD:
|
||||
case OSUB:
|
||||
case OAND:
|
||||
case OXOR:
|
||||
case OOR:
|
||||
if(typev[n->type->etype] && typev[n->left->type->etype] && typev[n->right->type->etype])
|
||||
return 1;
|
||||
break;
|
||||
|
||||
case OMUL:
|
||||
case OLMUL:
|
||||
if(typev[n->type->etype] && typeil[n->left->type->etype] && typeil[n->right->type->etype]
|
||||
&& typeu[n->type->etype] == typeu[n->left->type->etype]
|
||||
&& typeu[n->type->etype] == typeu[n->right->type->etype])
|
||||
return 1;
|
||||
break;
|
||||
|
||||
case OASASHL:
|
||||
case OASASHR:
|
||||
case OASLSHR:
|
||||
case OASHL:
|
||||
case OASHR:
|
||||
case OLSHR:
|
||||
if(typev[n->type->etype] && typev[n->left->type->etype] && n->right->op == OCONST)
|
||||
return 1;
|
||||
break;
|
||||
|
||||
case OCAST:
|
||||
if(typeilp[n->type->etype] && typev[n->left->type->etype])
|
||||
return 1;
|
||||
if(typev[n->type->etype] && typeilp[n->left->type->etype])
|
||||
return 1;
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
|
@ -13,6 +13,7 @@ OFILES=\
|
|||
sgen.$O\
|
||||
swt.$O\
|
||||
txt.$O\
|
||||
machcap.$O\
|
||||
|
||||
HFILES=\
|
||||
gc.h\
|
||||
|
|
|
@ -249,7 +249,6 @@ uniqs(Reg *r)
|
|||
int
|
||||
regtyp(Adr *a)
|
||||
{
|
||||
|
||||
if(a->type == D_REG)
|
||||
return 1;
|
||||
if(a->type == D_FREG)
|
||||
|
@ -302,6 +301,7 @@ subprop(Reg *r0)
|
|||
case ASLL:
|
||||
case ASRL:
|
||||
case ASRA:
|
||||
case AROR:
|
||||
case AORR:
|
||||
case AAND:
|
||||
case AEOR:
|
||||
|
@ -888,6 +888,25 @@ copyu(Prog *p, Adr *v, Adr *s)
|
|||
print(" (???)");
|
||||
return 2;
|
||||
|
||||
case AMULL:
|
||||
case AMULAL:
|
||||
case AMULLU:
|
||||
case AMULALU:
|
||||
if(v->type != D_REG)
|
||||
return 0;
|
||||
if(copyau(&p->to, v))
|
||||
return (p->as == AMULAL || p->as == AMULALU) ? 2 : 3;
|
||||
if(p->from.reg == v->reg || p->reg == v->reg){
|
||||
if(s != A && !copyau(&p->to, s) && p->from.reg != s->reg && p->reg != s->reg){
|
||||
if(p->from.reg == v->reg)
|
||||
p->from.reg = s->reg;
|
||||
if(p->reg == v->reg)
|
||||
p->reg = s->reg;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
|
||||
case AMOVM:
|
||||
if(v->type != D_REG)
|
||||
return 0;
|
||||
|
@ -974,6 +993,7 @@ copyu(Prog *p, Adr *v, Adr *s)
|
|||
case ASLL:
|
||||
case ASRL:
|
||||
case ASRA:
|
||||
case AROR:
|
||||
case AORR:
|
||||
case AAND:
|
||||
case AEOR:
|
||||
|
@ -1110,6 +1130,7 @@ a2type(Prog *p)
|
|||
case ASLL:
|
||||
case ASRL:
|
||||
case ASRA:
|
||||
case AROR:
|
||||
case AORR:
|
||||
case AAND:
|
||||
case AEOR:
|
||||
|
@ -1170,13 +1191,16 @@ copyau(Adr *a, Adr *v)
|
|||
return 1;
|
||||
if(v->type == D_REG) {
|
||||
if(a->type == D_OREG) {
|
||||
if(v->reg == a->reg)
|
||||
if(a->reg == v->reg)
|
||||
return 1;
|
||||
} else if(a->type == D_SHIFT) {
|
||||
if((a->offset&0xf) == v->reg)
|
||||
return 1;
|
||||
if((a->offset&(1<<4)) && (a->offset>>8) == v->reg)
|
||||
return 1;
|
||||
} else if(a->type == D_REGREG) {
|
||||
if(a->reg == v->reg || a->offset == v->reg)
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
@ -1212,7 +1236,12 @@ copysub(Adr *a, Adr *v, Adr *s, int f)
|
|||
a->offset = (a->offset&~0xf)|s->reg;
|
||||
if((a->offset&(1<<4)) && (a->offset>>8) == v->reg)
|
||||
a->offset = (a->offset&~(0xf<<8))|(s->reg<<8);
|
||||
} else
|
||||
} else if(a->type == D_REGREG) {
|
||||
if(a->offset == v->reg)
|
||||
a->offset = s->reg;
|
||||
if(a->reg == v->reg)
|
||||
a->reg = s->reg;
|
||||
} else
|
||||
a->reg = s->reg;
|
||||
}
|
||||
return 0;
|
||||
|
|
|
@ -109,6 +109,25 @@ xcom(Node *n)
|
|||
|
||||
case OMUL:
|
||||
case OLMUL:
|
||||
if(typev[n->type->etype]){
|
||||
/* try to lift 32->64 bit cast */
|
||||
if(typev[l->type->etype] && l->op == OCAST && typeil[l->left->type->etype]
|
||||
&& typeu[n->type->etype] == typeu[l->left->type->etype])
|
||||
l = l->left;
|
||||
if(typev[r->type->etype] && r->op == OCAST && typeil[r->left->type->etype]
|
||||
&& typeu[n->type->etype] == typeu[r->left->type->etype])
|
||||
r = r->left;
|
||||
|
||||
if(typeil[l->type->etype] && typeil[r->type->etype]){
|
||||
n->left = l;
|
||||
n->right = r;
|
||||
xcom(l);
|
||||
xcom(r);
|
||||
break;
|
||||
}
|
||||
l = n->left;
|
||||
r = n->right;
|
||||
}
|
||||
xcom(l);
|
||||
xcom(r);
|
||||
t = vlog(r);
|
||||
|
@ -123,7 +142,6 @@ xcom(Node *n)
|
|||
n->left = r;
|
||||
n->right = l;
|
||||
r = l;
|
||||
l = n->left;
|
||||
r->vconst = t;
|
||||
r->type = types[TINT];
|
||||
}
|
||||
|
@ -171,6 +189,13 @@ xcom(Node *n)
|
|||
}
|
||||
break;
|
||||
|
||||
case OOR:
|
||||
xcom(l);
|
||||
xcom(r);
|
||||
if(typeil[n->type->etype])
|
||||
rolor(n);
|
||||
break;
|
||||
|
||||
default:
|
||||
if(l != Z)
|
||||
xcom(l);
|
||||
|
@ -180,7 +205,8 @@ xcom(Node *n)
|
|||
}
|
||||
if(n->addable >= 10)
|
||||
return;
|
||||
|
||||
l = n->left;
|
||||
r = n->right;
|
||||
if(l != Z)
|
||||
n->complex = l->complex;
|
||||
if(r != Z) {
|
||||
|
|
|
@ -523,6 +523,10 @@ zaddr(char *bp, Adr *a, int s)
|
|||
case D_PSR:
|
||||
break;
|
||||
|
||||
case D_REGREG:
|
||||
*bp++ = a->offset;
|
||||
break;
|
||||
|
||||
case D_OREG:
|
||||
case D_CONST:
|
||||
case D_BRANCH:
|
||||
|
|
|
@ -297,6 +297,7 @@ regalloc(Node *n, Node *tn, Node *o)
|
|||
j = REGRET+1;
|
||||
if(reg[j] == 0 && resvreg[j] == 0) {
|
||||
i = j;
|
||||
lasti = (i - REGRET) % 3;
|
||||
goto out;
|
||||
}
|
||||
j++;
|
||||
|
@ -306,7 +307,6 @@ regalloc(Node *n, Node *tn, Node *o)
|
|||
|
||||
case TFLOAT:
|
||||
case TDOUBLE:
|
||||
case TVLONG:
|
||||
if(o != Z && o->op == OREGISTER) {
|
||||
i = o->reg;
|
||||
if(i >= NREG && i < NREG+NFREG)
|
||||
|
@ -324,6 +324,32 @@ regalloc(Node *n, Node *tn, Node *o)
|
|||
}
|
||||
diag(tn, "out of float registers");
|
||||
goto err;
|
||||
|
||||
case TVLONG:
|
||||
case TUVLONG:
|
||||
n->op = OREGPAIR;
|
||||
n->complex = 0; /* already in registers */
|
||||
n->addable = 11;
|
||||
n->type = tn->type;
|
||||
n->lineno = nearln;
|
||||
n->left = alloc(sizeof(Node));
|
||||
n->right = alloc(sizeof(Node));
|
||||
if(o != Z && o->op == OREGPAIR) {
|
||||
regalloc(n->left, ®node, o->left);
|
||||
regalloc(n->right, ®node, o->right);
|
||||
} else {
|
||||
regalloc(n->left, ®node, Z);
|
||||
regalloc(n->right, ®node, Z);
|
||||
}
|
||||
if(n->left->reg > n->right->reg){
|
||||
j = n->left->reg;
|
||||
n->left->reg = n->right->reg;
|
||||
n->right->reg = j;
|
||||
}
|
||||
n->right->type = types[TULONG];
|
||||
if(tn->type->etype == TUVLONG)
|
||||
n->left->type = types[TULONG];
|
||||
return;
|
||||
}
|
||||
diag(tn, "unknown type in regalloc: %T", tn->type);
|
||||
err:
|
||||
|
@ -331,9 +357,6 @@ err:
|
|||
return;
|
||||
out:
|
||||
reg[i]++;
|
||||
lasti++;
|
||||
if(lasti >= 5)
|
||||
lasti = 0;
|
||||
nodreg(n, tn, i);
|
||||
}
|
||||
|
||||
|
@ -352,6 +375,11 @@ regfree(Node *n)
|
|||
{
|
||||
int i;
|
||||
|
||||
if(n->op == OREGPAIR) {
|
||||
regfree(n->left);
|
||||
regfree(n->right);
|
||||
return;
|
||||
}
|
||||
i = 0;
|
||||
if(n->op != OREGISTER && n->op != OINDREG)
|
||||
goto err;
|
||||
|
@ -604,11 +632,30 @@ gmove(Node *f, Node *t)
|
|||
a = AMOVHU;
|
||||
break;
|
||||
}
|
||||
if(typechlp[ft] && typeilp[tt])
|
||||
regalloc(&nod, t, t);
|
||||
else
|
||||
regalloc(&nod, f, t);
|
||||
gins(a, f, &nod);
|
||||
if(typev[ft]) {
|
||||
if(typev[tt]) {
|
||||
nod1 = *f;
|
||||
regalloc(&nod, f, t);
|
||||
if(f->op == OINDREG && f->xoffset == 0 && nod.left->reg < nod.right->reg) {
|
||||
gmovm(&nod1, nodconst((1<<nod.left->reg)|(1<<nod.right->reg)), 0);
|
||||
} else {
|
||||
/* low order first, because its value will be used first */
|
||||
gins(AMOVW, &nod1, nod.left);
|
||||
nod1.xoffset += SZ_LONG;
|
||||
gins(AMOVW, &nod1, nod.right);
|
||||
}
|
||||
} else {
|
||||
/* assumed not float or double */
|
||||
regalloc(&nod, ®node, t);
|
||||
gins(AMOVW, f, &nod);
|
||||
}
|
||||
} else {
|
||||
if(typechlp[ft] && typeilp[tt])
|
||||
regalloc(&nod, t, t);
|
||||
else
|
||||
regalloc(&nod, f, t);
|
||||
gins(a, f, &nod);
|
||||
}
|
||||
gmove(&nod, t);
|
||||
regfree(&nod);
|
||||
return;
|
||||
|
@ -639,7 +686,6 @@ gmove(Node *f, Node *t)
|
|||
case TFLOAT:
|
||||
a = AMOVF;
|
||||
break;
|
||||
case TVLONG:
|
||||
case TDOUBLE:
|
||||
a = AMOVD;
|
||||
break;
|
||||
|
@ -649,7 +695,17 @@ gmove(Node *f, Node *t)
|
|||
else
|
||||
regalloc(&nod, t, Z);
|
||||
gmove(f, &nod);
|
||||
gins(a, &nod, t);
|
||||
if(typev[tt]) {
|
||||
nod1 = *t;
|
||||
if(t->op == OINDREG && t->xoffset == 0 && nod.left->reg < nod.right->reg){
|
||||
gmovm(nodconst((1<<nod.left->reg)|(1<<nod.right->reg)), &nod1, 0);
|
||||
} else {
|
||||
gins(a, nod.left, &nod1);
|
||||
nod1.xoffset += SZ_LONG;
|
||||
gins(a, nod.right, &nod1);
|
||||
}
|
||||
} else
|
||||
gins(a, &nod, t);
|
||||
regfree(&nod);
|
||||
return;
|
||||
}
|
||||
|
@ -660,7 +716,6 @@ gmove(Node *f, Node *t)
|
|||
a = AGOK;
|
||||
switch(ft) {
|
||||
case TDOUBLE:
|
||||
case TVLONG:
|
||||
case TFLOAT:
|
||||
switch(tt) {
|
||||
case TDOUBLE:
|
||||
|
@ -876,13 +931,28 @@ gmove(Node *f, Node *t)
|
|||
break;
|
||||
}
|
||||
break;
|
||||
case TVLONG:
|
||||
case TUVLONG:
|
||||
switch(tt) {
|
||||
case TVLONG:
|
||||
case TUVLONG:
|
||||
a = AMOVW;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if(a == AGOK)
|
||||
diag(Z, "bad opcode in gmove %T -> %T", f->type, t->type);
|
||||
if(a == AMOVW || a == AMOVF || a == AMOVD)
|
||||
if(samaddr(f, t))
|
||||
return;
|
||||
gins(a, f, t);
|
||||
if(typev[ft]) {
|
||||
if(f->op != OREGPAIR || t->op != OREGPAIR)
|
||||
diag(Z, "bad vlong in gmove (%O->%O)", f->op, t->op);
|
||||
gins(a, f->left, t->left);
|
||||
gins(a, f->right, t->right);
|
||||
} else
|
||||
gins(a, f, t);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -1002,6 +1072,12 @@ gopcode(int o, Node *f1, Node *f2, Node *t)
|
|||
a = ASLL;
|
||||
break;
|
||||
|
||||
case OROL:
|
||||
assert(f1->op == OCONST);
|
||||
f1->vconst = 32-f1->vconst;
|
||||
a = AROR;
|
||||
break;
|
||||
|
||||
case OFUNC:
|
||||
a = ABL;
|
||||
break;
|
||||
|
@ -1151,6 +1227,9 @@ samaddr(Node *f, Node *t)
|
|||
if(f->reg != t->reg)
|
||||
break;
|
||||
return 1;
|
||||
|
||||
case OREGPAIR:
|
||||
return samaddr(f->left, t->left) && samaddr(f->right, t->right);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue