xref: /llvm-project/libc/src/__support/FPUtil/arm/FEnvImpl.h (revision 5ff3ff33ff930e4ec49da7910612d8a41eb068cb)
1ae8e1b8fSSiva Chandra Reddy //===-- arm floating point env manipulation functions -----------*- C++ -*-===//
2ae8e1b8fSSiva Chandra Reddy //
3ae8e1b8fSSiva Chandra Reddy // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4ae8e1b8fSSiva Chandra Reddy // See https://llvm.org/LICENSE.txt for license information.
5ae8e1b8fSSiva Chandra Reddy // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6ae8e1b8fSSiva Chandra Reddy //
7ae8e1b8fSSiva Chandra Reddy //===----------------------------------------------------------------------===//
8ae8e1b8fSSiva Chandra Reddy 
9270547f3SGuillaume Chatelet #ifndef LLVM_LIBC_SRC___SUPPORT_FPUTIL_ARM_FENVIMPL_H
10270547f3SGuillaume Chatelet #define LLVM_LIBC_SRC___SUPPORT_FPUTIL_ARM_FENVIMPL_H
11ae8e1b8fSSiva Chandra Reddy 
1249561181SJob Henandez Lara #include "hdr/fenv_macros.h"
1375bbf4ddSJob Henandez Lara #include "hdr/types/fenv_t.h"
14ae8e1b8fSSiva Chandra Reddy #include "src/__support/FPUtil/FPBits.h"
156899f035Slntue #include "src/__support/macros/attributes.h" // For LIBC_INLINE
16*5ff3ff33SPetr Hosek #include "src/__support/macros/config.h"
17ae8e1b8fSSiva Chandra Reddy #include <stdint.h>
18ae8e1b8fSSiva Chandra Reddy 
19*5ff3ff33SPetr Hosek namespace LIBC_NAMESPACE_DECL {
20ae8e1b8fSSiva Chandra Reddy namespace fputil {
21ae8e1b8fSSiva Chandra Reddy 
22ae8e1b8fSSiva Chandra Reddy struct FEnv {
23ae8e1b8fSSiva Chandra Reddy   // Arm floating point state is all stored in a single 32-bit register named
24ae8e1b8fSSiva Chandra Reddy   // fpscr.
25ae8e1b8fSSiva Chandra Reddy   uint32_t fpscr;
26ae8e1b8fSSiva Chandra Reddy   static constexpr uint32_t RoundingControlBitPosition = 22;
27ae8e1b8fSSiva Chandra Reddy   static constexpr uint32_t ExceptionControlBitPosition = 8;
28ae8e1b8fSSiva Chandra Reddy 
29ae8e1b8fSSiva Chandra Reddy   static constexpr uint32_t TONEAREST = 0x0;
30ae8e1b8fSSiva Chandra Reddy   static constexpr uint32_t UPWARD = 0x1;
31ae8e1b8fSSiva Chandra Reddy   static constexpr uint32_t DOWNWARD = 0x2;
32ae8e1b8fSSiva Chandra Reddy   static constexpr uint32_t TOWARDZERO = 0x3;
33ae8e1b8fSSiva Chandra Reddy 
34ae8e1b8fSSiva Chandra Reddy   static constexpr uint32_t INVALID_ENABLE = 0x1;
35ae8e1b8fSSiva Chandra Reddy   static constexpr uint32_t DIVBYZERO_ENABLE = 0x2;
36ae8e1b8fSSiva Chandra Reddy   static constexpr uint32_t OVERFLOW_ENABLE = 0x4;
37ae8e1b8fSSiva Chandra Reddy   static constexpr uint32_t UNDERFLOW_ENABLE = 0x8;
38ae8e1b8fSSiva Chandra Reddy   static constexpr uint32_t INEXACT_ENABLE = 0x10;
39ae8e1b8fSSiva Chandra Reddy   static constexpr uint32_t DENORMAL_ENABLE = 0x20;
40ae8e1b8fSSiva Chandra Reddy 
41ae8e1b8fSSiva Chandra Reddy   static constexpr uint32_t INVALID_STATUS = 0x1;
42ae8e1b8fSSiva Chandra Reddy   static constexpr uint32_t DIVBYZERO_STATUS = 0x2;
43ae8e1b8fSSiva Chandra Reddy   static constexpr uint32_t OVERFLOW_STATUS = 0x4;
44ae8e1b8fSSiva Chandra Reddy   static constexpr uint32_t UNDERFLOW_STATUS = 0x8;
45ae8e1b8fSSiva Chandra Reddy   static constexpr uint32_t INEXACT_STATUS = 0x10;
46ae8e1b8fSSiva Chandra Reddy   static constexpr uint32_t DENORMAL_STATUS = 0x80;
47ae8e1b8fSSiva Chandra Reddy 
48ae8e1b8fSSiva Chandra Reddy   LIBC_INLINE static uint32_t get_fpscr() { return __builtin_arm_get_fpscr(); }
49ae8e1b8fSSiva Chandra Reddy   LIBC_INLINE static void set_fpscr(uint32_t val) {
50ae8e1b8fSSiva Chandra Reddy     __builtin_arm_set_fpscr(val);
51ae8e1b8fSSiva Chandra Reddy   }
52ae8e1b8fSSiva Chandra Reddy 
53ae8e1b8fSSiva Chandra Reddy   LIBC_INLINE static int exception_enable_bits_to_macro(uint32_t status) {
54a98a6e95Sluolent     return ((status & INVALID_ENABLE) ? FE_INVALID : 0) |
55a98a6e95Sluolent            ((status & DIVBYZERO_ENABLE) ? FE_DIVBYZERO : 0) |
56a98a6e95Sluolent            ((status & OVERFLOW_ENABLE) ? FE_OVERFLOW : 0) |
57a98a6e95Sluolent            ((status & UNDERFLOW_ENABLE) ? FE_UNDERFLOW : 0) |
58a98a6e95Sluolent            ((status & INEXACT_ENABLE) ? FE_INEXACT : 0);
59ae8e1b8fSSiva Chandra Reddy   }
60ae8e1b8fSSiva Chandra Reddy 
61ae8e1b8fSSiva Chandra Reddy   LIBC_INLINE static uint32_t exception_macro_to_enable_bits(int except) {
62a98a6e95Sluolent     return ((except & FE_INVALID) ? INVALID_ENABLE : 0) |
63a98a6e95Sluolent            ((except & FE_DIVBYZERO) ? DIVBYZERO_ENABLE : 0) |
64a98a6e95Sluolent            ((except & FE_OVERFLOW) ? OVERFLOW_ENABLE : 0) |
65a98a6e95Sluolent            ((except & FE_UNDERFLOW) ? UNDERFLOW_ENABLE : 0) |
66a98a6e95Sluolent            ((except & FE_INEXACT) ? INEXACT_ENABLE : 0);
67ae8e1b8fSSiva Chandra Reddy   }
68ae8e1b8fSSiva Chandra Reddy 
69ae8e1b8fSSiva Chandra Reddy   LIBC_INLINE static uint32_t exception_macro_to_status_bits(int except) {
70a98a6e95Sluolent     return ((except & FE_INVALID) ? INVALID_STATUS : 0) |
71a98a6e95Sluolent            ((except & FE_DIVBYZERO) ? DIVBYZERO_STATUS : 0) |
72a98a6e95Sluolent            ((except & FE_OVERFLOW) ? OVERFLOW_STATUS : 0) |
73a98a6e95Sluolent            ((except & FE_UNDERFLOW) ? UNDERFLOW_STATUS : 0) |
74a98a6e95Sluolent            ((except & FE_INEXACT) ? INEXACT_STATUS : 0);
75ae8e1b8fSSiva Chandra Reddy   }
76ae8e1b8fSSiva Chandra Reddy 
77ae8e1b8fSSiva Chandra Reddy   LIBC_INLINE static uint32_t exception_status_bits_to_macro(int status) {
78a98a6e95Sluolent     return ((status & INVALID_STATUS) ? FE_INVALID : 0) |
79a98a6e95Sluolent            ((status & DIVBYZERO_STATUS) ? FE_DIVBYZERO : 0) |
80a98a6e95Sluolent            ((status & OVERFLOW_STATUS) ? FE_OVERFLOW : 0) |
81a98a6e95Sluolent            ((status & UNDERFLOW_STATUS) ? FE_UNDERFLOW : 0) |
82a98a6e95Sluolent            ((status & INEXACT_STATUS) ? FE_INEXACT : 0);
83ae8e1b8fSSiva Chandra Reddy   }
84ae8e1b8fSSiva Chandra Reddy };
85ae8e1b8fSSiva Chandra Reddy 
86ae8e1b8fSSiva Chandra Reddy // Enables exceptions in |excepts| and returns the previously set exceptions.
87ae8e1b8fSSiva Chandra Reddy LIBC_INLINE int enable_except(int excepts) {
88ae8e1b8fSSiva Chandra Reddy   uint32_t new_excepts = FEnv::exception_macro_to_enable_bits(excepts);
89ae8e1b8fSSiva Chandra Reddy   uint32_t fpscr = FEnv::get_fpscr();
90ae8e1b8fSSiva Chandra Reddy   int old = (fpscr >> FEnv::ExceptionControlBitPosition) & 0x3F;
91ae8e1b8fSSiva Chandra Reddy   fpscr |= (new_excepts << FEnv::ExceptionControlBitPosition);
92ae8e1b8fSSiva Chandra Reddy   FEnv::set_fpscr(fpscr);
93ae8e1b8fSSiva Chandra Reddy   return FEnv::exception_enable_bits_to_macro(old);
94ae8e1b8fSSiva Chandra Reddy }
95ae8e1b8fSSiva Chandra Reddy 
96ae8e1b8fSSiva Chandra Reddy // Disables exceptions in |excepts| and returns the previously set exceptions.
97ae8e1b8fSSiva Chandra Reddy LIBC_INLINE int disable_except(int excepts) {
98ae8e1b8fSSiva Chandra Reddy   uint32_t disable_bits = FEnv::exception_macro_to_enable_bits(excepts);
99ae8e1b8fSSiva Chandra Reddy   uint32_t fpscr = FEnv::get_fpscr();
100ae8e1b8fSSiva Chandra Reddy   int old = (fpscr >> FEnv::ExceptionControlBitPosition) & 0x3F;
101ae8e1b8fSSiva Chandra Reddy   fpscr &= ~(disable_bits << FEnv::ExceptionControlBitPosition);
102ae8e1b8fSSiva Chandra Reddy   FEnv::set_fpscr(fpscr);
103ae8e1b8fSSiva Chandra Reddy   return FEnv::exception_enable_bits_to_macro(old);
104ae8e1b8fSSiva Chandra Reddy }
105ae8e1b8fSSiva Chandra Reddy 
106ae8e1b8fSSiva Chandra Reddy // Returns the currently enabled exceptions.
107ae8e1b8fSSiva Chandra Reddy LIBC_INLINE int get_except() {
108ae8e1b8fSSiva Chandra Reddy   uint32_t fpscr = FEnv::get_fpscr();
109ae8e1b8fSSiva Chandra Reddy   int enabled_excepts = (fpscr >> FEnv::ExceptionControlBitPosition) & 0x3F;
110ae8e1b8fSSiva Chandra Reddy   return FEnv::exception_enable_bits_to_macro(enabled_excepts);
111ae8e1b8fSSiva Chandra Reddy }
112ae8e1b8fSSiva Chandra Reddy 
113ae8e1b8fSSiva Chandra Reddy // Clears the exceptions in |excepts|.
114ae8e1b8fSSiva Chandra Reddy LIBC_INLINE int clear_except(int excepts) {
115ae8e1b8fSSiva Chandra Reddy   uint32_t fpscr = FEnv::get_fpscr();
116ae8e1b8fSSiva Chandra Reddy   uint32_t to_clear = FEnv::exception_macro_to_status_bits(excepts);
117ae8e1b8fSSiva Chandra Reddy   fpscr &= ~to_clear;
118ae8e1b8fSSiva Chandra Reddy   FEnv::set_fpscr(fpscr);
119ae8e1b8fSSiva Chandra Reddy   return 0;
120ae8e1b8fSSiva Chandra Reddy }
121ae8e1b8fSSiva Chandra Reddy 
122ae8e1b8fSSiva Chandra Reddy // Returns the set of exceptions which are from the input set |excepts|.
123ae8e1b8fSSiva Chandra Reddy LIBC_INLINE int test_except(int excepts) {
124ae8e1b8fSSiva Chandra Reddy   uint32_t to_test = FEnv::exception_macro_to_status_bits(excepts);
125ae8e1b8fSSiva Chandra Reddy   uint32_t fpscr = FEnv::get_fpscr();
126ae8e1b8fSSiva Chandra Reddy   return FEnv::exception_status_bits_to_macro(fpscr & 0x9F & to_test);
127ae8e1b8fSSiva Chandra Reddy }
128ae8e1b8fSSiva Chandra Reddy 
129ae8e1b8fSSiva Chandra Reddy // Set the exceptions in |excepts|.
130ae8e1b8fSSiva Chandra Reddy LIBC_INLINE int set_except(int excepts) {
131ae8e1b8fSSiva Chandra Reddy   uint32_t fpscr = FEnv::get_fpscr();
132ae8e1b8fSSiva Chandra Reddy   FEnv::set_fpscr(fpscr | FEnv::exception_macro_to_status_bits(excepts));
133ae8e1b8fSSiva Chandra Reddy   return 0;
134ae8e1b8fSSiva Chandra Reddy }
135ae8e1b8fSSiva Chandra Reddy 
136ae8e1b8fSSiva Chandra Reddy LIBC_INLINE int raise_except(int excepts) {
137ae8e1b8fSSiva Chandra Reddy   float zero = 0.0f;
138ae8e1b8fSSiva Chandra Reddy   float one = 1.0f;
1393a9ff323Slntue   float large_value = FPBits<float>::max_normal().get_val();
1403a9ff323Slntue   float small_value = FPBits<float>::min_normal().get_val();
141ae8e1b8fSSiva Chandra Reddy   auto divfunc = [](float a, float b) {
142ae8e1b8fSSiva Chandra Reddy     __asm__ __volatile__("flds  s0, %0\n\t"
143ae8e1b8fSSiva Chandra Reddy                          "flds  s1, %1\n\t"
144ae8e1b8fSSiva Chandra Reddy                          "fdivs s0, s0, s1\n\t"
145ae8e1b8fSSiva Chandra Reddy                          : // No outputs
146ae8e1b8fSSiva Chandra Reddy                          : "m"(a), "m"(b)
147ae8e1b8fSSiva Chandra Reddy                          : "s0", "s1" /* s0 and s1 are clobbered */);
148ae8e1b8fSSiva Chandra Reddy   };
149ae8e1b8fSSiva Chandra Reddy 
150ae8e1b8fSSiva Chandra Reddy   uint32_t to_raise = FEnv::exception_macro_to_status_bits(excepts);
151ae8e1b8fSSiva Chandra Reddy   int result = 0;
152ae8e1b8fSSiva Chandra Reddy 
153ae8e1b8fSSiva Chandra Reddy   if (to_raise & FEnv::INVALID_STATUS) {
154ae8e1b8fSSiva Chandra Reddy     divfunc(zero, zero);
155ae8e1b8fSSiva Chandra Reddy     uint32_t fpscr = FEnv::get_fpscr();
156ae8e1b8fSSiva Chandra Reddy     if (!(fpscr & FEnv::INVALID_STATUS))
157ae8e1b8fSSiva Chandra Reddy       result = -1;
158ae8e1b8fSSiva Chandra Reddy   }
159ae8e1b8fSSiva Chandra Reddy   if (to_raise & FEnv::DIVBYZERO_STATUS) {
160ae8e1b8fSSiva Chandra Reddy     divfunc(one, zero);
161ae8e1b8fSSiva Chandra Reddy     uint32_t fpscr = FEnv::get_fpscr();
162ae8e1b8fSSiva Chandra Reddy     if (!(fpscr & FEnv::DIVBYZERO_STATUS))
163ae8e1b8fSSiva Chandra Reddy       result = -1;
164ae8e1b8fSSiva Chandra Reddy   }
165ae8e1b8fSSiva Chandra Reddy   if (to_raise & FEnv::OVERFLOW_STATUS) {
166ae8e1b8fSSiva Chandra Reddy     divfunc(large_value, small_value);
167ae8e1b8fSSiva Chandra Reddy     uint32_t fpscr = FEnv::get_fpscr();
168ae8e1b8fSSiva Chandra Reddy     if (!(fpscr & FEnv::OVERFLOW_STATUS))
169ae8e1b8fSSiva Chandra Reddy       result = -1;
170ae8e1b8fSSiva Chandra Reddy   }
171ae8e1b8fSSiva Chandra Reddy   if (to_raise & FEnv::UNDERFLOW_STATUS) {
172ae8e1b8fSSiva Chandra Reddy     divfunc(small_value, large_value);
173ae8e1b8fSSiva Chandra Reddy     uint32_t fpscr = FEnv::get_fpscr();
174ae8e1b8fSSiva Chandra Reddy     if (!(fpscr & FEnv::UNDERFLOW_STATUS))
175ae8e1b8fSSiva Chandra Reddy       result = -1;
176ae8e1b8fSSiva Chandra Reddy   }
177ae8e1b8fSSiva Chandra Reddy   if (to_raise & FEnv::INEXACT_STATUS) {
178ae8e1b8fSSiva Chandra Reddy     float two = 2.0f;
179ae8e1b8fSSiva Chandra Reddy     float three = 3.0f;
180ae8e1b8fSSiva Chandra Reddy     // 2.0 / 3.0 cannot be represented exactly in any radix 2 floating point
181ae8e1b8fSSiva Chandra Reddy     // format.
182ae8e1b8fSSiva Chandra Reddy     divfunc(two, three);
183ae8e1b8fSSiva Chandra Reddy     uint32_t fpscr = FEnv::get_fpscr();
184ae8e1b8fSSiva Chandra Reddy     if (!(fpscr & FEnv::INEXACT_STATUS))
185ae8e1b8fSSiva Chandra Reddy       result = -1;
186ae8e1b8fSSiva Chandra Reddy   }
187ae8e1b8fSSiva Chandra Reddy   return result;
188ae8e1b8fSSiva Chandra Reddy }
189ae8e1b8fSSiva Chandra Reddy 
190ae8e1b8fSSiva Chandra Reddy LIBC_INLINE int get_round() {
191ae8e1b8fSSiva Chandra Reddy   uint32_t mode = (FEnv::get_fpscr() >> FEnv::RoundingControlBitPosition) & 0x3;
192ae8e1b8fSSiva Chandra Reddy   switch (mode) {
193ae8e1b8fSSiva Chandra Reddy   case FEnv::TONEAREST:
194ae8e1b8fSSiva Chandra Reddy     return FE_TONEAREST;
195ae8e1b8fSSiva Chandra Reddy   case FEnv::DOWNWARD:
196ae8e1b8fSSiva Chandra Reddy     return FE_DOWNWARD;
197ae8e1b8fSSiva Chandra Reddy   case FEnv::UPWARD:
198ae8e1b8fSSiva Chandra Reddy     return FE_UPWARD;
199ae8e1b8fSSiva Chandra Reddy   case FEnv::TOWARDZERO:
200ae8e1b8fSSiva Chandra Reddy     return FE_TOWARDZERO;
201ae8e1b8fSSiva Chandra Reddy   default:
202ae8e1b8fSSiva Chandra Reddy     return -1; // Error value.
203ae8e1b8fSSiva Chandra Reddy   }
204ae8e1b8fSSiva Chandra Reddy   return 0;
205ae8e1b8fSSiva Chandra Reddy }
206ae8e1b8fSSiva Chandra Reddy 
207ae8e1b8fSSiva Chandra Reddy LIBC_INLINE int set_round(int mode) {
208ae8e1b8fSSiva Chandra Reddy   uint16_t bits;
209ae8e1b8fSSiva Chandra Reddy   switch (mode) {
210ae8e1b8fSSiva Chandra Reddy   case FE_TONEAREST:
211ae8e1b8fSSiva Chandra Reddy     bits = FEnv::TONEAREST;
212ae8e1b8fSSiva Chandra Reddy     break;
213ae8e1b8fSSiva Chandra Reddy   case FE_DOWNWARD:
214ae8e1b8fSSiva Chandra Reddy     bits = FEnv::DOWNWARD;
215ae8e1b8fSSiva Chandra Reddy     break;
216ae8e1b8fSSiva Chandra Reddy   case FE_UPWARD:
217ae8e1b8fSSiva Chandra Reddy     bits = FEnv::UPWARD;
218ae8e1b8fSSiva Chandra Reddy     break;
219ae8e1b8fSSiva Chandra Reddy   case FE_TOWARDZERO:
220ae8e1b8fSSiva Chandra Reddy     bits = FEnv::TOWARDZERO;
221ae8e1b8fSSiva Chandra Reddy     break;
222ae8e1b8fSSiva Chandra Reddy   default:
223ae8e1b8fSSiva Chandra Reddy     return 1; // To indicate failure
224ae8e1b8fSSiva Chandra Reddy   }
225ae8e1b8fSSiva Chandra Reddy 
226ae8e1b8fSSiva Chandra Reddy   uint32_t fpscr = FEnv::get_fpscr();
227ae8e1b8fSSiva Chandra Reddy   fpscr &= ~(0x3 << FEnv::RoundingControlBitPosition);
228ae8e1b8fSSiva Chandra Reddy   fpscr |= (bits << FEnv::RoundingControlBitPosition);
229ae8e1b8fSSiva Chandra Reddy   FEnv::set_fpscr(fpscr);
230ae8e1b8fSSiva Chandra Reddy 
231ae8e1b8fSSiva Chandra Reddy   return 0;
232ae8e1b8fSSiva Chandra Reddy }
233ae8e1b8fSSiva Chandra Reddy 
234ae8e1b8fSSiva Chandra Reddy LIBC_INLINE int get_env(fenv_t *envp) {
235ae8e1b8fSSiva Chandra Reddy   FEnv *state = reinterpret_cast<FEnv *>(envp);
236ae8e1b8fSSiva Chandra Reddy   state->fpscr = FEnv::get_fpscr();
237ae8e1b8fSSiva Chandra Reddy   return 0;
238ae8e1b8fSSiva Chandra Reddy }
239ae8e1b8fSSiva Chandra Reddy 
240ae8e1b8fSSiva Chandra Reddy LIBC_INLINE int set_env(const fenv_t *envp) {
241ae8e1b8fSSiva Chandra Reddy   if (envp == FE_DFL_ENV) {
242ae8e1b8fSSiva Chandra Reddy     uint32_t fpscr = FEnv::get_fpscr();
243ae8e1b8fSSiva Chandra Reddy     // Default status implies:
244ae8e1b8fSSiva Chandra Reddy     // 1. Round to nearest rounding mode.
245ae8e1b8fSSiva Chandra Reddy     fpscr &= ~(0x3 << FEnv::RoundingControlBitPosition);
246ae8e1b8fSSiva Chandra Reddy     fpscr |= (FEnv::TONEAREST << FEnv::RoundingControlBitPosition);
247ae8e1b8fSSiva Chandra Reddy     // 2. All exceptions are disabled.
248ae8e1b8fSSiva Chandra Reddy     fpscr &= ~(0x3F << FEnv::ExceptionControlBitPosition);
249ae8e1b8fSSiva Chandra Reddy     // 3. All exceptions are cleared. There are two reserved bits
250ae8e1b8fSSiva Chandra Reddy     // at bit 5 and 6 so we just write one full byte (6 bits for
251ae8e1b8fSSiva Chandra Reddy     // the exceptions, and 2 reserved bits.)
252ae8e1b8fSSiva Chandra Reddy     fpscr &= ~(static_cast<uint32_t>(0xFF));
253ae8e1b8fSSiva Chandra Reddy 
254ae8e1b8fSSiva Chandra Reddy     FEnv::set_fpscr(fpscr);
255ae8e1b8fSSiva Chandra Reddy     return 0;
256ae8e1b8fSSiva Chandra Reddy   }
257ae8e1b8fSSiva Chandra Reddy 
258ae8e1b8fSSiva Chandra Reddy   const FEnv *state = reinterpret_cast<const FEnv *>(envp);
259ae8e1b8fSSiva Chandra Reddy   FEnv::set_fpscr(state->fpscr);
260ae8e1b8fSSiva Chandra Reddy   return 0;
261ae8e1b8fSSiva Chandra Reddy }
262ae8e1b8fSSiva Chandra Reddy 
263ae8e1b8fSSiva Chandra Reddy } // namespace fputil
264*5ff3ff33SPetr Hosek } // namespace LIBC_NAMESPACE_DECL
265ae8e1b8fSSiva Chandra Reddy 
266270547f3SGuillaume Chatelet #endif // LLVM_LIBC_SRC___SUPPORT_FPUTIL_ARM_FENVIMPL_H
267