From: Austin Clements Date: Thu, 18 Dec 2014 06:08:09 +0000 (-0500) Subject: liblink: generate correct code for MOVD $-n(Rm), x on ppc64 X-Git-Tag: go1.5beta1~2604 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=b21e936f3e88377a41f9a4216453665eed1fe9ca;p=gostls13.git liblink: generate correct code for MOVD $-n(Rm), x on ppc64 On ppc64, liblink rewrites MOVD's of >32-bit constants by putting the constant in memory and rewriting the MOVD to load from that memory address. However, there were two bugs in the condition: a) owing to an incorrect sign extension, it triggered for all negative constants, and b) it could trigger for constant offsets from registers (addresses of the form $n(Rm) in assembly) Together, these meant instructions of the form MOVD $-n(Rm), x were compiled by putting -n in memory and rewriting the MOVD to load this constant from memory (completely dropping Rm). Change-Id: I1f6cc980efa3e3d6f164b46c985b2c3b55971cca Reviewed-on: https://go-review.googlesource.com/1752 Reviewed-by: Minux Ma --- diff --git a/src/cmd/9l/9.out.h b/src/cmd/9l/9.out.h index 87917f88ac..016163b6fa 100644 --- a/src/cmd/9l/9.out.h +++ b/src/cmd/9l/9.out.h @@ -106,9 +106,9 @@ enum C_ANDCON, /* 0 < v <= 0xFFFF */ C_LCON, /* other 32 */ C_DCON, /* other 64 (could subdivide further) */ - C_SACON, + C_SACON, /* $n(REG) where n is small */ C_SECON, - C_LACON, + C_LACON, /* $n(REG) where n is large */ C_LECON, C_SBRA, C_LBRA, diff --git a/src/liblink/obj9.c b/src/liblink/obj9.c index 533dbc271b..a1ead3a0f3 100644 --- a/src/liblink/obj9.c +++ b/src/liblink/obj9.c @@ -145,7 +145,8 @@ progedit(Link *ctxt, Prog *p) } break; case AMOVD: - if(p->from.type == D_CONST && p->from.name == D_NONE && (int64)(uint32)p->from.offset != p->from.offset) { + // Put >32-bit constants in memory and load them + if(p->from.type == D_CONST && p->from.name == D_NONE && p->from.reg == NREG && (int32)p->from.offset != p->from.offset) { sprint(literal, "$i64.%016llux", (uvlong)p->from.offset); s = linklookup(ctxt, literal, 0); s->size = 8;