diff options
| author | Meng Zhuo <mzh@golangcn.org> | 2023-06-20 11:16:56 +0800 |
|---|---|---|
| committer | M Zhuo <mzh@golangcn.org> | 2024-02-21 14:34:57 +0000 |
| commit | 3580c212c2e3276077540afdab3478a7336d698b (patch) | |
| tree | 1a9e09ef35893fbb9f356b5b97b00fdd79e479bb /src/cmd/internal/obj | |
| parent | d4112310a4d3b1981d77226a3d52a8b566b0c0bc (diff) | |
| download | go-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.go | 2 | ||||
| -rw-r--r-- | src/cmd/internal/obj/riscv/cpu.go | 51 | ||||
| -rw-r--r-- | src/cmd/internal/obj/riscv/list.go | 16 | ||||
| -rw-r--r-- | src/cmd/internal/obj/riscv/obj.go | 17 |
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, |
