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