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