1 // SPDX-License-Identifier: MIT 2 // 3 // Copyright 2024 Advanced Micro Devices, Inc. 4 5 #include "spl_debug.h" 6 #include "spl_custom_float.h" 7 8 static 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 else 72 mantiss = spl_fixpt_shl(mantiss, format->mantissa_bits); 73 74 *mantissa = spl_fixpt_floor(mantiss); 75 76 return true; 77 } 78 79 static 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 it 91 */ 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 137 bool 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