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