6c, 8c: fix "DI botch" evacuating DI/SI/CX registers to ".save" variables

This commit is contained in:
cinap_lenrek 2017-01-02 05:49:18 +01:00
parent 8547defe70
commit 19dc7c2097
2 changed files with 146 additions and 141 deletions

View file

@ -1396,7 +1396,7 @@ sugen(Node *n, Node *nn, long w)
Prog *p1; Prog *p1;
Node nod0, nod1, nod2, nod3, nod4, *l, *r; Node nod0, nod1, nod2, nod3, nod4, *l, *r;
Type *t; Type *t;
int c, mt, mo; int v, c, mt, mo;
vlong o0, o1; vlong o0, o1;
if(n == Z || n->type == T) if(n == Z || n->type == T)
@ -1615,8 +1615,8 @@ copy:
return; return;
} }
c = cursafe;
if(w <= 32) { if(w <= 32) {
c = cursafe;
if(n->left != Z && n->left->complex >= FNX if(n->left != Z && n->left->complex >= FNX
&& n->right != Z && n->right->complex >= FNX) { && n->right != Z && n->right->complex >= FNX) {
regsalloc(&nod1, n->right); regsalloc(&nod1, n->right);
@ -1696,77 +1696,84 @@ copy:
return; return;
} }
/* botch, need to save in .safe */ t = n->type;
c = 0; if(t != types[TIND]){
if(n->complex > nn->complex) {
t = n->type;
n->type = types[TIND]; n->type = types[TIND];
nodreg(&nod1, n, D_SI); sugen(n, nn, w);
if(reg[D_SI]) {
gins(APUSHQ, &nod1, Z);
c |= 1;
reg[D_SI]++;
}
lcgen(n, &nod1);
n->type = t; n->type = t;
return;
t = nn->type; }
t = nn->type;
if(t != types[TIND]){
nn->type = types[TIND]; nn->type = types[TIND];
nodreg(&nod2, nn, D_DI); sugen(n, nn, w);
if(reg[D_DI]) {
warn(Z, "DI botch");
gins(APUSHQ, &nod2, Z);
c |= 2;
reg[D_DI]++;
}
lcgen(nn, &nod2);
nn->type = t; nn->type = t;
return;
}
if(nodreg(&nod1, n, D_SI)) {
regsalloc(&nod4, &nod1);
gmove(&nod1, &nod4);
v = reg[D_SI];
reg[D_SI] = 0;
sugen(n, nn, w);
reg[D_SI] = v;
gmove(&nod4, &nod1);
cursafe = c;
return;
}
if(nodreg(&nod2, nn, D_DI)) {
regsalloc(&nod4, &nod2);
gmove(&nod2, &nod4);
v = reg[D_DI];
reg[D_DI] = 0;
sugen(n, nn, w);
reg[D_DI] = v;
gmove(&nod4, &nod2);
cursafe = c;
return;
}
if(nodreg(&nod3, Z, D_CX)) {
regsalloc(&nod4, &nod3);
gmove(&nod3, &nod4);
v = reg[D_CX];
reg[D_CX] = 0;
sugen(n, nn, w);
reg[D_CX] = v;
gmove(&nod4, &nod3);
cursafe = c;
return;
}
if(n->complex > nn->complex){
reg[nod1.reg]++;
lcgen(n, &nod1);
reg[nod2.reg]++;
lcgen(nn, &nod2);
} else { } else {
t = nn->type; reg[nod2.reg]++;
nn->type = types[TIND];
nodreg(&nod2, nn, D_DI);
if(reg[D_DI]) {
warn(Z, "DI botch");
gins(APUSHQ, &nod2, Z);
c |= 2;
reg[D_DI]++;
}
lcgen(nn, &nod2); lcgen(nn, &nod2);
nn->type = t;
t = n->type; reg[nod1.reg]++;
n->type = types[TIND];
nodreg(&nod1, n, D_SI);
if(reg[D_SI]) {
gins(APUSHQ, &nod1, Z);
c |= 1;
reg[D_SI]++;
}
lcgen(n, &nod1); lcgen(n, &nod1);
n->type = t;
} }
nodreg(&nod3, n, D_CX); reg[nod3.reg]++;
if(reg[D_CX]) {
gins(APUSHQ, &nod3, Z); gins(AMOVL, nodconst(w/SZ_LONG), &nod3);
c |= 4;
reg[D_CX]++;
}
gins(AMOVL, nodconst(w/SZ_INT), &nod3);
gins(ACLD, Z, Z); gins(ACLD, Z, Z);
gins(AREP, Z, Z); gins(AREP, Z, Z);
gins(AMOVSL, Z, Z); gins(AMOVSL, Z, Z);
if(c & 4) { if(w & (SZ_LONG-1)) {
gins(APOPQ, Z, &nod3); /* odd length of packed structure */
reg[D_CX]--; gins(AMOVL, nodconst(w & (SZ_LONG-1)), &nod3);
} gins(AREP, Z, Z);
if(c & 2) { gins(AMOVSB, Z, Z);
gins(APOPQ, Z, &nod2);
reg[nod2.reg]--;
}
if(c & 1) {
gins(APOPQ, Z, &nod1);
reg[nod1.reg]--;
} }
reg[nod3.reg]--;
reg[nod2.reg]--;
reg[nod1.reg]--;
} }
/* /*

View file

@ -1687,11 +1687,10 @@ copy:
x = 0; x = 0;
v = w == 8; v = w == 8;
c = cursafe;
if(v) { if(v) {
c = cursafe;
if(n->left != Z && n->left->complex >= FNX if(n->left != Z && n->left->complex >= FNX
&& n->right != Z && n->right->complex >= FNX) { && n->right != Z && n->right->complex >= FNX) {
// warn(n, "toughie");
regsalloc(&nod1, n->right); regsalloc(&nod1, n->right);
cgen(n->right, &nod1); cgen(n->right, &nod1);
nod2 = *n; nod2 = *n;
@ -1708,14 +1707,10 @@ copy:
n = n->left; n = n->left;
x = 1; x = 1;
} }
}
/* botch, need to save in .safe */ if(n->complex > nn->complex){
c = 0; t = n->type;
if(n->complex > nn->complex) { n->type = types[TLONG];
t = n->type;
n->type = types[TLONG];
if(v) {
regalloc(&nod0, n, Z); regalloc(&nod0, n, Z);
if(!vaddr(n, 0)) { if(!vaddr(n, 0)) {
reglcgen(&nod1, n, Z); reglcgen(&nod1, n, Z);
@ -1724,21 +1719,9 @@ copy:
} }
else else
n->type = t; n->type = t;
}
else {
nodreg(&nod1, n, D_SI);
if(reg[D_SI]) {
gins(APUSHL, &nod1, Z);
c |= 1;
reg[D_SI]++;
}
lcgen(n, &nod1);
n->type = t;
}
t = nn->type; t = nn->type;
nn->type = types[TLONG]; nn->type = types[TLONG];
if(v) {
if(!vaddr(nn, 0)) { if(!vaddr(nn, 0)) {
reglcgen(&nod2, nn, Z); reglcgen(&nod2, nn, Z);
nn->type = t; nn->type = t;
@ -1746,21 +1729,9 @@ copy:
} }
else else
nn->type = t; nn->type = t;
} } else {
else { t = nn->type;
nodreg(&nod2, nn, D_DI); nn->type = types[TLONG];
if(reg[D_DI]) {
gins(APUSHL, &nod2, Z);
c |= 2;
reg[D_DI]++;
}
lcgen(nn, &nod2);
nn->type = t;
}
} else {
t = nn->type;
nn->type = types[TLONG];
if(v) {
regalloc(&nod0, nn, Z); regalloc(&nod0, nn, Z);
if(!vaddr(nn, 0)) { if(!vaddr(nn, 0)) {
reglcgen(&nod2, nn, Z); reglcgen(&nod2, nn, Z);
@ -1769,21 +1740,9 @@ copy:
} }
else else
nn->type = t; nn->type = t;
}
else {
nodreg(&nod2, nn, D_DI);
if(reg[D_DI]) {
gins(APUSHL, &nod2, Z);
c |= 2;
reg[D_DI]++;
}
lcgen(nn, &nod2);
nn->type = t;
}
t = n->type; t = n->type;
n->type = types[TLONG]; n->type = types[TLONG];
if(v) {
if(!vaddr(n, 0)) { if(!vaddr(n, 0)) {
reglcgen(&nod1, n, Z); reglcgen(&nod1, n, Z);
n->type = t; n->type = t;
@ -1792,18 +1751,6 @@ copy:
else else
n->type = t; n->type = t;
} }
else {
nodreg(&nod1, n, D_SI);
if(reg[D_SI]) {
gins(APUSHL, &nod1, Z);
c |= 1;
reg[D_SI]++;
}
lcgen(n, &nod1);
n->type = t;
}
}
if(v) {
gins(AMOVL, n, &nod0); gins(AMOVL, n, &nod0);
if(x) if(x)
gins(ANOTL, Z, &nod0); gins(ANOTL, Z, &nod0);
@ -1823,12 +1770,71 @@ copy:
regfree(&nod0); regfree(&nod0);
return; return;
} }
nodreg(&nod3, n, D_CX);
if(reg[D_CX]) { t = n->type;
gins(APUSHL, &nod3, Z); if(t != types[TIND]){
c |= 4; n->type = types[TIND];
reg[D_CX]++; sugen(n, nn, w);
n->type = t;
return;
} }
t = nn->type;
if(t != types[TIND]){
nn->type = types[TIND];
sugen(n, nn, w);
nn->type = t;
return;
}
if(nodreg(&nod1, n, D_SI)) {
regsalloc(&nod4, &nod1);
gmove(&nod1, &nod4);
v = reg[D_SI];
reg[D_SI] = 0;
sugen(n, nn, w);
reg[D_SI] = v;
gmove(&nod4, &nod1);
cursafe = c;
return;
}
if(nodreg(&nod2, nn, D_DI)) {
regsalloc(&nod4, &nod2);
gmove(&nod2, &nod4);
v = reg[D_DI];
reg[D_DI] = 0;
sugen(n, nn, w);
reg[D_DI] = v;
gmove(&nod4, &nod2);
cursafe = c;
return;
}
if(nodreg(&nod3, Z, D_CX)) {
regsalloc(&nod4, &nod3);
gmove(&nod3, &nod4);
v = reg[D_CX];
reg[D_CX] = 0;
sugen(n, nn, w);
reg[D_CX] = v;
gmove(&nod4, &nod3);
cursafe = c;
return;
}
if(n->complex > nn->complex){
reg[nod1.reg]++;
lcgen(n, &nod1);
reg[nod2.reg]++;
lcgen(nn, &nod2);
} else {
reg[nod2.reg]++;
lcgen(nn, &nod2);
reg[nod1.reg]++;
lcgen(n, &nod1);
}
reg[nod3.reg]++;
gins(AMOVL, nodconst(w/SZ_LONG), &nod3); gins(AMOVL, nodconst(w/SZ_LONG), &nod3);
gins(ACLD, Z, Z); gins(ACLD, Z, Z);
gins(AREP, Z, Z); gins(AREP, Z, Z);
@ -1839,16 +1845,8 @@ copy:
gins(AREP, Z, Z); gins(AREP, Z, Z);
gins(AMOVSB, Z, Z); gins(AMOVSB, Z, Z);
} }
if(c & 4) {
gins(APOPL, Z, &nod3); reg[nod3.reg]--;
reg[D_CX]--; reg[nod2.reg]--;
} reg[nod1.reg]--;
if(c & 2) {
gins(APOPL, Z, &nod2);
reg[nod2.reg]--;
}
if(c & 1) {
gins(APOPL, Z, &nod1);
reg[nod1.reg]--;
}
} }