mulh

Signed multiply high

Multiply the signed values in rs1 to rs2, and store the upper half of the result in rd. The lower half is thrown away.

If both the upper and lower halves are needed, it suggested to use the sequence:


  mulh rdh, rs1, rs2
  mul  rdl, rs1, rs2
---

Microarchitectures may look for that sequence and fuse the operations.

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

Assembly format

mulh rd, rs1, rs2

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) && (misa.M == 1'b0)) {
  raise(ExceptionCode::IllegalInstruction, mode(), $encoding);
}
Bits<1> rs1_sign_bit = X[rs1][xlen() - 1];
Bits<MXLEN `* 2> src1 = {{xlen(){rs1_sign_bit}}, X[rs1]};
Bits<1> rs2_sign_bit = X[rs2][xlen() - 1];
Bits<MXLEN `* 2> src2 = {{xlen(){rs2_sign_bit}}, X[rs2]};
X[rd] = (src1 * src2)[(xlen() * 8'd2) - 1:xlen()];
{
  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

Encoding

svg

Defining extension

  • anyOf:

    • M, version >= M@2.0.0

    • Zmmul, version >= Zmmul@1.0.0

Access

M HS U VS VU

Always

Always

Always

Always

Always

Containing profiles

  • Mandatory: RVA20S64, RVA20U64, RVA22S64, RVA22U64, RVA23M64, RVA23S64, RVA23U64, RVB23M64, RVB23S64, RVB23U64

  • Optional: RVI20U32, RVI20U64