(root)/
glibc-2.38/
sysdeps/
mips/
tst-abi-interlink.c
       1  /* Copyright (C) 2014-2023 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"