aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/internal/obj
diff options
context:
space:
mode:
authorMeng Zhuo <mzh@golangcn.org>2023-06-20 11:16:56 +0800
committerM Zhuo <mzh@golangcn.org>2024-02-21 14:34:57 +0000
commit3580c212c2e3276077540afdab3478a7336d698b (patch)
tree1a9e09ef35893fbb9f356b5b97b00fdd79e479bb /src/cmd/internal/obj
parentd4112310a4d3b1981d77226a3d52a8b566b0c0bc (diff)
downloadgo-3580c212c2e3276077540afdab3478a7336d698b.tar.xz
cmd/asm, cmd/internal/obj: enable rounding mode suffix for riscv64
This CL adds rounding modes for riscv64 floating point conversion instructions by suffix with 5 modes: RNE, RTZ, RDN, RUP and RMM. For example, for round to nearest (RNE), we can use `FCVTLD.RNE` According to RISCV manual 8.7 and 9.5, we changed these conversion instructions: FCVTWS FCVTLS FCVTWUS FCVTLUS FCVTWD FCVTLD FCVTWUD FCVTLUD Note: Round towards zero (RTZ) by default for all these instructions above. Change-Id: I491e522e14d721e24aa7f528ee0c4640c54c5808 Reviewed-on: https://go-review.googlesource.com/c/go/+/504736 Reviewed-by: Joel Sing <joel@sing.id.au> Run-TryBot: M Zhuo <mengzhuo1203@gmail.com> Reviewed-by: Cherry Mui <cherryyz@google.com> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> TryBot-Result: Gopher Robot <gobot@golang.org> Reviewed-by: Than McIntosh <thanm@google.com>
Diffstat (limited to 'src/cmd/internal/obj')
-rw-r--r--src/cmd/internal/obj/link.go2
-rw-r--r--src/cmd/internal/obj/riscv/cpu.go51
-rw-r--r--src/cmd/internal/obj/riscv/list.go16
-rw-r--r--src/cmd/internal/obj/riscv/obj.go17
4 files changed, 82 insertions, 4 deletions
diff --git a/src/cmd/internal/obj/link.go b/src/cmd/internal/obj/link.go
index 0b7878656c..5be493e176 100644
--- a/src/cmd/internal/obj/link.go
+++ b/src/cmd/internal/obj/link.go
@@ -314,7 +314,7 @@ type Prog struct {
RegTo2 int16 // 2nd destination operand
Mark uint16 // bitmask of arch-specific items
Optab uint16 // arch-specific opcode index
- Scond uint8 // bits that describe instruction suffixes (e.g. ARM conditions)
+ Scond uint8 // bits that describe instruction suffixes (e.g. ARM conditions, RISCV Rounding Mode)
Back uint8 // for x86 back end: backwards branch state
Ft uint8 // for x86 back end: type index of Prog.From
Tt uint8 // for x86 back end: type index of Prog.To
diff --git a/src/cmd/internal/obj/riscv/cpu.go b/src/cmd/internal/obj/riscv/cpu.go
index edd1ac820b..919f07b1a9 100644
--- a/src/cmd/internal/obj/riscv/cpu.go
+++ b/src/cmd/internal/obj/riscv/cpu.go
@@ -28,7 +28,12 @@
package riscv
-import "cmd/internal/obj"
+import (
+ "errors"
+ "fmt"
+
+ "cmd/internal/obj"
+)
//go:generate go run ../stringer.go -i $GOFILE -o anames.go -p riscv
@@ -607,6 +612,50 @@ const (
ALAST
)
+// opSuffix encoding to uint8 which fit into p.Scond
+var rmSuffixSet = map[string]uint8{
+ "RNE": RM_RNE,
+ "RTZ": RM_RTZ,
+ "RDN": RM_RDN,
+ "RUP": RM_RUP,
+ "RMM": RM_RMM,
+}
+
+const rmSuffixBit uint8 = 1 << 7
+
+func rmSuffixEncode(s string) (uint8, error) {
+ if s == "" {
+ return 0, errors.New("empty suffix")
+ }
+ enc, ok := rmSuffixSet[s]
+ if !ok {
+ return 0, fmt.Errorf("invalid encoding for unknown suffix:%q", s)
+ }
+ return enc | rmSuffixBit, nil
+}
+
+func rmSuffixString(u uint8) (string, error) {
+ if u&rmSuffixBit == 0 {
+ return "", fmt.Errorf("invalid suffix, require round mode bit:%x", u)
+ }
+
+ u &^= rmSuffixBit
+ for k, v := range rmSuffixSet {
+ if v == u {
+ return k, nil
+ }
+ }
+ return "", fmt.Errorf("unknown suffix:%x", u)
+}
+
+const (
+ RM_RNE uint8 = iota // Round to Nearest, ties to Even
+ RM_RTZ // Round towards Zero
+ RM_RDN // Round Down
+ RM_RUP // Round Up
+ RM_RMM // Round to Nearest, ties to Max Magnitude
+)
+
// All unary instructions which write to their arguments (as opposed to reading
// from them) go here. The assembly parser uses this information to populate
// its AST in a semantically reasonable way.
diff --git a/src/cmd/internal/obj/riscv/list.go b/src/cmd/internal/obj/riscv/list.go
index de90961e32..bc87539f27 100644
--- a/src/cmd/internal/obj/riscv/list.go
+++ b/src/cmd/internal/obj/riscv/list.go
@@ -13,6 +13,7 @@ import (
func init() {
obj.RegisterRegister(obj.RBaseRISCV, REG_END, RegName)
obj.RegisterOpcode(obj.ABaseRISCV, Anames)
+ obj.RegisterOpSuffix("riscv64", opSuffixString)
}
func RegName(r int) string {
@@ -31,3 +32,18 @@ func RegName(r int) string {
return fmt.Sprintf("Rgok(%d)", r-obj.RBaseRISCV)
}
}
+
+func opSuffixString(s uint8) string {
+ if s&rmSuffixBit == 0 {
+ return ""
+ }
+
+ ss, err := rmSuffixString(s)
+ if err != nil {
+ ss = fmt.Sprintf("<invalid 0x%x>", s)
+ }
+ if ss == "" {
+ return ss
+ }
+ return fmt.Sprintf(".%s", ss)
+}
diff --git a/src/cmd/internal/obj/riscv/obj.go b/src/cmd/internal/obj/riscv/obj.go
index 11d6c202ea..3ec740f85a 100644
--- a/src/cmd/internal/obj/riscv/obj.go
+++ b/src/cmd/internal/obj/riscv/obj.go
@@ -28,6 +28,7 @@ import (
"internal/abi"
"log"
"math/bits"
+ "strings"
)
func buildop(ctxt *obj.Link) {}
@@ -2273,8 +2274,12 @@ func instructionsForProg(p *obj.Prog) []*instruction {
ins.imm = 0x0ff
case AFCVTWS, AFCVTLS, AFCVTWUS, AFCVTLUS, AFCVTWD, AFCVTLD, AFCVTWUD, AFCVTLUD:
- // Set the rounding mode in funct3 to round to zero.
- ins.funct3 = 1
+ // Set the default rounding mode in funct3 to round to zero.
+ if p.Scond&rmSuffixBit == 0 {
+ ins.funct3 = uint32(RM_RTZ)
+ } else {
+ ins.funct3 = uint32(p.Scond &^ rmSuffixBit)
+ }
case AFNES, AFNED:
// Replace FNE[SD] with FEQ[SD] and NOT.
@@ -2478,6 +2483,14 @@ func isUnsafePoint(p *obj.Prog) bool {
return p.Mark&USES_REG_TMP == USES_REG_TMP || p.From.Reg == REG_TMP || p.To.Reg == REG_TMP || p.Reg == REG_TMP
}
+func ParseSuffix(prog *obj.Prog, cond string) (err error) {
+ switch prog.As {
+ case AFCVTWS, AFCVTLS, AFCVTWUS, AFCVTLUS, AFCVTWD, AFCVTLD, AFCVTWUD, AFCVTLUD:
+ prog.Scond, err = rmSuffixEncode(strings.TrimPrefix(cond, "."))
+ }
+ return
+}
+
var LinkRISCV64 = obj.LinkArch{
Arch: sys.ArchRISCV64,
Init: buildop,