summaryrefslogtreecommitdiff
path: root/src/cmd
diff options
context:
space:
mode:
authorAustin Clements <austin@google.com>2014-10-31 11:08:27 -0400
committerAustin Clements <austin@google.com>2014-10-31 11:08:27 -0400
commitbfab3e583ce8e78b9488fdb292f3f371949757a6 (patch)
treec7190580bc2a0dcef4a4a03a21604ceffcac8b19 /src/cmd
parent905f3e7cf489f05ae3764cabda3cd96684e3445f (diff)
downloadgo-bfab3e583ce8e78b9488fdb292f3f371949757a6.tar.gz
[dev.power64] 9g: fix under-zeroing in clearfat
All three cases of clearfat were wrong on power64x. The cases that handle 1032 bytes and up and 32 bytes and up both use MOVDU (one directly generated in a loop and the other via duffzero), which leaves the pointer register pointing at the *last written* address. The generated code was not accounting for this, so the byte fill loop was re-zeroing the last zeroed dword, rather than the bytes following the last zeroed dword. Fix this by simply adding an additional 8 byte offset to the byte zeroing loop. The case that handled under 32 bytes was also wrong. It didn't update the pointer register at all, so the byte zeroing loop was simply re-zeroing the beginning of region. Again, the fix is to add an offset to the byte zeroing loop to account for this. LGTM=dave, bradfitz R=rsc, dave, bradfitz CC=golang-codereviews https://codereview.appspot.com/168870043
Diffstat (limited to 'src/cmd')
-rw-r--r--src/cmd/9g/ggen.c20
1 files changed, 13 insertions, 7 deletions
diff --git a/src/cmd/9g/ggen.c b/src/cmd/9g/ggen.c
index c41d8eb41..7d9cf5050 100644
--- a/src/cmd/9g/ggen.c
+++ b/src/cmd/9g/ggen.c
@@ -900,7 +900,7 @@ ret:
void
clearfat(Node *nl)
{
- uint64 w, c, q, t;
+ uint64 w, c, q, t, boff;
Node dst, end, r0, *f;
Prog *p, *pl;
@@ -944,6 +944,8 @@ clearfat(Node *nl)
patch(gbranch(ABNE, T, 0), pl);
regfree(&end);
+ // The loop leaves R3 on the last zeroed dword
+ boff = 8;
} else if(q >= 4) {
p = gins(ASUB, N, &dst);
p->from.type = D_CONST;
@@ -953,17 +955,21 @@ clearfat(Node *nl)
afunclit(&p->to, f);
// 4 and 128 = magic constants: see ../../runtime/asm_power64x.s
p->to.offset = 4*(128-q);
- } else
- for(t = 0; t < q; t++) {
- p = gins(AMOVD, &r0, &dst);
- p->to.type = D_OREG;
- p->to.offset = 8*t;
+ // duffzero leaves R3 on the last zeroed dword
+ boff = 8;
+ } else {
+ for(t = 0; t < q; t++) {
+ p = gins(AMOVD, &r0, &dst);
+ p->to.type = D_OREG;
+ p->to.offset = 8*t;
+ }
+ boff = 8*q;
}
for(t = 0; t < c; t++) {
p = gins(AMOVB, &r0, &dst);
p->to.type = D_OREG;
- p->to.offset = t;
+ p->to.offset = t+boff;
}
reg[REGRT1]--;
}