Quellcodebibliothek Statistik Leitseite products/sources/formale Sprachen/C/Linux/tools/testing/selftests/x86/   (Open Source Betriebssystem Version 6.17.9©)  Datei vom 24.10.2025 mit Größe 7 kB image not shown  

Quelle  test_FCOMI.c   Sprache: C

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

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;
}

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;
}

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;
}

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;
}

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;
}

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;
}

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;
}

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 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;
}

Messung V0.5
C=95 H=96 G=95

¤ Dauer der Verarbeitung: 0.3 Sekunden  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.