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 #include <fp.h>
30 #include <externs.h>
31 #include <fps_ereport.h>
32
33 /* Traps enabled or disabled */
34 #define T_ENABLED 1
35 #define T_DISABLED 0
36
37 static int test_ieee754_exc_fields(int trapStatus,
38 struct fps_test_ereport *report);
39 static int test_fccn(struct fps_test_ereport *report);
40 static int test_rounding(struct fps_test_ereport *report);
41
42 /*
43 * Test data for testing the IEEE 754 exceptions.
44 * The first 5 entries are for the 5 FP exception fields of the FSR
45 */
46 static struct testws test_ws[] = {
47
48 /*
49 * a_msw, a_lsw, b_msw, b_lsw, instr, fsr_tem0..., fsr_tem1...,
50 * ecode
51 */
52
53 {one_sp, nocare, maxm_sp, nocare, op_add_sp,
54 FSR_TEM0_NX, FSR_TEM1_NX, E_NX}, /* inexact */
55 {one_sp, nocare, zero_sp, nocare, op_div_sp,
56 FSR_TEM0_DZ, FSR_TEM1_DZ, E_DZ}, /* div/zero */
57 {min1_sp, nocare, min1_sp, nocare, op_mul_sp,
58 FSR_TEM0_UF, FSR_TEM1_UF, E_UF}, /* unfl,inex */
59 {maxm_sp, nocare, maxm_sp, nocare, op_mul_sp,
60 FSR_TEM0_OF, FSR_TEM1_OF, E_OF}, /* overflow */
61 {zero_sp, nocare, zero_sp, nocare, op_div_sp,
62 FSR_TEM0_NV, FSR_TEM1_NV, E_NV}, /* not a valid */
63
64 {maxn_sp, nocare, maxn_sp, nocare, op_add_sp,
65 FSR_TEM0_OF_NX, FSR_CEXC_OF, E_OF}, /* 5-ovfl,inex */
66 {maxn_sp, nocare, maxn_sp, nocare, op_mul_sp,
67 FSR_TEM0_OF_NX, FSR_CEXC_OF, E_OF}, /* 5-ovfl,inex */
68 {maxn_msw, maxn_lsw, maxn_msw, maxn_lsw, op_mul_dp,
69 FSR_TEM0_OF_NX, FSR_CEXC_OF, E_OF},
70 {one_msw, one_lsw, zero_msw, zero_lsw, op_div_dp,
71 FSR_TEM1_DZ, FSR_TEM1_DZ, E_DZ},
72 {one_sp, nocare, nn_sp, nocare, op_add_sp,
73 FSR_TEM0_NV, FSR_TEM1_NV, E_NV},
74
75 {one_msw, one_lsw, nn_msw, nn_lsw, op_add_dp,
76 FSR_TEM0_NV, FSR_TEM1_NV, E_NV},
77 {one_sp, nocare, nn_sp, nocare, op_mul_sp,
78 FSR_TEM0_NV, FSR_TEM1_NV, E_NV},
79 {one_msw, one_lsw, nn_msw, nn_lsw, op_mul_dp,
80 FSR_TEM0_NV, FSR_TEM1_NV, E_NV},
81 {maxd_sp, nocare, two_sp, nocare, op_div_sp,
82 FSR_TEM0_UF_NX, FSR_CEXC_UF, E_UF}, /* 8-a-denorm */
83 {maxd_msw, maxd_lsw, two_msw, two_lsw, op_div_dp,
84 FSR_TEM0_UF_NX, FSR_CEXC_UF, E_UF},
85
86 {min1_sp, nocare, pi_4_sp, nocare, op_mul_sp,
87 FSR_TEM0_UF_NX, FSR_CEXC_UF, E_UF}, /* 7-unfl,inex */
88 {maxd_sp, nocare, half_sp, nocare, op_mul_sp,
89 FSR_TEM0_UF_NX, FSR_CEXC_UF, E_UF}, /* 8 -a-denorm */
90 {maxd_msw, maxd_lsw, half_msw, half_lsw, op_mul_dp,
91 FSR_TEM0_UF_NX, FSR_CEXC_UF, E_UF},
92 {half_sp, nocare, maxd_sp, nocare, op_mul_sp,
93 FSR_TEM0_UF_NX, FSR_CEXC_UF, E_UF}, /* 9 -b-denorm */
94 {half_msw, half_lsw, maxd_msw, maxd_lsw, op_mul_dp,
95 FSR_TEM0_UF_NX, FSR_CEXC_UF, E_UF},
96
97 {min1_msw, min1_lsw, pi_4_msw, pi_4_lsw, op_mul_dp,
98 FSR_TEM0_UF_NX, FSR_CEXC_UF, E_UF},
99 {nan_sp, nocare, zero_sp, nocare, op_add_sp,
100 FSR_TEM0_NV, FSR_TEM1_NV, E_NV}, /* 12-a-nan */
101 {nan_msw, nan_lsw, zero_msw, zero_lsw, op_add_dp,
102 FSR_TEM0_NV, FSR_TEM1_NV, E_NV},
103 {zero_sp, nocare, nan_sp, nocare, op_add_sp,
104 FSR_TEM0_NV, FSR_TEM1_NV, E_NV}, /* 13 -b-nan */
105 {zero_sp, nocare, nan_msw, nan_lsw, op_add_dp,
106 FSR_TEM0_NV, FSR_TEM1_NV, E_NV},
107
108 {nan_sp, nocare, nan_sp, nocare, op_add_sp,
109 FSR_TEM0_NV, FSR_TEM1_NV, E_NV}, /* 14 -ab-nan */
110 {nan_msw, nan_lsw, nan_msw, nan_lsw, op_add_dp,
111 FSR_TEM0_NV, FSR_TEM1_NV, E_NV},
112 {nan_sp, nocare, zero_sp, nocare, op_mul_sp,
113 FSR_TEM0_NV, FSR_TEM1_NV, E_NV}, /* 11-a-nan */
114 {nan_msw, nan_lsw, zero_msw, zero_lsw, op_mul_dp,
115 FSR_TEM0_NV, FSR_TEM1_NV, E_NV},
116 {zero_sp, nocare, nan_sp, nocare, op_mul_sp,
117 FSR_TEM0_NV, FSR_TEM1_NV, E_NV}, /* 13-b-nan */
118
119 {zero_sp, nocare, nan_msw, nan_lsw, op_mul_dp,
120 FSR_TEM0_NV, FSR_TEM1_NV, E_NV},
121 {nan_sp, nocare, nan_sp, nocare, op_mul_sp,
122 FSR_TEM0_NV, FSR_TEM1_NV, E_NV}, /* 14-ab-nan */
123 {nan_msw, nan_lsw, nan_msw, nan_lsw, op_mul_dp,
124 FSR_TEM0_NV, FSR_TEM1_NV, E_NV},
125
126 /* More IEEE 754 exceptions */
127
128 /* (+inf) + (-inf) */
129 {p_inf_sp, nocare, n_inf_sp, nocare, op_add_sp,
130 FSR_TEM0_NV, FSR_TEM1_NV, E_NV},
131 {p_inf_msw, p_inf_lsw, n_inf_msw, n_inf_lsw, op_add_dp,
132 FSR_TEM0_NV, FSR_TEM1_NV, E_NV},
133
134 /* (0) * (+inf) */
135 {zero_sp, nocare, p_inf_sp, nocare, op_mul_sp,
136 FSR_TEM0_NV, FSR_TEM1_NV, E_NV},
137 {zero_msw, zero_lsw, p_inf_msw, p_inf_lsw, op_mul_dp,
138 FSR_TEM0_NV, FSR_TEM1_NV, E_NV},
139
140 /* (0) * (-inf) */
141 {zero_sp, nocare, n_inf_sp, nocare, op_mul_sp,
142 FSR_TEM0_NV, FSR_TEM1_NV, E_NV},
143 {zero_msw, zero_lsw, n_inf_msw, n_inf_lsw, op_mul_dp,
144 FSR_TEM0_NV, FSR_TEM1_NV, E_NV},
145
146 /* (+inf) / (+inf) */
147 {p_inf_sp, nocare, p_inf_sp, nocare, op_div_sp,
148 FSR_TEM0_NV, FSR_TEM1_NV, E_NV},
149 {p_inf_msw, p_inf_lsw, p_inf_msw, p_inf_lsw, op_div_dp,
150 FSR_TEM0_NV, FSR_TEM1_NV, E_NV},
151
152 /* (+inf) / (-inf) */
153 {p_inf_sp, nocare, n_inf_sp, nocare, op_div_sp,
154 FSR_TEM0_NV, FSR_TEM1_NV, E_NV},
155 {p_inf_msw, p_inf_lsw, n_inf_msw, n_inf_lsw, op_div_dp,
156 FSR_TEM0_NV, FSR_TEM1_NV, E_NV},
157
158 /* sqrt(-1) */
159 {m_one_sp, nocare, nocare, nocare, op_fsqrts,
160 FSR_TEM0_NV, FSR_TEM1_NV, E_NV},
161 {m_one_msw, m_one_lsw, nocare, nocare, op_fsqrtd,
162 FSR_TEM0_NV, FSR_TEM1_NV, E_NV},
163
164
165 {00, 00, 000, 000, 0000, 0x0, 0x0, 0x0}};
166
167 /* Data used in test_fccn() */
168
169 /* No. of fccn fields in the FSR */
170 #define N_FCCN 4
171
172 #define FSR_FCC0_MASK ((uint64_t)FSR_FCC)
173 #define FSR_FCC1_MASK ((uint64_t)FSR_FCC1 << 32)
174 #define FSR_FCC2_MASK ((uint64_t)FSR_FCC2 << 32)
175 #define FSR_FCC3_MASK ((uint64_t)FSR_FCC3 << 32)
176
177 /*
178 * No. of bits to shift a fcc field to the right so that its value occupies
179 * the least significant bits
180 */
181 #define FSR_FCC0_SRL_N 10
182 #define FSR_FCC1_SRL_N 32
183 #define FSR_FCC2_SRL_N 34
184 #define FSR_FCC3_SRL_N 36
185
186 static uint64_t fccMasks[] =
187 {
188 FSR_FCC0_MASK,
189 FSR_FCC1_MASK,
190 FSR_FCC2_MASK,
191 FSR_FCC3_MASK
192 };
193
194 static unsigned int fccShifts[] =
195 {
196 FSR_FCC0_SRL_N,
197 FSR_FCC1_SRL_N,
198 FSR_FCC2_SRL_N,
199 FSR_FCC3_SRL_N
200 };
201
202
203 /*
204 * Data structure for the fccn test data. We are using only single-precision
205 * comparisions
206 */
207 typedef struct {
208 char *testId;
209 unsigned int val1; /* Operand 1 */
210 unsigned int val2; /* Operand 2 */
211
212 /* The value of the fcc field after the FP operation */
213 unsigned int fccVal;
214 }FccData;
215
216 static FccData fccData[] =
217 {
218 {"test-0", 0xc0980000, 0xc0980000, 0}, /* -ve = -ve */
219 {"test-1", 0x40980000, 0x40980000, 0}, /* +ve = +ve */
220
221 {"test-2", 0xc0980000, 0x40980000, 1}, /* -ve < +ve */
222 {"test-3", 0xc0980000, 0xc094cccd, 1}, /* -ve < -ve */
223 {"test-4", 0x40980000, 0x40983958, 1}, /* +ve < +ve */
224
225 {"test-5", 0x40980000, 0xc0980000, 2}, /* +ve > -ve */
226 {"test-6", 0x40983958, 0x40980000, 2}, /* +ve > +ve */
227 {"test-7", 0xc094cccd, 0xc0980000, 2}, /* -ve > -ve */
228
229 {"test-8", 0xc094cccd, nan_sp, 3}, /* +ve ? NaN */
230 {"test-9", nan_sp, 0xc094cccd, 3}, /* -ve ? NaN */
231 {"test-10", nan_sp, nan_sp, 3}, /* NaN ? NaN */
232
233 };
234
235 #define N_FCCDATA (sizeof (fccData) / sizeof (FccData))
236
237 /* Data used in test_rounding() */
238 #define FOUR_SP 0x40800000U
239 #define THREE_SP 0x40400000U
240 #define FOUR_DP_MSW 0x40100000U
241 #define FOUR_DP_LSW 0x00000000U
242 #define THREE_DP_MSW 0x40080000U
243 #define THREE_DP_LSW 0x00000000U
244 #define FSR_RD_MASK_Z 0xFFFFFFFF3FFFFFFFUL
245
246 /* No. of IEEE 754 rounding modes */
247 #define N_RD_MODES 4
248
249 /* Data structure for the rounding test data */
250 typedef struct {
251 char *test_id;
252 unsigned int operand1_msw;
253 unsigned int operand1_lsw;
254 unsigned int operand2_msw;
255 unsigned int operand2_lsw;
256 unsigned int operation;
257 uint64_t result_r2n; /* Round to Nearest */
258 uint64_t result_r2z; /* Round to Zero */
259 uint64_t result_r2pinf; /* Round to +infinity */
260 uint64_t result_r2ninf; /* Round to -infinity */
261
262 } RoundingData;
263
264
265 /* Strings for rounding modes */
266 static char *rndModes[] =
267 {
268 "Round to Nearest",
269 "Round to Zero",
270 "Round to +infinity",
271 "Round to -infinity",
272 };
273
274 /* Rounding test data */
275 static RoundingData r_data[] =
276 {
277 /* 4/3 SP */
278 {"Test-0",
279 FOUR_SP,
280 nocare,
281 THREE_SP,
282 nocare,
283 op_div_sp,
284 0x3faaaaab,
285 0x3faaaaaa,
286 0x3faaaaab,
287 0x3faaaaaa},
288
289 /* 4/3 DP */
290 {"Test-1",
291 FOUR_DP_MSW,
292 FOUR_DP_LSW,
293 THREE_DP_MSW,
294 THREE_DP_LSW,
295 op_div_dp,
296 0x3ff5555555555555,
297 0x3ff5555555555555,
298 0x3ff5555555555556,
299 0x3ff5555555555555},
300
301 {"Test-2",
302 0xc0600018,
303 nocare,
304 0xc1700009,
305 nocare,
306 op_add_sp,
307 0xc1940008,
308 0xc1940007,
309 0xc1940007,
310 0xc1940008},
311
312 {"Test-3",
313 0x880c0000,
314 0x00000018,
315 0x882e0000,
316 0x00000009,
317 op_add_dp,
318 0x8832800000000008,
319 0x8832800000000007,
320 0x8832800000000007,
321 0x8832800000000008},
322
323 /* 4/3 (DP) and convert to SP */
324 {"Test-4",
325 FOUR_DP_MSW,
326 FOUR_DP_LSW,
327 THREE_DP_MSW,
328 THREE_DP_LSW,
329 op_div_dp_c2sp,
330 0x3faaaaab,
331 0x3faaaaaa,
332 0x3faaaaab,
333 0x3faaaaaa},
334
335 /*
336 * Convert a 64-bit *signed* integer to a single- precison FP number.
337 * The 64-bit signed number used here, 0x0x882e000000000009, is
338 * -0x77d1fffffffffff7 i.e -8633963435622662135.
339 */
340 {"Test-5",
341 0x882e0000,
342 0x00000009,
343 nocare,
344 nocare,
345 op_fxtos,
346 0xdeefa400,
347 0xdeefa3ff,
348 0xdeefa3ff,
349 0xdeefa400}
350
351 };
352
353 #define R_DATA_N (sizeof (r_data)/sizeof (RoundingData))
354
355 /*
356 * fsr_test(struct fps_test_ereport *report) is the high level
357 * caller of the functions that test the different fields of
358 * the FSR. If an error is found, relevant data is stored in
359 * report.
360 */
361 int
fsr_test(struct fps_test_ereport * report)362 fsr_test(struct fps_test_ereport *report)
363 {
364 if (test_ieee754_exc_fields(T_DISABLED, report) != FPU_OK)
365 return (FPU_FOROFFLINE);
366
367 if (test_ieee754_exc_fields(T_ENABLED, report) != FPU_OK)
368 return (FPU_FOROFFLINE);
369
370 if (test_fccn(report) != FPU_OK)
371 return (FPU_FOROFFLINE);
372
373 if (test_rounding(report) != FPU_OK)
374 return (FPU_FOROFFLINE);
375
376 return (FPU_OK);
377 }
378
379 /*
380 * test_ieee754_exc_fields(int trapStatus,
381 * struct fps_test_ereport *report)tests the FSR.cexc,
382 * and FSR.aexc fields. It can operate in two modes: traps
383 * enabled and traps disabled.
384 *
385 * In the T_DISABLED (FSR.TEM=0) mode, it checks if the
386 * FSR.cexc and FSR.aexc fields have been set correctly.
387 *
388 * In the T_ENABLED mode, it check if the
389 * appropriate trap has been raised and the FSR.cexc field has the correct
390 * value.
391 *
392 * If an error is found, relevant data is stored in report.
393 */
394 static int
test_ieee754_exc_fields(int trapStatus,struct fps_test_ereport * report)395 test_ieee754_exc_fields(int trapStatus, struct fps_test_ereport *report)
396 {
397 char err_data[MAX_INFO_SIZE];
398 int i;
399 int rval;
400 uint64_t expected;
401 uint64_t observed;
402 uint64_t prev_fsr;
403 uint64_t result_fsr;
404 uint64_t t_fsr;
405 unsigned long alsw;
406 unsigned long amsw;
407 unsigned long blsw;
408 unsigned long bmsw;
409 unsigned long exc_bits;
410 unsigned long operation;
411
412 rval = FPU_OK;
413 prev_fsr = get_fsr();
414
415 for (i = 0; test_ws[i].instr != 0; i++) {
416 if (trapStatus == T_DISABLED) {
417 set_fsr(prev_fsr & 0xFFFFFFFFF07FFC00);
418 } else {
419 t_fsr = prev_fsr & 0xFFFFFFFFF07FFC1F;
420 t_fsr |= 0x000000000F800000;
421 set_fsr(t_fsr);
422 }
423
424 trap_flag = trap_flag | TRAP_SOLICITED;
425
426 amsw = test_ws[i].a_msw;
427 alsw = test_ws[i].a_lsw;
428 bmsw = test_ws[i].b_msw;
429 blsw = test_ws[i].b_lsw;
430 operation = test_ws[i].instr;
431
432 if (trapStatus == T_DISABLED)
433 exc_bits = test_ws[i].fsr_tem0_ieee754_exc;
434 else
435 exc_bits = test_ws[i].fsr_tem1_ieee754_exc;
436
437 result_fsr = 0;
438 fsr_at_trap = 0;
439
440 switch (operation) {
441 case op_add_sp:
442 result_fsr = wadd_sp(amsw, bmsw);
443 break;
444 case op_add_dp:
445 result_fsr = wadd_dp(amsw, alsw, bmsw, blsw);
446 break;
447 case op_div_sp:
448 result_fsr = wdiv_sp(amsw, bmsw);
449 break;
450 case op_div_dp:
451 result_fsr = wdiv_dp(amsw, alsw, bmsw, blsw);
452 break;
453 case op_mul_sp:
454 result_fsr = wmult_sp(amsw, bmsw);
455 break;
456 case op_mul_dp:
457 result_fsr = wmult_dp(amsw, alsw, bmsw, blsw);
458 break;
459 case op_fsqrts:
460 result_fsr = wsqrt_sp(amsw);
461 break;
462 case op_fsqrtd:
463 result_fsr = wsqrt_dp(((uint64_t)amsw << 32)
464 | alsw);
465 break;
466 default:
467 break;
468 }
469
470 if (trapStatus == T_ENABLED) {
471 if (!trap_flag) {
472 result_fsr = fsr_at_trap;
473 } else {
474 rval = FPU_FOROFFLINE;
475 observed = 1;
476 expected = 0;
477 (void) snprintf(err_data, sizeof (err_data),
478 "test: %d", i);
479 setup_fps_test_struct(IS_EREPORT_INFO,
480 report, 6305, &observed, &expected,
481 1, 1, err_data);
482 }
483 }
484 if ((result_fsr & exc_bits) != exc_bits) {
485 rval = FPU_FOROFFLINE;
486 observed = (uint64_t)(result_fsr & exc_bits);
487 expected = (uint64_t)exc_bits;
488 (void) snprintf(err_data, sizeof (err_data),
489 "test: %d, trapStatus: %d", i, trapStatus);
490 setup_fps_test_struct(IS_EREPORT_INFO, report,
491 6308, &observed, &expected, 1, 1, err_data);
492 }
493 }
494
495 set_fsr(prev_fsr);
496
497 return (rval);
498 }
499
500 /*
501 * test_fccn(struct fps_test_ereport *report)
502 * test the fcc0, fcc1, fcc2, and fcc3 fields of the FSR. Single-
503 * precision comparision operations are done using the test data given
504 * in fccData[], and the resultant value in the fccN field is compared
505 * against the value in fccData. Each test data is used with all the
506 * four fcc fields.
507 *
508 * If an error is found, relevant data is stored in report.
509 */
510 static int
test_fccn(struct fps_test_ereport * report)511 test_fccn(struct fps_test_ereport *report)
512 {
513 char err_data[MAX_INFO_SIZE];
514 int fcc;
515 int i;
516 int rval;
517 uint64_t expected;
518 uint64_t fcc_mask;
519 uint64_t observed;
520 uint64_t prev_fsr;
521 uint64_t result_fsr;
522 unsigned int shiftBits;
523
524 #ifdef __lint
525 uint64_t des_fcc;
526 uint64_t res_fcc;
527 #else
528 unsigned int des_fcc;
529 unsigned int res_fcc;
530 #endif
531
532 prev_fsr = get_fsr();
533 rval = FPU_OK;
534 set_fsr(prev_fsr & 0xFFFFFFFFF07FFC00);
535
536 for (fcc = 0; fcc < N_FCCN; fcc++) {
537 fcc_mask = fccMasks[fcc];
538 shiftBits = fccShifts[fcc];
539
540 for (i = 0; i < N_FCCDATA; i++) {
541 des_fcc = fccData[i].fccVal;
542
543 result_fsr = fcmps_fcc(fccData[i].val1,
544 fccData[i].val2, fcc);
545
546 res_fcc = ((result_fsr & fcc_mask)
547 >> shiftBits);
548
549 if (res_fcc != des_fcc) {
550 rval = FPU_FOROFFLINE;
551 expected = (uint64_t)des_fcc;
552 observed = (uint64_t)res_fcc;
553 (void) snprintf(err_data, sizeof (err_data),
554 "FSR.fcc: %d, FCC ID: %s"
555 "\nExpected: %lld"
556 "\nObserved: %lld",
557 fcc, fccData[i].testId, des_fcc,
558 res_fcc);
559 setup_fps_test_struct(IS_EREPORT_INFO,
560 report, 6310, &observed, &expected,
561 1, 1, err_data);
562 continue;
563 }
564 }
565 }
566
567 set_fsr(prev_fsr);
568
569 return (rval);
570 }
571
572 /*
573 * test_rounding(struct fps_test_ereport *report)
574 * tests the 4 IEEE 754 rounding modes.
575 * If an error is found, relevant data is stored
576 * in report.
577 */
578 static int
test_rounding(struct fps_test_ereport * report)579 test_rounding(struct fps_test_ereport *report)
580 {
581 char err_data[MAX_INFO_SIZE];
582 int i;
583 int rval;
584 uint64_t des_res;
585 uint64_t expected;
586 uint64_t fsr_rd_masked;
587 uint64_t gsr_im_z;
588 uint64_t observed;
589 uint64_t oprnd;
590 uint64_t oprnd1;
591 uint64_t oprnd2;
592 uint64_t prev_fsr;
593 uint64_t prev_gsr;
594 uint64_t rd;
595 uint64_t result;
596 uint64_t rmode;
597
598 rval = FPU_OK;
599 prev_fsr = get_fsr();
600 fsr_rd_masked = prev_fsr & FSR_RD_MASK_Z;
601 prev_gsr = get_gsr();
602 gsr_im_z = prev_gsr & GSR_IM_ZERO;
603
604 for (i = 0; i < R_DATA_N; i++) {
605 for (rd = 0; rd < N_RD_MODES; rd++) {
606 rmode = rd << 30;
607
608 if (rd == 0)
609 des_res = r_data[i].result_r2n;
610 else if (rd == 1)
611 des_res = r_data[i].result_r2z;
612 else if (rd == 2)
613 des_res = r_data[i].result_r2pinf;
614 else if (rd == 3)
615 des_res = r_data[i].result_r2ninf;
616
617 switch (r_data[i].operation) {
618 case op_add_sp:
619 set_gsr(gsr_im_z);
620 set_fsr(fsr_rd_masked | rmode);
621 result = add_sp(r_data[i].operand1_msw,
622 r_data[i].operand2_msw);
623
624 break;
625 case op_add_dp:
626 oprnd1 =
627 ((uint64_t)r_data[i].operand1_msw
628 << 32) | r_data[i].operand1_lsw;
629
630 oprnd2 =
631 ((uint64_t)r_data[i].operand2_msw
632 << 32) | r_data[i].operand2_lsw;
633
634 set_gsr(gsr_im_z);
635 set_fsr(fsr_rd_masked | rmode);
636 result = add_dp(oprnd1, oprnd2);
637
638 break;
639 case op_div_sp:
640 set_gsr(gsr_im_z);
641 set_fsr(fsr_rd_masked | rmode);
642 result = div_sp(r_data[i].operand1_msw,
643 r_data[i].operand2_msw);
644
645 break;
646 case op_div_dp:
647 oprnd1 =
648 ((uint64_t)r_data[i].operand1_msw
649 << 32) | r_data[i].operand1_lsw;
650
651 oprnd2 =
652 ((uint64_t)r_data[i].operand2_msw
653 << 32) | r_data[i].operand2_lsw;
654
655 set_gsr(gsr_im_z);
656 set_fsr(fsr_rd_masked | rmode);
657 result = div_dp(oprnd1, oprnd2);
658
659 break;
660 case op_div_dp_c2sp:
661 oprnd1 =
662 ((uint64_t)r_data[i].operand1_msw
663 << 32) | r_data[i].operand1_lsw;
664
665 oprnd2 =
666 ((uint64_t)r_data[i].operand2_msw
667 << 32) | r_data[i].operand2_lsw;
668
669 set_gsr(gsr_im_z);
670 set_fsr(fsr_rd_masked | rmode);
671 result = div_dp(oprnd1, oprnd2);
672 result = convert_dp_sp(result);
673
674 break;
675 case op_fxtos:
676 oprnd =
677 ((uint64_t)r_data[i].operand1_msw
678 << 32) | r_data[i].operand1_lsw;
679 set_gsr(gsr_im_z);
680 set_fsr(fsr_rd_masked | rmode);
681 result = long_float_s(oprnd);
682
683 break;
684 default:
685 break;
686 }
687
688 if (result != des_res) {
689 expected = (uint64_t)des_res;
690 observed = (uint64_t)result;
691 (void) snprintf(err_data, sizeof (err_data),
692 "FSR.RD: %d, %s, TestID: %s"
693 "\nExpected: %lld\nObserved: %lld",
694 rd, rndModes[rd], r_data[i].test_id,
695 des_res, result);
696 setup_fps_test_struct(IS_EREPORT_INFO,
697 report, 6309, &observed, &expected,
698 1, 1, err_data);
699 rval = FPU_FOROFFLINE;
700 }
701 }
702 }
703
704 set_gsr(prev_gsr);
705 set_fsr(prev_fsr);
706
707 return (rval);
708 }
709