Question bank — RISC-V extensions (M, A, F, D, V, C)
Before we start, one plain-word refresher so nothing is used undefined:
The bit-level pictures below back up the multiplication, LR/SC, and floating-point traps — look at them as you work.
Pictures that power the traps
One product, two halves. A 32×32 multiply makes a 64-bit result. MUL grabs the low half, MULH* the high half of the same product:

The LR/SC retry loop. LR raises a reservation; if another core writes the line, SC fails and the loop retries with fresh data:

Float addition alignment. Before mantissas can be added they must share an exponent — shift the smaller one right:

IEEE-754 exponent map. The stored exponent field carves the number line into regions — zero/subnormal, normal, and infinity/NaN:

See 5.2.03-IEEE-754-floating-point for the full treatment.
True or false — justify
The base ISA already includes integer multiply, so the M extension only adds divide.
MUL* and DIV*. A base-only chip does multiply in a shift-add software loop.MUL and MULH compute two independent multiplications.
MUL returns the low half, MULH the high half of the same product (see the two-halves figure).If you only need the low 32 bits of a 32×32 product, the signedness of the operands doesn't matter.
MUL but three MULH variants.LR.W followed by SC.W guarantees the store will succeed.
SC may fail (return non-zero) if another core touched the reserved line, or even spuriously; the point of the retry loop is that failure is expected and normal.amoadd.w and an LR/SC loop that adds are functionally interchangeable, so choose whichever.
amoadd.w is a single instruction that locks the line directly, while LR/SC is a multi-instruction loop that can livelock under heavy contention — prefer the AMO for simple patterns.The A extension needs no help from the memory system; it's purely a CPU feature.
The F extension's registers f0–f31 are the same registers as the integer x0–x31.
FMV/load-store; they don't overlap.Any decimal you write in source code has an exact single-precision representation.
0.1 and 0.2 repeat forever in binary, so they're stored rounded (see 5.2.03-IEEE-754-floating-point).Double precision is just "single precision but slower"; the number range is the same.
A chip can implement RV32IMAC while skipping F and D entirely.
Signed division DIV of MIN_INT by −1 raises an exception, just like division by zero does on x86.
MIN_INT ÷ −1 overflows the representable range so it is defined to return MIN_INT (and REM returns 0); no fault occurs.Spot the error
mulh t1, a0, a1 where a0, a1 hold two unsigned magnitudes — what's wrong?
MULH sign-extends both operands, so if either has its top bit set it's misread as negative. For unsigned inputs use MULHU.A programmer writes sc.w without ever running lr.w first, expecting a plain conditional store.
SC only means anything relative to a prior LR reservation; with no reservation raised it will simply fail (or behave undefined by contract). It is not a general "store-if" instruction.Inside an LR/SC retry loop, someone inserts a normal load/store to an unrelated address between the lr.w and sc.w.
Storing the true exponent −126 for a single-precision number directly as a signed 8-bit field.
−126 + 127 = 1, an unsigned value. Raw signed exponents would break the "compare as unsigned integers to compare magnitudes" trick.Claiming 0x80000000 × 0x80000000 overflows and can't be represented.
MULH returns the high half 0x40000000; nothing overflows because the product width is doubled by design.Testing floating equality with if (0.1 + 0.2 == 0.3) and expecting true.
0.1 + 0.2 come out as 0.30000000000000004; float comparisons must use a tolerance, never exact ==.Handling divide-by-zero by wrapping every DIV in a "hardware will fault, so I'll catch the exception" pattern.
DIV x, 0 to return all-ones (−1), DIVU x, 0 all-ones too, and REM/REMU x, 0 to return the dividend. You must test the divisor in software before dividing if you want error handling.Why questions
Why does MULH come in three flavours (MULH, MULHU, MULHSU) but MUL has only one?
MUL suffices.Why did RISC-V choose to define divide-by-zero results instead of trapping?
Why can't you build a lock in user mode by just "disabling interrupts around the critical section"?
Why does the A extension "piggyback" on cache coherence instead of adding new hardware?
Why is the floating-point exponent biased instead of stored as a signed two's-complement number?
Why does the result of 0.1 + 0.2 == 0.3 depend on the rounding mode?
0.1+0.2 up to ...0004, but a mode like round-toward-zero could land on a different last bit — so "which floats are equal" is mode-dependent.Why separate F and D into two extensions instead of one "floating point" extension?
Why does hardware floating-point addition need an "align exponents" step at all?
Why is the leading mantissa bit "implicit" (not stored) in normalized floats?
1.something × 2ᵏ, so the leading 1 is guaranteed and storing it would waste a bit — dropping it buys one extra bit of precision for free.Edge cases
What does SC return, and what does its value mean at the boundary between success and failure?
0 into rd on success (store happened, atomicity held) and non-zero (typically 1) on failure (reservation lost); zero being success lets bnez branch straight to the retry.Two cores both spin in an LR/SC increment loop forever — is progress guaranteed?
What is the defined result of DIV MIN_INT, −1 and REM MIN_INT, −1 on RV32?
DIV returns MIN_INT (0x80000000) because the true quotient +2³¹ doesn't fit, and REM returns 0; both are specified, no overflow flag or trap.Reserved exponent fields: what do the all-zero and all-ones exponents mean in IEEE 754?
Multiplying so the true product needs both halves — how do you reconstruct the full value from MUL and MULH?
MULH sits above MUL when you concatenate the two words.What happens to a running single-precision sum after ~10⁶ additions of numbers around the same magnitude?
Can a compressed-instruction (C) chip also lack multiply?
C only re-encodes existing instructions into 16-bit forms for code density (3.3.06-Instruction-encoding); it adds no arithmetic capability, so RV32C without M still has no hardware multiply.Is MULHSU symmetric — can you swap which operand is signed?
MULHSU fixes rs1 as signed and rs2 as unsigned; swapping the roles changes the interpretation and generally the result, so operand order is meaningful here.Recall Quick self-check
Why is the low half of a product signedness-independent? ::: Because two's-complement addition/multiplication produce identical low bits regardless of sign interpretation — only the high (sign-carrying) bits differ.
What flag makes atomics work, and who invalidates it? ::: The per-core reservation flag, invalidated by any other core's coherence write to the reserved line.
Why bias 127 for single precision? ::: It's , centring the exponent range and letting exponents be compared as unsigned integers.
What does RISC-V do on divide-by-zero? ::: Nothing exceptional — it returns a defined value (−1 for DIV, the dividend for REM); no trap, so check in software.