diff options
Diffstat (limited to 'libc/sysdeps/linux/sparc64/soft-fp')
44 files changed, 8827 insertions, 0 deletions
diff --git a/libc/sysdeps/linux/sparc64/soft-fp/Makefile b/libc/sysdeps/linux/sparc64/soft-fp/Makefile new file mode 100644 index 000000000..b145df283 --- /dev/null +++ b/libc/sysdeps/linux/sparc64/soft-fp/Makefile @@ -0,0 +1,33 @@ +# Software floating-point emulation. +# Makefile for SPARC v9 ABI mandated long double utility +# functions (_Qp_*). +# Copyright (C) 1999-2017 Free Software Foundation, Inc. +# This file is part of the GNU C Library. +# Contributed by Jakub Jelinek (jj@ultra.linux.cz). +# + +# The GNU C Library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. + +# The GNU C Library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. + +# You should have received a copy of the GNU Lesser General Public +# License along with the GNU C Library; if not, see +# <http://www.gnu.org/licenses/>. + +ifeq ($(subdir),soft-fp) +sparc64-quad-routines := qp_add qp_cmp qp_cmpe qp_div qp_dtoq qp_feq qp_fge \ + qp_fgt qp_fle qp_flt qp_fne qp_itoq qp_mul qp_neg qp_qtod qp_qtoi \ + qp_qtos qp_qtoui qp_qtoux qp_qtox qp_sqrt qp_stoq qp_sub qp_uitoq \ + qp_uxtoq qp_xtoq qp_util +sysdep_routines += $(sparc64-quad-routines) +endif + +ifeq ($(subdir),math) +CPPFLAGS += -I../soft-fp/ +endif diff --git a/libc/sysdeps/linux/sparc64/soft-fp/Versions b/libc/sysdeps/linux/sparc64/soft-fp/Versions new file mode 100644 index 000000000..9e89c3c3e --- /dev/null +++ b/libc/sysdeps/linux/sparc64/soft-fp/Versions @@ -0,0 +1,8 @@ +libc { + GLIBC_2.2 { + _Qp_add; _Qp_cmp; _Qp_cmpe; _Qp_div; _Qp_dtoq; _Qp_feq; _Qp_fge; _Qp_fgt; + _Qp_fle; _Qp_flt; _Qp_fne; _Qp_itoq; _Qp_mul; _Qp_neg; _Qp_qtod; _Qp_qtoi; + _Qp_qtos; _Qp_qtoui; _Qp_qtoux; _Qp_qtox; _Qp_sqrt; _Qp_stoq; _Qp_sub; + _Qp_uitoq; _Qp_uxtoq; _Qp_xtoq; + } +} diff --git a/libc/sysdeps/linux/sparc64/soft-fp/double.h b/libc/sysdeps/linux/sparc64/soft-fp/double.h new file mode 100644 index 000000000..055d9da6b --- /dev/null +++ b/libc/sysdeps/linux/sparc64/soft-fp/double.h @@ -0,0 +1,323 @@ +/* Software floating-point emulation. + Definitions for IEEE Double Precision + Copyright (C) 1997-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Richard Henderson (rth@cygnus.com), + Jakub Jelinek (jj@ultra.linux.cz), + David S. Miller (davem@redhat.com) and + Peter Maydell (pmaydell@chiark.greenend.org.uk). + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + In addition to the permissions in the GNU Lesser General Public + License, the Free Software Foundation gives you unlimited + permission to link the compiled version of this file into + combinations with other programs, and to distribute those + combinations without any restriction coming from the use of this + file. (The Lesser General Public License restrictions do apply in + other respects; for example, they cover modification of the file, + and distribution when not linked into a combine executable.) + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#ifndef SOFT_FP_DOUBLE_H +#define SOFT_FP_DOUBLE_H 1 + +#if _FP_W_TYPE_SIZE < 32 +# error "Here's a nickel kid. Go buy yourself a real computer." +#endif + +#if _FP_W_TYPE_SIZE < 64 +# define _FP_FRACTBITS_D (2 * _FP_W_TYPE_SIZE) +# define _FP_FRACTBITS_DW_D (4 * _FP_W_TYPE_SIZE) +#else +# define _FP_FRACTBITS_D _FP_W_TYPE_SIZE +# define _FP_FRACTBITS_DW_D (2 * _FP_W_TYPE_SIZE) +#endif + +#define _FP_FRACBITS_D 53 +#define _FP_FRACXBITS_D (_FP_FRACTBITS_D - _FP_FRACBITS_D) +#define _FP_WFRACBITS_D (_FP_WORKBITS + _FP_FRACBITS_D) +#define _FP_WFRACXBITS_D (_FP_FRACTBITS_D - _FP_WFRACBITS_D) +#define _FP_EXPBITS_D 11 +#define _FP_EXPBIAS_D 1023 +#define _FP_EXPMAX_D 2047 + +#define _FP_QNANBIT_D \ + ((_FP_W_TYPE) 1 << (_FP_FRACBITS_D-2) % _FP_W_TYPE_SIZE) +#define _FP_QNANBIT_SH_D \ + ((_FP_W_TYPE) 1 << (_FP_FRACBITS_D-2+_FP_WORKBITS) % _FP_W_TYPE_SIZE) +#define _FP_IMPLBIT_D \ + ((_FP_W_TYPE) 1 << (_FP_FRACBITS_D-1) % _FP_W_TYPE_SIZE) +#define _FP_IMPLBIT_SH_D \ + ((_FP_W_TYPE) 1 << (_FP_FRACBITS_D-1+_FP_WORKBITS) % _FP_W_TYPE_SIZE) +#define _FP_OVERFLOW_D \ + ((_FP_W_TYPE) 1 << _FP_WFRACBITS_D % _FP_W_TYPE_SIZE) + +#define _FP_WFRACBITS_DW_D (2 * _FP_WFRACBITS_D) +#define _FP_WFRACXBITS_DW_D (_FP_FRACTBITS_DW_D - _FP_WFRACBITS_DW_D) +#define _FP_HIGHBIT_DW_D \ + ((_FP_W_TYPE) 1 << (_FP_WFRACBITS_DW_D - 1) % _FP_W_TYPE_SIZE) + +typedef float DFtype __attribute__ ((mode (DF))); + +#if _FP_W_TYPE_SIZE < 64 + +union _FP_UNION_D +{ + DFtype flt; + struct _FP_STRUCT_LAYOUT + { +# if __BYTE_ORDER == __BIG_ENDIAN + unsigned sign : 1; + unsigned exp : _FP_EXPBITS_D; + unsigned frac1 : _FP_FRACBITS_D - (_FP_IMPLBIT_D != 0) - _FP_W_TYPE_SIZE; + unsigned frac0 : _FP_W_TYPE_SIZE; +# else + unsigned frac0 : _FP_W_TYPE_SIZE; + unsigned frac1 : _FP_FRACBITS_D - (_FP_IMPLBIT_D != 0) - _FP_W_TYPE_SIZE; + unsigned exp : _FP_EXPBITS_D; + unsigned sign : 1; +# endif + } bits __attribute__ ((packed)); +}; + +# define FP_DECL_D(X) _FP_DECL (2, X) +# define FP_UNPACK_RAW_D(X, val) _FP_UNPACK_RAW_2 (D, X, (val)) +# define FP_UNPACK_RAW_DP(X, val) _FP_UNPACK_RAW_2_P (D, X, (val)) +# define FP_PACK_RAW_D(val, X) _FP_PACK_RAW_2 (D, (val), X) +# define FP_PACK_RAW_DP(val, X) \ + do \ + { \ + if (!FP_INHIBIT_RESULTS) \ + _FP_PACK_RAW_2_P (D, (val), X); \ + } \ + while (0) + +# define FP_UNPACK_D(X, val) \ + do \ + { \ + _FP_UNPACK_RAW_2 (D, X, (val)); \ + _FP_UNPACK_CANONICAL (D, 2, X); \ + } \ + while (0) + +# define FP_UNPACK_DP(X, val) \ + do \ + { \ + _FP_UNPACK_RAW_2_P (D, X, (val)); \ + _FP_UNPACK_CANONICAL (D, 2, X); \ + } \ + while (0) + +# define FP_UNPACK_SEMIRAW_D(X, val) \ + do \ + { \ + _FP_UNPACK_RAW_2 (D, X, (val)); \ + _FP_UNPACK_SEMIRAW (D, 2, X); \ + } \ + while (0) + +# define FP_UNPACK_SEMIRAW_DP(X, val) \ + do \ + { \ + _FP_UNPACK_RAW_2_P (D, X, (val)); \ + _FP_UNPACK_SEMIRAW (D, 2, X); \ + } \ + while (0) + +# define FP_PACK_D(val, X) \ + do \ + { \ + _FP_PACK_CANONICAL (D, 2, X); \ + _FP_PACK_RAW_2 (D, (val), X); \ + } \ + while (0) + +# define FP_PACK_DP(val, X) \ + do \ + { \ + _FP_PACK_CANONICAL (D, 2, X); \ + if (!FP_INHIBIT_RESULTS) \ + _FP_PACK_RAW_2_P (D, (val), X); \ + } \ + while (0) + +# define FP_PACK_SEMIRAW_D(val, X) \ + do \ + { \ + _FP_PACK_SEMIRAW (D, 2, X); \ + _FP_PACK_RAW_2 (D, (val), X); \ + } \ + while (0) + +# define FP_PACK_SEMIRAW_DP(val, X) \ + do \ + { \ + _FP_PACK_SEMIRAW (D, 2, X); \ + if (!FP_INHIBIT_RESULTS) \ + _FP_PACK_RAW_2_P (D, (val), X); \ + } \ + while (0) + +# define FP_ISSIGNAN_D(X) _FP_ISSIGNAN (D, 2, X) +# define FP_NEG_D(R, X) _FP_NEG (D, 2, R, X) +# define FP_ADD_D(R, X, Y) _FP_ADD (D, 2, R, X, Y) +# define FP_SUB_D(R, X, Y) _FP_SUB (D, 2, R, X, Y) +# define FP_MUL_D(R, X, Y) _FP_MUL (D, 2, R, X, Y) +# define FP_DIV_D(R, X, Y) _FP_DIV (D, 2, R, X, Y) +# define FP_SQRT_D(R, X) _FP_SQRT (D, 2, R, X) +# define _FP_SQRT_MEAT_D(R, S, T, X, Q) _FP_SQRT_MEAT_2 (R, S, T, X, (Q)) +# define FP_FMA_D(R, X, Y, Z) _FP_FMA (D, 2, 4, R, X, Y, Z) + +# define FP_CMP_D(r, X, Y, un, ex) _FP_CMP (D, 2, (r), X, Y, (un), (ex)) +# define FP_CMP_EQ_D(r, X, Y, ex) _FP_CMP_EQ (D, 2, (r), X, Y, (ex)) +# define FP_CMP_UNORD_D(r, X, Y, ex) _FP_CMP_UNORD (D, 2, (r), X, Y, (ex)) + +# define FP_TO_INT_D(r, X, rsz, rsg) _FP_TO_INT (D, 2, (r), X, (rsz), (rsg)) +# define FP_TO_INT_ROUND_D(r, X, rsz, rsg) \ + _FP_TO_INT_ROUND (D, 2, (r), X, (rsz), (rsg)) +# define FP_FROM_INT_D(X, r, rs, rt) _FP_FROM_INT (D, 2, X, (r), (rs), rt) + +# define _FP_FRAC_HIGH_D(X) _FP_FRAC_HIGH_2 (X) +# define _FP_FRAC_HIGH_RAW_D(X) _FP_FRAC_HIGH_2 (X) + +# define _FP_FRAC_HIGH_DW_D(X) _FP_FRAC_HIGH_4 (X) + +#else + +union _FP_UNION_D +{ + DFtype flt; + struct _FP_STRUCT_LAYOUT + { +# if __BYTE_ORDER == __BIG_ENDIAN + unsigned sign : 1; + unsigned exp : _FP_EXPBITS_D; + _FP_W_TYPE frac : _FP_FRACBITS_D - (_FP_IMPLBIT_D != 0); +# else + _FP_W_TYPE frac : _FP_FRACBITS_D - (_FP_IMPLBIT_D != 0); + unsigned exp : _FP_EXPBITS_D; + unsigned sign : 1; +# endif + } bits __attribute__ ((packed)); +}; + +# define FP_DECL_D(X) _FP_DECL (1, X) +# define FP_UNPACK_RAW_D(X, val) _FP_UNPACK_RAW_1 (D, X, (val)) +# define FP_UNPACK_RAW_DP(X, val) _FP_UNPACK_RAW_1_P (D, X, (val)) +# define FP_PACK_RAW_D(val, X) _FP_PACK_RAW_1 (D, (val), X) +# define FP_PACK_RAW_DP(val, X) \ + do \ + { \ + if (!FP_INHIBIT_RESULTS) \ + _FP_PACK_RAW_1_P (D, (val), X); \ + } \ + while (0) + +# define FP_UNPACK_D(X, val) \ + do \ + { \ + _FP_UNPACK_RAW_1 (D, X, (val)); \ + _FP_UNPACK_CANONICAL (D, 1, X); \ + } \ + while (0) + +# define FP_UNPACK_DP(X, val) \ + do \ + { \ + _FP_UNPACK_RAW_1_P (D, X, (val)); \ + _FP_UNPACK_CANONICAL (D, 1, X); \ + } \ + while (0) + +# define FP_UNPACK_SEMIRAW_D(X, val) \ + do \ + { \ + _FP_UNPACK_RAW_1 (D, X, (val)); \ + _FP_UNPACK_SEMIRAW (D, 1, X); \ + } \ + while (0) + +# define FP_UNPACK_SEMIRAW_DP(X, val) \ + do \ + { \ + _FP_UNPACK_RAW_1_P (D, X, (val)); \ + _FP_UNPACK_SEMIRAW (D, 1, X); \ + } \ + while (0) + +# define FP_PACK_D(val, X) \ + do \ + { \ + _FP_PACK_CANONICAL (D, 1, X); \ + _FP_PACK_RAW_1 (D, (val), X); \ + } \ + while (0) + +# define FP_PACK_DP(val, X) \ + do \ + { \ + _FP_PACK_CANONICAL (D, 1, X); \ + if (!FP_INHIBIT_RESULTS) \ + _FP_PACK_RAW_1_P (D, (val), X); \ + } \ + while (0) + +# define FP_PACK_SEMIRAW_D(val, X) \ + do \ + { \ + _FP_PACK_SEMIRAW (D, 1, X); \ + _FP_PACK_RAW_1 (D, (val), X); \ + } \ + while (0) + +# define FP_PACK_SEMIRAW_DP(val, X) \ + do \ + { \ + _FP_PACK_SEMIRAW (D, 1, X); \ + if (!FP_INHIBIT_RESULTS) \ + _FP_PACK_RAW_1_P (D, (val), X); \ + } \ + while (0) + +# define FP_ISSIGNAN_D(X) _FP_ISSIGNAN (D, 1, X) +# define FP_NEG_D(R, X) _FP_NEG (D, 1, R, X) +# define FP_ADD_D(R, X, Y) _FP_ADD (D, 1, R, X, Y) +# define FP_SUB_D(R, X, Y) _FP_SUB (D, 1, R, X, Y) +# define FP_MUL_D(R, X, Y) _FP_MUL (D, 1, R, X, Y) +# define FP_DIV_D(R, X, Y) _FP_DIV (D, 1, R, X, Y) +# define FP_SQRT_D(R, X) _FP_SQRT (D, 1, R, X) +# define _FP_SQRT_MEAT_D(R, S, T, X, Q) _FP_SQRT_MEAT_1 (R, S, T, X, (Q)) +# define FP_FMA_D(R, X, Y, Z) _FP_FMA (D, 1, 2, R, X, Y, Z) + +/* The implementation of _FP_MUL_D and _FP_DIV_D should be chosen by + the target machine. */ + +# define FP_CMP_D(r, X, Y, un, ex) _FP_CMP (D, 1, (r), X, Y, (un), (ex)) +# define FP_CMP_EQ_D(r, X, Y, ex) _FP_CMP_EQ (D, 1, (r), X, Y, (ex)) +# define FP_CMP_UNORD_D(r, X, Y, ex) _FP_CMP_UNORD (D, 1, (r), X, Y, (ex)) + +# define FP_TO_INT_D(r, X, rsz, rsg) _FP_TO_INT (D, 1, (r), X, (rsz), (rsg)) +# define FP_TO_INT_ROUND_D(r, X, rsz, rsg) \ + _FP_TO_INT_ROUND (D, 1, (r), X, (rsz), (rsg)) +# define FP_FROM_INT_D(X, r, rs, rt) _FP_FROM_INT (D, 1, X, (r), (rs), rt) + +# define _FP_FRAC_HIGH_D(X) _FP_FRAC_HIGH_1 (X) +# define _FP_FRAC_HIGH_RAW_D(X) _FP_FRAC_HIGH_1 (X) + +# define _FP_FRAC_HIGH_DW_D(X) _FP_FRAC_HIGH_2 (X) + +#endif /* W_TYPE_SIZE < 64 */ + +#endif /* !SOFT_FP_DOUBLE_H */ diff --git a/libc/sysdeps/linux/sparc64/soft-fp/e_ilogbl.c b/libc/sysdeps/linux/sparc64/soft-fp/e_ilogbl.c new file mode 100644 index 000000000..5b19d12a4 --- /dev/null +++ b/libc/sysdeps/linux/sparc64/soft-fp/e_ilogbl.c @@ -0,0 +1,79 @@ +/* Software floating-point emulation. + ilogbl(x, exp) + Copyright (C) 1999-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek (jj@ultra.linux.cz). + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +/* ilogbl(long double x) + * return the binary exponent of non-zero x + * ilogbl(0) = 0x80000001 + * ilogbl(inf/NaN) = 0x7fffffff (no signal is raised) + */ + +#include "soft-fp.h" +#include "quad.h" +#include <math.h> + +int __ieee754_ilogbl (long double x) +{ + FP_DECL_EX; + FP_DECL_Q(X); + +/* + FP_UNPACK_Q(X, x); + switch (X_c) + { + case FP_CLS_ZERO: + return FP_ILOGB0; + case FP_CLS_NAN: + case FP_CLS_INF: + return FP_ILOGBNAN; + default: + return X_e; + } + */ + FP_UNPACK_RAW_Q(X, x); + switch (X_e) + { + default: + return X_e - _FP_EXPBIAS_Q; + case 0: +#if (2 * _FP_W_TYPE_SIZE) < _FP_FRACBITS_Q + if (_FP_FRAC_ZEROP_4(X)) + return FP_ILOGB0; + else + { + _FP_I_TYPE shift; + _FP_FRAC_CLZ_4(shift, X); + shift -= _FP_FRACXBITS_Q; + return X_e - _FP_EXPBIAS_Q - 1 + shift; + } +#else + if (_FP_FRAC_ZEROP_2(X)) + return FP_ILOGB0; + else + { + _FP_I_TYPE shift; + _FP_FRAC_CLZ_2(shift, X); + shift -= _FP_FRACXBITS_Q; + return X_e - _FP_EXPBIAS_Q - 1 + shift; + } +#endif + case _FP_EXPBIAS_Q: + return FP_ILOGBNAN; + } +} diff --git a/libc/sysdeps/linux/sparc64/soft-fp/longlong.h b/libc/sysdeps/linux/sparc64/soft-fp/longlong.h new file mode 100644 index 000000000..0ec11c505 --- /dev/null +++ b/libc/sysdeps/linux/sparc64/soft-fp/longlong.h @@ -0,0 +1,1773 @@ +/* longlong.h -- definitions for mixed size 32/64 bit arithmetic. + Copyright (C) 1991-2017 Free Software Foundation, Inc. + + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + In addition to the permissions in the GNU Lesser General Public + License, the Free Software Foundation gives you unlimited + permission to link the compiled version of this file into + combinations with other programs, and to distribute those + combinations without any restriction coming from the use of this + file. (The Lesser General Public License restrictions do apply in + other respects; for example, they cover modification of the file, + and distribution when not linked into a combine executable.) + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +/* You have to define the following before including this file: + + UWtype -- An unsigned type, default type for operations (typically a "word") + UHWtype -- An unsigned type, at least half the size of UWtype. + UDWtype -- An unsigned type, at least twice as large a UWtype + W_TYPE_SIZE -- size in bits of UWtype + + UQItype -- Unsigned 8 bit type. + SItype, USItype -- Signed and unsigned 32 bit types. + DItype, UDItype -- Signed and unsigned 64 bit types. + + On a 32 bit machine UWtype should typically be USItype; + on a 64 bit machine, UWtype should typically be UDItype. */ + +#define __BITS4 (W_TYPE_SIZE / 4) +#define __ll_B ((UWtype) 1 << (W_TYPE_SIZE / 2)) +#define __ll_lowpart(t) ((UWtype) (t) & (__ll_B - 1)) +#define __ll_highpart(t) ((UWtype) (t) >> (W_TYPE_SIZE / 2)) + +#ifndef W_TYPE_SIZE +#define W_TYPE_SIZE 32 +#define UWtype USItype +#define UHWtype USItype +#define UDWtype UDItype +#endif + +/* Used in glibc only. */ +#ifndef attribute_hidden +#define attribute_hidden +#endif + +extern const UQItype __clz_tab[256] attribute_hidden; + +/* Define auxiliary asm macros. + + 1) umul_ppmm(high_prod, low_prod, multiplier, multiplicand) multiplies two + UWtype integers MULTIPLIER and MULTIPLICAND, and generates a two UWtype + word product in HIGH_PROD and LOW_PROD. + + 2) __umulsidi3(a,b) multiplies two UWtype integers A and B, and returns a + UDWtype product. This is just a variant of umul_ppmm. + + 3) udiv_qrnnd(quotient, remainder, high_numerator, low_numerator, + denominator) divides a UDWtype, composed by the UWtype integers + HIGH_NUMERATOR and LOW_NUMERATOR, by DENOMINATOR and places the quotient + in QUOTIENT and the remainder in REMAINDER. HIGH_NUMERATOR must be less + than DENOMINATOR for correct operation. If, in addition, the most + significant bit of DENOMINATOR must be 1, then the pre-processor symbol + UDIV_NEEDS_NORMALIZATION is defined to 1. + + 4) sdiv_qrnnd(quotient, remainder, high_numerator, low_numerator, + denominator). Like udiv_qrnnd but the numbers are signed. The quotient + is rounded towards 0. + + 5) count_leading_zeros(count, x) counts the number of zero-bits from the + msb to the first nonzero bit in the UWtype X. This is the number of + steps X needs to be shifted left to set the msb. Undefined for X == 0, + unless the symbol COUNT_LEADING_ZEROS_0 is defined to some value. + + 6) count_trailing_zeros(count, x) like count_leading_zeros, but counts + from the least significant end. + + 7) add_ssaaaa(high_sum, low_sum, high_addend_1, low_addend_1, + high_addend_2, low_addend_2) adds two UWtype integers, composed by + HIGH_ADDEND_1 and LOW_ADDEND_1, and HIGH_ADDEND_2 and LOW_ADDEND_2 + respectively. The result is placed in HIGH_SUM and LOW_SUM. Overflow + (i.e. carry out) is not stored anywhere, and is lost. + + 8) sub_ddmmss(high_difference, low_difference, high_minuend, low_minuend, + high_subtrahend, low_subtrahend) subtracts two two-word UWtype integers, + composed by HIGH_MINUEND_1 and LOW_MINUEND_1, and HIGH_SUBTRAHEND_2 and + LOW_SUBTRAHEND_2 respectively. The result is placed in HIGH_DIFFERENCE + and LOW_DIFFERENCE. Overflow (i.e. carry out) is not stored anywhere, + and is lost. + + If any of these macros are left undefined for a particular CPU, + C macros are used. */ + +/* The CPUs come in alphabetical order below. + + Please add support for more CPUs here, or improve the current support + for the CPUs below! + (E.g. WE32100, IBM360.) */ + +#if defined (__GNUC__) && !defined (NO_ASM) + +/* We sometimes need to clobber "cc" with gcc2, but that would not be + understood by gcc1. Use cpp to avoid major code duplication. */ +#if __GNUC__ < 2 +#define __CLOBBER_CC +#define __AND_CLOBBER_CC +#else /* __GNUC__ >= 2 */ +#define __CLOBBER_CC : "cc" +#define __AND_CLOBBER_CC , "cc" +#endif /* __GNUC__ < 2 */ + +#if defined (__aarch64__) + +#if W_TYPE_SIZE == 32 +#define count_leading_zeros(COUNT, X) ((COUNT) = __builtin_clz (X)) +#define count_trailing_zeros(COUNT, X) ((COUNT) = __builtin_ctz (X)) +#define COUNT_LEADING_ZEROS_0 32 +#endif /* W_TYPE_SIZE == 32 */ + +#if W_TYPE_SIZE == 64 +#define count_leading_zeros(COUNT, X) ((COUNT) = __builtin_clzll (X)) +#define count_trailing_zeros(COUNT, X) ((COUNT) = __builtin_ctzll (X)) +#define COUNT_LEADING_ZEROS_0 64 +#endif /* W_TYPE_SIZE == 64 */ + +#endif /* __aarch64__ */ + +#if defined (__alpha) && W_TYPE_SIZE == 64 +/* There is a bug in g++ before version 5 that + errors on __builtin_alpha_umulh. */ +#if !defined(__cplusplus) || __GNUC__ >= 5 +#define umul_ppmm(ph, pl, m0, m1) \ + do { \ + UDItype __m0 = (m0), __m1 = (m1); \ + (ph) = __builtin_alpha_umulh (__m0, __m1); \ + (pl) = __m0 * __m1; \ + } while (0) +#define UMUL_TIME 46 +#endif /* !c++ */ +#ifndef LONGLONG_STANDALONE +#define udiv_qrnnd(q, r, n1, n0, d) \ + do { UDItype __r; \ + (q) = __udiv_qrnnd (&__r, (n1), (n0), (d)); \ + (r) = __r; \ + } while (0) +extern UDItype __udiv_qrnnd (UDItype *, UDItype, UDItype, UDItype); +#define UDIV_TIME 220 +#endif /* LONGLONG_STANDALONE */ +#ifdef __alpha_cix__ +#define count_leading_zeros(COUNT,X) ((COUNT) = __builtin_clzl (X)) +#define count_trailing_zeros(COUNT,X) ((COUNT) = __builtin_ctzl (X)) +#define COUNT_LEADING_ZEROS_0 64 +#else +#define count_leading_zeros(COUNT,X) \ + do { \ + UDItype __xr = (X), __t, __a; \ + __t = __builtin_alpha_cmpbge (0, __xr); \ + __a = __clz_tab[__t ^ 0xff] - 1; \ + __t = __builtin_alpha_extbl (__xr, __a); \ + (COUNT) = 64 - (__clz_tab[__t] + __a*8); \ + } while (0) +#define count_trailing_zeros(COUNT,X) \ + do { \ + UDItype __xr = (X), __t, __a; \ + __t = __builtin_alpha_cmpbge (0, __xr); \ + __t = ~__t & -~__t; \ + __a = ((__t & 0xCC) != 0) * 2; \ + __a += ((__t & 0xF0) != 0) * 4; \ + __a += ((__t & 0xAA) != 0); \ + __t = __builtin_alpha_extbl (__xr, __a); \ + __a <<= 3; \ + __t &= -__t; \ + __a += ((__t & 0xCC) != 0) * 2; \ + __a += ((__t & 0xF0) != 0) * 4; \ + __a += ((__t & 0xAA) != 0); \ + (COUNT) = __a; \ + } while (0) +#endif /* __alpha_cix__ */ +#endif /* __alpha */ + +#if defined (__arc__) && W_TYPE_SIZE == 32 +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + __asm__ ("add.f %1, %4, %5\n\tadc %0, %2, %3" \ + : "=r" ((USItype) (sh)), \ + "=&r" ((USItype) (sl)) \ + : "%r" ((USItype) (ah)), \ + "rIJ" ((USItype) (bh)), \ + "%r" ((USItype) (al)), \ + "rIJ" ((USItype) (bl))) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + __asm__ ("sub.f %1, %4, %5\n\tsbc %0, %2, %3" \ + : "=r" ((USItype) (sh)), \ + "=&r" ((USItype) (sl)) \ + : "r" ((USItype) (ah)), \ + "rIJ" ((USItype) (bh)), \ + "r" ((USItype) (al)), \ + "rIJ" ((USItype) (bl))) + +#define __umulsidi3(u,v) ((UDItype)(USItype)u*(USItype)v) +#ifdef __ARC_NORM__ +#define count_ |