mulhsu
Signed/unsigned multiply high
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)
Synopsis
This instruction must have data-independent timing when extension Zkt is enabled. |
Multiply the signed value in rs1 by the unsigned value in 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:
mulhsu rdh, rs1, rs2 mul rdl, rs1, rs2 ---
Microarchitectures may look for that sequence and fuse the operations.
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<1> rs1_sign_bit = X[rs1][XLEN - 1];
Bits<XLEN * 8'd2> src1 = {{XLEN{rs1_sign_bit}}, X[rs1]};
Bits<XLEN * 8'd2> src2 = {{XLEN{1'b0}}, 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
}
}