diff --git a/src/cmd/asm/internal/asm/parse.go b/src/cmd/asm/internal/asm/parse.go index 25d596f4d6656b..6e4b1b80c4e25a 100644 --- a/src/cmd/asm/internal/asm/parse.go +++ b/src/cmd/asm/internal/asm/parse.go @@ -493,7 +493,7 @@ func (p *Parser) operand(a *obj.Addr) { } if haveConstant { p.back() - if p.have(scanner.Float) { + if p.have(scanner.Float) || p.haveIndent("Inf") || p.haveIndent("NaN") { if prefix != '$' { p.errorf("floating-point constant must be an immediate") } @@ -1284,7 +1284,7 @@ func (p *Parser) floatExpr() float64 { return +p.floatExpr() case '-': return -p.floatExpr() - case scanner.Float: + case scanner.Float, scanner.Ident: return p.atof(tok.String()) } p.errorf("unexpected %s evaluating float expression", tok) @@ -1467,6 +1467,16 @@ func (p *Parser) have(token lex.ScanToken) bool { return false } +// have reports whether the remaining tokens (including the current one) contain the specified token. +func (p *Parser) haveIndent(token string) bool { + for i := p.inputPos; i < len(p.input); i++ { + if p.input[i].String() == token { + return true + } + } + return false +} + // at reports whether the next tokens are as requested. func (p *Parser) at(next ...lex.ScanToken) bool { if len(p.input)-p.inputPos < len(next) { diff --git a/src/cmd/asm/internal/asm/testdata/riscv64.s b/src/cmd/asm/internal/asm/testdata/riscv64.s index 4615119af00fd9..170c78ba9d118f 100644 --- a/src/cmd/asm/internal/asm/testdata/riscv64.s +++ b/src/cmd/asm/internal/asm/testdata/riscv64.s @@ -372,6 +372,95 @@ start: // 21.7: Double-Precision Floating-Point Classify Instruction FCLASSD F0, X5 // d31200e2 + // 24: "Zfa" Extension for Additional Floating-Point Instructions + // 24.1: Load-Immediate Instructions + FLIS $(NaN), F1 // d3801ff0 + FLIS $(-1.0), F1 // d30010f0 + FLIS $(-Inf), F1 // d38010f0 + FLIS $(1.52587890625e-05), F1 // d30011f0 + FLIS $(3.0517578125e-05), F1 // d38011f0 + FLIS $(0.00390625), F1 // d30012f0 + FLIS $(0.0078125), F1 // d38012f0 + FLIS $(0.0625), F1 // d30013f0 + FLIS $(0.125), F1 // d38013f0 + FLIS $(0.25), F1 // d30014f0 + FLIS $(0.3125), F1 // d38014f0 + FLIS $(0.375), F1 // d30015f0 + FLIS $(0.4375), F1 // d38015f0 + FLIS $(0.5), F1 // d30016f0 + FLIS $(0.625), F1 // d38016f0 + FLIS $(0.75), F1 // d30017f0 + FLIS $(0.875), F1 // d38017f0 + FLIS $(1.0), F1 // d30018f0 + FLIS $(1.25), F1 // d38018f0 + FLIS $(1.5), F1 // d30019f0 + FLIS $(1.75), F1 // d38019f0 + FLIS $(2.0), F1 // d3001af0 + FLIS $(2.5), F1 // d3801af0 + FLIS $(3.0), F1 // d3001bf0 + FLIS $(4.0), F1 // d3801bf0 + FLIS $(8.0), F1 // d3001cf0 + FLIS $(1.6000000000000001), F1 // d3801cf0 + FLIS $(1.28), F1 // d3001df0 + FLIS $(2.5600000000000001), F1 // d3801df0 + FLIS $(3.27), F1 // d3001ef0 + FLIS $(6.5499999999999998), F1 // d3801ef0 + FLIS $(+Inf), F1 // d3001ff0 + FLIS $(NaN), F1 // d3801ff0 + FLID $(-1.0), F1 // d30010f2 + FLID $(-Inf), F1 // d38010f2 + FLID $(1.52587890625e-05), F1 // d30011f2 + FLID $(3.0517578125e-05), F1 // d38011f2 + FLID $(0.00390625), F1 // d30012f2 + FLID $(0.0078125), F1 // d38012f2 + FLID $(0.0625), F1 // d30013f2 + FLID $(0.125), F1 // d38013f2 + FLID $(0.25), F1 // d30014f2 + FLID $(0.3125), F1 // d38014f2 + FLID $(0.375), F1 // d30015f2 + FLID $(0.4375), F1 // d38015f2 + FLID $(0.5), F1 // d30016f2 + FLID $(0.625), F1 // d38016f2 + FLID $(0.75), F1 // d30017f2 + FLID $(0.875), F1 // d38017f2 + FLID $(1.0), F1 // d30018f2 + FLID $(1.25), F1 // d38018f2 + FLID $(1.5), F1 // d30019f2 + FLID $(1.75), F1 // d38019f2 + FLID $(2.0), F1 // d3001af2 + FLID $(2.5), F1 // d3801af2 + FLID $(3.0), F1 // d3001bf2 + FLID $(4.0), F1 // d3801bf2 + FLID $(8.0), F1 // d3001cf2 + FLID $(1.6000000000000001), F1 // d3801cf2 + FLID $(1.28), F1 // d3001df2 + FLID $(2.5600000000000001), F1 // d3801df2 + FLID $(3.27), F1 // d3001ef2 + FLID $(6.5499999999999998), F1 // d3801ef2 + FLID $(+Inf), F1 // d3001ff2 + FLID $(NaN), F1 // d3801ff2 + + // 24.2: Minimum and Maximum Instructions + FMAXMD F21, F20, F19 // d3395a2b + FMAXMS F21, F20, F19 // d3395a29 + FMINMD F12, F11, F10 // 53a5c52a + FMINMS F12, F11, F10 // 53a5c528 + + // 24.3: Round-to-Integer Instructions + FROUNDD F18, F9 // d3044942 + FROUNDS F18, F9 // d3044940 + FROUNDNXD F18, F9 // d3045942 + FROUNDNXS F18, F9 // d3045940 + + // 24.4: Modular Convert-to-Integer Instruction + FCVTMODWD F1, X11 // d39580c2 + + // 24.6: Comparison Instructions + FLEQD F2, F1, X11 // d3c520a2 + FLEQS F2, F1, X11 // d3c520a0 + FLTQD F18, F9, X11 // d3d524a3 + FLTQS F18, F9, X11 // d3d524a1 + // // "C" Extension for Compressed Instructions, Version 2.0 // diff --git a/src/cmd/internal/obj/riscv/anames.go b/src/cmd/internal/obj/riscv/anames.go index 6c48e2f7de4799..2b0cc3c7a92b07 100644 --- a/src/cmd/internal/obj/riscv/anames.go +++ b/src/cmd/internal/obj/riscv/anames.go @@ -194,6 +194,21 @@ var Anames = []string{ "FLEQ", "FLTQ", "FCLASSQ", + "FLIS", + "FLID", + "FMAXMS", + "FMINMS", + "FMAXMD", + "FMINMD", + "FROUNDS", + "FROUNDNXS", + "FROUNDD", + "FROUNDNXD", + "FCVTMODWD", + "FLEQS", + "FLTQS", + "FLEQD", + "FLTQD", "CLWSP", "CLDSP", "CFLDSP", diff --git a/src/cmd/internal/obj/riscv/cpu.go b/src/cmd/internal/obj/riscv/cpu.go index a91395dd380b6a..1d46cae53d21df 100644 --- a/src/cmd/internal/obj/riscv/cpu.go +++ b/src/cmd/internal/obj/riscv/cpu.go @@ -585,6 +585,32 @@ const ( // 22.5: Quad-Precision Floating-Point Classify Instruction AFCLASSQ + // 24: "Zfa" Extension for Additional Floating-Point Instructions + // 24.1: Load-Immediate Instructions + AFLIS + AFLID + + // 24.2: Minimum and Maximum Instructions + AFMAXMS + AFMINMS + AFMAXMD + AFMINMD + + // 24.3: Round-to-Integer Instructions + AFROUNDS + AFROUNDNXS + AFROUNDD + AFROUNDNXD + + // 24.4: Modular Convert-to-Integer Instruction + AFCVTMODWD + + // 24.6: Comparison Instructions + AFLEQS + AFLTQS + AFLEQD + AFLTQD + // // "C" Extension for Compressed Instructions // diff --git a/src/cmd/internal/obj/riscv/inst.go b/src/cmd/internal/obj/riscv/inst.go index a5b3acdb18110c..ffbea7bfa9159d 100644 --- a/src/cmd/internal/obj/riscv/inst.go +++ b/src/cmd/internal/obj/riscv/inst.go @@ -1,4 +1,4 @@ -// Code generated by ./parse.py -go rv64_a rv64_c rv64_d rv64_f rv64_i rv64_m rv64_q rv64_zba rv64_zbb rv64_zbs rv_a rv_c rv_c_d rv_d rv_f rv_i rv_m rv_q rv_s rv_system rv_v rv_zba rv_zbb rv_zbs rv_zicond rv_zicsr; DO NOT EDIT. +// Code generated by uv run riscv_opcodes -go rv64_a rv64_c rv64_d rv64_f rv64_i rv64_m rv64_q rv64_zba rv64_zbb rv64_zbs rv_a rv_c rv_c_d rv_d rv_d_zfa rv_f rv_f_zfa rv_i rv_m rv_q rv_s rv_system rv_v rv_zba rv_zbb rv_zbs rv_zicond rv_zicsr; DO NOT EDIT. package riscv import "cmd/internal/obj" @@ -282,6 +282,8 @@ func encode(a obj.As) *inst { return &inst{0x53, 0x0, 0x0, 0x1, -927, 0x63} case AFCVTWUS: return &inst{0x53, 0x0, 0x0, 0x1, -1023, 0x60} + case AFCVTMODWD: + return &inst{0x53, 0x1, 0x0, 0x8, -984, 0x61} case AFDIVD: return &inst{0x53, 0x0, 0x0, 0x0, 416, 0xd} case AFDIVQ: @@ -304,6 +306,14 @@ func encode(a obj.As) *inst { return &inst{0x53, 0x0, 0x0, 0x0, -1440, 0x53} case AFLES: return &inst{0x53, 0x0, 0x0, 0x0, -1536, 0x50} + case AFLEQD: + return &inst{0x53, 0x4, 0x0, 0x0, -1504, 0x51} + case AFLEQS: + return &inst{0x53, 0x4, 0x0, 0x0, -1536, 0x50} + case AFLID: + return &inst{0x53, 0x0, 0x0, 0x1, -223, 0x79} + case AFLIS: + return &inst{0x53, 0x0, 0x0, 0x1, -255, 0x78} case AFLQ: return &inst{0x7, 0x4, 0x0, 0x0, 0, 0x0} case AFLTD: @@ -312,6 +322,10 @@ func encode(a obj.As) *inst { return &inst{0x53, 0x1, 0x0, 0x0, -1440, 0x53} case AFLTS: return &inst{0x53, 0x1, 0x0, 0x0, -1536, 0x50} + case AFLTQD: + return &inst{0x53, 0x5, 0x0, 0x0, -1504, 0x51} + case AFLTQS: + return &inst{0x53, 0x5, 0x0, 0x0, -1536, 0x50} case AFLW: return &inst{0x7, 0x2, 0x0, 0x0, 0, 0x0} case AFMADDD: @@ -326,12 +340,20 @@ func encode(a obj.As) *inst { return &inst{0x53, 0x1, 0x0, 0x0, 736, 0x17} case AFMAXS: return &inst{0x53, 0x1, 0x0, 0x0, 640, 0x14} + case AFMAXMD: + return &inst{0x53, 0x3, 0x0, 0x0, 672, 0x15} + case AFMAXMS: + return &inst{0x53, 0x3, 0x0, 0x0, 640, 0x14} case AFMIND: return &inst{0x53, 0x0, 0x0, 0x0, 672, 0x15} case AFMINQ: return &inst{0x53, 0x0, 0x0, 0x0, 736, 0x17} case AFMINS: return &inst{0x53, 0x0, 0x0, 0x0, 640, 0x14} + case AFMINMD: + return &inst{0x53, 0x2, 0x0, 0x0, 672, 0x15} + case AFMINMS: + return &inst{0x53, 0x2, 0x0, 0x0, 640, 0x14} case AFMSUBD: return &inst{0x47, 0x0, 0x0, 0x0, 32, 0x1} case AFMSUBQ: @@ -364,6 +386,14 @@ func encode(a obj.As) *inst { return &inst{0x4b, 0x0, 0x0, 0x0, 96, 0x3} case AFNMSUBS: return &inst{0x4b, 0x0, 0x0, 0x0, 0, 0x0} + case AFROUNDD: + return &inst{0x53, 0x0, 0x0, 0x4, 1060, 0x21} + case AFROUNDS: + return &inst{0x53, 0x0, 0x0, 0x4, 1028, 0x20} + case AFROUNDNXD: + return &inst{0x53, 0x0, 0x0, 0x5, 1061, 0x21} + case AFROUNDNXS: + return &inst{0x53, 0x0, 0x0, 0x5, 1029, 0x20} case AFSD: return &inst{0x27, 0x3, 0x0, 0x0, 0, 0x0} case AFSGNJD: @@ -1829,8 +1859,6 @@ var csrs = map[uint16]string{ 0x48: "USCRATCHCSW", 0x49: "USCRATCHCSWL", 0x100: "SSTATUS", - 0x102: "SEDELEG", - 0x103: "SIDELEG", 0x104: "SIE", 0x105: "STVEC", 0x106: "SCOUNTEREN", diff --git a/src/cmd/internal/obj/riscv/obj.go b/src/cmd/internal/obj/riscv/obj.go index 043be17c07c0f0..48c518ddf491be 100644 --- a/src/cmd/internal/obj/riscv/obj.go +++ b/src/cmd/internal/obj/riscv/obj.go @@ -159,6 +159,16 @@ func progedit(ctxt *obj.Link, p *obj.Prog, newprog obj.ProgAlloc) { p.From.Reg = REG_ZERO break } + if buildcfg.GORISCV64 >= 23 && p.To.Type == obj.TYPE_REG { + if math.IsNaN(float64(f32)) { + p.As = AFLIS + break + } + if _, ok := fimmMapping[float64(f32)]; ok { + p.As = AFLIS + break + } + } p.From.Type = obj.TYPE_MEM p.From.Sym = ctxt.Float32Sym(f32) p.From.Name = obj.NAME_EXTERN @@ -173,6 +183,16 @@ func progedit(ctxt *obj.Link, p *obj.Prog, newprog obj.ProgAlloc) { p.From.Reg = REG_ZERO break } + if buildcfg.GORISCV64 >= 23 && p.To.Type == obj.TYPE_REG { + if math.IsNaN(f64) { + p.As = AFLID + break + } + if _, ok := fimmMapping[f64]; ok { + p.As = AFLID + break + } + } p.From.Type = obj.TYPE_MEM p.From.Sym = ctxt.Float64Sym(f64) p.From.Name = obj.NAME_EXTERN @@ -2548,6 +2568,32 @@ var instructions = [ALAST & obj.AMask]instructionData{ // 21.7: Double-Precision Floating-Point Classify Instruction AFCLASSD & obj.AMask: {enc: rFIEncoding}, + // 24: "Zfa" Extension for Additional Floating-Point Instructions + // 24.1: Load-Immediate Instructions + AFLIS & obj.AMask: {enc: rIFEncoding}, + AFLID & obj.AMask: {enc: rIFEncoding}, + + // 24.2: Minimum and Maximum Instructions + AFMAXMS & obj.AMask: {enc: rFFFEncoding}, + AFMINMS & obj.AMask: {enc: rFFFEncoding}, + AFMAXMD & obj.AMask: {enc: rFFFEncoding}, + AFMINMD & obj.AMask: {enc: rFFFEncoding}, + + // 24.3: Round-to-Integer Instructions + AFROUNDS & obj.AMask: {enc: rFFEncoding}, + AFROUNDNXS & obj.AMask: {enc: rFFEncoding}, + AFROUNDD & obj.AMask: {enc: rFFEncoding}, + AFROUNDNXD & obj.AMask: {enc: rFFEncoding}, + + // 24.4: Modular Convert-to-Integer Instruction + AFCVTMODWD & obj.AMask: {enc: rFIEncoding}, + + // 24.6: Comparison Instructions + AFLEQS & obj.AMask: {enc: rFFIEncoding}, + AFLTQS & obj.AMask: {enc: rFFIEncoding}, + AFLEQD & obj.AMask: {enc: rFFIEncoding}, + AFLTQD & obj.AMask: {enc: rFFIEncoding}, + // // "C" Extension for Compressed Instructions, Version 2.0 // @@ -4172,6 +4218,40 @@ func instructionsForRotate(p *obj.Prog, ins *instruction) []*instruction { } } +var fimmMapping = map[float64]uint32{ + -1.0: 0, + math.Inf(-1): 1, + 1.52587890625e-05: 2, + 3.0517578125e-05: 3, + 0.00390625: 4, + 0.0078125: 5, + 0.0625: 6, + 0.125: 7, + 0.25: 8, + 0.3125: 9, + 0.375: 10, + 0.4375: 11, + 0.5: 12, + 0.625: 13, + 0.75: 14, + 0.875: 15, + 1.0: 16, + 1.25: 17, + 1.5: 18, + 1.75: 19, + 2.0: 20, + 2.5: 21, + 3.0: 22, + 4.0: 23, + 8.0: 24, + 1.6000000000000001: 25, + 1.28: 26, + 2.5600000000000001: 27, + 3.27: 28, + 6.5499999999999998: 29, + math.Inf(1): 30, +} + // instructionsForMinMax returns the machine instructions for an integer minimum or maximum. func instructionsForMinMax(p *obj.Prog, ins *instruction) []*instruction { if buildcfg.GORISCV64 >= 22 { @@ -4346,6 +4426,20 @@ func instructionsForProg(p *obj.Prog, compress bool) []*instruction { } ins.rs2 = obj.REG_NONE + case AFLIS, AFLID: + fimm := p.From.Val.(float64) + var index uint32 + // NaN is special as it can't be used in comparison. + if math.IsNaN(fimm) { + index = 31 + } else if idx, ok := fimmMapping[fimm]; ok { + index = idx + } else { + p.Ctxt.Diag("%v: unknown floating point immediate", fimm) + return nil + } + ins.rs2 = REG_ZERO + index + case AFENCE: ins.rd, ins.rs1, ins.rs2 = REG_ZERO, REG_ZERO, obj.REG_NONE ins.imm = 0x0ff diff --git a/src/cmd/internal/obj/util.go b/src/cmd/internal/obj/util.go index 7d87bff94918b4..a60d5b2509f6fc 100644 --- a/src/cmd/internal/obj/util.go +++ b/src/cmd/internal/obj/util.go @@ -11,6 +11,7 @@ import ( "internal/abi" "internal/buildcfg" "io" + "math" "strings" ) @@ -322,9 +323,10 @@ func writeDconv(w io.Writer, p *Prog, a *Addr, abiDetail bool) { } case TYPE_FCONST: - str := fmt.Sprintf("%.17g", a.Val.(float64)) + fimm := a.Val.(float64) + str := fmt.Sprintf("%.17g", fimm) // Make sure 1 prints as 1.0 - if !strings.ContainsAny(str, ".e") { + if !strings.ContainsAny(str, ".e") && !math.IsNaN(fimm) && !math.IsInf(fimm, -1) && !math.IsInf(fimm, 1) { str += ".0" } fmt.Fprintf(w, "$(%s)", str)