mulw

Signed 32-bit 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

mulw rd, rs1, rs2

Synopsis

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

Multiplies the lower 32 bits of the source registers, placing the sign-extension of the lower 32 bits of the result into the destination register.

Any overflow is thrown away.

In RV64, MUL can be used to obtain the upper 32 bits of the 64-bit product, but signed arguments must be proper 32-bit signed values, whereas unsigned arguments must have their upper 32 bits clear. If the arguments are not known to be sign- or zero-extended, an alternative is to shift both arguments left by 32 bits, then use MULH[[S]U].

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);
}
Bits<32> src1 = X[rs1][31:0];
Bits<32> src2 = X[rs2][31:0];
Bits<32> result = src1 * src2;
Bits<1> sign_bit = result[31];
X[rd] = {{32{sign_bit}}, result};
{
  if extension("M") | haveZmmul() then {
    let rs1_val = X(rs1)[31..0];
    let rs2_val = X(rs2)[31..0];
    let rs1_int : int = signed(rs1_val);
    let rs2_int : int = signed(rs2_val);
    /* to_bits requires expansion to 64 bits followed by truncation */
    let result32 = to_bits(64, rs1_int * rs2_int)[31..0];
    let result : xlenbits = sign_extend(result32);
    X(rd) = result;
    RETIRE_SUCCESS
  } else {
    handle_illegal();
    RETIRE_FAIL
  }
}

Exceptions

This instruction may result in the following synchronous exceptions:

  • IllegalInstruction