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 constant loads
Rather than rewriting the obj.Prog for a MOV pseudo-instruction targeting a constant to register load, generate the appropriate machine instruction sequence directly. Change-Id: I38e62f282b39be2a0a241f32280d306558d49b44 Reviewed-on: https://go-review.googlesource.com/c/go/+/344450 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
4957976b1a
commit
9cb5716f00
2 changed files with 24 additions and 30 deletions
2
src/cmd/asm/internal/asm/testdata/riscv64.s
vendored
2
src/cmd/asm/internal/asm/testdata/riscv64.s
vendored
|
|
@ -282,6 +282,8 @@ start:
|
|||
MOV X5, X6 // 13830200
|
||||
MOV $2047, X5 // 9b02f07f
|
||||
MOV $-2048, X5 // 9b020080
|
||||
MOV $2048, X5 // b71200009b820280
|
||||
MOV $-2049, X5 // b7f2ffff9b82f27f
|
||||
|
||||
// Converted to load of symbol.
|
||||
MOV $4294967296, X5 // 97020000
|
||||
|
|
|
|||
|
|
@ -305,42 +305,12 @@ func rewriteMOV(ctxt *obj.Link, newprog obj.ProgAlloc, p *obj.Prog) {
|
|||
}
|
||||
|
||||
case obj.TYPE_CONST:
|
||||
// MOV $c, R
|
||||
// If c is small enough, convert to:
|
||||
// ADD $c, ZERO, R
|
||||
// If not, convert to:
|
||||
// LUI top20bits(c), R
|
||||
// ADD bottom12bits(c), R, R
|
||||
if p.As != AMOV {
|
||||
ctxt.Diag("%v: unsupported constant load", p)
|
||||
}
|
||||
if p.To.Type != obj.TYPE_REG {
|
||||
ctxt.Diag("%v: constant load must target register", p)
|
||||
}
|
||||
off := p.From.Offset
|
||||
to := p.To
|
||||
|
||||
low, high, err := Split32BitImmediate(off)
|
||||
if err != nil {
|
||||
ctxt.Diag("%v: constant %d too large: %v", p, off, err)
|
||||
}
|
||||
|
||||
// LUI is only necessary if the offset doesn't fit in 12-bits.
|
||||
needLUI := high != 0
|
||||
if needLUI {
|
||||
p.As = ALUI
|
||||
p.To = to
|
||||
// Pass top 20 bits to LUI.
|
||||
p.From = obj.Addr{Type: obj.TYPE_CONST, Offset: high}
|
||||
p = obj.Appendp(p, newprog)
|
||||
}
|
||||
p.As = AADDIW
|
||||
p.To = to
|
||||
p.From = obj.Addr{Type: obj.TYPE_CONST, Offset: low}
|
||||
p.Reg = REG_ZERO
|
||||
if needLUI {
|
||||
p.Reg = to.Reg
|
||||
}
|
||||
|
||||
case obj.TYPE_ADDR: // MOV $sym+off(SP/SB), R
|
||||
if p.To.Type != obj.TYPE_REG || p.As != AMOV {
|
||||
|
|
@ -1845,6 +1815,28 @@ func instructionsForMOV(p *obj.Prog) []*instruction {
|
|||
inss := []*instruction{ins}
|
||||
|
||||
switch {
|
||||
case p.From.Type == obj.TYPE_CONST && p.To.Type == obj.TYPE_REG:
|
||||
// Handle constant to register moves.
|
||||
low, high, err := Split32BitImmediate(ins.imm)
|
||||
if err != nil {
|
||||
p.Ctxt.Diag("%v: constant %d too large: %v", p, ins.imm, err)
|
||||
return nil
|
||||
}
|
||||
|
||||
// MOV $c, R -> ADD $c, ZERO, R
|
||||
ins.as, ins.rs1, ins.rs2, ins.imm = AADDIW, REG_ZERO, obj.REG_NONE, low
|
||||
|
||||
// LUI is only necessary if the constant does not fit in 12 bits.
|
||||
if high == 0 {
|
||||
break
|
||||
}
|
||||
|
||||
// LUI top20bits(c), R
|
||||
// ADD bottom12bits(c), R, R
|
||||
insLUI := &instruction{as: ALUI, rd: ins.rd, imm: high}
|
||||
ins.rs1 = ins.rd
|
||||
inss = []*instruction{insLUI, ins}
|
||||
|
||||
case p.From.Type == obj.TYPE_REG && p.To.Type == obj.TYPE_REG:
|
||||
// Handle register to register moves.
|
||||
switch p.As {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue