xref: /haiku/src/system/libroot/posix/arch/m68k/fenv.c (revision 372b901dfeada686207d00bbcce456f748bbda12)
1 /*
2  * Copyright (c) 2005-2019 Rich Felker, et al.
3  *
4  * Part of MUSL, released under the MIT license.
5  */
6 
7 
8 #include <fenv.h>
9 #include <features.h>
10 
11 #define hidden __attribute__((__visibility__("hidden")))
12 
13 #if __HAVE_68881__ || __mcffpu__
14 
15 static unsigned getsr()
16 {
17 	unsigned v;
18 	__asm__ __volatile__ ("fmove.l %%fpsr,%0" : "=dm"(v));
19 	return v;
20 }
21 
22 static void setsr(unsigned v)
23 {
24 	__asm__ __volatile__ ("fmove.l %0,%%fpsr" : : "dm"(v));
25 }
26 
27 static unsigned getcr()
28 {
29 	unsigned v;
30 	__asm__ __volatile__ ("fmove.l %%fpcr,%0" : "=dm"(v));
31 	return v;
32 }
33 
34 static void setcr(unsigned v)
35 {
36 	__asm__ __volatile__ ("fmove.l %0,%%fpcr" : : "dm"(v));
37 }
38 
39 int feclearexcept(int mask)
40 {
41 	if (mask & ~FE_ALL_EXCEPT) return -1;
42 	setsr(getsr() & ~mask);
43 	return 0;
44 }
45 
46 int feraiseexcept(int mask)
47 {
48 	if (mask & ~FE_ALL_EXCEPT) return -1;
49 	setsr(getsr() | mask);
50 	return 0;
51 }
52 
53 int fetestexcept(int mask)
54 {
55 	return getsr() & mask;
56 }
57 
58 int fegetround(void)
59 {
60 	return getcr() & FE_UPWARD;
61 }
62 
63 hidden int __fesetround(int r)
64 {
65 	setcr((getcr() & ~FE_UPWARD) | r);
66 	return 0;
67 }
68 
69 int fegetenv(fenv_t *envp)
70 {
71 	envp->__control_register = getcr();
72 	envp->__status_register = getsr();
73 	__asm__ __volatile__ ("fmove.l %%fpiar,%0"
74 		: "=dm"(envp->__instruction_address));
75 	return 0;
76 }
77 
78 int fesetenv(const fenv_t *envp)
79 {
80 	static const fenv_t default_env = { 0 };
81 	if (envp == FE_DFL_ENV)
82 		envp = &default_env;
83 	setcr(envp->__control_register);
84 	setsr(envp->__status_register);
85 	__asm__ __volatile__ ("fmove.l %0,%%fpiar"
86 		: : "dm"(envp->__instruction_address));
87 	return 0;
88 }
89 
90 #else
91 
92 #include "fenv-generic.c"
93 
94 #endif
95