1 /*
2  * Copyright (c) 2015 - 2019, Linaro Limited
3  *
4  * SPDX-License-Identifier: BSD-2-Clause-Patent
5  */
6 
7 #include "platform.h"
8 #include <softfloat.h>
9 
10 /*
11  * On ARM32 EABI defines both a soft-float ABI and a hard-float ABI,
12  * hard-float is basically a super set of soft-float. Hard-float requires
13  * all the support routines provided for soft-float, but the compiler may
14  * choose to optimize to not use some of them.
15  *
16  * The AEABI functions uses soft-float calling convention even if the
17  * functions are compiled for hard-float. So where float and double would
18  * have been expected we use aeabi_float_t and aeabi_double_t respectively
19  * instead.
20  */
21 typedef uint32_t aeabi_float_t;
22 typedef uint64_t aeabi_double_t;
23 
24 /*
25  * Helpers to convert between float32 and aeabi_float_t, and float64 and
26  * aeabi_double_t used by the AEABI functions below.
27  */
f32_to_f(float32_t val)28 static aeabi_float_t f32_to_f(float32_t val)
29 {
30 	return val.v;
31 }
32 
f32_from_f(aeabi_float_t val)33 static float32_t f32_from_f(aeabi_float_t val)
34 {
35 	float32_t res;
36 
37 	res.v = val;
38 
39 	return res;
40 }
41 
f64_to_d(float64_t val)42 static aeabi_double_t f64_to_d(float64_t val)
43 {
44 	return val.v;
45 }
46 
f64_from_d(aeabi_double_t val)47 static float64_t f64_from_d(aeabi_double_t val)
48 {
49 	float64_t res;
50 
51 	res.v = val;
52 
53 	return res;
54 }
55 
56 /*
57  * From ARM Run-time ABI for ARM Architecture
58  * ARM IHI 0043D, current through ABI release 2.09
59  *
60  * 4.1.2 The floating-point helper functions
61  */
62 
63 /*
64  * Table 2, Standard aeabi_double_t precision floating-point arithmetic helper
65  * functions
66  */
67 
__aeabi_dadd(aeabi_double_t a,aeabi_double_t b)68 aeabi_double_t __aeabi_dadd(aeabi_double_t a, aeabi_double_t b)
69 {
70 	return f64_to_d(f64_add(f64_from_d(a), f64_from_d(b)));
71 }
72 
__aeabi_ddiv(aeabi_double_t a,aeabi_double_t b)73 aeabi_double_t __aeabi_ddiv(aeabi_double_t a, aeabi_double_t b)
74 {
75 	return f64_to_d(f64_div(f64_from_d(a), f64_from_d(b)));
76 }
77 
__aeabi_dmul(aeabi_double_t a,aeabi_double_t b)78 aeabi_double_t __aeabi_dmul(aeabi_double_t a, aeabi_double_t b)
79 {
80 	return f64_to_d(f64_mul(f64_from_d(a), f64_from_d(b)));
81 }
82 
83 
__aeabi_drsub(aeabi_double_t a,aeabi_double_t b)84 aeabi_double_t __aeabi_drsub(aeabi_double_t a, aeabi_double_t b)
85 {
86 	return f64_to_d(f64_sub(f64_from_d(b), f64_from_d(a)));
87 }
88 
__aeabi_dsub(aeabi_double_t a,aeabi_double_t b)89 aeabi_double_t __aeabi_dsub(aeabi_double_t a, aeabi_double_t b)
90 {
91 	return f64_to_d(f64_sub(f64_from_d(a), f64_from_d(b)));
92 }
93 
94 /*
95  * Table 3, double precision floating-point comparison helper functions
96  */
97 
__aeabi_dcmpeq(aeabi_double_t a,aeabi_double_t b)98 int __aeabi_dcmpeq(aeabi_double_t a, aeabi_double_t b)
99 {
100 	return f64_eq(f64_from_d(a), f64_from_d(b));
101 }
102 
__aeabi_dcmplt(aeabi_double_t a,aeabi_double_t b)103 int __aeabi_dcmplt(aeabi_double_t a, aeabi_double_t b)
104 {
105 	return f64_lt(f64_from_d(a), f64_from_d(b));
106 }
107 
__aeabi_dcmple(aeabi_double_t a,aeabi_double_t b)108 int __aeabi_dcmple(aeabi_double_t a, aeabi_double_t b)
109 {
110 	return f64_le(f64_from_d(a), f64_from_d(b));
111 }
112 
__aeabi_dcmpge(aeabi_double_t a,aeabi_double_t b)113 int __aeabi_dcmpge(aeabi_double_t a, aeabi_double_t b)
114 {
115 	return f64_le(f64_from_d(b), f64_from_d(a));
116 }
117 
__aeabi_dcmpgt(aeabi_double_t a,aeabi_double_t b)118 int __aeabi_dcmpgt(aeabi_double_t a, aeabi_double_t b)
119 {
120 	return f64_lt(f64_from_d(b), f64_from_d(a));
121 }
122 
123 /*
124  * Table 4, Standard single precision floating-point arithmetic helper
125  * functions
126  */
127 
__aeabi_fadd(aeabi_float_t a,aeabi_float_t b)128 aeabi_float_t __aeabi_fadd(aeabi_float_t a, aeabi_float_t b)
129 {
130 	return f32_to_f(f32_add(f32_from_f(a), f32_from_f(b)));
131 }
132 
__aeabi_fdiv(aeabi_float_t a,aeabi_float_t b)133 aeabi_float_t __aeabi_fdiv(aeabi_float_t a, aeabi_float_t b)
134 {
135 	return f32_to_f(f32_div(f32_from_f(a), f32_from_f(b)));
136 }
137 
__aeabi_fmul(aeabi_float_t a,aeabi_float_t b)138 aeabi_float_t __aeabi_fmul(aeabi_float_t a, aeabi_float_t b)
139 {
140 	return f32_to_f(f32_mul(f32_from_f(a), f32_from_f(b)));
141 }
142 
__aeabi_frsub(aeabi_float_t a,aeabi_float_t b)143 aeabi_float_t __aeabi_frsub(aeabi_float_t a, aeabi_float_t b)
144 {
145 	return f32_to_f(f32_sub(f32_from_f(b), f32_from_f(a)));
146 }
147 
__aeabi_fsub(aeabi_float_t a,aeabi_float_t b)148 aeabi_float_t __aeabi_fsub(aeabi_float_t a, aeabi_float_t b)
149 {
150 	return f32_to_f(f32_sub(f32_from_f(a), f32_from_f(b)));
151 }
152 
153 /*
154  * Table 5, Standard single precision floating-point comparison helper
155  * functions
156  */
157 
__aeabi_fcmpeq(aeabi_float_t a,aeabi_float_t b)158 int __aeabi_fcmpeq(aeabi_float_t a, aeabi_float_t b)
159 {
160 	return f32_eq(f32_from_f(a), f32_from_f(b));
161 }
162 
__aeabi_fcmplt(aeabi_float_t a,aeabi_float_t b)163 int __aeabi_fcmplt(aeabi_float_t a, aeabi_float_t b)
164 {
165 	return f32_lt(f32_from_f(a), f32_from_f(b));
166 }
167 
__aeabi_fcmple(aeabi_float_t a,aeabi_float_t b)168 int __aeabi_fcmple(aeabi_float_t a, aeabi_float_t b)
169 {
170 	return f32_le(f32_from_f(a), f32_from_f(b));
171 }
172 
__aeabi_fcmpge(aeabi_float_t a,aeabi_float_t b)173 int __aeabi_fcmpge(aeabi_float_t a, aeabi_float_t b)
174 {
175 	return f32_le(f32_from_f(b), f32_from_f(a));
176 }
177 
__aeabi_fcmpgt(aeabi_float_t a,aeabi_float_t b)178 int __aeabi_fcmpgt(aeabi_float_t a, aeabi_float_t b)
179 {
180 	return f32_lt(f32_from_f(b), f32_from_f(a));
181 }
182 
183 /*
184  * Table 6, Standard floating-point to integer conversions
185  */
186 
__aeabi_d2iz(aeabi_double_t a)187 int __aeabi_d2iz(aeabi_double_t a)
188 {
189 	return f64_to_i32_r_minMag(f64_from_d(a), false);
190 }
191 
__aeabi_d2uiz(aeabi_double_t a)192 unsigned __aeabi_d2uiz(aeabi_double_t a)
193 {
194 	return f64_to_ui32_r_minMag(f64_from_d(a), false);
195 }
196 
__aeabi_d2lz(aeabi_double_t a)197 long long __aeabi_d2lz(aeabi_double_t a)
198 {
199 	return f64_to_i64_r_minMag(f64_from_d(a), false);
200 }
201 
__aeabi_d2ulz(aeabi_double_t a)202 unsigned long long __aeabi_d2ulz(aeabi_double_t a)
203 {
204 	return f64_to_ui64_r_minMag(f64_from_d(a), false);
205 }
206 
__aeabi_f2iz(aeabi_float_t a)207 int __aeabi_f2iz(aeabi_float_t a)
208 {
209 	return f32_to_i32_r_minMag(f32_from_f(a), false);
210 }
211 
__aeabi_f2uiz(aeabi_float_t a)212 unsigned __aeabi_f2uiz(aeabi_float_t a)
213 {
214 	return f32_to_ui32_r_minMag(f32_from_f(a), false);
215 }
216 
__aeabi_f2lz(aeabi_float_t a)217 long long __aeabi_f2lz(aeabi_float_t a)
218 {
219 	return f32_to_i64_r_minMag(f32_from_f(a), false);
220 }
221 
__aeabi_f2ulz(aeabi_float_t a)222 unsigned long long __aeabi_f2ulz(aeabi_float_t a)
223 {
224 	return f32_to_ui64_r_minMag(f32_from_f(a), false);
225 }
226 
227 /*
228  * Table 7, Standard conversions between floating types
229  */
230 
__aeabi_d2f(aeabi_double_t a)231 aeabi_float_t __aeabi_d2f(aeabi_double_t a)
232 {
233 	return f32_to_f(f64_to_f32(f64_from_d(a)));
234 }
235 
__aeabi_f2d(aeabi_float_t a)236 aeabi_double_t __aeabi_f2d(aeabi_float_t a)
237 {
238 	return f64_to_d(f32_to_f64(f32_from_f(a)));
239 }
240 
241 /*
242  * Table 8, Standard integer to floating-point conversions
243  */
244 
__aeabi_i2d(int a)245 aeabi_double_t __aeabi_i2d(int a)
246 {
247 	return f64_to_d(i32_to_f64(a));
248 }
249 
__aeabi_ui2d(unsigned a)250 aeabi_double_t __aeabi_ui2d(unsigned a)
251 {
252 	return f64_to_d(ui32_to_f64(a));
253 }
254 
__aeabi_l2d(long long a)255 aeabi_double_t __aeabi_l2d(long long a)
256 {
257 	return f64_to_d(i64_to_f64(a));
258 }
259 
__aeabi_ul2d(unsigned long long a)260 aeabi_double_t __aeabi_ul2d(unsigned long long a)
261 {
262 	return f64_to_d(ui64_to_f64(a));
263 }
264 
__aeabi_i2f(int a)265 aeabi_float_t __aeabi_i2f(int a)
266 {
267 	return f32_to_f(i32_to_f32(a));
268 }
269 
__aeabi_ui2f(unsigned a)270 aeabi_float_t __aeabi_ui2f(unsigned a)
271 {
272 	return f32_to_f(ui32_to_f32(a));
273 }
274 
__aeabi_l2f(long long a)275 aeabi_float_t __aeabi_l2f(long long a)
276 {
277 	return f32_to_f(i64_to_f32(a));
278 }
279 
__aeabi_ul2f(unsigned long long a)280 aeabi_float_t __aeabi_ul2f(unsigned long long a)
281 {
282 	return f32_to_f(ui64_to_f32(a));
283 }
284