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