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