1 #ifndef SPARC_FENV_PRIVATE_H
2 #define SPARC_FENV_PRIVATE_H 1
3 
4 #include <fenv.h>
5 #include <fpu_control.h>
6 
7 /* For internal use only: access the fp state register.  */
8 #define __fenv_stfsr(X)   _FPU_GETCW (X)
9 #define __fenv_ldfsr(X)   _FPU_SETCW (X)
10 
11 static __always_inline void
libc_feholdexcept(fenv_t * e)12 libc_feholdexcept (fenv_t *e)
13 {
14   fenv_t etmp;
15   __fenv_stfsr(etmp);
16   *(e) = etmp;
17   etmp = etmp & ~((0x1f << 23) | FE_ALL_EXCEPT);
18   __fenv_ldfsr(etmp);
19 }
20 
21 static __always_inline void
libc_fesetround(int r)22 libc_fesetround (int r)
23 {
24   fenv_t etmp;
25   __fenv_stfsr(etmp);
26   etmp = (etmp & ~__FE_ROUND_MASK) | (r);
27   __fenv_ldfsr(etmp);
28 }
29 
30 static __always_inline void
libc_feholdexcept_setround(fenv_t * e,int r)31 libc_feholdexcept_setround (fenv_t *e, int r)
32 {
33   fenv_t etmp;
34   __fenv_stfsr(etmp);
35   *(e) = etmp;
36   etmp = etmp & ~((0x1f << 23) | FE_ALL_EXCEPT);
37   etmp = (etmp & ~__FE_ROUND_MASK) | (r);
38   __fenv_ldfsr(etmp);
39 }
40 
41 static __always_inline int
libc_fetestexcept(int e)42 libc_fetestexcept (int e)
43 {
44   fenv_t etmp;
45   __fenv_stfsr(etmp);
46   return etmp & (e) & FE_ALL_EXCEPT;
47 }
48 
49 static __always_inline void
libc_fesetenv(fenv_t * e)50 libc_fesetenv (fenv_t *e)
51 {
52   __fenv_ldfsr(*e);
53 }
54 
55 static __always_inline int
libc_feupdateenv_test(fenv_t * e,int ex)56 libc_feupdateenv_test (fenv_t *e, int ex)
57 {
58   fenv_t etmp;
59 
60   __fenv_stfsr(etmp);
61   etmp &= FE_ALL_EXCEPT;
62 
63   __fenv_ldfsr(*e);
64 
65   feraiseexcept (etmp);
66 
67   return etmp & ex;
68 }
69 
70 static __always_inline void
libc_feupdateenv(fenv_t * e)71 libc_feupdateenv (fenv_t *e)
72 {
73   libc_feupdateenv_test (e, 0);
74 }
75 
76 static __always_inline void
libc_feholdsetround(fenv_t * e,int r)77 libc_feholdsetround (fenv_t *e, int r)
78 {
79   fenv_t etmp;
80   __fenv_stfsr(etmp);
81   *(e) = etmp;
82   etmp = (etmp & ~__FE_ROUND_MASK) | (r);
83   __fenv_ldfsr(etmp);
84 }
85 
86 static __always_inline void
libc_feresetround(fenv_t * e)87 libc_feresetround (fenv_t *e)
88 {
89   fenv_t etmp;
90   __fenv_stfsr(etmp);
91   etmp = (etmp & ~__FE_ROUND_MASK) | (*e & __FE_ROUND_MASK);
92   __fenv_ldfsr(etmp);
93 }
94 
95 #define libc_feholdexceptf		libc_feholdexcept
96 #define libc_fesetroundf		libc_fesetround
97 #define libc_feholdexcept_setroundf	libc_feholdexcept_setround
98 #define libc_fetestexceptf		libc_fetestexcept
99 #define libc_fesetenvf			libc_fesetenv
100 #define libc_feupdateenv_testf		libc_feupdateenv_test
101 #define libc_feupdateenvf		libc_feupdateenv
102 #define libc_feholdsetroundf		libc_feholdsetround
103 #define libc_feresetroundf		libc_feresetround
104 #define libc_feholdexcept		libc_feholdexcept
105 #define libc_fesetround			libc_fesetround
106 #define libc_feholdexcept_setround	libc_feholdexcept_setround
107 #define libc_fetestexcept		libc_fetestexcept
108 #define libc_fesetenv			libc_fesetenv
109 #define libc_feupdateenv_test		libc_feupdateenv_test
110 #define libc_feupdateenv		libc_feupdateenv
111 #define libc_feholdsetround		libc_feholdsetround
112 #define libc_feresetround		libc_feresetround
113 #define libc_feholdexceptl		libc_feholdexcept
114 #define libc_fesetroundl		libc_fesetround
115 #define libc_feholdexcept_setroundl	libc_feholdexcept_setround
116 #define libc_fetestexceptl		libc_fetestexcept
117 #define libc_fesetenvl			libc_fesetenv
118 #define libc_feupdateenv_testl		libc_feupdateenv_test
119 #define libc_feupdateenvl		libc_feupdateenv
120 #define libc_feholdsetroundl		libc_feholdsetround
121 #define libc_feresetroundl		libc_feresetround
122 
123 /* We have support for rounding mode context.  */
124 #define HAVE_RM_CTX 1
125 
126 static __always_inline void
libc_feholdexcept_setround_sparc_ctx(struct rm_ctx * ctx,int round)127 libc_feholdexcept_setround_sparc_ctx (struct rm_ctx *ctx, int round)
128 {
129   fenv_t new;
130 
131   __fenv_stfsr(ctx->env);
132   new = ctx->env & ~((0x1f << 23) | FE_ALL_EXCEPT);
133   new = (new & ~__FE_ROUND_MASK) | round;
134   if (unlikely (new != ctx->env))
135     {
136       __fenv_ldfsr(new);
137       ctx->updated_status = true;
138     }
139   else
140     ctx->updated_status = false;
141 }
142 
143 static __always_inline void
libc_fesetenv_sparc_ctx(struct rm_ctx * ctx)144 libc_fesetenv_sparc_ctx (struct rm_ctx *ctx)
145 {
146   libc_fesetenv(&ctx->env);
147 }
148 
149 static __always_inline void
libc_feupdateenv_sparc_ctx(struct rm_ctx * ctx)150 libc_feupdateenv_sparc_ctx (struct rm_ctx *ctx)
151 {
152   if (unlikely (ctx->updated_status))
153     libc_feupdateenv_test (&ctx->env, 0);
154 }
155 
156 static __always_inline void
libc_feholdsetround_sparc_ctx(struct rm_ctx * ctx,int round)157 libc_feholdsetround_sparc_ctx (struct rm_ctx *ctx, int round)
158 {
159   fenv_t new;
160 
161   __fenv_stfsr(ctx->env);
162   new = (ctx->env & ~__FE_ROUND_MASK) | round;
163   if (unlikely (new != ctx->env))
164     {
165       __fenv_ldfsr(new);
166       ctx->updated_status = true;
167     }
168   else
169     ctx->updated_status = false;
170 }
171 #define libc_feholdexcept_setround_ctx   libc_feholdexcept_setround_sparc_ctx
172 #define libc_feholdexcept_setroundf_ctx  libc_feholdexcept_setround_sparc_ctx
173 #define libc_feholdexcept_setroundl_ctx  libc_feholdexcept_setround_sparc_ctx
174 #define libc_fesetenv_ctx                libc_fesetenv_sparc_ctx
175 #define libc_fesetenvf_ctx               libc_fesetenv_sparc_ctx
176 #define libc_fesetenvl_ctx               libc_fesetenv_sparc_ctx
177 #define libc_feupdateenv_ctx             libc_feupdateenv_sparc_ctx
178 #define libc_feupdateenvf_ctx            libc_feupdateenv_sparc_ctx
179 #define libc_feupdateenvl_ctx            libc_feupdateenv_sparc_ctx
180 #define libc_feresetround_ctx            libc_feupdateenv_sparc_ctx
181 #define libc_feresetroundf_ctx           libc_feupdateenv_sparc_ctx
182 #define libc_feresetroundl_ctx           libc_feupdateenv_sparc_ctx
183 #define libc_feholdsetround_ctx          libc_feholdsetround_sparc_ctx
184 #define libc_feholdsetroundf_ctx         libc_feholdsetround_sparc_ctx
185 #define libc_feholdsetroundl_ctx         libc_feholdsetround_sparc_ctx
186 
187 #endif /* SPARC_FENV_PRIVATE_H */
188