| /* Software floating-point emulation. |
| Convert a _BitInt to IBM double double. |
| |
| Copyright (C) 2023-2026 Free Software Foundation, Inc. |
| |
| This file is part of GCC. |
| |
| GCC is free software; you can redistribute it and/or modify it under |
| the terms of the GNU General Public License as published by the Free |
| Software Foundation; either version 3, or (at your option) any later |
| version. |
| |
| GCC 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 General Public License |
| for more details. |
| |
| Under Section 7 of GPL version 3, you are granted additional |
| permissions described in the GCC Runtime Library Exception, version |
| 3.1, as published by the Free Software Foundation. |
| |
| You should have received a copy of the GNU General Public License and |
| a copy of the GCC Runtime Library Exception along with this program; |
| see the files COPYING3 and COPYING.RUNTIME respectively. If not, see |
| <http://www.gnu.org/licenses/>. */ |
| |
| #include "soft-fp.h" |
| #include "double.h" |
| #include "bitint.h" |
| |
| #ifdef __BITINT_MAXWIDTH__ |
| __ibm128 |
| __floatbitinttf (const UBILtype *i, SItype iprec) |
| { |
| DItype iv; |
| USItype shift = 0; |
| FP_DECL_EX; |
| FP_DECL_D (A); |
| FP_DECL_D (B); |
| union { __ibm128 a; DFtype b[2]; } ua; |
| |
| FP_FROM_BITINT (i, iprec, iv, shift, DI); |
| FP_INIT_ROUNDMODE; |
| FP_FROM_INT_D (A, iv, DI_BITS, UDItype); |
| if (shift) |
| { |
| A_e += shift; |
| if (A_e >= _FP_EXPMAX_D) |
| { |
| /* Exponent too big; overflow to infinity. */ |
| #if _FP_W_TYPE_SIZE < 64 |
| _FP_OVERFLOW_SEMIRAW (D, 2, A); |
| _FP_PACK_SEMIRAW (D, 2, A); |
| #else |
| _FP_OVERFLOW_SEMIRAW (D, 1, A); |
| _FP_PACK_SEMIRAW (D, 1, A); |
| #endif |
| } |
| } |
| FP_PACK_RAW_D (ua.b[0], A); |
| if (A_e >= _FP_EXPMAX_D || !iv) |
| ua.b[1] = 0; |
| else |
| { |
| USItype shift2 = 0; |
| UDItype iv2; |
| if (A_e >= _FP_EXPBIAS_D + _FP_FRACBITS_D + 1) |
| { |
| shift2 = A_e - (_FP_EXPBIAS_D + _FP_FRACBITS_D); |
| A_e -= shift2; |
| } |
| FP_TO_INT_D (iv2, A, DI_BITS, 1); |
| USItype shiftl = shift / BIL_TYPE_SIZE; |
| USItype shiftr = shift % BIL_TYPE_SIZE; |
| USItype aiprec = iprec < 0 ? -iprec : iprec; |
| USItype in = (aiprec + BIL_TYPE_SIZE - 1) / BIL_TYPE_SIZE; |
| (void) in; |
| USItype idx = BITINT_END (in - shiftl - 1, shiftl); |
| /* The low bit from FP_FROM_BITINT has all lower bits ored into it. |
| Undo this now. */ |
| if (((i[idx] >> shiftr) & 1) == 0) |
| iv &= ~(UDItype) 1; |
| iv = iv - (iv2 << (shift2 - shift)); |
| /* A has been rounded down by |
| ((_BitInt(iprec < 0 ? -iprec : iprec)) (DItype) iv) << shift. |
| Next step is to perform FP_FROM_BITINT virtually on a value |
| that has bits from iv for bits shift and up and bits from |
| i for the lower bits. */ |
| if (shift) |
| { |
| SItype n = DI_BITS + 1; |
| if (iv < 0) |
| { |
| if (iv != -1) |
| { |
| n = (sizeof (0ULL) * __CHAR_BIT__ + 1 |
| - __builtin_clzll (~iv)); |
| n = DI_BITS - n; |
| } |
| } |
| else if (iv) |
| { |
| n = sizeof (0ULL) * __CHAR_BIT__ - __builtin_clzll (iv); |
| n = DI_BITS - 1 - n; |
| } |
| shift = 0; |
| UBILtype msb = 0; |
| if (shiftr != 0) |
| { |
| msb = i[idx] & (((UBILtype) 1 << shiftr) - 1); |
| if (iv == 0) |
| { |
| if (msb != 0) |
| goto first_nonzero; |
| } |
| else if (iv == -1) |
| { |
| if (msb != ((UBILtype) 1 << shiftr) - 1) |
| { |
| msb |= (UBILtype) -1 << shiftr; |
| goto first_nonminusone; |
| } |
| } |
| else if (shiftr < DI_BITS && n >= (SItype) shiftr) |
| { |
| iv = (UDItype) iv << (shiftr < DI_BITS ? shiftr : 0); |
| iv |= msb; |
| n -= shiftr; |
| } |
| else |
| { |
| iv = (UDItype) iv << n; |
| iv |= msb >> (shiftr - n); |
| shift = shiftr - n; |
| n = 0; |
| } |
| } |
| if (iv == 0 && n == DI_BITS + 1) |
| while (BITINT_END (idx < in - 1, idx)) |
| { |
| idx -= BITINT_INC; |
| msb = i[idx]; |
| if (msb != 0) |
| { |
| if ((BILtype) msb < 0) |
| { |
| idx += BITINT_INC; |
| n = DI_BITS - 1; |
| break; |
| } |
| first_nonzero: |
| n = sizeof (0ULL) * __CHAR_BIT__ - __builtin_clzll (msb); |
| if (BIL_TYPE_SIZE >= DI_BITS && n >= DI_BITS) |
| { |
| iv = msb >> (n - DI_BITS + 1); |
| shift = n - DI_BITS + 1; |
| n = 0; |
| } |
| else |
| { |
| iv = msb; |
| n = DI_BITS - 1 - n; |
| } |
| break; |
| } |
| } |
| if (iv == -1 && n == DI_BITS + 1) |
| while (BITINT_END (idx < in - 1, idx)) |
| { |
| idx -= BITINT_INC; |
| msb = i[idx]; |
| if (msb != (UBILtype) -1) |
| { |
| if ((BILtype) msb >= 0) |
| { |
| idx += BITINT_INC; |
| n = DI_BITS - 1; |
| break; |
| } |
| first_nonminusone: |
| n = (sizeof (0ULL) * __CHAR_BIT__ + 1 |
| - __builtin_clzll (~msb)); |
| if (BIL_TYPE_SIZE > DI_BITS && n > DI_BITS) |
| { |
| iv = msb >> (n - DI_BITS); |
| shift = n - DI_BITS; |
| n = 0; |
| } |
| else |
| { |
| iv = (BILtype) msb; |
| n = DI_BITS - n; |
| } |
| break; |
| } |
| } |
| while (n && BITINT_END (idx < in - 1, idx)) |
| { |
| idx -= BITINT_INC; |
| msb = i[idx]; |
| if (BIL_TYPE_SIZE < DI_BITS && n >= BIL_TYPE_SIZE) |
| { |
| iv = (UDItype) iv << (BIL_TYPE_SIZE < DI_BITS |
| ? BIL_TYPE_SIZE : 0); |
| iv |= msb; |
| n -= BIL_TYPE_SIZE; |
| } |
| else |
| { |
| iv = (UDItype) iv << n; |
| iv |= msb >> (BIL_TYPE_SIZE - n); |
| shift = BIL_TYPE_SIZE - n; |
| break; |
| } |
| } |
| |
| UBILtype low_bits = 0; |
| if (shift) |
| low_bits = msb & (((UBILtype) 1 << shift) - 1); |
| shift += BITINT_END (in - 1 - idx, idx) * BIL_TYPE_SIZE; |
| while (!low_bits && BITINT_END (idx < in - 1, idx)) |
| { |
| idx -= BITINT_INC; |
| low_bits |= i[idx]; |
| } |
| iv |= (low_bits != 0); |
| } |
| FP_FROM_INT_D (B, iv, DI_BITS, UDItype); |
| if (shift) |
| B_e += shift; |
| FP_PACK_RAW_D (ua.b[1], B); |
| } |
| FP_HANDLE_EXCEPTIONS; |
| |
| return ua.a; |
| } |
| #endif |