packaing: switch off build_html
[platform/upstream/glibc.git] / sysdeps / mips / tst-abi-interlink.c
1 /* Copyright (C) 2014-2024 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)                                       \
39 case 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)                                   \
52 case o_ ## OBJ:                                                 \
53   current_fp_state = s_ ## NEXT_STATE;                          \
54   break;
55
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;
65
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;
76
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;
86
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;
99
100 static 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
107 struct fp_mode_req
108 {
109   int mode1;
110   int mode2;
111   int mode3;
112 };
113
114 enum 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
127 enum 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
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 };
167
168 /* This function will return the valid FP modes for the specified state.  */
169
170 static struct fp_mode_req
171 compute_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
260 static bool
261 current_mode_valid_p (enum fp_state s)
262 {
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);
267 }
268
269 /* Run the state machine by adding a new object.  */
270
271 static bool
272 set_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
499 static bool
500 remove_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
651 static int
652 mode_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 (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.  */
678 bool
679 load_object (enum fp_obj obj)
680 {
681   bool should_load = set_next_fp_state (obj);
682
683   shared_lib_ptrs[obj] = dlopen (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.  */
699 bool
700 unload_object (enum fp_obj obj)
701 {
702   if (!shared_lib_ptrs[obj])
703     return true;
704
705   remove_object (obj);
706
707   if (dlclose (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 permutation of OBJECTS.  */
719 static bool
720 test_permutations (enum fp_obj objects[], int count)
721 {
722   int i;
723
724   for (i = 0 ; i < count ; i++)
725     {
726       if (!load_object (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 (new_objects, count - 1))
742             return false;
743         }
744
745       if (!unload_object (objects[i]))
746         return false;
747     }
748   return true;
749 }
750
751 int
752 do_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 ("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 ("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 ("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 ("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 ("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 ("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 (test_objects, FPABI_COUNT))
835     {
836       puts ("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"