linux/tools/testing/selftests/x86/test_FISTTP.c
<<
>>
Prefs
   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
  17unsigned long long res64 = -1;
  18unsigned int res32 = -1;
  19unsigned short res16 = -1;
  20
  21int 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        "       fisttp  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        "       fisttp  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        "       fisttp  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        "       fisttp  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
 112void sighandler(int sig)
 113{
 114        printf("[FAIL]\tGot signal %d, exiting\n", sig);
 115        exit(1);
 116}
 117
 118int 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