div
lyszt.net covers div and other RISC-V instructions in more detail.
Encoding format
Description
div divides one register by another. It reads source registers rs1 and rs2, divides the first by the second, and writes the result to destination register rd. The form below means rd = rs1 / rs2.
div rd, rs1, rs2
Like multiply, it belongs to the M extension of optional math instructions, which this simulator includes.
This is integer division, so the fractional part is dropped. 7 divided by 2 gives 3. The leftover 1 comes from rem, which computes the remainder of the same two numbers. Negative results round toward zero, so -7 / 2 gives -3.
Dividing by zero returns -1, a register with every bit set to 1. The hardware gives no warning, so code that must treat a zero divisor as an error checks the divisor before dividing.
The RISC-V manual specifies the special cases. Dividing by zero gives a quotient with every bit set, which reads as -1 for div, and a remainder equal to the dividend. Signed overflow happens only when the most negative number is divided by -1. The quotient then equals the dividend and the remainder is zero. The manual says a trap on division by zero was considered and rejected, because it would be the only arithmetic trap in the instruction set, and that all bits set keeps the divider circuit simple.
For any division that does not overflow, the dividend equals the divisor times the quotient plus the remainder. When both the quotient and the remainder are needed, the manual recommends the two lines below, with rdq different from rs1 and rs2. A processor can then fuse the two into a single division.
div rdq, rs1, rs2 rem rdr, rs1, rs2
Division is the slowest arithmetic a processor does, often many times slower than multiplication. Dividing by a power of two (2, 4, 8 and so on) can use a right shift instead (see srai). The example divides 17 by 5. 5 goes into 17 three whole times with 2 left over, so the quotient 3 goes into t2.
Example
li t0, 17 li t1, 5 div t2, t0, t1 # t2 = 3
