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) 					\
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
compute_fp_modes(enum fp_state state)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
current_mode_valid_p(enum fp_state s)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
set_next_fp_state(enum fp_obj obj)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
remove_object(enum fp_obj obj)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
mode_transition_valid_p(void)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
load_object(enum fp_obj obj)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
unload_object(enum fp_obj obj)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 permuation of OBJECTS.  */
719 static bool
test_permutations(enum fp_obj objects[],int count)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
do_test(void)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"
845