\chapter{RISC-V Assembly Programmer's Handbook} \label{assembly} This chapter is a placeholder for an assembly programmer's manual. Table~\ref{regmap} lists the assembler mnemonics for the {\tt x} and {\tt f} registers and their role in the standard calling convention. \vspace{0.2in} \begin{table*}[htbp] \begin{center} \begin{tabular}{|l|l|l|l|} \hline Register & ABI Name & Description & Saver \\ \hline \tt x0 & \tt zero & Hard-wired zero & --- \\ \tt x1 & \tt ra & Return address & Caller \\ \tt x2 & \tt sp & Stack pointer & Callee \\ \tt x3 & \tt gp & Global pointer & --- \\ \tt x4 & \tt tp & Thread pointer & --- \\ \tt x5 & {\tt t0} & Temporary/alternate link register& Caller \\ {\tt x6}--{\tt 7} & {\tt t1}--{\tt 2} & Temporaries & Caller \\ \tt x8 & {\tt s0}/\tt fp & Saved register/frame pointer & Callee \\ \tt x9 & {\tt s1} & Saved register & Callee \\ {\tt x10}--{\tt 11} & {\tt a0}--{\tt 1} & Function arguments/return values & Caller \\ {\tt x12}--{\tt 17} & {\tt a2}--{\tt 7} & Function arguments & Caller \\ {\tt x18}--{\tt 27} & {\tt s2}--{\tt 11} & Saved registers & Callee \\ {\tt x28}--{\tt 31} & {\tt t3}--{\tt 6} & Temporaries & Caller \\ \hline {\tt f0}--{\tt 7} & {\tt ft0}--{\tt 7} & FP temporaries & Caller \\ {\tt f8}--{\tt 9} & {\tt fs0}--{\tt 1} & FP saved registers & Callee \\ {\tt f10}--{\tt 11} & {\tt fa0}--{\tt 1} & FP arguments/return values & Caller \\ {\tt f12}--{\tt 17} & {\tt fa2}--{\tt 7} & FP arguments & Caller \\ {\tt f18}--{\tt 27} & {\tt fs2}--{\tt 11} & FP saved registers & Callee \\ {\tt f28}--{\tt 31} & {\tt ft8}--{\tt 11} & FP temporaries & Caller \\ \hline \end{tabular} \end{center} \caption{Assembler mnemonics for RISC-V integer and floating-point registers.} \label{regmap} \end{table*} Tables~\ref{pseudos} and \ref{csr-pseudos} contain a listing of standard RISC-V pseudoinstructions. \begin{table}[h] \begin{small} \begin{center} \begin{tabular}{l l l} pseudoinstruction & Base Instruction(s) & Meaning \\ \hline \tt la rd, symbol & {\tt auipc rd, ${\tt delta[31:12]} + {\tt delta[11]}$} & Load absolute address, \\ & {\tt addi rd, rd, delta[11:0]} & where ${\tt delta} = {\tt symbol} - {\tt pc}$ \\[1ex] \tt l\{b|h|w|d\} rd, symbol & {\tt auipc rd, ${\tt delta[31:12]} + {\tt delta[11]}$} & Load global \\ & {\tt l\{b|h|w|d\} rd, delta[11:0](rd)} & \\[1ex] \tt s\{b|h|w|d\} rd, symbol, rt & {\tt auipc rt, ${\tt delta[31:12]} + {\tt delta[11]}$} & Store global \\ & {\tt s\{b|h|w|d\} rd, delta[11:0](rt)} & \\[1ex] \tt fl\{w|d\} rd, symbol, rt & {\tt auipc rt, ${\tt delta[31:12]} + {\tt delta[11]}$} & Floating-point load global \\ & {\tt fl\{w|d\} rd, delta[11:0](rt)} & \\[1ex] \tt fs\{w|d\} rd, symbol, rt & {\tt auipc rt, ${\tt delta[31:12]} + {\tt delta[11]}$} & Floating-point store global \\ & {\tt fs\{w|d\} rd, delta[11:0](rt)} & \\[1ex] \multicolumn{3}{p{.99\textwidth}}{\small \em The base instructions use {\tt pc}-relative addressing, so the linker subtracts {\tt pc} from {\tt symbol} to get {\tt delta}. The linker adds {\tt delta[11]} to the 20-bit high part, counteracting sign extension of the 12-bit low part.} \\ ~\\ \hline {\tt nop} & {\tt addi x0, x0, 0} & No operation \\ {\tt li rd, immediate} & {\em Myriad sequences} & Load immediate \\ {\tt mv rd, rs} & {\tt addi rd, rs, 0} & Copy register \\ {\tt not rd, rs} & {\tt xori rd, rs, -1} & One's complement \\ {\tt neg rd, rs} & {\tt sub rd, x0, rs} & Two's complement \\ {\tt negw rd, rs} & {\tt subw rd, x0, rs} & Two's complement word \\ {\tt sext.w rd, rs} & {\tt addiw rd, rs, 0} & Sign extend word \\ {\tt seqz rd, rs} & {\tt sltiu rd, rs, 1} & Set if $=$ zero \\ {\tt snez rd, rs} & {\tt sltu rd, x0, rs} & Set if $\neq$ zero \\ {\tt sltz rd, rs} & {\tt slt rd, rs, x0} & Set if $<$ zero \\ {\tt sgtz rd, rs} & {\tt slt rd, x0, rs} & Set if $>$ zero \\ \hline {\tt fmv.s rd, rs} & {\tt fsgnj.s rd, rs, rs} & Copy single-precision register \\ {\tt fabs.s rd, rs} & {\tt fsgnjx.s rd, rs, rs} & Single-precision absolute value \\ {\tt fneg.s rd, rs} & {\tt fsgnjn.s rd, rs, rs} & Single-precision negate \\ {\tt fmv.d rd, rs} & {\tt fsgnj.d rd, rs, rs} & Copy double-precision register \\ {\tt fabs.d rd, rs} & {\tt fsgnjx.d rd, rs, rs} & Double-precision absolute value \\ {\tt fneg.d rd, rs} & {\tt fsgnjn.d rd, rs, rs} & Double-precision negate \\ \hline {\tt beqz rs, offset} & {\tt beq rs, x0, offset} & Branch if $=$ zero \\ {\tt bnez rs, offset} & {\tt bne rs, x0, offset} & Branch if $\neq$ zero \\ {\tt blez rs, offset} & {\tt bge x0, rs, offset} & Branch if $\leq$ zero \\ {\tt bgez rs, offset} & {\tt bge rs, x0, offset} & Branch if $\geq$ zero \\ {\tt bltz rs, offset} & {\tt blt rs, x0, offset} & Branch if $<$ zero \\ {\tt bgtz rs, offset} & {\tt blt x0, rs, offset} & Branch if $>$ zero \\ \hline {\tt bgt rs, rt, offset} & {\tt blt rt, rs, offset} & Branch if $>$ \\ {\tt ble rs, rt, offset} & {\tt bge rt, rs, offset} & Branch if $\leq$ \\ {\tt bgtu rs, rt, offset} & {\tt bltu rt, rs, offset} & Branch if $>$, unsigned \\ {\tt bleu rs, rt, offset} & {\tt bgeu rt, rs, offset} & Branch if $\leq$, unsigned \\ \hline {\tt j offset} & {\tt jal x0, offset} & Jump \\ {\tt jal offset} & {\tt jal x1, offset} & Jump and link \\ {\tt jr rs} & {\tt jalr x0, 0(rs)} & Jump register \\ {\tt jalr rs} & {\tt jalr x1, 0(rs)} & Jump and link register \\ {\tt ret} & {\tt jalr x0, 0(x1)} & Return from subroutine \\ \tt call offset & {\tt auipc x1, ${\tt offset[31:12]} + {\tt offset[11]}$} & Call far-away subroutine \\ & {\tt jalr x1, offset[11:0](x1)} & \\ \tt tail offset & {\tt auipc x6, ${\tt offset[31:12]} + {\tt offset[11]}$} & Tail call far-away subroutine \\ & {\tt jalr x0, offset[11:0](x6)} & \\ \hline {\tt fence} & {\tt fence iorw, iorw} & Fence on all memory and I/O \\ \hline \end{tabular} \end{center} \end{small} \caption{RISC-V pseudoinstructions.} \label{pseudos} \end{table} \begin{table}[h] \begin{small} \begin{center} \begin{tabular}{l l l} pseudoinstruction & Base Instruction & Meaning \\ \hline {\tt rdinstret[h] rd} & {\tt csrrs rd, instret[h], x0} & Read instructions-retired counter \\ {\tt rdcycle[h] rd} & {\tt csrrs rd, cycle[h], x0} & Read cycle counter \\ {\tt rdtime[h] rd} & {\tt csrrs rd, time[h], x0} & Read real-time clock \\ \hline {\tt csrr rd, csr} & {\tt csrrs rd, csr, x0} & Read CSR \\ {\tt csrw csr, rs} & {\tt csrrw x0, csr, rs} & Write CSR \\ {\tt csrs csr, rs} & {\tt csrrs x0, csr, rs} & Set bits in CSR \\ {\tt csrc csr, rs} & {\tt csrrc x0, csr, rs} & Clear bits in CSR \\ \hline {\tt csrwi csr, imm} & {\tt csrrwi x0, csr, imm} & Write CSR, immediate \\ {\tt csrsi csr, imm} & {\tt csrrsi x0, csr, imm} & Set bits in CSR, immediate \\ {\tt csrci csr, imm} & {\tt csrrci x0, csr, imm} & Clear bits in CSR, immediate \\ \hline {\tt frcsr rd} & {\tt csrrs rd, fcsr, x0} & Read FP control/status register \\ {\tt fscsr rd, rs} & {\tt csrrw rd, fcsr, rs} & Swap FP control/status register \\ {\tt fscsr rs} & {\tt csrrw x0, fcsr, rs} & Write FP control/status register \\ \hline {\tt frrm rd} & {\tt csrrs rd, frm, x0} & Read FP rounding mode \\ {\tt fsrm rd, rs} & {\tt csrrw rd, frm, rs} & Swap FP rounding mode \\ {\tt fsrm rs} & {\tt csrrw x0, frm, rs} & Write FP rounding mode \\ \hline {\tt frflags rd} & {\tt csrrs rd, fflags, x0} & Read FP exception flags \\ {\tt fsflags rd, rs} & {\tt csrrw rd, fflags, rs} & Swap FP exception flags \\ {\tt fsflags rs} & {\tt csrrw x0, fflags, rs} & Write FP exception flags \\ \hline \end{tabular} \end{center} \end{small} \caption{Pseudoinstructions for accessing control and status registers.} \label{csr-pseudos} \end{table}