tst-mode-switch-3.c 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. /* Copyright (C) 2014-2019 Free Software Foundation, Inc.
  2. This file is part of the GNU C Library.
  3. The GNU C Library is free software; you can redistribute it and/or
  4. modify it under the terms of the GNU Lesser General Public
  5. License as published by the Free Software Foundation; either
  6. version 2.1 of the License, or (at your option) any later version.
  7. The GNU C Library is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  10. Lesser General Public License for more details.
  11. You should have received a copy of the GNU Lesser General Public
  12. License along with the GNU C Library; if not, see
  13. <http://www.gnu.org/licenses/>. */
  14. #include <errno.h>
  15. #include <stdio.h>
  16. #include <stdlib.h>
  17. #include <string.h>
  18. #include <unistd.h>
  19. #include <setjmp.h>
  20. #include <sys/prctl.h>
  21. #if __mips_fpr != 0 || _MIPS_SPFPSET != 16
  22. # error This test requires -mfpxx -mno-odd-spreg
  23. #endif
  24. /* This test verifies that mode changes between a setjmp and longjmp do
  25. not corrupt the state of callee-saved registers. */
  26. static int mode[6] =
  27. {
  28. 0,
  29. PR_FP_MODE_FR,
  30. PR_FP_MODE_FR | PR_FP_MODE_FRE,
  31. PR_FP_MODE_FR,
  32. 0,
  33. PR_FP_MODE_FR | PR_FP_MODE_FRE
  34. };
  35. static jmp_buf env;
  36. float check1 = 2.0;
  37. double check2 = 3.0;
  38. static int
  39. do_test (void)
  40. {
  41. int i;
  42. int result = 0;
  43. for (i = 0 ; i < 7 ; i++)
  44. {
  45. int retval;
  46. register float test1 __asm ("$f20");
  47. register double test2 __asm ("$f22");
  48. /* Hide what we are doing to $f20 and $f22 from the compiler. */
  49. __asm __volatile ("l.s %0,%2\n"
  50. "l.d %1,%3\n"
  51. : "=f" (test1), "=f" (test2)
  52. : "m" (check1), "m" (check2));
  53. retval = setjmp (env);
  54. /* Make sure the compiler knows we want to access the variables
  55. via the named registers again. */
  56. __asm __volatile ("" : : "f" (test1), "f" (test2));
  57. if (test1 != check1 || test2 != check2)
  58. {
  59. printf ("Corrupt register detected: $20 %f = %f, $22 %f = %f\n",
  60. test1, check1, test2, check2);
  61. result = 1;
  62. }
  63. if (retval == 0)
  64. {
  65. if (prctl (PR_SET_FP_MODE, mode[i % 6]) != 0
  66. && errno != ENOTSUP)
  67. {
  68. printf ("prctl PR_SET_FP_MODE failed: %m");
  69. exit (1);
  70. }
  71. longjmp (env, 0);
  72. }
  73. }
  74. return result;
  75. }
  76. #define TEST_FUNCTION do_test ()
  77. #include "../../test-skeleton.c"