Home | History | Annotate | Download | only in fptest
      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
     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
    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
    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
    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
    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
    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
    360 setgsr(unsigned long arg1)
    361 {
    362 	return (0);
    363 }
    364 
    365 /*ARGSUSED*/
    366 float
    367 fpackfix(double arg1)
    368 {
    369 	return (0.0);
    370 }
    371 
    372 /*ARGSUSED*/
    373 unsigned long
    374 fcmpne16(double arg1, double arg2)
    375 {
    376 	return (0);
    377 }
    378 
    379 /*ARGSUSED*/
    380 unsigned long
    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
    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
    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
    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
    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
    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
    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
    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