regtest: broaden none/tests/linux/bug498317 suppression for PPC
[valgrind.git] / none / tests / arm64 / simd.c
blobc0a178fe8c8a4f4ea16bfdf37b44838444f255c7
1 #include <math.h> // isnormal
2 #include <stdio.h>
3 #include "simd.h"
5 /* Conversion based on IEEE half-precision, as described in the IEEE 754-2008
6 standard and Arm Reference Manual 'A1.4.2 Half-precision floating-point
7 formats' where hardware capability supports __fp16 (VEX_HWCAPS_ARM64_FP16
8 and VEX_HWCAPS_ARM64_VFP16 set).
9 */
10 UInt halfToSingleFPAsInt(UShort y)
12 int s = (y >> 15) & 0x00000001; // Sign bit
13 int e = (y >> 10) & 0x0000001f; // Exponent
14 int f = y & 0x000003ff; // Fraction
16 // Handle +/- INF (7c00 and fc00 -INF) and +/-0
17 if (e == 0) {
18 if (f == 0)
19 return s << 31;
20 else { // Normalize
21 while (!(f & 0x00000400)) {
22 f <<= 1;
23 e -= 1;
25 e += 1;
26 f &= ~0x00000400;
28 } else if (e == 31) {
29 if (f == 0) // INF
30 return (s << 31) | 0x7f800000;
31 else // NaN
32 return (s << 31) | 0x7f800000 | (f << 13);
35 e = e + (127 - 15);
36 f = f << 13;
38 return ((s << 31) | (e << 23) | f);
41 UChar randUChar ( void )
43 static UInt seed = 80021;
44 seed = 1103515245 * seed + 12345;
45 return (seed >> 17) & 0xFF;
48 /* Generates a random V128. Ensures that that it contains normalised FP numbers
49 when viewed as either F16x8, F32x4 or F64x2, so that it is reasonable to use
50 in FP test cases. */
51 void randV128 ( /*OUT*/V128* v, LaneTy ty )
53 static UInt nCalls = 0, nIters = 0;
54 Int i;
55 nCalls++;
56 while (1) {
57 nIters++;
58 for (i = 0; i < 16; i++) {
59 v->u8[i] = randUChar();
61 if (isnormal(v->f32[0]) && isnormal(v->f32[1]) && isnormal(v->f32[2])
62 && isnormal(v->f32[3]) && isnormal(v->f64[0]) && isnormal(v->f64[1])
63 && isnormal(shortToSingle(v->f16[0])) && isnormal(shortToSingle(v->f16[1]))
64 && isnormal(shortToSingle(v->f16[2])) && isnormal(shortToSingle(v->f16[3]))
65 && isnormal(shortToSingle(v->f16[4])) && isnormal(shortToSingle(v->f16[5]))
66 && isnormal(shortToSingle(v->f16[6])) && isnormal(shortToSingle(v->f16[7]))) {
67 break;
70 if (0 == (nCalls & 0xFF))
71 printf("randV128: %u calls, %u iters\n", nCalls, nIters);
74 static Double special_values[10];
75 static Bool special_values_initted = False;
77 static __attribute__((noinline))
78 Double negate ( Double d ) { return -d; }
79 static __attribute__((noinline))
80 Double divf64 ( Double x, Double y ) { return x/y; }
82 static __attribute__((noinline))
83 Double plusZero ( void ) { return 0.0; }
84 static __attribute__((noinline))
85 Double minusZero ( void ) { return negate(plusZero()); }
87 static __attribute__((noinline))
88 Double plusOne ( void ) { return 1.0; }
89 static __attribute__((noinline))
90 Double minusOne ( void ) { return negate(plusOne()); }
92 static __attribute__((noinline))
93 Double plusInf ( void ) { return 1.0 / 0.0; }
94 static __attribute__((noinline))
95 Double minusInf ( void ) { return negate(plusInf()); }
97 static __attribute__((noinline))
98 Double plusNaN ( void ) { return divf64(plusInf(),plusInf()); }
99 static __attribute__((noinline))
100 Double minusNaN ( void ) { return negate(plusNaN()); }
102 static __attribute__((noinline))
103 Double plusDenorm ( void ) { return 1.23e-315 / 1e3; }
104 static __attribute__((noinline))
105 Double minusDenorm ( void ) { return negate(plusDenorm()); }
108 static void ensure_special_values_initted ( void )
110 if (special_values_initted) return;
111 special_values[0] = plusZero();
112 special_values[1] = minusZero();
113 special_values[2] = plusOne();
114 special_values[3] = minusOne();
115 special_values[4] = plusInf();
116 special_values[5] = minusInf();
117 special_values[6] = plusNaN();
118 special_values[7] = minusNaN();
119 special_values[8] = plusDenorm();
120 special_values[9] = minusDenorm();
121 special_values_initted = True;
122 int i;
123 printf("\n");
124 for (i = 0; i < 10; i++) {
125 printf("special value %d = %e\n", i, special_values[i]);
127 printf("\n");
130 Double randDouble ( void )
132 ensure_special_values_initted();
133 UChar c = randUChar();
134 if (c >= 128) {
135 // return a normal number about half of the time.
136 // 0 .. 2^63-1
137 ULong u64 = randULong(TyDF);
138 // -2^62 .. 2^62-1
139 Long s64 = (Long)u64;
140 // -2^55 .. 2^55-1
141 s64 >>= (62-55);
142 // and now as a float
143 return (Double)s64;
145 c = randUChar() % 10;
146 return special_values[c];
149 Float randFloat ( void )
151 ensure_special_values_initted();
152 UChar c = randUChar();
153 if (c >= 128) {
154 // return a normal number about half of the time.
155 // 0 .. 2^63-1
156 ULong u64 = randULong(TyDF);
157 // -2^62 .. 2^62-1
158 Long s64 = (Long)u64;
159 // -2^25 .. 2^25-1
160 s64 >>= (62-25);
161 // and now as a float
162 return (Float)s64;
164 c = randUChar() % 10;
165 return special_values[c];
168 void randBlock_Doubles ( V128* block, Int nBlock )
170 Int i;
171 for (i = 0; i < nBlock; i++) {
172 block[i].f64[0] = randDouble();
173 block[i].f64[1] = randDouble();
177 void randBlock_Floats ( V128* block, Int nBlock )
179 Int i;
180 for (i = 0; i < nBlock; i++) {
181 block[i].f32[0] = randFloat();
182 block[i].f32[1] = randFloat();
183 block[i].f32[2] = randFloat();
184 block[i].f32[3] = randFloat();