\chapter{``D'' Standard Extension for Double-Precision Floating-Point, Version 2.0} This chapter describes the standard double-precision floating-point instruction-set extension, which is named ``D'' and adds double-precision floating-point computational instructions compliant with the IEEE 754-2008 arithmetic standard. The D extension depends on the base single-precision instruction subset F. \section{D Register State} The D extension widens the 32 floating-point registers, {\tt f0}--{\tt f31}, to 64 bits (FLEN=64 in Figure~\ref{fprs}). \section{Double-Precision Load and Store Instructions} The FLD instruction loads a double-precision floating-point value from memory into floating-point register {\em rd}. FSD stores a double-precision value from the floating-point registers to memory. \vspace{-0.2in} \begin{center} \begin{tabular}{M@{}R@{}F@{}R@{}O} \\ \instbitrange{31}{20} & \instbitrange{19}{15} & \instbitrange{14}{12} & \instbitrange{11}{7} & \instbitrange{6}{0} \\ \hline \multicolumn{1}{|c|}{imm[11:0]} & \multicolumn{1}{c|}{rs1} & \multicolumn{1}{c|}{width} & \multicolumn{1}{c|}{rd} & \multicolumn{1}{c|}{opcode} \\ \hline 12 & 5 & 3 & 5 & 7 \\ offset[11:0] & base & D & dest & LOAD-FP \\ \end{tabular} \end{center} \vspace{-0.2in} \begin{center} \begin{tabular}{O@{}R@{}R@{}F@{}R@{}O} \\ \instbitrange{31}{25} & \instbitrange{24}{20} & \instbitrange{19}{15} & \instbitrange{14}{12} & \instbitrange{11}{7} & \instbitrange{6}{0} \\ \hline \multicolumn{1}{|c|}{imm[11:5]} & \multicolumn{1}{c|}{rs2} & \multicolumn{1}{c|}{rs1} & \multicolumn{1}{c|}{width} & \multicolumn{1}{c|}{imm[4:0]} & \multicolumn{1}{c|}{opcode} \\ \hline 7 & 5 & 5 & 3 & 5 & 7 \\ offset[11:5] & src & base & D & offset[4:0] & STORE-FP \\ \end{tabular} \end{center} If a floating-point register holds a single-precision value, it is guaranteed that a FSD of that register will place a value into memory that when reloaded with a FLD will recreate the original single-precision value in a register. The data format that is stored in memory is undefined beyond having this property. \begin{commentary} User-level code might not know the current type of data stored in a floating-point register but has to be able to save and restore the register values. A common case is for callee-save registers, but this is also essential to implement varargs and user-level threading libraries. \end{commentary} FLD and FSD are only guaranteed to execute atomically if the effective address is naturally aligned and XLEN$\geq$64. \section{Double-Precision Floating-Point Computational Instructions} The double-precision floating-point computational instructions are defined analogously to their single-precision counterparts, but operate on double-precision operands and produce double-precision results. \vspace{-0.2in} \begin{center} \begin{tabular}{R@{}F@{}R@{}R@{}F@{}R@{}O} \\ \instbitrange{31}{27} & \instbitrange{26}{25} & \instbitrange{24}{20} & \instbitrange{19}{15} & \instbitrange{14}{12} & \instbitrange{11}{7} & \instbitrange{6}{0} \\ \hline \multicolumn{1}{|c|}{funct5} & \multicolumn{1}{c|}{fmt} & \multicolumn{1}{c|}{rs2} & \multicolumn{1}{c|}{rs1} & \multicolumn{1}{c|}{rm} & \multicolumn{1}{c|}{rd} & \multicolumn{1}{c|}{opcode} \\ \hline 5 & 2 & 5 & 5 & 3 & 5 & 7 \\ FADD/FSUB & D & src2 & src1 & RM & dest & OP-FP \\ FMUL/FDIV & D & src2 & src1 & RM & dest & OP-FP \\ FMIN-MAX & D & src2 & src1 & MIN/MAX & dest & OP-FP \\ FSQRT & D & 0 & src & RM & dest & OP-FP \\ \end{tabular} \end{center} \vspace{-0.2in} \begin{center} \begin{tabular}{R@{}F@{}R@{}R@{}F@{}R@{}O} \\ \instbitrange{31}{27} & \instbitrange{26}{25} & \instbitrange{24}{20} & \instbitrange{19}{15} & \instbitrange{14}{12} & \instbitrange{11}{7} & \instbitrange{6}{0} \\ \hline \multicolumn{1}{|c|}{rs3} & \multicolumn{1}{c|}{fmt} & \multicolumn{1}{c|}{rs2} & \multicolumn{1}{c|}{rs1} & \multicolumn{1}{c|}{rm} & \multicolumn{1}{c|}{rd} & \multicolumn{1}{c|}{opcode} \\ \hline 5 & 2 & 5 & 5 & 3 & 5 & 7 \\ src3 & D & src2 & src1 & RM & dest & F[N]MADD/F[N]MSUB \\ \end{tabular} \end{center} \section{Double-Precision Floating-Point Conversion and Move Instructions} Floating-point-to-integer and integer-to-floating-point conversion instructions are encoded in the OP-FP major opcode space. FCVT.W.D or FCVT.L.D converts a double-precision floating-point number in floating-point register {\em rs1} to a signed 32-bit or 64-bit integer, respectively, in integer register {\em rd}. FCVT.D.W or FCVT.D.L converts a 32-bit or 64-bit signed integer, respectively, in integer register {\em rs1} into a double-precision floating-point number in floating-point register {\em rd}. FCVT.WU.D, FCVT.LU.D, FCVT.D.WU, and FCVT.D.LU variants convert to or from unsigned integer values. FCVT.L[U].D and FCVT.D.L[U] are illegal in RV32. The range of valid inputs for FCVT.{\em int}.D and the behavior for invalid inputs are the same as for FCVT.{\em int}.S. All floating-point to integer and integer to floating-point conversion instructions round according to the {\em rm} field. Note FCVT.D.W[U] always produces an exact result and is unaffected by rounding mode. \vspace{-0.2in} \begin{center} \begin{tabular}{R@{}F@{}R@{}R@{}F@{}R@{}O} \\ \instbitrange{31}{27} & \instbitrange{26}{25} & \instbitrange{24}{20} & \instbitrange{19}{15} & \instbitrange{14}{12} & \instbitrange{11}{7} & \instbitrange{6}{0} \\ \hline \multicolumn{1}{|c|}{funct5} & \multicolumn{1}{c|}{fmt} & \multicolumn{1}{c|}{rs2} & \multicolumn{1}{c|}{rs1} & \multicolumn{1}{c|}{rm} & \multicolumn{1}{c|}{rd} & \multicolumn{1}{c|}{opcode} \\ \hline 5 & 2 & 5 & 5 & 3 & 5 & 7 \\ FCVT.{\em int}.{\em fmt} & D & W[U]/L[U] & src & RM & dest & OP-FP \\ FCVT.{\em fmt}.{\em int} & D & W[U]/L[U] & src & RM & dest & OP-FP \\ \end{tabular} \end{center} The double-precision to single-precision and single-precision to double-precision conversion instructions, FCVT.S.D and FCVT.D.S, are encoded in the OP-FP major opcode space and both the source and destination are floating-point registers. The {\em rs2} field encodes the datatype of the source, and the {\em fmt} field encodes the datatype of the destination. FCVT.S.D rounds according to the RM field; FCVT.D.S will never round. \vspace{-0.2in} \begin{center} \begin{tabular}{R@{}F@{}R@{}R@{}F@{}R@{}O} \\ \instbitrange{31}{27} & \instbitrange{26}{25} & \instbitrange{24}{20} & \instbitrange{19}{15} & \instbitrange{14}{12} & \instbitrange{11}{7} & \instbitrange{6}{0} \\ \hline \multicolumn{1}{|c|}{funct5} & \multicolumn{1}{c|}{fmt} & \multicolumn{1}{c|}{rs2} & \multicolumn{1}{c|}{rs1} & \multicolumn{1}{c|}{rm} & \multicolumn{1}{c|}{rd} & \multicolumn{1}{c|}{opcode} \\ \hline 5 & 2 & 5 & 5 & 3 & 5 & 7 \\ FCVT.{\em fmt}.{\em fmt} & S & D & src & RM & dest & OP-FP \\ FCVT.{\em fmt}.{\em fmt} & D & S & src & RM & dest & OP-FP \\ \end{tabular} \end{center} Floating-point to floating-point sign-injection instructions, FSGNJ.D, FSGNJN.D, and FSGNJX.D are defined analogously to the single-precision sign-injection instruction. For FSGNJ.D, if {\em rs1} and {\em rs2} are the same register, which contains a single-precision floating-point value, the single-precision value will be correctly copied to {\em rd}. If {\em rs1} and {\em rs2} are not the same, the result is undefined. For FSGNJN.D and FSGNJX.D, the result is undefined for any single-precision inputs. \vspace{-0.2in} \begin{center} \begin{tabular}{R@{}F@{}R@{}R@{}F@{}R@{}O} \\ \instbitrange{31}{27} & \instbitrange{26}{25} & \instbitrange{24}{20} & \instbitrange{19}{15} & \instbitrange{14}{12} & \instbitrange{11}{7} & \instbitrange{6}{0} \\ \hline \multicolumn{1}{|c|}{funct5} & \multicolumn{1}{c|}{fmt} & \multicolumn{1}{c|}{rs2} & \multicolumn{1}{c|}{rs1} & \multicolumn{1}{c|}{rm} & \multicolumn{1}{c|}{rd} & \multicolumn{1}{c|}{opcode} \\ \hline 5 & 2 & 5 & 5 & 3 & 5 & 7 \\ FSGNJ & D & src2 & src1 & J[N]/JX & dest & OP-FP \\ \end{tabular} \end{center} For RV64 only, instructions are provided to move bit patterns between the floating-point and integer registers. FMV.X.D moves the double-precision value in floating-point register {\em rs1} to a representation in IEEE 754-2008 standard encoding in integer register {\em rd}. If the last value written to the source floating-point register was a single-precision floating-point value, then the value returned by FMV.X.D is undefined beyond having the property that moving the value back to a floating-point register will recreate the original single-precision value. FMV.D.X moves the double-precision value encoded in IEEE 754-2008 standard encoding from the integer register {\em rs1} to the floating-point register {\em rd}. \vspace{-0.2in} \begin{center} \begin{tabular}{R@{}F@{}R@{}R@{}F@{}R@{}O} \\ \instbitrange{31}{27} & \instbitrange{26}{25} & \instbitrange{24}{20} & \instbitrange{19}{15} & \instbitrange{14}{12} & \instbitrange{11}{7} & \instbitrange{6}{0} \\ \hline \multicolumn{1}{|c|}{funct5} & \multicolumn{1}{c|}{fmt} & \multicolumn{1}{c|}{rs2} & \multicolumn{1}{c|}{rs1} & \multicolumn{1}{c|}{rm} & \multicolumn{1}{c|}{rd} & \multicolumn{1}{c|}{opcode} \\ \hline 5 & 2 & 5 & 5 & 3 & 5 & 7 \\ FMV.X.{\em fmt} & D & 0 & src & 000 & dest & OP-FP \\ FMV.{\em fmt}.X & D & 0 & src & 000 & dest & OP-FP \\ \end{tabular} \end{center} \section{Double-Precision Floating-Point Compare Instructions} The double-precision floating-point compare instructions are defined analogously to their single-precision counterparts, but operate on double-precision operands. \vspace{-0.2in} \begin{center} \begin{tabular}{S@{}F@{}R@{}R@{}F@{}R@{}O} \\ \instbitrange{31}{27} & \instbitrange{26}{25} & \instbitrange{24}{20} & \instbitrange{19}{15} & \instbitrange{14}{12} & \instbitrange{11}{7} & \instbitrange{6}{0} \\ \hline \multicolumn{1}{|c|}{funct5} & \multicolumn{1}{c|}{fmt} & \multicolumn{1}{c|}{rs2} & \multicolumn{1}{c|}{rs1} & \multicolumn{1}{c|}{rm} & \multicolumn{1}{c|}{rd} & \multicolumn{1}{c|}{opcode} \\ \hline 5 & 2 & 5 & 5 & 3 & 5 & 7 \\ FCMP & D & src2 & src1 & EQ/LT/LE & dest & OP-FP \\ \end{tabular} \end{center} \section{Double-Precision Floating-Point Classify Instruction} The double-precision floating-point classify instruction, FCLASS.D, is defined analogously to its single-precision counterpart, but operates on double-precision operands. \vspace{-0.2in} \begin{center} \begin{tabular}{S@{}F@{}R@{}R@{}F@{}R@{}O} \\ \instbitrange{31}{27} & \instbitrange{26}{25} & \instbitrange{24}{20} & \instbitrange{19}{15} & \instbitrange{14}{12} & \instbitrange{11}{7} & \instbitrange{6}{0} \\ \hline \multicolumn{1}{|c|}{funct5} & \multicolumn{1}{c|}{fmt} & \multicolumn{1}{c|}{rs2} & \multicolumn{1}{c|}{rs1} & \multicolumn{1}{c|}{rm} & \multicolumn{1}{c|}{rd} & \multicolumn{1}{c|}{opcode} \\ \hline 5 & 2 & 5 & 5 & 3 & 5 & 7 \\ FCLASS & D & 0 & src & 001 & dest & OP-FP \\ \end{tabular} \end{center}