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 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 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 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 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