Skip to content

Commit

Permalink
liblink, cmd/internal/obj: prefer positive immediates
Browse files Browse the repository at this point in the history
Rewrite instructions that use negative immediates as the "negative"
instruction variant with a positive operand.

E.g. ADD $-2, R becomes SUB $2, R

Updates golang#6
  • Loading branch information
4ad committed Jan 29, 2015
1 parent 076d34d commit 6a42312
Show file tree
Hide file tree
Showing 4 changed files with 62 additions and 2 deletions.
2 changes: 1 addition & 1 deletion src/cmd/internal/obj/arm64/asm7.go
Original file line number Diff line number Diff line change
Expand Up @@ -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,

Expand Down
31 changes: 31 additions & 0 deletions src/cmd/internal/obj/arm64/obj7.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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) {
Expand Down
2 changes: 1 addition & 1 deletion src/liblink/asm7.c
Original file line number Diff line number Diff line change
Expand Up @@ -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:

Expand Down
29 changes: 29 additions & 0 deletions src/liblink/obj7.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down Expand Up @@ -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
Expand Down

0 comments on commit 6a42312

Please sign in to comment.