1/* Copyright (C) 2014-2022 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
3
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.
8
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.
13
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/>. */
17
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>
24
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
34
35#define STR_VAL(VAL) #VAL
36#define N_STR(VAL) STR_VAL(VAL)
37
38#define START_STATE(NAME) \
39case s_ ## NAME: \
40 { \
41 switch (obj) \
42 {
43
44#define END_STATE \
45 default: \
46 return false; \
47 } \
48 break; \
49 }
50
51#define NEXT(OBJ, NEXT_STATE) \
52case o_ ## OBJ: \
53 current_fp_state = s_ ## NEXT_STATE; \
54 break;
55
56#define NEXT_REQ_FR1(OBJ, NEXT_STATE) \
57case o_ ## OBJ: \
58 { \
59 if (has_fr1) \
60 current_fp_state = s_ ## NEXT_STATE; \
61 else \
62 return false; \
63 } \
64 break;
65
66#define NEXT_REQ_FR0(OBJ, NEXT_STATE) \
67case 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;
76
77#define NEXT_REQ_FRE(OBJ, NEXT_STATE) \
78case o_ ## OBJ: \
79 { \
80 if (has_fr1 && has_fre) \
81 current_fp_state = s_ ## NEXT_STATE; \
82 else \
83 return false; \
84 } \
85 break;
86
87#define NEXT_NO_MODE_CHANGE(OBJ, NEXT_STATE) \
88case 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;
99
100static const char * const shared_lib_names[] =
101 {
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"
105 };
106
107struct fp_mode_req
108{
109 int mode1;
110 int mode2;
111 int mode3;
112};
113
114enum fp_obj
115{
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
125};
126
127enum fp_state
128{
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
155};
156
157
158static int current_fp_mode;
159static bool cant_change_mode = false;
160static bool has_fr1 = false;
161static bool has_fre = false;
162static bool is_r6 = false;
163static unsigned int fp_obj_count[o_max];
164void * shared_lib_ptrs[o_max];
165static enum fp_state current_fp_state = s_any;
166static enum fp_obj test_objects[FPABI_COUNT] = { FPABI_LIST };
167
168/* This function will return the valid FP modes for the specified state. */
169
170static struct fp_mode_req
171compute_fp_modes (enum fp_state state)
172{
173 struct fp_mode_req requirements;
174
175 requirements.mode1 = -1;
176 requirements.mode2 = -1;
177 requirements.mode3 = -1;
178
179 switch (state)
180 {
181 case s_single:
182 {
183 if (is_r6)
184 requirements.mode1 = FR1_MODE;
185 else
186 {
187 requirements.mode1 = 0;
188 requirements.mode2 = FR1_MODE;
189 }
190 break;
191 }
192 case s_fp32:
193 case s_fp32_fpxx:
194 case s_fp32_fpxxo:
195 case s_fp32_fpxxo_fpxx:
196 {
197 if (is_r6)
198 requirements.mode1 = FRE_MODE;
199 else
200 {
201 requirements.mode1 = 0;
202 requirements.mode2 = FRE_MODE;
203 }
204 break;
205 }
206 case s_fpxx:
207 case s_fpxxo:
208 case s_fpxxo_fpxx:
209 case s_any:
210 case s_soft:
211 {
212 if (is_r6)
213 {
214 requirements.mode1 = FR1_MODE;
215 requirements.mode2 = FRE_MODE;
216 }
217 else
218 {
219 requirements.mode1 = 0;
220 requirements.mode2 = FR1_MODE;
221 requirements.mode3 = FRE_MODE;
222 }
223 break;
224 }
225 case s_fp64a:
226 case s_fp64a_fpxx:
227 case s_fp64a_fpxxo:
228 case s_fp64a_fpxx_fpxxo:
229 {
230 requirements.mode1 = FR1_MODE;
231 requirements.mode2 = FRE_MODE;
232 break;
233 }
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:
242 {
243 requirements.mode1 = FR1_MODE;
244 break;
245 }
246 case s_fp64a_fp32:
247 case s_fp32_fp64a_fpxx:
248 case s_fp32_fp64a_fpxxo:
249 case s_fp32_fp64a_fpxxo_fpxx:
250 {
251 requirements.mode1 = FRE_MODE;
252 break;
253 }
254 }
255 return requirements;
256}
257
258/* Check the current mode is suitable for the specified state. */
259
260static bool
261current_mode_valid_p (enum fp_state s)
262{
263 struct fp_mode_req req = compute_fp_modes (state: s);
264 return (req.mode1 == current_fp_mode
265 || req.mode2 == current_fp_mode
266 || req.mode3 == current_fp_mode);
267}
268
269/* Run the state machine by adding a new object. */
270
271static bool
272set_next_fp_state (enum fp_obj obj)
273{
274 cant_change_mode = false;
275 switch (current_fp_state)
276 {
277
278 START_STATE(soft)
279 NEXT(soft,soft)
280 NEXT(any,soft)
281 END_STATE
282
283 START_STATE(single)
284 NEXT(single,single)
285 NEXT(any,single)
286 END_STATE
287
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
298
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
306
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
315
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
324
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
333
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
341
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
350
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
358
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
366
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
374
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
382
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
391
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
400
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
409
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
417
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
425
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
433
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
441
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
449
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
457
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
465
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
473
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
481
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
489 }
490
491 if (obj != o_max)
492 fp_obj_count[obj]++;
493
494 return true;
495}
496
497/* Run the state machine by removing an object. */
498
499static bool
500remove_object (enum fp_obj obj)
501{
502 if (obj == o_max)
503 return false;
504
505 fp_obj_count[obj]--;
506
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;
511
512 switch (current_fp_state)
513 {
514 START_STATE(soft)
515 NEXT(soft,any)
516 END_STATE
517
518 START_STATE(single)
519 NEXT(single,any)
520 END_STATE
521
522 START_STATE(any)
523 NEXT(any,any)
524 END_STATE
525
526 START_STATE(fp32)
527 NEXT (fp32,any)
528 END_STATE
529
530 START_STATE(fpxx)
531 NEXT (fpxx,any)
532 END_STATE
533
534 START_STATE(fpxxo)
535 NEXT (fpxxo,any)
536 END_STATE
537
538 START_STATE(fp64a)
539 NEXT(fp64a, any)
540 END_STATE
541
542 START_STATE(fp64)
543 NEXT(fp64, any)
544 END_STATE
545
546 START_STATE(fpxxo_fpxx)
547 NEXT(fpxx, fpxxo)
548 NEXT(fpxxo, fpxx)
549 END_STATE
550
551 START_STATE(fp32_fpxx)
552 NEXT(fp32, fpxx)
553 NEXT(fpxx, fp32)
554 END_STATE
555
556 START_STATE(fp32_fpxxo)
557 NEXT(fp32, fpxxo)
558 NEXT(fpxxo, fp32)
559 END_STATE
560
561 START_STATE(fp32_fpxxo_fpxx)
562 NEXT(fp32, fpxxo_fpxx)
563 NEXT(fpxxo, fp32_fpxx)
564 NEXT(fpxx, fp32_fpxxo)
565 END_STATE
566
567 START_STATE(fp64a_fp32)
568 NEXT(fp32, fp64a)
569 NEXT(fp64a, fp32)
570 END_STATE
571
572 START_STATE(fp64a_fpxx)
573 NEXT(fp64a, fpxx)
574 NEXT(fpxx, fp64a)
575 END_STATE
576
577 START_STATE(fp64a_fpxxo)
578 NEXT(fp64a, fpxxo)
579 NEXT(fpxxo, fp64a)
580 END_STATE
581
582 START_STATE(fp64a_fpxx_fpxxo)
583 NEXT(fp64a, fpxxo_fpxx)
584 NEXT(fpxx, fp64a_fpxxo)
585 NEXT(fpxxo, fp64a_fpxx)
586 END_STATE
587
588 START_STATE(fp64_fpxx)
589 NEXT(fpxx, fp64)
590 NEXT(fp64, fpxx)
591 END_STATE
592
593 START_STATE(fp64_fpxxo)
594 NEXT(fpxxo, fp64)
595 NEXT(fp64, fpxxo)
596 END_STATE
597
598 START_STATE(fp64_fpxx_fpxxo)
599 NEXT(fp64, fpxxo_fpxx)
600 NEXT(fpxxo, fp64_fpxx)
601 NEXT(fpxx, fp64_fpxxo)
602 END_STATE
603
604 START_STATE(fp64a_fp64)
605 NEXT(fp64a, fp64)
606 NEXT(fp64, fp64a)
607 END_STATE
608
609 START_STATE(fp64a_fp64_fpxx)
610 NEXT(fp64a, fp64_fpxx)
611 NEXT(fpxx, fp64a_fp64)
612 NEXT(fp64, fp64a_fpxx)
613 END_STATE
614
615 START_STATE(fp64a_fp64_fpxxo)
616 NEXT(fp64a, fp64_fpxxo)
617 NEXT(fpxxo, fp64a_fp64)
618 NEXT(fp64, fp64a_fpxxo)
619 END_STATE
620
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
627
628 START_STATE(fp32_fp64a_fpxx)
629 NEXT(fp32, fp64a_fpxx)
630 NEXT(fp64a, fp32_fpxx)
631 NEXT(fpxx, fp64a_fp32)
632 END_STATE
633
634 START_STATE(fp32_fp64a_fpxxo)
635 NEXT(fp32, fp64a_fpxxo)
636 NEXT(fp64a, fp32_fpxxo)
637 NEXT(fpxxo, fp64a_fp32)
638 END_STATE
639
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
646 }
647
648 return true;
649}
650
651static int
652mode_transition_valid_p (void)
653{
654 int prev_fp_mode;
655
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);
660
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
665
666 if (!current_mode_valid_p (s: current_fp_state))
667 return 0;
668
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;
673
674 return 1;
675}
676
677/* Load OBJ and check that it was/was not loaded correctly. */
678bool
679load_object (enum fp_obj obj)
680{
681 bool should_load = set_next_fp_state (obj);
682
683 shared_lib_ptrs[obj] = dlopen (file: shared_lib_names[obj], RTLD_LAZY);
684
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;
688
689 if (should_load && (shared_lib_ptrs[obj] == 0))
690 return false;
691
692 if (!mode_transition_valid_p ())
693 return false;
694
695 return true;
696}
697
698/* Remove an object and check the state remains valid. */
699bool
700unload_object (enum fp_obj obj)
701{
702 if (!shared_lib_ptrs[obj])
703 return true;
704
705 remove_object (obj);
706
707 if (dlclose (handle: shared_lib_ptrs[obj]) != 0)
708 return false;
709
710 shared_lib_ptrs[obj] = 0;
711
712 if (!mode_transition_valid_p ())
713 return false;
714
715 return true;
716}
717
718/* Load every permuation of OBJECTS. */
719static bool
720test_permutations (enum fp_obj objects[], int count)
721{
722 int i;
723
724 for (i = 0 ; i < count ; i++)
725 {
726 if (!load_object (obj: objects[i]))
727 return false;
728
729 if (count > 1)
730 {
731 enum fp_obj new_objects[count - 1];
732 int j;
733 int k = 0;
734
735 for (j = 0 ; j < count ; j++)
736 {
737 if (j != i)
738 new_objects[k++] = objects[j];
739 }
740
741 if (!test_permutations (objects: new_objects, count: count - 1))
742 return false;
743 }
744
745 if (!unload_object (obj: objects[i]))
746 return false;
747 }
748 return true;
749}
750
751int
752do_test (void)
753{
754#if HAVE_PRCTL_FP_MODE
755 /* Determine available hardware support and current mode. */
756 current_fp_mode = prctl (PR_GET_FP_MODE);
757
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
762 {
763 if (prctl (PR_SET_FP_MODE, 0) != 0)
764 {
765 if (errno == ENOTSUP)
766 is_r6 = true;
767 else
768 {
769 printf (format: "unexpected error from PR_SET_FP_MODE, 0: %m\n");
770 return 1;
771 }
772 }
773
774 if (prctl (PR_SET_FP_MODE, PR_FP_MODE_FR) != 0)
775 {
776 if (errno != ENOTSUP)
777 {
778 printf (format: "unexpected error from PR_SET_FP_MODE, "
779 "PR_FP_MODE_FR: %m\n");
780 return 1;
781 }
782 }
783 else
784 has_fr1 = true;
785
786 if (prctl (PR_SET_FP_MODE, PR_FP_MODE_FR | PR_FP_MODE_FRE) != 0)
787 {
788 if (errno != ENOTSUP)
789 {
790 printf (format: "unexpected error from PR_SET_FP_MODE, "
791 "PR_FP_MODE_FR | PR_FP_MODE_FRE: %m\n");
792 return 1;
793 }
794 }
795 else
796 has_fre = true;
797
798 if (prctl (PR_SET_FP_MODE, current_fp_mode) != 0)
799 {
800 printf (format: "unable to restore initial FP mode: %m\n");
801 return 1;
802 }
803 }
804
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)))
808 {
809 puts (s: "Inconsistency detected between initial FP mode "
810 "and supported FP modes\n");
811 return 1;
812 }
813#else
814 current_fp_mode = 0;
815#endif
816
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))
824 {
825 puts (s: "Unable to enter initial ABI state\n");
826 return 1;
827 }
828
829 /* Compare the computed state with the hardware state. */
830 if (!mode_transition_valid_p ())
831 return 1;
832
833 /* Run all possible test permutations. */
834 if (!test_permutations (objects: test_objects, count: FPABI_COUNT))
835 {
836 puts (s: "Mode checks failed\n");
837 return 1;
838 }
839
840 return 0;
841}
842
843#define TEST_FUNCTION do_test ()
844#include "../../test-skeleton.c"
845

source code of glibc/sysdeps/mips/tst-abi-interlink.c