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