File: LongDoubleBitsX86.h

package info (click to toggle)
llvm-toolchain-13 1%3A13.0.1-11
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 1,418,840 kB
  • sloc: cpp: 5,290,826; ansic: 996,570; asm: 544,593; python: 188,212; objc: 72,027; lisp: 30,291; f90: 25,395; sh: 24,898; javascript: 9,780; pascal: 9,398; perl: 7,484; ml: 5,432; awk: 3,523; makefile: 2,913; xml: 953; cs: 573; fortran: 539
file content (180 lines) | stat: -rw-r--r-- 5,279 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
//===-- Bit representation of x86 long double numbers -----------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_LIBC_UTILS_FPUTIL_LONG_DOUBLE_BITS_X86_H
#define LLVM_LIBC_UTILS_FPUTIL_LONG_DOUBLE_BITS_X86_H

#include "FPBits.h"

#include <stdint.h>

namespace __llvm_libc {
namespace fputil {

template <unsigned Width> struct Padding;

// i386 padding.
template <> struct Padding<4> { static constexpr unsigned value = 16; };

// x86_64 padding.
template <> struct Padding<8> { static constexpr unsigned value = 48; };

template <> union FPBits<long double> {
  using UIntType = __uint128_t;

  static constexpr int exponentBias = 0x3FFF;
  static constexpr int maxExponent = 0x7FFF;
  static constexpr UIntType minSubnormal = UIntType(1);
  // Subnormal numbers include the implicit bit in x86 long double formats.
  static constexpr UIntType maxSubnormal =
      (UIntType(1) << (MantissaWidth<long double>::value)) - 1;
  static constexpr UIntType minNormal =
      (UIntType(3) << MantissaWidth<long double>::value);
  static constexpr UIntType maxNormal =
      ((UIntType(maxExponent) - 1) << (MantissaWidth<long double>::value + 1)) |
      (UIntType(1) << MantissaWidth<long double>::value) | maxSubnormal;

  using FloatProp = FloatProperties<long double>;

  UIntType bits;

  void setMantissa(UIntType mantVal) {
    mantVal &= (FloatProp::mantissaMask);
    bits &= ~(FloatProp::mantissaMask);
    bits |= mantVal;
  }

  UIntType getMantissa() const { return bits & FloatProp::mantissaMask; }

  void setUnbiasedExponent(UIntType expVal) {
    expVal = (expVal << (FloatProp::bitWidth - 1 - FloatProp::exponentWidth)) &
             FloatProp::exponentMask;
    bits &= ~(FloatProp::exponentMask);
    bits |= expVal;
  }

  uint16_t getUnbiasedExponent() const {
    return uint16_t((bits & FloatProp::exponentMask) >>
                    (FloatProp::bitWidth - 1 - FloatProp::exponentWidth));
  }

  void setImplicitBit(bool implicitVal) {
    bits &= ~(UIntType(1) << FloatProp::mantissaWidth);
    bits |= (UIntType(implicitVal) << FloatProp::mantissaWidth);
  }

  bool getImplicitBit() const {
    return ((bits & (UIntType(1) << FloatProp::mantissaWidth)) >>
            FloatProp::mantissaWidth);
  }

  void setSign(bool signVal) {
    bits &= ~(FloatProp::signMask);
    UIntType sign1 = UIntType(signVal) << (FloatProp::bitWidth - 1);
    bits |= sign1;
  }

  bool getSign() const {
    return ((bits & FloatProp::signMask) >> (FloatProp::bitWidth - 1));
  }

  long double val;

  FPBits() : bits(0) {}

  template <typename XType,
            cpp::EnableIfType<cpp::IsSame<long double, XType>::Value, int> = 0>
  explicit FPBits(XType x) : val(x) {}

  template <typename XType,
            cpp::EnableIfType<cpp::IsSame<XType, UIntType>::Value, int> = 0>
  explicit FPBits(XType x) : bits(x) {}

  operator long double() { return val; }

  UIntType uintval() {
    // We zero the padding bits as they can contain garbage.
    static constexpr UIntType mask =
        (UIntType(1) << (sizeof(long double) * 8 -
                         Padding<sizeof(uintptr_t)>::value)) -
        1;
    return bits & mask;
  }

  int getExponent() const {
    if (getUnbiasedExponent() == 0)
      return int(1) - exponentBias;
    return int(getUnbiasedExponent()) - exponentBias;
  }

  bool isZero() const {
    return getUnbiasedExponent() == 0 && getMantissa() == 0 &&
           getImplicitBit() == 0;
  }

  bool isInf() const {
    return getUnbiasedExponent() == maxExponent && getMantissa() == 0 &&
           getImplicitBit() == 1;
  }

  bool isNaN() const {
    if (getUnbiasedExponent() == maxExponent) {
      return (getImplicitBit() == 0) || getMantissa() != 0;
    } else if (getUnbiasedExponent() != 0) {
      return getImplicitBit() == 0;
    }
    return false;
  }

  bool isInfOrNaN() const {
    return (getUnbiasedExponent() == maxExponent) ||
           (getUnbiasedExponent() != 0 && getImplicitBit() == 0);
  }

  // Methods below this are used by tests.

  static FPBits<long double> zero() { return FPBits<long double>(0.0l); }

  static FPBits<long double> negZero() {
    FPBits<long double> bits(0.0l);
    bits.setSign(1);
    return bits;
  }

  static FPBits<long double> inf() {
    FPBits<long double> bits(0.0l);
    bits.setUnbiasedExponent(maxExponent);
    bits.setImplicitBit(1);
    return bits;
  }

  static FPBits<long double> negInf() {
    FPBits<long double> bits(0.0l);
    bits.setUnbiasedExponent(maxExponent);
    bits.setImplicitBit(1);
    bits.setSign(1);
    return bits;
  }

  static long double buildNaN(UIntType v) {
    FPBits<long double> bits(0.0l);
    bits.setUnbiasedExponent(maxExponent);
    bits.setImplicitBit(1);
    bits.setMantissa(v);
    return bits;
  }
};

static_assert(
    sizeof(FPBits<long double>) == sizeof(long double),
    "Internal long double representation does not match the machine format.");

} // namespace fputil
} // namespace __llvm_libc

#endif // LLVM_LIBC_UTILS_FPUTIL_LONG_DOUBLE_BITS_X86_H