]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/internal/obj/arm64: fix encoding of ADR/ADRP instruction
authorCherry Mui <cherryyz@google.com>
Mon, 23 May 2022 19:15:32 +0000 (15:15 -0400)
committerCherry Mui <cherryyz@google.com>
Mon, 23 May 2022 21:58:35 +0000 (21:58 +0000)
The referenced address is p.From, not p.To.

Separate from CL 403980, as this is a bug fix. Also, ADR is used
in CL 387336. This is needed to make it work correctly.

Change-Id: Ie0baaeb359b9a7f233458d2becf25dc6a1f8ecbf
Reviewed-on: https://go-review.googlesource.com/c/go/+/407884
Reviewed-by: David Chase <drchase@google.com>
Run-TryBot: Cherry Mui <cherryyz@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>

src/cmd/asm/internal/arch/arm64.go
src/cmd/asm/internal/asm/asm.go
src/cmd/asm/internal/asm/parse.go
src/cmd/asm/internal/asm/testdata/arm64.s
src/cmd/internal/obj/arm64/asm7.go

index 591c4d35db322915bdd2cbfbe5a2a82a068c2943..936b894a222219077a3b5cf30802baa0739f85cf 100644 (file)
@@ -47,6 +47,11 @@ var arm64Jump = map[string]bool{
        "JMP":   true,
        "TBNZ":  true,
        "TBZ":   true,
+
+       // ADR isn't really a jump, but it takes a PC or label reference,
+       // which needs to patched like a jump.
+       "ADR":  true,
+       "ADRP": true,
 }
 
 func jumpArm64(word string) bool {
@@ -81,6 +86,16 @@ func GetARM64SpecialOperand(name string) arm64.SpecialOperand {
        return arm64.SPOP_END
 }
 
+// IsARM64ADR reports whether the op (as defined by an arm64.A* constant) is
+// one of the comparison instructions that require special handling.
+func IsARM64ADR(op obj.As) bool {
+       switch op {
+       case arm64.AADR, arm64.AADRP:
+               return true
+       }
+       return false
+}
+
 // IsARM64CMP reports whether the op (as defined by an arm64.A* constant) is
 // one of the comparison instructions that require special handling.
 func IsARM64CMP(op obj.As) bool {
index 3babd4b6771313ef93f1f28caf981b7c6e473f08..cfd1f4c70732bd82abfb9a81506d070ea7da5be4 100644 (file)
@@ -394,6 +394,7 @@ func (p *Parser) asmJump(op obj.As, cond string, a []obj.Addr) {
                Pos:  p.pos(),
                As:   op,
        }
+       targetAddr := &prog.To
        switch len(a) {
        case 0:
                if p.arch.Family == sys.Wasm {
@@ -406,8 +407,15 @@ func (p *Parser) asmJump(op obj.As, cond string, a []obj.Addr) {
                target = &a[0]
        case 2:
                // Special 2-operand jumps.
-               target = &a[1]
-               prog.From = a[0]
+               if p.arch.Family == sys.ARM64 && arch.IsARM64ADR(op) {
+                       // ADR label, R. Label is in From.
+                       target = &a[0]
+                       prog.To = a[1]
+                       targetAddr = &prog.From
+               } else {
+                       target = &a[1]
+                       prog.From = a[0]
+               }
        case 3:
                if p.arch.Family == sys.PPC64 {
                        // Special 3-operand jumps.
@@ -513,20 +521,20 @@ func (p *Parser) asmJump(op obj.As, cond string, a []obj.Addr) {
        switch {
        case target.Type == obj.TYPE_BRANCH:
                // JMP 4(PC)
-               prog.To = obj.Addr{
+               *targetAddr = obj.Addr{
                        Type:   obj.TYPE_BRANCH,
                        Offset: p.pc + 1 + target.Offset, // +1 because p.pc is incremented in append, below.
                }
        case target.Type == obj.TYPE_REG:
                // JMP R1
-               prog.To = *target
+               *targetAddr = *target
        case target.Type == obj.TYPE_MEM && (target.Name == obj.NAME_EXTERN || target.Name == obj.NAME_STATIC):
                // JMP main·morestack(SB)
-               prog.To = *target
+               *targetAddr = *target
        case target.Type == obj.TYPE_INDIR && (target.Name == obj.NAME_EXTERN || target.Name == obj.NAME_STATIC):
                // JMP *main·morestack(SB)
-               prog.To = *target
-               prog.To.Type = obj.TYPE_INDIR
+               *targetAddr = *target
+               targetAddr.Type = obj.TYPE_INDIR
        case target.Type == obj.TYPE_MEM && target.Reg == 0 && target.Offset == 0:
                // JMP exit
                if target.Sym == nil {
@@ -535,20 +543,20 @@ func (p *Parser) asmJump(op obj.As, cond string, a []obj.Addr) {
                }
                targetProg := p.labels[target.Sym.Name]
                if targetProg == nil {
-                       p.toPatch = append(p.toPatch, Patch{prog, target.Sym.Name})
+                       p.toPatch = append(p.toPatch, Patch{targetAddr, target.Sym.Name})
                } else {
-                       p.branch(prog, targetProg)
+                       p.branch(targetAddr, targetProg)
                }
        case target.Type == obj.TYPE_MEM && target.Name == obj.NAME_NONE:
                // JMP 4(R0)
-               prog.To = *target
+               *targetAddr = *target
                // On the ppc64, 9a encodes BR (CTR) as BR CTR. We do the same.
                if p.arch.Family == sys.PPC64 && target.Offset == 0 {
-                       prog.To.Type = obj.TYPE_REG
+                       targetAddr.Type = obj.TYPE_REG
                }
        case target.Type == obj.TYPE_CONST:
                // JMP $4
-               prog.To = a[0]
+               *targetAddr = a[0]
        case target.Type == obj.TYPE_NONE:
                // JMP
        default:
@@ -566,17 +574,17 @@ func (p *Parser) patch() {
                        p.errorf("undefined label %s", patch.label)
                        return
                }
-               p.branch(patch.prog, targetProg)
+               p.branch(patch.addr, targetProg)
        }
        p.toPatch = p.toPatch[:0]
 }
 
-func (p *Parser) branch(jmp, target *obj.Prog) {
-       jmp.To = obj.Addr{
+func (p *Parser) branch(addr *obj.Addr, target *obj.Prog) {
+       *addr = obj.Addr{
                Type:  obj.TYPE_BRANCH,
                Index: 0,
        }
-       jmp.To.Val = target
+       addr.Val = target
 }
 
 // asmInstruction assembles an instruction.
index acd03e139946de74977a71cc65748b21ff29c6eb..6445e01bded2e4acaab0795c19e90abac51cf025 100644 (file)
@@ -49,7 +49,7 @@ type Parser struct {
 }
 
 type Patch struct {
-       prog  *obj.Prog
+       addr  *obj.Addr
        label string
 }
 
index 0e5799a022581cc63d64d0e88dd9e69799db4fe6..4451338d51d787102cd33e12c2dd32c193ce6e67 100644 (file)
@@ -10,7 +10,6 @@
 
 TEXT   foo(SB), DUPOK|NOSPLIT, $-8
 
-
 // arithmetic operations
        ADDW    $1, R2, R3
        ADDW    R1, R2, R3
@@ -851,6 +850,11 @@ again:
        JMP     foo(SB)
        CALL    foo(SB)
 
+// ADR
+       ADR     next, R11     // ADR R11 // 2b000010
+next:
+       NOP
+
 // LDP/STP
        LDP     (R0), (R0, R1)      // 000440a9
        LDP     (R0), (R1, R2)      // 010840a9
index 98933464bbd8c79c056fad2aec29b451e5728ab5..8732bf79355a7639fe6e884b531e83d50cfa29d3 100644 (file)
@@ -6683,7 +6683,12 @@ func (c *ctxt7) opimm(p *obj.Prog, a obj.As) uint32 {
 func (c *ctxt7) brdist(p *obj.Prog, preshift int, flen int, shift int) int64 {
        v := int64(0)
        t := int64(0)
-       q := p.To.Target()
+       var q *obj.Prog
+       if p.To.Type == obj.TYPE_BRANCH {
+               q = p.To.Target()
+       } else if p.From.Type == obj.TYPE_BRANCH { // adr, adrp
+               q = p.From.Target()
+       }
        if q == nil {
                // TODO: don't use brdist for this case, as it isn't a branch.
                // (Calls from omovlit, and maybe adr/adrp opcodes as well.)