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
spl_build_custom_float(struct spl_fixed31_32 value,const struct spl_custom_float_format * format,bool * negative,uint32_t * mantissa,uint32_t * exponenta)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
spl_setup_custom_float(const struct spl_custom_float_format * format,bool negative,uint32_t mantissa,uint32_t exponenta,uint32_t * result)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
spl_convert_to_custom_float_format(struct spl_fixed31_32 value,const struct spl_custom_float_format * format,uint32_t * result)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