xref: /optee_os/lib/libutils/isoc/arch/arm/arm32_aeabi_softfloat.c (revision fce4cfa1b70b1da9e730b00810a4cf4be13eb97a)
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 "platform.h"
29 #include <softfloat.h>
30 
31 /*
32  * Helpers to convert between float32 and float, and float64 and double
33  * used by the AEABI functions below.
34  */
35 static float f32_to_f(float32_t val)
36 {
37 	union {
38 		float32_t from;
39 		float to;
40 	} res = { .from = val };
41 
42 	return res.to;
43 }
44 
45 static float32_t f32_from_f(float val)
46 {
47 	union {
48 		float from;
49 		float32_t to;
50 	} res = { .from = val };
51 
52 	return res.to;
53 }
54 
55 static double f64_to_d(float64_t val)
56 {
57 	union {
58 		float64_t from;
59 		double to;
60 	} res = { .from = val };
61 
62 	return res.to;
63 }
64 
65 static float64_t f64_from_d(double val)
66 {
67 	union {
68 		double from;
69 		float64_t to;
70 	} res = { .from = val };
71 
72 	return res.to;
73 }
74 
75 /*
76  * From ARM Run-time ABI for ARM Architecture
77  * ARM IHI 0043D, current through ABI release 2.09
78  *
79  * 4.1.2 The floating-point helper functions
80  */
81 
82 /*
83  * Table 2, Standard double precision floating-point arithmetic helper
84  * functions
85  */
86 
87 double __aeabi_dadd(double a, double b)
88 {
89 	return f64_to_d(f64_add(f64_from_d(a), f64_from_d(b)));
90 }
91 
92 double __aeabi_ddiv(double a, double b)
93 {
94 	return f64_to_d(f64_div(f64_from_d(a), f64_from_d(b)));
95 }
96 
97 double __aeabi_dmul(double a, double b)
98 {
99 	return f64_to_d(f64_mul(f64_from_d(a), f64_from_d(b)));
100 }
101 
102 
103 double __aeabi_drsub(double a, double b)
104 {
105 	return f64_to_d(f64_sub(f64_from_d(b), f64_from_d(a)));
106 }
107 
108 double __aeabi_dsub(double a, double b)
109 {
110 	return f64_to_d(f64_sub(f64_from_d(a), f64_from_d(b)));
111 }
112 
113 /*
114  * Table 3, double precision floating-point comparison helper functions
115  */
116 
117 int __aeabi_dcmpeq(double a, double b)
118 {
119 	return f64_eq(f64_from_d(a), f64_from_d(b));
120 }
121 
122 int __aeabi_dcmplt(double a, double b)
123 {
124 	return f64_lt(f64_from_d(a), f64_from_d(b));
125 }
126 
127 int __aeabi_dcmple(double a, double b)
128 {
129 	return f64_le(f64_from_d(a), f64_from_d(b));
130 }
131 
132 int __aeabi_dcmpge(double a, double b)
133 {
134 	return f64_le(f64_from_d(b), f64_from_d(a));
135 }
136 
137 int __aeabi_dcmpgt(double a, double b)
138 {
139 	return f64_lt(f64_from_d(b), f64_from_d(a));
140 }
141 
142 /*
143  * Table 4, Standard single precision floating-point arithmetic helper
144  * functions
145  */
146 
147 float __aeabi_fadd(float a, float b)
148 {
149 	return f32_to_f(f32_add(f32_from_f(a), f32_from_f(b)));
150 }
151 
152 float __aeabi_fdiv(float a, float b)
153 {
154 	return f32_to_f(f32_div(f32_from_f(a), f32_from_f(b)));
155 }
156 
157 float __aeabi_fmul(float a, float b)
158 {
159 	return f32_to_f(f32_mul(f32_from_f(a), f32_from_f(b)));
160 }
161 
162 float __aeabi_frsub(float a, float b)
163 {
164 	return f32_to_f(f32_sub(f32_from_f(b), f32_from_f(a)));
165 }
166 
167 float __aeabi_fsub(float a, float b)
168 {
169 	return f32_to_f(f32_sub(f32_from_f(a), f32_from_f(b)));
170 }
171 
172 /*
173  * Table 5, Standard single precision floating-point comparison helper
174  * functions
175  */
176 
177 int __aeabi_fcmpeq(float a, float b)
178 {
179 	return f32_eq(f32_from_f(a), f32_from_f(b));
180 }
181 
182 int __aeabi_fcmplt(float a, float b)
183 {
184 	return f32_lt(f32_from_f(a), f32_from_f(b));
185 }
186 
187 int __aeabi_fcmple(float a, float b)
188 {
189 	return f32_le(f32_from_f(a), f32_from_f(b));
190 }
191 
192 int __aeabi_fcmpge(float a, float b)
193 {
194 	return f32_le(f32_from_f(b), f32_from_f(a));
195 }
196 
197 int __aeabi_fcmpgt(float a, float b)
198 {
199 	return f32_lt(f32_from_f(b), f32_from_f(a));
200 }
201 
202 /*
203  * Table 6, Standard floating-point to integer conversions
204  */
205 
206 int __aeabi_d2iz(double a)
207 {
208 	return f64_to_i32_r_minMag(f64_from_d(a), false);
209 }
210 
211 unsigned __aeabi_d2uiz(double a)
212 {
213 	return f64_to_ui32_r_minMag(f64_from_d(a), false);
214 }
215 
216 long long __aeabi_d2lz(double a)
217 {
218 	return f64_to_i64_r_minMag(f64_from_d(a), false);
219 }
220 
221 unsigned long long __aeabi_d2ulz(double a)
222 {
223 	return f64_to_ui64_r_minMag(f64_from_d(a), false);
224 }
225 
226 int __aeabi_f2iz(float a)
227 {
228 	return f32_to_i32_r_minMag(f32_from_f(a), false);
229 }
230 
231 unsigned __aeabi_f2uiz(float a)
232 {
233 	return f32_to_ui32_r_minMag(f32_from_f(a), false);
234 }
235 
236 long long __aeabi_f2lz(float a)
237 {
238 	return f32_to_i64_r_minMag(f32_from_f(a), false);
239 }
240 
241 unsigned long long __aeabi_f2ulz(float a)
242 {
243 	return f32_to_ui64_r_minMag(f32_from_f(a), false);
244 }
245 
246 /*
247  * Table 7, Standard conversions between floating types
248  */
249 
250 float __aeabi_d2f(double a)
251 {
252 	return f32_to_f(f64_to_f32(f64_from_d(a)));
253 }
254 
255 double __aeabi_f2d(float a)
256 {
257 	return f64_to_d(f32_to_f64(f32_from_f(a)));
258 }
259 
260 /*
261  * Table 8, Standard integer to floating-point conversions
262  */
263 
264 double __aeabi_i2d(int a)
265 {
266 	return f64_to_d(i32_to_f64(a));
267 }
268 
269 double __aeabi_ui2d(unsigned a)
270 {
271 	return f64_to_d(ui32_to_f64(a));
272 }
273 
274 double __aeabi_l2d(long long a)
275 {
276 	return f64_to_d(i64_to_f64(a));
277 }
278 
279 double __aeabi_ul2d(unsigned long long a)
280 {
281 	return f64_to_d(ui64_to_f64(a));
282 }
283 
284 float __aeabi_i2f(int a)
285 {
286 	return f32_to_f(i32_to_f32(a));
287 }
288 
289 float __aeabi_ui2f(unsigned a)
290 {
291 	return f32_to_f(ui32_to_f32(a));
292 }
293 
294 float __aeabi_l2f(long long a)
295 {
296 	return f32_to_f(i64_to_f32(a));
297 }
298 
299 float __aeabi_ul2f(unsigned long long a)
300 {
301 	return f32_to_f(ui64_to_f32(a));
302 }
303