Home | History | Annotate | Line # | Download | only in softfloat
qp.c revision 1.1.24.1
      1 /* $NetBSD: qp.c,v 1.1.24.1 2018/09/06 06:55:19 pgoyette Exp $ */
      2 
      3 /*-
      4  * Copyright (c) 2014 The NetBSD Foundation, Inc.
      5  * All rights reserved.
      6  *
      7  * This code is derived from software contributed to The NetBSD Foundation
      8  * by Matt Thomas of 3am Software Foundry.
      9  *
     10  * Redistribution and use in source and binary forms, with or without
     11  * modification, are permitted provided that the following conditions
     12  * are met:
     13  * 1. Redistributions of source code must retain the above copyright
     14  *    notice, this list of conditions and the following disclaimer.
     15  * 2. Redistributions in binary form must reproduce the above copyright
     16  *    notice, this list of conditions and the following disclaimer in the
     17  *    documentation and/or other materials provided with the distribution.
     18  *
     19  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     20  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     21  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     23  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     29  * POSSIBILITY OF SUCH DAMAGE.
     30  */
     31 #include <sys/cdefs.h>
     32 
     33 #include "milieu.h"
     34 #include "softfloat.h"
     35 
     36 /*
     37  * This file provides wrappers for the softfloat functions.  We can't use
     38  * invoke them directly since long double arguments are passed in FP/SIMD
     39  * as well as being returned in them while float128 arguments are passed
     40  * in normal registers.
     41  */
     42 
     43 long double __addtf3(long double, long double);
     44 long double __divtf3(long double, long double);
     45 long double __modtf3(long double, long double);
     46 long double __multf3(long double, long double);
     47 long double __negtf2(long double);
     48 long double __subtf3(long double, long double);
     49 
     50 double __trunctfdf2(long double);
     51 float __trunctfsf2(long double);
     52 
     53 long double __extendsftf2(float);
     54 long double __extenddftf2(double);
     55 
     56 long double __floatsitf(int32_t);
     57 long double __floatditf(int64_t);
     58 
     59 long double __floatunsitf(uint32_t);
     60 long double __floatunditf(uint64_t);
     61 
     62 int32_t __fixtfsi(long double);
     63 int64_t __fixtfdi(long double);
     64 
     65 uint32_t __fixuntfsi(long double);
     66 uint64_t __fixuntfdi(long double);
     67 
     68 #if 0
     69 long double __floattitf(int128_t);
     70 long double __floatuntitf(uint128_t);
     71 int128_t __fixtfti(long double);
     72 uint128_t __fixuntfti(long double);
     73 #endif
     74 
     75 union sf_ieee_flt_u {
     76 	float fltu_f;
     77 	float32 fltu_f32;
     78 };
     79 
     80 union sf_ieee_dbl_u {
     81 	double dblu_d;
     82 	float64 dblu_f64;
     83 };
     84 
     85 union sf_ieee_ldbl_u {
     86 	long double ldblu_ld;
     87 	float128 ldblu_f128;
     88 };
     89 
     90 long double
     91 __addtf3(long double ld_a, long double ld_b)
     92 {
     93 	const union sf_ieee_ldbl_u a = { .ldblu_ld = ld_a };
     94 	const union sf_ieee_ldbl_u b = { .ldblu_ld = ld_b };
     95 	const union sf_ieee_ldbl_u c = {
     96 	    .ldblu_f128 = float128_add(a.ldblu_f128, b.ldblu_f128)
     97 	};
     98 
     99 	return c.ldblu_ld;
    100 }
    101 
    102 long double
    103 __divtf3(long double ld_a, long double ld_b)
    104 {
    105 	const union sf_ieee_ldbl_u a = { .ldblu_ld = ld_a };
    106 	const union sf_ieee_ldbl_u b = { .ldblu_ld = ld_b };
    107 	const union sf_ieee_ldbl_u c = {
    108 	    .ldblu_f128 = float128_div(a.ldblu_f128, b.ldblu_f128)
    109 	};
    110 
    111 	return c.ldblu_ld;
    112 }
    113 
    114 long double
    115 __multf3(long double ld_a, long double ld_b)
    116 {
    117 	const union sf_ieee_ldbl_u a = { .ldblu_ld = ld_a };
    118 	const union sf_ieee_ldbl_u b = { .ldblu_ld = ld_b };
    119 	const union sf_ieee_ldbl_u c = {
    120 	    .ldblu_f128 = float128_mul(a.ldblu_f128, b.ldblu_f128)
    121 	};
    122 
    123 	return c.ldblu_ld;
    124 }
    125 
    126 long double
    127 __negtf2(long double ld_a)
    128 {
    129 	const union sf_ieee_ldbl_u zero = { .ldblu_ld = 0.0 };
    130 	const union sf_ieee_ldbl_u a = { .ldblu_ld = ld_a };
    131 	const union sf_ieee_ldbl_u b = {
    132 	    .ldblu_f128 = float128_div(zero.ldblu_f128, a.ldblu_f128)
    133 	};
    134 
    135 	return b.ldblu_ld;
    136 }
    137 
    138 long double
    139 __subtf3(long double ld_a, long double ld_b)
    140 {
    141 	const union sf_ieee_ldbl_u a = { .ldblu_ld = ld_a };
    142 	const union sf_ieee_ldbl_u b = { .ldblu_ld = ld_b };
    143 	const union sf_ieee_ldbl_u c = {
    144 	    .ldblu_f128 = float128_sub(a.ldblu_f128, b.ldblu_f128)
    145 	};
    146 
    147 	return c.ldblu_ld;
    148 }
    149 
    150 #if 0
    151 int
    152 __cmptf3(float128 *a, float128 *b)
    153 {
    154 	const union sf_ieee_ldbl_u a = { .ldblu_ld = ld_a };
    155 	const union sf_ieee_ldbl_u b = { .ldblu_ld = ld_b };
    156 
    157 	if (float128_eq(*a, *b))
    158 		return 0;
    159 
    160 	if (float128_le(*a, *b))
    161 		return 1;
    162 
    163 	return 2;
    164 }
    165 
    166 
    167 /*
    168  * XXX
    169  */
    170 int
    171 _Qp_cmpe(float128 *a, float128 *b)
    172 {
    173 	return _Qp_cmp(a, b);
    174 }
    175 #endif
    176 
    177 float
    178 __trunctfsf2(long double ld_a)
    179 {
    180 	const union sf_ieee_ldbl_u a = { .ldblu_ld = ld_a };
    181 	const union sf_ieee_flt_u c = {
    182 		.fltu_f32 = float128_to_float32(a.ldblu_f128),
    183 	};
    184 
    185 	return c.fltu_f;
    186 }
    187 
    188 double
    189 __trunctfdf2(long double ld_a)
    190 {
    191 	const union sf_ieee_ldbl_u a = { .ldblu_ld = ld_a };
    192 	const union sf_ieee_dbl_u c = {
    193 		.dblu_f64 = float128_to_float64(a.ldblu_f128),
    194 	};
    195 
    196 	return c.dblu_d;
    197 }
    198 
    199 int32_t
    200 __fixtfsi(long double ld_a)
    201 {
    202 	const union sf_ieee_ldbl_u a = { .ldblu_ld = ld_a };
    203 	return float128_to_int32_round_to_zero(a.ldblu_f128);
    204 }
    205 
    206 int64_t
    207 __fixtfdi(long double ld_a)
    208 {
    209 	const union sf_ieee_ldbl_u a = { .ldblu_ld = ld_a };
    210 
    211 	return float128_to_int64_round_to_zero(a.ldblu_f128);
    212 }
    213 
    214 #if 0
    215 uint32_t
    216 __fixuntfsi(long double ld_a)
    217 {
    218 	const union sf_ieee_ldbl_u a = { .ldblu_ld = ld_a };
    219 
    220 	return float128_to_uint32_round_to_zero(a.ldblu_f128);
    221 }
    222 
    223 uint64_t
    224 __fixuntfdi(long double ld_a)
    225 {
    226 	const union sf_ieee_ldbl_u a = { .ldblu_ld = ld_a };
    227 
    228 	return float128_to_uint64_round_to_zero(a.ldblu_f128);
    229 }
    230 #endif
    231 
    232 long double
    233 __extendsftf2(float f_a)
    234 {
    235 	const union sf_ieee_flt_u a = { .fltu_f = f_a };
    236 	const union sf_ieee_ldbl_u c = {
    237 		.ldblu_f128 = float32_to_float128(a.fltu_f32)
    238 	};
    239 
    240 	return c.ldblu_ld;
    241 }
    242 
    243 long double
    244 __extenddftf2(double d_a)
    245 {
    246 	const union sf_ieee_dbl_u a = { .dblu_d = d_a };
    247 	const union sf_ieee_ldbl_u c = {
    248 		.ldblu_f128 = float64_to_float128(a.dblu_f64)
    249 	};
    250 
    251 	return c.ldblu_ld;
    252 }
    253 
    254 long double
    255 __floatunsitf(uint32_t a)
    256 {
    257 	const union sf_ieee_ldbl_u c = {
    258 		.ldblu_f128 = int64_to_float128(a)
    259 	};
    260 
    261 	return c.ldblu_ld;
    262 }
    263 
    264 long double
    265 __floatunditf(uint64_t a)
    266 {
    267 	union sf_ieee_ldbl_u c;
    268 	const uint64_t msb64 = 1LL << 63;
    269 
    270 	if (a & msb64) {
    271 		static const union sf_ieee_ldbl_u two63 = {
    272 			.ldblu_ld = 0x1.0p63
    273 		};
    274 
    275 		c.ldblu_f128 = int64_to_float128(a ^ msb64);
    276 		c.ldblu_f128 = float128_add(c.ldblu_f128, two63.ldblu_f128);
    277 	} else {
    278 		c.ldblu_f128 = int64_to_float128(a);
    279 	}
    280 	return c.ldblu_ld;
    281 }
    282 
    283 long double
    284 __floatsitf(int32_t a)
    285 {
    286 	const union sf_ieee_ldbl_u c = {
    287 		.ldblu_f128 = int64_to_float128(a)
    288 	};
    289 
    290 	return c.ldblu_ld;
    291 }
    292 
    293 long double
    294 __floatditf(int64_t a)
    295 {
    296 	const union sf_ieee_ldbl_u c = {
    297 		.ldblu_f128 = int64_to_float128(a)
    298 	};
    299 
    300 	return c.ldblu_ld;
    301 }
    302