]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/internal/obj/riscv: implement floating point instructions
authorJoel Sing <joel@sing.id.au>
Wed, 18 Sep 2019 15:01:07 +0000 (01:01 +1000)
committerJoel Sing <joel@sing.id.au>
Wed, 25 Sep 2019 08:25:43 +0000 (08:25 +0000)
Add support for assembling various single-precision and double-precision
floating point instructions.

Based on the riscv-go port.

Updates #27532

Change-Id: Iac1aec9b03bb6cbf116b229daeef944d4df550fa
Reviewed-on: https://go-review.googlesource.com/c/go/+/196839
Reviewed-by: Cherry Zhang <cherryyz@google.com>
Run-TryBot: Cherry Zhang <cherryyz@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>

src/cmd/asm/internal/asm/testdata/riscvenc.s
src/cmd/internal/obj/riscv/anames.go
src/cmd/internal/obj/riscv/cpu.go
src/cmd/internal/obj/riscv/obj.go

index 8ee7f18a16ea45450eaa166a39cbb73ddf3fe04f..f0d31fda87cf171b9f4d4b891ef46fe36c7fb77c 100644 (file)
@@ -95,7 +95,7 @@ TEXT asmtest(SB),DUPOK|NOSPLIT,$0
        SB      $0, X5, X6                              // 23005300
        SB      $4, X5, X6                              // 23025300
 
-        // 5.2: Integer Computational Instructions (RV64I)
+       // 5.2: Integer Computational Instructions (RV64I)
        ADDIW   $1, X5, X6                              // 1b831200
        SLLIW   $1, X5, X6                              // 1b931200
        SRLIW   $1, X5, X6                              // 1bd31200
@@ -132,6 +132,75 @@ TEXT asmtest(SB),DUPOK|NOSPLIT,$0
        RDTIME          X5                              // f32210c0
        RDINSTRET       X5                              // f32220c0
 
+       // 11.5: Single-Precision Load and Store Instructions
+       FLW     $0, X5, F0                              // 07a00200
+       FLW     $4, X5, F0                              // 07a04200
+       FSW     $0, F0, X5                              // 27a00200
+       FSW     $4, F0, X5                              // 27a20200
+
+       // 11.6: Single-Precision Floating-Point Computational Instructions
+       FADDS   F1, F0, F2                              // 53011000
+       FSUBS   F1, F0, F2                              // 53011008
+       FMULS   F1, F0, F2                              // 53011010
+       FDIVS   F1, F0, F2                              // 53011018
+       FMINS   F1, F0, F2                              // 53011028
+       FMAXS   F1, F0, F2                              // 53111028
+       FSQRTS  F0, F1                                  // d3000058
+
+       // 11.7: Single-Precision Floating-Point Conversion and Move Instructions
+       FCVTWS  F0, X5                                  // d31200c0
+       FCVTLS  F0, X5                                  // d31220c0
+       FCVTSW  X5, F0                                  // 538002d0
+       FCVTSL  X5, F0                                  // 538022d0
+       FCVTWUS F0, X5                                  // d31210c0
+       FCVTLUS F0, X5                                  // d31230c0
+       FCVTSWU X5, F0                                  // 538012d0
+       FCVTSLU X5, F0                                  // 538032d0
+       FSGNJS  F1, F0, F2                              // 53011020
+       FSGNJNS F1, F0, F2                              // 53111020
+       FSGNJXS F1, F0, F2                              // 53211020
+       FMVXS   F0, X5                                  // d30200e0
+       FMVSX   X5, F0                                  // 538002f0
+       FMVXW   F0, X5                                  // d30200e0
+       FMVWX   X5, F0                                  // 538002f0
+
+       // 11.8: Single-Precision Floating-Point Compare Instructions
+       FEQS    F0, F1, X7                              // d3a300a0
+       FLTS    F0, F1, X7                              // d39300a0
+       FLES    F0, F1, X7                              // d38300a0
+
+       // 12.3: Double-Precision Load and Store Instructions
+       FLD     $0, X5, F0                              // 07b00200
+       FLD     $4, X5, F0                              // 07b04200
+       FSD     $0, F0, X5                              // 27b00200
+       FSD     $4, F0, X5                              // 27b20200
+
+       // 12.4: Double-Precision Floating-Point Computational Instructions
+       FADDD   F1, F0, F2                              // 53011002
+       FSUBD   F1, F0, F2                              // 5301100a
+       FMULD   F1, F0, F2                              // 53011012
+       FDIVD   F1, F0, F2                              // 5301101a
+       FMIND   F1, F0, F2                              // 5301102a
+       FMAXD   F1, F0, F2                              // 5311102a
+       FSQRTD  F0, F1                                  // d300005a
+
+       // 12.5: Double-Precision Floating-Point Conversion and Move Instructions
+       FCVTWD  F0, X5                                  // d31200c2
+       FCVTLD  F0, X5                                  // d31220c2
+       FCVTDW  X5, F0                                  // 538002d2
+       FCVTDL  X5, F0                                  // 538022d2
+       FCVTWUD F0, X5                                  // d31210c2
+       FCVTLUD F0, X5                                  // d31230c2
+       FCVTDWU X5, F0                                  // 538012d2
+       FCVTDLU X5, F0                                  // 538032d2
+       FCVTSD  F0, F1                                  // d3001040
+       FCVTDS  F0, F1                                  // d3000042
+       FSGNJD  F1, F0, F2                              // 53011022
+       FSGNJND F1, F0, F2                              // 53111022
+       FSGNJXD F1, F0, F2                              // 53211022
+       FMVXD   F0, X5                                  // d30200e2
+       FMVDX   X5, F0                                  // 538002f2
+
        // Privileged ISA
 
        // 3.2.1: Environment Call and Breakpoint
index c034b637bdb3c7cc588322e9c7d4947d4d1a2261..7d0e52f91bf8c5417b1823df72d99dce209e3025 100644 (file)
@@ -133,10 +133,10 @@ var Anames = []string{
        "FSGNJS",
        "FSGNJNS",
        "FSGNJXS",
-       "FMVSX",
        "FMVXS",
-       "FMVWX",
+       "FMVSX",
        "FMVXW",
+       "FMVWX",
        "FEQS",
        "FLTS",
        "FLES",
index 8c6817284b03c27ab2d0319c79402cfc4648133b..0f3371667656291c7e411270a023890536e5970c 100644 (file)
@@ -368,10 +368,10 @@ const (
        AFSGNJS
        AFSGNJNS
        AFSGNJXS
-       AFMVSX
        AFMVXS
-       AFMVWX
+       AFMVSX
        AFMVXW
+       AFMVWX
 
        // 11.8: Single-Precision Floating-Point Compare Instructions
        AFEQS
index 46188c1e300639aec971695ce382eb8329ffb155..578b4e8ccee713a4b66c524d5ec533ec8575957b 100644 (file)
@@ -96,6 +96,16 @@ func progedit(ctxt *obj.Link, p *obj.Prog, newprog obj.ProgAlloc) {
                if p.To.Type == obj.TYPE_NONE {
                        p.To.Type, p.To.Reg = obj.TYPE_REG, REG_ZERO
                }
+
+       case AFSQRTS, AFSQRTD:
+               // These instructions expect a zero (i.e. float register 0)
+               // to be the second input operand.
+               p.Reg = p.From.Reg
+               p.From = obj.Addr{Type: obj.TYPE_REG, Reg: REG_F0}
+
+       case AFCVTWS, AFCVTLS, AFCVTWUS, AFCVTLUS, AFCVTWD, AFCVTLD, AFCVTWUD, AFCVTLUD:
+               // Set the rounding mode in funct3 to round to zero.
+               p.Scond = 1
        }
 }
 
@@ -159,6 +169,11 @@ func regI(r int16) uint32 {
        return regVal(r, REG_X0, REG_X31)
 }
 
+// regF returns a float register.
+func regF(r int16) uint32 {
+       return regVal(r, REG_F0, REG_F31)
+}
+
 // regAddr extracts a register from an Addr.
 func regAddr(a obj.Addr, min, max int16) uint32 {
        if a.Type != obj.TYPE_REG {
@@ -172,6 +187,11 @@ func regIAddr(a obj.Addr) uint32 {
        return regAddr(a, REG_X0, REG_X31)
 }
 
+// regFAddr extracts the float register from an Addr.
+func regFAddr(a obj.Addr) uint32 {
+       return regAddr(a, REG_F0, REG_F31)
+}
+
 // immFits reports whether immediate value x fits in nbits bits as a
 // signed integer.
 func immFits(x int64, nbits uint) bool {
@@ -213,6 +233,11 @@ func wantIntReg(p *obj.Prog, pos string, r int16) {
        wantReg(p, pos, "integer", r, REG_X0, REG_X31)
 }
 
+// wantFloatReg checks that r is a floating-point register.
+func wantFloatReg(p *obj.Prog, pos string, r int16) {
+       wantReg(p, pos, "float", r, REG_F0, REG_F31)
+}
+
 func wantRegAddr(p *obj.Prog, pos string, a *obj.Addr, descr string, min int16, max int16) {
        if a == nil {
                p.Ctxt.Diag("%v\texpected register in %s position but got nothing", p, pos)
@@ -232,24 +257,68 @@ func wantIntRegAddr(p *obj.Prog, pos string, a *obj.Addr) {
        wantRegAddr(p, pos, a, "integer", REG_X0, REG_X31)
 }
 
+// wantFloatRegAddr checks that a contains a floating-point register.
+func wantFloatRegAddr(p *obj.Prog, pos string, a *obj.Addr) {
+       wantRegAddr(p, pos, a, "float", REG_F0, REG_F31)
+}
+
 func validateRIII(p *obj.Prog) {
        wantIntRegAddr(p, "from", &p.From)
        wantIntReg(p, "reg", p.Reg)
        wantIntRegAddr(p, "to", &p.To)
 }
 
+func validateRFFF(p *obj.Prog) {
+       wantFloatRegAddr(p, "from", &p.From)
+       wantFloatReg(p, "reg", p.Reg)
+       wantFloatRegAddr(p, "to", &p.To)
+}
+
+func validateRFFI(p *obj.Prog) {
+       wantFloatRegAddr(p, "from", &p.From)
+       wantFloatReg(p, "reg", p.Reg)
+       wantIntRegAddr(p, "to", &p.To)
+}
+
+func validateRFI(p *obj.Prog) {
+       wantFloatRegAddr(p, "from", &p.From)
+       wantIntRegAddr(p, "to", &p.To)
+}
+
+func validateRIF(p *obj.Prog) {
+       wantIntRegAddr(p, "from", &p.From)
+       wantFloatRegAddr(p, "to", &p.To)
+}
+
+func validateRFF(p *obj.Prog) {
+       wantFloatRegAddr(p, "from", &p.From)
+       wantFloatRegAddr(p, "to", &p.To)
+}
+
 func validateII(p *obj.Prog) {
        wantImm(p, "from", p.From, 12)
        wantIntReg(p, "reg", p.Reg)
        wantIntRegAddr(p, "to", &p.To)
 }
 
+func validateIF(p *obj.Prog) {
+       wantImm(p, "from", p.From, 12)
+       wantIntReg(p, "reg", p.Reg)
+       wantFloatRegAddr(p, "to", &p.To)
+}
+
 func validateSI(p *obj.Prog) {
        wantImm(p, "from", p.From, 12)
        wantIntReg(p, "reg", p.Reg)
        wantIntRegAddr(p, "to", &p.To)
 }
 
+func validateSF(p *obj.Prog) {
+       wantImm(p, "from", p.From, 12)
+       wantFloatReg(p, "reg", p.Reg)
+       wantIntRegAddr(p, "to", &p.To)
+}
+
 func validateRaw(p *obj.Prog) {
        // Treat the raw value specially as a 32-bit unsigned integer.
        // Nobody wants to enter negative machine code.
@@ -282,6 +351,26 @@ func encodeRIII(p *obj.Prog) uint32 {
        return encodeR(p, regI(p.Reg), regIAddr(p.From), regIAddr(p.To))
 }
 
+func encodeRFFF(p *obj.Prog) uint32 {
+       return encodeR(p, regF(p.Reg), regFAddr(p.From), regFAddr(p.To))
+}
+
+func encodeRFFI(p *obj.Prog) uint32 {
+       return encodeR(p, regF(p.Reg), regFAddr(p.From), regIAddr(p.To))
+}
+
+func encodeRFI(p *obj.Prog) uint32 {
+       return encodeR(p, regFAddr(p.From), 0, regIAddr(p.To))
+}
+
+func encodeRIF(p *obj.Prog) uint32 {
+       return encodeR(p, regIAddr(p.From), 0, regFAddr(p.To))
+}
+
+func encodeRFF(p *obj.Prog) uint32 {
+       return encodeR(p, regFAddr(p.From), 0, regFAddr(p.To))
+}
+
 // encodeI encodes an I-type RISC-V instruction.
 func encodeI(p *obj.Prog, rd uint32) uint32 {
        imm := immI(p.From, 12)
@@ -298,6 +387,10 @@ func encodeII(p *obj.Prog) uint32 {
        return encodeI(p, regIAddr(p.To))
 }
 
+func encodeIF(p *obj.Prog) uint32 {
+       return encodeI(p, regFAddr(p.To))
+}
+
 // encodeS encodes an S-type RISC-V instruction.
 func encodeS(p *obj.Prog, rs2 uint32) uint32 {
        imm := immI(p.From, 12)
@@ -313,6 +406,10 @@ func encodeSI(p *obj.Prog) uint32 {
        return encodeS(p, regI(p.Reg))
 }
 
+func encodeSF(p *obj.Prog) uint32 {
+       return encodeS(p, regF(p.Reg))
+}
+
 // encodeRaw encodes a raw instruction value.
 func encodeRaw(p *obj.Prog) uint32 {
        // Treat the raw value specially as a 32-bit unsigned integer.
@@ -346,10 +443,17 @@ var (
        // indicates an S-type instruction with rs2 being a float register.
 
        rIIIEncoding = encoding{encode: encodeRIII, validate: validateRIII, length: 4}
+       rFFFEncoding = encoding{encode: encodeRFFF, validate: validateRFFF, length: 4}
+       rFFIEncoding = encoding{encode: encodeRFFI, validate: validateRFFI, length: 4}
+       rFIEncoding  = encoding{encode: encodeRFI, validate: validateRFI, length: 4}
+       rIFEncoding  = encoding{encode: encodeRIF, validate: validateRIF, length: 4}
+       rFFEncoding  = encoding{encode: encodeRFF, validate: validateRFF, length: 4}
 
        iIEncoding = encoding{encode: encodeII, validate: validateII, length: 4}
+       iFEncoding = encoding{encode: encodeIF, validate: validateIF, length: 4}
 
        sIEncoding = encoding{encode: encodeSI, validate: validateSI, length: 4}
+       sFEncoding = encoding{encode: encodeSF, validate: validateSF, length: 4}
 
        // rawEncoding encodes a raw instruction byte sequence.
        rawEncoding = encoding{encode: encodeRaw, validate: validateRaw, length: 4}
@@ -436,6 +540,76 @@ var encodingForAs = [ALAST & obj.AMask]encoding{
        ARDTIME & obj.AMask:    iIEncoding,
        ARDINSTRET & obj.AMask: iIEncoding,
 
+       // 11.5: Single-Precision Load and Store Instructions
+       AFLW & obj.AMask: iFEncoding,
+       AFSW & obj.AMask: sFEncoding,
+
+       // 11.6: Single-Precision Floating-Point Computational Instructions
+       AFADDS & obj.AMask:  rFFFEncoding,
+       AFSUBS & obj.AMask:  rFFFEncoding,
+       AFMULS & obj.AMask:  rFFFEncoding,
+       AFDIVS & obj.AMask:  rFFFEncoding,
+       AFMINS & obj.AMask:  rFFFEncoding,
+       AFMAXS & obj.AMask:  rFFFEncoding,
+       AFSQRTS & obj.AMask: rFFFEncoding,
+
+       // 11.7: Single-Precision Floating-Point Conversion and Move Instructions
+       AFCVTWS & obj.AMask:  rFIEncoding,
+       AFCVTLS & obj.AMask:  rFIEncoding,
+       AFCVTSW & obj.AMask:  rIFEncoding,
+       AFCVTSL & obj.AMask:  rIFEncoding,
+       AFCVTWUS & obj.AMask: rFIEncoding,
+       AFCVTLUS & obj.AMask: rFIEncoding,
+       AFCVTSWU & obj.AMask: rIFEncoding,
+       AFCVTSLU & obj.AMask: rIFEncoding,
+       AFSGNJS & obj.AMask:  rFFFEncoding,
+       AFSGNJNS & obj.AMask: rFFFEncoding,
+       AFSGNJXS & obj.AMask: rFFFEncoding,
+       AFMVXS & obj.AMask:   rFIEncoding,
+       AFMVSX & obj.AMask:   rIFEncoding,
+       AFMVXW & obj.AMask:   rFIEncoding,
+       AFMVWX & obj.AMask:   rIFEncoding,
+
+       // 11.8: Single-Precision Floating-Point Compare Instructions
+       AFEQS & obj.AMask: rFFIEncoding,
+       AFLTS & obj.AMask: rFFIEncoding,
+       AFLES & obj.AMask: rFFIEncoding,
+
+       // 12.3: Double-Precision Load and Store Instructions
+       AFLD & obj.AMask: iFEncoding,
+       AFSD & obj.AMask: sFEncoding,
+
+       // 12.4: Double-Precision Floating-Point Computational Instructions
+       AFADDD & obj.AMask:  rFFFEncoding,
+       AFSUBD & obj.AMask:  rFFFEncoding,
+       AFMULD & obj.AMask:  rFFFEncoding,
+       AFDIVD & obj.AMask:  rFFFEncoding,
+       AFMIND & obj.AMask:  rFFFEncoding,
+       AFMAXD & obj.AMask:  rFFFEncoding,
+       AFSQRTD & obj.AMask: rFFFEncoding,
+
+       // 12.5: Double-Precision Floating-Point Conversion and Move Instructions
+       AFCVTWD & obj.AMask:  rFIEncoding,
+       AFCVTLD & obj.AMask:  rFIEncoding,
+       AFCVTDW & obj.AMask:  rIFEncoding,
+       AFCVTDL & obj.AMask:  rIFEncoding,
+       AFCVTWUD & obj.AMask: rFIEncoding,
+       AFCVTLUD & obj.AMask: rFIEncoding,
+       AFCVTDWU & obj.AMask: rIFEncoding,
+       AFCVTDLU & obj.AMask: rIFEncoding,
+       AFCVTSD & obj.AMask:  rFFEncoding,
+       AFCVTDS & obj.AMask:  rFFEncoding,
+       AFSGNJD & obj.AMask:  rFFFEncoding,
+       AFSGNJND & obj.AMask: rFFFEncoding,
+       AFSGNJXD & obj.AMask: rFFFEncoding,
+       AFMVXD & obj.AMask:   rFIEncoding,
+       AFMVDX & obj.AMask:   rIFEncoding,
+
+       // 12.6: Double-Precision Floating-Point Compare Instructions
+       AFEQD & obj.AMask: rFFIEncoding,
+       AFLTD & obj.AMask: rFFIEncoding,
+       AFLED & obj.AMask: rFFIEncoding,
+
        // Privileged ISA
 
        // 3.2.1: Environment Call and Breakpoint