Line data Source code
1 : /*
2 : * Copyright 2017 Advanced Micro Devices, Inc.
3 : *
4 : * Permission is hereby granted, free of charge, to any person obtaining a
5 : * copy of this software and associated documentation files (the "Software"),
6 : * to deal in the Software without restriction, including without limitation
7 : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 : * and/or sell copies of the Software, and to permit persons to whom the
9 : * Software is furnished to do so, subject to the following conditions:
10 : *
11 : * The above copyright notice and this permission notice shall be included in
12 : * all copies or substantial portions of the Software.
13 : *
14 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 : * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 : * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 : * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 : * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 : * OTHER DEALINGS IN THE SOFTWARE.
21 : *
22 : * Authors: AMD
23 : *
24 : */
25 : #include "dm_services.h"
26 : #include "custom_float.h"
27 :
28 :
29 0 : static bool build_custom_float(
30 : struct fixed31_32 value,
31 : const struct custom_float_format *format,
32 : bool *negative,
33 : uint32_t *mantissa,
34 : uint32_t *exponenta)
35 : {
36 0 : uint32_t exp_offset = (1 << (format->exponenta_bits - 1)) - 1;
37 :
38 0 : const struct fixed31_32 mantissa_constant_plus_max_fraction =
39 0 : dc_fixpt_from_fraction(
40 0 : (1LL << (format->mantissa_bits + 1)) - 1,
41 0 : 1LL << format->mantissa_bits);
42 :
43 : struct fixed31_32 mantiss;
44 :
45 0 : if (dc_fixpt_eq(
46 : value,
47 : dc_fixpt_zero)) {
48 0 : *negative = false;
49 0 : *mantissa = 0;
50 0 : *exponenta = 0;
51 0 : return true;
52 : }
53 :
54 0 : if (dc_fixpt_lt(
55 : value,
56 : dc_fixpt_zero)) {
57 0 : *negative = format->sign;
58 : value = dc_fixpt_neg(value);
59 : } else {
60 0 : *negative = false;
61 : }
62 :
63 0 : if (dc_fixpt_lt(
64 : value,
65 : dc_fixpt_one)) {
66 : uint32_t i = 1;
67 :
68 : do {
69 0 : value = dc_fixpt_shl(value, 1);
70 0 : ++i;
71 : } while (dc_fixpt_lt(
72 : value,
73 0 : dc_fixpt_one));
74 :
75 0 : --i;
76 :
77 0 : if (exp_offset <= i) {
78 0 : *mantissa = 0;
79 0 : *exponenta = 0;
80 0 : return true;
81 : }
82 :
83 0 : *exponenta = exp_offset - i;
84 0 : } else if (dc_fixpt_le(
85 : mantissa_constant_plus_max_fraction,
86 : value)) {
87 : uint32_t i = 1;
88 :
89 : do {
90 0 : value = dc_fixpt_shr(value, 1);
91 0 : ++i;
92 : } while (dc_fixpt_lt(
93 : mantissa_constant_plus_max_fraction,
94 0 : value));
95 :
96 0 : *exponenta = exp_offset + i - 1;
97 : } else {
98 0 : *exponenta = exp_offset;
99 : }
100 :
101 0 : mantiss = dc_fixpt_sub(
102 : value,
103 : dc_fixpt_one);
104 :
105 0 : if (dc_fixpt_lt(
106 : mantiss,
107 0 : dc_fixpt_zero) ||
108 : dc_fixpt_lt(
109 : dc_fixpt_one,
110 : mantiss))
111 : mantiss = dc_fixpt_zero;
112 : else
113 0 : mantiss = dc_fixpt_shl(
114 : mantiss,
115 0 : format->mantissa_bits);
116 :
117 0 : *mantissa = dc_fixpt_floor(mantiss);
118 :
119 0 : return true;
120 : }
121 :
122 0 : static bool setup_custom_float(
123 : const struct custom_float_format *format,
124 : bool negative,
125 : uint32_t mantissa,
126 : uint32_t exponenta,
127 : uint32_t *result)
128 : {
129 0 : uint32_t i = 0;
130 0 : uint32_t j = 0;
131 :
132 0 : uint32_t value = 0;
133 :
134 : /* verification code:
135 : * once calculation is ok we can remove it
136 : */
137 :
138 0 : const uint32_t mantissa_mask =
139 0 : (1 << (format->mantissa_bits + 1)) - 1;
140 :
141 0 : const uint32_t exponenta_mask =
142 0 : (1 << (format->exponenta_bits + 1)) - 1;
143 :
144 0 : if (mantissa & ~mantissa_mask) {
145 0 : BREAK_TO_DEBUGGER();
146 0 : mantissa = mantissa_mask;
147 : }
148 :
149 0 : if (exponenta & ~exponenta_mask) {
150 0 : BREAK_TO_DEBUGGER();
151 0 : exponenta = exponenta_mask;
152 : }
153 :
154 : /* end of verification code */
155 :
156 0 : while (i < format->mantissa_bits) {
157 0 : uint32_t mask = 1 << i;
158 :
159 0 : if (mantissa & mask)
160 0 : value |= mask;
161 :
162 0 : ++i;
163 : }
164 :
165 0 : while (j < format->exponenta_bits) {
166 0 : uint32_t mask = 1 << j;
167 :
168 0 : if (exponenta & mask)
169 0 : value |= mask << i;
170 :
171 0 : ++j;
172 : }
173 :
174 0 : if (negative && format->sign)
175 0 : value |= 1 << (i + j);
176 :
177 0 : *result = value;
178 :
179 0 : return true;
180 : }
181 :
182 0 : bool convert_to_custom_float_format(
183 : struct fixed31_32 value,
184 : const struct custom_float_format *format,
185 : uint32_t *result)
186 : {
187 : uint32_t mantissa;
188 : uint32_t exponenta;
189 : bool negative;
190 :
191 0 : return build_custom_float(
192 0 : value, format, &negative, &mantissa, &exponenta) &&
193 0 : setup_custom_float(
194 : format, negative, mantissa, exponenta, result);
195 : }
196 :
197 :
|