mul

mul

RISC-V Assembly Reference

lyszt.net covers mul and other RISC-V instructions in more detail.

Encoding format

R
31–25funct7
24–20rs2
19–15rs1
14–12funct3
11–7rd
6–0opcode
I
31–20imm[11:0]
19–15rs1
14–12funct3
11–7rd
6–0opcode
S
31–25imm[11:5]
24–20rs2
19–15rs1
14–12funct3
11–7imm[4:0]
6–0opcode
B
31–25imm[12,10:5]
24–20rs2
19–15rs1
14–12funct3
11–7imm[4:1,11]
6–0opcode
U
31–12imm[31:12]
11–7rd
6–0opcode
J
31–12imm[20,10:1,11,19:12]
11–7rd
6–0opcode

Description

mul multiplies two registers. It reads rs1 and rs2, multiplies those values, and writes the product to rd. The format below means rd = rs1 * rs2.

mul rd, rs1, rs2

RISC-V is organized in layers called extensions. Multiply and divide belong to the extension named M, which the smallest RISC-V core can omit. This simulator includes it, because its full name RV32IM ends in M, so mul and div are available. A processor without M must do the work in software.

The product of two 32-bit numbers can reach 64 bits, which exceeds what one register holds. mul keeps the lower 32 bits. For small values that is the whole answer. The upper 32 bits come from a separate instruction, mulh. Signed and unsigned inputs produce the same lower 32 bits, so one instruction covers both.

When both halves of a product are needed, the RISC-V manual recommends a fixed pair of instructions. A mulh instruction (or one of its unsigned variants) supplies the high half, and mul with the same source registers in the same order supplies the low half. The destination of the high half cannot be rs1 or rs2. A processor can then fuse the two instructions into one multiplication.

Multiplying by a power of two (2, 4, 8, 16 and so on) can use a left shift instead. Shifting left by 3 places multiplies by 8, and a shift costs less than a multiply (see slli). Compilers make this replacement automatically. The example multiplies 6 by 7 and leaves 42 in t2.

Example

li t0, 6
li t1, 7
mul t2, t0, t1   # t2 = 42