xref: /netbsd-src/external/gpl3/gcc.old/dist/libgcc/config/libbid/bid128_scalb.c (revision 8feb0f0b7eaff0608f8350bbfa3098827b4bb91b)
1*8feb0f0bSmrg /* Copyright (C) 2007-2020 Free Software Foundation, Inc.
236ac495dSmrg 
336ac495dSmrg This file is part of GCC.
436ac495dSmrg 
536ac495dSmrg GCC is free software; you can redistribute it and/or modify it under
636ac495dSmrg the terms of the GNU General Public License as published by the Free
736ac495dSmrg Software Foundation; either version 3, or (at your option) any later
836ac495dSmrg version.
936ac495dSmrg 
1036ac495dSmrg GCC is distributed in the hope that it will be useful, but WITHOUT ANY
1136ac495dSmrg WARRANTY; without even the implied warranty of MERCHANTABILITY or
1236ac495dSmrg FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
1336ac495dSmrg for more details.
1436ac495dSmrg 
1536ac495dSmrg Under Section 7 of GPL version 3, you are granted additional
1636ac495dSmrg permissions described in the GCC Runtime Library Exception, version
1736ac495dSmrg 3.1, as published by the Free Software Foundation.
1836ac495dSmrg 
1936ac495dSmrg You should have received a copy of the GNU General Public License and
2036ac495dSmrg a copy of the GCC Runtime Library Exception along with this program;
2136ac495dSmrg see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
2236ac495dSmrg <http://www.gnu.org/licenses/>.  */
2336ac495dSmrg 
2436ac495dSmrg #define BID_128RES
2536ac495dSmrg #include "bid_internal.h"
2636ac495dSmrg 
2736ac495dSmrg #define DECIMAL_EXPONENT_BIAS_128 6176
2836ac495dSmrg #define MAX_DECIMAL_EXPONENT_128  12287
2936ac495dSmrg 
3036ac495dSmrg 
3136ac495dSmrg 
3236ac495dSmrg BID128_FUNCTION_ARG128_ARGTYPE2 (bid128_scalb, x, int, n)
3336ac495dSmrg 
3436ac495dSmrg      UINT128 CX, CX2, CX8, res;
3536ac495dSmrg      SINT64 exp64;
3636ac495dSmrg      UINT64 sign_x;
3736ac495dSmrg      int exponent_x, rmode;
3836ac495dSmrg 
3936ac495dSmrg   // unpack arguments, check for NaN or Infinity
4036ac495dSmrg if (!unpack_BID128_value (&sign_x, &exponent_x, &CX, x)) {
4136ac495dSmrg     // x is Inf. or NaN or 0
4236ac495dSmrg #ifdef SET_STATUS_FLAGS
4336ac495dSmrg if ((x.w[1] & SNAN_MASK64) == SNAN_MASK64)	// y is sNaN
4436ac495dSmrg   __set_status_flags (pfpsf, INVALID_EXCEPTION);
4536ac495dSmrg #endif
4636ac495dSmrg res.w[1] = CX.w[1] & QUIET_MASK64;
4736ac495dSmrg res.w[0] = CX.w[0];
4836ac495dSmrg if (!CX.w[1]) {
4936ac495dSmrg        exp64 = (SINT64) exponent_x + (SINT64) n;
5036ac495dSmrg 	   if(exp64<0) exp64=0;
5136ac495dSmrg 	   if(exp64>MAX_DECIMAL_EXPONENT_128) exp64=MAX_DECIMAL_EXPONENT_128;
5236ac495dSmrg        exponent_x = exp64;
5336ac495dSmrg   get_BID128_very_fast (&res, sign_x, exponent_x, CX);
5436ac495dSmrg }
5536ac495dSmrg BID_RETURN (res);
5636ac495dSmrg }
5736ac495dSmrg 
5836ac495dSmrg exp64 = (SINT64) exponent_x + (SINT64) n;
5936ac495dSmrg exponent_x = exp64;
6036ac495dSmrg 
6136ac495dSmrg if ((UINT32) exponent_x <= MAX_DECIMAL_EXPONENT_128) {
6236ac495dSmrg   get_BID128_very_fast (&res, sign_x, exponent_x, CX);
6336ac495dSmrg   BID_RETURN (res);
6436ac495dSmrg }
6536ac495dSmrg   // check for overflow
6636ac495dSmrg if (exp64 > MAX_DECIMAL_EXPONENT_128) {
6736ac495dSmrg   if (CX.w[1] < 0x314dc6448d93ull) {
6836ac495dSmrg     // try to normalize coefficient
6936ac495dSmrg     do {
7036ac495dSmrg       CX8.w[1] = (CX.w[1] << 3) | (CX.w[0] >> 61);
7136ac495dSmrg       CX8.w[0] = CX.w[0] << 3;
7236ac495dSmrg       CX2.w[1] = (CX.w[1] << 1) | (CX.w[0] >> 63);
7336ac495dSmrg       CX2.w[0] = CX.w[0] << 1;
7436ac495dSmrg       __add_128_128 (CX, CX2, CX8);
7536ac495dSmrg 
7636ac495dSmrg       exponent_x--;
7736ac495dSmrg       exp64--;
7836ac495dSmrg     }
7936ac495dSmrg     while (CX.w[1] < 0x314dc6448d93ull
8036ac495dSmrg 	   && exp64 > MAX_DECIMAL_EXPONENT_128);
8136ac495dSmrg 
8236ac495dSmrg   }
8336ac495dSmrg   if (exp64 <= MAX_DECIMAL_EXPONENT_128) {
8436ac495dSmrg     get_BID128_very_fast (&res, sign_x, exponent_x, CX);
8536ac495dSmrg     BID_RETURN (res);
8636ac495dSmrg   } else
8736ac495dSmrg     exponent_x = 0x7fffffff;	// overflow
8836ac495dSmrg }
8936ac495dSmrg   // exponent < 0
9036ac495dSmrg   // the BID pack routine will round the coefficient
9136ac495dSmrg rmode = rnd_mode;
9236ac495dSmrg get_BID128 (&res, sign_x, exponent_x, CX, (unsigned int *) &rmode,
9336ac495dSmrg 	    pfpsf);
9436ac495dSmrg BID_RETURN (res);
9536ac495dSmrg 
9636ac495dSmrg }
97