1 /* Copyright (C) 2014-2015 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
4 The GNU C Library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 2.1 of the License, or (at your option) any later version.
9 The GNU C Library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Lesser General Public License for more details.
14 You should have received a copy of the GNU Lesser General Public
15 License along with the GNU C Library; if not, see
16 <http://www.gnu.org/licenses/>. */
18 #include <sys/prctl.h>
25 #if defined PR_GET_FP_MODE && defined PR_SET_FP_MODE
26 # define HAVE_PRCTL_FP_MODE 1
27 # define FR1_MODE (PR_FP_MODE_FR)
28 # define FRE_MODE (PR_FP_MODE_FR | PR_FP_MODE_FRE)
30 # define HAVE_PRCTL_FP_MODE 0
35 #define STR_VAL(VAL) #VAL
36 #define N_STR(VAL) STR_VAL(VAL)
38 #define START_STATE(NAME) \
51 #define NEXT(OBJ, NEXT_STATE) \
53 current_fp_state = s_ ## NEXT_STATE; \
56 #define NEXT_REQ_FR1(OBJ, NEXT_STATE) \
60 current_fp_state = s_ ## NEXT_STATE; \
66 #define NEXT_REQ_FR0(OBJ, NEXT_STATE) \
70 || (is_r6 && has_fr1 && has_fre)) \
71 current_fp_state = s_ ## NEXT_STATE; \
77 #define NEXT_REQ_FRE(OBJ, NEXT_STATE) \
80 if (has_fr1 && has_fre) \
81 current_fp_state = s_ ## NEXT_STATE; \
87 #define NEXT_NO_MODE_CHANGE(OBJ, NEXT_STATE) \
90 if (current_mode_valid_p (s_ ## NEXT_STATE)) \
92 current_fp_state = s_ ## NEXT_STATE; \
93 cant_change_mode = true; \
100 static const char * const shared_lib_names
[] =
102 "tst-abi-fpanymod.so", "tst-abi-fpsoftmod.so", "tst-abi-fpsinglemod.so",
103 "tst-abi-fp32mod.so", "tst-abi-fp64mod.so", "tst-abi-fp64amod.so",
104 "tst-abi-fpxxmod.so", "tst-abi-fpxxomod.so"
143 s_fp32_fp64a_fpxxo_fpxx
,
151 s_fp64a_fp64_fpxxo_fpxx
,
158 static int current_fp_mode
;
159 static bool cant_change_mode
= false;
160 static bool has_fr1
= false;
161 static bool has_fre
= false;
162 static bool is_r6
= false;
163 static unsigned int fp_obj_count
[o_max
];
164 void * shared_lib_ptrs
[o_max
];
165 static enum fp_state current_fp_state
= s_any
;
166 static enum fp_obj test_objects
[FPABI_COUNT
] = { FPABI_LIST
};
168 /* This function will return the valid FP modes for the specified state. */
170 static struct fp_mode_req
171 compute_fp_modes (enum fp_state state
)
173 struct fp_mode_req requirements
;
175 requirements
.mode1
= -1;
176 requirements
.mode2
= -1;
177 requirements
.mode3
= -1;
184 requirements
.mode1
= FR1_MODE
;
187 requirements
.mode1
= 0;
188 requirements
.mode2
= FR1_MODE
;
195 case s_fp32_fpxxo_fpxx
:
198 requirements
.mode1
= FRE_MODE
;
201 requirements
.mode1
= 0;
202 requirements
.mode2
= FRE_MODE
;
214 requirements
.mode1
= FR1_MODE
;
215 requirements
.mode2
= FRE_MODE
;
219 requirements
.mode1
= 0;
220 requirements
.mode2
= FR1_MODE
;
221 requirements
.mode3
= FRE_MODE
;
228 case s_fp64a_fpxx_fpxxo
:
230 requirements
.mode1
= FR1_MODE
;
231 requirements
.mode2
= FRE_MODE
;
237 case s_fp64_fpxx_fpxxo
:
239 case s_fp64a_fp64_fpxx
:
240 case s_fp64a_fp64_fpxxo
:
241 case s_fp64a_fp64_fpxxo_fpxx
:
243 requirements
.mode1
= FR1_MODE
;
247 case s_fp32_fp64a_fpxx
:
248 case s_fp32_fp64a_fpxxo
:
249 case s_fp32_fp64a_fpxxo_fpxx
:
251 requirements
.mode1
= FRE_MODE
;
258 /* Check the current mode is suitable for the specified state. */
261 current_mode_valid_p (enum fp_state s
)
263 struct fp_mode_req req
= compute_fp_modes (s
);
264 return (req
.mode1
== current_fp_mode
265 || req
.mode2
== current_fp_mode
266 || req
.mode3
== current_fp_mode
);
269 /* Run the state machine by adding a new object. */
272 set_next_fp_state (enum fp_obj obj
)
274 cant_change_mode
= false;
275 switch (current_fp_state
)
289 NEXT_REQ_FR0(fp32
, fp32
)
292 NEXT_REQ_FR1(fp64a
, fp64a
)
293 NEXT_REQ_FR1(fp64
, fp64
)
300 NEXT_REQ_FR0(fp32
,fp32
)
301 NEXT(fpxx
, fp32_fpxx
)
302 NEXT(fpxxo
, fp32_fpxxo
)
303 NEXT_REQ_FRE(fp64a
, fp64a_fp32
)
308 NEXT_REQ_FR0(fp32
, fp32_fpxx
)
309 NEXT_REQ_FR1(fp64
, fp64_fpxx
)
310 NEXT_REQ_FR1(fp64a
, fp64a_fpxx
)
311 NEXT(fpxxo
, fpxxo_fpxx
)
317 NEXT_NO_MODE_CHANGE(fp32
, fp32_fpxxo
)
318 NEXT_NO_MODE_CHANGE(fp64
, fp64_fpxxo
)
319 NEXT_NO_MODE_CHANGE(fp64a
, fp64a_fpxxo
)
320 NEXT_NO_MODE_CHANGE(fpxx
, fpxxo_fpxx
)
321 NEXT_NO_MODE_CHANGE(fpxxo
,fpxxo
)
322 NEXT_NO_MODE_CHANGE(any
,fpxxo
)
326 NEXT_REQ_FRE(fp32
, fp64a_fp32
)
327 NEXT_REQ_FR1(fp64
, fp64a_fp64
)
328 NEXT(fpxxo
, fp64a_fpxxo
)
329 NEXT(fpxx
, fp64a_fpxx
)
330 NEXT_REQ_FR1(fp64a
, fp64a
)
335 NEXT_REQ_FR1(fp64a
, fp64a_fp64
)
336 NEXT(fpxxo
, fp64_fpxxo
)
337 NEXT(fpxx
, fp64_fpxx
)
338 NEXT_REQ_FR1(fp64
, fp64
)
342 START_STATE(fpxxo_fpxx
)
343 NEXT_NO_MODE_CHANGE(fp32
, fp32_fpxxo_fpxx
)
344 NEXT_NO_MODE_CHANGE(fp64
, fp64_fpxx_fpxxo
)
345 NEXT_NO_MODE_CHANGE(fp64a
, fp64a_fpxx_fpxxo
)
346 NEXT_NO_MODE_CHANGE(fpxx
, fpxxo_fpxx
)
347 NEXT_NO_MODE_CHANGE(fpxxo
, fpxxo_fpxx
)
348 NEXT_NO_MODE_CHANGE(any
, fpxxo_fpxx
)
351 START_STATE(fp32_fpxx
)
352 NEXT_REQ_FR0(fp32
, fp32_fpxx
)
353 NEXT(fpxx
, fp32_fpxx
)
354 NEXT(fpxxo
, fp32_fpxxo_fpxx
)
355 NEXT_REQ_FRE(fp64a
, fp32_fp64a_fpxx
)
359 START_STATE(fp32_fpxxo
)
360 NEXT_NO_MODE_CHANGE(fp32
, fp32_fpxxo
)
361 NEXT_NO_MODE_CHANGE(fpxxo
, fp32_fpxxo
)
362 NEXT_NO_MODE_CHANGE(fpxx
, fp32_fpxxo_fpxx
)
363 NEXT_NO_MODE_CHANGE(fp64a
, fp32_fp64a_fpxxo
)
364 NEXT_NO_MODE_CHANGE(any
, fp32_fpxxo
)
367 START_STATE(fp32_fpxxo_fpxx
)
368 NEXT_NO_MODE_CHANGE(fp32
, fp32_fpxxo_fpxx
)
369 NEXT_NO_MODE_CHANGE(fpxxo
, fp32_fpxxo_fpxx
)
370 NEXT_NO_MODE_CHANGE(fpxx
, fp32_fpxxo_fpxx
)
371 NEXT_NO_MODE_CHANGE(fp64a
, fp32_fp64a_fpxxo_fpxx
)
372 NEXT_NO_MODE_CHANGE(any
, fp32_fpxxo_fpxx
)
375 START_STATE(fp64a_fp32
)
376 NEXT_REQ_FRE(fp32
, fp64a_fp32
)
377 NEXT_REQ_FRE(fp64a
, fp64a_fp32
)
378 NEXT(fpxxo
, fp32_fp64a_fpxxo
)
379 NEXT(fpxx
, fp32_fp64a_fpxx
)
380 NEXT(any
, fp64a_fp32
)
383 START_STATE(fp64a_fpxx
)
384 NEXT_REQ_FRE(fp32
, fp32_fp64a_fpxx
)
385 NEXT_REQ_FR1(fp64a
, fp64a_fpxx
)
386 NEXT(fpxx
, fp64a_fpxx
)
387 NEXT(fpxxo
, fp64a_fpxx_fpxxo
)
388 NEXT_REQ_FR1(fp64
, fp64a_fp64_fpxx
)
389 NEXT(any
, fp64a_fpxx
)
392 START_STATE(fp64a_fpxxo
)
393 NEXT_NO_MODE_CHANGE(fp32
, fp32_fp64a_fpxxo
)
394 NEXT_NO_MODE_CHANGE(fp64a
, fp64a_fpxxo
)
395 NEXT_NO_MODE_CHANGE(fpxx
, fp64a_fpxx_fpxxo
)
396 NEXT_NO_MODE_CHANGE(fpxxo
, fp64a_fpxxo
)
397 NEXT_NO_MODE_CHANGE(fp64
, fp64a_fp64_fpxxo
)
398 NEXT_NO_MODE_CHANGE(any
, fp64a_fpxxo
)
401 START_STATE(fp64a_fpxx_fpxxo
)
402 NEXT_NO_MODE_CHANGE(fp32
, fp32_fp64a_fpxxo_fpxx
)
403 NEXT_NO_MODE_CHANGE(fp64a
, fp64a_fpxx_fpxxo
)
404 NEXT_NO_MODE_CHANGE(fpxx
, fp64a_fpxx_fpxxo
)
405 NEXT_NO_MODE_CHANGE(fpxxo
, fp64a_fpxx_fpxxo
)
406 NEXT_NO_MODE_CHANGE(fp64
, fp64a_fp64_fpxxo_fpxx
)
407 NEXT_NO_MODE_CHANGE(any
, fp64a_fpxx_fpxxo
)
410 START_STATE(fp64_fpxx
)
411 NEXT_REQ_FR1(fp64a
, fp64a_fp64_fpxx
)
412 NEXT(fpxxo
, fp64_fpxx_fpxxo
)
413 NEXT(fpxx
, fp64_fpxx
)
414 NEXT_REQ_FR1(fp64
, fp64_fpxx
)
418 START_STATE(fp64_fpxxo
)
419 NEXT_NO_MODE_CHANGE(fp64a
, fp64a_fp64_fpxxo
)
420 NEXT_NO_MODE_CHANGE(fpxxo
, fp64_fpxxo
)
421 NEXT_NO_MODE_CHANGE(fpxx
, fp64_fpxx_fpxxo
)
422 NEXT_NO_MODE_CHANGE(fp64
, fp64_fpxxo
)
423 NEXT_NO_MODE_CHANGE(any
, fp64_fpxxo
)
426 START_STATE(fp64_fpxx_fpxxo
)
427 NEXT_NO_MODE_CHANGE(fp64a
, fp64a_fp64_fpxxo_fpxx
)
428 NEXT_NO_MODE_CHANGE(fpxxo
, fp64_fpxx_fpxxo
)
429 NEXT_NO_MODE_CHANGE(fpxx
, fp64_fpxx_fpxxo
)
430 NEXT_NO_MODE_CHANGE(fp64
, fp64_fpxx_fpxxo
)
431 NEXT_NO_MODE_CHANGE(any
, fp64_fpxx_fpxxo
)
434 START_STATE(fp64a_fp64
)
435 NEXT_REQ_FR1(fp64a
, fp64a_fp64
)
436 NEXT(fpxxo
, fp64a_fp64_fpxxo
)
437 NEXT(fpxx
, fp64a_fp64_fpxx
)
438 NEXT_REQ_FR1(fp64
, fp64a_fp64
)
439 NEXT(any
, fp64a_fp64
)
442 START_STATE(fp64a_fp64_fpxx
)
443 NEXT_REQ_FR1(fp64a
, fp64a_fp64_fpxx
)
444 NEXT(fpxxo
, fp64a_fp64_fpxxo_fpxx
)
445 NEXT(fpxx
, fp64a_fp64_fpxx
)
446 NEXT_REQ_FR1(fp64
, fp64a_fp64_fpxx
)
447 NEXT(any
, fp64a_fp64_fpxx
)
450 START_STATE(fp64a_fp64_fpxxo
)
451 NEXT_NO_MODE_CHANGE(fp64a
, fp64a_fp64_fpxxo
)
452 NEXT_NO_MODE_CHANGE(fpxx
, fp64a_fp64_fpxxo_fpxx
)
453 NEXT_NO_MODE_CHANGE(fpxxo
, fp64a_fp64_fpxxo
)
454 NEXT_NO_MODE_CHANGE(fp64
, fp64a_fp64_fpxxo
)
455 NEXT_NO_MODE_CHANGE(any
, fp64a_fp64_fpxxo
)
458 START_STATE(fp64a_fp64_fpxxo_fpxx
)
459 NEXT_NO_MODE_CHANGE(fp64a
, fp64a_fp64_fpxxo_fpxx
)
460 NEXT_NO_MODE_CHANGE(fpxx
, fp64a_fp64_fpxxo_fpxx
)
461 NEXT_NO_MODE_CHANGE(fpxxo
, fp64a_fp64_fpxxo_fpxx
)
462 NEXT_NO_MODE_CHANGE(fp64
, fp64a_fp64_fpxxo_fpxx
)
463 NEXT_NO_MODE_CHANGE(any
, fp64a_fp64_fpxxo_fpxx
)
466 START_STATE(fp32_fp64a_fpxx
)
467 NEXT_REQ_FRE(fp32
, fp32_fp64a_fpxx
)
468 NEXT_REQ_FRE(fp64a
, fp32_fp64a_fpxx
)
469 NEXT(fpxxo
, fp32_fp64a_fpxxo_fpxx
)
470 NEXT(fpxx
, fp32_fp64a_fpxx
)
471 NEXT(any
, fp32_fp64a_fpxx
)
474 START_STATE(fp32_fp64a_fpxxo
)
475 NEXT_NO_MODE_CHANGE(fp32
, fp32_fp64a_fpxxo
)
476 NEXT_NO_MODE_CHANGE(fp64a
, fp32_fp64a_fpxxo
)
477 NEXT_NO_MODE_CHANGE(fpxx
, fp32_fp64a_fpxxo_fpxx
)
478 NEXT_NO_MODE_CHANGE(fpxxo
, fp32_fp64a_fpxxo
)
479 NEXT_NO_MODE_CHANGE(any
, fp32_fp64a_fpxxo
)
482 START_STATE(fp32_fp64a_fpxxo_fpxx
)
483 NEXT_NO_MODE_CHANGE(fp32
, fp32_fp64a_fpxxo_fpxx
)
484 NEXT_NO_MODE_CHANGE(fp64a
, fp32_fp64a_fpxxo_fpxx
)
485 NEXT_NO_MODE_CHANGE(fpxx
, fp32_fp64a_fpxxo_fpxx
)
486 NEXT_NO_MODE_CHANGE(fpxxo
, fp32_fp64a_fpxxo_fpxx
)
487 NEXT_NO_MODE_CHANGE(any
, fp32_fp64a_fpxxo_fpxx
)
497 /* Run the state machine by removing an object. */
500 remove_object (enum fp_obj obj
)
507 /* We can't change fp state until all the objects
508 of a particular type have been unloaded. */
509 if (fp_obj_count
[obj
] != 0)
512 switch (current_fp_state
)
546 START_STATE(fpxxo_fpxx
)
551 START_STATE(fp32_fpxx
)
556 START_STATE(fp32_fpxxo
)
561 START_STATE(fp32_fpxxo_fpxx
)
562 NEXT(fp32
, fpxxo_fpxx
)
563 NEXT(fpxxo
, fp32_fpxx
)
564 NEXT(fpxx
, fp32_fpxxo
)
567 START_STATE(fp64a_fp32
)
572 START_STATE(fp64a_fpxx
)
577 START_STATE(fp64a_fpxxo
)
582 START_STATE(fp64a_fpxx_fpxxo
)
583 NEXT(fp64a
, fpxxo_fpxx
)
584 NEXT(fpxx
, fp64a_fpxxo
)
585 NEXT(fpxxo
, fp64a_fpxx
)
588 START_STATE(fp64_fpxx
)
593 START_STATE(fp64_fpxxo
)
598 START_STATE(fp64_fpxx_fpxxo
)
599 NEXT(fp64
, fpxxo_fpxx
)
600 NEXT(fpxxo
, fp64_fpxx
)
601 NEXT(fpxx
, fp64_fpxxo
)
604 START_STATE(fp64a_fp64
)
609 START_STATE(fp64a_fp64_fpxx
)
610 NEXT(fp64a
, fp64_fpxx
)
611 NEXT(fpxx
, fp64a_fp64
)
612 NEXT(fp64
, fp64a_fpxx
)
615 START_STATE(fp64a_fp64_fpxxo
)
616 NEXT(fp64a
, fp64_fpxxo
)
617 NEXT(fpxxo
, fp64a_fp64
)
618 NEXT(fp64
, fp64a_fpxxo
)
621 START_STATE(fp64a_fp64_fpxxo_fpxx
)
622 NEXT(fp64a
, fp64_fpxx_fpxxo
)
623 NEXT(fpxx
, fp64a_fp64_fpxxo
)
624 NEXT(fpxxo
, fp64a_fp64_fpxx
)
625 NEXT(fp64
, fp64a_fpxx_fpxxo
)
628 START_STATE(fp32_fp64a_fpxx
)
629 NEXT(fp32
, fp64a_fpxx
)
630 NEXT(fp64a
, fp32_fpxx
)
631 NEXT(fpxx
, fp64a_fp32
)
634 START_STATE(fp32_fp64a_fpxxo
)
635 NEXT(fp32
, fp64a_fpxxo
)
636 NEXT(fp64a
, fp32_fpxxo
)
637 NEXT(fpxxo
, fp64a_fp32
)
640 START_STATE(fp32_fp64a_fpxxo_fpxx
)
641 NEXT(fp32
, fp64a_fpxx_fpxxo
)
642 NEXT(fp64a
, fp32_fpxxo_fpxx
)
643 NEXT(fpxx
, fp32_fp64a_fpxxo
)
644 NEXT(fpxxo
, fp32_fp64a_fpxx
)
652 mode_transition_valid_p (void)
656 /* Get the current fp mode. */
657 prev_fp_mode
= current_fp_mode
;
658 #if HAVE_PRCTL_FP_MODE
659 current_fp_mode
= prctl (PR_GET_FP_MODE
);
661 /* If the prctl call fails assume the core only has FR0 mode support. */
662 if (current_fp_mode
== -1)
666 if (!current_mode_valid_p (current_fp_state
))
669 /* Check if mode changes are not allowed but a mode change happened. */
671 && current_fp_mode
!= prev_fp_mode
)
677 /* Load OBJ and check that it was/was not loaded correctly. */
679 load_object (enum fp_obj obj
)
681 bool should_load
= set_next_fp_state (obj
);
683 shared_lib_ptrs
[obj
] = dlopen (shared_lib_names
[obj
], RTLD_LAZY
);
685 /* If we expected an error and the load was successful then fail. */
686 if (!should_load
&& (shared_lib_ptrs
[obj
] != 0))
689 if (should_load
&& (shared_lib_ptrs
[obj
] == 0))
692 if (!mode_transition_valid_p ())
698 /* Remove an object and check the state remains valid. */
700 unload_object (enum fp_obj obj
)
702 if (!shared_lib_ptrs
[obj
])
707 if (dlclose (shared_lib_ptrs
[obj
]) != 0)
710 shared_lib_ptrs
[obj
] = 0;
712 if (!mode_transition_valid_p ())
718 /* Load every permuation of OBJECTS. */
720 test_permutations (enum fp_obj objects
[], int count
)
724 for (i
= 0 ; i
< count
; i
++)
726 if (!load_object (objects
[i
]))
731 enum fp_obj new_objects
[count
- 1];
735 for (j
= 0 ; j
< count
; j
++)
738 new_objects
[k
++] = objects
[j
];
741 if (!test_permutations (new_objects
, count
- 1))
745 if (!unload_object (objects
[i
]))
754 #if HAVE_PRCTL_FP_MODE
755 /* Determine available hardware support and current mode. */
756 current_fp_mode
= prctl (PR_GET_FP_MODE
);
758 /* If the prctl call fails assume the core only has FR0 mode support. */
759 if (current_fp_mode
== -1)
763 if (prctl (PR_SET_FP_MODE
, 0) != 0)
765 if (errno
== ENOTSUP
)
769 printf ("unexpected error from PR_SET_FP_MODE, 0: %m\n");
774 if (prctl (PR_SET_FP_MODE
, PR_FP_MODE_FR
) != 0)
776 if (errno
!= ENOTSUP
)
778 printf ("unexpected error from PR_SET_FP_MODE, "
779 "PR_FP_MODE_FR: %m\n");
786 if (prctl (PR_SET_FP_MODE
, PR_FP_MODE_FR
| PR_FP_MODE_FRE
) != 0)
788 if (errno
!= ENOTSUP
)
790 printf ("unexpected error from PR_SET_FP_MODE, "
791 "PR_FP_MODE_FR | PR_FP_MODE_FRE: %m\n");
798 if (prctl (PR_SET_FP_MODE
, current_fp_mode
) != 0)
800 printf ("unable to restore initial FP mode: %m\n");
805 if ((is_r6
&& !(current_fp_mode
& PR_FP_MODE_FR
))
806 || (!has_fr1
&& (current_fp_mode
& PR_FP_MODE_FR
))
807 || (!has_fre
&& (current_fp_mode
& PR_FP_MODE_FRE
)))
809 puts ("Inconsistency detected between initial FP mode "
810 "and supported FP modes\n");
817 /* Set up the initial state from executable and LDSO. Assumptions:
818 1) All system libraries have the same ABI as ld.so.
819 2) Due to the fact that ld.so is tested by invoking it directly
820 rather than via an interpreter, there is no point in varying
821 the ABI of the test program. Instead the ABI only varies for
822 the shared libraries which get loaded. */
823 if (!set_next_fp_state (FPABI_NATIVE
))
825 puts ("Unable to enter initial ABI state\n");
829 /* Compare the computed state with the hardware state. */
830 if (!mode_transition_valid_p ())
833 /* Run all possible test permutations. */
834 if (!test_permutations (test_objects
, FPABI_COUNT
))
836 puts ("Mode checks failed\n");
843 #define TEST_FUNCTION do_test ()
844 #include "../../test-skeleton.c"