Cygwin: access: Fix X_OK behaviour for backup operators and admins
[newlib-cygwin.git] / newlib / libc / machine / riscv / ieeefp.c
blob185da648c8b197b8d94bca8a6fe73d8e790fc378
1 /* Copyright (c) 2017 SiFive Inc. All rights reserved.
3 This copyrighted material is made available to anyone wishing to use,
4 modify, copy, or redistribute it subject to the terms and conditions
5 of the FreeBSD License. This program is distributed in the hope that
6 it will be useful, but WITHOUT ANY WARRANTY expressed or implied,
7 including the implied warranties of MERCHANTABILITY or FITNESS FOR
8 A PARTICULAR PURPOSE. A copy of this license is available at
9 http://www.opensource.org/licenses.
12 #include <ieeefp.h>
14 #if defined(__riscv_flen) || defined (__riscv_zfinx)
15 static void
16 fssr(unsigned value)
18 asm volatile ("fscsr %0" :: "r"(value));
21 static unsigned
22 frsr()
24 unsigned value;
25 asm volatile ("frcsr %0" : "=r" (value));
26 return value;
29 static fp_rnd
30 frm_fp_rnd (unsigned frm)
32 switch (frm)
34 case 0: return FP_RN;
35 case 1: return FP_RZ;
36 case 2: return FP_RM;
37 case 3: return FP_RP;
38 /* 4 ~ 7 is invalid value, so just retun FP_RP. */
39 default:return FP_RP;
43 static fp_except
44 frm_fp_except (unsigned except)
46 fp_except fp = 0;
47 if (except & (1 << 0))
48 fp |= FP_X_IMP;
49 if (except & (1 << 1))
50 fp |= FP_X_UFL;
51 if (except & (1 << 2))
52 fp |= FP_X_OFL;
53 if (except & (1 << 3))
54 fp |= FP_X_DX;
55 if (except & (1 << 4))
56 fp |= FP_X_INV;
57 return fp;
60 static unsigned
61 frm_except(fp_except fp)
63 unsigned except = 0;
64 if (fp & FP_X_IMP)
65 except |= (1 << 0);
66 if (fp & FP_X_UFL)
67 except |= (1 << 1);
68 if (fp & FP_X_OFL)
69 except |= (1 << 2);
70 if (fp & FP_X_DX)
71 except |= (1 << 3);
72 if (fp & FP_X_INV)
73 except |= (1 << 4);
74 return except;
77 #endif /* __riscv_flen */
79 fp_except
80 fpgetmask(void)
82 return 0;
85 fp_rnd
86 fpgetround(void)
88 #if defined(__riscv_flen) || defined (__riscv_zfinx)
89 unsigned rm = (frsr () >> 5) & 0x7;
90 return frm_fp_rnd (rm);
91 #else
92 return FP_RZ;
93 #endif /* __riscv_flen */
96 fp_except
97 fpgetsticky(void)
99 #if defined(__riscv_flen) || defined (__riscv_zfinx)
100 return frm_fp_except(frsr ());
101 #else
102 return 0;
103 #endif /* __riscv_flen */
106 fp_except
107 fpsetmask(fp_except mask)
109 return -1;
112 fp_rnd
113 fpsetround(fp_rnd rnd_dir)
115 #if defined(__riscv_flen) || defined (__riscv_zfinx)
116 unsigned fsr = frsr ();
117 unsigned rm = (fsr >> 5) & 0x7;
118 unsigned new_rm;
119 switch (rnd_dir)
121 case FP_RN: new_rm = 0; break;
122 case FP_RZ: new_rm = 1; break;
123 case FP_RM: new_rm = 2; break;
124 case FP_RP: new_rm = 3; break;
125 default: return -1;
127 fssr (new_rm << 5 | fsr & 0x1f);
128 return frm_fp_rnd (rm);
129 #else
130 return -1;
131 #endif /* __riscv_flen */
134 fp_except
135 fpsetsticky(fp_except sticky)
137 #if defined(__riscv_flen) || defined (__riscv_zfinx)
138 unsigned fsr = frsr ();
139 fssr (frm_except(sticky) | (fsr & ~0x1f));
140 return frm_fp_except(fsr);
141 #else
142 return -1;
143 #endif /* __riscv_flen */