xref: /optee_os/lib/libutils/isoc/arch/arm/arm32_aeabi_softfloat.c (revision 1bb929836182ecb96d2d9d268daa807c67596396)
1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3  * Copyright (c) 2015, Linaro Limited
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions are met:
8  *
9  * 1. Redistributions of source code must retain the above copyright notice,
10  * this list of conditions and the following disclaimer.
11  *
12  * 2. Redistributions in binary form must reproduce the above copyright notice,
13  * this list of conditions and the following disclaimer in the documentation
14  * and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26  * POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 #include <compiler.h>
30 #include "platform.h"
31 #include <softfloat.h>
32 
33 /*
34  * On ARM32 EABI defines both a soft-float ABI and a hard-float ABI,
35  * hard-float is basically a super set of soft-float. Hard-float requires
36  * all the support routines provided for soft-float, but the compiler may
37  * choose to optimize to not use some of them.
38  *
39  * The AEABI functions uses soft-float calling convention even if the
40  * functions are compiled for hard-float. So where float and double would
41  * have been expected we use aeabi_float_t and aeabi_double_t respectively
42  * instead.
43  */
44 typedef unsigned aeabi_float_t;
45 typedef unsigned long long aeabi_double_t;
46 
47 /*
48  * Helpers to convert between float32 and aeabi_float_t, and float64 and
49  * aeabi_double_t used by the AEABI functions below.
50  */
51 static aeabi_float_t f32_to_f(float32_t val)
52 {
53 	union {
54 		float32_t from;
55 		aeabi_float_t to;
56 	} res = { .from = val };
57 
58 	return res.to;
59 }
60 
61 static float32_t f32_from_f(aeabi_float_t val)
62 {
63 	union {
64 		aeabi_float_t from;
65 		float32_t to;
66 	} res = { .from = val };
67 
68 	return res.to;
69 }
70 
71 static aeabi_double_t f64_to_d(float64_t val)
72 {
73 	union {
74 		float64_t from;
75 		aeabi_double_t to;
76 	} res = { .from = val };
77 
78 	return res.to;
79 }
80 
81 static float64_t f64_from_d(aeabi_double_t val)
82 {
83 	union {
84 		aeabi_double_t from;
85 		float64_t to;
86 	} res = { .from = val };
87 
88 	return res.to;
89 }
90 
91 /*
92  * From ARM Run-time ABI for ARM Architecture
93  * ARM IHI 0043D, current through ABI release 2.09
94  *
95  * 4.1.2 The floating-point helper functions
96  */
97 
98 /*
99  * Table 2, Standard aeabi_double_t precision floating-point arithmetic helper
100  * functions
101  */
102 
103 aeabi_double_t __aeabi_dadd(aeabi_double_t a, aeabi_double_t b)
104 {
105 	return f64_to_d(f64_add(f64_from_d(a), f64_from_d(b)));
106 }
107 
108 aeabi_double_t __aeabi_ddiv(aeabi_double_t a, aeabi_double_t b)
109 {
110 	return f64_to_d(f64_div(f64_from_d(a), f64_from_d(b)));
111 }
112 
113 aeabi_double_t __aeabi_dmul(aeabi_double_t a, aeabi_double_t b)
114 {
115 	return f64_to_d(f64_mul(f64_from_d(a), f64_from_d(b)));
116 }
117 
118 
119 aeabi_double_t __aeabi_drsub(aeabi_double_t a, aeabi_double_t b)
120 {
121 	return f64_to_d(f64_sub(f64_from_d(b), f64_from_d(a)));
122 }
123 
124 aeabi_double_t __aeabi_dsub(aeabi_double_t a, aeabi_double_t b)
125 {
126 	return f64_to_d(f64_sub(f64_from_d(a), f64_from_d(b)));
127 }
128 
129 /*
130  * Table 3, double precision floating-point comparison helper functions
131  */
132 
133 int __aeabi_dcmpeq(aeabi_double_t a, aeabi_double_t b)
134 {
135 	return f64_eq(f64_from_d(a), f64_from_d(b));
136 }
137 
138 int __aeabi_dcmplt(aeabi_double_t a, aeabi_double_t b)
139 {
140 	return f64_lt(f64_from_d(a), f64_from_d(b));
141 }
142 
143 int __aeabi_dcmple(aeabi_double_t a, aeabi_double_t b)
144 {
145 	return f64_le(f64_from_d(a), f64_from_d(b));
146 }
147 
148 int __aeabi_dcmpge(aeabi_double_t a, aeabi_double_t b)
149 {
150 	return f64_le(f64_from_d(b), f64_from_d(a));
151 }
152 
153 int __aeabi_dcmpgt(aeabi_double_t a, aeabi_double_t b)
154 {
155 	return f64_lt(f64_from_d(b), f64_from_d(a));
156 }
157 
158 /*
159  * Table 4, Standard single precision floating-point arithmetic helper
160  * functions
161  */
162 
163 aeabi_float_t __aeabi_fadd(aeabi_float_t a, aeabi_float_t b)
164 {
165 	return f32_to_f(f32_add(f32_from_f(a), f32_from_f(b)));
166 }
167 
168 aeabi_float_t __aeabi_fdiv(aeabi_float_t a, aeabi_float_t b)
169 {
170 	return f32_to_f(f32_div(f32_from_f(a), f32_from_f(b)));
171 }
172 
173 aeabi_float_t __aeabi_fmul(aeabi_float_t a, aeabi_float_t b)
174 {
175 	return f32_to_f(f32_mul(f32_from_f(a), f32_from_f(b)));
176 }
177 
178 aeabi_float_t __aeabi_frsub(aeabi_float_t a, aeabi_float_t b)
179 {
180 	return f32_to_f(f32_sub(f32_from_f(b), f32_from_f(a)));
181 }
182 
183 aeabi_float_t __aeabi_fsub(aeabi_float_t a, aeabi_float_t b)
184 {
185 	return f32_to_f(f32_sub(f32_from_f(a), f32_from_f(b)));
186 }
187 
188 /*
189  * Table 5, Standard single precision floating-point comparison helper
190  * functions
191  */
192 
193 int __aeabi_fcmpeq(aeabi_float_t a, aeabi_float_t b)
194 {
195 	return f32_eq(f32_from_f(a), f32_from_f(b));
196 }
197 
198 int __aeabi_fcmplt(aeabi_float_t a, aeabi_float_t b)
199 {
200 	return f32_lt(f32_from_f(a), f32_from_f(b));
201 }
202 
203 int __aeabi_fcmple(aeabi_float_t a, aeabi_float_t b)
204 {
205 	return f32_le(f32_from_f(a), f32_from_f(b));
206 }
207 
208 int __aeabi_fcmpge(aeabi_float_t a, aeabi_float_t b)
209 {
210 	return f32_le(f32_from_f(b), f32_from_f(a));
211 }
212 
213 int __aeabi_fcmpgt(aeabi_float_t a, aeabi_float_t b)
214 {
215 	return f32_lt(f32_from_f(b), f32_from_f(a));
216 }
217 
218 /*
219  * Table 6, Standard floating-point to integer conversions
220  */
221 
222 int __aeabi_d2iz(aeabi_double_t a)
223 {
224 	return f64_to_i32_r_minMag(f64_from_d(a), false);
225 }
226 
227 unsigned __aeabi_d2uiz(aeabi_double_t a)
228 {
229 	return f64_to_ui32_r_minMag(f64_from_d(a), false);
230 }
231 
232 long long __aeabi_d2lz(aeabi_double_t a)
233 {
234 	return f64_to_i64_r_minMag(f64_from_d(a), false);
235 }
236 
237 unsigned long long __aeabi_d2ulz(aeabi_double_t a)
238 {
239 	return f64_to_ui64_r_minMag(f64_from_d(a), false);
240 }
241 
242 int __aeabi_f2iz(aeabi_float_t a)
243 {
244 	return f32_to_i32_r_minMag(f32_from_f(a), false);
245 }
246 
247 unsigned __aeabi_f2uiz(aeabi_float_t a)
248 {
249 	return f32_to_ui32_r_minMag(f32_from_f(a), false);
250 }
251 
252 long long __aeabi_f2lz(aeabi_float_t a)
253 {
254 	return f32_to_i64_r_minMag(f32_from_f(a), false);
255 }
256 
257 unsigned long long __aeabi_f2ulz(aeabi_float_t a)
258 {
259 	return f32_to_ui64_r_minMag(f32_from_f(a), false);
260 }
261 
262 /*
263  * Table 7, Standard conversions between floating types
264  */
265 
266 aeabi_float_t __aeabi_d2f(aeabi_double_t a)
267 {
268 	return f32_to_f(f64_to_f32(f64_from_d(a)));
269 }
270 
271 aeabi_double_t __aeabi_f2d(aeabi_float_t a)
272 {
273 	return f64_to_d(f32_to_f64(f32_from_f(a)));
274 }
275 
276 /*
277  * Table 8, Standard integer to floating-point conversions
278  */
279 
280 aeabi_double_t __aeabi_i2d(int a)
281 {
282 	return f64_to_d(i32_to_f64(a));
283 }
284 
285 aeabi_double_t __aeabi_ui2d(unsigned a)
286 {
287 	return f64_to_d(ui32_to_f64(a));
288 }
289 
290 aeabi_double_t __aeabi_l2d(long long a)
291 {
292 	return f64_to_d(i64_to_f64(a));
293 }
294 
295 aeabi_double_t __aeabi_ul2d(unsigned long long a)
296 {
297 	return f64_to_d(ui64_to_f64(a));
298 }
299 
300 aeabi_float_t __aeabi_i2f(int a)
301 {
302 	return f32_to_f(i32_to_f32(a));
303 }
304 
305 aeabi_float_t __aeabi_ui2f(unsigned a)
306 {
307 	return f32_to_f(ui32_to_f32(a));
308 }
309 
310 aeabi_float_t __aeabi_l2f(long long a)
311 {
312 	return f32_to_f(i64_to_f32(a));
313 }
314 
315 aeabi_float_t __aeabi_ul2f(unsigned long long a)
316 {
317 	return f32_to_f(ui64_to_f32(a));
318 }
319