linux: Make fdopendir fail with O_PATH (BZ 30373)
[glibc.git] / sysdeps / mips / tst-abi-interlink.c
blobccd136f4db2d91757bdbab6ce0cdafcefef16c73
1 /* Copyright (C) 2014-2023 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 <https://www.gnu.org/licenses/>. */
18 #include <sys/prctl.h>
19 #include <dlfcn.h>
20 #include <stdio.h>
21 #include <string.h>
22 #include <stdbool.h>
23 #include <errno.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)
29 #else
30 # define HAVE_PRCTL_FP_MODE 0
31 # define FR1_MODE 0x1
32 # define FRE_MODE 0x2
33 #endif
35 #define STR_VAL(VAL) #VAL
36 #define N_STR(VAL) STR_VAL(VAL)
38 #define START_STATE(NAME) \
39 case s_ ## NAME: \
40 { \
41 switch (obj) \
44 #define END_STATE \
45 default: \
46 return false; \
47 } \
48 break; \
51 #define NEXT(OBJ, NEXT_STATE) \
52 case o_ ## OBJ: \
53 current_fp_state = s_ ## NEXT_STATE; \
54 break;
56 #define NEXT_REQ_FR1(OBJ, NEXT_STATE) \
57 case o_ ## OBJ: \
58 { \
59 if (has_fr1) \
60 current_fp_state = s_ ## NEXT_STATE; \
61 else \
62 return false; \
63 } \
64 break;
66 #define NEXT_REQ_FR0(OBJ, NEXT_STATE) \
67 case o_ ## OBJ: \
68 { \
69 if (!is_r6 \
70 || (is_r6 && has_fr1 && has_fre)) \
71 current_fp_state = s_ ## NEXT_STATE; \
72 else \
73 return false; \
74 } \
75 break;
77 #define NEXT_REQ_FRE(OBJ, NEXT_STATE) \
78 case o_ ## OBJ: \
79 { \
80 if (has_fr1 && has_fre) \
81 current_fp_state = s_ ## NEXT_STATE; \
82 else \
83 return false; \
84 } \
85 break;
87 #define NEXT_NO_MODE_CHANGE(OBJ, NEXT_STATE) \
88 case o_ ## OBJ: \
89 { \
90 if (current_mode_valid_p (s_ ## NEXT_STATE)) \
91 { \
92 current_fp_state = s_ ## NEXT_STATE; \
93 cant_change_mode = true; \
94 } \
95 else \
96 return false; \
97 } \
98 break;
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"
107 struct fp_mode_req
109 int mode1;
110 int mode2;
111 int mode3;
114 enum fp_obj
116 o_any,
117 o_soft,
118 o_single,
119 o_fp32,
120 o_fp64,
121 o_fp64a,
122 o_fpxx,
123 o_fpxxo,
124 o_max
127 enum fp_state
129 s_any,
130 s_soft,
131 s_single,
132 s_fp32,
133 s_fpxx,
134 s_fpxxo,
135 s_fp64a,
136 s_fp64,
137 s_fpxxo_fpxx,
138 s_fp32_fpxx,
139 s_fp32_fpxxo,
140 s_fp32_fpxxo_fpxx,
141 s_fp32_fp64a_fpxx,
142 s_fp32_fp64a_fpxxo,
143 s_fp32_fp64a_fpxxo_fpxx,
144 s_fp64a_fp32,
145 s_fp64a_fpxx,
146 s_fp64a_fpxxo,
147 s_fp64a_fp64,
148 s_fp64a_fp64_fpxx,
149 s_fp64a_fp64_fpxxo,
150 s_fp64a_fpxx_fpxxo,
151 s_fp64a_fp64_fpxxo_fpxx,
152 s_fp64_fpxx,
153 s_fp64_fpxxo,
154 s_fp64_fpxx_fpxxo
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;
179 switch (state)
181 case s_single:
183 if (is_r6)
184 requirements.mode1 = FR1_MODE;
185 else
187 requirements.mode1 = 0;
188 requirements.mode2 = FR1_MODE;
190 break;
192 case s_fp32:
193 case s_fp32_fpxx:
194 case s_fp32_fpxxo:
195 case s_fp32_fpxxo_fpxx:
197 if (is_r6)
198 requirements.mode1 = FRE_MODE;
199 else
201 requirements.mode1 = 0;
202 requirements.mode2 = FRE_MODE;
204 break;
206 case s_fpxx:
207 case s_fpxxo:
208 case s_fpxxo_fpxx:
209 case s_any:
210 case s_soft:
212 if (is_r6)
214 requirements.mode1 = FR1_MODE;
215 requirements.mode2 = FRE_MODE;
217 else
219 requirements.mode1 = 0;
220 requirements.mode2 = FR1_MODE;
221 requirements.mode3 = FRE_MODE;
223 break;
225 case s_fp64a:
226 case s_fp64a_fpxx:
227 case s_fp64a_fpxxo:
228 case s_fp64a_fpxx_fpxxo:
230 requirements.mode1 = FR1_MODE;
231 requirements.mode2 = FRE_MODE;
232 break;
234 case s_fp64:
235 case s_fp64_fpxx:
236 case s_fp64_fpxxo:
237 case s_fp64_fpxx_fpxxo:
238 case s_fp64a_fp64:
239 case s_fp64a_fp64_fpxx:
240 case s_fp64a_fp64_fpxxo:
241 case s_fp64a_fp64_fpxxo_fpxx:
243 requirements.mode1 = FR1_MODE;
244 break;
246 case s_fp64a_fp32:
247 case s_fp32_fp64a_fpxx:
248 case s_fp32_fp64a_fpxxo:
249 case s_fp32_fp64a_fpxxo_fpxx:
251 requirements.mode1 = FRE_MODE;
252 break;
255 return requirements;
258 /* Check the current mode is suitable for the specified state. */
260 static bool
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. */
271 static bool
272 set_next_fp_state (enum fp_obj obj)
274 cant_change_mode = false;
275 switch (current_fp_state)
278 START_STATE(soft)
279 NEXT(soft,soft)
280 NEXT(any,soft)
281 END_STATE
283 START_STATE(single)
284 NEXT(single,single)
285 NEXT(any,single)
286 END_STATE
288 START_STATE(any)
289 NEXT_REQ_FR0(fp32, fp32)
290 NEXT(fpxx, fpxx)
291 NEXT(fpxxo, fpxxo)
292 NEXT_REQ_FR1(fp64a, fp64a)
293 NEXT_REQ_FR1(fp64, fp64)
294 NEXT(any,any)
295 NEXT(soft,soft)
296 NEXT(single,single)
297 END_STATE
299 START_STATE(fp32)
300 NEXT_REQ_FR0(fp32,fp32)
301 NEXT(fpxx, fp32_fpxx)
302 NEXT(fpxxo, fp32_fpxxo)
303 NEXT_REQ_FRE(fp64a, fp64a_fp32)
304 NEXT(any,fp32)
305 END_STATE
307 START_STATE(fpxx)
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)
312 NEXT(fpxx,fpxx)
313 NEXT(any,fpxx)
314 END_STATE
316 START_STATE(fpxxo)
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)
323 END_STATE
325 START_STATE(fp64a)
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)
331 NEXT(any, fp64a)
332 END_STATE
334 START_STATE(fp64)
335 NEXT_REQ_FR1(fp64a, fp64a_fp64)
336 NEXT(fpxxo, fp64_fpxxo)
337 NEXT(fpxx, fp64_fpxx)
338 NEXT_REQ_FR1(fp64, fp64)
339 NEXT(any, fp64)
340 END_STATE
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)
349 END_STATE
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)
356 NEXT(any, fp32_fpxx)
357 END_STATE
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)
365 END_STATE
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)
373 END_STATE
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)
381 END_STATE
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)
390 END_STATE
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)
399 END_STATE
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)
408 END_STATE
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)
415 NEXT(any, fp64_fpxx)
416 END_STATE
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)
424 END_STATE
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)
432 END_STATE
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)
440 END_STATE
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)
448 END_STATE
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)
456 END_STATE
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)
464 END_STATE
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)
472 END_STATE
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)
480 END_STATE
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)
488 END_STATE
491 if (obj != o_max)
492 fp_obj_count[obj]++;
494 return true;
497 /* Run the state machine by removing an object. */
499 static bool
500 remove_object (enum fp_obj obj)
502 if (obj == o_max)
503 return false;
505 fp_obj_count[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)
510 return false;
512 switch (current_fp_state)
514 START_STATE(soft)
515 NEXT(soft,any)
516 END_STATE
518 START_STATE(single)
519 NEXT(single,any)
520 END_STATE
522 START_STATE(any)
523 NEXT(any,any)
524 END_STATE
526 START_STATE(fp32)
527 NEXT (fp32,any)
528 END_STATE
530 START_STATE(fpxx)
531 NEXT (fpxx,any)
532 END_STATE
534 START_STATE(fpxxo)
535 NEXT (fpxxo,any)
536 END_STATE
538 START_STATE(fp64a)
539 NEXT(fp64a, any)
540 END_STATE
542 START_STATE(fp64)
543 NEXT(fp64, any)
544 END_STATE
546 START_STATE(fpxxo_fpxx)
547 NEXT(fpxx, fpxxo)
548 NEXT(fpxxo, fpxx)
549 END_STATE
551 START_STATE(fp32_fpxx)
552 NEXT(fp32, fpxx)
553 NEXT(fpxx, fp32)
554 END_STATE
556 START_STATE(fp32_fpxxo)
557 NEXT(fp32, fpxxo)
558 NEXT(fpxxo, fp32)
559 END_STATE
561 START_STATE(fp32_fpxxo_fpxx)
562 NEXT(fp32, fpxxo_fpxx)
563 NEXT(fpxxo, fp32_fpxx)
564 NEXT(fpxx, fp32_fpxxo)
565 END_STATE
567 START_STATE(fp64a_fp32)
568 NEXT(fp32, fp64a)
569 NEXT(fp64a, fp32)
570 END_STATE
572 START_STATE(fp64a_fpxx)
573 NEXT(fp64a, fpxx)
574 NEXT(fpxx, fp64a)
575 END_STATE
577 START_STATE(fp64a_fpxxo)
578 NEXT(fp64a, fpxxo)
579 NEXT(fpxxo, fp64a)
580 END_STATE
582 START_STATE(fp64a_fpxx_fpxxo)
583 NEXT(fp64a, fpxxo_fpxx)
584 NEXT(fpxx, fp64a_fpxxo)
585 NEXT(fpxxo, fp64a_fpxx)
586 END_STATE
588 START_STATE(fp64_fpxx)
589 NEXT(fpxx, fp64)
590 NEXT(fp64, fpxx)
591 END_STATE
593 START_STATE(fp64_fpxxo)
594 NEXT(fpxxo, fp64)
595 NEXT(fp64, fpxxo)
596 END_STATE
598 START_STATE(fp64_fpxx_fpxxo)
599 NEXT(fp64, fpxxo_fpxx)
600 NEXT(fpxxo, fp64_fpxx)
601 NEXT(fpxx, fp64_fpxxo)
602 END_STATE
604 START_STATE(fp64a_fp64)
605 NEXT(fp64a, fp64)
606 NEXT(fp64, fp64a)
607 END_STATE
609 START_STATE(fp64a_fp64_fpxx)
610 NEXT(fp64a, fp64_fpxx)
611 NEXT(fpxx, fp64a_fp64)
612 NEXT(fp64, fp64a_fpxx)
613 END_STATE
615 START_STATE(fp64a_fp64_fpxxo)
616 NEXT(fp64a, fp64_fpxxo)
617 NEXT(fpxxo, fp64a_fp64)
618 NEXT(fp64, fp64a_fpxxo)
619 END_STATE
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)
626 END_STATE
628 START_STATE(fp32_fp64a_fpxx)
629 NEXT(fp32, fp64a_fpxx)
630 NEXT(fp64a, fp32_fpxx)
631 NEXT(fpxx, fp64a_fp32)
632 END_STATE
634 START_STATE(fp32_fp64a_fpxxo)
635 NEXT(fp32, fp64a_fpxxo)
636 NEXT(fp64a, fp32_fpxxo)
637 NEXT(fpxxo, fp64a_fp32)
638 END_STATE
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)
645 END_STATE
648 return true;
651 static int
652 mode_transition_valid_p (void)
654 int prev_fp_mode;
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)
663 current_fp_mode = 0;
664 #endif
666 if (!current_mode_valid_p (current_fp_state))
667 return 0;
669 /* Check if mode changes are not allowed but a mode change happened. */
670 if (cant_change_mode
671 && current_fp_mode != prev_fp_mode)
672 return 0;
674 return 1;
677 /* Load OBJ and check that it was/was not loaded correctly. */
678 bool
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))
687 return false;
689 if (should_load && (shared_lib_ptrs[obj] == 0))
690 return false;
692 if (!mode_transition_valid_p ())
693 return false;
695 return true;
698 /* Remove an object and check the state remains valid. */
699 bool
700 unload_object (enum fp_obj obj)
702 if (!shared_lib_ptrs[obj])
703 return true;
705 remove_object (obj);
707 if (dlclose (shared_lib_ptrs[obj]) != 0)
708 return false;
710 shared_lib_ptrs[obj] = 0;
712 if (!mode_transition_valid_p ())
713 return false;
715 return true;
718 /* Load every permutation of OBJECTS. */
719 static bool
720 test_permutations (enum fp_obj objects[], int count)
722 int i;
724 for (i = 0 ; i < count ; i++)
726 if (!load_object (objects[i]))
727 return false;
729 if (count > 1)
731 enum fp_obj new_objects[count - 1];
732 int j;
733 int k = 0;
735 for (j = 0 ; j < count ; j++)
737 if (j != i)
738 new_objects[k++] = objects[j];
741 if (!test_permutations (new_objects, count - 1))
742 return false;
745 if (!unload_object (objects[i]))
746 return false;
748 return true;
752 do_test (void)
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)
760 current_fp_mode = 0;
761 else
763 if (prctl (PR_SET_FP_MODE, 0) != 0)
765 if (errno == ENOTSUP)
766 is_r6 = true;
767 else
769 printf ("unexpected error from PR_SET_FP_MODE, 0: %m\n");
770 return 1;
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");
780 return 1;
783 else
784 has_fr1 = true;
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");
792 return 1;
795 else
796 has_fre = true;
798 if (prctl (PR_SET_FP_MODE, current_fp_mode) != 0)
800 printf ("unable to restore initial FP mode: %m\n");
801 return 1;
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");
811 return 1;
813 #else
814 current_fp_mode = 0;
815 #endif
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");
826 return 1;
829 /* Compare the computed state with the hardware state. */
830 if (!mode_transition_valid_p ())
831 return 1;
833 /* Run all possible test permutations. */
834 if (!test_permutations (test_objects, FPABI_COUNT))
836 puts ("Mode checks failed\n");
837 return 1;
840 return 0;
843 #define TEST_FUNCTION do_test ()
844 #include "../../test-skeleton.c"