\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}
