]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/internal/obj/riscv: avoid obj.Prog rewriting for memory loads
authorJoel Sing <joel@sing.id.au>
Fri, 19 Mar 2021 14:09:59 +0000 (14:09 +0000)
committerJoel Sing <joel@sing.id.au>
Sat, 4 Sep 2021 10:58:11 +0000 (10:58 +0000)
Rather than rewriting the obj.Prog for a MOV pseudo-instruction targeting
a memory to register load, generate the appropriate machine instruction
sequence directly.

Change-Id: I4c7292ba00f576ec71d4842b6ff27a8ce6db0650
Reviewed-on: https://go-review.googlesource.com/c/go/+/344454
Trust: Joel Sing <joel@sing.id.au>
Reviewed-by: Cherry Mui <cherryyz@google.com>
src/cmd/asm/internal/asm/testdata/riscv64.s
src/cmd/internal/obj/riscv/obj.go

index b22d1a7e37833e45c0a0b0b3e36ea3bd4fce7e22..6f37a940c7dbbd4ee0968738f4dc47116b3d1804 100644 (file)
@@ -285,8 +285,8 @@ start:
        MOV     $2048, X5                               // b71200009b820280
        MOV     $-2049, X5                              // b7f2ffff9b82f27f
 
-       // Converted to load of symbol.
-       MOV     $4294967296, X5                         // 97020000
+       // Converted to load of symbol (AUIPC + LD)
+       MOV     $4294967296, X5                         // 9702000083b20200
 
        MOV     (X5), X6                                // 03b30200
        MOV     4(X5), X6                               // 03b34200
index 2ae3d7f301b182d15c1fa871dfb58dd3263cf8ae..88ffeee51f1f94ddd9b5bae62991194d47740f28 100644 (file)
@@ -227,32 +227,15 @@ func rewriteMOV(ctxt *obj.Link, newprog obj.ProgAlloc, p *obj.Prog) {
        }
 
        switch p.From.Type {
-       case obj.TYPE_MEM: // MOV c(Rs), Rd -> L $c, Rs, Rd
+       case obj.TYPE_MEM:
                switch p.From.Name {
                case obj.NAME_AUTO, obj.NAME_PARAM, obj.NAME_NONE:
                        if p.To.Type != obj.TYPE_REG {
-                               ctxt.Diag("unsupported load at %v", p)
+                               ctxt.Diag("unsupported load for %v", p)
                        }
-                       p.As = movToLoad(p.As)
-                       p.From.Reg = addrToReg(p.From)
 
                case obj.NAME_EXTERN, obj.NAME_STATIC:
-                       // AUIPC $off_hi, R
-                       // L $off_lo, R
-                       as := p.As
-                       to := p.To
-
-                       p.As = AAUIPC
                        p.Mark |= NEED_PCREL_ITYPE_RELOC
-                       p.SetFrom3(obj.Addr{Type: obj.TYPE_CONST, Offset: p.From.Offset, Sym: p.From.Sym})
-                       p.From = obj.Addr{Type: obj.TYPE_CONST, Offset: 0}
-                       p.Reg = 0
-                       p.To = obj.Addr{Type: obj.TYPE_REG, Reg: to.Reg}
-                       p = obj.Appendp(p, newprog)
-
-                       p.As = movToLoad(as)
-                       p.From = obj.Addr{Type: obj.TYPE_MEM, Reg: to.Reg, Offset: 0}
-                       p.To = to
 
                default:
                        ctxt.Diag("unsupported name %d for %v", p.From.Name, p)
@@ -1749,22 +1732,25 @@ func instructionForProg(p *obj.Prog) *instruction {
        return ins
 }
 
-func instructionsForLoad(p *obj.Prog) []*instruction {
+// instructionsForLoad returns the machine instructions for a load. The load
+// instruction is specified by as and the base/source register is specified
+// by rs, instead of the obj.Prog.
+func instructionsForLoad(p *obj.Prog, as obj.As, rs int16) []*instruction {
        if p.From.Type != obj.TYPE_MEM {
                p.Ctxt.Diag("%v requires memory for source", p)
                return nil
        }
 
-       switch p.As {
+       switch as {
        case ALD, ALB, ALH, ALW, ALBU, ALHU, ALWU, AFLW, AFLD:
        default:
-               p.Ctxt.Diag("%v: unknown load instruction %v", p, p.As)
+               p.Ctxt.Diag("%v: unknown load instruction %v", p, as)
                return nil
        }
 
        // <load> $imm, REG, TO (load $imm+(REG), TO)
        ins := instructionForProg(p)
-       ins.rs1, ins.rs2 = uint32(p.From.Reg), obj.REG_NONE
+       ins.as, ins.rs1, ins.rs2 = as, uint32(rs), obj.REG_NONE
        ins.imm = p.From.Offset
 
        low, high, err := Split32BitImmediate(ins.imm)
@@ -1887,6 +1873,21 @@ func instructionsForMOV(p *obj.Prog) []*instruction {
                        inss = append(inss, ins2)
                }
 
+       case p.From.Type == obj.TYPE_MEM && p.To.Type == obj.TYPE_REG:
+               // Memory to register loads.
+               switch p.From.Name {
+               case obj.NAME_AUTO, obj.NAME_PARAM, obj.NAME_NONE:
+                       // MOV c(Rs), Rd -> L $c, Rs, Rd
+                       inss = instructionsForLoad(p, movToLoad(p.As), addrToReg(p.From))
+
+               case obj.NAME_EXTERN, obj.NAME_STATIC:
+                       // AUIPC $off_hi, Rd
+                       // L $off_lo, Rd, Rd
+                       insAUIPC := &instruction{as: AAUIPC, rd: ins.rd}
+                       ins.as, ins.rs1, ins.rs2, ins.imm = movToLoad(p.As), ins.rd, obj.REG_NONE, 0
+                       inss = []*instruction{insAUIPC, ins}
+               }
+
        default:
                // If we get here with a MOV pseudo-instruction it is going to
                // remain unhandled. For now we trust rewriteMOV to catch these.
@@ -1943,7 +1944,7 @@ func instructionsForProg(p *obj.Prog) []*instruction {
                return instructionsForMOV(p)
 
        case ALW, ALWU, ALH, ALHU, ALB, ALBU, ALD, AFLW, AFLD:
-               return instructionsForLoad(p)
+               return instructionsForLoad(p, ins.as, p.From.Reg)
 
        case ASW, ASH, ASB, ASD, AFSW, AFSD:
                return instructionsForStore(p)
@@ -2073,22 +2074,28 @@ func assemble(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
                                rel.Add = p.To.Offset
                                rel.Type = objabi.R_CALLRISCV
                        }
-               case AAUIPC:
+
+               case AAUIPC, AMOV, AMOVB, AMOVH, AMOVW, AMOVBU, AMOVHU, AMOVWU, AMOVF, AMOVD:
+                       var addr *obj.Addr
                        var rt objabi.RelocType
                        if p.Mark&NEED_PCREL_ITYPE_RELOC == NEED_PCREL_ITYPE_RELOC {
                                rt = objabi.R_RISCV_PCREL_ITYPE
+                               addr = &p.From
                        } else if p.Mark&NEED_PCREL_STYPE_RELOC == NEED_PCREL_STYPE_RELOC {
                                rt = objabi.R_RISCV_PCREL_STYPE
+                               addr = &p.To
                        } else {
                                break
                        }
-                       if p.Link == nil {
-                               ctxt.Diag("AUIPC needing PC-relative reloc missing following instruction")
-                               break
+                       if p.As == AAUIPC {
+                               if p.Link == nil {
+                                       ctxt.Diag("AUIPC needing PC-relative reloc missing following instruction")
+                                       break
+                               }
+                               addr = &p.RestArgs[0].Addr
                        }
-                       addr := p.RestArgs[0]
                        if addr.Sym == nil {
-                               ctxt.Diag("AUIPC needing PC-relative reloc missing symbol")
+                               ctxt.Diag("PC-relative relocation missing symbol")
                                break
                        }
                        if addr.Sym.Type == objabi.STLSBSS {