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