xref: /onnv-gate/usr/src/cmd/fps/fptest/benchmarks.c (revision 7186:e728311aafb0)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 #ifdef __lint
30 #pragma error_messages(off, E_VALUE_TYPE)
31 #endif
32 
33 #include <stdlib.h>
34 #include <unistd.h>
35 #include <fp.h>
36 #include <fps_ereport.h>
37 
38 #define	EXPECTED	1.9999999999999998E+00
39 
40 static void fdivd(double *f22, double *f2, double *f12);
41 static void fmuld(double *x, double *y, double *z, double *z1);
42 static void fmulx(uint64_t *rs1, uint64_t *rs2, uint64_t *rd);
43 int fpu_fdivd(int rloop, struct fps_test_ereport *report);
44 int fpu_fmuld(int rloop, struct fps_test_ereport *report);
45 int fpu_fmulx(int rloop, struct fps_test_ereport *report);
46 
47 #ifdef V9B
48 
49 /* Lint doesn't recognize .il files where these are defined */
50 #ifdef __lint
51 
52 unsigned long fcmpgt16(double in1, double in2);
53 unsigned long fcmpne16(double in1, double in2);
54 unsigned long setgsr(unsigned long);
55 
56 #else
57 
58 extern float fpackfix(double num);
59 extern unsigned long fcmpgt16(double in1, double in2);
60 extern unsigned long fcmpne16(double in1, double in2);
61 extern unsigned long setgsr(unsigned long);
62 
63 #endif
64 
65 int align_data(int loop,
66     struct fps_test_ereport *report);
67 int vis_test(struct fps_test_ereport *report);
68 static int align_error_create(char *err, uint32_t start, uint32_t offest,
69     int loop, uint32_t count);
70 static int do_aligndata(uchar_t *from, uint32_t *offset, size_t sz,
71     uchar_t *f0, uchar_t *f2, uint32_t bmask);
72 static int visgt16(struct fps_test_ereport *report);
73 static int visne16(struct fps_test_ereport *report);
74 static int vispackfix(struct fps_test_ereport *report);
75 
76 #endif
77 
78 
79 /*
80  * fpu_fdivd(int rloop, int unit, struct fps_test_ereport *report)
81  * returns whether the correct value is calculated each time
82  * rloop times. If an error is found, the relevant data is stored
83  * in report. The test uses internally generated random double
84  * precision within a certain range to conduct the following test:
85  *
86  * (a * 2^1022) / ((a+e) * 2^1021)
87  *
88  * which is guaranteed to fill the resulting mantissa with all ones.
89  *
90  */
91 int
fpu_fdivd(int rloop,struct fps_test_ereport * report)92 fpu_fdivd(int rloop, struct fps_test_ereport *report)
93 {
94 
95 	char err_data[MAX_INFO_SIZE];
96 	double expect_ans = EXPECTED;
97 	double f12 = 0;
98 	double f2;
99 	double f22;
100 	int loop = 0;
101 	uint64_t expect;
102 	uint64_t observe;
103 
104 	srand48(1L);
105 
106 	while (loop < rloop) {
107 		loop++;
108 
109 		*(uint32_t *)& f22 = mrand48();
110 		*(uint32_t *)& f22 &= 0x80069fff;
111 		*(uint32_t *)& f22 |= 0x7fd69f00;
112 
113 #ifdef __lint
114 		(void) f22;
115 #endif
116 
117 		*((uint32_t *)& f22 + 1) = mrand48();
118 		*((uint32_t *)& f22 + 1) |= 0x00000001;
119 
120 		*(uint64_t *)& f2 = *(uint64_t *)& f22 + 1;
121 		*(uint32_t *)& f2 &= 0x800FFFFF;
122 		*(uint32_t *)& f2 |= 0x7FC00000;
123 #ifdef __lint
124 		(void) f2;
125 #endif
126 
127 		fdivd(&f22, &f2, &f12);
128 
129 		if (f12 != expect_ans) {
130 			(void) snprintf(err_data, sizeof (err_data),
131 			    "\nExpected: %.16e,\nObserved: %.16e",
132 			    expect_ans, f12);
133 			expect = *(uint64_t *)&expect_ans;
134 			observe = *(uint64_t *)&f12;
135 			setup_fps_test_struct(IS_EREPORT_INFO, report,
136 			    6340, &observe, &expect, 1, 1, err_data);
137 
138 			return (-1);
139 		}
140 	}
141 
142 	return (0);
143 }
144 
145 /*
146  * fdivd(uint64_t *rs1, uint64_t *rs2, uint64_t *rd)
147  * performs the assembly level instructions for
148  * fpu_fdivd.
149  */
150 /* ARGSUSED */
151 static void
fdivd(double * f22,double * f2,double * f12)152 fdivd(double *f22, double *f2, double *f12)
153 {
154 	asm("ldd	[%i0], %f22");
155 	asm("ldd	[%i1], %f2");
156 	asm("fdivd   	%f22, %f2, %f12");
157 	asm("std	%f12,[%i2]");
158 	asm("membar #Sync");
159 }
160 
161 /*
162  * fpu_fmuld(int rloop, int unit, struct fps_test_ereport *report)
163  * returns whether the correct value is calculated each time
164  * rloop times. If an error is found, the relevant data is stored
165  * in report. The goal is to check if (x * y) == (y * x). The
166  * data pattern is important, and the back-to-back fmuld's are
167  * important.
168  */
169 int
fpu_fmuld(int rloop,struct fps_test_ereport * report)170 fpu_fmuld(int rloop, struct fps_test_ereport *report)
171 {
172 	char err_data[MAX_INFO_SIZE];
173 	double x;
174 	double y;
175 	double z;
176 	double z1;
177 	int loop;
178 	uint64_t expect;
179 	uint64_t observe;
180 	uint64_t *px;
181 	uint64_t *py;
182 
183 	loop = 0;
184 	px = (uint64_t *)& x;
185 	py = (uint64_t *)& y;
186 	*px = 0x2FEBD8507111CDE5UL;	/* 4865027 */
187 	*py = 0x2FE284A9A98EAA26UL;
188 
189 #ifdef __lint
190 	(void) x;
191 	(void) y;
192 #endif
193 
194 	while (loop < rloop) {
195 		loop++;
196 		z = z1 = 0.0;
197 
198 		/*
199 		 * Data pattern and back-to-back fmuld() are
200 		 * important
201 		 */
202 		fmuld(&x, &y, &z, &z1);
203 
204 		if (*(uint64_t *)&z != *(uint64_t *)&z1) {
205 			(void) snprintf(err_data, sizeof (err_data),
206 			    "\nExpected: %.16e,\nObserved: %.16e",
207 			    *(uint64_t *)&z, *(uint64_t *)&z1);
208 			expect = *(uint64_t *)&z;
209 			observe = *(uint64_t *)&z1;
210 			setup_fps_test_struct(IS_EREPORT_INFO, report,
211 			    6341, &observe, &expect, 1, 1, err_data);
212 
213 			return (-1);
214 		}
215 	}
216 
217 	return (0);
218 }
219 
220 /*
221  * fmuld(double *x,double *y, double *z, double *z1)
222  * performs the assembly level instructions for
223  * fpu_fmuld.
224  */
225 /* ARGSUSED */
226 static void
fmuld(double * x,double * y,double * z,double * z1)227 fmuld(double *x, double *y, double *z, double *z1)
228 {
229 	asm("ldd[%i0], %f0");
230 	asm("ldd[%i1], %f4");
231 	asm("fmuld%f0, %f4, %f2");
232 	asm("fmuld%f4, %f0, %f6");
233 	asm("std%f2, [%i2]");
234 	asm("std%f6, [%i3]");
235 	asm("membar #Sync");
236 }
237 
238 
239 /*
240  * fpu_fmulx(int rloop, int unit, struct fps_test_ereport *report)
241  * returns whether the correct value is calculated each time
242  * rloop times. If an error is found, the relevant data is stored
243  * in report. The goal is to check if (x * y) == (y * x) with
244  * 64-bit intgers.
245  */
246 int
fpu_fmulx(int rloop,struct fps_test_ereport * report)247 fpu_fmulx(int rloop, struct fps_test_ereport *report)
248 {
249 	char err_data[MAX_INFO_SIZE];
250 	int loop;
251 	int loop_lim;
252 	uint32_t *rs1;
253 	uint32_t *rs2;
254 	uint64_t expect;
255 	uint64_t observe;
256 	uint64_t v1;
257 	uint64_t v2;
258 	uint64_t vd1;
259 	uint64_t vd2;
260 	uint64_t *rd1;
261 	uint64_t *rd2;
262 
263 	v1 = v2 = vd1 = vd2 = 0;
264 	loop = 0;
265 	loop_lim = rloop;
266 
267 	if (loop_lim < 10)
268 		loop_lim = 10;
269 
270 	if (loop_lim > 100000)
271 		loop_lim = 100000;
272 
273 	rs1 = (uint32_t *)& v1;
274 	rs2 = (uint32_t *)& v2;
275 	rd1 = &vd1;
276 	rd2 = &vd2;
277 
278 #ifdef __lint
279 	(void) v1;
280 	(void) v2;
281 #endif
282 
283 	srand(0l);
284 	while (loop < loop_lim) {
285 		loop++;
286 
287 #ifndef __lint
288 
289 		*rs1 = mrand48();
290 		*(rs1 + 1) = mrand48();
291 		*rs2 = mrand48();
292 		*(rs2 + 1) = mrand48();
293 #endif
294 
295 		/* LINTED */
296 		fmulx((uint64_t *)rs1, (uint64_t *)rs2, rd1);
297 
298 		/* LINTED */
299 		fmulx((uint64_t *)rs2, (uint64_t *)rs1, rd2);
300 
301 		if (*rd1 != *rd2) {
302 			expect = (uint64_t)*rd1;
303 			observe = (uint64_t)*rd2;
304 			(void) snprintf(err_data, sizeof (err_data),
305 			    "\nExpected: %lld\nObserved: %lld", *rd1, *rd2);
306 			setup_fps_test_struct(IS_EREPORT_INFO, report,
307 			    6356, &observe, &expect, 1, 1, err_data);
308 
309 		return (-1);
310 		}
311 	}
312 
313 	return (0);
314 }
315 
316 /*
317  * fmulx(uint64_t *rs1, uint64_t *rs2, uint64_t *rd)
318  * performs the assembly level instructions for
319  * fpu_fmulx.
320  */
321 /* ARGSUSED */
322 static void
fmulx(uint64_t * rs1,uint64_t * rs2,uint64_t * rd)323 fmulx(uint64_t *rs1, uint64_t *rs2, uint64_t *rd)
324 {
325 	asm("ldx   [%i0], %l0");
326 	asm("ldx   [%i1], %l1");
327 	asm("mulx  %l0, %l1, %l2");
328 	asm("stx   %l2, [%i2]");
329 	asm("membar	#Sync");
330 
331 }
332 
333 
334 
335 #ifdef V9B
336 
337 #pragma align 64  (f0)
338 #pragma align 8  (f2)
339 
340 #define	MEMSIZE	2048*3
341 
342 static uchar_t f0[64];
343 static uchar_t f2[8];
344 
345 static uint32_t bmask[] = {0x01234567, 0x12345678,
346 			0x23456789, 0x3456789a,
347 			0x456789ab, 0x56789abc,
348 			0x6789abcd, 0x789abcde,
349 			0x89abcdef, 0x9abcdef0,
350 			0xabcdef01, 0xbcdef012,
351 			0xcdef0123, 0xdef01234,
352 			0xef012345, 0xf0123456,
353 			0x55555555, 0xaaaaaaaa,
354 			0x00000000, 0xffffffff};
355 
356 #ifdef __lint
357 
358 /*ARGSUSED*/
359 unsigned long
setgsr(unsigned long arg1)360 setgsr(unsigned long arg1)
361 {
362 	return (0);
363 }
364 
365 /*ARGSUSED*/
366 float
fpackfix(double arg1)367 fpackfix(double arg1)
368 {
369 	return (0.0);
370 }
371 
372 /*ARGSUSED*/
373 unsigned long
fcmpne16(double arg1,double arg2)374 fcmpne16(double arg1, double arg2)
375 {
376 	return (0);
377 }
378 
379 /*ARGSUSED*/
380 unsigned long
fcmpgt16(double arg1,double arg2)381 fcmpgt16(double arg1, double arg2)
382 {
383 	return (0);
384 }
385 
386 #endif /* LINT */
387 
388 /*
389  * align_data(int loop, struct fps_test_ereport *report)
390  * returns whether a miscompare was found after running alignment tests
391  * loop amount of times. If an error is found, relevant data is stored
392  * in report. This test exercises the alignaddr and aligndata
393  * instructions with different byte alignments to ensure proper
394  * operation. These two instructions are used extensively by the kernel
395  * to move data size greater than 512 bytes. User level memcpy and
396  * memmove library also use these instructions for data size
397  * greater than 256 bytes.
398  */
399 int
align_data(int loop,struct fps_test_ereport * report)400 align_data(int loop, struct fps_test_ereport *report)
401 {
402 	char err[MAX_INFO_SIZE];
403 	int test_ret;
404 	int nr_malloc;
405 	size_t memsize;
406 	struct timeval timeout;
407 	uchar_t c;
408 	uchar_t *pf0;
409 	uchar_t *pf2;
410 	uchar_t *src;
411 	uint32_t cnt;
412 	uint32_t i;
413 	uint32_t offset;
414 	uint32_t start;
415 	uint64_t expect[2];
416 	uint64_t observe[2];
417 
418 	timeout.tv_sec = 0;
419 	timeout.tv_usec = 10000;
420 	nr_malloc = 0;
421 	err[0] = '\0';
422 
423 	/* Make sure memsize is 64 bytes aligned  with minimum of 64 bytes */
424 	memsize = MEMSIZE;
425 	memsize = memsize / 64 * 64;
426 
427 	if (memsize < 64)
428 		memsize = 64;
429 
430 	src = (uchar_t *)memalign(64, memsize + 64);
431 
432 	while (src == NULL && nr_malloc < 10) {
433 		(void) select(1, NULL, NULL, NULL, &timeout);
434 		nr_malloc++;
435 		src = (uchar_t *)memalign(64, memsize + 64);
436 	}
437 
438 	if (src == NULL)
439 		_exit(FPU_SYSCALL_FAIL);
440 
441 	/* Initialize source array with sequential data */
442 	c = 0;
443 
444 	for (i = 0; i < memsize + 64; i++)
445 		*(src + i) = c++;
446 
447 	for (cnt = 0; cnt < loop; cnt++) {
448 		for (start = 1; start < 64; start += 1) {
449 			offset = 0;
450 
451 			test_ret = do_aligndata(src + start, &offset,
452 			    memsize, f0, f2, bmask[cnt % 20]);
453 
454 			/*
455 			 * Miscompare on the two aligndata
456 			 * instructions. Calculate offset to source
457 			 * array and get miscompare data
458 			 */
459 
460 			if (test_ret != 0) {
461 				pf0 = f0 + offset % 64;
462 				pf2 = f2;
463 
464 				for (i = 0; i < 8; i++) {
465 					if (*(pf0 + i) != *(pf2 + i))
466 						break;
467 				}
468 
469 				(void) align_error_create(err, start,
470 				    offset + start + i, loop, cnt);
471 				expect[0] =
472 				    (uint64_t)(*(uint8_t *)
473 				    (src + offset + start + i));
474 				expect[1] = (uint64_t)0;
475 				observe[0] = (uint64_t)(*(uint8_t *)(pf0 + i));
476 				observe[1] = (uint64_t)(*(uint8_t *)(pf2 + i));
477 				setup_fps_test_struct(
478 				    IS_EREPORT_INFO,
479 				    report, 6344, observe,
480 				    expect, 1, 2, err);
481 
482 				free(src);
483 
484 				return (-1);
485 			}
486 
487 			/*
488 			 * No miscompare on the aligndata
489 			 * instructions. Check to see whether the
490 			 * last 64 bytes matches the input
491 			 */
492 			if (test_ret == 0) {
493 				pf2 = src + offset + start;
494 
495 				for (i = 0; i < 64; i++) {
496 					if (f0[i] != *(pf2 + i)) {
497 
498 						(void) align_error_create(err,
499 						    start,
500 						    offset + start + i,
501 						    loop, cnt);
502 						expect[0] =
503 						    (uint64_t)(*(uint8_t *)
504 						    (pf2 + i));
505 						expect[1] = (uint64_t)0;
506 						observe[0] = (uint64_t)f0[i];
507 						observe[1] = (uint64_t)0;
508 						setup_fps_test_struct(
509 						    IS_EREPORT_INFO,
510 						    report, 6343, observe,
511 						    expect, 1, 1, err);
512 
513 						free(src);
514 						return (-1);
515 					}
516 				}
517 			}
518 		}
519 	}
520 
521 	free(src);
522 
523 	return (0);
524 }
525 
526 /*
527  * align_error_create(char *err, int start, int offset, int loop, int count)
528  * returns if a successful snprintf was performed when creating an align_data
529  * error message for align_data.
530  */
531 static int
align_error_create(char * err,uint32_t start,uint32_t offset,int loop,uint32_t count)532 align_error_create(char *err, uint32_t start,
533 	uint32_t offset, int loop, uint32_t count)
534 {
535 	if (err == NULL)
536 		return (-1);
537 
538 	return snprintf(err, sizeof (err),
539 	    "Start = %2.2d offset = %2.2d loop = %d cnt = %d",
540 	    start, offset, loop, count);
541 }
542 
543 /*
544  * do_aligndata(uchar_t *from, uint32_t *offset, size_t sz,
545  * uchar_t *f0, uchar_t *f2, uint32_t bmask) performs
546  * the assembly lvl routines for align_data.
547  */
548 /*ARGSUSED*/
549 static int
do_aligndata(uchar_t * from,uint32_t * offset,size_t sz,uchar_t * f0,uchar_t * f2,uint32_t bmask)550 do_aligndata(uchar_t *from, uint32_t *offset, size_t sz,
551 	uchar_t *f0, uchar_t *f2, uint32_t bmask)
552 {
553 	int ret = 1;
554 
555 	asm("bmask	%i5,%g0,%g0");
556 	/* produce GSR.offset and align %l0 to 8 bytes boundary */
557 	asm("alignaddr	%i0, %g0, %l0");
558 	/* %i0 then used as error register, assume error */
559 	asm("mov	1,%i0");
560 	/* %l1 used as offset counter */
561 	asm("mov	-8,%l1");
562 	asm("ldd	[%l0], %f0");
563 
564 	asm("next_read:");
565 
566 	asm("ldd	[%l0+8], %f2");
567 	asm("ldd	[%l0+0x10], %f4");
568 	asm("faligndata	%f0, %f2, %f32");
569 	asm("faligndata	%f0, %f2, %f48");
570 	asm("fcmpd	%fcc0,%f32,%f48");
571 	asm("fblg,pn	%fcc0,error");
572 	/* %l1 contains offset value */
573 	asm("add	%l1,8,%l1");
574 	/* 0 - 7 */
575 
576 	asm("ldd	[%l0+0x18], %f6");
577 	asm("faligndata	%f2, %f4, %f34");
578 	asm("faligndata	%f2, %f4, %f48");
579 	asm("fcmpd	%fcc0,%f34,%f48");
580 	asm("fblg,pn	%fcc0,error");
581 	/* %l1 contains offset value */
582 	asm("add	%l1,8,%l1");
583 	/* 9 - 15 */
584 
585 	asm("ldd	[%l0+0x20], %f8");
586 	asm("faligndata	%f4, %f6, %f36");
587 	asm("faligndata	%f4, %f6, %f48");
588 	asm("fcmpd	%fcc0,%f36,%f48");
589 	asm("fblg,pn	%fcc0,error");
590 	/* %l1 contains offset value */
591 	asm("add	%l1,8,%l1");
592 	/* 16 - 23 */
593 
594 	asm("ldd	[%l0+0x28], %f10");
595 	asm("faligndata	%f6, %f8, %f38");
596 	asm("faligndata	%f6, %f8, %f48");
597 	asm("fcmpd	%fcc0,%f38,%f48");
598 	asm("fblg,pn	%fcc0,error");
599 	/* contains offset value */
600 	asm("add	%l1,8,%l1");
601 	/* 24 - 31 */
602 
603 	asm("ldd	[%l0+0x28], %f10");
604 	asm("faligndata	%f8, %f10, %f40");
605 	asm("faligndata	%f8, %f10, %f48");
606 	asm("fcmpd	%fcc0,%f40,%f48");
607 	asm("fblg,pn	%fcc0,error");
608 	/* %l1 contains offset value */
609 	asm("add	%l1,8,%l1");
610 	/* 32 - 39 */
611 
612 	asm("ldd	[%l0+0x30], %f12");
613 	asm("faligndata	%f10, %f12, %f42");
614 	asm("faligndata	%f10, %f12, %f48");
615 	asm("fcmpd	%fcc0,%f42,%f48");
616 	asm("fblg,pn	%fcc0,error");
617 	/* %l1 contains offset value */
618 	asm("add	%l1,8,%l1");
619 	/* 40 - 47 */
620 
621 	asm("ldd	[%l0+0x38], %f14");
622 	asm("faligndata	%f12, %f14, %f44");
623 	asm("faligndata	%f12, %f14, %f48");
624 	asm("fcmpd	%fcc0,%f44,%f48");
625 	asm("fblg,pn	%fcc0,error");
626 	/* %l1 contains offset value */
627 	asm("add	%l1,8,%l1");
628 	/* 48 - 55 */
629 
630 	asm("ldd	[%l0+0x40], %f0");
631 	asm("faligndata	%f14, %f0, %f46");
632 	asm("faligndata	%f14, %f0, %f48");
633 	asm("fcmpd	%fcc0,%f46,%f48");
634 	asm("fblg,pn	%fcc0,error");
635 	/* %l1 contains offset value */
636 	asm("add	%l1,8,%l1");
637 	/* 56 - 63 */
638 
639 	asm("subcc	%i2,64,%i2");
640 	asm("bg		next_read");
641 	asm("add	%l0,64,%l0");
642 
643 	/* no miscompare error */
644 	asm("mov	0,%i0");
645 	ret = 0;
646 	/* no error, move back to last 64 bytes boundary */
647 	asm("sub	%l1,56,%l1");
648 
649 	asm("error:");
650 	asm("stda	%f32,[%i3]0xf0");
651 	asm("std	%f48,[%i4]");
652 	/* store offset value */
653 	asm("st 	%l1,[%i1]");
654 	asm("membar	#Sync");
655 
656 	return (ret);
657 }
658 
659 /*
660  * vis_test(struct fps_test_ereport *report)
661  * checks if various RISC operations are performed
662  * succesfully. If an error is found, relevant data
663  * is stored in report.
664  */
665 int
vis_test(struct fps_test_ereport * report)666 vis_test(struct fps_test_ereport *report)
667 {
668 	int v1;
669 	int v2;
670 	int v3;
671 
672 	v1 = visgt16(report);
673 	v2 = visne16(report);
674 	v3 = vispackfix(report);
675 
676 	if ((0 != v1) || (0 != v2) || (0 != v3))
677 		return (-1);
678 
679 	return (0);
680 }
681 
682 /*
683  * visgt16(struct fps_test_ereport *report)
684  * does a greater-than compare instruction and returns if
685  * successful or not. If an error, relevant data is
686  * stored in report.
687  */
688 static int
visgt16(struct fps_test_ereport * report)689 visgt16(struct fps_test_ereport *report)
690 {
691 	uint64_t expected;
692 	uint64_t observed;
693 	unsigned long a = 0x0000000000000001;
694 	unsigned long b = 0x8000000008000008;
695 	unsigned long c = fcmpgt16(*((double *)&a), *((double *)&b));
696 
697 	if (c == 0x8)
698 		return (0);
699 	else {
700 		expected = (uint64_t)0x8;
701 		observed = (*(uint64_t *)&c);
702 		setup_fps_test_struct(NO_EREPORT_INFO, report,
703 		    6364, &observed, &expected, 1, 1);
704 
705 		return (-1);
706 	}
707 }
708 
709 /*
710  * visne16(struct fps_test_ereport *report)
711  * does a not-equal compare instruction and returns if
712  * successful or not. If an error, relevant data is
713  * stored in report.
714  */
715 static int
visne16(struct fps_test_ereport * report)716 visne16(struct fps_test_ereport *report)
717 {
718 	uint64_t expected;
719 	uint64_t observed;
720 	unsigned long a = 0x0000000000000001;
721 	unsigned long b = 0x0001000000001001;
722 	unsigned long c = fcmpne16(*((double *)&a), *((double *)&b));
723 
724 	if (c == 0x9)
725 		return (0);
726 	else {
727 		expected = (uint64_t)0x9;
728 		observed = (*(uint64_t *)&c);
729 		setup_fps_test_struct(NO_EREPORT_INFO, report,
730 		    6365, &observed, &expected, 1, 1);
731 
732 		return (-1);
733 	}
734 }
735 
736 /*
737  * vispackfix(struct fps_test_ereport *report)
738  * does four 16-bit pack conversions to a lower precsion
739  * format and returns if successful or not. If an error,
740  * relevant data is stored in report.
741  */
742 static int
vispackfix(struct fps_test_ereport * report)743 vispackfix(struct fps_test_ereport *report)
744 {
745 	float b;
746 	uint64_t expected;
747 	uint64_t observed;
748 	unsigned int c;
749 	unsigned long a = 0x8008000008008008;
750 	unsigned long gsr = 0;
751 
752 	(void) setgsr(gsr);
753 
754 	b = fpackfix(*((double *)&a));
755 	c = *((unsigned int *)&b);
756 
757 	if (c == 0x80080800)
758 		return (0);
759 	else {
760 		expected = (uint64_t)0x80080800;
761 		observed = (uint64_t)c;
762 		setup_fps_test_struct(NO_EREPORT_INFO, report,
763 		    6366, &observed, &expected, 1, 1);
764 
765 		return (-1);
766 	}
767 }
768 
769 #endif
770