xref: /llvm-project/compiler-rt/lib/builtins/arm/fp_mode.c (revision bdbfaf0ca7c069192c1d05094c0517b4e52a4773)
133b8a553SYi Kong //===----- lib/arm/fp_mode.c - Floaing-point mode utilities -------*- C -*-===//
233b8a553SYi Kong //
333b8a553SYi Kong // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
433b8a553SYi Kong // See https://llvm.org/LICENSE.txt for license information.
533b8a553SYi Kong // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
633b8a553SYi Kong //
733b8a553SYi Kong //===----------------------------------------------------------------------===//
833b8a553SYi Kong 
933b8a553SYi Kong #include <stdint.h>
1033b8a553SYi Kong 
1133b8a553SYi Kong #include "../fp_mode.h"
1233b8a553SYi Kong 
1333b8a553SYi Kong #define ARM_TONEAREST  0x0
1433b8a553SYi Kong #define ARM_UPWARD     0x1
1533b8a553SYi Kong #define ARM_DOWNWARD   0x2
1633b8a553SYi Kong #define ARM_TOWARDZERO 0x3
1733b8a553SYi Kong #define ARM_RMODE_MASK (ARM_TONEAREST | ARM_UPWARD | \
1833b8a553SYi Kong                         ARM_DOWNWARD | ARM_TOWARDZERO)
1933b8a553SYi Kong #define ARM_RMODE_SHIFT 22
2033b8a553SYi Kong 
21e2cd2f7dSAlex Richardson #define ARM_INEXACT     0x10
2233b8a553SYi Kong 
2333b8a553SYi Kong #ifndef __ARM_FP
2433b8a553SYi Kong // For soft float targets, allow changing rounding mode by overriding the weak
2533b8a553SYi Kong // __arm_fe_default_rmode symbol.
26ed0bf875SAlex Richardson CRT_FE_ROUND_MODE __attribute__((weak)) __arm_fe_default_rmode =
27ed0bf875SAlex Richardson     CRT_FE_TONEAREST;
2833b8a553SYi Kong #endif
2933b8a553SYi Kong 
__fe_getround(void)30*bdbfaf0cSAaron Ballman CRT_FE_ROUND_MODE __fe_getround(void) {
3133b8a553SYi Kong #ifdef __ARM_FP
3233b8a553SYi Kong   uint32_t fpscr;
3333b8a553SYi Kong   __asm__ __volatile__("vmrs  %0, fpscr" : "=r" (fpscr));
3433b8a553SYi Kong   fpscr = fpscr >> ARM_RMODE_SHIFT & ARM_RMODE_MASK;
3533b8a553SYi Kong   switch (fpscr) {
3633b8a553SYi Kong     case ARM_UPWARD:
37ed0bf875SAlex Richardson       return CRT_FE_UPWARD;
3833b8a553SYi Kong     case ARM_DOWNWARD:
39ed0bf875SAlex Richardson       return CRT_FE_DOWNWARD;
4033b8a553SYi Kong     case ARM_TOWARDZERO:
41ed0bf875SAlex Richardson       return CRT_FE_TOWARDZERO;
4233b8a553SYi Kong     case ARM_TONEAREST:
4333b8a553SYi Kong     default:
44ed0bf875SAlex Richardson       return CRT_FE_TONEAREST;
4533b8a553SYi Kong   }
4633b8a553SYi Kong #else
4733b8a553SYi Kong   return __arm_fe_default_rmode;
4833b8a553SYi Kong #endif
4933b8a553SYi Kong }
5033b8a553SYi Kong 
__fe_raise_inexact(void)51*bdbfaf0cSAaron Ballman int __fe_raise_inexact(void) {
5233b8a553SYi Kong #ifdef __ARM_FP
5333b8a553SYi Kong   uint32_t fpscr;
5433b8a553SYi Kong   __asm__ __volatile__("vmrs  %0, fpscr" : "=r" (fpscr));
5533b8a553SYi Kong   __asm__ __volatile__("vmsr  fpscr, %0" : : "ri" (fpscr | ARM_INEXACT));
5633b8a553SYi Kong   return 0;
5733b8a553SYi Kong #else
5833b8a553SYi Kong   return 0;
5933b8a553SYi Kong #endif
6033b8a553SYi Kong }
61