syslog: Improve fortify with clang
[glibc.git] / sysdeps / riscv / rvf / fenv_private.h
blobe8fa6ab25914295e24ef83e9b36d769bd8378a19
1 /* Private floating point rounding and exceptions handling. RISC-V version.
2 Copyright (C) 2014-2024 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, see
17 <https://www.gnu.org/licenses/>. */
19 #ifndef RISCV_FENV_PRIVATE_H
20 #define RISCV_FENV_PRIVATE_H 1
22 #include <fenv.h>
23 #include <fpu_control.h>
24 #include <get-rounding-mode.h>
26 static __always_inline int
27 riscv_getround (void)
29 return get_rounding_mode ();
32 static __always_inline void
33 riscv_setround (int rm)
35 asm volatile ("fsrm %z0" : : "rJ" (rm));
38 static __always_inline int
39 riscv_getflags (void)
41 int flags;
42 asm volatile ("frflags %0" : "=r" (flags));
43 return flags;
46 static __always_inline void
47 riscv_setflags (int flags)
49 asm volatile ("fsflags %z0" : : "rJ" (flags));
52 static __always_inline void
53 libc_feholdexcept_riscv (fenv_t *envp)
55 asm volatile ("csrrc %0, fcsr, %1" : "=r" (*envp) : "i" (FE_ALL_EXCEPT));
58 #define libc_feholdexcept libc_feholdexcept_riscv
59 #define libc_feholdexceptf libc_feholdexcept_riscv
60 #define libc_feholdexceptl libc_feholdexcept_riscv
62 static __always_inline void
63 libc_fesetround_riscv (int round)
65 riscv_setround (round);
68 #define libc_fesetround libc_fesetround_riscv
69 #define libc_fesetroundf libc_fesetround_riscv
70 #define libc_fesetroundl libc_fesetround_riscv
72 static __always_inline void
73 libc_feholdexcept_setround_riscv (fenv_t *envp, int round)
75 libc_feholdexcept_riscv (envp);
76 libc_fesetround_riscv (round);
79 #define libc_feholdexcept_setround libc_feholdexcept_setround_riscv
80 #define libc_feholdexcept_setroundf libc_feholdexcept_setround_riscv
81 #define libc_feholdexcept_setroundl libc_feholdexcept_setround_riscv
83 static __always_inline int
84 libc_fetestexcept_riscv (int ex)
86 return riscv_getflags () & ex;
89 #define libc_fetestexcept libc_fetestexcept_riscv
90 #define libc_fetestexceptf libc_fetestexcept_riscv
91 #define libc_fetestexceptl libc_fetestexcept_riscv
93 static __always_inline void
94 libc_fesetenv_riscv (const fenv_t *envp)
96 long int env = (envp != FE_DFL_ENV ? *envp : 0);
97 _FPU_SETCW (env);
100 #define libc_fesetenv libc_fesetenv_riscv
101 #define libc_fesetenvf libc_fesetenv_riscv
102 #define libc_fesetenvl libc_fesetenv_riscv
103 #define libc_feresetround_noex libc_fesetenv_riscv
104 #define libc_feresetround_noexf libc_fesetenv_riscv
105 #define libc_feresetround_noexl libc_fesetenv_riscv
107 static __always_inline int
108 libc_feupdateenv_test_riscv (const fenv_t *envp, int ex)
110 fenv_t env = *envp;
111 int flags = riscv_getflags ();
112 asm volatile ("csrw fcsr, %z0" : : "rJ" (env | flags));
113 return flags & ex;
116 #define libc_feupdateenv_test libc_feupdateenv_test_riscv
117 #define libc_feupdateenv_testf libc_feupdateenv_test_riscv
118 #define libc_feupdateenv_testl libc_feupdateenv_test_riscv
120 static __always_inline void
121 libc_feupdateenv_riscv (const fenv_t *envp)
123 long int env = (envp != FE_DFL_ENV ? *envp : 0);
124 _FPU_SETCW (env | riscv_getflags ());
127 #define libc_feupdateenv libc_feupdateenv_riscv
128 #define libc_feupdateenvf libc_feupdateenv_riscv
129 #define libc_feupdateenvl libc_feupdateenv_riscv
131 static __always_inline void
132 libc_feholdsetround_riscv (fenv_t *envp, int round)
134 /* Note this implementation makes an improperly-formatted fenv_t and
135 so should only be used in conjunction with libc_feresetround. */
136 int old_round;
137 asm volatile ("csrrw %0, frm, %z1" : "=r" (old_round) : "rJ" (round));
138 *envp = old_round;
141 #define libc_feholdsetround libc_feholdsetround_riscv
142 #define libc_feholdsetroundf libc_feholdsetround_riscv
143 #define libc_feholdsetroundl libc_feholdsetround_riscv
145 static __always_inline void
146 libc_feresetround_riscv (fenv_t *envp)
148 /* Note this implementation takes an improperly-formatted fenv_t and
149 so should only be used in conjunction with libc_feholdsetround. */
150 riscv_setround (*envp);
153 #define libc_feresetround libc_feresetround_riscv
154 #define libc_feresetroundf libc_feresetround_riscv
155 #define libc_feresetroundl libc_feresetround_riscv
157 #include_next <fenv_private.h>
159 #endif