1 // SPDX-License-Identifier: GPL-2.0 2 #undef _GNU_SOURCE 3 #define _GNU_SOURCE 1 4 #undef __USE_GNU 5 #define __USE_GNU 1 6 #include <unistd.h> 7 #include <stdlib.h> 8 #include <string.h> 9 #include <stdio.h> 10 #include <signal.h> 11 #include <sys/types.h> 12 #include <sys/select.h> 13 #include <sys/time.h> 14 #include <sys/wait.h> 15 #include <fenv.h> 16 17 unsigned long long res64 = -1; 18 unsigned int res32 = -1; 19 unsigned short res16 = -1; 20 21 int test(void) 22 { 23 int ex; 24 25 feclearexcept(FE_DIVBYZERO|FE_INEXACT|FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW); 26 asm volatile ("\n" 27 " fld1""\n" 28 " fisttps res16""\n" 29 " fld1""\n" 30 " fisttpl res32""\n" 31 " fld1""\n" 32 " fisttpll res64""\n" 33 : : : "memory" 34 ); 35 if (res16 != 1 || res32 != 1 || res64 != 1) { 36 printf("[BAD]\tfisttp 1\n"); 37 return 1; 38 } 39 ex = fetestexcept(FE_DIVBYZERO|FE_INEXACT|FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW); 40 if (ex != 0) { 41 printf("[BAD]\tfisttp 1: wrong exception state\n"); 42 return 1; 43 } 44 45 feclearexcept(FE_DIVBYZERO|FE_INEXACT|FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW); 46 asm volatile ("\n" 47 " fldpi""\n" 48 " fisttps res16""\n" 49 " fldpi""\n" 50 " fisttpl res32""\n" 51 " fldpi""\n" 52 " fisttpll res64""\n" 53 : : : "memory" 54 ); 55 if (res16 != 3 || res32 != 3 || res64 != 3) { 56 printf("[BAD]\tfisttp pi\n"); 57 return 1; 58 } 59 ex = fetestexcept(FE_DIVBYZERO|FE_INEXACT|FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW); 60 if (ex != FE_INEXACT) { 61 printf("[BAD]\tfisttp pi: wrong exception state\n"); 62 return 1; 63 } 64 65 feclearexcept(FE_DIVBYZERO|FE_INEXACT|FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW); 66 asm volatile ("\n" 67 " fldpi""\n" 68 " fchs""\n" 69 " fisttps res16""\n" 70 " fldpi""\n" 71 " fchs""\n" 72 " fisttpl res32""\n" 73 " fldpi""\n" 74 " fchs""\n" 75 " fisttpll res64""\n" 76 : : : "memory" 77 ); 78 if (res16 != 0xfffd || res32 != 0xfffffffd || res64 != 0xfffffffffffffffdULL) { 79 printf("[BAD]\tfisttp -pi\n"); 80 return 1; 81 } 82 ex = fetestexcept(FE_DIVBYZERO|FE_INEXACT|FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW); 83 if (ex != FE_INEXACT) { 84 printf("[BAD]\tfisttp -pi: wrong exception state\n"); 85 return 1; 86 } 87 88 feclearexcept(FE_DIVBYZERO|FE_INEXACT|FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW); 89 asm volatile ("\n" 90 " fldln2""\n" 91 " fisttps res16""\n" 92 " fldln2""\n" 93 " fisttpl res32""\n" 94 " fldln2""\n" 95 " fisttpll res64""\n" 96 : : : "memory" 97 ); 98 /* Test truncation to zero (round-to-nearest would give 1 here) */ 99 if (res16 != 0 || res32 != 0 || res64 != 0) { 100 printf("[BAD]\tfisttp ln2\n"); 101 return 1; 102 } 103 ex = fetestexcept(FE_DIVBYZERO|FE_INEXACT|FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW); 104 if (ex != FE_INEXACT) { 105 printf("[BAD]\tfisttp ln2: wrong exception state\n"); 106 return 1; 107 } 108 109 return 0; 110 } 111 112 void sighandler(int sig) 113 { 114 printf("[FAIL]\tGot signal %d, exiting\n", sig); 115 exit(1); 116 } 117 118 int main(int argc, char **argv, char **envp) 119 { 120 int err = 0; 121 122 /* SIGILL triggers on 32-bit kernels w/o fisttp emulation 123 * when run with "no387 nofxsr". Other signals are caught 124 * just in case. 125 */ 126 signal(SIGILL, sighandler); 127 signal(SIGFPE, sighandler); 128 signal(SIGSEGV, sighandler); 129 130 printf("[RUN]\tTesting fisttp instructions\n"); 131 err |= test(); 132 if (!err) 133 printf("[OK]\tfisttp\n"); 134 else 135 printf("[FAIL]\tfisttp errors: %d\n", err); 136 137 return err; 138 } 139