mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
cmd/internal/obj/riscv: avoid obj.Prog rewriting for load instructions
Rather than rewriting the obj.Prog for a load instruction, generate the appropriate machine instruction sequence directly. Change-Id: Iba656dbf2dff2bce02aa221d9a5cad7b7c4630d8 Reviewed-on: https://go-review.googlesource.com/c/go/+/344451 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>
This commit is contained in:
parent
9cb5716f00
commit
8a01010c26
2 changed files with 55 additions and 43 deletions
|
|
@ -256,15 +256,19 @@ var RISCV64DWARFRegisters = map[int16]int16{
|
||||||
|
|
||||||
// Prog.Mark flags.
|
// Prog.Mark flags.
|
||||||
const (
|
const (
|
||||||
|
// USES_REG_TMP indicates that a machine instruction generated from the
|
||||||
|
// corresponding *obj.Prog uses the temporary register.
|
||||||
|
USES_REG_TMP = 1 << iota
|
||||||
|
|
||||||
// NEED_PCREL_ITYPE_RELOC is set on AUIPC instructions to indicate that
|
// NEED_PCREL_ITYPE_RELOC is set on AUIPC instructions to indicate that
|
||||||
// it is the first instruction in an AUIPC + I-type pair that needs a
|
// it is the first instruction in an AUIPC + I-type pair that needs a
|
||||||
// R_RISCV_PCREL_ITYPE relocation.
|
// R_RISCV_PCREL_ITYPE relocation.
|
||||||
NEED_PCREL_ITYPE_RELOC = 1 << 0
|
NEED_PCREL_ITYPE_RELOC
|
||||||
|
|
||||||
// NEED_PCREL_STYPE_RELOC is set on AUIPC instructions to indicate that
|
// NEED_PCREL_STYPE_RELOC is set on AUIPC instructions to indicate that
|
||||||
// it is the first instruction in an AUIPC + S-type pair that needs a
|
// it is the first instruction in an AUIPC + S-type pair that needs a
|
||||||
// R_RISCV_PCREL_STYPE relocation.
|
// R_RISCV_PCREL_STYPE relocation.
|
||||||
NEED_PCREL_STYPE_RELOC = 1 << 1
|
NEED_PCREL_STYPE_RELOC
|
||||||
)
|
)
|
||||||
|
|
||||||
// RISC-V mnemonics, as defined in the "opcodes" and "opcodes-pseudo" files
|
// RISC-V mnemonics, as defined in the "opcodes" and "opcodes-pseudo" files
|
||||||
|
|
|
||||||
|
|
@ -795,38 +795,6 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
|
||||||
p.Reg = q.Reg
|
p.Reg = q.Reg
|
||||||
p.From = obj.Addr{Type: obj.TYPE_REG, Reg: REG_TMP}
|
p.From = obj.Addr{Type: obj.TYPE_REG, Reg: REG_TMP}
|
||||||
|
|
||||||
// <load> $imm, REG, TO (load $imm+(REG), TO)
|
|
||||||
case ALD, ALB, ALH, ALW, ALBU, ALHU, ALWU, AFLW, AFLD:
|
|
||||||
low, high, err := Split32BitImmediate(p.From.Offset)
|
|
||||||
if err != nil {
|
|
||||||
ctxt.Diag("%v: constant %d too large", p, p.From.Offset)
|
|
||||||
}
|
|
||||||
if high == 0 {
|
|
||||||
break // no need to split
|
|
||||||
}
|
|
||||||
q := *p
|
|
||||||
|
|
||||||
// LUI $high, TMP
|
|
||||||
// ADD TMP, REG, TMP
|
|
||||||
// <load> $low, TMP, TO
|
|
||||||
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.From.Reg
|
|
||||||
p.To = obj.Addr{Type: obj.TYPE_REG, Reg: REG_TMP}
|
|
||||||
p = obj.Appendp(p, newprog)
|
|
||||||
|
|
||||||
p.As = q.As
|
|
||||||
p.To = q.To
|
|
||||||
p.From = obj.Addr{Type: obj.TYPE_MEM, Reg: REG_TMP, Offset: low}
|
|
||||||
p.Reg = obj.REG_NONE
|
|
||||||
|
|
||||||
// <store> $imm, REG, TO (store $imm+(TO), REG)
|
// <store> $imm, REG, TO (store $imm+(TO), REG)
|
||||||
case ASD, ASB, ASH, ASW, AFSW, AFSD:
|
case ASD, ASB, ASH, ASW, AFSW, AFSD:
|
||||||
low, high, err := Split32BitImmediate(p.To.Offset)
|
low, high, err := Split32BitImmediate(p.To.Offset)
|
||||||
|
|
@ -1793,6 +1761,10 @@ func (ins *instruction) validate(ctxt *obj.Link) {
|
||||||
enc.validate(ctxt, ins)
|
enc.validate(ctxt, ins)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (ins *instruction) usesRegTmp() bool {
|
||||||
|
return ins.rd == REG_TMP || ins.rs1 == REG_TMP || ins.rs2 == REG_TMP
|
||||||
|
}
|
||||||
|
|
||||||
// instructionForProg returns the default *obj.Prog to instruction mapping.
|
// instructionForProg returns the default *obj.Prog to instruction mapping.
|
||||||
func instructionForProg(p *obj.Prog) *instruction {
|
func instructionForProg(p *obj.Prog) *instruction {
|
||||||
ins := &instruction{
|
ins := &instruction{
|
||||||
|
|
@ -1808,6 +1780,43 @@ func instructionForProg(p *obj.Prog) *instruction {
|
||||||
return ins
|
return ins
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func instructionsForLoad(p *obj.Prog) []*instruction {
|
||||||
|
if p.From.Type != obj.TYPE_MEM {
|
||||||
|
p.Ctxt.Diag("%v requires memory for source", p)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
switch p.As {
|
||||||
|
case ALD, ALB, ALH, ALW, ALBU, ALHU, ALWU, AFLW, AFLD:
|
||||||
|
default:
|
||||||
|
p.Ctxt.Diag("%v: unknown load instruction %v", p, 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.imm = p.From.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, REG, TMP
|
||||||
|
// <load> $low, TMP, TO
|
||||||
|
insLUI := &instruction{as: ALUI, rd: REG_TMP, imm: high}
|
||||||
|
insADD := &instruction{as: AADD, rd: REG_TMP, rs1: REG_TMP, rs2: ins.rs1}
|
||||||
|
ins.rs1, ins.imm = REG_TMP, low
|
||||||
|
|
||||||
|
return []*instruction{insLUI, insADD, ins}
|
||||||
|
}
|
||||||
|
|
||||||
// instructionsForMOV returns the machine instructions for an *obj.Prog that
|
// instructionsForMOV returns the machine instructions for an *obj.Prog that
|
||||||
// uses a MOV pseudo-instruction.
|
// uses a MOV pseudo-instruction.
|
||||||
func instructionsForMOV(p *obj.Prog) []*instruction {
|
func instructionsForMOV(p *obj.Prog) []*instruction {
|
||||||
|
|
@ -1928,12 +1937,7 @@ func instructionsForProg(p *obj.Prog) []*instruction {
|
||||||
return instructionsForMOV(p)
|
return instructionsForMOV(p)
|
||||||
|
|
||||||
case ALW, ALWU, ALH, ALHU, ALB, ALBU, ALD, AFLW, AFLD:
|
case ALW, ALWU, ALH, ALHU, ALB, ALBU, ALD, AFLW, AFLD:
|
||||||
if p.From.Type != obj.TYPE_MEM {
|
return instructionsForLoad(p)
|
||||||
p.Ctxt.Diag("%v requires memory for source", p)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
ins.rs1, ins.rs2 = uint32(p.From.Reg), obj.REG_NONE
|
|
||||||
ins.imm = p.From.Offset
|
|
||||||
|
|
||||||
case ASW, ASH, ASB, ASD, AFSW, AFSD:
|
case ASW, ASH, ASB, ASD, AFSW, AFSD:
|
||||||
if p.To.Type != obj.TYPE_MEM {
|
if p.To.Type != obj.TYPE_MEM {
|
||||||
|
|
@ -2104,9 +2108,13 @@ func assemble(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
|
||||||
|
|
||||||
for _, ins := range instructionsForProg(p) {
|
for _, ins := range instructionsForProg(p) {
|
||||||
ic, err := ins.encode()
|
ic, err := ins.encode()
|
||||||
if err == nil {
|
if err != nil {
|
||||||
symcode = append(symcode, ic)
|
break
|
||||||
}
|
}
|
||||||
|
if ins.usesRegTmp() {
|
||||||
|
p.Mark |= USES_REG_TMP
|
||||||
|
}
|
||||||
|
symcode = append(symcode, ic)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
cursym.Size = int64(4 * len(symcode))
|
cursym.Size = int64(4 * len(symcode))
|
||||||
|
|
@ -2120,7 +2128,7 @@ func assemble(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func isUnsafePoint(p *obj.Prog) bool {
|
func isUnsafePoint(p *obj.Prog) bool {
|
||||||
return p.From.Reg == REG_TMP || p.To.Reg == REG_TMP || p.Reg == REG_TMP
|
return p.Mark&USES_REG_TMP == USES_REG_TMP || p.From.Reg == REG_TMP || p.To.Reg == REG_TMP || p.Reg == REG_TMP
|
||||||
}
|
}
|
||||||
|
|
||||||
var LinkRISCV64 = obj.LinkArch{
|
var LinkRISCV64 = obj.LinkArch{
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue