]>
Commit | Line | Data |
---|---|---|
3cc57695 AB |
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 | */ | |
28 | static aeabi_float_t f32_to_f(float32_t val) | |
29 | { | |
30 | return val.v; | |
31 | } | |
32 | ||
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 | ||
42 | static aeabi_double_t f64_to_d(float64_t val) | |
43 | { | |
44 | return val.v; | |
45 | } | |
46 | ||
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 | ||
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 | ||
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 | ||
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 | ||
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 | ||
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 | ||
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 | ||
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 | ||
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 | ||
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 | ||
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 | ||
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 | ||
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 | ||
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 | ||
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 | ||
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 | ||
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 | ||
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 | ||
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 | ||
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 | ||
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 | ||
187 | int __aeabi_d2iz(aeabi_double_t a) | |
188 | { | |
189 | return f64_to_i32_r_minMag(f64_from_d(a), false); | |
190 | } | |
191 | ||
192 | unsigned __aeabi_d2uiz(aeabi_double_t a) | |
193 | { | |
194 | return f64_to_ui32_r_minMag(f64_from_d(a), false); | |
195 | } | |
196 | ||
197 | long long __aeabi_d2lz(aeabi_double_t a) | |
198 | { | |
199 | return f64_to_i64_r_minMag(f64_from_d(a), false); | |
200 | } | |
201 | ||
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 | ||
207 | int __aeabi_f2iz(aeabi_float_t a) | |
208 | { | |
209 | return f32_to_i32_r_minMag(f32_from_f(a), false); | |
210 | } | |
211 | ||
212 | unsigned __aeabi_f2uiz(aeabi_float_t a) | |
213 | { | |
214 | return f32_to_ui32_r_minMag(f32_from_f(a), false); | |
215 | } | |
216 | ||
217 | long long __aeabi_f2lz(aeabi_float_t a) | |
218 | { | |
219 | return f32_to_i64_r_minMag(f32_from_f(a), false); | |
220 | } | |
221 | ||
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 | ||
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 | ||
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 | ||
245 | aeabi_double_t __aeabi_i2d(int a) | |
246 | { | |
247 | return f64_to_d(i32_to_f64(a)); | |
248 | } | |
249 | ||
250 | aeabi_double_t __aeabi_ui2d(unsigned a) | |
251 | { | |
252 | return f64_to_d(ui32_to_f64(a)); | |
253 | } | |
254 | ||
255 | aeabi_double_t __aeabi_l2d(long long a) | |
256 | { | |
257 | return f64_to_d(i64_to_f64(a)); | |
258 | } | |
259 | ||
260 | aeabi_double_t __aeabi_ul2d(unsigned long long a) | |
261 | { | |
262 | return f64_to_d(ui64_to_f64(a)); | |
263 | } | |
264 | ||
265 | aeabi_float_t __aeabi_i2f(int a) | |
266 | { | |
267 | return f32_to_f(i32_to_f32(a)); | |
268 | } | |
269 | ||
270 | aeabi_float_t __aeabi_ui2f(unsigned a) | |
271 | { | |
272 | return f32_to_f(ui32_to_f32(a)); | |
273 | } | |
274 | ||
275 | aeabi_float_t __aeabi_l2f(long long a) | |
276 | { | |
277 | return f32_to_f(i64_to_f32(a)); | |
278 | } | |
279 | ||
280 | aeabi_float_t __aeabi_ul2f(unsigned long long a) | |
281 | { | |
282 | return f32_to_f(ui64_to_f32(a)); | |
283 | } |