123f13e19SIlya Leoshkevich #define _GNU_SOURCE
223f13e19SIlya Leoshkevich #include <fenv.h>
323f13e19SIlya Leoshkevich #include <stdbool.h>
423f13e19SIlya Leoshkevich #include <stdio.h>
523f13e19SIlya Leoshkevich #include <string.h>
623f13e19SIlya Leoshkevich
7*6dc29354SIlya Leoshkevich #include "float.h"
8*6dc29354SIlya Leoshkevich
923f13e19SIlya Leoshkevich /*
1023f13e19SIlya Leoshkevich * vfmin/vfmax instruction execution.
1123f13e19SIlya Leoshkevich */
1223f13e19SIlya Leoshkevich #define VFMIN 0xEE
1323f13e19SIlya Leoshkevich #define VFMAX 0xEF
1423f13e19SIlya Leoshkevich
1523f13e19SIlya Leoshkevich extern char insn[6];
1623f13e19SIlya Leoshkevich asm(".pushsection .rwx,\"awx\",@progbits\n"
1723f13e19SIlya Leoshkevich ".globl insn\n"
1823f13e19SIlya Leoshkevich /* e7 89 a0 00 2e ef */
1923f13e19SIlya Leoshkevich "insn: vfmaxsb %v24,%v25,%v26,0\n"
2023f13e19SIlya Leoshkevich ".popsection\n");
2123f13e19SIlya Leoshkevich
vfminmax(unsigned int op,unsigned int m4,unsigned int m5,unsigned int m6,void * v1,const void * v2,const void * v3)2223f13e19SIlya Leoshkevich static void vfminmax(unsigned int op,
2323f13e19SIlya Leoshkevich unsigned int m4, unsigned int m5, unsigned int m6,
2423f13e19SIlya Leoshkevich void *v1, const void *v2, const void *v3)
2523f13e19SIlya Leoshkevich {
2623f13e19SIlya Leoshkevich insn[3] = (m6 << 4) | m5;
2723f13e19SIlya Leoshkevich insn[4] = (m4 << 4) | 0x0e;
2823f13e19SIlya Leoshkevich insn[5] = op;
2923f13e19SIlya Leoshkevich
3023f13e19SIlya Leoshkevich asm("vl %%v25,%[v2]\n"
3123f13e19SIlya Leoshkevich "vl %%v26,%[v3]\n"
3223f13e19SIlya Leoshkevich "ex 0,%[insn]\n"
3323f13e19SIlya Leoshkevich "vst %%v24,%[v1]\n"
3423f13e19SIlya Leoshkevich : [v1] "=m" (*(char (*)[16])v1)
35*6dc29354SIlya Leoshkevich : [v2] "m" (*(const char (*)[16])v2)
36*6dc29354SIlya Leoshkevich , [v3] "m" (*(const char (*)[16])v3)
3723f13e19SIlya Leoshkevich , [insn] "m" (insn)
3823f13e19SIlya Leoshkevich : "v24", "v25", "v26");
3923f13e19SIlya Leoshkevich }
4023f13e19SIlya Leoshkevich
4123f13e19SIlya Leoshkevich /*
4223f13e19SIlya Leoshkevich * PoP tables as close to the original as possible.
4323f13e19SIlya Leoshkevich */
4423f13e19SIlya Leoshkevich struct signed_test {
4523f13e19SIlya Leoshkevich int op;
4623f13e19SIlya Leoshkevich int m6;
4723f13e19SIlya Leoshkevich const char *m6_desc;
4823f13e19SIlya Leoshkevich const char *table[N_SIGNED_CLASSES][N_SIGNED_CLASSES];
4923f13e19SIlya Leoshkevich } signed_tests[] = {
5023f13e19SIlya Leoshkevich {
5123f13e19SIlya Leoshkevich .op = VFMIN,
5223f13e19SIlya Leoshkevich .m6 = 0,
5323f13e19SIlya Leoshkevich .m6_desc = "IEEE MinNum",
5423f13e19SIlya Leoshkevich .table = {
5523f13e19SIlya Leoshkevich /* -inf -Fn -0 +0 +Fn +inf QNaN SNaN */
5623f13e19SIlya Leoshkevich {/* -inf */ "T(a)", "T(a)", "T(a)", "T(a)", "T(a)", "T(a)", "T(a)", "Xi: T(b*)"},
5723f13e19SIlya Leoshkevich {/* -Fn */ "T(b)", "T(M(a,b))", "T(a)", "T(a)", "T(a)", "T(a)", "T(a)", "Xi: T(b*)"},
5823f13e19SIlya Leoshkevich {/* -0 */ "T(b)", "T(b)", "T(a)", "T(a)", "T(a)", "T(a)", "T(a)", "Xi: T(b*)"},
5923f13e19SIlya Leoshkevich {/* +0 */ "T(b)", "T(b)", "T(b)", "T(a)", "T(a)", "T(a)", "T(a)", "Xi: T(b*)"},
6023f13e19SIlya Leoshkevich {/* +Fn */ "T(b)", "T(b)", "T(b)", "T(b)", "T(M(a,b))", "T(a)", "T(a)", "Xi: T(b*)"},
6123f13e19SIlya Leoshkevich {/* +inf */ "T(b)", "T(b)", "T(b)", "T(b)", "T(b)", "T(a)", "T(a)", "Xi: T(b*)"},
6223f13e19SIlya Leoshkevich {/* QNaN */ "T(b)", "T(b)", "T(b)", "T(b)", "T(b)", "T(b)", "T(a)", "Xi: T(b*)"},
6323f13e19SIlya Leoshkevich {/* SNaN */ "Xi: T(a*)", "Xi: T(a*)", "Xi: T(a*)", "Xi: T(a*)", "Xi: T(a*)", "Xi: T(a*)", "Xi: T(a*)", "Xi: T(a*)"},
6423f13e19SIlya Leoshkevich },
6523f13e19SIlya Leoshkevich },
6623f13e19SIlya Leoshkevich {
6723f13e19SIlya Leoshkevich .op = VFMIN,
6823f13e19SIlya Leoshkevich .m6 = 1,
6923f13e19SIlya Leoshkevich .m6_desc = "JAVA Math.Min()",
7023f13e19SIlya Leoshkevich .table = {
7123f13e19SIlya Leoshkevich /* -inf -Fn -0 +0 +Fn +inf QNaN SNaN */
7223f13e19SIlya Leoshkevich {/* -inf */ "T(b)", "T(a)", "T(a)", "T(a)", "T(a)", "T(a)", "T(b)", "Xi: T(b*)"},
7323f13e19SIlya Leoshkevich {/* -Fn */ "T(b)", "T(M(a,b))", "T(a)", "T(a)", "T(a)", "T(a)", "T(b)", "Xi: T(b*)"},
7423f13e19SIlya Leoshkevich {/* -0 */ "T(b)", "T(b)", "T(b)", "T(a)", "T(a)", "T(a)", "T(b)", "Xi: T(b*)"},
7523f13e19SIlya Leoshkevich {/* +0 */ "T(b)", "T(b)", "T(b)", "T(b)", "T(a)", "T(a)", "T(b)", "Xi: T(b*)"},
7623f13e19SIlya Leoshkevich {/* +Fn */ "T(b)", "T(b)", "T(b)", "T(b)", "T(M(a,b))", "T(a)", "T(b)", "Xi: T(b*)"},
7723f13e19SIlya Leoshkevich {/* +inf */ "T(b)", "T(b)", "T(b)", "T(b)", "T(b)", "T(b)", "T(b)", "Xi: T(b*)"},
7823f13e19SIlya Leoshkevich {/* QNaN */ "T(a)", "T(a)", "T(a)", "T(a)", "T(a)", "T(a)", "T(a)", "Xi: T(b*)"},
7923f13e19SIlya Leoshkevich {/* SNaN */ "Xi: T(a*)", "Xi: T(a*)", "Xi: T(a*)", "Xi: T(a*)", "Xi: T(a*)", "Xi: T(a*)", "Xi: T(a*)", "Xi: T(a*)"},
8023f13e19SIlya Leoshkevich },
8123f13e19SIlya Leoshkevich },
8223f13e19SIlya Leoshkevich {
8323f13e19SIlya Leoshkevich .op = VFMIN,
8423f13e19SIlya Leoshkevich .m6 = 2,
8523f13e19SIlya Leoshkevich .m6_desc = "C-style Min Macro",
8623f13e19SIlya Leoshkevich .table = {
8723f13e19SIlya Leoshkevich /* -inf -Fn -0 +0 +Fn +inf QNaN SNaN */
8823f13e19SIlya Leoshkevich {/* -inf */ "T(b)", "T(a)", "T(a)", "T(a)", "T(a)", "T(a)", "Xi: T(b)", "Xi: T(b)"},
8923f13e19SIlya Leoshkevich {/* -Fn */ "T(b)", "T(M(a,b))", "T(a)", "T(a)", "T(a)", "T(a)", "Xi: T(b)", "Xi: T(b)"},
9023f13e19SIlya Leoshkevich {/* -0 */ "T(b)", "T(b)", "T(b)", "T(b)", "T(a)", "T(a)", "Xi: T(b)", "Xi: T(b)"},
9123f13e19SIlya Leoshkevich {/* +0 */ "T(b)", "T(b)", "T(b)", "T(b)", "T(a)", "T(a)", "Xi: T(b)", "Xi: T(b)"},
9223f13e19SIlya Leoshkevich {/* +Fn */ "T(b)", "T(b)", "T(b)", "T(b)", "T(M(a,b))", "T(a)", "Xi: T(b)", "Xi: T(b)"},
9323f13e19SIlya Leoshkevich {/* +inf */ "T(b)", "T(b)", "T(b)", "T(b)", "T(b)", "T(a)", "Xi: T(b)", "Xi: T(b)"},
9423f13e19SIlya Leoshkevich {/* QNaN */ "Xi: T(b)", "Xi: T(b)", "Xi: T(b)", "Xi: T(b)", "Xi: T(b)", "Xi: T(b)", "Xi: T(b)", "Xi: T(b)"},
9523f13e19SIlya Leoshkevich {/* SNaN */ "Xi: T(b)", "Xi: T(b)", "Xi: T(b)", "Xi: T(b)", "Xi: T(b)", "Xi: T(b)", "Xi: T(b)", "Xi: T(b)"},
9623f13e19SIlya Leoshkevich },
9723f13e19SIlya Leoshkevich },
9823f13e19SIlya Leoshkevich {
9923f13e19SIlya Leoshkevich .op = VFMIN,
10023f13e19SIlya Leoshkevich .m6 = 3,
10123f13e19SIlya Leoshkevich .m6_desc = "C++ algorithm.min()",
10223f13e19SIlya Leoshkevich .table = {
10323f13e19SIlya Leoshkevich /* -inf -Fn -0 +0 +Fn +inf QNaN SNaN */
10423f13e19SIlya Leoshkevich {/* -inf */ "T(b)", "T(a)", "T(a)", "T(a)", "T(a)", "T(a)", "Xi: T(a)", "Xi: T(a)"},
10523f13e19SIlya Leoshkevich {/* -Fn */ "T(b)", "T(M(a,b))", "T(a)", "T(a)", "T(a)", "T(a)", "Xi: T(a)", "Xi: T(a)"},
10623f13e19SIlya Leoshkevich {/* -0 */ "T(b)", "T(b)", "T(a)", "T(a)", "T(a)", "T(a)", "Xi: T(a)", "Xi: T(a)"},
10723f13e19SIlya Leoshkevich {/* +0 */ "T(b)", "T(b)", "T(a)", "T(a)", "T(a)", "T(a)", "Xi: T(a)", "Xi: T(a)"},
10823f13e19SIlya Leoshkevich {/* +Fn */ "T(b)", "T(b)", "T(b)", "T(b)", "T(M(a,b))", "T(a)", "Xi: T(a)", "Xi: T(a)"},
10923f13e19SIlya Leoshkevich {/* +inf */ "T(b)", "T(b)", "T(b)", "T(b)", "T(b)", "T(a)", "Xi: T(a)", "Xi: T(a)"},
11023f13e19SIlya Leoshkevich {/* QNaN */ "Xi: T(a)", "Xi: T(a)", "Xi: T(a)", "Xi: T(a)", "Xi: T(a)", "Xi: T(a)", "Xi: T(a)", "Xi: T(a)"},
11123f13e19SIlya Leoshkevich {/* SNaN */ "Xi: T(a)", "Xi: T(a)", "Xi: T(a)", "Xi: T(a)", "Xi: T(a)", "Xi: T(a)", "Xi: T(a)", "Xi: T(a)"},
11223f13e19SIlya Leoshkevich },
11323f13e19SIlya Leoshkevich },
11423f13e19SIlya Leoshkevich {
11523f13e19SIlya Leoshkevich .op = VFMIN,
11623f13e19SIlya Leoshkevich .m6 = 4,
11723f13e19SIlya Leoshkevich .m6_desc = "fmin()",
11823f13e19SIlya Leoshkevich .table = {
11923f13e19SIlya Leoshkevich /* -inf -Fn -0 +0 +Fn +inf QNaN SNaN */
12023f13e19SIlya Leoshkevich {/* -inf */ "T(a)", "T(a)", "T(a)", "T(a)", "T(a)", "T(a)", "T(a)", "Xi: T(a)"},
12123f13e19SIlya Leoshkevich {/* -Fn */ "T(b)", "T(M(a,b))", "T(a)", "T(a)", "T(a)", "T(a)", "T(a)", "Xi: T(a)"},
12223f13e19SIlya Leoshkevich {/* -0 */ "T(b)", "T(b)", "T(a)", "T(a)", "T(a)", "T(a)", "T(a)", "Xi: T(a)"},
12323f13e19SIlya Leoshkevich {/* +0 */ "T(b)", "T(b)", "T(b)", "T(a)", "T(a)", "T(a)", "T(a)", "Xi: T(a)"},
12423f13e19SIlya Leoshkevich {/* +Fn */ "T(b)", "T(b)", "T(b)", "T(b)", "T(M(a,b))", "T(a)", "T(a)", "Xi: T(a)"},
12523f13e19SIlya Leoshkevich {/* +inf */ "T(b)", "T(b)", "T(b)", "T(b)", "T(b)", "T(a)", "T(a)", "Xi: T(a)"},
12623f13e19SIlya Leoshkevich {/* QNaN */ "T(b)", "T(b)", "T(b)", "T(b)", "T(b)", "T(b)", "T(a)", "Xi: T(a)"},
12723f13e19SIlya Leoshkevich {/* SNaN */ "Xi: T(b)", "Xi: T(b)", "Xi: T(b)", "Xi: T(b)", "Xi: T(b)", "Xi: T(b)", "Xi: T(a)", "Xi: T(a)"},
12823f13e19SIlya Leoshkevich },
12923f13e19SIlya Leoshkevich },
13023f13e19SIlya Leoshkevich
13123f13e19SIlya Leoshkevich {
13223f13e19SIlya Leoshkevich .op = VFMAX,
13323f13e19SIlya Leoshkevich .m6 = 0,
13423f13e19SIlya Leoshkevich .m6_desc = "IEEE MaxNum",
13523f13e19SIlya Leoshkevich .table = {
13623f13e19SIlya Leoshkevich /* -inf -Fn -0 +0 +Fn +inf QNaN SNaN */
13723f13e19SIlya Leoshkevich {/* -inf */ "T(a)", "T(b)", "T(b)", "T(b)", "T(b)", "T(b)", "T(a)", "Xi: T(b*)"},
13823f13e19SIlya Leoshkevich {/* -Fn */ "T(a)", "T(M(a,b))", "T(b)", "T(b)", "T(b)", "T(b)", "T(a)", "Xi: T(b*)"},
13923f13e19SIlya Leoshkevich {/* -0 */ "T(a)", "T(a)", "T(a)", "T(b)", "T(b)", "T(b)", "T(a)", "Xi: T(b*)"},
14023f13e19SIlya Leoshkevich {/* +0 */ "T(a)", "T(a)", "T(a)", "T(a)", "T(b)", "T(b)", "T(a)", "Xi: T(b*)"},
14123f13e19SIlya Leoshkevich {/* +Fn */ "T(a)", "T(a)", "T(a)", "T(a)", "T(M(a,b))", "T(b)", "T(a)", "Xi: T(b*)"},
14223f13e19SIlya Leoshkevich {/* +inf */ "T(a)", "T(a)", "T(a)", "T(a)", "T(a)", "T(a)", "T(a)", "Xi: T(b*)"},
14323f13e19SIlya Leoshkevich {/* QNaN */ "T(b)", "T(b)", "T(b)", "T(b)", "T(b)", "T(b)", "T(a)", "Xi: T(b*)"},
14423f13e19SIlya Leoshkevich {/* SNaN */ "Xi: T(a*)", "Xi: T(a*)", "Xi: T(a*)", "Xi: T(a*)", "Xi: T(a*)", "Xi: T(a*)", "Xi: T(a*)", "Xi: T(a*)"},
14523f13e19SIlya Leoshkevich },
14623f13e19SIlya Leoshkevich },
14723f13e19SIlya Leoshkevich {
14823f13e19SIlya Leoshkevich .op = VFMAX,
14923f13e19SIlya Leoshkevich .m6 = 1,
15023f13e19SIlya Leoshkevich .m6_desc = "JAVA Math.Max()",
15123f13e19SIlya Leoshkevich .table = {
15223f13e19SIlya Leoshkevich /* -inf -Fn -0 +0 +Fn +inf QNaN SNaN */
15323f13e19SIlya Leoshkevich {/* -inf */ "T(a)", "T(b)", "T(b)", "T(b)", "T(b)", "T(b)", "T(b)", "Xi: T(b*)"},
15423f13e19SIlya Leoshkevich {/* -Fn */ "T(a)", "T(M(a,b))", "T(b)", "T(b)", "T(b)", "T(b)", "T(b)", "Xi: T(b*)"},
15523f13e19SIlya Leoshkevich {/* -0 */ "T(a)", "T(a)", "T(a)", "T(b)", "T(b)", "T(b)", "T(b)", "Xi: T(b*)"},
15623f13e19SIlya Leoshkevich {/* +0 */ "T(a)", "T(a)", "T(a)", "T(a)", "T(b)", "T(b)", "T(b)", "Xi: T(b*)"},
15723f13e19SIlya Leoshkevich {/* +Fn */ "T(a)", "T(a)", "T(a)", "T(a)", "T(M(a,b))", "T(b)", "T(b)", "Xi: T(b*)"},
15823f13e19SIlya Leoshkevich {/* +inf */ "T(a)", "T(a)", "T(a)", "T(a)", "T(a)", "T(a)", "T(b)", "Xi: T(b*)"},
15923f13e19SIlya Leoshkevich {/* QNaN */ "T(a)", "T(a)", "T(a)", "T(a)", "T(a)", "T(a)", "T(a)", "Xi: T(b*)"},
16023f13e19SIlya Leoshkevich {/* SNaN */ "Xi: T(a*)", "Xi: T(a*)", "Xi: T(a*)", "Xi: T(a*)", "Xi: T(a*)", "Xi: T(a*)", "Xi: T(a*)", "Xi: T(a*)"},
16123f13e19SIlya Leoshkevich },
16223f13e19SIlya Leoshkevich },
16323f13e19SIlya Leoshkevich {
16423f13e19SIlya Leoshkevich .op = VFMAX,
16523f13e19SIlya Leoshkevich .m6 = 2,
16623f13e19SIlya Leoshkevich .m6_desc = "C-style Max Macro",
16723f13e19SIlya Leoshkevich .table = {
16823f13e19SIlya Leoshkevich /* -inf -Fn -0 +0 +Fn +inf QNaN SNaN */
16923f13e19SIlya Leoshkevich {/* -inf */ "T(b)", "T(b)", "T(b)", "T(b)", "T(b)", "T(b)", "Xi: T(b)", "Xi: T(b)"},
17023f13e19SIlya Leoshkevich {/* -Fn */ "T(a)", "T(M(a,b))", "T(b)", "T(b)", "T(b)", "T(b)", "Xi: T(b)", "Xi: T(b)"},
17123f13e19SIlya Leoshkevich {/* -0 */ "T(a)", "T(a)", "T(b)", "T(b)", "T(b)", "T(b)", "Xi: T(b)", "Xi: T(b)"},
17223f13e19SIlya Leoshkevich {/* +0 */ "T(a)", "T(a)", "T(b)", "T(b)", "T(b)", "T(b)", "Xi: T(b)", "Xi: T(b)"},
17323f13e19SIlya Leoshkevich {/* +Fn */ "T(a)", "T(a)", "T(a)", "T(a)", "T(M(a,b))", "T(b)", "Xi: T(b)", "Xi: T(b)"},
17423f13e19SIlya Leoshkevich {/* +inf */ "T(a)", "T(a)", "T(a)", "T(a)", "T(a)", "T(b)", "Xi: T(b)", "Xi: T(b)"},
17523f13e19SIlya Leoshkevich {/* QNaN */ "Xi: T(b)", "Xi: T(b)", "Xi: T(b)", "Xi: T(b)", "Xi: T(b)", "Xi: T(b)", "Xi: T(b)", "Xi: T(b)"},
17623f13e19SIlya Leoshkevich {/* SNaN */ "Xi: T(b)", "Xi: T(b)", "Xi: T(b)", "Xi: T(b)", "Xi: T(b)", "Xi: T(b)", "Xi: T(b)", "Xi: T(b)"},
17723f13e19SIlya Leoshkevich },
17823f13e19SIlya Leoshkevich },
17923f13e19SIlya Leoshkevich {
18023f13e19SIlya Leoshkevich .op = VFMAX,
18123f13e19SIlya Leoshkevich .m6 = 3,
18223f13e19SIlya Leoshkevich .m6_desc = "C++ algorithm.max()",
18323f13e19SIlya Leoshkevich .table = {
18423f13e19SIlya Leoshkevich /* -inf -Fn -0 +0 +Fn +inf QNaN SNaN */
18523f13e19SIlya Leoshkevich {/* -inf */ "T(a)", "T(b)", "T(b)", "T(b)", "T(b)", "T(b)", "Xi: T(a)", "Xi: T(a)"},
18623f13e19SIlya Leoshkevich {/* -Fn */ "T(a)", "T(M(a,b))", "T(b)", "T(b)", "T(b)", "T(b)", "Xi: T(a)", "Xi: T(a)"},
18723f13e19SIlya Leoshkevich {/* -0 */ "T(a)", "T(a)", "T(a)", "T(a)", "T(b)", "T(b)", "Xi: T(a)", "Xi: T(a)"},
18823f13e19SIlya Leoshkevich {/* +0 */ "T(a)", "T(a)", "T(a)", "T(a)", "T(b)", "T(b)", "Xi: T(a)", "Xi: T(a)"},
18923f13e19SIlya Leoshkevich {/* +Fn */ "T(a)", "T(a)", "T(a)", "T(a)", "T(M(a,b))", "T(b)", "Xi: T(a)", "Xi: T(a)"},
19023f13e19SIlya Leoshkevich {/* +inf */ "T(a)", "T(a)", "T(a)", "T(a)", "T(a)", "T(a)", "Xi: T(a)", "Xi: T(a)"},
19123f13e19SIlya Leoshkevich {/* QNaN */ "Xi: T(a)", "Xi: T(a)", "Xi: T(a)", "Xi: T(a)", "Xi: T(a)", "Xi: T(a)", "Xi: T(a)", "Xi: T(a)"},
19223f13e19SIlya Leoshkevich {/* SNaN */ "Xi: T(a)", "Xi: T(a)", "Xi: T(a)", "Xi: T(a)", "Xi: T(a)", "Xi: T(a)", "Xi: T(a)", "Xi: T(a)"},
19323f13e19SIlya Leoshkevich },
19423f13e19SIlya Leoshkevich },
19523f13e19SIlya Leoshkevich {
19623f13e19SIlya Leoshkevich .op = VFMAX,
19723f13e19SIlya Leoshkevich .m6 = 4,
19823f13e19SIlya Leoshkevich .m6_desc = "fmax()",
19923f13e19SIlya Leoshkevich .table = {
20023f13e19SIlya Leoshkevich /* -inf -Fn -0 +0 +Fn +inf QNaN SNaN */
20123f13e19SIlya Leoshkevich {/* -inf */ "T(a)", "T(b)", "T(b)", "T(b)", "T(b)", "T(b)", "T(a)", "Xi: T(a)"},
20223f13e19SIlya Leoshkevich {/* -Fn */ "T(a)", "T(M(a,b))", "T(b)", "T(b)", "T(b)", "T(b)", "T(a)", "Xi: T(a)"},
20323f13e19SIlya Leoshkevich {/* -0 */ "T(a)", "T(a)", "T(a)", "T(b)", "T(b)", "T(b)", "T(a)", "Xi: T(a)"},
20423f13e19SIlya Leoshkevich {/* +0 */ "T(a)", "T(a)", "T(a)", "T(a)", "T(b)", "T(b)", "T(a)", "Xi: T(a)"},
20523f13e19SIlya Leoshkevich {/* +Fn */ "T(a)", "T(a)", "T(a)", "T(a)", "T(M(a,b))", "T(b)", "T(a)", "Xi: T(a)"},
20623f13e19SIlya Leoshkevich {/* +inf */ "T(a)", "T(a)", "T(a)", "T(a)", "T(a)", "T(a)", "T(a)", "Xi: T(a)"},
20723f13e19SIlya Leoshkevich {/* QNaN */ "T(b)", "T(b)", "T(b)", "T(b)", "T(b)", "T(b)", "T(a)", "Xi: T(a)"},
20823f13e19SIlya Leoshkevich {/* SNaN */ "Xi: T(b)", "Xi: T(b)", "Xi: T(b)", "Xi: T(b)", "Xi: T(b)", "Xi: T(b)", "Xi: T(a)", "Xi: T(a)"},
20923f13e19SIlya Leoshkevich },
21023f13e19SIlya Leoshkevich },
21123f13e19SIlya Leoshkevich };
21223f13e19SIlya Leoshkevich
signed_test(struct signed_test * test,int m4,int m5,const void * v1_exp,bool xi_exp,const void * v2,const void * v3)21323f13e19SIlya Leoshkevich static int signed_test(struct signed_test *test, int m4, int m5,
21423f13e19SIlya Leoshkevich const void *v1_exp, bool xi_exp,
21523f13e19SIlya Leoshkevich const void *v2, const void *v3)
21623f13e19SIlya Leoshkevich {
21723f13e19SIlya Leoshkevich size_t n = (m5 & 8) ? float_sizes[m4 - 2] : 16;
21823f13e19SIlya Leoshkevich char v1[16];
21923f13e19SIlya Leoshkevich bool xi;
22023f13e19SIlya Leoshkevich
22123f13e19SIlya Leoshkevich feclearexcept(FE_ALL_EXCEPT);
22223f13e19SIlya Leoshkevich vfminmax(test->op, m4, m5, test->m6, v1, v2, v3);
22323f13e19SIlya Leoshkevich xi = fetestexcept(FE_ALL_EXCEPT) == FE_INVALID;
22423f13e19SIlya Leoshkevich
22523f13e19SIlya Leoshkevich if (memcmp(v1, v1_exp, n) != 0 || xi != xi_exp) {
22623f13e19SIlya Leoshkevich fprintf(stderr, "[ FAILED ] %s ", test->m6_desc);
22723f13e19SIlya Leoshkevich dump_v(stderr, v2, n);
22823f13e19SIlya Leoshkevich fprintf(stderr, ", ");
22923f13e19SIlya Leoshkevich dump_v(stderr, v3, n);
23023f13e19SIlya Leoshkevich fprintf(stderr, ", %d, %d, %d: actual=", m4, m5, test->m6);
23123f13e19SIlya Leoshkevich dump_v(stderr, v1, n);
23223f13e19SIlya Leoshkevich fprintf(stderr, "/%d, expected=", (int)xi);
23323f13e19SIlya Leoshkevich dump_v(stderr, v1_exp, n);
23423f13e19SIlya Leoshkevich fprintf(stderr, "/%d\n", (int)xi_exp);
23523f13e19SIlya Leoshkevich return 1;
23623f13e19SIlya Leoshkevich }
23723f13e19SIlya Leoshkevich
23823f13e19SIlya Leoshkevich return 0;
23923f13e19SIlya Leoshkevich }
24023f13e19SIlya Leoshkevich
241*6dc29354SIlya Leoshkevich struct iter {
242*6dc29354SIlya Leoshkevich int cls[2];
243*6dc29354SIlya Leoshkevich int val[2];
244*6dc29354SIlya Leoshkevich };
245*6dc29354SIlya Leoshkevich
iter_next(struct iter * it,int fmt)246*6dc29354SIlya Leoshkevich static bool iter_next(struct iter *it, int fmt)
24723f13e19SIlya Leoshkevich {
248*6dc29354SIlya Leoshkevich int i;
249*6dc29354SIlya Leoshkevich
250*6dc29354SIlya Leoshkevich for (i = 1; i >= 0; i--) {
251*6dc29354SIlya Leoshkevich if (++it->val[i] != signed_floats[fmt][it->cls[i]].n) {
252*6dc29354SIlya Leoshkevich return true;
253*6dc29354SIlya Leoshkevich }
254*6dc29354SIlya Leoshkevich it->val[i] = 0;
255*6dc29354SIlya Leoshkevich
256*6dc29354SIlya Leoshkevich if (++it->cls[i] != N_SIGNED_CLASSES) {
257*6dc29354SIlya Leoshkevich return true;
258*6dc29354SIlya Leoshkevich }
259*6dc29354SIlya Leoshkevich it->cls[i] = 0;
260*6dc29354SIlya Leoshkevich }
261*6dc29354SIlya Leoshkevich
262*6dc29354SIlya Leoshkevich return false;
26323f13e19SIlya Leoshkevich }
26423f13e19SIlya Leoshkevich
main(void)26523f13e19SIlya Leoshkevich int main(void)
26623f13e19SIlya Leoshkevich {
26723f13e19SIlya Leoshkevich int ret = 0;
26823f13e19SIlya Leoshkevich size_t i;
26923f13e19SIlya Leoshkevich
27023f13e19SIlya Leoshkevich for (i = 0; i < sizeof(signed_tests) / sizeof(signed_tests[0]); i++) {
27123f13e19SIlya Leoshkevich struct signed_test *test = &signed_tests[i];
272*6dc29354SIlya Leoshkevich int fmt;
27323f13e19SIlya Leoshkevich
274*6dc29354SIlya Leoshkevich for (fmt = 0; fmt < N_FORMATS; fmt++) {
275*6dc29354SIlya Leoshkevich size_t float_size = float_sizes[fmt];
276*6dc29354SIlya Leoshkevich int m4 = fmt + 2;
27723f13e19SIlya Leoshkevich int m5;
27823f13e19SIlya Leoshkevich
27923f13e19SIlya Leoshkevich for (m5 = 0; m5 <= 8; m5 += 8) {
28023f13e19SIlya Leoshkevich char v1_exp[16], v2[16], v3[16];
28123f13e19SIlya Leoshkevich bool xi_exp = false;
282*6dc29354SIlya Leoshkevich struct iter it = {};
28323f13e19SIlya Leoshkevich int pos = 0;
28423f13e19SIlya Leoshkevich
285*6dc29354SIlya Leoshkevich do {
286*6dc29354SIlya Leoshkevich const char *spec = test->table[it.cls[0]][it.cls[1]];
28723f13e19SIlya Leoshkevich
288*6dc29354SIlya Leoshkevich memcpy(&v2[pos],
289*6dc29354SIlya Leoshkevich signed_floats[fmt][it.cls[0]].v[it.val[0]],
290*6dc29354SIlya Leoshkevich float_size);
291*6dc29354SIlya Leoshkevich memcpy(&v3[pos],
292*6dc29354SIlya Leoshkevich signed_floats[fmt][it.cls[1]].v[it.val[1]],
293*6dc29354SIlya Leoshkevich float_size);
29423f13e19SIlya Leoshkevich if (strcmp(spec, "T(a)") == 0 ||
29523f13e19SIlya Leoshkevich strcmp(spec, "Xi: T(a)") == 0) {
29623f13e19SIlya Leoshkevich memcpy(&v1_exp[pos], &v2[pos], float_size);
29723f13e19SIlya Leoshkevich } else if (strcmp(spec, "T(b)") == 0 ||
29823f13e19SIlya Leoshkevich strcmp(spec, "Xi: T(b)") == 0) {
29923f13e19SIlya Leoshkevich memcpy(&v1_exp[pos], &v3[pos], float_size);
30023f13e19SIlya Leoshkevich } else if (strcmp(spec, "Xi: T(a*)") == 0) {
30123f13e19SIlya Leoshkevich memcpy(&v1_exp[pos], &v2[pos], float_size);
302*6dc29354SIlya Leoshkevich snan_to_qnan(&v1_exp[pos], fmt);
30323f13e19SIlya Leoshkevich } else if (strcmp(spec, "Xi: T(b*)") == 0) {
30423f13e19SIlya Leoshkevich memcpy(&v1_exp[pos], &v3[pos], float_size);
305*6dc29354SIlya Leoshkevich snan_to_qnan(&v1_exp[pos], fmt);
30623f13e19SIlya Leoshkevich } else if (strcmp(spec, "T(M(a,b))") == 0) {
30723f13e19SIlya Leoshkevich /*
308*6dc29354SIlya Leoshkevich * Comparing floats is risky, since the compiler might
309*6dc29354SIlya Leoshkevich * generate the same instruction that we are testing.
310*6dc29354SIlya Leoshkevich * Compare ints instead. This works, because we get
311*6dc29354SIlya Leoshkevich * here only for +-Fn, and the corresponding test
312*6dc29354SIlya Leoshkevich * values have identical exponents.
31323f13e19SIlya Leoshkevich */
31423f13e19SIlya Leoshkevich int v2_int = *(int *)&v2[pos];
31523f13e19SIlya Leoshkevich int v3_int = *(int *)&v3[pos];
31623f13e19SIlya Leoshkevich
31723f13e19SIlya Leoshkevich if ((v2_int < v3_int) ==
31823f13e19SIlya Leoshkevich ((test->op == VFMIN) != (v2_int < 0))) {
31923f13e19SIlya Leoshkevich memcpy(&v1_exp[pos], &v2[pos], float_size);
32023f13e19SIlya Leoshkevich } else {
32123f13e19SIlya Leoshkevich memcpy(&v1_exp[pos], &v3[pos], float_size);
32223f13e19SIlya Leoshkevich }
32323f13e19SIlya Leoshkevich } else {
32423f13e19SIlya Leoshkevich fprintf(stderr, "Unexpected spec: %s\n", spec);
32523f13e19SIlya Leoshkevich return 1;
32623f13e19SIlya Leoshkevich }
32723f13e19SIlya Leoshkevich xi_exp |= spec[0] == 'X';
32823f13e19SIlya Leoshkevich pos += float_size;
32923f13e19SIlya Leoshkevich
33023f13e19SIlya Leoshkevich if ((m5 & 8) || pos == 16) {
33123f13e19SIlya Leoshkevich ret |= signed_test(test, m4, m5,
33223f13e19SIlya Leoshkevich v1_exp, xi_exp, v2, v3);
33323f13e19SIlya Leoshkevich pos = 0;
33423f13e19SIlya Leoshkevich xi_exp = false;
33523f13e19SIlya Leoshkevich }
336*6dc29354SIlya Leoshkevich } while (iter_next(&it, fmt));
33723f13e19SIlya Leoshkevich
33823f13e19SIlya Leoshkevich if (pos != 0) {
33923f13e19SIlya Leoshkevich ret |= signed_test(test, m4, m5, v1_exp, xi_exp, v2, v3);
34023f13e19SIlya Leoshkevich }
34123f13e19SIlya Leoshkevich }
34223f13e19SIlya Leoshkevich }
34323f13e19SIlya Leoshkevich }
34423f13e19SIlya Leoshkevich
34523f13e19SIlya Leoshkevich return ret;
34623f13e19SIlya Leoshkevich }
347