mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
cmd/internal/obj/riscv: improve handling of float point moves
Translate moves from an integer register to a floating point register, or from a floating point register to an integer register, to the appropriate move instruction (i.e. FMVXW/FMVWX/FMVXD/FMVDX). Add support for MOVF with a constant - we previously added support for MOVD but not for MOVF. Add special handling for 0.0, which we can translate to a move from the zero register to a floating point register (leveraging the above mentioned change). Change-Id: If8df2f5610e69b4ec0af85efb884951024685f5b Reviewed-on: https://go-review.googlesource.com/c/go/+/703216 Reviewed-by: Meng Zhuo <mengzhuo1203@gmail.com> Reviewed-by: Mark Freeman <markfreeman@google.com> Reviewed-by: Michael Knyszek <mknyszek@google.com> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Reviewed-by: Mark Ryan <markdryan@rivosinc.com>
This commit is contained in:
parent
281c632e6e
commit
e2cfc1eb3a
2 changed files with 61 additions and 8 deletions
13
src/cmd/asm/internal/asm/testdata/riscv64.s
vendored
13
src/cmd/asm/internal/asm/testdata/riscv64.s
vendored
|
|
@ -1952,12 +1952,23 @@ start:
|
||||||
MOVF 4(X5), F0 // 07a04200
|
MOVF 4(X5), F0 // 07a04200
|
||||||
MOVF F0, 4(X5) // 27a20200
|
MOVF F0, 4(X5) // 27a20200
|
||||||
MOVF F0, F1 // d3000020
|
MOVF F0, F1 // d3000020
|
||||||
|
MOVF X1, F3 // d38100f0
|
||||||
|
MOVF F3, X1 // d38001e0
|
||||||
|
MOVF X0, F3 // d30100f0
|
||||||
|
MOVF $(0.0), F3 // d30100f0
|
||||||
|
|
||||||
|
// Converted to load of symbol (AUIPC + FLW)
|
||||||
|
MOVF $(709.78271289338397), F3 // 970f000087a10f00
|
||||||
|
|
||||||
MOVD 4(X5), F0 // 07b04200
|
MOVD 4(X5), F0 // 07b04200
|
||||||
MOVD F0, 4(X5) // 27b20200
|
MOVD F0, 4(X5) // 27b20200
|
||||||
MOVD F0, F1 // d3000022
|
MOVD F0, F1 // d3000022
|
||||||
|
MOVD F3, X1 // d38001e2
|
||||||
|
MOVD X1, F3 // d38100f2
|
||||||
|
MOVD X0, F3 // d30100f2
|
||||||
|
MOVD $(0.0), F3 // d30100f2
|
||||||
|
|
||||||
// Convert to load of symbol (AUIPC + FLD)
|
// Converted to load of symbol (AUIPC + FLD)
|
||||||
MOVD $(709.78271289338397), F3 // 970f000087b10f00
|
MOVD $(709.78271289338397), F3 // 970f000087b10f00
|
||||||
|
|
||||||
// TLS load with local-exec (LUI + ADDIW + ADD of TP + load)
|
// TLS load with local-exec (LUI + ADDIW + ADD of TP + load)
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,7 @@ import (
|
||||||
"internal/abi"
|
"internal/abi"
|
||||||
"internal/buildcfg"
|
"internal/buildcfg"
|
||||||
"log"
|
"log"
|
||||||
|
"math"
|
||||||
"math/bits"
|
"math/bits"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
@ -145,9 +146,29 @@ func progedit(ctxt *obj.Link, p *obj.Prog, newprog obj.ProgAlloc) {
|
||||||
p.From.Offset = 0
|
p.From.Offset = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case AMOVF:
|
||||||
|
if p.From.Type == obj.TYPE_FCONST && p.From.Name == obj.NAME_NONE && p.From.Reg == obj.REG_NONE {
|
||||||
|
f64 := p.From.Val.(float64)
|
||||||
|
f32 := float32(f64)
|
||||||
|
if math.Float32bits(f32) == 0 {
|
||||||
|
p.From.Type = obj.TYPE_REG
|
||||||
|
p.From.Reg = REG_ZERO
|
||||||
|
break
|
||||||
|
}
|
||||||
|
p.From.Type = obj.TYPE_MEM
|
||||||
|
p.From.Sym = ctxt.Float32Sym(f32)
|
||||||
|
p.From.Name = obj.NAME_EXTERN
|
||||||
|
p.From.Offset = 0
|
||||||
|
}
|
||||||
|
|
||||||
case AMOVD:
|
case AMOVD:
|
||||||
if p.From.Type == obj.TYPE_FCONST && p.From.Name == obj.NAME_NONE && p.From.Reg == obj.REG_NONE {
|
if p.From.Type == obj.TYPE_FCONST && p.From.Name == obj.NAME_NONE && p.From.Reg == obj.REG_NONE {
|
||||||
f64 := p.From.Val.(float64)
|
f64 := p.From.Val.(float64)
|
||||||
|
if math.Float64bits(f64) == 0 {
|
||||||
|
p.From.Type = obj.TYPE_REG
|
||||||
|
p.From.Reg = REG_ZERO
|
||||||
|
break
|
||||||
|
}
|
||||||
p.From.Type = obj.TYPE_MEM
|
p.From.Type = obj.TYPE_MEM
|
||||||
p.From.Sym = ctxt.Float64Sym(f64)
|
p.From.Sym = ctxt.Float64Sym(f64)
|
||||||
p.From.Name = obj.NAME_EXTERN
|
p.From.Name = obj.NAME_EXTERN
|
||||||
|
|
@ -3254,16 +3275,37 @@ func instructionsForMOV(p *obj.Prog) []*instruction {
|
||||||
case p.From.Type == obj.TYPE_REG && p.To.Type == obj.TYPE_REG:
|
case p.From.Type == obj.TYPE_REG && p.To.Type == obj.TYPE_REG:
|
||||||
// Handle register to register moves.
|
// Handle register to register moves.
|
||||||
switch p.As {
|
switch p.As {
|
||||||
case AMOV: // MOV Ra, Rb -> ADDI $0, Ra, Rb
|
case AMOV:
|
||||||
|
// MOV Ra, Rb -> ADDI $0, Ra, Rb
|
||||||
ins.as, ins.rs1, ins.rs2, ins.imm = AADDI, uint32(p.From.Reg), obj.REG_NONE, 0
|
ins.as, ins.rs1, ins.rs2, ins.imm = AADDI, uint32(p.From.Reg), obj.REG_NONE, 0
|
||||||
case AMOVW: // MOVW Ra, Rb -> ADDIW $0, Ra, Rb
|
case AMOVW:
|
||||||
|
// MOVW Ra, Rb -> ADDIW $0, Ra, Rb
|
||||||
ins.as, ins.rs1, ins.rs2, ins.imm = AADDIW, uint32(p.From.Reg), obj.REG_NONE, 0
|
ins.as, ins.rs1, ins.rs2, ins.imm = AADDIW, uint32(p.From.Reg), obj.REG_NONE, 0
|
||||||
case AMOVBU: // MOVBU Ra, Rb -> ANDI $255, Ra, Rb
|
case AMOVBU:
|
||||||
|
// MOVBU Ra, Rb -> ANDI $255, Ra, Rb
|
||||||
ins.as, ins.rs1, ins.rs2, ins.imm = AANDI, uint32(p.From.Reg), obj.REG_NONE, 255
|
ins.as, ins.rs1, ins.rs2, ins.imm = AANDI, uint32(p.From.Reg), obj.REG_NONE, 255
|
||||||
case AMOVF: // MOVF Ra, Rb -> FSGNJS Ra, Ra, Rb
|
case AMOVF:
|
||||||
|
// MOVF Ra, Rb -> FSGNJS Ra, Ra, Rb
|
||||||
|
// or -> FMVWX Ra, Rb
|
||||||
|
// or -> FMVXW Ra, Rb
|
||||||
|
if ins.rs2 >= REG_X0 && ins.rs2 <= REG_X31 && ins.rd >= REG_F0 && ins.rd <= REG_F31 {
|
||||||
|
ins.as = AFMVWX
|
||||||
|
} else if ins.rs2 >= REG_F0 && ins.rs2 <= REG_F31 && ins.rd >= REG_X0 && ins.rd <= REG_X31 {
|
||||||
|
ins.as = AFMVXW
|
||||||
|
} else {
|
||||||
ins.as, ins.rs1 = AFSGNJS, uint32(p.From.Reg)
|
ins.as, ins.rs1 = AFSGNJS, uint32(p.From.Reg)
|
||||||
case AMOVD: // MOVD Ra, Rb -> FSGNJD Ra, Ra, Rb
|
}
|
||||||
|
case AMOVD:
|
||||||
|
// MOVD Ra, Rb -> FSGNJD Ra, Ra, Rb
|
||||||
|
// or -> FMVDX Ra, Rb
|
||||||
|
// or -> FMVXD Ra, Rb
|
||||||
|
if ins.rs2 >= REG_X0 && ins.rs2 <= REG_X31 && ins.rd >= REG_F0 && ins.rd <= REG_F31 {
|
||||||
|
ins.as = AFMVDX
|
||||||
|
} else if ins.rs2 >= REG_F0 && ins.rs2 <= REG_F31 && ins.rd >= REG_X0 && ins.rd <= REG_X31 {
|
||||||
|
ins.as = AFMVXD
|
||||||
|
} else {
|
||||||
ins.as, ins.rs1 = AFSGNJD, uint32(p.From.Reg)
|
ins.as, ins.rs1 = AFSGNJD, uint32(p.From.Reg)
|
||||||
|
}
|
||||||
case AMOVB, AMOVH:
|
case AMOVB, AMOVH:
|
||||||
if buildcfg.GORISCV64 >= 22 {
|
if buildcfg.GORISCV64 >= 22 {
|
||||||
// Use SEXTB or SEXTH to extend.
|
// Use SEXTB or SEXTH to extend.
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue