cregit-Linux how code gets into the kernel

Release 4.7 tools/testing/selftests/x86/test_FCOMI.c


#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>

enum {
	
CF = 1 << 0,
	
PF = 1 << 2,
	
ZF = 1 << 6,
	
ARITH = CF | PF | ZF,
};


long res_fcomi_pi_1;

long res_fcomi_1_pi;

long res_fcomi_1_1;

long res_fcomi_nan_1;
/* sNaN is s|111 1111 1|1xx xxxx xxxx xxxx xxxx xxxx */
/* qNaN is s|111 1111 1|0xx xxxx xxxx xxxx xxxx xxxx (some x must be nonzero) */

int snan = 0x7fc11111;

int qnan = 0x7f811111;

unsigned short snan1[5];
/* sNaN80 is s|111 1111 1111 1111 |10xx xx...xx (some x must be nonzero) */

unsigned short snan80[5] = { 0x1111, 0x1111, 0x1111, 0x8111, 0x7fff };


int test(long flags) { feclearexcept(FE_DIVBYZERO|FE_INEXACT|FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW); asm ("\n" " push %0""\n" " popf""\n" " fld1""\n" " fldpi""\n" " fcomi %%st(1), %%st" "\n" " ffree %%st(0)" "\n" " ffree %%st(1)" "\n" " pushf""\n" " pop res_fcomi_1_pi""\n" " push %0""\n" " popf""\n" " fldpi""\n" " fld1""\n" " fcomi %%st(1), %%st" "\n" " ffree %%st(0)" "\n" " ffree %%st(1)" "\n" " pushf""\n" " pop res_fcomi_pi_1""\n" " push %0""\n" " popf""\n" " fld1""\n" " fld1""\n" " fcomi %%st(1), %%st" "\n" " ffree %%st(0)" "\n" " ffree %%st(1)" "\n" " pushf""\n" " pop res_fcomi_1_1""\n" : : "r" (flags) ); if ((res_fcomi_1_pi & ARITH) != (0)) { printf("[BAD]\tfcomi_1_pi with flags:%lx\n", flags); return 1; } if ((res_fcomi_pi_1 & ARITH) != (CF)) { printf("[BAD]\tfcomi_pi_1 with flags:%lx->%lx\n", flags, res_fcomi_pi_1 & ARITH); return 1; } if ((res_fcomi_1_1 & ARITH) != (ZF)) { printf("[BAD]\tfcomi_1_1 with flags:%lx\n", flags); return 1; } if (fetestexcept(FE_INVALID) != 0) { printf("[BAD]\tFE_INVALID is set in %s\n", __func__); return 1; } return 0; }

Contributors

PersonTokensPropCommitsCommitProp
denys vlasenkodenys vlasenko122100.00%1100.00%
Total122100.00%1100.00%


int test_qnan(long flags) { feclearexcept(FE_DIVBYZERO|FE_INEXACT|FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW); asm ("\n" " push %0""\n" " popf""\n" " flds qnan""\n" " fld1""\n" " fnclex""\n" // fld of a qnan raised FE_INVALID, clear it " fcomi %%st(1), %%st" "\n" " ffree %%st(0)" "\n" " ffree %%st(1)" "\n" " pushf""\n" " pop res_fcomi_nan_1""\n" : : "r" (flags) ); if ((res_fcomi_nan_1 & ARITH) != (ZF|CF|PF)) { printf("[BAD]\tfcomi_qnan_1 with flags:%lx\n", flags); return 1; } if (fetestexcept(FE_INVALID) != FE_INVALID) { printf("[BAD]\tFE_INVALID is not set in %s\n", __func__); return 1; } return 0; }

Contributors

PersonTokensPropCommitsCommitProp
denys vlasenkodenys vlasenko76100.00%1100.00%
Total76100.00%1100.00%


int testu_qnan(long flags) { feclearexcept(FE_DIVBYZERO|FE_INEXACT|FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW); asm ("\n" " push %0""\n" " popf""\n" " flds qnan""\n" " fld1""\n" " fnclex""\n" // fld of a qnan raised FE_INVALID, clear it " fucomi %%st(1), %%st" "\n" " ffree %%st(0)" "\n" " ffree %%st(1)" "\n" " pushf""\n" " pop res_fcomi_nan_1""\n" : : "r" (flags) ); if ((res_fcomi_nan_1 & ARITH) != (ZF|CF|PF)) { printf("[BAD]\tfcomi_qnan_1 with flags:%lx\n", flags); return 1; } if (fetestexcept(FE_INVALID) != 0) { printf("[BAD]\tFE_INVALID is set in %s\n", __func__); return 1; } return 0; }

Contributors

PersonTokensPropCommitsCommitProp
denys vlasenkodenys vlasenko76100.00%1100.00%
Total76100.00%1100.00%


int testu_snan(long flags) { feclearexcept(FE_DIVBYZERO|FE_INEXACT|FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW); asm ("\n" " push %0""\n" " popf""\n" // " flds snan""\n" // WRONG, this will convert 32-bit fp snan to a *qnan* in 80-bit fp register! // " fstpt snan1""\n" // if uncommented, it prints "snan1:7fff c111 1100 0000 0000" - c111, not 8111! // " fnclex""\n" // flds of a snan raised FE_INVALID, clear it " fldt snan80""\n" // fldt never raise FE_INVALID " fld1""\n" " fucomi %%st(1), %%st" "\n" " ffree %%st(0)" "\n" " ffree %%st(1)" "\n" " pushf""\n" " pop res_fcomi_nan_1""\n" : : "r" (flags) ); if ((res_fcomi_nan_1 & ARITH) != (ZF|CF|PF)) { printf("[BAD]\tfcomi_qnan_1 with flags:%lx\n", flags); return 1; } // printf("snan:%x snan1:%04x %04x %04x %04x %04x\n", snan, snan1[4], snan1[3], snan1[2], snan1[1], snan1[0]); if (fetestexcept(FE_INVALID) != FE_INVALID) { printf("[BAD]\tFE_INVALID is not set in %s\n", __func__); return 1; } return 0; }

Contributors

PersonTokensPropCommitsCommitProp
denys vlasenkodenys vlasenko81100.00%1100.00%
Total81100.00%1100.00%


int testp(long flags) { feclearexcept(FE_DIVBYZERO|FE_INEXACT|FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW); asm ("\n" " push %0""\n" " popf""\n" " fld1""\n" " fldpi""\n" " fcomip %%st(1), %%st" "\n" " ffree %%st(0)" "\n" " pushf""\n" " pop res_fcomi_1_pi""\n" " push %0""\n" " popf""\n" " fldpi""\n" " fld1""\n" " fcomip %%st(1), %%st" "\n" " ffree %%st(0)" "\n" " pushf""\n" " pop res_fcomi_pi_1""\n" " push %0""\n" " popf""\n" " fld1""\n" " fld1""\n" " fcomip %%st(1), %%st" "\n" " ffree %%st(0)" "\n" " pushf""\n" " pop res_fcomi_1_1""\n" : : "r" (flags) ); if ((res_fcomi_1_pi & ARITH) != (0)) { printf("[BAD]\tfcomi_1_pi with flags:%lx\n", flags); return 1; } if ((res_fcomi_pi_1 & ARITH) != (CF)) { printf("[BAD]\tfcomi_pi_1 with flags:%lx->%lx\n", flags, res_fcomi_pi_1 & ARITH); return 1; } if ((res_fcomi_1_1 & ARITH) != (ZF)) { printf("[BAD]\tfcomi_1_1 with flags:%lx\n", flags); return 1; } if (fetestexcept(FE_INVALID) != 0) { printf("[BAD]\tFE_INVALID is set in %s\n", __func__); return 1; } return 0; }

Contributors

PersonTokensPropCommitsCommitProp
denys vlasenkodenys vlasenko122100.00%1100.00%
Total122100.00%1100.00%


int testp_qnan(long flags) { feclearexcept(FE_DIVBYZERO|FE_INEXACT|FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW); asm ("\n" " push %0""\n" " popf""\n" " flds qnan""\n" " fld1""\n" " fnclex""\n" // fld of a qnan raised FE_INVALID, clear it " fcomip %%st(1), %%st" "\n" " ffree %%st(0)" "\n" " pushf""\n" " pop res_fcomi_nan_1""\n" : : "r" (flags) ); if ((res_fcomi_nan_1 & ARITH) != (ZF|CF|PF)) { printf("[BAD]\tfcomi_qnan_1 with flags:%lx\n", flags); return 1; } if (fetestexcept(FE_INVALID) != FE_INVALID) { printf("[BAD]\tFE_INVALID is not set in %s\n", __func__); return 1; } return 0; }

Contributors

PersonTokensPropCommitsCommitProp
denys vlasenkodenys vlasenko76100.00%1100.00%
Total76100.00%1100.00%


int testup_qnan(long flags) { feclearexcept(FE_DIVBYZERO|FE_INEXACT|FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW); asm ("\n" " push %0""\n" " popf""\n" " flds qnan""\n" " fld1""\n" " fnclex""\n" // fld of a qnan raised FE_INVALID, clear it " fucomip %%st(1), %%st" "\n" " ffree %%st(0)" "\n" " pushf""\n" " pop res_fcomi_nan_1""\n" : : "r" (flags) ); if ((res_fcomi_nan_1 & ARITH) != (ZF|CF|PF)) { printf("[BAD]\tfcomi_qnan_1 with flags:%lx\n", flags); return 1; } if (fetestexcept(FE_INVALID) != 0) { printf("[BAD]\tFE_INVALID is set in %s\n", __func__); return 1; } return 0; }

Contributors

PersonTokensPropCommitsCommitProp
denys vlasenkodenys vlasenko76100.00%1100.00%
Total76100.00%1100.00%


void sighandler(int sig) { printf("[FAIL]\tGot signal %d, exiting\n", sig); exit(1); }

Contributors

PersonTokensPropCommitsCommitProp
denys vlasenkodenys vlasenko20100.00%1100.00%
Total20100.00%1100.00%


int main(int argc, char **argv, char **envp) { int err = 0; /* SIGILL triggers on 32-bit kernels w/o fcomi 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 f[u]comi[p] instructions\n"); err |= test(0); err |= test_qnan(0); err |= testu_qnan(0); err |= testu_snan(0); err |= test(CF|ZF|PF); err |= test_qnan(CF|ZF|PF); err |= testu_qnan(CF|ZF|PF); err |= testu_snan(CF|ZF|PF); err |= testp(0); err |= testp_qnan(0); err |= testup_qnan(0); err |= testp(CF|ZF|PF); err |= testp_qnan(CF|ZF|PF); err |= testup_qnan(CF|ZF|PF); if (!err) printf("[OK]\tf[u]comi[p]\n"); else printf("[FAIL]\tf[u]comi[p] errors: %d\n", err); return err; }

Contributors

PersonTokensPropCommitsCommitProp
denys vlasenkodenys vlasenko197100.00%1100.00%
Total197100.00%1100.00%


Overall Contributors

PersonTokensPropCommitsCommitProp
denys vlasenkodenys vlasenko970100.00%1100.00%
Total970100.00%1100.00%
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.
{% endraw %}