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 #ifdef __clang__ 29 " fisttps res16""\n" 30 #else 31 " fisttp res16""\n" 32 #endif 33 " fld1""\n" 34 " fisttpl res32""\n" 35 " fld1""\n" 36 " fisttpll res64""\n" 37 : : : "memory" 38 ); 39 if (res16 != 1 || res32 != 1 || res64 != 1) { 40 printf("[BAD]\tfisttp 1\n"); 41 return 1; 42 } 43 ex = fetestexcept(FE_DIVBYZERO|FE_INEXACT|FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW); 44 if (ex != 0) { 45 printf("[BAD]\tfisttp 1: wrong exception state\n"); 46 return 1; 47 } 48 49 feclearexcept(FE_DIVBYZERO|FE_INEXACT|FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW); 50 asm volatile ("\n" 51 " fldpi""\n" 52 #ifdef __clang__ 53 " fisttps res16""\n" 54 #else 55 " fisttp res16""\n" 56 #endif 57 " fldpi""\n" 58 " fisttpl res32""\n" 59 " fldpi""\n" 60 " fisttpll res64""\n" 61 : : : "memory" 62 ); 63 if (res16 != 3 || res32 != 3 || res64 != 3) { 64 printf("[BAD]\tfisttp pi\n"); 65 return 1; 66 } 67 ex = fetestexcept(FE_DIVBYZERO|FE_INEXACT|FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW); 68 if (ex != FE_INEXACT) { 69 printf("[BAD]\tfisttp pi: wrong exception state\n"); 70 return 1; 71 } 72 73 feclearexcept(FE_DIVBYZERO|FE_INEXACT|FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW); 74 asm volatile ("\n" 75 " fldpi""\n" 76 " fchs""\n" 77 #ifdef __clang__ 78 " fisttps res16""\n" 79 #else 80 // clang will complain: ambiguous instructions require an explicit suffix 81 // (could be 'fisttps', or 'fisttpl') 82 " fisttp res16""\n" 83 #endif 84 " fldpi""\n" 85 " fchs""\n" 86 " fisttpl res32""\n" 87 " fldpi""\n" 88 " fchs""\n" 89 " fisttpll res64""\n" 90 : : : "memory" 91 ); 92 if (res16 != 0xfffd || res32 != 0xfffffffd || res64 != 0xfffffffffffffffdULL) { 93 printf("[BAD]\tfisttp -pi\n"); 94 return 1; 95 } 96 ex = fetestexcept(FE_DIVBYZERO|FE_INEXACT|FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW); 97 if (ex != FE_INEXACT) { 98 printf("[BAD]\tfisttp -pi: wrong exception state\n"); 99 return 1; 100 } 101 102 feclearexcept(FE_DIVBYZERO|FE_INEXACT|FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW); 103 asm volatile ("\n" 104 " fldln2""\n" 105 #ifdef __clang__ 106 " fisttps res16""\n" 107 #else 108 " fisttp res16""\n" 109 #endif 110 " fldln2""\n" 111 " fisttpl res32""\n" 112 " fldln2""\n" 113 " fisttpll res64""\n" 114 : : : "memory" 115 ); 116 /* Test truncation to zero (round-to-nearest would give 1 here) */ 117 if (res16 != 0 || res32 != 0 || res64 != 0) { 118 printf("[BAD]\tfisttp ln2\n"); 119 return 1; 120 } 121 ex = fetestexcept(FE_DIVBYZERO|FE_INEXACT|FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW); 122 if (ex != FE_INEXACT) { 123 printf("[BAD]\tfisttp ln2: wrong exception state\n"); 124 return 1; 125 } 126 127 return 0; 128 } 129 130 void sighandler(int sig) 131 { 132 printf("[FAIL]\tGot signal %d, exiting\n", sig); 133 exit(1); 134 } 135 136 int main(int argc, char **argv, char **envp) 137 { 138 int err = 0; 139 140 /* SIGILL triggers on 32-bit kernels w/o fisttp emulation 141 * when run with "no387 nofxsr". Other signals are caught 142 * just in case. 143 */ 144 signal(SIGILL, sighandler); 145 signal(SIGFPE, sighandler); 146 signal(SIGSEGV, sighandler); 147 148 printf("[RUN]\tTesting fisttp instructions\n"); 149 err |= test(); 150 if (!err) 151 printf("[OK]\tfisttp\n"); 152 else 153 printf("[FAIL]\tfisttp errors: %d\n", err); 154 155 return err; 156 } 157