Author: Siva Chandra
Date: 2021-01-19T12:47:54-08:00
New Revision: 7bd3702b64043fb623bf82c1d1a8a2d168142219
URL:
https://github.com/llvm/llvm-project/commit/7bd3702b64043fb623bf82c1d1a8a2d168142219
DIFF:
https://github.com/llvm/llvm-project/commit/7bd3702b64043fb623bf82c1d1a8a2d168142219.diff
LOG: [libc] Extend the current fenv functions to aarch64.
This change does not try to move the common parts of x86 and aarch64 and
build few abstractions over them. While this is possible, x86 story
needs a bit of cleanup, especially around manipulation of the mxcsr
register. Moreover, on x86 one can raise exceptions without performing
exception raising operations. So, all of this can be done in follow up
patches.
Reviewed By: lntue
Differential Revision: https://reviews.llvm.org/D94947
Added:
libc/utils/FPUtil/aarch64/FEnv.h
Modified:
libc/config/linux/aarch64/entrypoints.txt
libc/utils/FPUtil/FEnv.h
Removed:
diff --git a/libc/config/linux/aarch64/entrypoints.txt
b/libc/config/linux/aarch64/entrypoints.txt
index 4e20903ad260..ca7252b17e64 100644
--- a/libc/config/linux/aarch64/entrypoints.txt
+++ b/libc/config/linux/aarch64/entrypoints.txt
@@ -20,6 +20,13 @@ set(TARGET_LIBC_ENTRYPOINTS
# errno.h entrypoints
libc.src.errno.__errno_location
+# fenv.h entrypoints
+libc.src.fenv.feclearexcept
+libc.src.fenv.fegetround
+libc.src.fenv.fesetround
+libc.src.fenv.feraiseexcept
+libc.src.fenv.fetestexcept
+
# stdlib.h entrypoints
libc.src.stdlib.abs
libc.src.stdlib.labs
diff --git a/libc/utils/FPUtil/FEnv.h b/libc/utils/FPUtil/FEnv.h
index bf520672161e..1634f5f10125 100644
--- a/libc/utils/FPUtil/FEnv.h
+++ b/libc/utils/FPUtil/FEnv.h
@@ -11,6 +11,8 @@
#ifdef __x86_64__
#include "x86_64/FEnv.h"
+#elif defined(__aarch64__)
+#include "aarch64/FEnv.h"
#else
#include "DummyFEnv.h"
#endif
diff --git a/libc/utils/FPUtil/aarch64/FEnv.h
b/libc/utils/FPUtil/aarch64/FEnv.h
new file mode 100644
index ..ac0ef70b522d
--- /dev/null
+++ b/libc/utils/FPUtil/aarch64/FEnv.h
@@ -0,0 +1,204 @@
+//===-- aarch64 floating point env manipulation functions ---*- 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_AARCH64_FENV_H
+#define LLVM_LIBC_UTILS_FPUTIL_AARCH64_FENV_H
+
+#include
+#include
+#include
+
+#include "utils/FPUtil/FPBits.h"
+
+namespace __llvm_libc {
+namespace fputil {
+
+struct FEnv {
+ static constexpr uint32_t ToNearest = 0x0;
+ static constexpr uint32_t Upward = 0x1;
+ static constexpr uint32_t Downward = 0x2;
+ static constexpr uint32_t TowardZero = 0x3;
+
+ static constexpr uint32_t Invalid = 0x1;
+ static constexpr uint32_t DivByZero = 0x2;
+ static constexpr uint32_t Overflow = 0x4;
+ static constexpr uint32_t Underflow = 0x8;
+ static constexpr uint32_t Inexact = 0x10;
+
+ // Zero-th bit is the first bit.
+ static constexpr uint32_t RoundingControlBitPosition = 22;
+ static constexpr uint32_t ExceptionStatusFlagsBitPosition = 0;
+ static constexpr uint32_t ExceptionControlFlagsBitPosition = 8;
+
+ static inline uint32_t getStatusValueForExcept(int excepts) {
+return (excepts & FE_INVALID ? Invalid : 0) |
+ (excepts & FE_DIVBYZERO ? DivByZero : 0) |
+ (excepts & FE_OVERFLOW ? Overflow : 0) |
+ (excepts & FE_UNDERFLOW ? Underflow : 0) |
+ (excepts & FE_INEXACT ? Inexact : 0);
+ }
+
+ static inline int exceptionStatusToMacro(uint32_t status) {
+return (status & Invalid ? FE_INVALID : 0) |
+ (status & DivByZero ? FE_DIVBYZERO : 0) |
+ (status & Overflow ? FE_OVERFLOW : 0) |
+ (status & Underflow ? FE_UNDERFLOW : 0) |
+ (status & Inexact ? FE_INEXACT : 0);
+ }
+
+ static uint32_t getControlWord() { return __arm_rsr("fpcr"); }
+
+ static void writeControlWord(uint32_t fpcr) { __arm_wsr("fpcr", fpcr); }
+
+ static uint32_t getStatusWord() { return __arm_rsr("fpsr"); }
+
+ static void writeStatusWord(uint32_t fpsr) { __arm_wsr("fpsr", fpsr); }
+};
+
+static inline int enableExcept(int excepts) {
+ uint32_t newExcepts = FEnv::getStatusValueForExcept(excepts);
+ uint32_t controlWord = FEnv::getControlWord();
+ int oldExcepts =
+ (controlWord >> FEnv::ExceptionControlFlagsBitPosition) & 0x1F;
+ controlWord |= (newExcepts << FEnv::ExceptionControlFlagsBitPosition);
+ FEnv::writeControlWord(controlWord);
+ return FEnv::exceptionStatusToMacro(oldExcepts);
+}
+
+static inline int disableExcept(int excepts) {
+ uint32_t disabledExcepts = FEnv::getStatusValueForExcept(excepts);
+ uint32_t controlWord = FEnv::getControlWord();
+ int oldExcepts