]>
git.ipfire.org Git - thirdparty/glibc.git/blob - sysdeps/powerpc/fpu/tst-setcontext-fpscr.c
1 /* Copyright (C) 2001,2002,2004,2006,2007,2008 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
3 Contributed by Ryan S. Arnold <rsa@us.ibm.com>
4 Sean Curry <spcurry@us.ibm.com>
6 The GNU C Library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Lesser General Public
8 License as published by the Free Software Foundation; either
9 version 2.1 of the License, or (at your option) any later version.
11 The GNU C Library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
16 You should have received a copy of the GNU Lesser General Public
17 License along with the GNU C Library; if not, write to the Free
18 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
31 #include <fpu_control.h>
33 static ucontext_t ctx
[3];
39 static int back_in_main
;
42 volatile static ElfW(auxv_t
) *auxv
= NULL
;
44 ElfW(Addr
) query_auxv(int type
)
47 ElfW(auxv_t
) auxv_struct
;
48 ElfW(auxv_t
) *auxv_temp
;
51 /* if the /proc/self/auxv file has not been manually copied into the heap
56 auxv_f
= fopen("/proc/self/auxv", "r");
60 perror("Error opening file for reading");
63 auxv
= (ElfW(auxv_t
) *)malloc(getpagesize());
67 fread(&auxv_struct
, sizeof(ElfW(auxv_t
)), 1, auxv_f
);
68 auxv
[i
] = auxv_struct
;
70 } while(auxv_struct
.a_type
!= AT_NULL
);
73 auxv_temp
= (ElfW(auxv_t
) *)auxv
;
77 if(auxv_temp
[i
].a_type
== type
)
79 return auxv_temp
[i
].a_un
.a_val
;
82 } while (auxv_temp
[i
].a_type
!= AT_NULL
);
87 typedef unsigned long long di_fpscr_t
__attribute__ ((__mode__ (__DI__
)));
88 typedef unsigned int si_fpscr_t
__attribute__ ((__mode__ (__SI__
)));
90 #define _FPSCR_RESERVED 0xfffffff8ffffff04ULL
92 #define _FPSCR_TEST0_DRN 0x0000000400000000ULL
93 #define _FPSCR_TEST0_RN 0x0000000000000003ULL
95 #define _FPSCR_TEST1_DRN 0x0000000300000000ULL
96 #define _FPSCR_TEST1_RN 0x0000000000000002ULL
98 /* Macros for accessing the hardware control word on Power6[x]. */
99 # define _GET_DI_FPSCR(__fpscr) ({ \
101 di_fpscr_t fpscr; } \
102 tmp __attribute__ ((__aligned__(8))); \
103 __asm__ ("mffs 0; stfd%U0 0,%0" : "=m" (tmp.d) : : "fr0"); \
104 (__fpscr)=tmp.fpscr; \
107 # define _SET_DI_FPSCR(__fpscr) { \
108 union { double d; di_fpscr_t fpscr; } \
109 tmp __attribute__ ((__aligned__(8))); \
110 tmp.fpscr = __fpscr; \
111 /* Set the entire 64-bit FPSCR. */ \
112 __asm__ ("lfd%U0 0,%0; mtfsf 255,0,1,0" : : "m" (tmp.d) : "fr0"); \
115 # define _GET_SI_FPSCR(__fpscr) ({ \
117 si_fpscr_t cw[2]; } \
118 tmp __attribute__ ((__aligned__(8))); \
119 __asm__ ("mffs 0; stfd%U0 0,%0" : "=m" (tmp.d) : : "fr0"); \
120 (__fpscr)=tmp.cw[1]; \
123 # define _SET_SI_FPSCR(__fpscr) { \
124 union { double d; si_fpscr_t fpscr[2]; } \
125 tmp __attribute__ ((__aligned__(8))); \
126 /* More-or-less arbitrary; this is a QNaN. */ \
127 tmp.fpscr[0] = 0xFFF80000; \
128 tmp.fpscr[1] = __fpscr; \
129 __asm__ ("lfd%U0 0,%0; mtfsf 255,0" : : "m" (tmp.d) : "fr0"); \
132 void prime_special_regs(int which
)
136 di_fpscr_t di_fpscr
__attribute__ ((__aligned__(8)));
138 a_val
= query_auxv(AT_HWCAP
);
141 puts ("querying the auxv for the hwcap failed");
145 /* Indicates a 64-bit FPSCR. */
146 if (a_val
& PPC_FEATURE_HAS_DFP
)
148 _GET_DI_FPSCR(di_fpscr
);
150 /* Overwrite the existing DRN and RN if there is one. */
152 di_fpscr
= ((di_fpscr
& _FPSCR_RESERVED
) | (_FPSCR_TEST0_DRN
| _FPSCR_TEST0_RN
));
154 di_fpscr
= ((di_fpscr
& _FPSCR_RESERVED
) | (_FPSCR_TEST1_DRN
| _FPSCR_TEST1_RN
));
155 puts ("Priming 64-bit FPSCR with:");
156 printf("0x%.16llx\n",(unsigned long long int)di_fpscr
);
158 _SET_DI_FPSCR(di_fpscr
);
162 puts ("32-bit FPSCR found and will be tested.");
163 _GET_SI_FPSCR(di_fpscr
);
165 /* Overwrite the existing RN if there is one. */
167 di_fpscr
= ((di_fpscr
& _FPSCR_RESERVED
) | (_FPSCR_TEST0_RN
));
169 di_fpscr
= ((di_fpscr
& _FPSCR_RESERVED
) | (_FPSCR_TEST1_RN
));
170 puts ("Priming 32-bit FPSCR with:");
171 printf("0x%.8lx\n",(unsigned long int) di_fpscr
);
173 _SET_SI_FPSCR(di_fpscr
);
177 void clear_special_regs(void)
181 di_fpscr_t di_fpscr
__attribute__ ((__aligned__(8)));
185 unsigned long long int lli
;
189 a_val
= query_auxv(AT_HWCAP
);
192 puts ("querying the auxv for the hwcap failed");
197 dlli
.d
= ctx
[0].uc_mcontext
.uc_regs
->fpregs
.fpscr
;
199 dlli
.d
= ctx
[0].uc_mcontext
.fp_regs
[32];
202 puts("The FPSCR value saved in the ucontext_t is:");
204 /* Indicates a 64-bit FPSCR. */
205 if (a_val
& PPC_FEATURE_HAS_DFP
)
207 printf("0x%.16llx\n",dlli
.lli
);
209 puts ("Clearing the 64-bit FPSCR to:");
210 printf("0x%.16llx\n",(unsigned long long int) di_fpscr
);
212 _SET_DI_FPSCR(di_fpscr
);
216 printf("0x%.8x\n",(unsigned int) dlli
.li
[1]);
218 puts ("Clearing the 32-bit FPSCR to:");
219 printf("0x%.8lx\n",(unsigned long int) di_fpscr
);
221 _SET_SI_FPSCR(di_fpscr
);
225 void test_special_regs(int which
)
228 unsigned long long int test
;
230 di_fpscr_t di_fpscr
__attribute__ ((__aligned__(8)));
232 a_val
= query_auxv(AT_HWCAP
);
235 puts ("querying the auxv for the hwcap failed");
239 /* Indicates a 64-bit FPSCR. */
240 if (a_val
& PPC_FEATURE_HAS_DFP
)
242 _GET_DI_FPSCR(di_fpscr
);
245 puts ("After setcontext the 64-bit FPSCR contains:");
247 puts ("After swapcontext the 64-bit FPSCR contains:");
249 printf("0x%.16llx\n",(unsigned long long int) di_fpscr
);
250 test
= (_FPSCR_TEST0_DRN
| _FPSCR_TEST0_RN
);
251 if((di_fpscr
& (test
)) != (test
))
253 printf ("%s: DRN and RN bits set before getcontext were not preserved across [set|swap]context call: %m",__FUNCTION__
);
259 _GET_SI_FPSCR(di_fpscr
);
261 puts ("After setcontext the 32-bit FPSCR contains:");
263 puts ("After swapcontext the 32-bit FPSCR contains:");
265 printf("0x%.8lx\n",(unsigned long int) di_fpscr
);
266 test
= _FPSCR_TEST0_RN
;
267 if((di_fpscr
& test
) != test
)
269 printf ("%s: RN bit set before getcontext was not preserved across [set|swap]context call: %m",__FUNCTION__
);
279 if (back_in_main
== 0)
281 puts ("program did not reach main again");
290 atexit (check_called
);
292 puts ("priming the FPSCR with a marker");
293 prime_special_regs (0);
295 puts ("making contexts");
296 if (getcontext (&ctx
[0]) != 0)
304 printf ("%s: getcontext: %m\n", __FUNCTION__
);
308 /* Play some tricks with this context. */
311 clear_special_regs ( );
312 if (setcontext (&ctx
[0]) != 0)
314 printf ("%s: setcontext: %m\n", __FUNCTION__
);
320 printf ("%s: 'global' not incremented twice\n", __FUNCTION__
);
324 test_special_regs (0);
327 if (getcontext (&ctx
[0]) != 0)
329 printf ("%s: getcontext: %m\n", __FUNCTION__
);
335 puts ("priming the FPSCR with a marker");
336 prime_special_regs (1);
338 puts ("swapping contexts");
339 if (swapcontext (&ctx
[1], &ctx
[0]) != 0)
341 printf ("%s: swapcontext: %m\n", __FUNCTION__
);
347 printf ("%s: 'global' not incremented twice\n", __FUNCTION__
);
351 test_special_regs (1);
353 puts ("back at main program");
356 puts ("test succeeded");