1 // SPDX-License-Identifier: MIT
3 * Copyright 2023 Advanced Micro Devices, Inc.
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
19 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
20 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
21 * OTHER DEALINGS IN THE SOFTWARE.
26 #include "dm_services.h"
27 #include "custom_float.h"
29 static bool build_custom_float(struct fixed31_32 value,
30 const struct custom_float_format *format,
35 uint32_t exp_offset = (1 << (format->exponenta_bits - 1)) - 1;
37 const struct fixed31_32 mantissa_constant_plus_max_fraction =
38 dc_fixpt_from_fraction((1LL << (format->mantissa_bits + 1)) - 1,
39 1LL << format->mantissa_bits);
41 struct fixed31_32 mantiss;
43 if (dc_fixpt_eq(value, dc_fixpt_zero)) {
50 if (dc_fixpt_lt(value, dc_fixpt_zero)) {
51 *negative = format->sign;
52 value = dc_fixpt_neg(value);
57 if (dc_fixpt_lt(value, dc_fixpt_one)) {
61 value = dc_fixpt_shl(value, 1);
63 } while (dc_fixpt_lt(value, dc_fixpt_one));
67 if (exp_offset <= i) {
73 *exponenta = exp_offset - i;
74 } else if (dc_fixpt_le(mantissa_constant_plus_max_fraction, value)) {
78 value = dc_fixpt_shr(value, 1);
80 } while (dc_fixpt_lt(mantissa_constant_plus_max_fraction, value));
82 *exponenta = exp_offset + i - 1;
84 *exponenta = exp_offset;
87 mantiss = dc_fixpt_sub(value, dc_fixpt_one);
89 if (dc_fixpt_lt(mantiss, dc_fixpt_zero) ||
90 dc_fixpt_lt(dc_fixpt_one, mantiss))
91 mantiss = dc_fixpt_zero;
93 mantiss = dc_fixpt_shl(mantiss, format->mantissa_bits);
95 *mantissa = dc_fixpt_floor(mantiss);
100 static bool setup_custom_float(const struct custom_float_format *format,
110 /* verification code:
111 * once calculation is ok we can remove it
114 const uint32_t mantissa_mask =
115 (1 << (format->mantissa_bits + 1)) - 1;
117 const uint32_t exponenta_mask =
118 (1 << (format->exponenta_bits + 1)) - 1;
120 if (mantissa & ~mantissa_mask) {
122 mantissa = mantissa_mask;
125 if (exponenta & ~exponenta_mask) {
127 exponenta = exponenta_mask;
130 /* end of verification code */
132 while (i < format->mantissa_bits) {
133 uint32_t mask = 1 << i;
141 while (j < format->exponenta_bits) {
142 uint32_t mask = 1 << j;
144 if (exponenta & mask)
150 if (negative && format->sign)
151 value |= 1 << (i + j);
158 bool convert_to_custom_float_format(struct fixed31_32 value,
159 const struct custom_float_format *format,
166 return build_custom_float(value, format, &negative, &mantissa, &exponenta) &&
167 setup_custom_float(format,