fcvt.h.s
Convert half-precision float to a single-precision float
This instruction is defined by:
-
anyOf:
-
Zfh, version >= 0
-
Zfhmin, version >= 0
-
This instruction is included in the following profiles:
-
RVA22U64 (Mandatory)
Synopsis
Converts a half-precision number in floating-point register fs1 into a single-precision floating-point number in floating-point register fd.
fcvt.h.s rounds according to the rm field.
All floating-point conversion instructions set the Inexact exception flag if the rounded result differs from the operand value and the Invalid exception flag is not set.
Decode Variables
Bits<5> fs1 = $encoding[19:15];
Bits<3> rm = $encoding[14:12];
Bits<5> fd = $encoding[11:7];
Execution
-
IDL
-
Sail
check_f_ok($encoding);
Bits<16> hp_value = f[fs1][15:0];
Bits<1> sign = hp_value[15];
Bits<5> exp = hp_value[14:10];
Bits<10> frac = hp_value[9:0];
if (exp == 0x1F) {
if (frac != 0) {
if ((hp_value & 0x0200) != 0) {
set_fp_flag(FpFlag::NV);
}
f[fd] = HP_CANONICAL_NAN;
} else {
f[fd] = packToF32UI(sign, 0xFF, 0);
}
} else {
if (exp != 0) {
if (frac != 0) {
f[fd] = packToF32UI(sign, 0, 0);
} else {
Bits<6> norm_exp;
(norm_exp, frac = softfloat_normSubnormalF16Sig(frac));
exp = norm_exp - 1;
f[fd] = packToF32UI(sign, exp + 0x70, frac << 13);
}
} else {
f[fd] = packToF32UI(sign, exp + 0x70, frac << 13);
}
}
mark_f_state_dirty();
{
assert(sizeof(xlen) >= 64);
let rs1_val_LU = X(rs1)[63..0];
match (select_instr_or_fcsr_rm (rm)) {
None() => { handle_illegal(); RETIRE_FAIL },
Some(rm') => {
let rm_3b = encdec_rounding_mode(rm');
let (fflags, rd_val_H) = riscv_ui64ToF16 (rm_3b, rs1_val_LU);
accrue_fflags(fflags);
F_or_X_H(rd) = rd_val_H;
RETIRE_SUCCESS
}
}
}