152 lines · c
1// SPDX-License-Identifier: MIT2//3// Copyright 2024 Advanced Micro Devices, Inc.4 5#include "spl_debug.h"6#include "spl_custom_float.h"7 8static bool spl_build_custom_float(struct spl_fixed31_32 value,9 const struct spl_custom_float_format *format,10 bool *negative,11 uint32_t *mantissa,12 uint32_t *exponenta)13{14 uint32_t exp_offset = (1 << (format->exponenta_bits - 1)) - 1;15 16 const struct spl_fixed31_32 mantissa_constant_plus_max_fraction =17 spl_fixpt_from_fraction((1LL << (format->mantissa_bits + 1)) - 1,18 1LL << format->mantissa_bits);19 20 struct spl_fixed31_32 mantiss;21 22 if (spl_fixpt_eq(value, spl_fixpt_zero)) {23 *negative = false;24 *mantissa = 0;25 *exponenta = 0;26 return true;27 }28 29 if (spl_fixpt_lt(value, spl_fixpt_zero)) {30 *negative = format->sign;31 value = spl_fixpt_neg(value);32 } else {33 *negative = false;34 }35 36 if (spl_fixpt_lt(value, spl_fixpt_one)) {37 uint32_t i = 1;38 39 do {40 value = spl_fixpt_shl(value, 1);41 ++i;42 } while (spl_fixpt_lt(value, spl_fixpt_one));43 44 --i;45 46 if (exp_offset <= i) {47 *mantissa = 0;48 *exponenta = 0;49 return true;50 }51 52 *exponenta = exp_offset - i;53 } else if (spl_fixpt_le(mantissa_constant_plus_max_fraction, value)) {54 uint32_t i = 1;55 56 do {57 value = spl_fixpt_shr(value, 1);58 ++i;59 } while (spl_fixpt_lt(mantissa_constant_plus_max_fraction, value));60 61 *exponenta = exp_offset + i - 1;62 } else {63 *exponenta = exp_offset;64 }65 66 mantiss = spl_fixpt_sub(value, spl_fixpt_one);67 68 if (spl_fixpt_lt(mantiss, spl_fixpt_zero) ||69 spl_fixpt_lt(spl_fixpt_one, mantiss))70 mantiss = spl_fixpt_zero;71 else72 mantiss = spl_fixpt_shl(mantiss, format->mantissa_bits);73 74 *mantissa = spl_fixpt_floor(mantiss);75 76 return true;77}78 79static bool spl_setup_custom_float(const struct spl_custom_float_format *format,80 bool negative,81 uint32_t mantissa,82 uint32_t exponenta,83 uint32_t *result)84{85 uint32_t i = 0;86 uint32_t j = 0;87 uint32_t value = 0;88 89 /* verification code:90 * once calculation is ok we can remove it91 */92 93 const uint32_t mantissa_mask =94 (1 << (format->mantissa_bits + 1)) - 1;95 96 const uint32_t exponenta_mask =97 (1 << (format->exponenta_bits + 1)) - 1;98 99 if (mantissa & ~mantissa_mask) {100 SPL_BREAK_TO_DEBUGGER();101 mantissa = mantissa_mask;102 }103 104 if (exponenta & ~exponenta_mask) {105 SPL_BREAK_TO_DEBUGGER();106 exponenta = exponenta_mask;107 }108 109 /* end of verification code */110 111 while (i < format->mantissa_bits) {112 uint32_t mask = 1 << i;113 114 if (mantissa & mask)115 value |= mask;116 117 ++i;118 }119 120 while (j < format->exponenta_bits) {121 uint32_t mask = 1 << j;122 123 if (exponenta & mask)124 value |= mask << i;125 126 ++j;127 }128 129 if (negative && format->sign)130 value |= 1 << (i + j);131 132 *result = value;133 134 return true;135}136 137bool spl_convert_to_custom_float_format(struct spl_fixed31_32 value,138 const struct spl_custom_float_format *format,139 uint32_t *result)140{141 uint32_t mantissa;142 uint32_t exponenta;143 bool negative;144 145 return spl_build_custom_float(value, format, &negative, &mantissa, &exponenta) &&146 spl_setup_custom_float(format,147 negative,148 mantissa,149 exponenta,150 result);151}152