]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/internal/obj/riscv: avoid obj.Prog rewriting for store instructions
authorJoel Sing <joel@sing.id.au>
Thu, 19 Aug 2021 05:33:01 +0000 (05:33 +0000)
committerJoel Sing <joel@sing.id.au>
Sat, 4 Sep 2021 10:43:00 +0000 (10:43 +0000)
Rather than rewriting the obj.Prog for a store instruction, generate the
appropriate machine instruction sequence directly.

Change-Id: I026250ca3d249a1013243948a4e567b708b72d0c
Reviewed-on: https://go-review.googlesource.com/c/go/+/344452
Trust: Joel Sing <joel@sing.id.au>
Reviewed-by: Cherry Mui <cherryyz@google.com>
Run-TryBot: Cherry Mui <cherryyz@google.com>
TryBot-Result: Go Bot <gobot@golang.org>

src/cmd/internal/obj/riscv/obj.go

index 3d304c1b421ff1174108c4b84beeaf6ab5ad0658..2ae3d7f301b182d15c1fa871dfb58dd3263cf8ae 100644 (file)
@@ -794,37 +794,6 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
                        p.To = q.To
                        p.Reg = q.Reg
                        p.From = obj.Addr{Type: obj.TYPE_REG, Reg: REG_TMP}
-
-               // <store> $imm, REG, TO (store $imm+(TO), REG)
-               case ASD, ASB, ASH, ASW, AFSW, AFSD:
-                       low, high, err := Split32BitImmediate(p.To.Offset)
-                       if err != nil {
-                               ctxt.Diag("%v: constant %d too large", p, p.To.Offset)
-                       }
-                       if high == 0 {
-                               break // no need to split
-                       }
-                       q := *p
-
-                       // LUI $high, TMP
-                       // ADD TMP, TO, TMP
-                       // <store> $low, REG, TMP
-                       p.As = ALUI
-                       p.From = obj.Addr{Type: obj.TYPE_CONST, Offset: high}
-                       p.Reg = 0
-                       p.To = obj.Addr{Type: obj.TYPE_REG, Reg: REG_TMP}
-                       p.Spadj = 0 // needed if TO is SP
-                       p = obj.Appendp(p, newprog)
-
-                       p.As = AADD
-                       p.From = obj.Addr{Type: obj.TYPE_REG, Reg: REG_TMP}
-                       p.Reg = q.To.Reg
-                       p.To = obj.Addr{Type: obj.TYPE_REG, Reg: REG_TMP}
-                       p = obj.Appendp(p, newprog)
-
-                       p.As = q.As
-                       p.From = obj.Addr{Type: obj.TYPE_REG, Reg: q.From.Reg, Offset: 0}
-                       p.To = obj.Addr{Type: obj.TYPE_MEM, Reg: REG_TMP, Offset: low}
                }
        }
 
@@ -1817,6 +1786,43 @@ func instructionsForLoad(p *obj.Prog) []*instruction {
        return []*instruction{insLUI, insADD, ins}
 }
 
+func instructionsForStore(p *obj.Prog) []*instruction {
+       if p.To.Type != obj.TYPE_MEM {
+               p.Ctxt.Diag("%v requires memory for destination", p)
+               return nil
+       }
+
+       switch p.As {
+       case ASW, ASH, ASB, ASD, AFSW, AFSD:
+       default:
+               p.Ctxt.Diag("%v: unknown store instruction %v", p, p.As)
+               return nil
+       }
+
+       // <store> $imm, REG, TO (store $imm+(TO), REG)
+       ins := instructionForProg(p)
+       ins.rs1, ins.rs2 = uint32(p.From.Reg), obj.REG_NONE
+       ins.imm = p.To.Offset
+
+       low, high, err := Split32BitImmediate(ins.imm)
+       if err != nil {
+               p.Ctxt.Diag("%v: constant %d too large", p, ins.imm)
+               return nil
+       }
+       if high == 0 {
+               return []*instruction{ins}
+       }
+
+       // LUI $high, TMP
+       // ADD TMP, TO, TMP
+       // <store> $low, REG, TMP
+       insLUI := &instruction{as: ALUI, rd: REG_TMP, imm: high}
+       insADD := &instruction{as: AADD, rd: REG_TMP, rs1: REG_TMP, rs2: ins.rd}
+       ins.rd, ins.imm = REG_TMP, low
+
+       return []*instruction{insLUI, insADD, ins}
+}
+
 // instructionsForMOV returns the machine instructions for an *obj.Prog that
 // uses a MOV pseudo-instruction.
 func instructionsForMOV(p *obj.Prog) []*instruction {
@@ -1940,12 +1946,7 @@ func instructionsForProg(p *obj.Prog) []*instruction {
                return instructionsForLoad(p)
 
        case ASW, ASH, ASB, ASD, AFSW, AFSD:
-               if p.To.Type != obj.TYPE_MEM {
-                       p.Ctxt.Diag("%v requires memory for destination", p)
-                       return nil
-               }
-               ins.rs1, ins.rs2 = uint32(p.From.Reg), obj.REG_NONE
-               ins.imm = p.To.Offset
+               return instructionsForStore(p)
 
        case ALRW, ALRD:
                // Set aq to use acquire access ordering, which matches Go's memory requirements.