Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Signedness and width guide

RISC-V does not consistently encode signedness in mnemonics. Some operations have separate signed and unsigned forms; others use the same instruction regardless of interpretation. This page is a quick-reference for which is which.

Quick-reference table

OperationSigned formUnsigned formNotes
byte loadLBLBULB sign-extends to XLEN; LBU zero-extends
halfword loadLHLHUsame pattern as byte loads
word loadLWLWUboth load 32 bits; LW sign-extends to XLEN, LWU zero-extends; LWU is RV64-only
less-than branchBLTBLTUsame register encoding, different comparison
less-than setSLT / SLTISLTU / SLTIUproduces a 0/1 boolean
comparison branchesBGEBGEUgreater-or-equal counterpart
divisionDIVDIVUquotient; remainder follows (REM / REMU)
multiply highMULHMULHUhigh half of XLEN × XLEN product

Operations that are always the same

Addition, subtraction, bitwise logic, left shift, and low-half multiplication produce the same bit pattern regardless of signed or unsigned interpretation. Right shift is the exception: choose logical SRL for zero-fill or arithmetic SRA for sign propagation.

InstructionWhy no separate form
ADD / ADDITwo’s-complement addition is bitwise identical for signed and unsigned
SUBSame as addition — a − b = a + (~b + 1) works the same way
AND / OR / XORBitwise operations have no signedness
SLLLeft shift has the same bit result for signed and unsigned values
SRL / SRARight shift requires an explicit choice: zero-fill or sign propagation
MUL (low half)Low XLEN bits of a product are identical for signed and unsigned operands

Width extension

Load instructions extend the loaded value to fill the destination register. The extension direction (sign or zero) is the key difference between the signed and unsigned forms.

LB   rd, off(rs1)     # load byte,     sign-extend to XLEN
LBU  rd, off(rs1)     # load byte,     zero-extend to XLEN

LH   rd, off(rs1)     # load halfword, sign-extend to XLEN
LHU  rd, off(rs1)     # load halfword, zero-extend to XLEN

LW   rd, off(rs1)     # load word,     sign-extend to XLEN
LWU  rd, off(rs1)     # load word,     zero-extend to XLEN (RV64 only)

LW is available on both RV32 and RV64. LWU is RV64-only (GNU as rejects it for RV32 targets). On RV32 both forms would be identical — there is no extension to perform when loading 32 bits into a 32-bit register — but the assembler does not accept LWU as a mnemonic.

The SLTIU gotcha

SLTIU performs an unsigned comparison but still sign-extends its 12-bit immediate before comparing. This means a negative immediate represents a large unsigned value:

sltiu rd, rs, 0         # rd = (rs < 0) — always 0 (unsigned)
sltiu rd, rs, -1        # rd = (rs < 0xFFFF…FF) — always 1 unless rs is max value
sltiu rd, rs, 1         # rd = (rs < 1) — equivalent to seqz (rs == 0)

The immediate is sign-extended because SLTIU reuses the same immediate encoding as every other I-type instruction — the sign-extension is a property of the encoding, not the comparison logic.

x86 connection

x86 expresses signedness through different mnemonics for almost every operation: jl vs jb, setl vs setb, idiv vs div, imul vs mul, movsx vs movzx. RISC-V collapses many of these pairs into a single instruction (addition, subtraction, low-half multiply) because the bit pattern is the same either way.

Where RISC-V does use separate forms (loads, branches, set-less-than, division), the U suffix consistently means “unsigned,” which is simpler than x86’s historical naming (jb = jump below, jl = jump less, setb = set below, setl = set less, etc.).

Related: Loads, Stores, BLT / BGE / BLTU / BGEU, SLT / SLTI / SLTU / SLTIU, *W — RV64 word operations.