mul

Signed multiply

This instruction is defined by:

  • anyOf:

    • M, version >= 0

    • Zmmul, version >= 0

This instruction is included in the following profiles:

  • RVA20U64 (Mandatory)

  • RVA22U64 (Mandatory)

  • RVI20U32 (Optional)

  • RVI20U64 (Optional)

Encoding

svg

Assembly format

mul rd, rs1, rs2

Synopsis

This instruction must have data-independent timing when extension Zkt is enabled.

MUL performs an XLEN-bitxXLEN-bit multiplication of rs1 by rs2 and places the lower XLEN bits in the destination register. Any overflow is thrown away.

If both the high and low bits of the same product are required, then the recommended code sequence is: MULH[[S]U] rdh, rs1, rs2; MUL rdl, rs1, rs2 (source register specifiers must be in same order and rdh cannot be the same as rs1 or rs2). Microarchitectures can then fuse these into a single multiply operation instead of performing two separate multiplies.

Access

M HS U VS VU

Always

Always

Always

Always

Always

Decode Variables

Bits<5> rs2 = $encoding[24:20];
Bits<5> rs1 = $encoding[19:15];
Bits<5> rd = $encoding[11:7];

Execution

  • IDL

  • Sail

if (implemented?(ExtensionName::M) && (CSR[misa].M == 1'b0)) {
  raise(ExceptionCode::IllegalInstruction, mode(), $encoding);
}
XReg src1 = X[rs1];
XReg src2 = X[rs2];
X[rd] = (src1 * src2)[XLEN - 1:0];
{
  if extension("M") | haveZmmul() then {
    let rs1_val = X(rs1);
    let rs2_val = X(rs2);
    let rs1_int : int = if signed1 then signed(rs1_val) else unsigned(rs1_val);
    let rs2_int : int = if signed2 then signed(rs2_val) else unsigned(rs2_val);
    let result_wide = to_bits(2 * sizeof(xlen), rs1_int * rs2_int);
    let result = if   high
                 then result_wide[(2 * sizeof(xlen) - 1) .. sizeof(xlen)]
                 else result_wide[(sizeof(xlen) - 1) .. 0];
    X(rd) = result;
    RETIRE_SUCCESS
  } else {
    handle_illegal();
    RETIRE_FAIL
  }
}

Exceptions

This instruction may result in the following synchronous exceptions:

  • IllegalInstruction