* sysdeps/unix/sysv/linux/powerpc/powerpc64/setcontext.S: Use
[glibc.git] / sysdeps / powerpc / fpu / tst-setcontext-fpscr.c
blobe75a7f19419686c356ea05e2164327d29729f72c
1 /* Copyright (C) 2001,2002,2004,2006-2008,2009 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
19 02111-1307 USA. */
21 #include <errno.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <ucontext.h>
26 #include <unistd.h>
27 #include <malloc.h>
28 #include <link.h>
29 #include <elf.h>
30 #include <sysdep.h>
31 #include <fpu_control.h>
33 static ucontext_t ctx[3];
36 volatile int global;
39 static int back_in_main;
42 volatile static ElfW(auxv_t) *auxv = NULL;
44 ElfW(Addr) query_auxv(int type)
46 FILE *auxv_f;
47 ElfW(auxv_t) auxv_struct;
48 ElfW(auxv_t) *auxv_temp;
49 int i = 0;
51 /* if the /proc/self/auxv file has not been manually copied into the heap
52 yet, then do it */
54 if(auxv == NULL)
56 auxv_f = fopen("/proc/self/auxv", "r");
58 if(auxv_f == 0)
60 perror("Error opening file for reading");
61 return 0;
63 auxv = (ElfW(auxv_t) *)malloc(getpagesize());
67 fread(&auxv_struct, sizeof(ElfW(auxv_t)), 1, auxv_f);
68 auxv[i] = auxv_struct;
69 i++;
70 } while(auxv_struct.a_type != AT_NULL);
73 auxv_temp = (ElfW(auxv_t) *)auxv;
74 i = 0;
77 if(auxv_temp[i].a_type == type)
79 return auxv_temp[i].a_un.a_val;
81 i++;
82 } while (auxv_temp[i].a_type != AT_NULL);
84 return 0;
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) ({ \
100 union { double d; \
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; \
105 tmp.fpscr; })
107 /* We make sure to zero fp0 after we use it in order to prevent stale data
108 in an fp register from making a test-case pass erroneously. */
109 # define _SET_DI_FPSCR(__fpscr) { \
110 union { double d; di_fpscr_t fpscr; } \
111 tmp __attribute__ ((__aligned__(8))); \
112 tmp.fpscr = __fpscr; \
113 /* Set the entire 64-bit FPSCR. */ \
114 __asm__ ("lfd%U0 0,%0; " \
115 ".machine push; " \
116 ".machine \"power6\"; " \
117 "mtfsf 255,0,1,0; " \
118 ".machine pop" : : "m" (tmp.d) : "fr0"); \
119 tmp.d = 0; \
120 __asm__("lfd%U0 0,%0" : : "m" (tmp.d) : "fr0"); \
123 # define _GET_SI_FPSCR(__fpscr) ({ \
124 union { double d; \
125 si_fpscr_t cw[2]; } \
126 tmp __attribute__ ((__aligned__(8))); \
127 __asm__ ("mffs 0; stfd%U0 0,%0" : "=m" (tmp.d) : : "fr0"); \
128 (__fpscr)=tmp.cw[1]; \
129 tmp.cw[0]; })
131 /* We make sure to zero fp0 after we use it in order to prevent stale data
132 in an fp register from making a test-case pass erroneously. */
133 # define _SET_SI_FPSCR(__fpscr) { \
134 union { double d; si_fpscr_t fpscr[2]; } \
135 tmp __attribute__ ((__aligned__(8))); \
136 /* More-or-less arbitrary; this is a QNaN. */ \
137 tmp.fpscr[0] = 0xFFF80000; \
138 tmp.fpscr[1] = __fpscr; \
139 __asm__ ("lfd%U0 0,%0; mtfsf 255,0" : : "m" (tmp.d) : "fr0"); \
140 tmp.d = 0; \
141 __asm__("lfd%U0 0,%0" : : "m" (tmp.d) : "fr0"); \
144 void prime_special_regs(int which)
146 ElfW(Addr) a_val;
148 di_fpscr_t di_fpscr __attribute__ ((__aligned__(8)));
150 a_val = query_auxv(AT_HWCAP);
151 if(a_val == -1)
153 puts ("querying the auxv for the hwcap failed");
154 _exit (1);
157 /* Indicates a 64-bit FPSCR. */
158 if (a_val & PPC_FEATURE_HAS_DFP)
160 _GET_DI_FPSCR(di_fpscr);
162 /* Overwrite the existing DRN and RN if there is one. */
163 if (which == 0)
164 di_fpscr = ((di_fpscr & _FPSCR_RESERVED) | (_FPSCR_TEST0_DRN | _FPSCR_TEST0_RN));
165 else
166 di_fpscr = ((di_fpscr & _FPSCR_RESERVED) | (_FPSCR_TEST1_DRN | _FPSCR_TEST1_RN));
167 puts ("Priming 64-bit FPSCR with:");
168 printf("0x%.16llx\n",(unsigned long long int)di_fpscr);
170 _SET_DI_FPSCR(di_fpscr);
172 else
174 puts ("32-bit FPSCR found and will be tested.");
175 _GET_SI_FPSCR(di_fpscr);
177 /* Overwrite the existing RN if there is one. */
178 if (which == 0)
179 di_fpscr = ((di_fpscr & _FPSCR_RESERVED) | (_FPSCR_TEST0_RN));
180 else
181 di_fpscr = ((di_fpscr & _FPSCR_RESERVED) | (_FPSCR_TEST1_RN));
182 puts ("Priming 32-bit FPSCR with:");
183 printf("0x%.8lx\n",(unsigned long int) di_fpscr);
185 _SET_SI_FPSCR(di_fpscr);
189 void clear_special_regs(void)
191 ElfW(Addr) a_val;
193 di_fpscr_t di_fpscr __attribute__ ((__aligned__(8)));
195 union {
196 double d;
197 unsigned long long int lli;
198 unsigned int li[2];
199 } dlli;
201 a_val = query_auxv(AT_HWCAP);
202 if(a_val == -1)
204 puts ("querying the auxv for the hwcap failed");
205 _exit (1);
208 #if __WORDSIZE == 32
209 dlli.d = ctx[0].uc_mcontext.uc_regs->fpregs.fpscr;
210 #else
211 dlli.d = ctx[0].uc_mcontext.fp_regs[32];
212 #endif
214 puts("The FPSCR value saved in the ucontext_t is:");
216 /* Indicates a 64-bit FPSCR. */
217 if (a_val & PPC_FEATURE_HAS_DFP)
219 printf("0x%.16llx\n",dlli.lli);
220 di_fpscr = 0x0;
221 puts ("Clearing the 64-bit FPSCR to:");
222 printf("0x%.16llx\n",(unsigned long long int) di_fpscr);
224 _SET_DI_FPSCR(di_fpscr);
226 else
228 printf("0x%.8x\n",(unsigned int) dlli.li[1]);
229 di_fpscr = 0x0;
230 puts ("Clearing the 32-bit FPSCR to:");
231 printf("0x%.8lx\n",(unsigned long int) di_fpscr);
233 _SET_SI_FPSCR(di_fpscr);
237 void test_special_regs(int which)
239 ElfW(Addr) a_val;
240 unsigned long long int test;
242 di_fpscr_t di_fpscr __attribute__ ((__aligned__(8)));
244 a_val = query_auxv(AT_HWCAP);
245 if(a_val == -1)
247 puts ("querying the auxv for the hwcap failed");
248 _exit (2);
251 /* Indicates a 64-bit FPSCR. */
252 if (a_val & PPC_FEATURE_HAS_DFP)
254 _GET_DI_FPSCR(di_fpscr);
256 if (which == 0)
257 puts ("After setcontext the 64-bit FPSCR contains:");
258 else
259 puts ("After swapcontext the 64-bit FPSCR contains:");
261 printf("0x%.16llx\n",(unsigned long long int) di_fpscr);
262 test = (_FPSCR_TEST0_DRN | _FPSCR_TEST0_RN);
263 if((di_fpscr & (test)) != (test))
265 printf ("%s: DRN and RN bits set before getcontext were not preserved across [set|swap]context call: %m",__FUNCTION__);
266 _exit (3);
269 else
271 _GET_SI_FPSCR(di_fpscr);
272 if (which == 0)
273 puts ("After setcontext the 32-bit FPSCR contains:");
274 else
275 puts ("After swapcontext the 32-bit FPSCR contains:");
277 printf("0x%.8lx\n",(unsigned long int) di_fpscr);
278 test = _FPSCR_TEST0_RN;
279 if((di_fpscr & test) != test)
281 printf ("%s: RN bit set before getcontext was not preserved across [set|swap]context call: %m",__FUNCTION__);
282 _exit (4);
288 static void
289 check_called (void)
291 if (back_in_main == 0)
293 puts ("program did not reach main again");
294 _exit (5);
300 main (void)
302 atexit (check_called);
304 puts ("priming the FPSCR with a marker");
305 prime_special_regs (0);
307 puts ("making contexts");
308 if (getcontext (&ctx[0]) != 0)
310 if (errno == ENOSYS)
312 back_in_main = 1;
313 exit (0);
316 printf ("%s: getcontext: %m\n", __FUNCTION__);
317 exit (6);
320 /* Play some tricks with this context. */
321 if (++global == 1)
323 clear_special_regs ( );
324 if (setcontext (&ctx[0]) != 0)
326 printf ("%s: setcontext: %m\n", __FUNCTION__);
327 exit (7);
330 if (global != 2)
332 printf ("%s: 'global' not incremented twice\n", __FUNCTION__);
333 exit (8);
336 test_special_regs (0);
338 global = 0;
339 if (getcontext (&ctx[0]) != 0)
341 printf ("%s: getcontext: %m\n", __FUNCTION__);
342 exit (9);
345 if (++global == 1)
347 puts ("priming the FPSCR with a marker");
348 prime_special_regs (1);
350 puts ("swapping contexts");
351 if (swapcontext (&ctx[1], &ctx[0]) != 0)
353 printf ("%s: swapcontext: %m\n", __FUNCTION__);
354 exit (9);
357 if (global != 2)
359 printf ("%s: 'global' not incremented twice\n", __FUNCTION__);
360 exit (10);
363 test_special_regs (1);
365 puts ("back at main program");
366 back_in_main = 1;
368 puts ("test succeeded");
369 return 0;