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