xref: /onnv-gate/usr/src/cmd/fps/fptest/benchmarks.c (revision 7186:e728311aafb0)
16429Svs195195 /*
26429Svs195195  * CDDL HEADER START
36429Svs195195  *
46429Svs195195  * The contents of this file are subject to the terms of the
56429Svs195195  * Common Development and Distribution License (the "License").
66429Svs195195  * You may not use this file except in compliance with the License.
76429Svs195195  *
86429Svs195195  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
96429Svs195195  * or http://www.opensolaris.org/os/licensing.
106429Svs195195  * See the License for the specific language governing permissions
116429Svs195195  * and limitations under the License.
126429Svs195195  *
136429Svs195195  * When distributing Covered Code, include this CDDL HEADER in each
146429Svs195195  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
156429Svs195195  * If applicable, add the following below this CDDL HEADER, with the
166429Svs195195  * fields enclosed by brackets "[]" replaced with your own identifying
176429Svs195195  * information: Portions Copyright [yyyy] [name of copyright owner]
186429Svs195195  *
196429Svs195195  * CDDL HEADER END
206429Svs195195  */
216429Svs195195 
226429Svs195195 /*
236491Sia112686  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
246429Svs195195  * Use is subject to license terms.
256429Svs195195  */
266429Svs195195 
276429Svs195195 #pragma ident	"%Z%%M%	%I%	%E% SMI"
286429Svs195195 
296429Svs195195 #ifdef __lint
306429Svs195195 #pragma error_messages(off, E_VALUE_TYPE)
316429Svs195195 #endif
326429Svs195195 
336429Svs195195 #include <stdlib.h>
346429Svs195195 #include <unistd.h>
356429Svs195195 #include <fp.h>
366429Svs195195 #include <fps_ereport.h>
376429Svs195195 
386429Svs195195 #define	EXPECTED	1.9999999999999998E+00
396429Svs195195 
406429Svs195195 static void fdivd(double *f22, double *f2, double *f12);
416429Svs195195 static void fmuld(double *x, double *y, double *z, double *z1);
426429Svs195195 static void fmulx(uint64_t *rs1, uint64_t *rs2, uint64_t *rd);
436429Svs195195 int fpu_fdivd(int rloop, struct fps_test_ereport *report);
446429Svs195195 int fpu_fmuld(int rloop, struct fps_test_ereport *report);
456429Svs195195 int fpu_fmulx(int rloop, struct fps_test_ereport *report);
466429Svs195195 
476429Svs195195 #ifdef V9B
486429Svs195195 
49*7186Skk158166 /* Lint doesn't recognize .il files where these are defined */
50*7186Skk158166 #ifdef __lint
51*7186Skk158166 
52*7186Skk158166 unsigned long fcmpgt16(double in1, double in2);
53*7186Skk158166 unsigned long fcmpne16(double in1, double in2);
54*7186Skk158166 unsigned long setgsr(unsigned long);
55*7186Skk158166 
56*7186Skk158166 #else
57*7186Skk158166 
586429Svs195195 extern float fpackfix(double num);
596429Svs195195 extern unsigned long fcmpgt16(double in1, double in2);
606429Svs195195 extern unsigned long fcmpne16(double in1, double in2);
61*7186Skk158166 extern unsigned long setgsr(unsigned long);
626429Svs195195 
63*7186Skk158166 #endif
64*7186Skk158166 
65*7186Skk158166 int align_data(int loop,
666429Svs195195     struct fps_test_ereport *report);
67*7186Skk158166 int vis_test(struct fps_test_ereport *report);
68*7186Skk158166 static int align_error_create(char *err, uint32_t start, uint32_t offest,
69*7186Skk158166     int loop, uint32_t count);
706429Svs195195 static int do_aligndata(uchar_t *from, uint32_t *offset, size_t sz,
716429Svs195195     uchar_t *f0, uchar_t *f2, uint32_t bmask);
72*7186Skk158166 static int visgt16(struct fps_test_ereport *report);
73*7186Skk158166 static int visne16(struct fps_test_ereport *report);
74*7186Skk158166 static int vispackfix(struct fps_test_ereport *report);
756429Svs195195 
766429Svs195195 #endif
776429Svs195195 
786429Svs195195 
796429Svs195195 /*
806429Svs195195  * fpu_fdivd(int rloop, int unit, struct fps_test_ereport *report)
816429Svs195195  * returns whether the correct value is calculated each time
826429Svs195195  * rloop times. If an error is found, the relevant data is stored
836429Svs195195  * in report. The test uses internally generated random double
846429Svs195195  * precision within a certain range to conduct the following test:
856429Svs195195  *
866429Svs195195  * (a * 2^1022) / ((a+e) * 2^1021)
876429Svs195195  *
886429Svs195195  * which is guaranteed to fill the resulting mantissa with all ones.
896429Svs195195  *
906429Svs195195  */
916429Svs195195 int
fpu_fdivd(int rloop,struct fps_test_ereport * report)926429Svs195195 fpu_fdivd(int rloop, struct fps_test_ereport *report)
936429Svs195195 {
946429Svs195195 
956429Svs195195 	char err_data[MAX_INFO_SIZE];
966429Svs195195 	double expect_ans = EXPECTED;
976429Svs195195 	double f12 = 0;
986429Svs195195 	double f2;
996429Svs195195 	double f22;
1006429Svs195195 	int loop = 0;
1016429Svs195195 	uint64_t expect;
1026429Svs195195 	uint64_t observe;
1036429Svs195195 
1046429Svs195195 	srand48(1L);
1056429Svs195195 
1066429Svs195195 	while (loop < rloop) {
1076429Svs195195 		loop++;
1086429Svs195195 
1096429Svs195195 		*(uint32_t *)& f22 = mrand48();
1106429Svs195195 		*(uint32_t *)& f22 &= 0x80069fff;
1116429Svs195195 		*(uint32_t *)& f22 |= 0x7fd69f00;
1126429Svs195195 
1136429Svs195195 #ifdef __lint
1146429Svs195195 		(void) f22;
1156429Svs195195 #endif
1166429Svs195195 
1176429Svs195195 		*((uint32_t *)& f22 + 1) = mrand48();
1186429Svs195195 		*((uint32_t *)& f22 + 1) |= 0x00000001;
1196429Svs195195 
1206429Svs195195 		*(uint64_t *)& f2 = *(uint64_t *)& f22 + 1;
1216429Svs195195 		*(uint32_t *)& f2 &= 0x800FFFFF;
1226429Svs195195 		*(uint32_t *)& f2 |= 0x7FC00000;
1236429Svs195195 #ifdef __lint
1246429Svs195195 		(void) f2;
1256429Svs195195 #endif
1266429Svs195195 
1276429Svs195195 		fdivd(&f22, &f2, &f12);
1286429Svs195195 
1296429Svs195195 		if (f12 != expect_ans) {
130*7186Skk158166 			(void) snprintf(err_data, sizeof (err_data),
1316429Svs195195 			    "\nExpected: %.16e,\nObserved: %.16e",
1326429Svs195195 			    expect_ans, f12);
1336429Svs195195 			expect = *(uint64_t *)&expect_ans;
1346429Svs195195 			observe = *(uint64_t *)&f12;
1356429Svs195195 			setup_fps_test_struct(IS_EREPORT_INFO, report,
1366429Svs195195 			    6340, &observe, &expect, 1, 1, err_data);
1376429Svs195195 
1386429Svs195195 			return (-1);
1396429Svs195195 		}
1406429Svs195195 	}
1416429Svs195195 
1426429Svs195195 	return (0);
1436429Svs195195 }
1446429Svs195195 
1456429Svs195195 /*
1466429Svs195195  * fdivd(uint64_t *rs1, uint64_t *rs2, uint64_t *rd)
1476429Svs195195  * performs the assembly level instructions for
1486429Svs195195  * fpu_fdivd.
1496429Svs195195  */
1506429Svs195195 /* ARGSUSED */
1516429Svs195195 static void
fdivd(double * f22,double * f2,double * f12)1526429Svs195195 fdivd(double *f22, double *f2, double *f12)
1536429Svs195195 {
1546429Svs195195 	asm("ldd	[%i0], %f22");
1556429Svs195195 	asm("ldd	[%i1], %f2");
1566429Svs195195 	asm("fdivd   	%f22, %f2, %f12");
1576429Svs195195 	asm("std	%f12,[%i2]");
1586429Svs195195 	asm("membar #Sync");
1596429Svs195195 }
1606429Svs195195 
1616429Svs195195 /*
1626429Svs195195  * fpu_fmuld(int rloop, int unit, struct fps_test_ereport *report)
1636429Svs195195  * returns whether the correct value is calculated each time
1646429Svs195195  * rloop times. If an error is found, the relevant data is stored
1656429Svs195195  * in report. The goal is to check if (x * y) == (y * x). The
1666429Svs195195  * data pattern is important, and the back-to-back fmuld's are
1676429Svs195195  * important.
1686429Svs195195  */
1696429Svs195195 int
fpu_fmuld(int rloop,struct fps_test_ereport * report)1706429Svs195195 fpu_fmuld(int rloop, struct fps_test_ereport *report)
1716429Svs195195 {
1726429Svs195195 	char err_data[MAX_INFO_SIZE];
1736429Svs195195 	double x;
1746429Svs195195 	double y;
1756429Svs195195 	double z;
1766429Svs195195 	double z1;
1776429Svs195195 	int loop;
1786429Svs195195 	uint64_t expect;
1796429Svs195195 	uint64_t observe;
1806429Svs195195 	uint64_t *px;
1816429Svs195195 	uint64_t *py;
1826429Svs195195 
1836429Svs195195 	loop = 0;
1846429Svs195195 	px = (uint64_t *)& x;
1856429Svs195195 	py = (uint64_t *)& y;
1866429Svs195195 	*px = 0x2FEBD8507111CDE5UL;	/* 4865027 */
1876429Svs195195 	*py = 0x2FE284A9A98EAA26UL;
1886429Svs195195 
1896429Svs195195 #ifdef __lint
1906429Svs195195 	(void) x;
1916429Svs195195 	(void) y;
1926429Svs195195 #endif
1936429Svs195195 
1946429Svs195195 	while (loop < rloop) {
1956429Svs195195 		loop++;
1966429Svs195195 		z = z1 = 0.0;
1976429Svs195195 
1986429Svs195195 		/*
1996429Svs195195 		 * Data pattern and back-to-back fmuld() are
2006429Svs195195 		 * important
2016429Svs195195 		 */
2026429Svs195195 		fmuld(&x, &y, &z, &z1);
2036429Svs195195 
2046429Svs195195 		if (*(uint64_t *)&z != *(uint64_t *)&z1) {
205*7186Skk158166 			(void) snprintf(err_data, sizeof (err_data),
2066429Svs195195 			    "\nExpected: %.16e,\nObserved: %.16e",
2076429Svs195195 			    *(uint64_t *)&z, *(uint64_t *)&z1);
2086429Svs195195 			expect = *(uint64_t *)&z;
2096429Svs195195 			observe = *(uint64_t *)&z1;
2106429Svs195195 			setup_fps_test_struct(IS_EREPORT_INFO, report,
2116429Svs195195 			    6341, &observe, &expect, 1, 1, err_data);
2126429Svs195195 
2136429Svs195195 			return (-1);
2146429Svs195195 		}
2156429Svs195195 	}
2166429Svs195195 
2176429Svs195195 	return (0);
2186429Svs195195 }
2196429Svs195195 
2206429Svs195195 /*
2216429Svs195195  * fmuld(double *x,double *y, double *z, double *z1)
2226429Svs195195  * performs the assembly level instructions for
2236429Svs195195  * fpu_fmuld.
2246429Svs195195  */
2256429Svs195195 /* ARGSUSED */
2266429Svs195195 static void
fmuld(double * x,double * y,double * z,double * z1)2276429Svs195195 fmuld(double *x, double *y, double *z, double *z1)
2286429Svs195195 {
2296429Svs195195 	asm("ldd[%i0], %f0");
2306429Svs195195 	asm("ldd[%i1], %f4");
2316429Svs195195 	asm("fmuld%f0, %f4, %f2");
2326429Svs195195 	asm("fmuld%f4, %f0, %f6");
2336429Svs195195 	asm("std%f2, [%i2]");
2346429Svs195195 	asm("std%f6, [%i3]");
2356429Svs195195 	asm("membar #Sync");
2366429Svs195195 }
2376429Svs195195 
2386429Svs195195 
2396429Svs195195 /*
2406429Svs195195  * fpu_fmulx(int rloop, int unit, struct fps_test_ereport *report)
2416429Svs195195  * returns whether the correct value is calculated each time
2426429Svs195195  * rloop times. If an error is found, the relevant data is stored
2436429Svs195195  * in report. The goal is to check if (x * y) == (y * x) with
2446429Svs195195  * 64-bit intgers.
2456429Svs195195  */
2466429Svs195195 int
fpu_fmulx(int rloop,struct fps_test_ereport * report)2476429Svs195195 fpu_fmulx(int rloop, struct fps_test_ereport *report)
2486429Svs195195 {
2496429Svs195195 	char err_data[MAX_INFO_SIZE];
2506429Svs195195 	int loop;
2516429Svs195195 	int loop_lim;
2526429Svs195195 	uint32_t *rs1;
2536429Svs195195 	uint32_t *rs2;
2546429Svs195195 	uint64_t expect;
2556429Svs195195 	uint64_t observe;
2566429Svs195195 	uint64_t v1;
2576429Svs195195 	uint64_t v2;
2586429Svs195195 	uint64_t vd1;
2596429Svs195195 	uint64_t vd2;
2606429Svs195195 	uint64_t *rd1;
2616429Svs195195 	uint64_t *rd2;
2626429Svs195195 
2636429Svs195195 	v1 = v2 = vd1 = vd2 = 0;
2646429Svs195195 	loop = 0;
2656429Svs195195 	loop_lim = rloop;
2666429Svs195195 
2676429Svs195195 	if (loop_lim < 10)
2686429Svs195195 		loop_lim = 10;
2696429Svs195195 
2706429Svs195195 	if (loop_lim > 100000)
2716429Svs195195 		loop_lim = 100000;
2726429Svs195195 
2736429Svs195195 	rs1 = (uint32_t *)& v1;
2746429Svs195195 	rs2 = (uint32_t *)& v2;
2756429Svs195195 	rd1 = &vd1;
2766429Svs195195 	rd2 = &vd2;
2776429Svs195195 
2786429Svs195195 #ifdef __lint
2796429Svs195195 	(void) v1;
2806429Svs195195 	(void) v2;
2816429Svs195195 #endif
2826429Svs195195 
2836429Svs195195 	srand(0l);
2846429Svs195195 	while (loop < loop_lim) {
2856429Svs195195 		loop++;
2866429Svs195195 
2876429Svs195195 #ifndef __lint
2886429Svs195195 
2896429Svs195195 		*rs1 = mrand48();
2906429Svs195195 		*(rs1 + 1) = mrand48();
2916429Svs195195 		*rs2 = mrand48();
2926429Svs195195 		*(rs2 + 1) = mrand48();
2936429Svs195195 #endif
2946429Svs195195 
2956429Svs195195 		/* LINTED */
2966429Svs195195 		fmulx((uint64_t *)rs1, (uint64_t *)rs2, rd1);
2976429Svs195195 
2986429Svs195195 		/* LINTED */
2996429Svs195195 		fmulx((uint64_t *)rs2, (uint64_t *)rs1, rd2);
3006429Svs195195 
3016429Svs195195 		if (*rd1 != *rd2) {
3026429Svs195195 			expect = (uint64_t)*rd1;
3036429Svs195195 			observe = (uint64_t)*rd2;
304*7186Skk158166 			(void) snprintf(err_data, sizeof (err_data),
3056429Svs195195 			    "\nExpected: %lld\nObserved: %lld", *rd1, *rd2);
3066429Svs195195 			setup_fps_test_struct(IS_EREPORT_INFO, report,
3076429Svs195195 			    6356, &observe, &expect, 1, 1, err_data);
3086429Svs195195 
3096429Svs195195 		return (-1);
3106429Svs195195 		}
3116429Svs195195 	}
3126429Svs195195 
3136429Svs195195 	return (0);
3146429Svs195195 }
3156429Svs195195 
3166429Svs195195 /*
3176429Svs195195  * fmulx(uint64_t *rs1, uint64_t *rs2, uint64_t *rd)
3186429Svs195195  * performs the assembly level instructions for
3196429Svs195195  * fpu_fmulx.
3206429Svs195195  */
3216429Svs195195 /* ARGSUSED */
3226429Svs195195 static void
fmulx(uint64_t * rs1,uint64_t * rs2,uint64_t * rd)3236429Svs195195 fmulx(uint64_t *rs1, uint64_t *rs2, uint64_t *rd)
3246429Svs195195 {
3256429Svs195195 	asm("ldx   [%i0], %l0");
3266429Svs195195 	asm("ldx   [%i1], %l1");
3276429Svs195195 	asm("mulx  %l0, %l1, %l2");
3286429Svs195195 	asm("stx   %l2, [%i2]");
3296429Svs195195 	asm("membar	#Sync");
3306429Svs195195 
3316429Svs195195 }
3326429Svs195195 
3336429Svs195195 
3346429Svs195195 
3356429Svs195195 #ifdef V9B
3366429Svs195195 
3376429Svs195195 #pragma align 64  (f0)
3386429Svs195195 #pragma align 8  (f2)
3396429Svs195195 
3406429Svs195195 #define	MEMSIZE	2048*3
3416429Svs195195 
3426429Svs195195 static uchar_t f0[64];
3436429Svs195195 static uchar_t f2[8];
3446429Svs195195 
3456429Svs195195 static uint32_t bmask[] = {0x01234567, 0x12345678,
3466429Svs195195 			0x23456789, 0x3456789a,
3476429Svs195195 			0x456789ab, 0x56789abc,
3486429Svs195195 			0x6789abcd, 0x789abcde,
3496429Svs195195 			0x89abcdef, 0x9abcdef0,
3506429Svs195195 			0xabcdef01, 0xbcdef012,
3516429Svs195195 			0xcdef0123, 0xdef01234,
3526429Svs195195 			0xef012345, 0xf0123456,
3536429Svs195195 			0x55555555, 0xaaaaaaaa,
3546429Svs195195 			0x00000000, 0xffffffff};
3556429Svs195195 
356*7186Skk158166 #ifdef __lint
357*7186Skk158166 
358*7186Skk158166 /*ARGSUSED*/
359*7186Skk158166 unsigned long
setgsr(unsigned long arg1)360*7186Skk158166 setgsr(unsigned long arg1)
361*7186Skk158166 {
362*7186Skk158166 	return (0);
363*7186Skk158166 }
364*7186Skk158166 
365*7186Skk158166 /*ARGSUSED*/
366*7186Skk158166 float
fpackfix(double arg1)367*7186Skk158166 fpackfix(double arg1)
368*7186Skk158166 {
369*7186Skk158166 	return (0.0);
370*7186Skk158166 }
371*7186Skk158166 
372*7186Skk158166 /*ARGSUSED*/
373*7186Skk158166 unsigned long
fcmpne16(double arg1,double arg2)374*7186Skk158166 fcmpne16(double arg1, double arg2)
375*7186Skk158166 {
376*7186Skk158166 	return (0);
377*7186Skk158166 }
378*7186Skk158166 
379*7186Skk158166 /*ARGSUSED*/
380*7186Skk158166 unsigned long
fcmpgt16(double arg1,double arg2)381*7186Skk158166 fcmpgt16(double arg1, double arg2)
382*7186Skk158166 {
383*7186Skk158166 	return (0);
384*7186Skk158166 }
385*7186Skk158166 
386*7186Skk158166 #endif /* LINT */
387*7186Skk158166 
3886429Svs195195 /*
389*7186Skk158166  * align_data(int loop, struct fps_test_ereport *report)
3906429Svs195195  * returns whether a miscompare was found after running alignment tests
3916429Svs195195  * loop amount of times. If an error is found, relevant data is stored
3926429Svs195195  * in report. This test exercises the alignaddr and aligndata
3936429Svs195195  * instructions with different byte alignments to ensure proper
3946429Svs195195  * operation. These two instructions are used extensively by the kernel
3956429Svs195195  * to move data size greater than 512 bytes. User level memcpy and
3966429Svs195195  * memmove library also use these instructions for data size
3976429Svs195195  * greater than 256 bytes.
3986429Svs195195  */
3996429Svs195195 int
align_data(int loop,struct fps_test_ereport * report)400*7186Skk158166 align_data(int loop, struct fps_test_ereport *report)
4016429Svs195195 {
4026429Svs195195 	char err[MAX_INFO_SIZE];
4036429Svs195195 	int test_ret;
4046429Svs195195 	int nr_malloc;
4056429Svs195195 	size_t memsize;
4066429Svs195195 	struct timeval timeout;
4076429Svs195195 	uchar_t c;
4086429Svs195195 	uchar_t *pf0;
4096429Svs195195 	uchar_t *pf2;
4106429Svs195195 	uchar_t *src;
4116429Svs195195 	uint32_t cnt;
4126429Svs195195 	uint32_t i;
4136429Svs195195 	uint32_t offset;
4146429Svs195195 	uint32_t start;
4156429Svs195195 	uint64_t expect[2];
4166429Svs195195 	uint64_t observe[2];
4176429Svs195195 
4186429Svs195195 	timeout.tv_sec = 0;
4196429Svs195195 	timeout.tv_usec = 10000;
4206429Svs195195 	nr_malloc = 0;
4216429Svs195195 	err[0] = '\0';
4226429Svs195195 
4236429Svs195195 	/* Make sure memsize is 64 bytes aligned  with minimum of 64 bytes */
4246429Svs195195 	memsize = MEMSIZE;
4256429Svs195195 	memsize = memsize / 64 * 64;
4266429Svs195195 
4276429Svs195195 	if (memsize < 64)
4286429Svs195195 		memsize = 64;
4296429Svs195195 
4306429Svs195195 	src = (uchar_t *)memalign(64, memsize + 64);
4316429Svs195195 
4326429Svs195195 	while (src == NULL && nr_malloc < 10) {
433*7186Skk158166 		(void) select(1, NULL, NULL, NULL, &timeout);
4346429Svs195195 		nr_malloc++;
4356429Svs195195 		src = (uchar_t *)memalign(64, memsize + 64);
4366429Svs195195 	}
4376429Svs195195 
4386429Svs195195 	if (src == NULL)
4396429Svs195195 		_exit(FPU_SYSCALL_FAIL);
4406429Svs195195 
4416429Svs195195 	/* Initialize source array with sequential data */
4426429Svs195195 	c = 0;
4436429Svs195195 
4446429Svs195195 	for (i = 0; i < memsize + 64; i++)
4456429Svs195195 		*(src + i) = c++;
4466429Svs195195 
4476429Svs195195 	for (cnt = 0; cnt < loop; cnt++) {
4486429Svs195195 		for (start = 1; start < 64; start += 1) {
4496429Svs195195 			offset = 0;
4506429Svs195195 
4516429Svs195195 			test_ret = do_aligndata(src + start, &offset,
4526429Svs195195 			    memsize, f0, f2, bmask[cnt % 20]);
4536429Svs195195 
4546429Svs195195 			/*
4556429Svs195195 			 * Miscompare on the two aligndata
4566429Svs195195 			 * instructions. Calculate offset to source
4576429Svs195195 			 * array and get miscompare data
4586429Svs195195 			 */
4596429Svs195195 
4606429Svs195195 			if (test_ret != 0) {
4616429Svs195195 				pf0 = f0 + offset % 64;
4626429Svs195195 				pf2 = f2;
4636429Svs195195 
4646429Svs195195 				for (i = 0; i < 8; i++) {
4656429Svs195195 					if (*(pf0 + i) != *(pf2 + i))
4666429Svs195195 						break;
4676429Svs195195 				}
4686429Svs195195 
469*7186Skk158166 				(void) align_error_create(err, start,
4706429Svs195195 				    offset + start + i, loop, cnt);
4716429Svs195195 				expect[0] =
4726429Svs195195 				    (uint64_t)(*(uint8_t *)
4736429Svs195195 				    (src + offset + start + i));
4746429Svs195195 				expect[1] = (uint64_t)0;
4756429Svs195195 				observe[0] = (uint64_t)(*(uint8_t *)(pf0 + i));
4766429Svs195195 				observe[1] = (uint64_t)(*(uint8_t *)(pf2 + i));
4776429Svs195195 				setup_fps_test_struct(
4786429Svs195195 				    IS_EREPORT_INFO,
4796429Svs195195 				    report, 6344, observe,
4806429Svs195195 				    expect, 1, 2, err);
4816429Svs195195 
4826429Svs195195 				free(src);
4836429Svs195195 
4846429Svs195195 				return (-1);
4856429Svs195195 			}
4866429Svs195195 
4876429Svs195195 			/*
4886429Svs195195 			 * No miscompare on the aligndata
4896429Svs195195 			 * instructions. Check to see whether the
4906429Svs195195 			 * last 64 bytes matches the input
4916429Svs195195 			 */
4926429Svs195195 			if (test_ret == 0) {
4936429Svs195195 				pf2 = src + offset + start;
4946429Svs195195 
4956429Svs195195 				for (i = 0; i < 64; i++) {
4966429Svs195195 					if (f0[i] != *(pf2 + i)) {
4976429Svs195195 
498*7186Skk158166 						(void) align_error_create(err,
4996429Svs195195 						    start,
5006429Svs195195 						    offset + start + i,
5016429Svs195195 						    loop, cnt);
5026429Svs195195 						expect[0] =
5036429Svs195195 						    (uint64_t)(*(uint8_t *)
5046429Svs195195 						    (pf2 + i));
5056429Svs195195 						expect[1] = (uint64_t)0;
5066429Svs195195 						observe[0] = (uint64_t)f0[i];
5076429Svs195195 						observe[1] = (uint64_t)0;
5086429Svs195195 						setup_fps_test_struct(
5096429Svs195195 						    IS_EREPORT_INFO,
5106429Svs195195 						    report, 6343, observe,
5116429Svs195195 						    expect, 1, 1, err);
5126429Svs195195 
5136429Svs195195 						free(src);
5146429Svs195195 						return (-1);
5156429Svs195195 					}
5166429Svs195195 				}
5176429Svs195195 			}
5186429Svs195195 		}
5196429Svs195195 	}
5206429Svs195195 
5216429Svs195195 	free(src);
5226429Svs195195 
5236429Svs195195 	return (0);
5246429Svs195195 }
5256429Svs195195 
5266429Svs195195 /*
5276429Svs195195  * align_error_create(char *err, int start, int offset, int loop, int count)
5286429Svs195195  * returns if a successful snprintf was performed when creating an align_data
5296429Svs195195  * error message for align_data.
5306429Svs195195  */
5316429Svs195195 static int
align_error_create(char * err,uint32_t start,uint32_t offset,int loop,uint32_t count)532*7186Skk158166 align_error_create(char *err, uint32_t start,
533*7186Skk158166 	uint32_t offset, int loop, uint32_t count)
5346429Svs195195 {
5356429Svs195195 	if (err == NULL)
5366429Svs195195 		return (-1);
5376429Svs195195 
5386429Svs195195 	return snprintf(err, sizeof (err),
5396429Svs195195 	    "Start = %2.2d offset = %2.2d loop = %d cnt = %d",
5406429Svs195195 	    start, offset, loop, count);
5416429Svs195195 }
5426429Svs195195 
5436429Svs195195 /*
5446429Svs195195  * do_aligndata(uchar_t *from, uint32_t *offset, size_t sz,
5456429Svs195195  * uchar_t *f0, uchar_t *f2, uint32_t bmask) performs
5466429Svs195195  * the assembly lvl routines for align_data.
5476429Svs195195  */
548*7186Skk158166 /*ARGSUSED*/
5496429Svs195195 static int
do_aligndata(uchar_t * from,uint32_t * offset,size_t sz,uchar_t * f0,uchar_t * f2,uint32_t bmask)5506429Svs195195 do_aligndata(uchar_t *from, uint32_t *offset, size_t sz,
5516429Svs195195 	uchar_t *f0, uchar_t *f2, uint32_t bmask)
5526429Svs195195 {
553*7186Skk158166 	int ret = 1;
554*7186Skk158166 
5556429Svs195195 	asm("bmask	%i5,%g0,%g0");
5566429Svs195195 	/* produce GSR.offset and align %l0 to 8 bytes boundary */
5576429Svs195195 	asm("alignaddr	%i0, %g0, %l0");
5586429Svs195195 	/* %i0 then used as error register, assume error */
5596429Svs195195 	asm("mov	1,%i0");
5606429Svs195195 	/* %l1 used as offset counter */
5616429Svs195195 	asm("mov	-8,%l1");
5626429Svs195195 	asm("ldd	[%l0], %f0");
5636429Svs195195 
5646429Svs195195 	asm("next_read:");
5656429Svs195195 
5666429Svs195195 	asm("ldd	[%l0+8], %f2");
5676429Svs195195 	asm("ldd	[%l0+0x10], %f4");
5686429Svs195195 	asm("faligndata	%f0, %f2, %f32");
5696429Svs195195 	asm("faligndata	%f0, %f2, %f48");
5706429Svs195195 	asm("fcmpd	%fcc0,%f32,%f48");
5716429Svs195195 	asm("fblg,pn	%fcc0,error");
5726429Svs195195 	/* %l1 contains offset value */
5736429Svs195195 	asm("add	%l1,8,%l1");
5746429Svs195195 	/* 0 - 7 */
5756429Svs195195 
5766429Svs195195 	asm("ldd	[%l0+0x18], %f6");
5776429Svs195195 	asm("faligndata	%f2, %f4, %f34");
5786429Svs195195 	asm("faligndata	%f2, %f4, %f48");
5796429Svs195195 	asm("fcmpd	%fcc0,%f34,%f48");
5806429Svs195195 	asm("fblg,pn	%fcc0,error");
5816429Svs195195 	/* %l1 contains offset value */
5826429Svs195195 	asm("add	%l1,8,%l1");
5836429Svs195195 	/* 9 - 15 */
5846429Svs195195 
5856429Svs195195 	asm("ldd	[%l0+0x20], %f8");
5866429Svs195195 	asm("faligndata	%f4, %f6, %f36");
5876429Svs195195 	asm("faligndata	%f4, %f6, %f48");
5886429Svs195195 	asm("fcmpd	%fcc0,%f36,%f48");
5896429Svs195195 	asm("fblg,pn	%fcc0,error");
5906429Svs195195 	/* %l1 contains offset value */
5916429Svs195195 	asm("add	%l1,8,%l1");
5926429Svs195195 	/* 16 - 23 */
5936429Svs195195 
5946429Svs195195 	asm("ldd	[%l0+0x28], %f10");
5956429Svs195195 	asm("faligndata	%f6, %f8, %f38");
5966429Svs195195 	asm("faligndata	%f6, %f8, %f48");
5976429Svs195195 	asm("fcmpd	%fcc0,%f38,%f48");
5986429Svs195195 	asm("fblg,pn	%fcc0,error");
5996429Svs195195 	/* contains offset value */
6006429Svs195195 	asm("add	%l1,8,%l1");
6016429Svs195195 	/* 24 - 31 */
6026429Svs195195 
6036429Svs195195 	asm("ldd	[%l0+0x28], %f10");
6046429Svs195195 	asm("faligndata	%f8, %f10, %f40");
6056429Svs195195 	asm("faligndata	%f8, %f10, %f48");
6066429Svs195195 	asm("fcmpd	%fcc0,%f40,%f48");
6076429Svs195195 	asm("fblg,pn	%fcc0,error");
6086429Svs195195 	/* %l1 contains offset value */
6096429Svs195195 	asm("add	%l1,8,%l1");
6106429Svs195195 	/* 32 - 39 */
6116429Svs195195 
6126429Svs195195 	asm("ldd	[%l0+0x30], %f12");
6136429Svs195195 	asm("faligndata	%f10, %f12, %f42");
6146429Svs195195 	asm("faligndata	%f10, %f12, %f48");
6156429Svs195195 	asm("fcmpd	%fcc0,%f42,%f48");
6166429Svs195195 	asm("fblg,pn	%fcc0,error");
6176429Svs195195 	/* %l1 contains offset value */
6186429Svs195195 	asm("add	%l1,8,%l1");
6196429Svs195195 	/* 40 - 47 */
6206429Svs195195 
6216429Svs195195 	asm("ldd	[%l0+0x38], %f14");
6226429Svs195195 	asm("faligndata	%f12, %f14, %f44");
6236429Svs195195 	asm("faligndata	%f12, %f14, %f48");
6246429Svs195195 	asm("fcmpd	%fcc0,%f44,%f48");
6256429Svs195195 	asm("fblg,pn	%fcc0,error");
6266429Svs195195 	/* %l1 contains offset value */
6276429Svs195195 	asm("add	%l1,8,%l1");
6286429Svs195195 	/* 48 - 55 */
6296429Svs195195 
6306429Svs195195 	asm("ldd	[%l0+0x40], %f0");
6316429Svs195195 	asm("faligndata	%f14, %f0, %f46");
6326429Svs195195 	asm("faligndata	%f14, %f0, %f48");
6336429Svs195195 	asm("fcmpd	%fcc0,%f46,%f48");
6346429Svs195195 	asm("fblg,pn	%fcc0,error");
6356429Svs195195 	/* %l1 contains offset value */
6366429Svs195195 	asm("add	%l1,8,%l1");
6376429Svs195195 	/* 56 - 63 */
6386429Svs195195 
6396429Svs195195 	asm("subcc	%i2,64,%i2");
6406429Svs195195 	asm("bg		next_read");
6416429Svs195195 	asm("add	%l0,64,%l0");
6426429Svs195195 
6436429Svs195195 	/* no miscompare error */
6446429Svs195195 	asm("mov	0,%i0");
645*7186Skk158166 	ret = 0;
6466429Svs195195 	/* no error, move back to last 64 bytes boundary */
6476429Svs195195 	asm("sub	%l1,56,%l1");
6486429Svs195195 
6496429Svs195195 	asm("error:");
6506429Svs195195 	asm("stda	%f32,[%i3]0xf0");
6516429Svs195195 	asm("std	%f48,[%i4]");
6526429Svs195195 	/* store offset value */
6536429Svs195195 	asm("st 	%l1,[%i1]");
6546429Svs195195 	asm("membar	#Sync");
6556429Svs195195 
656*7186Skk158166 	return (ret);
6576429Svs195195 }
6586429Svs195195 
6596429Svs195195 /*
660*7186Skk158166  * vis_test(struct fps_test_ereport *report)
6616429Svs195195  * checks if various RISC operations are performed
6626429Svs195195  * succesfully. If an error is found, relevant data
6636429Svs195195  * is stored in report.
6646429Svs195195  */
6656429Svs195195 int
vis_test(struct fps_test_ereport * report)666*7186Skk158166 vis_test(struct fps_test_ereport *report)
6676429Svs195195 {
6686429Svs195195 	int v1;
6696429Svs195195 	int v2;
6706429Svs195195 	int v3;
6716429Svs195195 
672*7186Skk158166 	v1 = visgt16(report);
673*7186Skk158166 	v2 = visne16(report);
674*7186Skk158166 	v3 = vispackfix(report);
6756429Svs195195 
6766429Svs195195 	if ((0 != v1) || (0 != v2) || (0 != v3))
6776429Svs195195 		return (-1);
6786429Svs195195 
6796429Svs195195 	return (0);
6806429Svs195195 }
6816429Svs195195 
6826429Svs195195 /*
683*7186Skk158166  * visgt16(struct fps_test_ereport *report)
6846429Svs195195  * does a greater-than compare instruction and returns if
6856429Svs195195  * successful or not. If an error, relevant data is
6866429Svs195195  * stored in report.
6876429Svs195195  */
6886429Svs195195 static int
visgt16(struct fps_test_ereport * report)689*7186Skk158166 visgt16(struct fps_test_ereport *report)
6906429Svs195195 {
6916429Svs195195 	uint64_t expected;
6926429Svs195195 	uint64_t observed;
6936429Svs195195 	unsigned long a = 0x0000000000000001;
6946429Svs195195 	unsigned long b = 0x8000000008000008;
6956429Svs195195 	unsigned long c = fcmpgt16(*((double *)&a), *((double *)&b));
6966429Svs195195 
6976429Svs195195 	if (c == 0x8)
6986429Svs195195 		return (0);
6996429Svs195195 	else {
7006429Svs195195 		expected = (uint64_t)0x8;
7016429Svs195195 		observed = (*(uint64_t *)&c);
7026429Svs195195 		setup_fps_test_struct(NO_EREPORT_INFO, report,
7036429Svs195195 		    6364, &observed, &expected, 1, 1);
7046429Svs195195 
7056429Svs195195 		return (-1);
7066429Svs195195 	}
7076429Svs195195 }
7086429Svs195195 
7096429Svs195195 /*
710*7186Skk158166  * visne16(struct fps_test_ereport *report)
7116429Svs195195  * does a not-equal compare instruction and returns if
7126429Svs195195  * successful or not. If an error, relevant data is
7136429Svs195195  * stored in report.
7146429Svs195195  */
7156429Svs195195 static int
visne16(struct fps_test_ereport * report)716*7186Skk158166 visne16(struct fps_test_ereport *report)
7176429Svs195195 {
7186429Svs195195 	uint64_t expected;
7196429Svs195195 	uint64_t observed;
7206429Svs195195 	unsigned long a = 0x0000000000000001;
7216429Svs195195 	unsigned long b = 0x0001000000001001;
7226429Svs195195 	unsigned long c = fcmpne16(*((double *)&a), *((double *)&b));
7236429Svs195195 
7246429Svs195195 	if (c == 0x9)
7256429Svs195195 		return (0);
7266429Svs195195 	else {
7276429Svs195195 		expected = (uint64_t)0x9;
7286429Svs195195 		observed = (*(uint64_t *)&c);
7296429Svs195195 		setup_fps_test_struct(NO_EREPORT_INFO, report,
7306429Svs195195 		    6365, &observed, &expected, 1, 1);
7316429Svs195195 
7326429Svs195195 		return (-1);
7336429Svs195195 	}
7346429Svs195195 }
7356429Svs195195 
7366429Svs195195 /*
737*7186Skk158166  * vispackfix(struct fps_test_ereport *report)
7386429Svs195195  * does four 16-bit pack conversions to a lower precsion
7396429Svs195195  * format and returns if successful or not. If an error,
7406429Svs195195  * relevant data is stored in report.
7416429Svs195195  */
7426429Svs195195 static int
vispackfix(struct fps_test_ereport * report)743*7186Skk158166 vispackfix(struct fps_test_ereport *report)
7446429Svs195195 {
7456429Svs195195 	float b;
7466429Svs195195 	uint64_t expected;
7476429Svs195195 	uint64_t observed;
7486429Svs195195 	unsigned int c;
7496429Svs195195 	unsigned long a = 0x8008000008008008;
7506429Svs195195 	unsigned long gsr = 0;
7516429Svs195195 
7526429Svs195195 	(void) setgsr(gsr);
7536429Svs195195 
7546429Svs195195 	b = fpackfix(*((double *)&a));
7556429Svs195195 	c = *((unsigned int *)&b);
7566429Svs195195 
7576429Svs195195 	if (c == 0x80080800)
7586429Svs195195 		return (0);
7596429Svs195195 	else {
7606429Svs195195 		expected = (uint64_t)0x80080800;
7616429Svs195195 		observed = (uint64_t)c;
7626429Svs195195 		setup_fps_test_struct(NO_EREPORT_INFO, report,
7636429Svs195195 		    6366, &observed, &expected, 1, 1);
7646429Svs195195 
7656429Svs195195 		return (-1);
7666429Svs195195 	}
7676429Svs195195 }
7686429Svs195195 
7696429Svs195195 #endif
770