162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci#undef _GNU_SOURCE
362306a36Sopenharmony_ci#define _GNU_SOURCE 1
462306a36Sopenharmony_ci#undef __USE_GNU
562306a36Sopenharmony_ci#define __USE_GNU 1
662306a36Sopenharmony_ci#include <unistd.h>
762306a36Sopenharmony_ci#include <stdlib.h>
862306a36Sopenharmony_ci#include <string.h>
962306a36Sopenharmony_ci#include <stdio.h>
1062306a36Sopenharmony_ci#include <signal.h>
1162306a36Sopenharmony_ci#include <sys/types.h>
1262306a36Sopenharmony_ci#include <sys/select.h>
1362306a36Sopenharmony_ci#include <sys/time.h>
1462306a36Sopenharmony_ci#include <sys/wait.h>
1562306a36Sopenharmony_ci
1662306a36Sopenharmony_ci#define TEST(insn) \
1762306a36Sopenharmony_cilong double __attribute__((noinline)) insn(long flags) \
1862306a36Sopenharmony_ci{						\
1962306a36Sopenharmony_ci	long double out;			\
2062306a36Sopenharmony_ci	asm ("\n"				\
2162306a36Sopenharmony_ci	"	push	%1""\n"			\
2262306a36Sopenharmony_ci	"	popf""\n"			\
2362306a36Sopenharmony_ci	"	fldpi""\n"			\
2462306a36Sopenharmony_ci	"	fld1""\n"			\
2562306a36Sopenharmony_ci	"	" #insn " %%st(1), %%st" "\n"	\
2662306a36Sopenharmony_ci	"	ffree	%%st(1)" "\n"		\
2762306a36Sopenharmony_ci	: "=t" (out)				\
2862306a36Sopenharmony_ci	: "r" (flags)				\
2962306a36Sopenharmony_ci	);					\
3062306a36Sopenharmony_ci	return out;				\
3162306a36Sopenharmony_ci}
3262306a36Sopenharmony_ci
3362306a36Sopenharmony_ciTEST(fcmovb)
3462306a36Sopenharmony_ciTEST(fcmove)
3562306a36Sopenharmony_ciTEST(fcmovbe)
3662306a36Sopenharmony_ciTEST(fcmovu)
3762306a36Sopenharmony_ciTEST(fcmovnb)
3862306a36Sopenharmony_ciTEST(fcmovne)
3962306a36Sopenharmony_ciTEST(fcmovnbe)
4062306a36Sopenharmony_ciTEST(fcmovnu)
4162306a36Sopenharmony_ci
4262306a36Sopenharmony_cienum {
4362306a36Sopenharmony_ci	CF = 1 << 0,
4462306a36Sopenharmony_ci	PF = 1 << 2,
4562306a36Sopenharmony_ci	ZF = 1 << 6,
4662306a36Sopenharmony_ci};
4762306a36Sopenharmony_ci
4862306a36Sopenharmony_civoid sighandler(int sig)
4962306a36Sopenharmony_ci{
5062306a36Sopenharmony_ci	printf("[FAIL]\tGot signal %d, exiting\n", sig);
5162306a36Sopenharmony_ci	exit(1);
5262306a36Sopenharmony_ci}
5362306a36Sopenharmony_ci
5462306a36Sopenharmony_ciint main(int argc, char **argv, char **envp)
5562306a36Sopenharmony_ci{
5662306a36Sopenharmony_ci	int err = 0;
5762306a36Sopenharmony_ci
5862306a36Sopenharmony_ci	/* SIGILL triggers on 32-bit kernels w/o fcomi emulation
5962306a36Sopenharmony_ci	 * when run with "no387 nofxsr". Other signals are caught
6062306a36Sopenharmony_ci	 * just in case.
6162306a36Sopenharmony_ci	 */
6262306a36Sopenharmony_ci	signal(SIGILL, sighandler);
6362306a36Sopenharmony_ci	signal(SIGFPE, sighandler);
6462306a36Sopenharmony_ci	signal(SIGSEGV, sighandler);
6562306a36Sopenharmony_ci
6662306a36Sopenharmony_ci	printf("[RUN]\tTesting fcmovCC instructions\n");
6762306a36Sopenharmony_ci	/* If fcmovCC() returns 1.0, the move wasn't done */
6862306a36Sopenharmony_ci	err |= !(fcmovb(0)   == 1.0); err |= !(fcmovnb(0)  != 1.0);
6962306a36Sopenharmony_ci	err |= !(fcmove(0)   == 1.0); err |= !(fcmovne(0)  != 1.0);
7062306a36Sopenharmony_ci	err |= !(fcmovbe(0)  == 1.0); err |= !(fcmovnbe(0) != 1.0);
7162306a36Sopenharmony_ci	err |= !(fcmovu(0)   == 1.0); err |= !(fcmovnu(0)  != 1.0);
7262306a36Sopenharmony_ci
7362306a36Sopenharmony_ci	err |= !(fcmovb(CF)  != 1.0); err |= !(fcmovnb(CF)  == 1.0);
7462306a36Sopenharmony_ci	err |= !(fcmove(CF)  == 1.0); err |= !(fcmovne(CF)  != 1.0);
7562306a36Sopenharmony_ci	err |= !(fcmovbe(CF) != 1.0); err |= !(fcmovnbe(CF) == 1.0);
7662306a36Sopenharmony_ci	err |= !(fcmovu(CF)  == 1.0); err |= !(fcmovnu(CF)  != 1.0);
7762306a36Sopenharmony_ci
7862306a36Sopenharmony_ci	err |= !(fcmovb(ZF)  == 1.0); err |= !(fcmovnb(ZF)  != 1.0);
7962306a36Sopenharmony_ci	err |= !(fcmove(ZF)  != 1.0); err |= !(fcmovne(ZF)  == 1.0);
8062306a36Sopenharmony_ci	err |= !(fcmovbe(ZF) != 1.0); err |= !(fcmovnbe(ZF) == 1.0);
8162306a36Sopenharmony_ci	err |= !(fcmovu(ZF)  == 1.0); err |= !(fcmovnu(ZF)  != 1.0);
8262306a36Sopenharmony_ci
8362306a36Sopenharmony_ci	err |= !(fcmovb(PF)  == 1.0); err |= !(fcmovnb(PF)  != 1.0);
8462306a36Sopenharmony_ci	err |= !(fcmove(PF)  == 1.0); err |= !(fcmovne(PF)  != 1.0);
8562306a36Sopenharmony_ci	err |= !(fcmovbe(PF) == 1.0); err |= !(fcmovnbe(PF) != 1.0);
8662306a36Sopenharmony_ci	err |= !(fcmovu(PF)  != 1.0); err |= !(fcmovnu(PF)  == 1.0);
8762306a36Sopenharmony_ci
8862306a36Sopenharmony_ci        if (!err)
8962306a36Sopenharmony_ci                printf("[OK]\tfcmovCC\n");
9062306a36Sopenharmony_ci	else
9162306a36Sopenharmony_ci		printf("[FAIL]\tfcmovCC errors: %d\n", err);
9262306a36Sopenharmony_ci
9362306a36Sopenharmony_ci	return err;
9462306a36Sopenharmony_ci}
95