Home | History | Annotate | Download | only in x86
      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