1. "F" Standard Extension for SinglePrecision FloatingPoint, Version 2.2
This chapter describes the standard instructionset extension for singleprecision floatingpoint, which is named "F" and adds singleprecision floatingpoint computational instructions compliant with the IEEE 7542008 arithmetic standard (ANSI/IEEE Std 7542008, IEEE Standard for FloatingPoint Arithmetic, 2008). The F extension depends on the "Zicsr" extension for control and status register access.
1.1. F Register State
The F extension adds 32 floatingpoint registers, f0f31
, each 32
bits wide, and a floatingpoint control and status register fcsr
,
which contains the operating mode and exception status of the
floatingpoint unit. This additional state is shown in
Table 1. We use the term FLEN to describe the width of
the floatingpoint registers in the RISCV ISA, and FLEN=32 for the F
singleprecision floatingpoint extension. Most floatingpoint
instructions operate on values in the floatingpoint register file.
Floatingpoint load and store instructions transfer floatingpoint
values between registers and memory. Instructions to transfer values to and from the integer register file are also provided.
We considered a unified register file for both integer and floatingpoint values as this simplifies software register allocation and calling conventions, and reduces total user state. However, a split organization increases the total number of registers accessible with a given instruction width, simplifies provision of enough regfile ports for wide superscalar issue, supports decoupled floatingpointunit architectures, and simplifies use of internal floatingpoint encoding techniques. Compiler support and calling conventions for split register file architectures are well understood, and using dirty bits on floatingpoint register file state can reduce contextswitch overhead. 
FLEN1 
0 

f0 

f1 

f2 

f3 

f4 

f5 

f6 

f7 

f8 

f9 

f10 

f11 

f12 

f13 

f14 

f15 

f16 

f17 

f18 

f19 

f20 

f21 

f22 

f23 

f24 

f25 

f26 

f27 

f28 

f29 

f30 

f31 

FLEN 

31 
0 

fcsr 

32 
1.2. FloatingPoint Control and Status Register
The floatingpoint control and status register, fcsr
, is a RISCV
control and status register (CSR). It is a 32bit read/write register
that selects the dynamic rounding mode for floatingpoint arithmetic
operations and holds the accrued exception flags, as shown in FloatingPoint Control and Status Register.
The fcsr
register can be read and written with the FRCSR and FSCSR
instructions, which are assembler pseudoinstructions built on the
underlying CSR access instructions. FRCSR reads fcsr
by copying it
into integer register rd. FSCSR swaps the value in fcsr
by copying
the original value into integer register rd, and then writing a new
value obtained from integer register rs1 into fcsr
.
The fields within the fcsr
can also be accessed individually through
different CSR addresses, and separate assembler pseudoinstructions are defined
for these accesses. The FRRM instruction reads the Rounding Mode field frm
(fcsr
bits 7—5) and copies it into the leastsignificant three bits of
integer register rd, with zero in all other bits. FSRM swaps the value in
frm
by copying the original value into integer register rd, and then
writing a new value obtained from the three leastsignificant bits of integer
register rs1 into frm
. FRFLAGS and FSFLAGS are defined analogously for the
Accrued Exception Flags field fflags
(fcsr
bits 4—0).
Bits 31—8 of the fcsr
are reserved for other standard extensions. If
these extensions are not present, implementations shall ignore writes to
these bits and supply a zero value when read. Standard software should
preserve the contents of these bits.
Floatingpoint operations use either a static rounding mode encoded in
the instruction, or a dynamic rounding mode held in frm
. Rounding
modes are encoded as shown in Table 2. A value of 111 in the
instruction’s rm field selects the dynamic rounding mode held in
frm
. The behavior of floatingpoint instructions that depend on
rounding mode when executed with a reserved rounding mode is reserved, including both static reserved rounding modes (101110) and dynamic reserved rounding modes (101111). Some instructions, including widening conversions, have the rm field but are nevertheless mathematically unaffected by the rounding mode; software should set their rm field to
RNE (000) but implementations must treat the rm field as usual (in
particular, with regard to decoding legal vs. reserved encodings).
Rounding Mode  Mnemonic  Meaning 

000 
RNE 
Round to Nearest, ties to Even 
001 
RTZ 
Round towards Zero 
010 
RDN 
Round Down (towards \(\infty\)) 
011 
RUP 
Round Up (towards \(+\infty\)) 
100 
RMM 
Round to Nearest, ties to Max Magnitude 
101 
Reserved for future use. 

110 
Reserved for future use. 

111 
DYN 
In instruction’s rm field, selects dynamic rounding mode; In Rounding Mode register, reserved. 
The C99 language standard effectively mandates the provision of a dynamic rounding mode register. In typical implementations, writes to the dynamic rounding mode CSR state will serialize the pipeline. Static rounding modes are used to implement specialized arithmetic operations that often have to switch frequently between different rounding modes. The ratified version of the F spec mandated that an illegalinstruction exception was raised when an instruction was executed with a reserved dynamic rounding mode. This has been weakened to reserved, which matches the behavior of static roundingmode instructions. Raising an illegalinstruction exception is still valid behavior when encountering a reserved encoding, so implementations compatible with the ratified spec are compatible with the weakened spec. 
The accrued exception flags indicate the exception conditions that have arisen on any floatingpoint arithmetic instruction since the field was last reset by software, as shown in Table 3. The base RISCV ISA does not support generating a trap on the setting of a floatingpoint exception flag.
Flag Mnemonic  Flag Meaning 

NV 
Invalid Operation 
DZ 
Divide by Zero 
OF 
Overflow 
UF 
Underflow 
NX 
Inexact 
As allowed by the standard, we do not support traps on floatingpoint exceptions in the F extension, but instead require explicit checks of the flags in software. We considered adding branches controlled directly by the contents of the floatingpoint accrued exception flags, but ultimately chose to omit these instructions to keep the ISA simple. 
1.3. NaN Generation and Propagation
Except when otherwise stated, if the result of a floatingpoint
operation is NaN, it is the canonical NaN. The canonical NaN has a
positive sign and all significand bits clear except the MSB, a.k.a. the
quiet bit. For singleprecision floatingpoint, this corresponds to the pattern 0x7fc00000
.
We considered propagating NaN payloads, as is recommended by the standard, but this decision would have increased hardware cost. Moreover, since this feature is optional in the standard, it cannot be used in portable code. Implementors are free to provide a NaN payload propagation scheme as a nonstandard extension enabled by a nonstandard operating mode. However, the canonical NaN scheme described above must always be supported and should be the default mode. 
We require implementations to return the standardmandated default values in the case of exceptional conditions, without any further intervention on the part of userlevel software (unlike the Alpha ISA floatingpoint trap barriers). We believe full hardware handling of exceptional cases will become more common, and so wish to avoid complicating the userlevel ISA to optimize other approaches. Implementations can always trap to machinemode software handlers to provide exceptional default values. 
1.4. Subnormal Arithmetic
Operations on subnormal numbers are handled in accordance with the IEEE 7542008 standard.
In the parlance of the IEEE standard, tininess is detected after rounding.
Detecting tininess after rounding results in fewer spurious underflow signals. 
1.5. SinglePrecision Load and Store Instructions
Floatingpoint loads and stores use the same base+offset addressing mode as the integer base ISAs, with a base address in register rs1 and a 12bit signed byte offset. The FLW instruction loads a singleprecision floatingpoint value from memory into floatingpoint register rd. FSW stores a singleprecision value from floatingpoint register rs2 to memory.
FLW and FSW are only guaranteed to execute atomically if the effective address is naturally aligned.
FLW and FSW do not modify the bits being transferred; in particular, the payloads of noncanonical NaNs are preserved.
As described in [ldst], the execution environment defines whether misaligned floatingpoint loads and stores are handled invisibly or raise a contained or fatal trap.
1.6. SinglePrecision FloatingPoint Computational Instructions
Floatingpoint arithmetic instructions with one or two source operands use the Rtype format with the OPFP major opcode. FADD.S and FMUL.S perform singleprecision floatingpoint addition and multiplication respectively, between rs1 and rs2. FSUB.S performs the singleprecision floatingpoint subtraction of rs2 from rs1. FDIV.S performs the singleprecision floatingpoint division of rs1 by rs2. FSQRT.S computes the square root of rs1. In each case, the result is written to rd.
The 2bit floatingpoint format field fmt is encoded as shown in Table 4. It is set to S (00) for all instructions in the F extension.
fmt field  Mnemonic  Meaning 

00 
S 
32bit singleprecision 
01 
D 
64bit doubleprecision 
10 
H 
16bit halfprecision 
11 
Q 
128bit quadprecision 
All floatingpoint operations that perform rounding can select the rounding mode using the rm field with the encoding shown in Table 2.
Floatingpoint minimumnumber and maximumnumber instructions FMIN.S and FMAX.S write, respectively, the smaller or larger of rs1 and rs2 to rd. For the purposes of these instructions only, the value \(0.0\) is considered to be less than the value \(+0.0\). If both inputs are NaNs, the result is the canonical NaN. If only one operand is a NaN, the result is the nonNaN operand. Signaling NaN inputs set the invalid operation exception flag, even when the result is not NaN.
Note that in version 2.2 of the F extension, the FMIN.S and FMAX.S instructions were amended to implement the proposed IEEE 754201x minimumNumber and maximumNumber operations, rather than the IEEE 7542008 minNum and maxNum operations. These operations differ in their handling of signaling NaNs. 
Floatingpoint fused multiplyadd instructions require a new standard instruction format. R4type instructions specify three source registers (rs1, rs2, and rs3) and a destination register (rd). This format is only used by the floatingpoint fused multiplyadd instructions.
FMADD.S multiplies the values in rs1 and rs2, adds the value in rs3, and writes the final result to rd. FMADD.S computes (rs1\(\times\)rs2)\(\+\)rs3.
FMSUB.S multiplies the values in rs1 and rs2, subtracts the value in rs3, and writes the final result to rd. FMSUB.S computes (rs1\(\times\)rs2)\(\\)rs3.
FNMSUB.S multiplies the values in rs1 and rs2, negates the product, adds the value in rs3, and writes the final result to rd. FNMSUB.S computes (rs1\(\times\)rs2)\(\+\)rs3.
FNMADD.S multiplies the values in rs1 and rs2, negates the product, subtracts the value in rs3, and writes the final result to rd. FNMADD.S computes (rs1\(\times\)rs2)\(\\)rs3.
The FNMSUB and FNMADD instructions are counterintuitively named, owing to the naming of the corresponding instructions in MIPSIV. The MIPS instructions were defined to negate the sum, rather than negating the product as the RISCV instructions do, so the naming scheme was more rational at the time. The two definitions differ with respect to signedzero results. The RISCV definition matches the behavior of the x86 and ARM fused multiplyadd instructions, but unfortunately the RISCV FNMSUB and FNMADD instruction names are swapped compared to x86 and ARM. 
The fused multiplyadd (FMA) instructions consume a large part of the 32bit instruction encoding space. Some alternatives considered were to restrict FMA to only use dynamic rounding modes, but static rounding modes are useful in code that exploits the lack of product rounding. Another alternative would have been to use rd to provide rs3, but this would require additional move instructions in some common sequences. The current design still leaves a large portion of the 32bit encoding space open while avoiding having FMA be nonorthogonal. 
The fused multiplyadd instructions must set the invalid operation exception flag when the multiplicands are \(\infty\) and zero, even when the addend is a quiet NaN.
The IEEE 7542008 standard permits, but does not require, raising the invalid exception for the operation \(\infty\times 0\ +\)qNaN. 
1.7. SinglePrecision FloatingPoint Conversion and Move Instructions
Floatingpointtointeger and integertofloatingpoint conversion instructions are encoded in the OPFP major opcode space. FCVT.W.S or FCVT.L.S converts a floatingpoint number in floatingpoint register rs1 to a signed 32bit or 64bit integer, respectively, in integer register rd. FCVT.S.W or FCVT.S.L converts a 32bit or 64bit signed integer, respectively, in integer register rs1 into a floatingpoint number in floatingpoint register rd. FCVT.WU.S, FCVT.LU.S, FCVT.S.WU, and FCVT.S.LU variants convert to or from unsigned integer values. For XLEN\(>32\), FCVT.W[U].S signextends the 32bit result to the destination register width. FCVT.L[U].S and FCVT.S.L[U] are RV64only instructions. If the rounded result is not representable in the destination format, it is clipped to the nearest value and the invalid flag is set. Table 5 gives the range of valid inputs for FCVT.int.S and the behavior for invalid inputs.
All floatingpoint to integer and integer to floatingpoint conversion
instructions round according to the rm field. A floatingpoint
register can be initialized to floatingpoint positive zero using
FCVT.S.W rd, x0
, which will never set any exception flags.
FCVT.W.S  FCVT.WU.S  FCVT.L.S  FCVT.LU.S  

Minimum valid input (after rounding) 
\(2^{31}\) 
0 
\(2^{63}\) 
0 
Maximum valid input (after rounding) 
\(2^{31}1\) 
\(2^{32}1\) 
\(2^{63}1\) 
\(2^{64}1\) 
Output for outofrange negative input 
\(2^{31}\) 
0 
\(2^{63}\) 
0 
Output for \(\infty\) 
\(2^{31}\) 
0 
\(2^{63}\) 
0 
Output for outofrange positive input 
\(2^{31}1\) 
\(2^{32}1\) 
\(2^{63}1\) 
\(2^{64}1\) 
Output for \(+\infty\) or NaN 
\(2^{31}1\) 
\(2^{32}1\) 
\(2^{63}1\) 
\(2^{64}1\) 
All floatingpoint conversion instructions set the Inexact exception flag if the rounded result differs from the operand value and the Invalid exception flag is not set.
Floatingpoint to floatingpoint signinjection instructions, FSGNJ.S, FSGNJN.S, and FSGNJX.S, produce a result that takes all bits except the sign bit from rs1. For FSGNJ, the result’s sign bit is rs2's sign bit; for FSGNJN, the result’s sign bit is the opposite of rs2's sign bit; and for FSGNJX, the sign bit is the XOR of the sign bits of rs1 and rs2. Signinjection instructions do not set floatingpoint exception flags, nor do they canonicalize NaNs. Note, FSGNJ.S rx, ry, ry moves ry to rx (assembler pseudoinstruction FMV.S rx, ry); FSGNJN.S rx, ry, ry moves the negation of ry to rx (assembler pseudoinstruction FNEG.S rx, ry); and FSGNJX.S rx, ry, ry moves the absolute value of ry to rx (assembler pseudoinstruction FABS.S rx, ry).
The signinjection instructions provide floatingpoint MV, ABS, and NEG, as well as supporting a few other operations, including the IEEE copySign operation and sign manipulation in transcendental math function libraries. Although MV, ABS, and NEG only need a single register operand, whereas FSGNJ instructions need two, it is unlikely most microarchitectures would add optimizations to benefit from the reduced number of register reads for these relatively infrequent instructions. Even in this case, a microarchitecture can simply detect when both source registers are the same for FSGNJ instructions and only read a single copy. 
Instructions are provided to move bit patterns between the floatingpoint and integer registers. FMV.X.W moves the singleprecision value in floatingpoint register rs1 represented in IEEE 7542008 encoding to the lower 32 bits of integer register rd. The bits are not modified in the transfer, and in particular, the payloads of noncanonical NaNs are preserved. For RV64, the higher 32 bits of the destination register are filled with copies of the floatingpoint number’s sign bit.
FMV.W.X moves the singleprecision value encoded in IEEE 7542008 standard encoding from the lower 32 bits of integer register rs1 to the floatingpoint register rd. The bits are not modified in the transfer, and in particular, the payloads of noncanonical NaNs are preserved.
The FMV.W.X and FMV.X.W instructions were previously called FMV.S.X and FMV.X.S. The use of W is more consistent with their semantics as an instruction that moves 32 bits without interpreting them. This became clearer after defining NaNboxing. To avoid disturbing existing code, both the W and S versions will be supported by tools. 
The base floatingpoint ISA was defined so as to allow implementations to employ an internal recoding of the floatingpoint format in registers to simplify handling of subnormal values and possibly to reduce functional unit latency. To this end, the F extension avoids representing integer values in the floatingpoint registers by defining conversion and comparison operations that read and write the integer register file directly. This also removes many of the common cases where explicit moves between integer and floatingpoint registers are required, reducing instruction count and critical paths for common mixedformat code sequences. 
1.8. SinglePrecision FloatingPoint Compare Instructions
Floatingpoint compare instructions (FEQ.S, FLT.S, FLE.S) perform the specified comparison between floatingpoint registers (\(\mbox{\em rs1} = \mbox{\em rs2}\), \(\mbox{\em rs1} < \mbox{\em rs2}\), \(\mbox{\em rs1} \leq \mbox{\em rs2}\)) writing 1 to the integer register rd if the condition holds, and 0 otherwise.
FLT.S and FLE.S perform what the IEEE 7542008 standard refers to as signaling comparisons: that is, they set the invalid operation exception flag if either input is NaN. FEQ.S performs a quiet comparison: it only sets the invalid operation exception flag if either input is a signaling NaN. For all three instructions, the result is 0 if either operand is NaN.
The F extension provides a \(\leq\) comparison, whereas the base ISAs provide a \(\geq\) branch comparison. Because \(\leq\) can be synthesized from \(\geq\) and viceversa, there is no performance implication to this inconsistency, but it is nevertheless an unfortunate incongruity in the ISA. 
1.9. SinglePrecision FloatingPoint Classify Instruction
The FCLASS.S instruction examines the value in floatingpoint register rs1 and writes to integer register rd a 10bit mask that indicates the class of the floatingpoint number. The format of the mask is described in Table 6. The corresponding bit in rd will be set if the property is true and clear otherwise. All other bits in rd are cleared. Note that exactly one bit in rd will be set. FCLASS.S does not set the floatingpoint exception flags.
rd bit  Meaning 

0 
rs1 is \(\infty\). 
1 
rs1 is a negative normal number. 
2 
rs1 is a negative subnormal number. 
3 
rs1 is \(0\). 
4 
rs1 is \(+0\). 
5 
rs1 is a positive subnormal number. 
6 
rs1 is a positive normal number. 
7 
rs1 is \(+\infty\). 
8 
rs1 is a signaling NaN. 
9 
rs1 is a quiet NaN. 