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