1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*
  22  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  23  * Use is subject to license terms.
  24  */
  25 
  26 #ifndef _SYS_FPU_FPU_SIMULATOR_H
  27 #define _SYS_FPU_FPU_SIMULATOR_H
  28 
  29 /* SunOS-4.0 1.10       */
  30 
  31 /*
  32  * sparc floating-point simulator definitions.
  33  */
  34 
  35 #ifndef _ASM
  36 #include <sys/types.h>
  37 #include <sys/ieeefp.h>
  38 #include <vm/seg.h>
  39 #include <sys/kstat.h>
  40 #endif /* _ASM */
  41 
  42 #ifdef  __cplusplus
  43 extern "C" {
  44 #endif
  45 
  46 /*
  47  * Constants to decode/extract "fitos" instruction fields
  48  */
  49 #define FITOS_INSTR_MASK        0xc1f83fe0
  50 #define FITOS_INSTR             0x81a01880
  51 #define FITOS_RS2_SHIFT         0
  52 #define FITOS_RD_SHIFT          25
  53 #define FITOS_REG_MASK          0x1f
  54 
  55 #ifndef _ASM
  56 /*      PUBLIC TYPES    */
  57 
  58 enum fcc_type {                 /* relationships */
  59         fcc_equal       = 0,
  60         fcc_less        = 1,
  61         fcc_greater     = 2,
  62         fcc_unordered   = 3
  63 };
  64 
  65 enum cc_type {                  /* icc/fcc number */
  66         fcc_0   = 0,
  67         fcc_1   = 1,
  68         fcc_2   = 2,
  69         fcc_3   = 3,
  70         icc     = 4,
  71         xcc     = 6
  72 };
  73 
  74 /* FSR types. */
  75 
  76 enum ftt_type {                 /* types of traps */
  77         ftt_none        = 0,
  78         ftt_ieee        = 1,
  79         ftt_unfinished  = 2,
  80         ftt_unimplemented = 3,
  81         ftt_sequence    = 4,
  82         ftt_alignment   = 5,    /* defined by software convention only */
  83         ftt_fault       = 6,    /* defined by software convention only */
  84         ftt_7           = 7
  85 };
  86 
  87 typedef struct {                /* sparc V9 FSR. */
  88         unsigned int                    : 26;
  89         unsigned int            fcc3    : 2;    /* fp condition code 3 */
  90         unsigned int            fcc2    : 2;    /* fp condition code 2 */
  91         unsigned int            fcc1    : 2;    /* fp condition code 1 */
  92                                                 /* enum fp_direction_type */
  93         unsigned int            rnd     : 2;    /* rounding direction */
  94         unsigned int            rnp     : 2;    /* for v7 compatibility only */
  95         unsigned int            tem     : 5;    /* trap enable mask */
  96         unsigned int             ns     : 1;    /* non-standard */
  97         unsigned int                    : 5;
  98                                                 /* enum ftt_type */
  99         unsigned int            ftt     : 3;    /* FPU trap type */
 100         unsigned int            qne     : 1;    /* FPQ not empty */
 101         unsigned int             pr     : 1;    /* partial result */
 102                                                 /* enum fcc_type */
 103         unsigned int            fcc     : 2;    /* fp condition code 0 */
 104         unsigned int            aexc    : 5;    /* accumulated exceptions */
 105         unsigned int            cexc    : 5;    /* current exception */
 106 } fsr_types;
 107 
 108 /*
 109  * The C compiler and the C spec do not support bitfields in a long long,
 110  * as per fsr_types above, so don't hold your breath waiting for this
 111  * workaround cruft to disappear.
 112  */
 113 
 114 typedef union {
 115         fsr_types       fsr;
 116         uint64_t        ll;
 117 } fsr_type;
 118 
 119 #define fcc3    fsr.fcc3
 120 #define fcc2    fsr.fcc2
 121 #define fcc1    fsr.fcc1
 122 #define fcc0    fsr.fcc
 123 #define rnd     fsr.rnd
 124 #define rnp     fsr.rnp
 125 #define tem     fsr.tem
 126 #define aexc    fsr.aexc
 127 #define cexc    fsr.cexc
 128 
 129 typedef                 /* FPU register viewed as single components. */
 130         struct {
 131         uint32_t sign :         1;
 132         uint32_t exponent :     8;
 133         uint32_t significand : 23;
 134 } single_type;
 135 
 136 typedef                 /* FPU register viewed as double components. */
 137         struct {
 138         uint32_t sign :         1;
 139         uint32_t exponent :    11;
 140         uint32_t significand : 20;
 141 } double_type;
 142 
 143 typedef                 /* FPU register viewed as extended components. */
 144         struct {
 145         uint32_t sign :          1;
 146         uint32_t exponent :     15;
 147         uint32_t significand :  16;
 148 } extended_type;
 149 
 150 typedef                 /* FPU register with multiple data views. */
 151         union {
 152         int32_t         int32_reg;
 153         int64_t         int64_reg;
 154         uint32_t        uint32_reg;
 155         uint64_t        uint64_reg;
 156         float           float_reg;
 157         single_type     single_reg;
 158         double_type     double_reg;
 159         extended_type   extended_reg;
 160 } freg_type;
 161 
 162 enum fp_op_type {               /* Type specifiers in FPU instructions. */
 163         fp_op_int32     = 0,    /* Not in hardware, but convenient to define. */
 164         fp_op_single    = 1,
 165         fp_op_double    = 2,
 166         fp_op_extended  = 3,
 167         fp_op_int64     = 4
 168 };
 169 
 170 enum fp_opcode {        /* FPU op codes, minus precision and leading 0. */
 171         fmovs           = 0x0,
 172         fnegs           = 0x1,
 173         fabss           = 0x2,
 174         fp_op_3 = 3, fp_op_4 = 4, fp_op_5 = 5, fp_op_6 = 6, fp_op_7 = 7,
 175         fp_op_8         = 0x8,
 176         fp_op_9         = 0x9,
 177         fsqrt           = 0xa,
 178         fp_op_b = 0xb, fp_op_c = 0xc, fp_op_d = 0xd,
 179         fp_op_e = 0xe, fp_op_f = 0xf,
 180         fadd            = 0x10,
 181         fsub            = 0x11,
 182         fmul            = 0x12,
 183         fdiv            = 0x13,
 184         fcmp            = 0x14,
 185         fcmpe           = 0x15,
 186         fp_op_16 = 0x16, fp_op_17 = 0x17,
 187         fp_op_18        = 0x18,
 188         fp_op_19        = 0x19,
 189         fsmuld          = 0x1a,
 190         fdmulx          = 0x1b,
 191         ftoll           = 0x20,
 192         flltos          = 0x21,
 193         flltod          = 0x22,
 194         flltox          = 0x23,
 195         fp_op_24 = 0x24, fp_op_25 = 0x25, fp_op_26 = 0x26, fp_op_27 = 0x27,
 196         fp_op_28 = 0x28, fp_op_29 = 0x29, fp_op_2a = 0x2a, fp_op_2b = 0x2b,
 197         fp_op_2c = 0x2c, fp_op_2d = 0x2d, fp_op_2e = 0x2e, fp_op_2f = 0x2f,
 198         fp_op_30        = 0x30,
 199         fitos           = 0x31,
 200         fitod           = 0x32,
 201         fitox           = 0x33,
 202         ftoi            = 0x34,
 203         fp_op_35 = 0x35, fp_op_36 = 0x36, fp_op_37 = 0x37,
 204         ft_op_38        = 0x38,
 205         fp_op_39 = 0x39, fp_op_3a = 0x3a, fp_op_3b = 0x3b,
 206         fp_op_3c        = 0x3c,
 207         fp_op_3d = 0x3d, fp_op_3e = 0x3e, fp_op_3f = 0x3f
 208 };
 209 
 210 typedef                 /* FPU instruction. */
 211         struct {
 212         uint32_t                hibits  : 2;    /* Top two bits. */
 213         uint32_t                rd      : 5;    /* Destination. */
 214         uint32_t                op3     : 6;    /* Main op code. */
 215         uint32_t                rs1     : 5;    /* First operand. */
 216         uint32_t                ibit    : 1;    /* I format bit. */
 217         uint32_t /* enum fp_opcode */  opcode : 6; /* Floating-point op code. */
 218         uint32_t /* enum fp_op_type */ prec   : 2; /* Precision. */
 219         uint32_t                rs2     : 5;    /* Second operand. */
 220 } fp_inst_type;
 221 
 222 enum fp_op_fma_var {    /* IMPDEP2B FMA-fused instr. variations */
 223         fmadd   =       0,
 224         fmsub   =       1,
 225         fnmsub  =       2,
 226         fnmadd  =       3
 227 };
 228 
 229 typedef         /* IMPDEP2B FPU FMA-fused instruction. */
 230         struct {
 231         uint32_t                hibits  : 2;    /* Top two bits. */
 232         uint32_t                rd      : 5;    /* Destination. */
 233         uint32_t                op3     : 6;    /* Main op code. */
 234         uint32_t                rs1     : 5;    /* First operand. */
 235         uint32_t                rs3     : 5;    /* Third operand */
 236         uint32_t /* enum fp_op_fma_var */ var : 2; /* Instr. variation */
 237         uint32_t                sz      : 2;    /* Size */
 238         uint32_t                rs2     : 5;    /* Second operand. */
 239 } fp_fma_inst_type;
 240 
 241 typedef                 /* Integer condition code. */
 242         struct {
 243         uint32_t                        : 28;   /* the unused part */
 244         uint32_t                n       : 1;    /* Negative bit. */
 245         uint32_t                z       : 1;    /* Zero bit. */
 246         uint32_t                v       : 1;    /* Overflow bit. */
 247         uint32_t                c       : 1;    /* Carry bit. */
 248 } ccr_type;
 249 
 250 typedef                 /* FPU data used by simulator. */
 251         struct {
 252         uint_t                  fp_fsrtem;
 253         enum fp_direction_type  fp_direction;
 254         enum fp_precision_type  fp_precision;
 255         uint_t                  fp_current_exceptions;
 256         kfpu_t                  *fp_current_pfregs;
 257         void                    (*fp_current_read_freg) ();
 258         void                    (*fp_current_write_freg) ();
 259         void                    (*fp_current_read_dreg) ();
 260         void                    (*fp_current_write_dreg) ();
 261         uint64_t                (*fp_current_read_gsr) (kfpu_t *);
 262         void                    (*fp_current_write_gsr) (uint64_t, kfpu_t *);
 263         int                     fp_trapcode;
 264         char                    *fp_trapaddr;
 265         struct  regs            *fp_traprp;
 266         enum    seg_rw          fp_traprw;
 267 } fp_simd_type;
 268 
 269 /*
 270  * FPU related kstat structures
 271  */
 272 struct fpustat_kstat  {
 273         struct kstat_named              fpu_ieee_traps;
 274         struct kstat_named              fpu_unfinished_traps;
 275         struct kstat_named              fpu_unimplemented_traps;
 276 };
 277 
 278 struct fpuinfo_kstat {
 279         struct kstat_named              fpu_sim_fmovs;
 280         struct kstat_named              fpu_sim_fmovd;
 281         struct kstat_named              fpu_sim_fmovq;
 282         struct kstat_named              fpu_sim_fnegs;
 283         struct kstat_named              fpu_sim_fnegd;
 284         struct kstat_named              fpu_sim_fnegq;
 285         struct kstat_named              fpu_sim_fabss;
 286         struct kstat_named              fpu_sim_fabsd;
 287         struct kstat_named              fpu_sim_fabsq;
 288         struct kstat_named              fpu_sim_fsqrts;
 289         struct kstat_named              fpu_sim_fsqrtd;
 290         struct kstat_named              fpu_sim_fsqrtq;
 291         struct kstat_named              fpu_sim_fadds;
 292         struct kstat_named              fpu_sim_faddd;
 293         struct kstat_named              fpu_sim_faddq;
 294         struct kstat_named              fpu_sim_fsubs;
 295         struct kstat_named              fpu_sim_fsubd;
 296         struct kstat_named              fpu_sim_fsubq;
 297         struct kstat_named              fpu_sim_fmuls;
 298         struct kstat_named              fpu_sim_fmuld;
 299         struct kstat_named              fpu_sim_fmulq;
 300         struct kstat_named              fpu_sim_fdivs;
 301         struct kstat_named              fpu_sim_fdivd;
 302         struct kstat_named              fpu_sim_fdivq;
 303         struct kstat_named              fpu_sim_fcmps;
 304         struct kstat_named              fpu_sim_fcmpd;
 305         struct kstat_named              fpu_sim_fcmpq;
 306         struct kstat_named              fpu_sim_fcmpes;
 307         struct kstat_named              fpu_sim_fcmped;
 308         struct kstat_named              fpu_sim_fcmpeq;
 309         struct kstat_named              fpu_sim_fsmuld;
 310         struct kstat_named              fpu_sim_fdmulx;
 311         struct kstat_named              fpu_sim_fstox;
 312         struct kstat_named              fpu_sim_fdtox;
 313         struct kstat_named              fpu_sim_fqtox;
 314         struct kstat_named              fpu_sim_fxtos;
 315         struct kstat_named              fpu_sim_fxtod;
 316         struct kstat_named              fpu_sim_fxtoq;
 317         struct kstat_named              fpu_sim_fitos;
 318         struct kstat_named              fpu_sim_fitod;
 319         struct kstat_named              fpu_sim_fitoq;
 320         struct kstat_named              fpu_sim_fstoi;
 321         struct kstat_named              fpu_sim_fdtoi;
 322         struct kstat_named              fpu_sim_fqtoi;
 323         struct kstat_named              fpu_sim_fmovcc;
 324         struct kstat_named              fpu_sim_fmovr;
 325         struct kstat_named              fpu_sim_fmadds;
 326         struct kstat_named              fpu_sim_fmaddd;
 327         struct kstat_named              fpu_sim_fmsubs;
 328         struct kstat_named              fpu_sim_fmsubd;
 329         struct kstat_named              fpu_sim_fnmadds;
 330         struct kstat_named              fpu_sim_fnmaddd;
 331         struct kstat_named              fpu_sim_fnmsubs;
 332         struct kstat_named              fpu_sim_fnmsubd;
 333         struct kstat_named              fpu_sim_invalid;
 334 };
 335 
 336 struct visinfo_kstat {
 337         struct kstat_named              vis_edge8;
 338         struct kstat_named              vis_edge8n;
 339         struct kstat_named              vis_edge8l;
 340         struct kstat_named              vis_edge8ln;
 341         struct kstat_named              vis_edge16;
 342         struct kstat_named              vis_edge16n;
 343         struct kstat_named              vis_edge16l;
 344         struct kstat_named              vis_edge16ln;
 345         struct kstat_named              vis_edge32;
 346         struct kstat_named              vis_edge32n;
 347         struct kstat_named              vis_edge32l;
 348         struct kstat_named              vis_edge32ln;
 349         struct kstat_named              vis_array8;
 350         struct kstat_named              vis_array16;
 351         struct kstat_named              vis_array32;
 352         struct kstat_named              vis_bmask;
 353         struct kstat_named              vis_fcmple16;
 354         struct kstat_named              vis_fcmpne16;
 355         struct kstat_named              vis_fcmpgt16;
 356         struct kstat_named              vis_fcmpeq16;
 357         struct kstat_named              vis_fcmple32;
 358         struct kstat_named              vis_fcmpne32;
 359         struct kstat_named              vis_fcmpgt32;
 360         struct kstat_named              vis_fcmpeq32;
 361         struct kstat_named              vis_fmul8x16;
 362         struct kstat_named              vis_fmul8x16au;
 363         struct kstat_named              vis_fmul8x16al;
 364         struct kstat_named              vis_fmul8sux16;
 365         struct kstat_named              vis_fmul8ulx16;
 366         struct kstat_named              vis_fmuld8sux16;
 367         struct kstat_named              vis_fmuld8ulx16;
 368         struct kstat_named              vis_fpack16;
 369         struct kstat_named              vis_fpack32;
 370         struct kstat_named              vis_fpackfix;
 371         struct kstat_named              vis_fexpand;
 372         struct kstat_named              vis_fpmerge;
 373         struct kstat_named              vis_pdist;
 374         struct kstat_named              vis_pdistn;
 375         struct kstat_named              vis_bshuffle;
 376 };
 377 
 378 #define VISINFO_KSTAT(opcode)   {                                       \
 379         extern void __dtrace_probe___visinfo_##opcode(uint64_t *);      \
 380         uint64_t *stataddr = &visinfo.opcode.value.ui64;            \
 381         __dtrace_probe___visinfo_##opcode(stataddr);                    \
 382         atomic_add_64(&visinfo.opcode.value.ui64, 1);                       \
 383 }
 384 
 385 
 386 /* PUBLIC FUNCTIONS */
 387 
 388 #ifdef  __STDC__
 389 
 390 /*
 391  * fpu_vis_sim simulates FPU VIS Partial load store instructions; reads and
 392  * writes FPU data registers directly or works with the PCB image if fpu_exists
 393  * is 0.
 394  */
 395 extern enum ftt_type fpu_vis_sim(fp_simd_type *pfpsd, fp_inst_type *pinst,
 396         struct regs *pregs, fsr_type *pfsr, uint64_t gsr, uint32_t inst);
 397 /*
 398  * fpu_simulator simulates FPU instructions only; reads and writes FPU data
 399  * registers directly.
 400  */
 401 extern enum ftt_type fpu_simulator(fp_simd_type *pfpsd, fp_inst_type *pinst,
 402         fsr_type *pfsr, uint64_t gsr, uint32_t inst);
 403 /*
 404  * fp_emulator simulates FPU and CPU-FPU instructions; reads and writes FPU
 405  * data registers from image in pfpu.
 406  */
 407 extern enum ftt_type fp_emulator(fp_simd_type *pfpsd, fp_inst_type *pinst,
 408         struct regs *rp, void *prw, kfpu_t *pfpu);
 409 /*
 410  * fp_traps handles passing exception conditions to the kernel.
 411  * It is called after fp_simulator or fp_emulator fail (return a non-zero ftt).
 412  */
 413 extern void fp_traps(fp_simd_type *pfpsd, enum ftt_type ftt, struct regs *rp);
 414 
 415 /*
 416  * fp_kstat_update tracks fpu exception conditions.
 417  * It is called after a hardware trap returns a non-zero ftt.
 418  */
 419 extern void fp_kstat_update(enum ftt_type ftt);
 420 
 421 /*
 422  * fp_precise handles floating point unimplemented and unfinished traps,
 423  * for sparc V9 hardware. These traps are normally passed along to the
 424  * fpu_simulator, to see if it can run the unimplemented instruction or
 425  * finish the unfinished instruction. Needless to say, this takes time.
 426  */
 427 extern void fp_precise(struct regs *rp);
 428 
 429 /*
 430  * fpu_trap handles V9 floating point ieee and other floating point traps.
 431  * It is called after fp_simulator or fp_emulator fail (return a non-zero ftt),
 432  * and from the _fp_ieee_exception trap handler.
 433  */
 434 extern void fpu_trap(struct regs *rp, caddr_t addr, uint32_t type,
 435                         uint32_t code);
 436 
 437 #else   /* ! __STDC__ */
 438 
 439 /*
 440  * fpu_simulator simulates FPU instructions only; reads and writes FPU data
 441  * registers directly.
 442  */
 443 extern enum ftt_type fpu_simulator(
 444         fp_simd_type    *pfpsd,  /* Pointer to FPU simulator data */
 445         fp_inst_type    *pinst,  /* Pointer to FPU instruction to simulate. */
 446         fsr_type        *pfsr,   /* Pointer to image of FSR to read & write. */
 447         int             instr);  /* Instruction to emulate. */
 448 
 449 /*
 450  * fp_emulator simulates FPU and CPU-FPU instructions; reads and writes FPU
 451  * data registers from image in pfpu.
 452  */
 453 extern enum ftt_type fp_emulator(
 454         fp_simd_type    *pfpsd,    /* Pointer to FPU simulator data */
 455         fp_inst_type    *pinst,    /* Pointer to FPU instruction to simulate. */
 456         struct regs     *pregs,    /* Pointer to PCB image of registers. */
 457         struct rwindow  *pwindow,  /* Pointer to locals and ins. */
 458         struct fpu      *pfpu);    /* Pointer to FPU register block. */
 459 
 460 /*
 461  * fp_traps handles passing exception conditions to the kernel.
 462  * It is called after fp_simulator or fp_emulator fail (return a non-zero ftt).
 463  */
 464 extern void fp_traps(
 465         fp_simd_type    *pfpsd,  /* Pointer to FPU simulator data */
 466         enum ftt_type   ftt,     /* Type of trap. */
 467         struct regs     *rp);    /* Pointer to PCB image of registers. */
 468 
 469 /*
 470  * fp_kstat_update tracks fpu exception conditions.
 471  * It is called after a hardware trap returns a non-zero ftt.
 472  */
 473 extern void fp_kstat_update(enum ftt_type ftt); /* Type of trap. */
 474 
 475 /*
 476  * fp_precise handles floating point unimplemented and unfinished traps,
 477  * for sparc V9 hardware. These traps are normally passed along to the
 478  * fpu_simulator, to see if it can run the unimplemented instruction or
 479  * finish the unfinished instruction. Needless to say, this takes time.
 480  */
 481 extern void fp_precise(
 482         struct regs *rp);       /* Pointer to PCB image of registers. */
 483 
 484 /*
 485  * fpu_trap handles V9 floating point ieee and other floating point traps.
 486  * It is called after fp_simulator or fp_emulator fail (return a non-zero ftt),
 487  * and from the _fp_ieee_exception trap handler.
 488  */
 489 extern void fpu_trap(
 490         struct regs *rp,        /* Pointer to PCB image of registers. */
 491         caddr_t addr,           /* Address of trapping instruction. */
 492         uint32_t type,          /* Type of trapping exception. */
 493         uint32_t code);         /* Trap code -> si_code. */
 494 
 495 #endif  /* __STDC__ */
 496 #endif /* _ASM */
 497 
 498 #ifdef  __cplusplus
 499 }
 500 #endif
 501 
 502 #endif  /* _SYS_FPU_FPU_SIMULATOR_H */