From 0b66310924ace48c15a3140843576d5b069762de Mon Sep 17 00:00:00 2001 From: Joel Sing Date: Thu, 19 Aug 2021 05:33:01 +0000 Subject: [PATCH] cmd/internal/obj/riscv: avoid obj.Prog rewriting for store instructions 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 Reviewed-by: Cherry Mui Run-TryBot: Cherry Mui TryBot-Result: Go Bot --- src/cmd/internal/obj/riscv/obj.go | 75 ++++++++++++++++--------------- 1 file changed, 38 insertions(+), 37 deletions(-) diff --git a/src/cmd/internal/obj/riscv/obj.go b/src/cmd/internal/obj/riscv/obj.go index 3d304c1b42..2ae3d7f301 100644 --- a/src/cmd/internal/obj/riscv/obj.go +++ b/src/cmd/internal/obj/riscv/obj.go @@ -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} - - // $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 - // $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 + } + + // $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 + // $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. -- 2.50.0