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
23 #include <fpu_control.h>
24 #include <get-rounding-mode.h>
26 static __always_inline
int
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
42 asm volatile ("frflags %0" : "=r" (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);
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
)
111 int flags
= riscv_getflags ();
112 asm volatile ("csrw fcsr, %z0" : : "rJ" (env
| flags
));
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. */
137 asm volatile ("csrrw %0, frm, %z1" : "=r" (old_round
) : "rJ" (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>