1311536Sdim//===-- lib/floattitf.c - int128 -> quad-precision conversion -----*- C -*-===// 2311536Sdim// 3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4353358Sdim// See https://llvm.org/LICENSE.txt for license information. 5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6311536Sdim// 7311536Sdim//===----------------------------------------------------------------------===// 8311536Sdim// 9311536Sdim// This file implements ti_int to quad-precision conversion for the 10311536Sdim// compiler-rt library in the IEEE-754 default round-to-nearest, ties-to-even 11311536Sdim// mode. 12311536Sdim// 13311536Sdim//===----------------------------------------------------------------------===// 14311536Sdim 15311536Sdim#define QUAD_PRECISION 16311536Sdim#include "fp_lib.h" 17311536Sdim#include "int_lib.h" 18311536Sdim 19353358Sdim// Returns: convert a ti_int to a fp_t, rounding toward even. 20311536Sdim 21353358Sdim// Assumption: fp_t is a IEEE 128 bit floating point type 22353358Sdim// ti_int is a 128 bit integral type 23311536Sdim 24353358Sdim// seee eeee eeee eeee mmmm mmmm mmmm mmmm | mmmm mmmm mmmm mmmm mmmm mmmm mmmm 25353358Sdim// mmmm | mmmm mmmm mmmm mmmm mmmm mmmm mmmm mmmm | mmmm mmmm mmmm mmmm mmmm 26353358Sdim// mmmm mmmm mmmm 27311536Sdim 28311536Sdim#if defined(CRT_HAS_128BIT) && defined(CRT_LDBL_128BIT) 29353358SdimCOMPILER_RT_ABI fp_t __floattitf(ti_int a) { 30353358Sdim if (a == 0) 31353358Sdim return 0.0; 32353358Sdim const unsigned N = sizeof(ti_int) * CHAR_BIT; 33353358Sdim const ti_int s = a >> (N - 1); 34353358Sdim a = (a ^ s) - s; 35353358Sdim int sd = N - __clzti2(a); // number of significant digits 36353358Sdim int e = sd - 1; // exponent 37353358Sdim if (sd > LDBL_MANT_DIG) { 38353358Sdim // start: 0000000000000000000001xxxxxxxxxxxxxxxxxxxxxxPQxxxxxxxxxxxxxxxxxx 39353358Sdim // finish: 000000000000000000000000000000000000001xxxxxxxxxxxxxxxxxxxxxxPQR 40353358Sdim // 12345678901234567890123456 41353358Sdim // 1 = msb 1 bit 42353358Sdim // P = bit LDBL_MANT_DIG-1 bits to the right of 1 43353358Sdim // Q = bit LDBL_MANT_DIG bits to the right of 1 44353358Sdim // R = "or" of all bits to the right of Q 45353358Sdim switch (sd) { 46353358Sdim case LDBL_MANT_DIG + 1: 47353358Sdim a <<= 1; 48353358Sdim break; 49353358Sdim case LDBL_MANT_DIG + 2: 50353358Sdim break; 51353358Sdim default: 52353358Sdim a = ((tu_int)a >> (sd - (LDBL_MANT_DIG + 2))) | 53353358Sdim ((a & ((tu_int)(-1) >> ((N + LDBL_MANT_DIG + 2) - sd))) != 0); 54353358Sdim }; 55353358Sdim // finish: 56353358Sdim a |= (a & 4) != 0; // Or P into R 57353358Sdim ++a; // round - this step may add a significant bit 58353358Sdim a >>= 2; // dump Q and R 59353358Sdim // a is now rounded to LDBL_MANT_DIG or LDBL_MANT_DIG+1 bits 60353358Sdim if (a & ((tu_int)1 << LDBL_MANT_DIG)) { 61353358Sdim a >>= 1; 62353358Sdim ++e; 63311536Sdim } 64353358Sdim // a is now rounded to LDBL_MANT_DIG bits 65353358Sdim } else { 66353358Sdim a <<= (LDBL_MANT_DIG - sd); 67353358Sdim // a is now rounded to LDBL_MANT_DIG bits 68353358Sdim } 69311536Sdim 70353358Sdim long_double_bits fb; 71353358Sdim fb.u.high.all = (s & 0x8000000000000000LL) // sign 72353358Sdim | (du_int)(e + 16383) << 48 // exponent 73353358Sdim | ((a >> 64) & 0x0000ffffffffffffLL); // significand 74353358Sdim fb.u.low.all = (du_int)(a); 75353358Sdim return fb.f; 76311536Sdim} 77311536Sdim 78311536Sdim#endif 79