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 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 /* VIS floating point instruction simulator for Sparc FPU simulator. */ 27 28 #include <sys/types.h> 29 #include <sys/systm.h> 30 #include <sys/fpu/fpusystm.h> 31 #include <sys/fpu/fpu_simulator.h> 32 #include <sys/vis_simulator.h> 33 #include <sys/fpu/globals.h> 34 #include <sys/privregs.h> 35 #include <sys/sun4asi.h> 36 #include <sys/machasi.h> 37 #include <sys/debug.h> 38 #include <sys/cpu_module.h> 39 #include <sys/systm.h> 40 41 #define FPU_REG_FIELD uint32_reg /* Coordinate with FPU_REGS_TYPE. */ 42 #define FPU_DREG_FIELD uint64_reg /* Coordinate with FPU_DREGS_TYPE. */ 43 #define FPU_FSR_FIELD uint64_reg /* Coordinate with V9_FPU_FSR_TYPE. */ 44 45 extern uint_t get_subcc_ccr(uint64_t, uint64_t); 46 47 static enum ftt_type vis_array(fp_simd_type *, vis_inst_type, struct regs *, 48 void *); 49 static enum ftt_type vis_alignaddr(fp_simd_type *, vis_inst_type, 50 struct regs *, void *, kfpu_t *); 51 static enum ftt_type vis_edge(fp_simd_type *, vis_inst_type, struct regs *, 52 void *); 53 static enum ftt_type vis_faligndata(fp_simd_type *, fp_inst_type, 54 kfpu_t *); 55 static enum ftt_type vis_bmask(fp_simd_type *, vis_inst_type, struct regs *, 56 void *, kfpu_t *); 57 static enum ftt_type vis_bshuffle(fp_simd_type *, fp_inst_type, 58 kfpu_t *); 59 static enum ftt_type vis_siam(fp_simd_type *, vis_inst_type, kfpu_t *); 60 static enum ftt_type vis_fcmp(fp_simd_type *, vis_inst_type, struct regs *, 61 void *); 62 static enum ftt_type vis_fmul(fp_simd_type *, vis_inst_type); 63 static enum ftt_type vis_fpixel(fp_simd_type *, vis_inst_type, kfpu_t *); 64 static enum ftt_type vis_fpaddsub(fp_simd_type *, vis_inst_type); 65 static enum ftt_type vis_pdist(fp_simd_type *, fp_inst_type, struct regs *, 66 void *, uint_t); 67 static enum ftt_type vis_prtl_fst(fp_simd_type *, vis_inst_type, struct regs *, 68 void *, uint_t); 69 static enum ftt_type vis_short_fls(fp_simd_type *, vis_inst_type, 70 struct regs *, void *, uint_t); 71 static enum ftt_type vis_blk_fldst(fp_simd_type *, vis_inst_type, 72 struct regs *, void *, uint_t); 73 74 /* 75 * Simulator for VIS instructions with op3 == 0x36 that get fp_disabled 76 * traps. 77 */ 78 enum ftt_type 79 vis_fpu_simulator( 80 fp_simd_type *pfpsd, /* FPU simulator data. */ 81 fp_inst_type pinst, /* FPU instruction to simulate. */ 82 struct regs *pregs, /* Pointer to PCB image of registers. */ 83 void *prw, /* Pointer to locals and ins. */ 84 kfpu_t *fp) /* Need to fp to access gsr reg */ 85 { 86 uint_t nrs1, nrs2, nrd; /* Register number fields. */ 87 uint_t us1, us2, usr; 88 uint64_t lus1, lus2, lusr; 89 enum ftt_type ftt = ftt_none; 90 union { 91 vis_inst_type inst; 92 fp_inst_type pinst; 93 } f; 94 95 ASSERT(USERMODE(pregs->r_tstate)); 96 nrs1 = pinst.rs1; 97 nrs2 = pinst.rs2; 98 nrd = pinst.rd; 99 f.pinst = pinst; 100 if ((f.inst.opf & 1) == 0) { /* double precision */ 101 if ((nrs1 & 1) == 1) /* fix register encoding */ 102 nrs1 = (nrs1 & 0x1e) | 0x20; 103 if ((nrs2 & 1) == 1) 104 nrs2 = (nrs2 & 0x1e) | 0x20; 105 if ((nrd & 1) == 1) 106 nrd = (nrd & 0x1e) | 0x20; 107 } 108 109 switch (f.inst.opf) { 110 /* these instr's do not use fp regs */ 111 case edge8: 112 case edge8l: 113 case edge8n: 114 case edge8ln: 115 case edge16: 116 case edge16l: 117 case edge16n: 118 case edge16ln: 119 case edge32: 120 case edge32l: 121 case edge32n: 122 case edge32ln: 123 ftt = vis_edge(pfpsd, f.inst, pregs, prw); 124 break; 125 case array8: 126 case array16: 127 case array32: 128 ftt = vis_array(pfpsd, f.inst, pregs, prw); 129 break; 130 case alignaddr: 131 case alignaddrl: 132 ftt = vis_alignaddr(pfpsd, f.inst, pregs, prw, fp); 133 break; 134 case bmask: 135 ftt = vis_bmask(pfpsd, f.inst, pregs, prw, fp); 136 break; 137 case fcmple16: 138 case fcmpne16: 139 case fcmpgt16: 140 case fcmpeq16: 141 case fcmple32: 142 case fcmpne32: 143 case fcmpgt32: 144 case fcmpeq32: 145 ftt = vis_fcmp(pfpsd, f.inst, pregs, prw); 146 break; 147 case fmul8x16: 148 case fmul8x16au: 149 case fmul8x16al: 150 case fmul8sux16: 151 case fmul8ulx16: 152 case fmuld8sux16: 153 case fmuld8ulx16: 154 ftt = vis_fmul(pfpsd, f.inst); 155 break; 156 case fpack16: 157 case fpack32: 158 case fpackfix: 159 case fexpand: 160 case fpmerge: 161 ftt = vis_fpixel(pfpsd, f.inst, fp); 162 break; 163 case pdist: 164 case pdistn: 165 ftt = vis_pdist(pfpsd, pinst, pregs, prw, f.inst.opf); 166 break; 167 case faligndata: 168 ftt = vis_faligndata(pfpsd, pinst, fp); 169 break; 170 case bshuffle: 171 ftt = vis_bshuffle(pfpsd, pinst, fp); 172 break; 173 case fpadd16: 174 case fpadd16s: 175 case fpadd32: 176 case fpadd32s: 177 case fpsub16: 178 case fpsub16s: 179 case fpsub32: 180 case fpsub32s: 181 ftt = vis_fpaddsub(pfpsd, f.inst); 182 break; 183 case fzero: 184 lusr = 0; 185 _fp_pack_extword(pfpsd, &lusr, nrd); 186 break; 187 case fzeros: 188 usr = 0; 189 _fp_pack_word(pfpsd, &usr, nrd); 190 break; 191 case fnor: 192 _fp_unpack_extword(pfpsd, &lus1, nrs1); 193 _fp_unpack_extword(pfpsd, &lus2, nrs2); 194 lusr = ~(lus1 | lus2); 195 _fp_pack_extword(pfpsd, &lusr, nrd); 196 break; 197 case fnors: 198 _fp_unpack_word(pfpsd, &us1, nrs1); 199 _fp_unpack_word(pfpsd, &us2, nrs2); 200 usr = ~(us1 | us2); 201 _fp_pack_word(pfpsd, &usr, nrd); 202 break; 203 case fandnot2: 204 _fp_unpack_extword(pfpsd, &lus1, nrs1); 205 _fp_unpack_extword(pfpsd, &lus2, nrs2); 206 lusr = (lus1 & ~lus2); 207 _fp_pack_extword(pfpsd, &lusr, nrd); 208 break; 209 case fandnot2s: 210 _fp_unpack_word(pfpsd, &us1, nrs1); 211 _fp_unpack_word(pfpsd, &us2, nrs2); 212 usr = (us1 & ~us2); 213 _fp_pack_word(pfpsd, &usr, nrd); 214 break; 215 case fnot2: 216 _fp_unpack_extword(pfpsd, &lus2, nrs2); 217 lusr = ~lus2; 218 _fp_pack_extword(pfpsd, &lusr, nrd); 219 break; 220 case fnot2s: 221 _fp_unpack_word(pfpsd, &us2, nrs2); 222 usr = ~us2; 223 _fp_pack_word(pfpsd, &usr, nrd); 224 break; 225 case fandnot1: 226 _fp_unpack_extword(pfpsd, &lus1, nrs1); 227 _fp_unpack_extword(pfpsd, &lus2, nrs2); 228 lusr = (~lus1 & lus2); 229 _fp_pack_extword(pfpsd, &lusr, nrd); 230 break; 231 case fandnot1s: 232 _fp_unpack_word(pfpsd, &us1, nrs1); 233 _fp_unpack_word(pfpsd, &us2, nrs2); 234 usr = (~us1 & us2); 235 _fp_pack_word(pfpsd, &usr, nrd); 236 break; 237 case fnot1: 238 _fp_unpack_extword(pfpsd, &lus1, nrs1); 239 lusr = ~lus1; 240 _fp_pack_extword(pfpsd, &lusr, nrd); 241 break; 242 case fnot1s: 243 _fp_unpack_word(pfpsd, &us1, nrs1); 244 usr = ~us1; 245 _fp_pack_word(pfpsd, &usr, nrd); 246 break; 247 case fxor: 248 _fp_unpack_extword(pfpsd, &lus1, nrs1); 249 _fp_unpack_extword(pfpsd, &lus2, nrs2); 250 lusr = (lus1 ^ lus2); 251 _fp_pack_extword(pfpsd, &lusr, nrd); 252 break; 253 case fxors: 254 _fp_unpack_word(pfpsd, &us1, nrs1); 255 _fp_unpack_word(pfpsd, &us2, nrs2); 256 usr = (us1 ^ us2); 257 _fp_pack_word(pfpsd, &usr, nrd); 258 break; 259 case fnand: 260 _fp_unpack_extword(pfpsd, &lus1, nrs1); 261 _fp_unpack_extword(pfpsd, &lus2, nrs2); 262 lusr = ~(lus1 & lus2); 263 _fp_pack_extword(pfpsd, &lusr, nrd); 264 break; 265 case fnands: 266 _fp_unpack_word(pfpsd, &us1, nrs1); 267 _fp_unpack_word(pfpsd, &us2, nrs2); 268 usr = ~(us1 & us2); 269 _fp_pack_word(pfpsd, &usr, nrd); 270 break; 271 case fand: 272 _fp_unpack_extword(pfpsd, &lus1, nrs1); 273 _fp_unpack_extword(pfpsd, &lus2, nrs2); 274 lusr = (lus1 & lus2); 275 _fp_pack_extword(pfpsd, &lusr, nrd); 276 break; 277 case fands: 278 _fp_unpack_word(pfpsd, &us1, nrs1); 279 _fp_unpack_word(pfpsd, &us2, nrs2); 280 usr = (us1 & us2); 281 _fp_pack_word(pfpsd, &usr, nrd); 282 break; 283 case fxnor: 284 _fp_unpack_extword(pfpsd, &lus1, nrs1); 285 _fp_unpack_extword(pfpsd, &lus2, nrs2); 286 lusr = ~(lus1 ^ lus2); 287 _fp_pack_extword(pfpsd, &lusr, nrd); 288 break; 289 case fxnors: 290 _fp_unpack_word(pfpsd, &us1, nrs1); 291 _fp_unpack_word(pfpsd, &us2, nrs2); 292 usr = ~(us1 ^ us2); 293 _fp_pack_word(pfpsd, &usr, nrd); 294 break; 295 case fsrc1: 296 _fp_unpack_extword(pfpsd, &lusr, nrs1); 297 _fp_pack_extword(pfpsd, &lusr, nrd); 298 break; 299 case fsrc1s: 300 _fp_unpack_word(pfpsd, &usr, nrs1); 301 _fp_pack_word(pfpsd, &usr, nrd); 302 break; 303 case fornot2: 304 _fp_unpack_extword(pfpsd, &lus1, nrs1); 305 _fp_unpack_extword(pfpsd, &lus2, nrs2); 306 lusr = (lus1 | ~lus2); 307 _fp_pack_extword(pfpsd, &lusr, nrd); 308 break; 309 case fornot2s: 310 _fp_unpack_word(pfpsd, &us1, nrs1); 311 _fp_unpack_word(pfpsd, &us2, nrs2); 312 usr = (us1 | ~us2); 313 _fp_pack_word(pfpsd, &usr, nrd); 314 break; 315 case fsrc2: 316 _fp_unpack_extword(pfpsd, &lusr, nrs2); 317 _fp_pack_extword(pfpsd, &lusr, nrd); 318 break; 319 case fsrc2s: 320 _fp_unpack_word(pfpsd, &usr, nrs2); 321 _fp_pack_word(pfpsd, &usr, nrd); 322 break; 323 case fornot1: 324 _fp_unpack_extword(pfpsd, &lus1, nrs1); 325 _fp_unpack_extword(pfpsd, &lus2, nrs2); 326 lusr = (~lus1 | lus2); 327 _fp_pack_extword(pfpsd, &lusr, nrd); 328 break; 329 case fornot1s: 330 _fp_unpack_word(pfpsd, &us1, nrs1); 331 _fp_unpack_word(pfpsd, &us2, nrs2); 332 usr = (~us1 | us2); 333 _fp_pack_word(pfpsd, &usr, nrd); 334 break; 335 case for_op: 336 _fp_unpack_extword(pfpsd, &lus1, nrs1); 337 _fp_unpack_extword(pfpsd, &lus2, nrs2); 338 lusr = (lus1 | lus2); 339 _fp_pack_extword(pfpsd, &lusr, nrd); 340 break; 341 case fors_op: 342 _fp_unpack_word(pfpsd, &us1, nrs1); 343 _fp_unpack_word(pfpsd, &us2, nrs2); 344 usr = (us1 | us2); 345 _fp_pack_word(pfpsd, &usr, nrd); 346 break; 347 case fone: 348 lusr = 0xffffffffffffffff; 349 _fp_pack_extword(pfpsd, &lusr, nrd); 350 break; 351 case fones: 352 usr = 0xffffffffUL; 353 _fp_pack_word(pfpsd, &usr, nrd); 354 break; 355 case siam: 356 ftt = vis_siam(pfpsd, f.inst, fp); 357 break; 358 default: 359 return (ftt_unimplemented); 360 } 361 362 pregs->r_pc = pregs->r_npc; /* Do not retry emulated instruction. */ 363 pregs->r_npc += 4; 364 return (ftt); 365 } 366 367 /* 368 * Simulator for edge instructions 369 */ 370 static enum ftt_type 371 vis_edge( 372 fp_simd_type *pfpsd, /* FPU simulator data. */ 373 vis_inst_type inst, /* FPU instruction to simulate. */ 374 struct regs *pregs, /* Pointer to PCB image of registers. */ 375 void *prw) /* Pointer to locals and ins. */ 376 377 { 378 uint_t nrs1, nrs2, nrd; /* Register number fields. */ 379 enum ftt_type ftt; 380 uint64_t addrl, addrr, mask; 381 uint64_t ah61l, ah61r; /* Higher 61 bits of address */ 382 int al3l, al3r; /* Lower 3 bits of address */ 383 uint_t ccr; 384 385 nrs1 = inst.rs1; 386 nrs2 = inst.rs2; 387 nrd = inst.rd; 388 389 ftt = read_iureg(pfpsd, nrs1, pregs, prw, &addrl); 390 if (ftt != ftt_none) 391 return (ftt); 392 ftt = read_iureg(pfpsd, nrs2, pregs, prw, &addrr); 393 if (ftt != ftt_none) 394 return (ftt); 395 396 /* Test PSTATE.AM to determine 32-bit vs 64-bit addressing */ 397 if ((pregs->r_tstate & TSTATE_AM) != 0) { 398 ah61l = addrl & 0xfffffff8; 399 ah61r = addrr & 0xfffffff8; 400 } else { 401 ah61l = addrl & ~0x7; 402 ah61r = addrr & ~0x7; 403 } 404 405 406 switch (inst.opf) { 407 case edge8: 408 case edge8n: 409 case edge8l: 410 case edge8ln: 411 al3l = addrl & 0x7; 412 switch (inst.opf) { 413 case edge8: 414 case edge8n: 415 if (inst.opf == edge8) { 416 VISINFO_KSTAT(vis_edge8); 417 } else { 418 VISINFO_KSTAT(vis_edge8n); 419 } 420 mask = 0xff >> al3l; 421 if (ah61l == ah61r) { 422 al3r = addrr & 0x7; 423 mask &= (0xff << (0x7 - al3r)) & 0xff; 424 } 425 break; 426 case edge8l: 427 case edge8ln: 428 if (inst.opf == edge8l) { 429 VISINFO_KSTAT(vis_edge8l); 430 } else { 431 VISINFO_KSTAT(vis_edge8ln); 432 } 433 mask = (0xff << al3l) & 0xff; 434 if (ah61l == ah61r) { 435 al3r = addrr & 0x7; 436 mask &= 0xff >> (0x7 - al3r); 437 } 438 break; 439 } 440 break; 441 case edge16: 442 case edge16l: 443 case edge16n: 444 case edge16ln: 445 al3l = addrl & 0x6; 446 al3l >>= 0x1; 447 switch (inst.opf) { 448 case edge16: 449 case edge16n: 450 if (inst.opf == edge16) { 451 VISINFO_KSTAT(vis_edge16); 452 453 } else { 454 VISINFO_KSTAT(vis_edge16n); 455 } 456 mask = 0xf >> al3l; 457 if (ah61l == ah61r) { 458 al3r = addrr & 0x6; 459 al3r >>= 0x1; 460 mask &= (0xf << (0x3 - al3r)) & 0xf; 461 } 462 break; 463 case edge16l: 464 case edge16ln: 465 if (inst.opf == edge16l) { 466 VISINFO_KSTAT(vis_edge16l); 467 468 } else { 469 VISINFO_KSTAT(vis_edge16ln); 470 } 471 472 mask = (0xf << al3l) & 0xf; 473 if (ah61l == ah61r) { 474 al3r = addrr & 0x6; 475 al3r >>= 0x1; 476 mask &= 0xf >> (0x3 - al3r); 477 } 478 break; 479 } 480 break; 481 case edge32: 482 case edge32l: 483 case edge32n: 484 case edge32ln: 485 al3l = addrl & 0x4; 486 al3l >>= 0x2; 487 488 switch (inst.opf) { 489 case edge32: 490 case edge32n: 491 if (inst.opf == edge32) { 492 VISINFO_KSTAT(vis_edge32); 493 494 } else { 495 VISINFO_KSTAT(vis_edge32n); 496 } 497 mask = 0x3 >> al3l; 498 if (ah61l == ah61r) { 499 al3r = addrr & 0x4; 500 al3r >>= 0x2; 501 mask &= (0x3 << (0x1 - al3r)) & 0x3; 502 } 503 break; 504 case edge32l: 505 case edge32ln: 506 if (inst.opf == edge32l) { 507 VISINFO_KSTAT(vis_edge32l); 508 509 } else { 510 VISINFO_KSTAT(vis_edge32ln); 511 } 512 mask = (0x3 << al3l) & 0x3; 513 if (ah61l == ah61r) { 514 al3r = addrr & 0x4; 515 al3r >>= 0x2; 516 mask &= 0x3 >> (0x1 - al3r); 517 } 518 break; 519 } 520 break; 521 } 522 523 ftt = write_iureg(pfpsd, nrd, pregs, prw, &mask); 524 525 switch (inst.opf) { 526 case edge8: 527 case edge8l: 528 case edge16: 529 case edge16l: 530 case edge32: 531 case edge32l: 532 533 /* Update flags per SUBcc outcome */ 534 pregs->r_tstate &= ~((uint64_t)TSTATE_CCR_MASK 535 << TSTATE_CCR_SHIFT); 536 ccr = get_subcc_ccr(addrl, addrr); /* get subcc cond. codes */ 537 pregs->r_tstate |= ((uint64_t)ccr << TSTATE_CCR_SHIFT); 538 539 break; 540 } 541 return (ftt); 542 } 543 544 /* 545 * Simulator for three dimentional array addressing instructions. 546 */ 547 static enum ftt_type 548 vis_array( 549 fp_simd_type *pfpsd, /* FPU simulator data. */ 550 vis_inst_type inst, /* FPU instruction to simulate. */ 551 struct regs *pregs, /* Pointer to PCB image of registers. */ 552 void *prw) /* Pointer to locals and ins. */ 553 554 { 555 uint_t nrs1, nrs2, nrd; /* Register number fields. */ 556 enum ftt_type ftt; 557 uint64_t laddr, bsize, baddr; 558 uint64_t nbit; 559 int oy, oz; 560 561 nrs1 = inst.rs1; 562 nrs2 = inst.rs2; 563 nrd = inst.rd; 564 565 ftt = read_iureg(pfpsd, nrs1, pregs, prw, &laddr); 566 if (ftt != ftt_none) 567 return (ftt); 568 ftt = read_iureg(pfpsd, nrs2, pregs, prw, &bsize); 569 if (ftt != ftt_none) 570 return (ftt); 571 572 if (bsize > 5) { 573 bsize = 5; 574 } 575 nbit = (1 << bsize) - 1; /* Number of bits for XY<6+n-1:6> */ 576 oy = 17 + bsize; /* Offset of Y<6+n-1:6> */ 577 oz = 17 + 2 * bsize; /* Offset of Z<8:5> */ 578 579 baddr = 0; 580 baddr |= (laddr >> (11 - 0)) & (0x03 << 0); /* X_integer<1:0> */ 581 baddr |= (laddr >> (33 - 2)) & (0x03 << 2); /* Y_integer<1:0> */ 582 baddr |= (laddr >> (55 - 4)) & (0x01 << 4); /* Z_integer<0> */ 583 baddr |= (laddr >> (13 - 5)) & (0x0f << 5); /* X_integer<5:2> */ 584 baddr |= (laddr >> (35 - 9)) & (0x0f << 9); /* Y_integer<5:2> */ 585 baddr |= (laddr >> (56 - 13)) & (0x0f << 13); /* Z_integer<4:1> */ 586 baddr |= (laddr >> (17 - 17)) & (nbit << 17); /* X_integer<6+n-1:6> */ 587 baddr |= (laddr >> (39 - oy)) & (nbit << oy); /* Y_integer<6+n-1:6> */ 588 baddr |= (laddr >> (60 - oz)) & (0x0f << oz); /* Z_integer<8:5> */ 589 590 switch (inst.opf) { 591 case array8: 592 VISINFO_KSTAT(vis_array8); 593 break; 594 case array16: 595 VISINFO_KSTAT(vis_array16); 596 baddr <<= 1; 597 break; 598 case array32: 599 VISINFO_KSTAT(vis_array32); 600 baddr <<= 2; 601 break; 602 } 603 604 ftt = write_iureg(pfpsd, nrd, pregs, prw, &baddr); 605 606 return (ftt); 607 } 608 609 /* 610 * Simulator for alignaddr and alignaddrl instructions. 611 */ 612 static enum ftt_type 613 vis_alignaddr( 614 fp_simd_type *pfpsd, /* FPU simulator data. */ 615 vis_inst_type inst, /* FPU instruction to simulate. */ 616 struct regs *pregs, /* Pointer to PCB image of registers. */ 617 void *prw, /* Pointer to locals and ins. */ 618 kfpu_t *fp) /* Need to fp to access gsr reg */ 619 { 620 uint_t nrs1, nrs2, nrd; /* Register number fields. */ 621 enum ftt_type ftt; 622 uint64_t ea, tea, g, r; 623 short s; 624 625 nrs1 = inst.rs1; 626 nrs2 = inst.rs2; 627 nrd = inst.rd; 628 629 ftt = read_iureg(pfpsd, nrs1, pregs, prw, &ea); 630 if (ftt != ftt_none) 631 return (ftt); 632 ftt = read_iureg(pfpsd, nrs2, pregs, prw, &tea); 633 if (ftt != ftt_none) 634 return (ftt); 635 ea += tea; 636 r = ea & ~0x7; /* zero least 3 significant bits */ 637 ftt = write_iureg(pfpsd, nrd, pregs, prw, &r); 638 639 640 g = pfpsd->fp_current_read_gsr(fp); 641 g &= ~(GSR_ALIGN_MASK); /* zero the align offset */ 642 r = ea & 0x7; 643 if (inst.opf == alignaddrl) { 644 s = (short)(~r); /* 2's complement for alignaddrl */ 645 if (s < 0) 646 r = (uint64_t)((s + 1) & 0x7); 647 else 648 r = (uint64_t)(s & 0x7); 649 } 650 g |= (r << GSR_ALIGN_SHIFT) & GSR_ALIGN_MASK; 651 pfpsd->fp_current_write_gsr(g, fp); 652 653 return (ftt); 654 } 655 656 /* 657 * Simulator for bmask instruction. 658 */ 659 static enum ftt_type 660 vis_bmask( 661 fp_simd_type *pfpsd, /* FPU simulator data. */ 662 vis_inst_type inst, /* FPU instruction to simulate. */ 663 struct regs *pregs, /* Pointer to PCB image of registers. */ 664 void *prw, /* Pointer to locals and ins. */ 665 kfpu_t *fp) /* Need to fp to access gsr reg */ 666 { 667 uint_t nrs1, nrs2, nrd; /* Register number fields. */ 668 enum ftt_type ftt; 669 uint64_t ea, tea, g; 670 671 VISINFO_KSTAT(vis_bmask); 672 nrs1 = inst.rs1; 673 nrs2 = inst.rs2; 674 nrd = inst.rd; 675 676 ftt = read_iureg(pfpsd, nrs1, pregs, prw, &ea); 677 if (ftt != ftt_none) 678 return (ftt); 679 ftt = read_iureg(pfpsd, nrs2, pregs, prw, &tea); 680 if (ftt != ftt_none) 681 return (ftt); 682 ea += tea; 683 ftt = write_iureg(pfpsd, nrd, pregs, prw, &ea); 684 685 g = pfpsd->fp_current_read_gsr(fp); 686 g &= ~(GSR_MASK_MASK); /* zero the mask offset */ 687 688 /* Put the least significant 32 bits of ea in GSR.mask */ 689 g |= (ea << GSR_MASK_SHIFT) & GSR_MASK_MASK; 690 pfpsd->fp_current_write_gsr(g, fp); 691 return (ftt); 692 } 693 694 /* 695 * Simulator for fp[add|sub]* instruction. 696 */ 697 static enum ftt_type 698 vis_fpaddsub( 699 fp_simd_type *pfpsd, /* FPU simulator data. */ 700 vis_inst_type inst) /* FPU instruction to simulate. */ 701 { 702 uint_t nrs1, nrs2, nrd; /* Register number fields. */ 703 union { 704 uint64_t ll; 705 uint32_t i[2]; 706 uint16_t s[4]; 707 } lrs1, lrs2, lrd; 708 union { 709 uint32_t i; 710 uint16_t s[2]; 711 } krs1, krs2, krd; 712 int i; 713 714 nrs1 = inst.rs1; 715 nrs2 = inst.rs2; 716 nrd = inst.rd; 717 if ((inst.opf & 1) == 0) { /* double precision */ 718 if ((nrs1 & 1) == 1) /* fix register encoding */ 719 nrs1 = (nrs1 & 0x1e) | 0x20; 720 if ((nrs2 & 1) == 1) 721 nrs2 = (nrs2 & 0x1e) | 0x20; 722 if ((nrd & 1) == 1) 723 nrd = (nrd & 0x1e) | 0x20; 724 } 725 switch (inst.opf) { 726 case fpadd16: 727 _fp_unpack_extword(pfpsd, &lrs1.ll, nrs1); 728 _fp_unpack_extword(pfpsd, &lrs2.ll, nrs2); 729 for (i = 0; i <= 3; i++) { 730 lrd.s[i] = lrs1.s[i] + lrs2.s[i]; 731 } 732 _fp_pack_extword(pfpsd, &lrd.ll, nrd); 733 break; 734 case fpadd16s: 735 _fp_unpack_word(pfpsd, &krs1.i, nrs1); 736 _fp_unpack_word(pfpsd, &krs2.i, nrs2); 737 for (i = 0; i <= 1; i++) { 738 krd.s[i] = krs1.s[i] + krs2.s[i]; 739 } 740 _fp_pack_word(pfpsd, &krd.i, nrd); 741 break; 742 case fpadd32: 743 _fp_unpack_extword(pfpsd, &lrs1.ll, nrs1); 744 _fp_unpack_extword(pfpsd, &lrs2.ll, nrs2); 745 for (i = 0; i <= 1; i++) { 746 lrd.i[i] = lrs1.i[i] + lrs2.i[i]; 747 } 748 _fp_pack_extword(pfpsd, &lrd.ll, nrd); 749 break; 750 case fpadd32s: 751 _fp_unpack_word(pfpsd, &krs1.i, nrs1); 752 _fp_unpack_word(pfpsd, &krs2.i, nrs2); 753 krd.i = krs1.i + krs2.i; 754 _fp_pack_word(pfpsd, &krd.i, nrd); 755 break; 756 case fpsub16: 757 _fp_unpack_extword(pfpsd, &lrs1.ll, nrs1); 758 _fp_unpack_extword(pfpsd, &lrs2.ll, nrs2); 759 for (i = 0; i <= 3; i++) { 760 lrd.s[i] = lrs1.s[i] - lrs2.s[i]; 761 } 762 _fp_pack_extword(pfpsd, &lrd.ll, nrd); 763 break; 764 case fpsub16s: 765 _fp_unpack_word(pfpsd, &krs1.i, nrs1); 766 _fp_unpack_word(pfpsd, &krs2.i, nrs2); 767 for (i = 0; i <= 1; i++) { 768 krd.s[i] = krs1.s[i] - krs2.s[i]; 769 } 770 _fp_pack_word(pfpsd, &krd.i, nrd); 771 break; 772 case fpsub32: 773 _fp_unpack_extword(pfpsd, &lrs1.ll, nrs1); 774 _fp_unpack_extword(pfpsd, &lrs2.ll, nrs2); 775 for (i = 0; i <= 1; i++) { 776 lrd.i[i] = lrs1.i[i] - lrs2.i[i]; 777 } 778 _fp_pack_extword(pfpsd, &lrd.ll, nrd); 779 break; 780 case fpsub32s: 781 _fp_unpack_word(pfpsd, &krs1.i, nrs1); 782 _fp_unpack_word(pfpsd, &krs2.i, nrs2); 783 krd.i = krs1.i - krs2.i; 784 _fp_pack_word(pfpsd, &krd.i, nrd); 785 break; 786 } 787 return (ftt_none); 788 } 789 790 /* 791 * Simulator for fcmp* instruction. 792 */ 793 static enum ftt_type 794 vis_fcmp( 795 fp_simd_type *pfpsd, /* FPU simulator data. */ 796 vis_inst_type inst, /* FPU instruction to simulate. */ 797 struct regs *pregs, /* Pointer to PCB image of registers. */ 798 void *prw) /* Pointer to locals and ins. */ 799 { 800 uint_t nrs1, nrs2, nrd; /* Register number fields. */ 801 union { 802 uint64_t ll; 803 uint32_t i[2]; 804 uint16_t s[4]; 805 } krs1, krs2, krd; 806 enum ftt_type ftt; 807 short sr1, sr2; 808 int i, ir1, ir2; 809 810 nrs1 = inst.rs1; 811 nrs2 = inst.rs2; 812 nrd = inst.rd; 813 krd.ll = 0; 814 if ((nrs1 & 1) == 1) /* fix register encoding */ 815 nrs1 = (nrs1 & 0x1e) | 0x20; 816 if ((nrs2 & 1) == 1) 817 nrs2 = (nrs2 & 0x1e) | 0x20; 818 819 _fp_unpack_extword(pfpsd, &krs1.ll, nrs1); 820 _fp_unpack_extword(pfpsd, &krs2.ll, nrs2); 821 switch (inst.opf) { 822 case fcmple16: 823 VISINFO_KSTAT(vis_fcmple16); 824 for (i = 0; i <= 3; i++) { 825 sr1 = (short)krs1.s[i]; 826 sr2 = (short)krs2.s[i]; 827 if (sr1 <= sr2) 828 krd.ll += (0x8 >> i); 829 } 830 break; 831 case fcmpne16: 832 VISINFO_KSTAT(vis_fcmpne16); 833 for (i = 0; i <= 3; i++) { 834 sr1 = (short)krs1.s[i]; 835 sr2 = (short)krs2.s[i]; 836 if (sr1 != sr2) 837 krd.ll += (0x8 >> i); 838 } 839 break; 840 case fcmpgt16: 841 VISINFO_KSTAT(vis_fcmpgt16); 842 for (i = 0; i <= 3; i++) { 843 sr1 = (short)krs1.s[i]; 844 sr2 = (short)krs2.s[i]; 845 if (sr1 > sr2) 846 krd.ll += (0x8 >> i); 847 } 848 break; 849 case fcmpeq16: 850 VISINFO_KSTAT(vis_fcmpeq16); 851 for (i = 0; i <= 3; i++) { 852 sr1 = (short)krs1.s[i]; 853 sr2 = (short)krs2.s[i]; 854 if (sr1 == sr2) 855 krd.ll += (0x8 >> i); 856 } 857 break; 858 case fcmple32: 859 VISINFO_KSTAT(vis_fcmple32); 860 for (i = 0; i <= 1; i++) { 861 ir1 = (int)krs1.i[i]; 862 ir2 = (int)krs2.i[i]; 863 if (ir1 <= ir2) 864 krd.ll += (0x2 >> i); 865 } 866 break; 867 case fcmpne32: 868 VISINFO_KSTAT(vis_fcmpne32); 869 for (i = 0; i <= 1; i++) { 870 ir1 = (int)krs1.i[i]; 871 ir2 = (int)krs2.i[i]; 872 if (ir1 != ir2) 873 krd.ll += (0x2 >> i); 874 } 875 break; 876 case fcmpgt32: 877 VISINFO_KSTAT(vis_fcmpgt32); 878 for (i = 0; i <= 1; i++) { 879 ir1 = (int)krs1.i[i]; 880 ir2 = (int)krs2.i[i]; 881 if (ir1 > ir2) 882 krd.ll += (0x2 >> i); 883 } 884 break; 885 case fcmpeq32: 886 VISINFO_KSTAT(vis_fcmpeq32); 887 for (i = 0; i <= 1; i++) { 888 ir1 = (int)krs1.i[i]; 889 ir2 = (int)krs2.i[i]; 890 if (ir1 == ir2) 891 krd.ll += (0x2 >> i); 892 } 893 break; 894 } 895 ftt = write_iureg(pfpsd, nrd, pregs, prw, &krd.ll); 896 return (ftt); 897 } 898 899 /* 900 * Simulator for fmul* instruction. 901 */ 902 static enum ftt_type 903 vis_fmul( 904 fp_simd_type *pfpsd, /* FPU simulator data. */ 905 vis_inst_type inst) /* FPU instruction to simulate. */ 906 { 907 uint_t nrs1, nrs2, nrd; /* Register number fields. */ 908 union { 909 uint64_t ll; 910 uint32_t i[2]; 911 uint16_t s[4]; 912 uint8_t c[8]; 913 } lrs1, lrs2, lrd; 914 union { 915 uint32_t i; 916 uint16_t s[2]; 917 uint8_t c[4]; 918 } krs1, krs2, kres; 919 short s1, s2, sres; 920 ushort_t us1; 921 char c1; 922 int i; 923 924 nrs1 = inst.rs1; 925 nrs2 = inst.rs2; 926 nrd = inst.rd; 927 if ((inst.opf & 1) == 0) { /* double precision */ 928 if ((nrd & 1) == 1) /* fix register encoding */ 929 nrd = (nrd & 0x1e) | 0x20; 930 } 931 932 switch (inst.opf) { 933 case fmul8x16: 934 VISINFO_KSTAT(vis_fmul8x16); 935 _fp_unpack_word(pfpsd, &krs1.i, nrs1); 936 if ((nrs2 & 1) == 1) 937 nrs2 = (nrs2 & 0x1e) | 0x20; 938 _fp_unpack_extword(pfpsd, &lrs2.ll, nrs2); 939 for (i = 0; i <= 3; i++) { 940 us1 = (ushort_t)krs1.c[i]; 941 s2 = (short)lrs2.s[i]; 942 kres.i = us1 * s2; 943 sres = (short)((kres.c[1] << 8) | kres.c[2]); 944 if (kres.c[3] >= 0x80) 945 sres++; 946 lrd.s[i] = sres; 947 } 948 _fp_pack_extword(pfpsd, &lrd.ll, nrd); 949 break; 950 case fmul8x16au: 951 VISINFO_KSTAT(vis_fmul8x16au); 952 _fp_unpack_word(pfpsd, &krs1.i, nrs1); 953 _fp_unpack_word(pfpsd, &krs2.i, nrs2); 954 for (i = 0; i <= 3; i++) { 955 us1 = (ushort_t)krs1.c[i]; 956 s2 = (short)krs2.s[0]; 957 kres.i = us1 * s2; 958 sres = (short)((kres.c[1] << 8) | kres.c[2]); 959 if (kres.c[3] >= 0x80) 960 sres++; 961 lrd.s[i] = sres; 962 } 963 _fp_pack_extword(pfpsd, &lrd.ll, nrd); 964 break; 965 case fmul8x16al: 966 VISINFO_KSTAT(vis_fmul8x16al); 967 _fp_unpack_word(pfpsd, &krs1.i, nrs1); 968 _fp_unpack_word(pfpsd, &krs2.i, nrs2); 969 for (i = 0; i <= 3; i++) { 970 us1 = (ushort_t)krs1.c[i]; 971 s2 = (short)krs2.s[1]; 972 kres.i = us1 * s2; 973 sres = (short)((kres.c[1] << 8) | kres.c[2]); 974 if (kres.c[3] >= 0x80) 975 sres++; 976 lrd.s[i] = sres; 977 } 978 _fp_pack_extword(pfpsd, &lrd.ll, nrd); 979 break; 980 case fmul8sux16: 981 VISINFO_KSTAT(vis_fmul8sux16); 982 if ((nrs1 & 1) == 1) /* fix register encoding */ 983 nrs1 = (nrs1 & 0x1e) | 0x20; 984 _fp_unpack_extword(pfpsd, &lrs1.ll, nrs1); 985 if ((nrs2 & 1) == 1) 986 nrs2 = (nrs2 & 0x1e) | 0x20; 987 _fp_unpack_extword(pfpsd, &lrs2.ll, nrs2); 988 for (i = 0; i <= 3; i++) { 989 c1 = lrs1.c[(i*2)]; 990 s1 = (short)c1; /* keeps the sign alive */ 991 s2 = (short)lrs2.s[i]; 992 kres.i = s1 * s2; 993 sres = (short)((kres.c[1] << 8) | kres.c[2]); 994 if (kres.c[3] >= 0x80) 995 sres++; 996 if (sres < 0) 997 lrd.s[i] = (sres & 0xFFFF); 998 else 999 lrd.s[i] = sres; 1000 } 1001 _fp_pack_extword(pfpsd, &lrd.ll, nrd); 1002 break; 1003 case fmul8ulx16: 1004 VISINFO_KSTAT(vis_fmul8ulx16); 1005 if ((nrs1 & 1) == 1) /* fix register encoding */ 1006 nrs1 = (nrs1 & 0x1e) | 0x20; 1007 _fp_unpack_extword(pfpsd, &lrs1.ll, nrs1); 1008 if ((nrs2 & 1) == 1) 1009 nrs2 = (nrs2 & 0x1e) | 0x20; 1010 _fp_unpack_extword(pfpsd, &lrs2.ll, nrs2); 1011 for (i = 0; i <= 3; i++) { 1012 us1 = (ushort_t)lrs1.c[(i*2)+1]; 1013 s2 = (short)lrs2.s[i]; 1014 kres.i = us1 * s2; 1015 sres = (short)kres.s[0]; 1016 if (kres.s[1] >= 0x8000) 1017 sres++; 1018 lrd.s[i] = sres; 1019 } 1020 _fp_pack_extword(pfpsd, &lrd.ll, nrd); 1021 break; 1022 case fmuld8sux16: 1023 VISINFO_KSTAT(vis_fmuld8sux16); 1024 _fp_unpack_word(pfpsd, &krs1.i, nrs1); 1025 _fp_unpack_word(pfpsd, &krs2.i, nrs2); 1026 for (i = 0; i <= 1; i++) { 1027 c1 = krs1.c[(i*2)]; 1028 s1 = (short)c1; /* keeps the sign alive */ 1029 s2 = (short)krs2.s[i]; 1030 kres.i = s1 * s2; 1031 lrd.i[i] = kres.i << 8; 1032 } 1033 _fp_pack_extword(pfpsd, &lrd.ll, nrd); 1034 break; 1035 case fmuld8ulx16: 1036 VISINFO_KSTAT(vis_fmuld8ulx16); 1037 _fp_unpack_word(pfpsd, &krs1.i, nrs1); 1038 _fp_unpack_word(pfpsd, &krs2.i, nrs2); 1039 for (i = 0; i <= 1; i++) { 1040 us1 = (ushort_t)krs1.c[(i*2)+1]; 1041 s2 = (short)krs2.s[i]; 1042 lrd.i[i] = us1 * s2; 1043 } 1044 _fp_pack_extword(pfpsd, &lrd.ll, nrd); 1045 break; 1046 } 1047 return (ftt_none); 1048 } 1049 1050 /* 1051 * Simulator for fpixel formatting instructions. 1052 */ 1053 static enum ftt_type 1054 vis_fpixel( 1055 fp_simd_type *pfpsd, /* FPU simulator data. */ 1056 vis_inst_type inst, /* FPU instruction to simulate. */ 1057 kfpu_t *fp) /* Need to fp to access gsr reg */ 1058 { 1059 uint_t nrs1, nrs2, nrd; /* Register number fields. */ 1060 int i, j, k, sf; 1061 union { 1062 uint64_t ll; 1063 uint32_t i[2]; 1064 uint16_t s[4]; 1065 uint8_t c[8]; 1066 } lrs1, lrs2, lrd; 1067 union { 1068 uint32_t i; 1069 uint16_t s[2]; 1070 uint8_t c[4]; 1071 } krs1, krs2, krd; 1072 uint64_t r; 1073 int64_t l, m; 1074 short s; 1075 uchar_t uc; 1076 1077 nrs1 = inst.rs1; 1078 nrs2 = inst.rs2; 1079 nrd = inst.rd; 1080 if ((inst.opf != fpack16) && (inst.opf != fpackfix)) { 1081 if ((nrd & 1) == 1) /* fix register encoding */ 1082 nrd = (nrd & 0x1e) | 0x20; 1083 } 1084 1085 switch (inst.opf) { 1086 case fpack16: 1087 VISINFO_KSTAT(vis_fpack16); 1088 if ((nrs2 & 1) == 1) /* fix register encoding */ 1089 nrs2 = (nrs2 & 0x1e) | 0x20; 1090 _fp_unpack_extword(pfpsd, &lrs2.ll, nrs2); 1091 r = pfpsd->fp_current_read_gsr(fp); 1092 /* fpack16 ignores GSR.scale msb */ 1093 sf = (int)(GSR_SCALE(r) & 0xf); 1094 for (i = 0; i <= 3; i++) { 1095 s = (short)lrs2.s[i]; /* preserve the sign */ 1096 j = ((int)s << sf); 1097 k = j >> 7; 1098 if (k < 0) { 1099 uc = 0; 1100 } else if (k > 255) { 1101 uc = 255; 1102 } else { 1103 uc = (uchar_t)k; 1104 } 1105 krd.c[i] = uc; 1106 } 1107 _fp_pack_word(pfpsd, &krd.i, nrd); 1108 break; 1109 case fpack32: 1110 VISINFO_KSTAT(vis_fpack32); 1111 if ((nrs1 & 1) == 1) /* fix register encoding */ 1112 nrs1 = (nrs1 & 0x1e) | 0x20; 1113 _fp_unpack_extword(pfpsd, &lrs1.ll, nrs1); 1114 if ((nrs2 & 1) == 1) 1115 nrs2 = (nrs2 & 0x1e) | 0x20; 1116 _fp_unpack_extword(pfpsd, &lrs2.ll, nrs2); 1117 1118 r = pfpsd->fp_current_read_gsr(fp); 1119 sf = (int)GSR_SCALE(r); 1120 lrd.ll = lrs1.ll << 8; 1121 for (i = 0, k = 3; i <= 1; i++, k += 4) { 1122 j = (int)lrs2.i[i]; /* preserve the sign */ 1123 l = ((int64_t)j << sf); 1124 m = l >> 23; 1125 if (m < 0) { 1126 uc = 0; 1127 } else if (m > 255) { 1128 uc = 255; 1129 } else { 1130 uc = (uchar_t)m; 1131 } 1132 lrd.c[k] = uc; 1133 } 1134 _fp_pack_extword(pfpsd, &lrd.ll, nrd); 1135 break; 1136 case fpackfix: 1137 VISINFO_KSTAT(vis_fpackfix); 1138 if ((nrs2 & 1) == 1) 1139 nrs2 = (nrs2 & 0x1e) | 0x20; 1140 _fp_unpack_extword(pfpsd, &lrs2.ll, nrs2); 1141 1142 r = pfpsd->fp_current_read_gsr(fp); 1143 sf = (int)GSR_SCALE(r); 1144 for (i = 0; i <= 1; i++) { 1145 j = (int)lrs2.i[i]; /* preserve the sign */ 1146 l = ((int64_t)j << sf); 1147 m = l >> 16; 1148 if (m < -32768) { 1149 s = -32768; 1150 } else if (m > 32767) { 1151 s = 32767; 1152 } else { 1153 s = (short)m; 1154 } 1155 krd.s[i] = s; 1156 } 1157 _fp_pack_word(pfpsd, &krd.i, nrd); 1158 break; 1159 case fexpand: 1160 VISINFO_KSTAT(vis_fexpand); 1161 _fp_unpack_word(pfpsd, &krs2.i, nrs2); 1162 for (i = 0; i <= 3; i++) { 1163 uc = krs2.c[i]; 1164 lrd.s[i] = (ushort_t)(uc << 4); 1165 } 1166 _fp_pack_extword(pfpsd, &lrd.ll, nrd); 1167 break; 1168 case fpmerge: 1169 VISINFO_KSTAT(vis_fpmerge); 1170 _fp_unpack_word(pfpsd, &krs1.i, nrs1); 1171 _fp_unpack_word(pfpsd, &krs2.i, nrs2); 1172 for (i = 0, j = 0; i <= 3; i++, j += 2) { 1173 lrd.c[j] = krs1.c[i]; 1174 lrd.c[j+1] = krs2.c[i]; 1175 } 1176 _fp_pack_extword(pfpsd, &lrd.ll, nrd); 1177 break; 1178 } 1179 return (ftt_none); 1180 } 1181 1182 /* 1183 * Simulator for pdist instruction. 1184 */ 1185 enum ftt_type 1186 vis_pdist( 1187 fp_simd_type *pfpsd, /* FPU simulator data. */ 1188 fp_inst_type pinst, /* FPU instruction to simulate. */ 1189 struct regs *pregs, /* Pointer to PCB image of registers. */ 1190 void *prw, /* Pointer to locals and ins. */ 1191 uint_t op) /* Opcode pdist or pdistn */ 1192 { 1193 uint_t nrs1, nrs2, nrd; /* Register number fields. */ 1194 int i; 1195 short s; 1196 union { 1197 uint64_t ll; 1198 uint8_t c[8]; 1199 } lrs1, lrs2, lrd; 1200 1201 nrs1 = pinst.rs1; 1202 nrs2 = pinst.rs2; 1203 nrd = pinst.rd; 1204 1205 if ((nrs1 & 1) == 1) /* fix register encoding */ 1206 nrs1 = (nrs1 & 0x1e) | 0x20; 1207 if ((nrs2 & 1) == 1) 1208 nrs2 = (nrs2 & 0x1e) | 0x20; 1209 if ((nrd & 1) == 1) 1210 nrd = (nrd & 0x1e) | 0x20; 1211 1212 _fp_unpack_extword(pfpsd, &lrs1.ll, nrs1); 1213 _fp_unpack_extword(pfpsd, &lrs2.ll, nrs2); 1214 1215 if (op == pdist) { 1216 VISINFO_KSTAT(vis_pdist); 1217 _fp_unpack_extword(pfpsd, &lrd.ll, nrd); 1218 } else { 1219 /* pdistn */ 1220 VISINFO_KSTAT(vis_pdistn); 1221 lrd.ll = 0; 1222 } 1223 1224 for (i = 0; i <= 7; i++) { 1225 s = (short)(lrs1.c[i] - lrs2.c[i]); 1226 if (s < 0) 1227 s = ~s + 1; 1228 lrd.ll += s; 1229 } 1230 1231 if (op == pdist) 1232 _fp_pack_extword(pfpsd, &lrd.ll, nrd); 1233 else 1234 /* pdistn */ 1235 (void) write_iureg(pfpsd, nrd, pregs, prw, &lrd.ll); 1236 return (ftt_none); 1237 } 1238 1239 /* 1240 * Simulator for faligndata instruction. 1241 */ 1242 static enum ftt_type 1243 vis_faligndata( 1244 fp_simd_type *pfpsd, /* FPU simulator data. */ 1245 fp_inst_type pinst, /* FPU instruction to simulate. */ 1246 kfpu_t *fp) /* Need to fp to access gsr reg */ 1247 { 1248 uint_t nrs1, nrs2, nrd; /* Register number fields. */ 1249 int i, j, k, ao; 1250 union { 1251 uint64_t ll; 1252 uint8_t c[8]; 1253 } lrs1, lrs2, lrd; 1254 uint64_t r; 1255 1256 nrs1 = pinst.rs1; 1257 nrs2 = pinst.rs2; 1258 nrd = pinst.rd; 1259 if ((nrs1 & 1) == 1) /* fix register encoding */ 1260 nrs1 = (nrs1 & 0x1e) | 0x20; 1261 if ((nrs2 & 1) == 1) 1262 nrs2 = (nrs2 & 0x1e) | 0x20; 1263 if ((nrd & 1) == 1) 1264 nrd = (nrd & 0x1e) | 0x20; 1265 1266 _fp_unpack_extword(pfpsd, &lrs1.ll, nrs1); 1267 _fp_unpack_extword(pfpsd, &lrs2.ll, nrs2); 1268 1269 r = pfpsd->fp_current_read_gsr(fp); 1270 ao = (int)GSR_ALIGN(r); 1271 1272 for (i = 0, j = ao, k = 0; i <= 7; i++) 1273 if (j <= 7) { 1274 lrd.c[i] = lrs1.c[j++]; 1275 } else { 1276 lrd.c[i] = lrs2.c[k++]; 1277 } 1278 _fp_pack_extword(pfpsd, &lrd.ll, nrd); 1279 1280 return (ftt_none); 1281 } 1282 1283 /* 1284 * Simulator for bshuffle instruction. 1285 */ 1286 static enum ftt_type 1287 vis_bshuffle( 1288 fp_simd_type *pfpsd, /* FPU simulator data. */ 1289 fp_inst_type pinst, /* FPU instruction to simulate. */ 1290 kfpu_t *fp) /* Need to fp to access gsr reg */ 1291 { 1292 uint_t nrs1, nrs2, nrd; /* Register number fields. */ 1293 int i, j, ao; 1294 union { 1295 uint64_t ll; 1296 uint8_t c[8]; 1297 } lrs1, lrs2, lrd; 1298 uint64_t r; 1299 1300 VISINFO_KSTAT(vis_bshuffle); 1301 nrs1 = pinst.rs1; 1302 nrs2 = pinst.rs2; 1303 nrd = pinst.rd; 1304 if ((nrs1 & 1) == 1) /* fix register encoding */ 1305 nrs1 = (nrs1 & 0x1e) | 0x20; 1306 if ((nrs2 & 1) == 1) 1307 nrs2 = (nrs2 & 0x1e) | 0x20; 1308 if ((nrd & 1) == 1) 1309 nrd = (nrd & 0x1e) | 0x20; 1310 1311 _fp_unpack_extword(pfpsd, &lrs1.ll, nrs1); 1312 _fp_unpack_extword(pfpsd, &lrs2.ll, nrs2); 1313 1314 r = pfpsd->fp_current_read_gsr(fp); 1315 ao = (int)GSR_MASK(r); 1316 1317 /* 1318 * BSHUFFLE Destination Byte Selection 1319 * rd Byte Source 1320 * 0 rs byte[GSR.mask<31..28>] 1321 * 1 rs byte[GSR.mask<27..24>] 1322 * 2 rs byte[GSR.mask<23..20>] 1323 * 3 rs byte[GSR.mask<19..16>] 1324 * 4 rs byte[GSR.mask<15..12>] 1325 * 5 rs byte[GSR.mask<11..8>] 1326 * 6 rs byte[GSR.mask<7..4>] 1327 * 7 rs byte[GSR.mask<3..0>] 1328 * P.S. rs1 is the upper half and rs2 is the lower half 1329 * Bytes in the source value are numbered from most to 1330 * least significant 1331 */ 1332 for (i = 7; i >= 0; i--, ao = (ao >> 4)) { 1333 j = ao & 0xf; /* get byte number */ 1334 if (j < 8) { 1335 lrd.c[i] = lrs1.c[j]; 1336 } else { 1337 lrd.c[i] = lrs2.c[j - 8]; 1338 } 1339 } 1340 _fp_pack_extword(pfpsd, &lrd.ll, nrd); 1341 1342 return (ftt_none); 1343 } 1344 1345 /* 1346 * Simulator for siam instruction. 1347 */ 1348 static enum ftt_type 1349 vis_siam( 1350 fp_simd_type *pfpsd, /* FPU simulator data. */ 1351 vis_inst_type inst, /* FPU instruction to simulate. */ 1352 kfpu_t *fp) /* Need to fp to access gsr reg */ 1353 { 1354 uint_t nrs2; /* Register number fields. */ 1355 uint64_t g, r; 1356 nrs2 = inst.rs2; 1357 1358 g = pfpsd->fp_current_read_gsr(fp); 1359 g &= ~(GSR_IM_IRND_MASK); /* zero the IM and IRND fields */ 1360 r = nrs2 & 0x7; /* get mode(3 bit) */ 1361 g |= (r << GSR_IRND_SHIFT); 1362 pfpsd->fp_current_write_gsr(g, fp); 1363 return (ftt_none); 1364 } 1365 1366 /* 1367 * Simulator for VIS loads and stores between floating-point unit and memory. 1368 */ 1369 enum ftt_type 1370 vis_fldst( 1371 fp_simd_type *pfpsd, /* FPU simulator data. */ 1372 fp_inst_type pinst, /* FPU instruction to simulate. */ 1373 struct regs *pregs, /* Pointer to PCB image of registers. */ 1374 void *prw, /* Pointer to locals and ins. */ 1375 uint_t asi) /* asi to emulate! */ 1376 { 1377 union { 1378 vis_inst_type inst; 1379 fp_inst_type pinst; 1380 } i; 1381 1382 ASSERT(USERMODE(pregs->r_tstate)); 1383 i.pinst = pinst; 1384 switch (asi) { 1385 case ASI_PST8_P: 1386 case ASI_PST8_S: 1387 case ASI_PST16_P: 1388 case ASI_PST16_S: 1389 case ASI_PST32_P: 1390 case ASI_PST32_S: 1391 case ASI_PST8_PL: 1392 case ASI_PST8_SL: 1393 case ASI_PST16_PL: 1394 case ASI_PST16_SL: 1395 case ASI_PST32_PL: 1396 case ASI_PST32_SL: 1397 return (vis_prtl_fst(pfpsd, i.inst, pregs, 1398 prw, asi)); 1399 case ASI_FL8_P: 1400 case ASI_FL8_S: 1401 case ASI_FL8_PL: 1402 case ASI_FL8_SL: 1403 case ASI_FL16_P: 1404 case ASI_FL16_S: 1405 case ASI_FL16_PL: 1406 case ASI_FL16_SL: 1407 return (vis_short_fls(pfpsd, i.inst, pregs, 1408 prw, asi)); 1409 case ASI_BLK_AIUP: 1410 case ASI_BLK_AIUS: 1411 case ASI_BLK_AIUPL: 1412 case ASI_BLK_AIUSL: 1413 case ASI_BLK_P: 1414 case ASI_BLK_S: 1415 case ASI_BLK_PL: 1416 case ASI_BLK_SL: 1417 case ASI_BLK_COMMIT_P: 1418 case ASI_BLK_COMMIT_S: 1419 return (vis_blk_fldst(pfpsd, i.inst, pregs, 1420 prw, asi)); 1421 default: 1422 return (ftt_unimplemented); 1423 } 1424 } 1425 1426 /* 1427 * Simulator for partial stores between floating-point unit and memory. 1428 */ 1429 static enum ftt_type 1430 vis_prtl_fst( 1431 fp_simd_type *pfpsd, /* FPU simulator data. */ 1432 vis_inst_type inst, /* ISE instruction to simulate. */ 1433 struct regs *pregs, /* Pointer to PCB image of registers. */ 1434 void *prw, /* Pointer to locals and ins. */ 1435 uint_t asi) /* asi to emulate! */ 1436 { 1437 uint_t nrs1, nrs2, nrd; /* Register number fields. */ 1438 uint_t opf, msk; 1439 int h, i, j; 1440 uint64_t ea, tmsk; 1441 union { 1442 freg_type f; 1443 uint64_t ll; 1444 uint32_t i[2]; 1445 uint16_t s[4]; 1446 uint8_t c[8]; 1447 } k, l, res; 1448 enum ftt_type ftt; 1449 1450 nrs1 = inst.rs1; 1451 nrs2 = inst.rs2; 1452 nrd = inst.rd; 1453 if ((nrd & 1) == 1) /* fix register encoding */ 1454 nrd = (nrd & 0x1e) | 0x20; 1455 opf = inst.opf; 1456 res.ll = 0; 1457 if ((opf & 0x100) == 0) { /* effective address = rs1 */ 1458 ftt = read_iureg(pfpsd, nrs1, pregs, prw, &ea); 1459 if (ftt != ftt_none) 1460 return (ftt); 1461 ftt = read_iureg(pfpsd, nrs2, pregs, prw, &tmsk); 1462 if (ftt != ftt_none) 1463 return (ftt); 1464 msk = (uint_t)tmsk; 1465 } else { 1466 pfpsd->fp_trapaddr = (caddr_t)pregs->r_pc; 1467 return (ftt_unimplemented); 1468 } 1469 1470 pfpsd->fp_trapaddr = (caddr_t)ea; /* setup bad addr in case we trap */ 1471 if ((ea & 0x3) != 0) 1472 return (ftt_alignment); /* Require 32 bit-alignment. */ 1473 1474 switch (asi) { 1475 case ASI_PST8_P: 1476 case ASI_PST8_S: 1477 ftt = _fp_read_extword((uint64_t *)ea, &l.ll, pfpsd); 1478 if (ftt != ftt_none) 1479 return (ftt); 1480 _fp_unpack_extword(pfpsd, &k.f.FPU_DREG_FIELD, nrd); 1481 for (i = 0, j = 0x80; i <= 7; i++, j >>= 1) { 1482 if ((msk & j) == j) 1483 res.c[i] = k.c[i]; 1484 else 1485 res.c[i] = l.c[i]; 1486 } 1487 ftt = _fp_write_extword((uint64_t *)ea, res.ll, pfpsd); 1488 if (ftt != ftt_none) 1489 return (ftt); 1490 break; 1491 case ASI_PST8_PL: /* little-endian */ 1492 case ASI_PST8_SL: 1493 ftt = _fp_read_extword((uint64_t *)ea, &l.ll, pfpsd); 1494 if (ftt != ftt_none) 1495 return (ftt); 1496 _fp_unpack_extword(pfpsd, &k.f.FPU_DREG_FIELD, nrd); 1497 for (h = 7, i = 0, j = 1; i <= 7; h--, i++, j <<= 1) { 1498 if ((msk & j) == j) 1499 res.c[i] = k.c[h]; 1500 else 1501 res.c[i] = l.c[i]; 1502 } 1503 ftt = _fp_write_extword((uint64_t *)ea, res.ll, pfpsd); 1504 if (ftt != ftt_none) 1505 return (ftt); 1506 break; 1507 case ASI_PST16_P: 1508 case ASI_PST16_S: 1509 ftt = _fp_read_extword((uint64_t *)ea, &l.ll, pfpsd); 1510 if (ftt != ftt_none) 1511 return (ftt); 1512 _fp_unpack_extword(pfpsd, &k.f.FPU_DREG_FIELD, nrd); 1513 for (i = 0, j = 0x8; i <= 3; i++, j >>= 1) { 1514 if ((msk & j) == j) 1515 res.s[i] = k.s[i]; 1516 else 1517 res.s[i] = l.s[i]; 1518 } 1519 ftt = _fp_write_extword((uint64_t *)ea, res.ll, pfpsd); 1520 if (ftt != ftt_none) 1521 return (ftt); 1522 break; 1523 case ASI_PST16_PL: 1524 case ASI_PST16_SL: 1525 ftt = _fp_read_extword((uint64_t *)ea, &l.ll, pfpsd); 1526 if (ftt != ftt_none) 1527 return (ftt); 1528 _fp_unpack_extword(pfpsd, &k.f.FPU_DREG_FIELD, nrd); 1529 for (h = 7, i = 0, j = 1; i <= 6; h -= 2, i += 2, j <<= 1) { 1530 if ((msk & j) == j) { 1531 res.c[i] = k.c[h]; 1532 res.c[i+1] = k.c[h-1]; 1533 } else { 1534 res.c[i] = l.c[i]; 1535 res.c[i+1] = l.c[i+1]; 1536 } 1537 } 1538 ftt = _fp_write_extword((uint64_t *)ea, res.ll, pfpsd); 1539 if (ftt != ftt_none) 1540 return (ftt); 1541 break; 1542 case ASI_PST32_P: 1543 case ASI_PST32_S: 1544 ftt = _fp_read_extword((uint64_t *)ea, &l.ll, pfpsd); 1545 if (ftt != ftt_none) 1546 return (ftt); 1547 _fp_unpack_extword(pfpsd, &k.f.FPU_DREG_FIELD, nrd); 1548 for (i = 0, j = 0x2; i <= 1; i++, j >>= 1) { 1549 if ((msk & j) == j) 1550 res.i[i] = k.i[i]; 1551 else 1552 res.i[i] = l.i[i]; 1553 } 1554 ftt = _fp_write_extword((uint64_t *)ea, res.ll, pfpsd); 1555 if (ftt != ftt_none) 1556 return (ftt); 1557 break; 1558 case ASI_PST32_PL: 1559 case ASI_PST32_SL: 1560 ftt = _fp_read_extword((uint64_t *)ea, &l.ll, pfpsd); 1561 if (ftt != ftt_none) 1562 return (ftt); 1563 _fp_unpack_extword(pfpsd, &k.f.FPU_DREG_FIELD, nrd); 1564 for (h = 7, i = 0, j = 1; i <= 4; h -= 4, i += 4, j <<= 1) { 1565 if ((msk & j) == j) { 1566 res.c[i] = k.c[h]; 1567 res.c[i+1] = k.c[h-1]; 1568 res.c[i+2] = k.c[h-2]; 1569 res.c[i+3] = k.c[h-3]; 1570 } else { 1571 res.c[i] = l.c[i]; 1572 res.c[i+1] = l.c[i+1]; 1573 res.c[i+2] = l.c[i+2]; 1574 res.c[i+3] = l.c[i+3]; 1575 } 1576 } 1577 ftt = _fp_write_extword((uint64_t *)ea, res.ll, pfpsd); 1578 if (ftt != ftt_none) 1579 return (ftt); 1580 break; 1581 } 1582 1583 pregs->r_pc = pregs->r_npc; /* Do not retry emulated instruction. */ 1584 pregs->r_npc += 4; 1585 return (ftt_none); 1586 } 1587 1588 /* 1589 * Simulator for short load/stores between floating-point unit and memory. 1590 */ 1591 static enum ftt_type 1592 vis_short_fls( 1593 fp_simd_type *pfpsd, /* FPU simulator data. */ 1594 vis_inst_type inst, /* ISE instruction to simulate. */ 1595 struct regs *pregs, /* Pointer to PCB image of registers. */ 1596 void *prw, /* Pointer to locals and ins. */ 1597 uint_t asi) /* asi to emulate! */ 1598 { 1599 uint_t nrs1, nrs2, nrd; /* Register number fields. */ 1600 uint_t opf; 1601 uint64_t ea, tea; 1602 union { 1603 freg_type f; 1604 uint64_t ll; 1605 uint32_t i[2]; 1606 uint16_t s[4]; 1607 uint8_t c[8]; 1608 } k; 1609 union { 1610 vis_inst_type inst; 1611 int i; 1612 } fp; 1613 enum ftt_type ftt = ftt_none; 1614 ushort_t us; 1615 uchar_t uc; 1616 1617 nrs1 = inst.rs1; 1618 nrs2 = inst.rs2; 1619 nrd = inst.rd; 1620 if ((nrd & 1) == 1) /* fix register encoding */ 1621 nrd = (nrd & 0x1e) | 0x20; 1622 opf = inst.opf; 1623 fp.inst = inst; 1624 if ((opf & 0x100) == 0) { /* effective address = rs1 + rs2 */ 1625 ftt = read_iureg(pfpsd, nrs1, pregs, prw, &ea); 1626 if (ftt != ftt_none) 1627 return (ftt); 1628 ftt = read_iureg(pfpsd, nrs2, pregs, prw, &tea); 1629 if (ftt != ftt_none) 1630 return (ftt); 1631 ea += tea; 1632 } else { /* effective address = rs1 + imm13 */ 1633 fp.inst = inst; 1634 ea = (fp.i << 19) >> 19; /* Extract simm13 field. */ 1635 ftt = read_iureg(pfpsd, nrs1, pregs, prw, &tea); 1636 if (ftt != ftt_none) 1637 return (ftt); 1638 ea += tea; 1639 } 1640 if (get_udatamodel() == DATAMODEL_ILP32) 1641 ea = (uint64_t)(caddr32_t)ea; 1642 1643 pfpsd->fp_trapaddr = (caddr_t)ea; /* setup bad addr in case we trap */ 1644 switch (asi) { 1645 case ASI_FL8_P: 1646 case ASI_FL8_S: 1647 case ASI_FL8_PL: /* little-endian */ 1648 case ASI_FL8_SL: 1649 if ((inst.op3 & 7) == 3) { /* load byte */ 1650 if (fuword8((void *)ea, &uc) == -1) 1651 return (ftt_fault); 1652 k.ll = 0; 1653 k.c[7] = uc; 1654 _fp_pack_extword(pfpsd, &k.f.FPU_DREG_FIELD, nrd); 1655 } else { /* store byte */ 1656 _fp_unpack_extword(pfpsd, &k.f.FPU_DREG_FIELD, nrd); 1657 uc = k.c[7]; 1658 if (subyte((caddr_t)ea, uc) == -1) 1659 return (ftt_fault); 1660 } 1661 break; 1662 case ASI_FL16_P: 1663 case ASI_FL16_S: 1664 if ((ea & 1) == 1) 1665 return (ftt_alignment); 1666 if ((inst.op3 & 7) == 3) { /* load short */ 1667 if (fuword16((void *)ea, &us) == -1) 1668 return (ftt_fault); 1669 k.ll = 0; 1670 k.s[3] = us; 1671 _fp_pack_extword(pfpsd, &k.f.FPU_DREG_FIELD, nrd); 1672 } else { /* store short */ 1673 _fp_unpack_extword(pfpsd, &k.f.FPU_DREG_FIELD, nrd); 1674 us = k.s[3]; 1675 if (suword16((caddr_t)ea, us) == -1) 1676 return (ftt_fault); 1677 } 1678 break; 1679 case ASI_FL16_PL: /* little-endian */ 1680 case ASI_FL16_SL: 1681 if ((ea & 1) == 1) 1682 return (ftt_alignment); 1683 if ((inst.op3 & 7) == 3) { /* load short */ 1684 if (fuword16((void *)ea, &us) == -1) 1685 return (ftt_fault); 1686 k.ll = 0; 1687 k.c[6] = (uchar_t)us; 1688 k.c[7] = (uchar_t)((us & 0xff00) >> 8); 1689 _fp_pack_extword(pfpsd, &k.f.FPU_DREG_FIELD, nrd); 1690 } else { /* store short */ 1691 _fp_unpack_extword(pfpsd, &k.f.FPU_DREG_FIELD, nrd); 1692 uc = k.c[7]; 1693 us = (ushort_t)((uc << 8) | k.c[6]); 1694 if (suword16((void *)ea, us) == -1) 1695 return (ftt_fault); 1696 } 1697 break; 1698 } 1699 1700 pregs->r_pc = pregs->r_npc; /* Do not retry emulated instruction. */ 1701 pregs->r_npc += 4; 1702 return (ftt_none); 1703 } 1704 1705 /* 1706 * Simulator for block loads and stores between floating-point unit and memory. 1707 * We pass the addrees of ea to sync_data_memory() to flush the Ecache. 1708 * Sync_data_memory() calls platform dependent code to flush the Ecache. 1709 */ 1710 static enum ftt_type 1711 vis_blk_fldst( 1712 fp_simd_type *pfpsd, /* FPU simulator data. */ 1713 vis_inst_type inst, /* ISE instruction to simulate. */ 1714 struct regs *pregs, /* Pointer to PCB image of registers. */ 1715 void *prw, /* Pointer to locals and ins. */ 1716 uint_t asi) /* asi to emulate! */ 1717 { 1718 uint_t nrs1, nrs2, nrd; /* Register number fields. */ 1719 uint_t opf, h, i, j; 1720 uint64_t ea, tea; 1721 union { 1722 freg_type f; 1723 uint64_t ll; 1724 uint8_t c[8]; 1725 } k, l; 1726 union { 1727 vis_inst_type inst; 1728 int32_t i; 1729 } fp; 1730 enum ftt_type ftt; 1731 boolean_t little_endian = B_FALSE; 1732 1733 nrs1 = inst.rs1; 1734 nrs2 = inst.rs2; 1735 nrd = inst.rd; 1736 if ((nrd & 1) == 1) /* fix register encoding */ 1737 nrd = (nrd & 0x1e) | 0x20; 1738 1739 /* ensure register is 8-double precision aligned */ 1740 if ((nrd & 0xf) != 0) 1741 return (ftt_unimplemented); 1742 1743 opf = inst.opf; 1744 if ((opf & 0x100) == 0) { /* effective address = rs1 + rs2 */ 1745 ftt = read_iureg(pfpsd, nrs1, pregs, prw, &ea); 1746 if (ftt != ftt_none) 1747 return (ftt); 1748 ftt = read_iureg(pfpsd, nrs2, pregs, prw, &tea); 1749 if (ftt != ftt_none) 1750 return (ftt); 1751 ea += tea; 1752 } else { /* effective address = rs1 + imm13 */ 1753 fp.inst = inst; 1754 ea = (fp.i << 19) >> 19; /* Extract simm13 field. */ 1755 ftt = read_iureg(pfpsd, nrs1, pregs, prw, &tea); 1756 if (ftt != ftt_none) 1757 return (ftt); 1758 ea += tea; 1759 } 1760 if ((ea & 0x3F) != 0) /* Require 64 byte-alignment. */ 1761 return (ftt_alignment); 1762 1763 pfpsd->fp_trapaddr = (caddr_t)ea; /* setup bad addr in case we trap */ 1764 switch (asi) { 1765 case ASI_BLK_AIUPL: 1766 case ASI_BLK_AIUSL: 1767 case ASI_BLK_PL: 1768 case ASI_BLK_SL: 1769 little_endian = B_TRUE; 1770 /* FALLTHROUGH */ 1771 case ASI_BLK_AIUP: 1772 case ASI_BLK_AIUS: 1773 case ASI_BLK_P: 1774 case ASI_BLK_S: 1775 case ASI_BLK_COMMIT_P: 1776 case ASI_BLK_COMMIT_S: 1777 if ((inst.op3 & 7) == 3) { /* lddf */ 1778 for (i = 0; i < 8; i++, nrd += 2) { 1779 ftt = _fp_read_extword((uint64_t *)ea, &k.ll, 1780 pfpsd); 1781 if (ftt != ftt_none) 1782 return (ftt); 1783 if (little_endian) { 1784 for (j = 0, h = 7; j < 8; j++, h--) 1785 l.c[h] = k.c[j]; 1786 k.ll = l.ll; 1787 } 1788 _fp_pack_extword(pfpsd, &k.f.FPU_DREG_FIELD, 1789 nrd); 1790 ea += 8; 1791 } 1792 } else { /* stdf */ 1793 for (i = 0; i < 8; i++, nrd += 2) { 1794 _fp_unpack_extword(pfpsd, &k.f.FPU_DREG_FIELD, 1795 nrd); 1796 if (little_endian) { 1797 for (j = 0, h = 7; j < 8; j++, h--) 1798 l.c[h] = k.c[j]; 1799 k.ll = l.ll; 1800 } 1801 ftt = _fp_write_extword((uint64_t *)ea, k.ll, 1802 pfpsd); 1803 if (ftt != ftt_none) 1804 return (ftt); 1805 ea += 8; 1806 } 1807 } 1808 if ((asi == ASI_BLK_COMMIT_P) || (asi == ASI_BLK_COMMIT_S)) 1809 sync_data_memory((caddr_t)(ea - 64), 64); 1810 break; 1811 default: 1812 /* addr of unimp inst */ 1813 pfpsd->fp_trapaddr = (caddr_t)pregs->r_pc; 1814 return (ftt_unimplemented); 1815 } 1816 1817 pregs->r_pc = pregs->r_npc; /* Do not retry emulated instruction. */ 1818 pregs->r_npc += 4; 1819 return (ftt_none); 1820 } 1821 1822 /* 1823 * Simulator for rd %gsr instruction. 1824 */ 1825 enum ftt_type 1826 vis_rdgsr( 1827 fp_simd_type *pfpsd, /* FPU simulator data. */ 1828 fp_inst_type pinst, /* FPU instruction to simulate. */ 1829 struct regs *pregs, /* Pointer to PCB image of registers. */ 1830 void *prw, /* Pointer to locals and ins. */ 1831 kfpu_t *fp) /* Need to fp to access gsr reg */ 1832 { 1833 uint_t nrd; 1834 uint64_t r; 1835 enum ftt_type ftt = ftt_none; 1836 1837 nrd = pinst.rd; 1838 1839 r = pfpsd->fp_current_read_gsr(fp); 1840 ftt = write_iureg(pfpsd, nrd, pregs, prw, &r); 1841 pregs->r_pc = pregs->r_npc; /* Do not retry emulated instruction. */ 1842 pregs->r_npc += 4; 1843 return (ftt); 1844 } 1845 1846 /* 1847 * Simulator for wr %gsr instruction. 1848 */ 1849 enum ftt_type 1850 vis_wrgsr( 1851 fp_simd_type *pfpsd, /* FPU simulator data. */ 1852 fp_inst_type pinst, /* FPU instruction to simulate. */ 1853 struct regs *pregs, /* Pointer to PCB image of registers. */ 1854 void *prw, /* Pointer to locals and ins. */ 1855 kfpu_t *fp) /* Need to fp to access gsr reg */ 1856 { 1857 uint_t nrs1; 1858 uint64_t r, r1, r2; 1859 enum ftt_type ftt = ftt_none; 1860 1861 nrs1 = pinst.rs1; 1862 ftt = read_iureg(pfpsd, nrs1, pregs, prw, &r1); 1863 if (ftt != ftt_none) 1864 return (ftt); 1865 if (pinst.ibit == 0) { /* copy the value in r[rs2] */ 1866 uint_t nrs2; 1867 1868 nrs2 = pinst.rs2; 1869 ftt = read_iureg(pfpsd, nrs2, pregs, prw, &r2); 1870 if (ftt != ftt_none) 1871 return (ftt); 1872 } else { /* use sign_ext(simm13) */ 1873 union { 1874 fp_inst_type inst; 1875 uint32_t i; 1876 } fp; 1877 1878 fp.inst = pinst; /* Extract simm13 field */ 1879 r2 = (fp.i << 19) >> 19; 1880 } 1881 r = r1 ^ r2; 1882 pfpsd->fp_current_write_gsr(r, fp); 1883 pregs->r_pc = pregs->r_npc; /* Do not retry emulated instruction. */ 1884 pregs->r_npc += 4; 1885 return (ftt); 1886 } 1887 1888 /* 1889 * This is the loadable module wrapper. 1890 */ 1891 #include <sys/errno.h> 1892 #include <sys/modctl.h> 1893 1894 /* 1895 * Module linkage information for the kernel. 1896 */ 1897 extern struct mod_ops mod_miscops; 1898 1899 static struct modlmisc modlmisc = { 1900 &mod_miscops, 1901 "vis fp simulation", 1902 }; 1903 1904 static struct modlinkage modlinkage = { 1905 MODREV_1, (void *)&modlmisc, NULL 1906 }; 1907 1908 int 1909 _init(void) 1910 { 1911 return (mod_install(&modlinkage)); 1912 } 1913 1914 int 1915 _info(struct modinfo *modinfop) 1916 { 1917 return (mod_info(&modlinkage, modinfop)); 1918 } 1919