diff --git a/src/cmd/internal/obj/arm64/asm7.go b/src/cmd/internal/obj/arm64/asm7.go index 999c0ede561d8..de63fbb8bfa05 100644 --- a/src/cmd/internal/obj/arm64/asm7.go +++ b/src/cmd/internal/obj/arm64/asm7.go @@ -818,7 +818,7 @@ func addpool(ctxt *obj.Link, p *obj.Prog, a *obj.Addr) { so we need to know what to do with C_MOVCON. The correct fix is to use the "negation" instruction variant, - e.g. CMN $0, R instead of CMP $-1, R, or SUB $1, R instead + e.g. CMN $1, R instead of CMP $-1, R, or SUB $1, R instead of ADD $-1, R. */ case C_MOVCON, diff --git a/src/cmd/internal/obj/arm64/obj7.go b/src/cmd/internal/obj/arm64/obj7.go index c1458f0164303..7b740a0616b4e 100644 --- a/src/cmd/internal/obj/arm64/obj7.go +++ b/src/cmd/internal/obj/arm64/obj7.go @@ -88,6 +88,17 @@ func settextflag(p *obj.Prog, f int) { p.Reg = uint8(f) } +var complements = []int16{ + AADD: ASUB, + AADDW: ASUBW, + ASUB: AADD, + ASUBW: AADDW, + ACMP: ACMN, + ACMPW: ACMNW, + ACMN: ACMP, + ACMNW: ACMPW, +} + func progedit(ctxt *obj.Link, p *obj.Prog) { var literal string var s *obj.LSym @@ -142,6 +153,26 @@ func progedit(ctxt *obj.Link, p *obj.Prog) { break } + + // Rewrite negative immediates as positive immediates with + // complementary instruction. + switch p.As { + + case AADD, + AADDW, + ASUB, + ASUBW, + ACMP, + ACMPW, + ACMN, + ACMNW: + if p.From.Type == D_CONST && p.From.Offset < 0 { + p.From.Offset = -p.From.Offset + p.As = complements[p.As] + } + + break + } } func follow(ctxt *obj.Link, s *obj.LSym) { diff --git a/src/liblink/asm7.c b/src/liblink/asm7.c index d56c1527d8f1b..005ec8a886d9b 100644 --- a/src/liblink/asm7.c +++ b/src/liblink/asm7.c @@ -911,7 +911,7 @@ addpool(Link *ctxt, Prog *p, Addr *a) so we need to know what to do with C_MOVCON. The correct fix is to use the "negation" instruction variant, - e.g. CMN $0, R instead of CMP $-1, R, or SUB $1, R instead + e.g. CMN $1, R instead of CMP $-1, R, or SUB $1, R instead of ADD $-1, R. */ case C_MOVCON: diff --git a/src/liblink/obj7.c b/src/liblink/obj7.c index 131ba75b48bce..fd1c2a67af60a 100644 --- a/src/liblink/obj7.c +++ b/src/liblink/obj7.c @@ -102,6 +102,17 @@ settextflag(Prog *p, int f) p->reg = f; } +static short complements[] = { + [AADD] ASUB, + [AADDW] ASUBW, + [ASUB] AADD, + [ASUBW] AADDW, + [ACMP] ACMN, + [ACMPW] ACMNW, + [ACMN] ACMP, + [ACMNW] ACMPW, +}; + static void progedit(Link *ctxt, Prog *p) { @@ -156,6 +167,24 @@ progedit(Link *ctxt, Prog *p) } break; } + + // Rewrite negative immediates as positive immediates with + // complementary instruction. + switch(p->as) { + case AADD: + case AADDW: + case ASUB: + case ASUBW: + case ACMP: + case ACMPW: + case ACMN: + case ACMNW: + if(p->from.type == D_CONST && p->from.offset < 0) { + p->from.offset = -p->from.offset; + p->as = complements[p->as]; + } + break; + } } static void