aboutsummaryrefslogtreecommitdiff
path: root/model/riscv_insts_vext_utils.sail
diff options
context:
space:
mode:
Diffstat (limited to 'model/riscv_insts_vext_utils.sail')
-rwxr-xr-xmodel/riscv_insts_vext_utils.sail660
1 files changed, 4 insertions, 656 deletions
diff --git a/model/riscv_insts_vext_utils.sail b/model/riscv_insts_vext_utils.sail
index 6796060..99d575b 100755
--- a/model/riscv_insts_vext_utils.sail
+++ b/model/riscv_insts_vext_utils.sail
@@ -41,18 +41,6 @@ function assert_vstart(i) = {
unsigned(vstart) == i
}
-/* Check for valid floating-point operation types
- * 1. Valid element width of floating-point numbers
- * 2. Valid floating-point rounding mode
- */
-val valid_fp_op : ({8, 16, 32, 64}, bits(3)) -> bool
-function valid_fp_op(SEW, rm_3b) = {
- /* 128-bit floating-point values will be supported in future extensions */
- let valid_sew = (SEW >= 16 & SEW <= 128);
- let valid_rm = not(rm_3b == 0b101 | rm_3b == 0b110 | rm_3b == 0b111);
- valid_sew & valid_rm
-}
-
/* Check for valid destination register when vector masking is enabled:
* The destination vector register group for a masked vector instruction
* cannot overlap the source mask register (v0),
@@ -145,65 +133,27 @@ function illegal_reduction_widen(SEW_widen, LMUL_pow_widen) = {
not(valid_vtype()) | not(assert_vstart(0)) | not(valid_eew_emul(SEW_widen, LMUL_pow_widen))
}
-/* g. Normal check for floating-point instructions */
-val illegal_fp_normal : (regidx, bits(1), {8, 16, 32, 64}, bits(3)) -> bool
-function illegal_fp_normal(vd, vm, SEW, rm_3b) = {
- not(valid_vtype()) | not(valid_rd_mask(vd, vm)) | not(valid_fp_op(SEW, rm_3b))
-}
-
-/* h. Masked check for floating-point instructions encoded with vm = 0 */
-val illegal_fp_vd_masked : (regidx, {8, 16, 32, 64}, bits(3)) -> bool
-function illegal_fp_vd_masked(vd, SEW, rm_3b) = {
- not(valid_vtype()) | vd == 0b00000 | not(valid_fp_op(SEW, rm_3b))
-}
-
-/* i. Unmasked check for floating-point instructions encoded with vm = 1 */
-val illegal_fp_vd_unmasked : ({8, 16, 32, 64}, bits(3)) -> bool
-function illegal_fp_vd_unmasked(SEW, rm_3b) = {
- not(valid_vtype()) | not(valid_fp_op(SEW, rm_3b))
-}
-
-/* j. Variable width check for floating-point widening/narrowing instructions */
-val illegal_fp_variable_width : (regidx, bits(1), {8, 16, 32, 64}, bits(3), int, int) -> bool
-function illegal_fp_variable_width(vd, vm, SEW, rm_3b, SEW_new, LMUL_pow_new) = {
- not(valid_vtype()) | not(valid_rd_mask(vd, vm)) | not(valid_fp_op(SEW, rm_3b)) |
- not(valid_eew_emul(SEW_new, LMUL_pow_new))
-}
-
-/* k. Normal check for floating-point reduction instructions */
-val illegal_fp_reduction : ({8, 16, 32, 64}, bits(3)) -> bool
-function illegal_fp_reduction(SEW, rm_3b) = {
- not(valid_vtype()) | not(assert_vstart(0)) | not(valid_fp_op(SEW, rm_3b))
-}
-
-/* l. Variable width check for floating-point widening reduction instructions */
-val illegal_fp_reduction_widen : ({8, 16, 32, 64}, bits(3), int, int) -> bool
-function illegal_fp_reduction_widen(SEW, rm_3b, SEW_widen, LMUL_pow_widen) = {
- not(valid_vtype()) | not(assert_vstart(0)) | not(valid_fp_op(SEW, rm_3b)) |
- not(valid_eew_emul(SEW_widen, LMUL_pow_widen))
-}
-
-/* m. Non-indexed load instruction check */
+/* g. Non-indexed load instruction check */
val illegal_load : (regidx, bits(1), int, int, int) -> bool
function illegal_load(vd, vm, nf, EEW, EMUL_pow) = {
not(valid_vtype()) | not(valid_rd_mask(vd, vm)) |
not(valid_eew_emul(EEW, EMUL_pow)) | not(valid_segment(nf, EMUL_pow))
}
-/* n. Non-indexed store instruction check (with vs3 rather than vd) */
+/* h. Non-indexed store instruction check (with vs3 rather than vd) */
val illegal_store : (int, int, int) -> bool
function illegal_store(nf, EEW, EMUL_pow) = {
not(valid_vtype()) | not(valid_eew_emul(EEW, EMUL_pow)) | not(valid_segment(nf, EMUL_pow))
}
-/* o. Indexed load instruction check */
+/* i. Indexed load instruction check */
val illegal_indexed_load : (regidx, bits(1), int, int, int, int) -> bool
function illegal_indexed_load(vd, vm, nf, EEW_index, EMUL_pow_index, EMUL_pow_data) = {
not(valid_vtype()) | not(valid_rd_mask(vd, vm)) |
not(valid_eew_emul(EEW_index, EMUL_pow_index)) | not(valid_segment(nf, EMUL_pow_data))
}
-/* p. Indexed store instruction check (with vs3 rather than vd) */
+/* j. Indexed store instruction check (with vs3 rather than vd) */
val illegal_indexed_store : (int, int, int, int) -> bool
function illegal_indexed_store(nf, EEW_index, EMUL_pow_index, EMUL_pow_data) = {
not(valid_vtype()) | not(valid_eew_emul(EEW_index, EMUL_pow_index)) |
@@ -437,127 +387,6 @@ function read_vreg_seg(num_elem, SEW, LMUL_pow, nf, vrid) = {
result
}
-/* Floating point canonical NaN for 16-bit, 32-bit and 64-bit types */
-val canonical_NaN : forall 'm, 'm in {16, 32, 64}. int('m) -> bits('m)
-function canonical_NaN('m) = {
- match 'm {
- 16 => canonical_NaN_H(),
- 32 => canonical_NaN_S(),
- 64 => canonical_NaN_D()
- }
-}
-
-/* Floating point classification functions */
-val f_is_neg_inf : forall 'm, 'm in {16, 32, 64}. bits('m) -> bool
-function f_is_neg_inf(xf) = {
- match 'm {
- 16 => f_is_neg_inf_H(xf),
- 32 => f_is_neg_inf_S(xf),
- 64 => f_is_neg_inf_D(xf)
- }
-}
-
-val f_is_neg_norm : forall 'm, 'm in {16, 32, 64}. bits('m) -> bool
-function f_is_neg_norm(xf) = {
- match 'm {
- 16 => f_is_neg_norm_H(xf),
- 32 => f_is_neg_norm_S(xf),
- 64 => f_is_neg_norm_D(xf)
- }
-}
-
-val f_is_neg_subnorm : forall 'm, 'm in {16, 32, 64}. bits('m) -> bool
-function f_is_neg_subnorm(xf) = {
- match 'm {
- 16 => f_is_neg_subnorm_H(xf),
- 32 => f_is_neg_subnorm_S(xf),
- 64 => f_is_neg_subnorm_D(xf)
- }
-}
-
-val f_is_neg_zero : forall 'm, 'm in {16, 32, 64}. bits('m) -> bool
-function f_is_neg_zero(xf) = {
- match 'm {
- 16 => f_is_neg_zero_H(xf),
- 32 => f_is_neg_zero_S(xf),
- 64 => f_is_neg_zero_D(xf)
- }
-}
-
-val f_is_pos_zero : forall 'm, 'm in {16, 32, 64}. bits('m) -> bool
-function f_is_pos_zero(xf) = {
- match 'm {
- 16 => f_is_pos_zero_H(xf),
- 32 => f_is_pos_zero_S(xf),
- 64 => f_is_pos_zero_D(xf)
- }
-}
-
-val f_is_pos_subnorm : forall 'm, 'm in {16, 32, 64}. bits('m) -> bool
-function f_is_pos_subnorm(xf) = {
- match 'm {
- 16 => f_is_pos_subnorm_H(xf),
- 32 => f_is_pos_subnorm_S(xf),
- 64 => f_is_pos_subnorm_D(xf)
- }
-}
-
-val f_is_pos_norm : forall 'm, 'm in {16, 32, 64}. bits('m) -> bool
-function f_is_pos_norm(xf) = {
- match 'm {
- 16 => f_is_pos_norm_H(xf),
- 32 => f_is_pos_norm_S(xf),
- 64 => f_is_pos_norm_D(xf)
- }
-}
-
-val f_is_pos_inf : forall 'm, 'm in {16, 32, 64}. bits('m) -> bool
-function f_is_pos_inf(xf) = {
- match 'm {
- 16 => f_is_pos_inf_H(xf),
- 32 => f_is_pos_inf_S(xf),
- 64 => f_is_pos_inf_D(xf)
- }
-}
-
-val f_is_SNaN : forall 'm, 'm in {16, 32, 64}. bits('m) -> bool
-function f_is_SNaN(xf) = {
- match 'm {
- 16 => f_is_SNaN_H(xf),
- 32 => f_is_SNaN_S(xf),
- 64 => f_is_SNaN_D(xf)
- }
-}
-
-val f_is_QNaN : forall 'm, 'm in {16, 32, 64}. bits('m) -> bool
-function f_is_QNaN(xf) = {
- match 'm {
- 16 => f_is_QNaN_H(xf),
- 32 => f_is_QNaN_S(xf),
- 64 => f_is_QNaN_D(xf)
- }
-}
-
-val f_is_NaN : forall 'm, 'm in {16, 32, 64}. bits('m) -> bool
-function f_is_NaN(xf) = {
- match 'm {
- 16 => f_is_NaN_H(xf),
- 32 => f_is_NaN_S(xf),
- 64 => f_is_NaN_D(xf)
- }
-}
-
-/* Scalar register shaping for floating point operations */
-val get_scalar_fp : forall 'n, 'n in {16, 32, 64}. (regidx, int('n)) -> bits('n)
-function get_scalar_fp(rs1, SEW) = {
- assert(sizeof(flen) >= SEW, "invalid vector floating-point type width: FLEN < SEW");
- match SEW {
- 16 => F_H(rs1),
- 32 => F_S(rs1),
- 64 => F_D(rs1)
- }
-}
-
/* Shift amounts */
val get_shift_amount : forall 'n 'm, 0 <= 'n & 'm in {8, 16, 32, 64}. (bits('n), int('m)) -> nat
function get_shift_amount(bit_val, SEW) = {
@@ -610,283 +439,6 @@ function signed_saturation(len, elem) = {
};
}
-/* Get the floating point rounding mode from csr fcsr */
-val get_fp_rounding_mode : unit -> rounding_mode
-function get_fp_rounding_mode() = encdec_rounding_mode(fcsr[FRM])
-
-/* Negate a floating point number */
-val negate_fp : forall 'm, 'm in {16, 32, 64}. bits('m) -> bits('m)
-function negate_fp(xf) = {
- match 'm {
- 16 => negate_H(xf),
- 32 => negate_S(xf),
- 64 => negate_D(xf)
- }
-}
-
-/* Floating point functions using softfloat interface */
-val fp_add: forall 'm, 'm in {16, 32, 64}. (bits(3), bits('m), bits('m)) -> bits('m)
-function fp_add(rm_3b, op1, op2) = {
- let (fflags, result_val) : (bits_fflags, bits('m)) = match 'm {
- 16 => riscv_f16Add(rm_3b, op1, op2),
- 32 => riscv_f32Add(rm_3b, op1, op2),
- 64 => riscv_f64Add(rm_3b, op1, op2)
- };
- accrue_fflags(fflags);
- result_val
-}
-
-val fp_sub: forall 'm, 'm in {16, 32, 64}. (bits(3), bits('m), bits('m)) -> bits('m)
-function fp_sub(rm_3b, op1, op2) = {
- let (fflags, result_val) : (bits_fflags, bits('m)) = match 'm {
- 16 => riscv_f16Sub(rm_3b, op1, op2),
- 32 => riscv_f32Sub(rm_3b, op1, op2),
- 64 => riscv_f64Sub(rm_3b, op1, op2)
- };
- accrue_fflags(fflags);
- result_val
-}
-
-val fp_min : forall 'm, 'm in {16, 32, 64}. (bits('m), bits('m)) -> bits('m)
-function fp_min(op1, op2) = {
- let (fflags, op1_lt_op2) : (bits_fflags, bool) = match 'm {
- 16 => riscv_f16Lt_quiet(op1, op2),
- 32 => riscv_f32Lt_quiet(op1, op2),
- 64 => riscv_f64Lt_quiet(op1, op2)
- };
-
- let result_val = if (f_is_NaN(op1) & f_is_NaN(op2)) then canonical_NaN('m)
- else if f_is_NaN(op1) then op2
- else if f_is_NaN(op2) then op1
- else if (f_is_neg_zero(op1) & f_is_pos_zero(op2)) then op1
- else if (f_is_neg_zero(op2) & f_is_pos_zero(op1)) then op2
- else if op1_lt_op2 then op1
- else op2;
- accrue_fflags(fflags);
- result_val
-}
-
-val fp_max : forall 'm, 'm in {16, 32, 64}. (bits('m), bits('m)) -> bits('m)
-function fp_max(op1, op2) = {
- let (fflags, op1_lt_op2) : (bits_fflags, bool) = match 'm {
- 16 => riscv_f16Lt_quiet(op1, op2),
- 32 => riscv_f32Lt_quiet(op1, op2),
- 64 => riscv_f64Lt_quiet(op1, op2)
- };
-
- let result_val = if (f_is_NaN(op1) & f_is_NaN(op2)) then canonical_NaN('m)
- else if f_is_NaN(op1) then op2
- else if f_is_NaN(op2) then op1
- else if (f_is_neg_zero(op1) & f_is_pos_zero(op2)) then op2
- else if (f_is_neg_zero(op2) & f_is_pos_zero(op1)) then op1
- else if op1_lt_op2 then op2
- else op1;
- accrue_fflags(fflags);
- result_val
-}
-
-val fp_eq : forall 'm, 'm in {16, 32, 64}. (bits('m), bits('m)) -> bool
-function fp_eq(op1, op2) = {
- let (fflags, result_val) : (bits_fflags, bool) = match 'm {
- 16 => riscv_f16Eq(op1, op2),
- 32 => riscv_f32Eq(op1, op2),
- 64 => riscv_f64Eq(op1, op2)
- };
- accrue_fflags(fflags);
- result_val
-}
-
-val fp_gt : forall 'm, 'm in {16, 32, 64}. (bits('m), bits('m)) -> bool
-function fp_gt(op1, op2) = {
- let (fflags, temp_val) : (bits_fflags, bool) = match 'm {
- 16 => riscv_f16Le(op1, op2),
- 32 => riscv_f32Le(op1, op2),
- 64 => riscv_f64Le(op1, op2)
- };
- let result_val = (if fflags == 0b10000 then false else not(temp_val));
- accrue_fflags(fflags);
- result_val
-}
-
-val fp_ge : forall 'm, 'm in {16, 32, 64}. (bits('m), bits('m)) -> bool
-function fp_ge(op1, op2) = {
- let (fflags, temp_val) : (bits_fflags, bool) = match 'm {
- 16 => riscv_f16Lt(op1, op2),
- 32 => riscv_f32Lt(op1, op2),
- 64 => riscv_f64Lt(op1, op2)
- };
- let result_val = (if fflags == 0b10000 then false else not(temp_val));
- accrue_fflags(fflags);
- result_val
-}
-
-val fp_lt : forall 'm, 'm in {16, 32, 64}. (bits('m), bits('m)) -> bool
-function fp_lt(op1, op2) = {
- let (fflags, result_val) : (bits_fflags, bool) = match 'm {
- 16 => riscv_f16Lt(op1, op2),
- 32 => riscv_f32Lt(op1, op2),
- 64 => riscv_f64Lt(op1, op2)
- };
- accrue_fflags(fflags);
- result_val
-}
-
-val fp_le : forall 'm, 'm in {16, 32, 64}. (bits('m), bits('m)) -> bool
-function fp_le(op1, op2) = {
- let (fflags, result_val) : (bits_fflags, bool) = match 'm {
- 16 => riscv_f16Le(op1, op2),
- 32 => riscv_f32Le(op1, op2),
- 64 => riscv_f64Le(op1, op2)
- };
- accrue_fflags(fflags);
- result_val
-}
-
-val fp_mul : forall 'm, 'm in {16, 32, 64}. (bits(3), bits('m), bits('m)) -> bits('m)
-function fp_mul(rm_3b, op1, op2) = {
- let (fflags, result_val) : (bits_fflags, bits('m)) = match 'm {
- 16 => riscv_f16Mul(rm_3b, op1, op2),
- 32 => riscv_f32Mul(rm_3b, op1, op2),
- 64 => riscv_f64Mul(rm_3b, op1, op2)
- };
- accrue_fflags(fflags);
- result_val
-}
-
-val fp_div : forall 'm, 'm in {16, 32, 64}. (bits(3), bits('m), bits('m)) -> bits('m)
-function fp_div(rm_3b, op1, op2) = {
- let (fflags, result_val) : (bits_fflags, bits('m)) = match 'm {
- 16 => riscv_f16Div(rm_3b, op1, op2),
- 32 => riscv_f32Div(rm_3b, op1, op2),
- 64 => riscv_f64Div(rm_3b, op1, op2)
- };
- accrue_fflags(fflags);
- result_val
-}
-
-val fp_muladd : forall 'm, 'm in {16, 32, 64}. (bits(3), bits('m), bits('m), bits('m)) -> bits('m)
-function fp_muladd(rm_3b, op1, op2, opadd) = {
- let (fflags, result_val) : (bits_fflags, bits('m)) = match 'm {
- 16 => riscv_f16MulAdd(rm_3b, op1, op2, opadd),
- 32 => riscv_f32MulAdd(rm_3b, op1, op2, opadd),
- 64 => riscv_f64MulAdd(rm_3b, op1, op2, opadd)
- };
- accrue_fflags(fflags);
- result_val
-}
-
-val fp_nmuladd : forall 'm, 'm in {16, 32, 64}. (bits(3), bits('m), bits('m), bits('m)) -> bits('m)
-function fp_nmuladd(rm_3b, op1, op2, opadd) = {
- let op1 = negate_fp(op1);
- let (fflags, result_val) : (bits_fflags, bits('m)) = match 'm {
- 16 => riscv_f16MulAdd(rm_3b, op1, op2, opadd),
- 32 => riscv_f32MulAdd(rm_3b, op1, op2, opadd),
- 64 => riscv_f64MulAdd(rm_3b, op1, op2, opadd)
- };
- accrue_fflags(fflags);
- result_val
-}
-
-val fp_mulsub : forall 'm, 'm in {16, 32, 64}. (bits(3), bits('m), bits('m), bits('m)) -> bits('m)
-function fp_mulsub(rm_3b, op1, op2, opsub) = {
- let opsub = negate_fp(opsub);
- let (fflags, result_val) : (bits_fflags, bits('m)) = match 'm {
- 16 => riscv_f16MulAdd(rm_3b, op1, op2, opsub),
- 32 => riscv_f32MulAdd(rm_3b, op1, op2, opsub),
- 64 => riscv_f64MulAdd(rm_3b, op1, op2, opsub)
- };
- accrue_fflags(fflags);
- result_val
-}
-
-val fp_nmulsub : forall 'm, 'm in {16, 32, 64}. (bits(3), bits('m), bits('m), bits('m)) -> bits('m)
-function fp_nmulsub(rm_3b, op1, op2, opsub) = {
- let opsub = negate_fp(opsub);
- let op1 = negate_fp(op1);
- let (fflags, result_val) : (bits_fflags, bits('m)) = match 'm {
- 16 => riscv_f16MulAdd(rm_3b, op1, op2, opsub),
- 32 => riscv_f32MulAdd(rm_3b, op1, op2, opsub),
- 64 => riscv_f64MulAdd(rm_3b, op1, op2, opsub)
- };
- accrue_fflags(fflags);
- result_val
-}
-
-val fp_class : forall 'm, 'm in {16, 32, 64}. bits('m) -> bits('m)
-function fp_class(xf) = {
- let result_val_10b : bits(10) =
- if f_is_neg_inf(xf) then 0b_00_0000_0001
- else if f_is_neg_norm(xf) then 0b_00_0000_0010
- else if f_is_neg_subnorm(xf) then 0b_00_0000_0100
- else if f_is_neg_zero(xf) then 0b_00_0000_1000
- else if f_is_pos_zero(xf) then 0b_00_0001_0000
- else if f_is_pos_subnorm(xf) then 0b_00_0010_0000
- else if f_is_pos_norm(xf) then 0b_00_0100_0000
- else if f_is_pos_inf(xf) then 0b_00_1000_0000
- else if f_is_SNaN(xf) then 0b_01_0000_0000
- else if f_is_QNaN(xf) then 0b_10_0000_0000
- else zeros();
-
- zero_extend(result_val_10b)
-}
-
-val fp_widen : forall 'm, 'm in {16, 32}. bits('m) -> bits('m * 2)
-function fp_widen(nval) = {
- let rm_3b = fcsr[FRM];
- let (fflags, wval) : (bits_fflags, bits('m * 2)) = match 'm {
- 16 => riscv_f16ToF32(rm_3b, nval),
- 32 => riscv_f32ToF64(rm_3b, nval)
- };
- accrue_fflags(fflags);
- wval
-}
-
-/* Floating point functions without softfloat support */
-val riscv_f16ToI16 : (bits_rm, bits_H) -> (bits_fflags, bits(16))
-function riscv_f16ToI16 (rm, v) = {
- let (_, sig32) = riscv_f16ToI32(rm, v);
- if signed(sig32) > signed(0b0 @ ones(15)) then (nvFlag(), 0b0 @ ones(15))
- else if signed(sig32) < signed(0b1 @ zeros(15)) then (nvFlag(), 0b1 @ zeros(15))
- else (zeros(5), sig32[15 .. 0]);
-}
-
-val riscv_f16ToI8 : (bits_rm, bits_H) -> (bits_fflags, bits(8))
-function riscv_f16ToI8 (rm, v) = {
- let (_, sig32) = riscv_f16ToI32(rm, v);
- if signed(sig32) > signed(0b0 @ ones(7)) then (nvFlag(), 0b0 @ ones(7))
- else if signed(sig32) < signed(0b1 @ zeros(7)) then (nvFlag(), 0b1 @ zeros(7))
- else (zeros(5), sig32[7 .. 0]);
-}
-
-val riscv_f32ToI16 : (bits_rm, bits_S) -> (bits_fflags, bits(16))
-function riscv_f32ToI16 (rm, v) = {
- let (_, sig32) = riscv_f32ToI32(rm, v);
- if signed(sig32) > signed(0b0 @ ones(15)) then (nvFlag(), 0b0 @ ones(15))
- else if signed(sig32) < signed(0b1 @ zeros(15)) then (nvFlag(), 0b1 @ zeros(15))
- else (zeros(5), sig32[15 .. 0]);
-}
-
-val riscv_f16ToUi16 : (bits_rm, bits_H) -> (bits_fflags, bits(16))
-function riscv_f16ToUi16 (rm, v) = {
- let (_, sig32) = riscv_f16ToUi32(rm, v);
- if unsigned(sig32) > unsigned(ones(16)) then (nvFlag(), ones(16))
- else (zeros(5), sig32[15 .. 0]);
-}
-
-val riscv_f16ToUi8 : (bits_rm, bits_H) -> (bits_fflags, bits(8))
-function riscv_f16ToUi8 (rm, v) = {
- let (_, sig32) = riscv_f16ToUi32(rm, v);
- if unsigned(sig32) > unsigned(ones(8)) then (nvFlag(), ones(8))
- else (zeros(5), sig32[7 .. 0]);
-}
-
-val riscv_f32ToUi16 : (bits_rm, bits_S) -> (bits_fflags, bits(16))
-function riscv_f32ToUi16 (rm, v) = {
- let (_, sig32) = riscv_f32ToUi32(rm, v);
- if unsigned(sig32) > unsigned(ones(16)) then (nvFlag(), ones(16))
- else (zeros(5), sig32[15 .. 0]);
-}
-
val count_leadingzeros : (bits(64), int) -> int
function count_leadingzeros (sig, len) = {
idx : int = -1;
@@ -896,207 +448,3 @@ function count_leadingzeros (sig, len) = {
};
len - idx - 1
}
-
-val rsqrt7 : forall 'm, 'm in {16, 32, 64}. (bits('m), bool) -> bits_D
-function rsqrt7 (v, sub) = {
- let (sig, exp, sign, e, s) : (bits(64), bits(64), bits(1), nat, nat) = match 'm {
- 16 => (zero_extend(64, v[9 .. 0]), zero_extend(64, v[14 .. 10]), [v[15]], 5, 10),
- 32 => (zero_extend(64, v[22 .. 0]), zero_extend(64, v[30 .. 23]), [v[31]], 8, 23),
- 64 => (zero_extend(64, v[51 .. 0]), zero_extend(64, v[62 .. 52]), [v[63]], 11, 52)
- };
- assert(s == 10 & e == 5 | s == 23 & e == 8 | s == 52 & e == 11);
- let table : vector(128, dec, int) = [
- 52, 51, 50, 48, 47, 46, 44, 43,
- 42, 41, 40, 39, 38, 36, 35, 34,
- 33, 32, 31, 30, 30, 29, 28, 27,
- 26, 25, 24, 23, 23, 22, 21, 20,
- 19, 19, 18, 17, 16, 16, 15, 14,
- 14, 13, 12, 12, 11, 10, 10, 9,
- 9, 8, 7, 7, 6, 6, 5, 4,
- 4, 3, 3, 2, 2, 1, 1, 0,
- 127, 125, 123, 121, 119, 118, 116, 114,
- 113, 111, 109, 108, 106, 105, 103, 102,
- 100, 99, 97, 96, 95, 93, 92, 91,
- 90, 88, 87, 86, 85, 84, 83, 82,
- 80, 79, 78, 77, 76, 75, 74, 73,
- 72, 71, 70, 70, 69, 68, 67, 66,
- 65, 64, 63, 63, 62, 61, 60, 59,
- 59, 58, 57, 56, 56, 55, 54, 53];
-
- let (normalized_exp, normalized_sig) =
- if sub then {
- let nr_leadingzeros = count_leadingzeros(sig, s);
- assert(nr_leadingzeros >= 0);
- (to_bits(64, (0 - nr_leadingzeros)), zero_extend(64, sig[(s - 1) .. 0] << (1 + nr_leadingzeros)))
- } else {
- (exp, sig)
- };
-
- let idx : nat = match 'm {
- 16 => unsigned([normalized_exp[0]] @ normalized_sig[9 .. 4]),
- 32 => unsigned([normalized_exp[0]] @ normalized_sig[22 .. 17]),
- 64 => unsigned([normalized_exp[0]] @ normalized_sig[51 .. 46])
- };
- assert(idx >= 0 & idx < 128);
- let out_sig = to_bits(s, table[(127 - idx)]) << (s - 7);
- let out_exp = to_bits(e, (3 * (2^(e - 1) - 1) - 1 - signed(normalized_exp)) / 2);
- zero_extend(64, sign @ out_exp @ out_sig)
-}
-
-val riscv_f16Rsqrte7 : (bits_rm, bits_H) -> (bits_fflags, bits_H)
-function riscv_f16Rsqrte7 (rm, v) = {
- match fp_class(v) {
- 0x0001 => (nvFlag(), 0x7e00),
- 0x0002 => (nvFlag(), 0x7e00),
- 0x0004 => (nvFlag(), 0x7e00),
- 0x0100 => (nvFlag(), 0x7e00),
- 0x0200 => (zeros(5), 0x7e00),
- 0x0008 => (dzFlag(), 0xfc00),
- 0x0010 => (dzFlag(), 0x7c00),
- 0x0080 => (zeros(5), 0x0000),
- 0x0020 => (zeros(5), rsqrt7(v, true)[15 .. 0]),
- _ => (zeros(5), rsqrt7(v, false)[15 .. 0])
- }
-}
-
-val riscv_f32Rsqrte7 : (bits_rm, bits_S) -> (bits_fflags, bits_S)
-function riscv_f32Rsqrte7 (rm, v) = {
- match fp_class(v)[15 .. 0] {
- 0x0001 => (nvFlag(), 0x7fc00000),
- 0x0002 => (nvFlag(), 0x7fc00000),
- 0x0004 => (nvFlag(), 0x7fc00000),
- 0x0100 => (nvFlag(), 0x7fc00000),
- 0x0200 => (zeros(5), 0x7fc00000),
- 0x0008 => (dzFlag(), 0xff800000),
- 0x0010 => (dzFlag(), 0x7f800000),
- 0x0080 => (zeros(5), 0x00000000),
- 0x0020 => (zeros(5), rsqrt7(v, true)[31 .. 0]),
- _ => (zeros(5), rsqrt7(v, false)[31 .. 0])
- }
-}
-
-val riscv_f64Rsqrte7 : (bits_rm, bits_D) -> (bits_fflags, bits_D)
-function riscv_f64Rsqrte7 (rm, v) = {
- match fp_class(v)[15 .. 0] {
- 0x0001 => (nvFlag(), 0x7ff8000000000000),
- 0x0002 => (nvFlag(), 0x7ff8000000000000),
- 0x0004 => (nvFlag(), 0x7ff8000000000000),
- 0x0100 => (nvFlag(), 0x7ff8000000000000),
- 0x0200 => (zeros(5), 0x7ff8000000000000),
- 0x0008 => (dzFlag(), 0xfff0000000000000),
- 0x0010 => (dzFlag(), 0x7ff0000000000000),
- 0x0080 => (zeros(5), zeros(64)),
- 0x0020 => (zeros(5), rsqrt7(v, true)[63 .. 0]),
- _ => (zeros(5), rsqrt7(v, false)[63 .. 0])
- }
-}
-
-val recip7 : forall 'm, 'm in {16, 32, 64}. (bits('m), bits(3), bool) -> (bool, bits_D)
-function recip7 (v, rm_3b, sub) = {
- let (sig, exp, sign, e, s) : (bits(64), bits(64), bits(1), nat, nat) = match 'm {
- 16 => (zero_extend(64, v[9 .. 0]), zero_extend(64, v[14 .. 10]), [v[15]], 5, 10),
- 32 => (zero_extend(64, v[22 .. 0]), zero_extend(64, v[30 .. 23]), [v[31]], 8, 23),
- 64 => (zero_extend(64, v[51 .. 0]), zero_extend(64, v[62 .. 52]), [v[63]], 11, 52)
- };
- assert(s == 10 & e == 5 | s == 23 & e == 8 | s == 52 & e == 11);
- let table : vector(128, dec, int) = [
- 127, 125, 123, 121, 119, 117, 116, 114,
- 112, 110, 109, 107, 105, 104, 102, 100,
- 99, 97, 96, 94, 93, 91, 90, 88,
- 87, 85, 84, 83, 81, 80, 79, 77,
- 76, 75, 74, 72, 71, 70, 69, 68,
- 66, 65, 64, 63, 62, 61, 60, 59,
- 58, 57, 56, 55, 54, 53, 52, 51,
- 50, 49, 48, 47, 46, 45, 44, 43,
- 42, 41, 40, 40, 39, 38, 37, 36,
- 35, 35, 34, 33, 32, 31, 31, 30,
- 29, 28, 28, 27, 26, 25, 25, 24,
- 23, 23, 22, 21, 21, 20, 19, 19,
- 18, 17, 17, 16, 15, 15, 14, 14,
- 13, 12, 12, 11, 11, 10, 9, 9,
- 8, 8, 7, 7, 6, 5, 5, 4,
- 4, 3, 3, 2, 2, 1, 1, 0];
-
- let nr_leadingzeros = count_leadingzeros(sig, s);
- assert(nr_leadingzeros >= 0);
- let (normalized_exp, normalized_sig) =
- if sub then {
- (to_bits(64, (0 - nr_leadingzeros)), zero_extend(64, sig[(s - 1) .. 0] << (1 + nr_leadingzeros)))
- } else {
- (exp, sig)
- };
-
- let idx : nat = match 'm {
- 16 => unsigned(normalized_sig[9 .. 3]),
- 32 => unsigned(normalized_sig[22 .. 16]),
- 64 => unsigned(normalized_sig[51 .. 45])
- };
- assert(idx >= 0 & idx < 128);
- let mid_exp = to_bits(e, 2 * (2^(e - 1) - 1) - 1 - signed(normalized_exp));
- let mid_sig = to_bits(s, table[(127 - idx)]) << (s - 7);
-
- let (out_exp, out_sig)=
- if mid_exp == zeros(e) then {
- (mid_exp, mid_sig >> 1 | 0b1 @ zeros(s - 1))
- } else if mid_exp == ones(e) then {
- (zeros(e), mid_sig >> 2 | 0b01 @ zeros(s - 2))
- } else (mid_exp, mid_sig);
-
- if sub & nr_leadingzeros > 1 then {
- if (rm_3b == 0b001 | rm_3b == 0b010 & sign == 0b0 | rm_3b == 0b011 & sign == 0b1) then {
- (true, zero_extend(64, sign @ ones(e - 1) @ 0b0 @ ones(s)))
- }
- else (true, zero_extend(64, sign @ ones(e) @ zeros(s)))
- } else (false, zero_extend(64, sign @ out_exp @ out_sig))
-}
-
-val riscv_f16Recip7 : (bits_rm, bits_H) -> (bits_fflags, bits_H)
-function riscv_f16Recip7 (rm, v) = {
- let (round_abnormal_true, res_true) = recip7(v, rm, true);
- let (round_abnormal_false, res_false) = recip7(v, rm, false);
- match fp_class(v) {
- 0x0001 => (zeros(5), 0x8000),
- 0x0080 => (zeros(5), 0x0000),
- 0x0008 => (dzFlag(), 0xfc00),
- 0x0010 => (dzFlag(), 0x7c00),
- 0x0100 => (nvFlag(), 0x7e00),
- 0x0200 => (zeros(5), 0x7e00),
- 0x0004 => if round_abnormal_true then (nxFlag() | ofFlag(), res_true[15 .. 0]) else (zeros(5), res_true[15 .. 0]),
- 0x0020 => if round_abnormal_true then (nxFlag() | ofFlag(), res_true[15 .. 0]) else (zeros(5), res_true[15 .. 0]),
- _ => if round_abnormal_false then (nxFlag() | ofFlag(), res_false[15 .. 0]) else (zeros(5), res_false[15 .. 0])
- }
-}
-
-val riscv_f32Recip7 : (bits_rm, bits_S) -> (bits_fflags, bits_S)
-function riscv_f32Recip7 (rm, v) = {
- let (round_abnormal_true, res_true) = recip7(v, rm, true);
- let (round_abnormal_false, res_false) = recip7(v, rm, false);
- match fp_class(v)[15 .. 0] {
- 0x0001 => (zeros(5), 0x80000000),
- 0x0080 => (zeros(5), 0x00000000),
- 0x0008 => (dzFlag(), 0xff800000),
- 0x0010 => (dzFlag(), 0x7f800000),
- 0x0100 => (nvFlag(), 0x7fc00000),
- 0x0200 => (zeros(5), 0x7fc00000),
- 0x0004 => if round_abnormal_true then (nxFlag() | ofFlag(), res_true[31 .. 0]) else (zeros(5), res_true[31 .. 0]),
- 0x0020 => if round_abnormal_true then (nxFlag() | ofFlag(), res_true[31 .. 0]) else (zeros(5), res_true[31 .. 0]),
- _ => if round_abnormal_false then (nxFlag() | ofFlag(), res_false[31 .. 0]) else (zeros(5), res_false[31 .. 0])
- }
-}
-
-val riscv_f64Recip7 : (bits_rm, bits_D) -> (bits_fflags, bits_D)
-function riscv_f64Recip7 (rm, v) = {
- let (round_abnormal_true, res_true) = recip7(v, rm, true);
- let (round_abnormal_false, res_false) = recip7(v, rm, false);
- match fp_class(v)[15 .. 0] {
- 0x0001 => (zeros(5), 0x8000000000000000),
- 0x0080 => (zeros(5), 0x0000000000000000),
- 0x0008 => (dzFlag(), 0xfff0000000000000),
- 0x0010 => (dzFlag(), 0x7ff0000000000000),
- 0x0100 => (nvFlag(), 0x7ff8000000000000),
- 0x0200 => (zeros(5), 0x7ff8000000000000),
- 0x0004 => if round_abnormal_true then (nxFlag() | ofFlag(), res_true[63 .. 0]) else (zeros(5), res_true[63 .. 0]),
- 0x0020 => if round_abnormal_true then (nxFlag() | ofFlag(), res_true[63 .. 0]) else (zeros(5), res_true[63 .. 0]),
- _ => if round_abnormal_false then (nxFlag() | ofFlag(), res_false[63 .. 0]) else (zeros(5), res_false[63 .. 0])
- }
-}