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