xref: /freebsd-src/contrib/llvm-project/compiler-rt/lib/builtins/arm/fp_mode.c (revision 68d75eff68281c1b445e3010bb975eae07aac225)
1*68d75effSDimitry Andric //===----- lib/arm/fp_mode.c - Floaing-point mode utilities -------*- C -*-===//
2*68d75effSDimitry Andric //
3*68d75effSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*68d75effSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*68d75effSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*68d75effSDimitry Andric //
7*68d75effSDimitry Andric //===----------------------------------------------------------------------===//
8*68d75effSDimitry Andric 
9*68d75effSDimitry Andric #include <stdint.h>
10*68d75effSDimitry Andric 
11*68d75effSDimitry Andric #include "../fp_mode.h"
12*68d75effSDimitry Andric 
13*68d75effSDimitry Andric #define ARM_TONEAREST  0x0
14*68d75effSDimitry Andric #define ARM_UPWARD     0x1
15*68d75effSDimitry Andric #define ARM_DOWNWARD   0x2
16*68d75effSDimitry Andric #define ARM_TOWARDZERO 0x3
17*68d75effSDimitry Andric #define ARM_RMODE_MASK (ARM_TONEAREST | ARM_UPWARD | \
18*68d75effSDimitry Andric                         ARM_DOWNWARD | ARM_TOWARDZERO)
19*68d75effSDimitry Andric #define ARM_RMODE_SHIFT 22
20*68d75effSDimitry Andric 
21*68d75effSDimitry Andric #define ARM_INEXACT     0x1000
22*68d75effSDimitry Andric 
23*68d75effSDimitry Andric #ifndef __ARM_FP
24*68d75effSDimitry Andric // For soft float targets, allow changing rounding mode by overriding the weak
25*68d75effSDimitry Andric // __arm_fe_default_rmode symbol.
26*68d75effSDimitry Andric FE_ROUND_MODE __attribute__((weak)) __arm_fe_default_rmode = FE_TONEAREST;
27*68d75effSDimitry Andric #endif
28*68d75effSDimitry Andric 
29*68d75effSDimitry Andric FE_ROUND_MODE __fe_getround() {
30*68d75effSDimitry Andric #ifdef __ARM_FP
31*68d75effSDimitry Andric   uint32_t fpscr;
32*68d75effSDimitry Andric   __asm__ __volatile__("vmrs  %0, fpscr" : "=r" (fpscr));
33*68d75effSDimitry Andric   fpscr = fpscr >> ARM_RMODE_SHIFT & ARM_RMODE_MASK;
34*68d75effSDimitry Andric   switch (fpscr) {
35*68d75effSDimitry Andric     case ARM_UPWARD:
36*68d75effSDimitry Andric       return FE_UPWARD;
37*68d75effSDimitry Andric     case ARM_DOWNWARD:
38*68d75effSDimitry Andric       return FE_DOWNWARD;
39*68d75effSDimitry Andric     case ARM_TOWARDZERO:
40*68d75effSDimitry Andric       return FE_TOWARDZERO;
41*68d75effSDimitry Andric     case ARM_TONEAREST:
42*68d75effSDimitry Andric     default:
43*68d75effSDimitry Andric       return FE_TONEAREST;
44*68d75effSDimitry Andric   }
45*68d75effSDimitry Andric #else
46*68d75effSDimitry Andric   return __arm_fe_default_rmode;
47*68d75effSDimitry Andric #endif
48*68d75effSDimitry Andric }
49*68d75effSDimitry Andric 
50*68d75effSDimitry Andric int __fe_raise_inexact() {
51*68d75effSDimitry Andric #ifdef __ARM_FP
52*68d75effSDimitry Andric   uint32_t fpscr;
53*68d75effSDimitry Andric   __asm__ __volatile__("vmrs  %0, fpscr" : "=r" (fpscr));
54*68d75effSDimitry Andric   __asm__ __volatile__("vmsr  fpscr, %0" : : "ri" (fpscr | ARM_INEXACT));
55*68d75effSDimitry Andric   return 0;
56*68d75effSDimitry Andric #else
57*68d75effSDimitry Andric   return 0;
58*68d75effSDimitry Andric #endif
59*68d75effSDimitry Andric }
60