xref: /openbmc/qemu/tests/tcg/s390x/vfminmax.c (revision 23f13e19)
1*23f13e19SIlya Leoshkevich #define _GNU_SOURCE
2*23f13e19SIlya Leoshkevich #include <fenv.h>
3*23f13e19SIlya Leoshkevich #include <stdbool.h>
4*23f13e19SIlya Leoshkevich #include <stdio.h>
5*23f13e19SIlya Leoshkevich #include <string.h>
6*23f13e19SIlya Leoshkevich 
7*23f13e19SIlya Leoshkevich /*
8*23f13e19SIlya Leoshkevich  * vfmin/vfmax instruction execution.
9*23f13e19SIlya Leoshkevich  */
10*23f13e19SIlya Leoshkevich #define VFMIN 0xEE
11*23f13e19SIlya Leoshkevich #define VFMAX 0xEF
12*23f13e19SIlya Leoshkevich 
13*23f13e19SIlya Leoshkevich extern char insn[6];
14*23f13e19SIlya Leoshkevich asm(".pushsection .rwx,\"awx\",@progbits\n"
15*23f13e19SIlya Leoshkevich     ".globl insn\n"
16*23f13e19SIlya Leoshkevich     /* e7 89 a0 00 2e ef */
17*23f13e19SIlya Leoshkevich     "insn: vfmaxsb %v24,%v25,%v26,0\n"
18*23f13e19SIlya Leoshkevich     ".popsection\n");
19*23f13e19SIlya Leoshkevich 
vfminmax(unsigned int op,unsigned int m4,unsigned int m5,unsigned int m6,void * v1,const void * v2,const void * v3)20*23f13e19SIlya Leoshkevich static void vfminmax(unsigned int op,
21*23f13e19SIlya Leoshkevich                      unsigned int m4, unsigned int m5, unsigned int m6,
22*23f13e19SIlya Leoshkevich                      void *v1, const void *v2, const void *v3)
23*23f13e19SIlya Leoshkevich {
24*23f13e19SIlya Leoshkevich    insn[3] = (m6 << 4) | m5;
25*23f13e19SIlya Leoshkevich    insn[4] = (m4 << 4) | 0x0e;
26*23f13e19SIlya Leoshkevich    insn[5] = op;
27*23f13e19SIlya Leoshkevich 
28*23f13e19SIlya Leoshkevich     asm("vl %%v25,%[v2]\n"
29*23f13e19SIlya Leoshkevich         "vl %%v26,%[v3]\n"
30*23f13e19SIlya Leoshkevich         "ex 0,%[insn]\n"
31*23f13e19SIlya Leoshkevich         "vst %%v24,%[v1]\n"
32*23f13e19SIlya Leoshkevich         : [v1] "=m" (*(char (*)[16])v1)
33*23f13e19SIlya Leoshkevich         : [v2] "m" (*(char (*)[16])v2)
34*23f13e19SIlya Leoshkevich         , [v3] "m" (*(char (*)[16])v3)
35*23f13e19SIlya Leoshkevich         , [insn] "m"(insn)
36*23f13e19SIlya Leoshkevich         : "v24", "v25", "v26");
37*23f13e19SIlya Leoshkevich }
38*23f13e19SIlya Leoshkevich 
39*23f13e19SIlya Leoshkevich /*
40*23f13e19SIlya Leoshkevich  * Floating-point value classes.
41*23f13e19SIlya Leoshkevich  */
42*23f13e19SIlya Leoshkevich #define N_FORMATS 3
43*23f13e19SIlya Leoshkevich #define N_SIGNED_CLASSES 8
44*23f13e19SIlya Leoshkevich static const size_t float_sizes[N_FORMATS] = {
45*23f13e19SIlya Leoshkevich     /* M4 == 2: short    */ 4,
46*23f13e19SIlya Leoshkevich     /* M4 == 3: long     */ 8,
47*23f13e19SIlya Leoshkevich     /* M4 == 4: extended */ 16,
48*23f13e19SIlya Leoshkevich };
49*23f13e19SIlya Leoshkevich static const size_t e_bits[N_FORMATS] = {
50*23f13e19SIlya Leoshkevich     /* M4 == 2: short    */ 8,
51*23f13e19SIlya Leoshkevich     /* M4 == 3: long     */ 11,
52*23f13e19SIlya Leoshkevich     /* M4 == 4: extended */ 15,
53*23f13e19SIlya Leoshkevich };
54*23f13e19SIlya Leoshkevich static const unsigned char signed_floats[N_FORMATS][N_SIGNED_CLASSES][2][16] = {
55*23f13e19SIlya Leoshkevich     /* M4 == 2: short */
56*23f13e19SIlya Leoshkevich     {
57*23f13e19SIlya Leoshkevich         /* -inf */ {{0xff, 0x80, 0x00, 0x00},
58*23f13e19SIlya Leoshkevich                     {0xff, 0x80, 0x00, 0x00}},
59*23f13e19SIlya Leoshkevich         /* -Fn */  {{0xc2, 0x28, 0x00, 0x00},
60*23f13e19SIlya Leoshkevich                     {0xc2, 0x29, 0x00, 0x00}},
61*23f13e19SIlya Leoshkevich         /* -0 */   {{0x80, 0x00, 0x00, 0x00},
62*23f13e19SIlya Leoshkevich                     {0x80, 0x00, 0x00, 0x00}},
63*23f13e19SIlya Leoshkevich         /* +0 */   {{0x00, 0x00, 0x00, 0x00},
64*23f13e19SIlya Leoshkevich                     {0x00, 0x00, 0x00, 0x00}},
65*23f13e19SIlya Leoshkevich         /* +Fn */  {{0x42, 0x28, 0x00, 0x00},
66*23f13e19SIlya Leoshkevich                     {0x42, 0x2a, 0x00, 0x00}},
67*23f13e19SIlya Leoshkevich         /* +inf */ {{0x7f, 0x80, 0x00, 0x00},
68*23f13e19SIlya Leoshkevich                     {0x7f, 0x80, 0x00, 0x00}},
69*23f13e19SIlya Leoshkevich         /* QNaN */ {{0x7f, 0xff, 0xff, 0xff},
70*23f13e19SIlya Leoshkevich                     {0x7f, 0xff, 0xff, 0xfe}},
71*23f13e19SIlya Leoshkevich         /* SNaN */ {{0x7f, 0xbf, 0xff, 0xff},
72*23f13e19SIlya Leoshkevich                     {0x7f, 0xbf, 0xff, 0xfd}},
73*23f13e19SIlya Leoshkevich     },
74*23f13e19SIlya Leoshkevich 
75*23f13e19SIlya Leoshkevich     /* M4 == 3: long */
76*23f13e19SIlya Leoshkevich     {
77*23f13e19SIlya Leoshkevich         /* -inf */ {{0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
78*23f13e19SIlya Leoshkevich                     {0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}},
79*23f13e19SIlya Leoshkevich         /* -Fn */  {{0xc0, 0x45, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
80*23f13e19SIlya Leoshkevich                     {0xc0, 0x46, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}},
81*23f13e19SIlya Leoshkevich         /* -0 */   {{0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
82*23f13e19SIlya Leoshkevich                     {0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}},
83*23f13e19SIlya Leoshkevich         /* +0 */   {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
84*23f13e19SIlya Leoshkevich                     {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}},
85*23f13e19SIlya Leoshkevich         /* +Fn */  {{0x40, 0x45, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
86*23f13e19SIlya Leoshkevich                     {0x40, 0x47, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}},
87*23f13e19SIlya Leoshkevich         /* +inf */ {{0x7f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
88*23f13e19SIlya Leoshkevich                     {0x7f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}},
89*23f13e19SIlya Leoshkevich         /* QNaN */ {{0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
90*23f13e19SIlya Leoshkevich                     {0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe}},
91*23f13e19SIlya Leoshkevich         /* SNaN */ {{0x7f, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
92*23f13e19SIlya Leoshkevich                     {0x7f, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd}},
93*23f13e19SIlya Leoshkevich     },
94*23f13e19SIlya Leoshkevich 
95*23f13e19SIlya Leoshkevich     /* M4 == 4: extended */
96*23f13e19SIlya Leoshkevich     {
97*23f13e19SIlya Leoshkevich         /* -inf */ {{0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
98*23f13e19SIlya Leoshkevich                     {0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}},
99*23f13e19SIlya Leoshkevich         /* -Fn */  {{0xc0, 0x04, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
100*23f13e19SIlya Leoshkevich                     {0xc0, 0x04, 0x51, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}},
101*23f13e19SIlya Leoshkevich         /* -0 */   {{0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
102*23f13e19SIlya Leoshkevich                     {0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}},
103*23f13e19SIlya Leoshkevich         /* +0 */   {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
104*23f13e19SIlya Leoshkevich                     {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}},
105*23f13e19SIlya Leoshkevich         /* +Fn */  {{0x40, 0x04, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
106*23f13e19SIlya Leoshkevich                     {0x40, 0x04, 0x52, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}},
107*23f13e19SIlya Leoshkevich         /* +inf */ {{0x7f, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
108*23f13e19SIlya Leoshkevich                     {0x7f, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}},
109*23f13e19SIlya Leoshkevich         /* QNaN */ {{0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
110*23f13e19SIlya Leoshkevich                     {0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe}},
111*23f13e19SIlya Leoshkevich         /* SNaN */ {{0x7f, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
112*23f13e19SIlya Leoshkevich                     {0x7f, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd}},
113*23f13e19SIlya Leoshkevich     },
114*23f13e19SIlya Leoshkevich };
115*23f13e19SIlya Leoshkevich 
116*23f13e19SIlya Leoshkevich /*
117*23f13e19SIlya Leoshkevich  * PoP tables as close to the original as possible.
118*23f13e19SIlya Leoshkevich  */
119*23f13e19SIlya Leoshkevich struct signed_test {
120*23f13e19SIlya Leoshkevich     int op;
121*23f13e19SIlya Leoshkevich     int m6;
122*23f13e19SIlya Leoshkevich     const char *m6_desc;
123*23f13e19SIlya Leoshkevich     const char *table[N_SIGNED_CLASSES][N_SIGNED_CLASSES];
124*23f13e19SIlya Leoshkevich } signed_tests[] = {
125*23f13e19SIlya Leoshkevich     {
126*23f13e19SIlya Leoshkevich         .op = VFMIN,
127*23f13e19SIlya Leoshkevich         .m6 = 0,
128*23f13e19SIlya Leoshkevich         .m6_desc = "IEEE MinNum",
129*23f13e19SIlya Leoshkevich         .table = {
130*23f13e19SIlya Leoshkevich              /*         -inf         -Fn          -0           +0           +Fn          +inf         QNaN         SNaN     */
131*23f13e19SIlya Leoshkevich             {/* -inf */ "T(a)",      "T(a)",      "T(a)",      "T(a)",      "T(a)",      "T(a)",      "T(a)",      "Xi: T(b*)"},
132*23f13e19SIlya Leoshkevich             {/* -Fn  */ "T(b)",      "T(M(a,b))", "T(a)",      "T(a)",      "T(a)",      "T(a)",      "T(a)",      "Xi: T(b*)"},
133*23f13e19SIlya Leoshkevich             {/* -0   */ "T(b)",      "T(b)",      "T(a)",      "T(a)",      "T(a)",      "T(a)",      "T(a)",      "Xi: T(b*)"},
134*23f13e19SIlya Leoshkevich             {/* +0   */ "T(b)",      "T(b)",      "T(b)",      "T(a)",      "T(a)",      "T(a)",      "T(a)",      "Xi: T(b*)"},
135*23f13e19SIlya Leoshkevich             {/* +Fn  */ "T(b)",      "T(b)",      "T(b)",      "T(b)",      "T(M(a,b))", "T(a)",      "T(a)",      "Xi: T(b*)"},
136*23f13e19SIlya Leoshkevich             {/* +inf */ "T(b)",      "T(b)",      "T(b)",      "T(b)",      "T(b)",      "T(a)",      "T(a)",      "Xi: T(b*)"},
137*23f13e19SIlya Leoshkevich             {/* QNaN */ "T(b)",      "T(b)",      "T(b)",      "T(b)",      "T(b)",      "T(b)",      "T(a)",      "Xi: T(b*)"},
138*23f13e19SIlya 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*)"},
139*23f13e19SIlya Leoshkevich         },
140*23f13e19SIlya Leoshkevich     },
141*23f13e19SIlya Leoshkevich     {
142*23f13e19SIlya Leoshkevich         .op = VFMIN,
143*23f13e19SIlya Leoshkevich         .m6 = 1,
144*23f13e19SIlya Leoshkevich         .m6_desc = "JAVA Math.Min()",
145*23f13e19SIlya Leoshkevich         .table = {
146*23f13e19SIlya Leoshkevich              /*         -inf         -Fn          -0           +0           +Fn          +inf         QNaN         SNaN     */
147*23f13e19SIlya Leoshkevich             {/* -inf */ "T(b)",      "T(a)",      "T(a)",      "T(a)",      "T(a)",      "T(a)",      "T(b)",      "Xi: T(b*)"},
148*23f13e19SIlya Leoshkevich             {/* -Fn  */ "T(b)",      "T(M(a,b))", "T(a)",      "T(a)",      "T(a)",      "T(a)",      "T(b)",      "Xi: T(b*)"},
149*23f13e19SIlya Leoshkevich             {/* -0   */ "T(b)",      "T(b)",      "T(b)",      "T(a)",      "T(a)",      "T(a)",      "T(b)",      "Xi: T(b*)"},
150*23f13e19SIlya Leoshkevich             {/* +0   */ "T(b)",      "T(b)",      "T(b)",      "T(b)",      "T(a)",      "T(a)",      "T(b)",      "Xi: T(b*)"},
151*23f13e19SIlya Leoshkevich             {/* +Fn  */ "T(b)",      "T(b)",      "T(b)",      "T(b)",      "T(M(a,b))", "T(a)",      "T(b)",      "Xi: T(b*)"},
152*23f13e19SIlya Leoshkevich             {/* +inf */ "T(b)",      "T(b)",      "T(b)",      "T(b)",      "T(b)",      "T(b)",      "T(b)",      "Xi: T(b*)"},
153*23f13e19SIlya Leoshkevich             {/* QNaN */ "T(a)",      "T(a)",      "T(a)",      "T(a)",      "T(a)",      "T(a)",      "T(a)",      "Xi: T(b*)"},
154*23f13e19SIlya 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*)"},
155*23f13e19SIlya Leoshkevich         },
156*23f13e19SIlya Leoshkevich     },
157*23f13e19SIlya Leoshkevich     {
158*23f13e19SIlya Leoshkevich         .op = VFMIN,
159*23f13e19SIlya Leoshkevich         .m6 = 2,
160*23f13e19SIlya Leoshkevich         .m6_desc = "C-style Min Macro",
161*23f13e19SIlya Leoshkevich         .table = {
162*23f13e19SIlya Leoshkevich              /*         -inf        -Fn          -0          +0          +Fn          +inf        QNaN        SNaN    */
163*23f13e19SIlya Leoshkevich             {/* -inf */ "T(b)",     "T(a)",      "T(a)",     "T(a)",     "T(a)",      "T(a)",     "Xi: T(b)", "Xi: T(b)"},
164*23f13e19SIlya Leoshkevich             {/* -Fn  */ "T(b)",     "T(M(a,b))", "T(a)",     "T(a)",     "T(a)",      "T(a)",     "Xi: T(b)", "Xi: T(b)"},
165*23f13e19SIlya Leoshkevich             {/* -0   */ "T(b)",     "T(b)",      "T(b)",     "T(b)",     "T(a)",      "T(a)",     "Xi: T(b)", "Xi: T(b)"},
166*23f13e19SIlya Leoshkevich             {/* +0   */ "T(b)",     "T(b)",      "T(b)",     "T(b)",     "T(a)",      "T(a)",     "Xi: T(b)", "Xi: T(b)"},
167*23f13e19SIlya Leoshkevich             {/* +Fn  */ "T(b)",     "T(b)",      "T(b)",     "T(b)",     "T(M(a,b))", "T(a)",     "Xi: T(b)", "Xi: T(b)"},
168*23f13e19SIlya Leoshkevich             {/* +inf */ "T(b)",     "T(b)",      "T(b)",     "T(b)",     "T(b)",      "T(a)",     "Xi: T(b)", "Xi: T(b)"},
169*23f13e19SIlya 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)"},
170*23f13e19SIlya 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)"},
171*23f13e19SIlya Leoshkevich         },
172*23f13e19SIlya Leoshkevich     },
173*23f13e19SIlya Leoshkevich     {
174*23f13e19SIlya Leoshkevich         .op = VFMIN,
175*23f13e19SIlya Leoshkevich         .m6 = 3,
176*23f13e19SIlya Leoshkevich         .m6_desc = "C++ algorithm.min()",
177*23f13e19SIlya Leoshkevich         .table = {
178*23f13e19SIlya Leoshkevich              /*         -inf        -Fn          -0          +0          +Fn          +inf        QNaN        SNaN    */
179*23f13e19SIlya Leoshkevich             {/* -inf */ "T(b)",     "T(a)",      "T(a)",     "T(a)",     "T(a)",      "T(a)",     "Xi: T(a)", "Xi: T(a)"},
180*23f13e19SIlya Leoshkevich             {/* -Fn  */ "T(b)",     "T(M(a,b))", "T(a)",     "T(a)",     "T(a)",      "T(a)",     "Xi: T(a)", "Xi: T(a)"},
181*23f13e19SIlya Leoshkevich             {/* -0   */ "T(b)",     "T(b)",      "T(a)",     "T(a)",     "T(a)",      "T(a)",     "Xi: T(a)", "Xi: T(a)"},
182*23f13e19SIlya Leoshkevich             {/* +0   */ "T(b)",     "T(b)",      "T(a)",     "T(a)",     "T(a)",      "T(a)",     "Xi: T(a)", "Xi: T(a)"},
183*23f13e19SIlya Leoshkevich             {/* +Fn  */ "T(b)",     "T(b)",      "T(b)",     "T(b)",     "T(M(a,b))", "T(a)",     "Xi: T(a)", "Xi: T(a)"},
184*23f13e19SIlya Leoshkevich             {/* +inf */ "T(b)",     "T(b)",      "T(b)",     "T(b)",     "T(b)",      "T(a)",     "Xi: T(a)", "Xi: T(a)"},
185*23f13e19SIlya 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)"},
186*23f13e19SIlya 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)"},
187*23f13e19SIlya Leoshkevich         },
188*23f13e19SIlya Leoshkevich     },
189*23f13e19SIlya Leoshkevich     {
190*23f13e19SIlya Leoshkevich         .op = VFMIN,
191*23f13e19SIlya Leoshkevich         .m6 = 4,
192*23f13e19SIlya Leoshkevich         .m6_desc = "fmin()",
193*23f13e19SIlya Leoshkevich         .table = {
194*23f13e19SIlya Leoshkevich              /*         -inf        -Fn          -0          +0          +Fn          +inf        QNaN        SNaN    */
195*23f13e19SIlya Leoshkevich             {/* -inf */ "T(a)",     "T(a)",      "T(a)",     "T(a)",     "T(a)",      "T(a)",     "T(a)",     "Xi: T(a)"},
196*23f13e19SIlya Leoshkevich             {/* -Fn  */ "T(b)",     "T(M(a,b))", "T(a)",     "T(a)",     "T(a)",      "T(a)",     "T(a)",     "Xi: T(a)"},
197*23f13e19SIlya Leoshkevich             {/* -0   */ "T(b)",     "T(b)",      "T(a)",     "T(a)",     "T(a)",      "T(a)",     "T(a)",     "Xi: T(a)"},
198*23f13e19SIlya Leoshkevich             {/* +0   */ "T(b)",     "T(b)",      "T(b)",     "T(a)",     "T(a)",      "T(a)",     "T(a)",     "Xi: T(a)"},
199*23f13e19SIlya Leoshkevich             {/* +Fn  */ "T(b)",     "T(b)",      "T(b)",     "T(b)",     "T(M(a,b))", "T(a)",     "T(a)",     "Xi: T(a)"},
200*23f13e19SIlya Leoshkevich             {/* +inf */ "T(b)",     "T(b)",      "T(b)",     "T(b)",     "T(b)",      "T(a)",     "T(a)",     "Xi: T(a)"},
201*23f13e19SIlya Leoshkevich             {/* QNaN */ "T(b)",     "T(b)",      "T(b)",     "T(b)",     "T(b)",      "T(b)",     "T(a)",     "Xi: T(a)"},
202*23f13e19SIlya 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)"},
203*23f13e19SIlya Leoshkevich         },
204*23f13e19SIlya Leoshkevich     },
205*23f13e19SIlya Leoshkevich 
206*23f13e19SIlya Leoshkevich     {
207*23f13e19SIlya Leoshkevich         .op = VFMAX,
208*23f13e19SIlya Leoshkevich         .m6 = 0,
209*23f13e19SIlya Leoshkevich         .m6_desc = "IEEE MaxNum",
210*23f13e19SIlya Leoshkevich         .table = {
211*23f13e19SIlya Leoshkevich              /*         -inf         -Fn          -0           +0           +Fn          +inf         QNaN         SNaN     */
212*23f13e19SIlya Leoshkevich             {/* -inf */ "T(a)",      "T(b)",      "T(b)",      "T(b)",      "T(b)",      "T(b)",      "T(a)",      "Xi: T(b*)"},
213*23f13e19SIlya Leoshkevich             {/* -Fn  */ "T(a)",      "T(M(a,b))", "T(b)",      "T(b)",      "T(b)",      "T(b)",      "T(a)",      "Xi: T(b*)"},
214*23f13e19SIlya Leoshkevich             {/* -0   */ "T(a)",      "T(a)",      "T(a)",      "T(b)",      "T(b)",      "T(b)",      "T(a)",      "Xi: T(b*)"},
215*23f13e19SIlya Leoshkevich             {/* +0   */ "T(a)",      "T(a)",      "T(a)",      "T(a)",      "T(b)",      "T(b)",      "T(a)",      "Xi: T(b*)"},
216*23f13e19SIlya Leoshkevich             {/* +Fn  */ "T(a)",      "T(a)",      "T(a)",      "T(a)",      "T(M(a,b))", "T(b)",      "T(a)",      "Xi: T(b*)"},
217*23f13e19SIlya Leoshkevich             {/* +inf */ "T(a)",      "T(a)",      "T(a)",      "T(a)",      "T(a)",      "T(a)",      "T(a)",      "Xi: T(b*)"},
218*23f13e19SIlya Leoshkevich             {/* QNaN */ "T(b)",      "T(b)",      "T(b)",      "T(b)",      "T(b)",      "T(b)",      "T(a)",      "Xi: T(b*)"},
219*23f13e19SIlya 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*)"},
220*23f13e19SIlya Leoshkevich         },
221*23f13e19SIlya Leoshkevich     },
222*23f13e19SIlya Leoshkevich     {
223*23f13e19SIlya Leoshkevich         .op = VFMAX,
224*23f13e19SIlya Leoshkevich         .m6 = 1,
225*23f13e19SIlya Leoshkevich         .m6_desc = "JAVA Math.Max()",
226*23f13e19SIlya Leoshkevich         .table = {
227*23f13e19SIlya Leoshkevich              /*         -inf         -Fn          -0           +0           +Fn          +inf         QNaN         SNaN     */
228*23f13e19SIlya Leoshkevich             {/* -inf */ "T(a)",      "T(b)",      "T(b)",      "T(b)",      "T(b)",      "T(b)",      "T(b)",      "Xi: T(b*)"},
229*23f13e19SIlya Leoshkevich             {/* -Fn  */ "T(a)",      "T(M(a,b))", "T(b)",      "T(b)",      "T(b)",      "T(b)",      "T(b)",      "Xi: T(b*)"},
230*23f13e19SIlya Leoshkevich             {/* -0   */ "T(a)",      "T(a)",      "T(a)",      "T(b)",      "T(b)",      "T(b)",      "T(b)",      "Xi: T(b*)"},
231*23f13e19SIlya Leoshkevich             {/* +0   */ "T(a)",      "T(a)",      "T(a)",      "T(a)",      "T(b)",      "T(b)",      "T(b)",      "Xi: T(b*)"},
232*23f13e19SIlya Leoshkevich             {/* +Fn  */ "T(a)",      "T(a)",      "T(a)",      "T(a)",      "T(M(a,b))", "T(b)",      "T(b)",      "Xi: T(b*)"},
233*23f13e19SIlya Leoshkevich             {/* +inf */ "T(a)",      "T(a)",      "T(a)",      "T(a)",      "T(a)",      "T(a)",      "T(b)",      "Xi: T(b*)"},
234*23f13e19SIlya Leoshkevich             {/* QNaN */ "T(a)",      "T(a)",      "T(a)",      "T(a)",      "T(a)",      "T(a)",      "T(a)",      "Xi: T(b*)"},
235*23f13e19SIlya 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*)"},
236*23f13e19SIlya Leoshkevich         },
237*23f13e19SIlya Leoshkevich     },
238*23f13e19SIlya Leoshkevich     {
239*23f13e19SIlya Leoshkevich         .op = VFMAX,
240*23f13e19SIlya Leoshkevich         .m6 = 2,
241*23f13e19SIlya Leoshkevich         .m6_desc = "C-style Max Macro",
242*23f13e19SIlya Leoshkevich         .table = {
243*23f13e19SIlya Leoshkevich              /*         -inf        -Fn          -0          +0          +Fn          +inf        QNaN        SNaN    */
244*23f13e19SIlya Leoshkevich             {/* -inf */ "T(b)",     "T(b)",      "T(b)",     "T(b)",     "T(b)",      "T(b)",     "Xi: T(b)", "Xi: T(b)"},
245*23f13e19SIlya Leoshkevich             {/* -Fn  */ "T(a)",     "T(M(a,b))", "T(b)",     "T(b)",     "T(b)",      "T(b)",     "Xi: T(b)", "Xi: T(b)"},
246*23f13e19SIlya Leoshkevich             {/* -0   */ "T(a)",     "T(a)",      "T(b)",     "T(b)",     "T(b)",      "T(b)",     "Xi: T(b)", "Xi: T(b)"},
247*23f13e19SIlya Leoshkevich             {/* +0   */ "T(a)",     "T(a)",      "T(b)",     "T(b)",     "T(b)",      "T(b)",     "Xi: T(b)", "Xi: T(b)"},
248*23f13e19SIlya Leoshkevich             {/* +Fn  */ "T(a)",     "T(a)",      "T(a)",     "T(a)",     "T(M(a,b))", "T(b)",     "Xi: T(b)", "Xi: T(b)"},
249*23f13e19SIlya Leoshkevich             {/* +inf */ "T(a)",     "T(a)",      "T(a)",     "T(a)",     "T(a)",      "T(b)",     "Xi: T(b)", "Xi: T(b)"},
250*23f13e19SIlya 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)"},
251*23f13e19SIlya 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)"},
252*23f13e19SIlya Leoshkevich         },
253*23f13e19SIlya Leoshkevich     },
254*23f13e19SIlya Leoshkevich     {
255*23f13e19SIlya Leoshkevich         .op = VFMAX,
256*23f13e19SIlya Leoshkevich         .m6 = 3,
257*23f13e19SIlya Leoshkevich         .m6_desc = "C++ algorithm.max()",
258*23f13e19SIlya Leoshkevich         .table = {
259*23f13e19SIlya Leoshkevich              /*         -inf        -Fn          -0          +0          +Fn          +inf        QNaN        SNaN    */
260*23f13e19SIlya Leoshkevich             {/* -inf */ "T(a)",     "T(b)",      "T(b)",     "T(b)",     "T(b)",      "T(b)",     "Xi: T(a)", "Xi: T(a)"},
261*23f13e19SIlya Leoshkevich             {/* -Fn  */ "T(a)",     "T(M(a,b))", "T(b)",     "T(b)",     "T(b)",      "T(b)",     "Xi: T(a)", "Xi: T(a)"},
262*23f13e19SIlya Leoshkevich             {/* -0   */ "T(a)",     "T(a)",      "T(a)",     "T(a)",     "T(b)",      "T(b)",     "Xi: T(a)", "Xi: T(a)"},
263*23f13e19SIlya Leoshkevich             {/* +0   */ "T(a)",     "T(a)",      "T(a)",     "T(a)",     "T(b)",      "T(b)",     "Xi: T(a)", "Xi: T(a)"},
264*23f13e19SIlya Leoshkevich             {/* +Fn  */ "T(a)",     "T(a)",      "T(a)",     "T(a)",     "T(M(a,b))", "T(b)",     "Xi: T(a)", "Xi: T(a)"},
265*23f13e19SIlya Leoshkevich             {/* +inf */ "T(a)",     "T(a)",      "T(a)",     "T(a)",     "T(a)",      "T(a)",     "Xi: T(a)", "Xi: T(a)"},
266*23f13e19SIlya 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)"},
267*23f13e19SIlya 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)"},
268*23f13e19SIlya Leoshkevich         },
269*23f13e19SIlya Leoshkevich     },
270*23f13e19SIlya Leoshkevich     {
271*23f13e19SIlya Leoshkevich         .op = VFMAX,
272*23f13e19SIlya Leoshkevich         .m6 = 4,
273*23f13e19SIlya Leoshkevich         .m6_desc = "fmax()",
274*23f13e19SIlya Leoshkevich         .table = {
275*23f13e19SIlya Leoshkevich              /*         -inf        -Fn          -0          +0          +Fn          +inf        QNaN        SNaN    */
276*23f13e19SIlya Leoshkevich             {/* -inf */ "T(a)",     "T(b)",      "T(b)",     "T(b)",     "T(b)",      "T(b)",     "T(a)",     "Xi: T(a)"},
277*23f13e19SIlya Leoshkevich             {/* -Fn  */ "T(a)",     "T(M(a,b))", "T(b)",     "T(b)",     "T(b)",      "T(b)",     "T(a)",     "Xi: T(a)"},
278*23f13e19SIlya Leoshkevich             {/* -0   */ "T(a)",     "T(a)",      "T(a)",     "T(b)",     "T(b)",      "T(b)",     "T(a)",     "Xi: T(a)"},
279*23f13e19SIlya Leoshkevich             {/* +0   */ "T(a)",     "T(a)",      "T(a)",     "T(a)",     "T(b)",      "T(b)",     "T(a)",     "Xi: T(a)"},
280*23f13e19SIlya Leoshkevich             {/* +Fn  */ "T(a)",     "T(a)",      "T(a)",     "T(a)",     "T(M(a,b))", "T(b)",     "T(a)",     "Xi: T(a)"},
281*23f13e19SIlya Leoshkevich             {/* +inf */ "T(a)",     "T(a)",      "T(a)",     "T(a)",     "T(a)",      "T(a)",     "T(a)",     "Xi: T(a)"},
282*23f13e19SIlya Leoshkevich             {/* QNaN */ "T(b)",     "T(b)",      "T(b)",     "T(b)",     "T(b)",      "T(b)",     "T(a)",     "Xi: T(a)"},
283*23f13e19SIlya 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)"},
284*23f13e19SIlya Leoshkevich         },
285*23f13e19SIlya Leoshkevich     },
286*23f13e19SIlya Leoshkevich };
287*23f13e19SIlya Leoshkevich 
dump_v(FILE * f,const void * v,size_t n)288*23f13e19SIlya Leoshkevich static void dump_v(FILE *f, const void *v, size_t n)
289*23f13e19SIlya Leoshkevich {
290*23f13e19SIlya Leoshkevich     for (int i = 0; i < n; i++) {
291*23f13e19SIlya Leoshkevich         fprintf(f, "%02x", ((const unsigned char *)v)[i]);
292*23f13e19SIlya Leoshkevich     }
293*23f13e19SIlya Leoshkevich }
294*23f13e19SIlya Leoshkevich 
signed_test(struct signed_test * test,int m4,int m5,const void * v1_exp,bool xi_exp,const void * v2,const void * v3)295*23f13e19SIlya Leoshkevich static int signed_test(struct signed_test *test, int m4, int m5,
296*23f13e19SIlya Leoshkevich                        const void *v1_exp, bool xi_exp,
297*23f13e19SIlya Leoshkevich                        const void *v2, const void *v3)
298*23f13e19SIlya Leoshkevich {
299*23f13e19SIlya Leoshkevich     size_t n = (m5 & 8) ? float_sizes[m4 - 2] : 16;
300*23f13e19SIlya Leoshkevich     char v1[16];
301*23f13e19SIlya Leoshkevich     bool xi;
302*23f13e19SIlya Leoshkevich 
303*23f13e19SIlya Leoshkevich     feclearexcept(FE_ALL_EXCEPT);
304*23f13e19SIlya Leoshkevich     vfminmax(test->op, m4, m5, test->m6, v1, v2, v3);
305*23f13e19SIlya Leoshkevich     xi = fetestexcept(FE_ALL_EXCEPT) == FE_INVALID;
306*23f13e19SIlya Leoshkevich 
307*23f13e19SIlya Leoshkevich     if (memcmp(v1, v1_exp, n) != 0 || xi != xi_exp) {
308*23f13e19SIlya Leoshkevich         fprintf(stderr, "[  FAILED  ] %s ", test->m6_desc);
309*23f13e19SIlya Leoshkevich         dump_v(stderr, v2, n);
310*23f13e19SIlya Leoshkevich         fprintf(stderr, ", ");
311*23f13e19SIlya Leoshkevich         dump_v(stderr, v3, n);
312*23f13e19SIlya Leoshkevich         fprintf(stderr, ", %d, %d, %d: actual=", m4, m5, test->m6);
313*23f13e19SIlya Leoshkevich         dump_v(stderr, v1, n);
314*23f13e19SIlya Leoshkevich         fprintf(stderr, "/%d, expected=", (int)xi);
315*23f13e19SIlya Leoshkevich         dump_v(stderr, v1_exp, n);
316*23f13e19SIlya Leoshkevich         fprintf(stderr, "/%d\n", (int)xi_exp);
317*23f13e19SIlya Leoshkevich         return 1;
318*23f13e19SIlya Leoshkevich     }
319*23f13e19SIlya Leoshkevich 
320*23f13e19SIlya Leoshkevich     return 0;
321*23f13e19SIlya Leoshkevich }
322*23f13e19SIlya Leoshkevich 
snan_to_qnan(char * v,int m4)323*23f13e19SIlya Leoshkevich static void snan_to_qnan(char *v, int m4)
324*23f13e19SIlya Leoshkevich {
325*23f13e19SIlya Leoshkevich     size_t bit = 1 + e_bits[m4 - 2];
326*23f13e19SIlya Leoshkevich     v[bit / 8] |= 1 << (7 - (bit % 8));
327*23f13e19SIlya Leoshkevich }
328*23f13e19SIlya Leoshkevich 
main(void)329*23f13e19SIlya Leoshkevich int main(void)
330*23f13e19SIlya Leoshkevich {
331*23f13e19SIlya Leoshkevich     int ret = 0;
332*23f13e19SIlya Leoshkevich     size_t i;
333*23f13e19SIlya Leoshkevich 
334*23f13e19SIlya Leoshkevich     for (i = 0; i < sizeof(signed_tests) / sizeof(signed_tests[0]); i++) {
335*23f13e19SIlya Leoshkevich         struct signed_test *test = &signed_tests[i];
336*23f13e19SIlya Leoshkevich         int m4;
337*23f13e19SIlya Leoshkevich 
338*23f13e19SIlya Leoshkevich         for (m4 = 2; m4 <= 4; m4++) {
339*23f13e19SIlya Leoshkevich             const unsigned char (*floats)[2][16] = signed_floats[m4 - 2];
340*23f13e19SIlya Leoshkevich             size_t float_size = float_sizes[m4 - 2];
341*23f13e19SIlya Leoshkevich             int m5;
342*23f13e19SIlya Leoshkevich 
343*23f13e19SIlya Leoshkevich             for (m5 = 0; m5 <= 8; m5 += 8) {
344*23f13e19SIlya Leoshkevich                 char v1_exp[16], v2[16], v3[16];
345*23f13e19SIlya Leoshkevich                 bool xi_exp = false;
346*23f13e19SIlya Leoshkevich                 int pos = 0;
347*23f13e19SIlya Leoshkevich                 int i2;
348*23f13e19SIlya Leoshkevich 
349*23f13e19SIlya Leoshkevich                 for (i2 = 0; i2 < N_SIGNED_CLASSES * 2; i2++) {
350*23f13e19SIlya Leoshkevich                     int i3;
351*23f13e19SIlya Leoshkevich 
352*23f13e19SIlya Leoshkevich                     for (i3 = 0; i3 < N_SIGNED_CLASSES * 2; i3++) {
353*23f13e19SIlya Leoshkevich                         const char *spec = test->table[i2 / 2][i3 / 2];
354*23f13e19SIlya Leoshkevich 
355*23f13e19SIlya Leoshkevich                         memcpy(&v2[pos], floats[i2 / 2][i2 % 2], float_size);
356*23f13e19SIlya Leoshkevich                         memcpy(&v3[pos], floats[i3 / 2][i3 % 2], float_size);
357*23f13e19SIlya Leoshkevich                         if (strcmp(spec, "T(a)") == 0 ||
358*23f13e19SIlya Leoshkevich                             strcmp(spec, "Xi: T(a)") == 0) {
359*23f13e19SIlya Leoshkevich                             memcpy(&v1_exp[pos], &v2[pos], float_size);
360*23f13e19SIlya Leoshkevich                         } else if (strcmp(spec, "T(b)") == 0 ||
361*23f13e19SIlya Leoshkevich                                    strcmp(spec, "Xi: T(b)") == 0) {
362*23f13e19SIlya Leoshkevich                             memcpy(&v1_exp[pos], &v3[pos], float_size);
363*23f13e19SIlya Leoshkevich                         } else if (strcmp(spec, "Xi: T(a*)") == 0) {
364*23f13e19SIlya Leoshkevich                             memcpy(&v1_exp[pos], &v2[pos], float_size);
365*23f13e19SIlya Leoshkevich                             snan_to_qnan(&v1_exp[pos], m4);
366*23f13e19SIlya Leoshkevich                         } else if (strcmp(spec, "Xi: T(b*)") == 0) {
367*23f13e19SIlya Leoshkevich                             memcpy(&v1_exp[pos], &v3[pos], float_size);
368*23f13e19SIlya Leoshkevich                             snan_to_qnan(&v1_exp[pos], m4);
369*23f13e19SIlya Leoshkevich                         } else if (strcmp(spec, "T(M(a,b))") == 0) {
370*23f13e19SIlya Leoshkevich                             /*
371*23f13e19SIlya Leoshkevich                              * Comparing floats is risky, since the compiler
372*23f13e19SIlya Leoshkevich                              * might generate the same instruction that we are
373*23f13e19SIlya Leoshkevich                              * testing. Compare ints instead. This works,
374*23f13e19SIlya Leoshkevich                              * because we get here only for +-Fn, and the
375*23f13e19SIlya Leoshkevich                              * corresponding test values have identical
376*23f13e19SIlya Leoshkevich                              * exponents.
377*23f13e19SIlya Leoshkevich                              */
378*23f13e19SIlya Leoshkevich                             int v2_int = *(int *)&v2[pos];
379*23f13e19SIlya Leoshkevich                             int v3_int = *(int *)&v3[pos];
380*23f13e19SIlya Leoshkevich 
381*23f13e19SIlya Leoshkevich                             if ((v2_int < v3_int) ==
382*23f13e19SIlya Leoshkevich                                 ((test->op == VFMIN) != (v2_int < 0))) {
383*23f13e19SIlya Leoshkevich                                 memcpy(&v1_exp[pos], &v2[pos], float_size);
384*23f13e19SIlya Leoshkevich                             } else {
385*23f13e19SIlya Leoshkevich                                 memcpy(&v1_exp[pos], &v3[pos], float_size);
386*23f13e19SIlya Leoshkevich                             }
387*23f13e19SIlya Leoshkevich                         } else {
388*23f13e19SIlya Leoshkevich                             fprintf(stderr, "Unexpected spec: %s\n", spec);
389*23f13e19SIlya Leoshkevich                             return 1;
390*23f13e19SIlya Leoshkevich                         }
391*23f13e19SIlya Leoshkevich                         xi_exp |= spec[0] == 'X';
392*23f13e19SIlya Leoshkevich                         pos += float_size;
393*23f13e19SIlya Leoshkevich 
394*23f13e19SIlya Leoshkevich                         if ((m5 & 8) || pos == 16) {
395*23f13e19SIlya Leoshkevich                             ret |= signed_test(test, m4, m5,
396*23f13e19SIlya Leoshkevich                                                v1_exp, xi_exp, v2, v3);
397*23f13e19SIlya Leoshkevich                             pos = 0;
398*23f13e19SIlya Leoshkevich                             xi_exp = false;
399*23f13e19SIlya Leoshkevich                         }
400*23f13e19SIlya Leoshkevich                     }
401*23f13e19SIlya Leoshkevich                 }
402*23f13e19SIlya Leoshkevich 
403*23f13e19SIlya Leoshkevich                 if (pos != 0) {
404*23f13e19SIlya Leoshkevich                     ret |= signed_test(test, m4, m5, v1_exp, xi_exp, v2, v3);
405*23f13e19SIlya Leoshkevich                 }
406*23f13e19SIlya Leoshkevich             }
407*23f13e19SIlya Leoshkevich         }
408*23f13e19SIlya Leoshkevich     }
409*23f13e19SIlya Leoshkevich 
410*23f13e19SIlya Leoshkevich     return ret;
411*23f13e19SIlya Leoshkevich }
412