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 2008 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, fmau = 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 { /* FMA-fused/unfused instr. variations */ 223 fmadd = 0, 224 fmsub = 1, 225 fnmsub = 2, 226 fnmadd = 3 227 }; 228 229 typedef /* FPU FMA-fused/unfused instructions. */ 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_fumadds; 334 struct kstat_named fpu_sim_fumaddd; 335 struct kstat_named fpu_sim_fumsubs; 336 struct kstat_named fpu_sim_fumsubd; 337 struct kstat_named fpu_sim_fnumadds; 338 struct kstat_named fpu_sim_fnumaddd; 339 struct kstat_named fpu_sim_fnumsubs; 340 struct kstat_named fpu_sim_fnumsubd; 341 struct kstat_named fpu_sim_invalid; 342 }; 343 344 struct visinfo_kstat { 345 struct kstat_named vis_edge8; 346 struct kstat_named vis_edge8n; 347 struct kstat_named vis_edge8l; 348 struct kstat_named vis_edge8ln; 349 struct kstat_named vis_edge16; 350 struct kstat_named vis_edge16n; 351 struct kstat_named vis_edge16l; 352 struct kstat_named vis_edge16ln; 353 struct kstat_named vis_edge32; 354 struct kstat_named vis_edge32n; 355 struct kstat_named vis_edge32l; 356 struct kstat_named vis_edge32ln; 357 struct kstat_named vis_array8; 358 struct kstat_named vis_array16; 359 struct kstat_named vis_array32; 360 struct kstat_named vis_bmask; 361 struct kstat_named vis_fcmple16; 362 struct kstat_named vis_fcmpne16; 363 struct kstat_named vis_fcmpgt16; 364 struct kstat_named vis_fcmpeq16; 365 struct kstat_named vis_fcmple32; 366 struct kstat_named vis_fcmpne32; 367 struct kstat_named vis_fcmpgt32; 368 struct kstat_named vis_fcmpeq32; 369 struct kstat_named vis_fmul8x16; 370 struct kstat_named vis_fmul8x16au; 371 struct kstat_named vis_fmul8x16al; 372 struct kstat_named vis_fmul8sux16; 373 struct kstat_named vis_fmul8ulx16; 374 struct kstat_named vis_fmuld8sux16; 375 struct kstat_named vis_fmuld8ulx16; 376 struct kstat_named vis_fpack16; 377 struct kstat_named vis_fpack32; 378 struct kstat_named vis_fpackfix; 379 struct kstat_named vis_fexpand; 380 struct kstat_named vis_fpmerge; 381 struct kstat_named vis_pdist; 382 struct kstat_named vis_bshuffle; 383 }; 384 385 #define VISINFO_KSTAT(opcode) { \ 386 extern void __dtrace_probe___visinfo_##opcode(uint64_t *); \ 387 uint64_t *stataddr = &visinfo.opcode.value.ui64; \ 388 __dtrace_probe___visinfo_##opcode(stataddr); \ 389 atomic_add_64(&visinfo.opcode.value.ui64, 1); \ 390 } 391 392 393 /* PUBLIC FUNCTIONS */ 394 395 #ifdef __STDC__ 396 397 /* 398 * fpu_vis_sim simulates FPU VIS Partial load store instructions; reads and 399 * writes FPU data registers directly or works with the PCB image if fpu_exists 400 * is 0. 401 */ 402 extern enum ftt_type fpu_vis_sim(fp_simd_type *pfpsd, fp_inst_type *pinst, 403 struct regs *pregs, fsr_type *pfsr, uint64_t gsr, uint32_t inst); 404 /* 405 * fpu_simulator simulates FPU instructions only; reads and writes FPU data 406 * registers directly. 407 */ 408 extern enum ftt_type fpu_simulator(fp_simd_type *pfpsd, fp_inst_type *pinst, 409 fsr_type *pfsr, uint64_t gsr, uint32_t inst); 410 /* 411 * fp_emulator simulates FPU and CPU-FPU instructions; reads and writes FPU 412 * data registers from image in pfpu. 413 */ 414 extern enum ftt_type fp_emulator(fp_simd_type *pfpsd, fp_inst_type *pinst, 415 struct regs *rp, void *prw, kfpu_t *pfpu); 416 /* 417 * fp_traps handles passing exception conditions to the kernel. 418 * It is called after fp_simulator or fp_emulator fail (return a non-zero ftt). 419 */ 420 extern void fp_traps(fp_simd_type *pfpsd, enum ftt_type ftt, struct regs *rp); 421 422 /* 423 * fp_kstat_update tracks fpu exception conditions. 424 * It is called after a hardware trap returns a non-zero ftt. 425 */ 426 extern void fp_kstat_update(enum ftt_type ftt); 427 428 /* 429 * fp_precise handles floating point unimplemented and unfinished traps, 430 * for sparc V9 hardware. These traps are normally passed along to the 431 * fpu_simulator, to see if it can run the unimplemented instruction or 432 * finish the unfinished instruction. Needless to say, this takes time. 433 */ 434 extern void fp_precise(struct regs *rp); 435 436 /* 437 * fpu_trap handles V9 floating point ieee and other floating point traps. 438 * It is called after fp_simulator or fp_emulator fail (return a non-zero ftt), 439 * and from the _fp_ieee_exception trap handler. 440 */ 441 extern void fpu_trap(struct regs *rp, caddr_t addr, uint32_t type, 442 uint32_t code); 443 444 #else /* ! __STDC__ */ 445 446 /* 447 * fpu_simulator simulates FPU instructions only; reads and writes FPU data 448 * registers directly. 449 */ 450 extern enum ftt_type fpu_simulator( 451 fp_simd_type *pfpsd, /* Pointer to FPU simulator data */ 452 fp_inst_type *pinst, /* Pointer to FPU instruction to simulate. */ 453 fsr_type *pfsr, /* Pointer to image of FSR to read & write. */ 454 int instr); /* Instruction to emulate. */ 455 456 /* 457 * fp_emulator simulates FPU and CPU-FPU instructions; reads and writes FPU 458 * data registers from image in pfpu. 459 */ 460 extern enum ftt_type fp_emulator( 461 fp_simd_type *pfpsd, /* Pointer to FPU simulator data */ 462 fp_inst_type *pinst, /* Pointer to FPU instruction to simulate. */ 463 struct regs *pregs, /* Pointer to PCB image of registers. */ 464 struct rwindow *pwindow, /* Pointer to locals and ins. */ 465 struct fpu *pfpu); /* Pointer to FPU register block. */ 466 467 /* 468 * fp_traps handles passing exception conditions to the kernel. 469 * It is called after fp_simulator or fp_emulator fail (return a non-zero ftt). 470 */ 471 extern void fp_traps( 472 fp_simd_type *pfpsd, /* Pointer to FPU simulator data */ 473 enum ftt_type ftt, /* Type of trap. */ 474 struct regs *rp); /* Pointer to PCB image of registers. */ 475 476 /* 477 * fp_kstat_update tracks fpu exception conditions. 478 * It is called after a hardware trap returns a non-zero ftt. 479 */ 480 extern void fp_kstat_update(enum ftt_type ftt); /* Type of trap. */ 481 482 /* 483 * fp_precise handles floating point unimplemented and unfinished traps, 484 * for sparc V9 hardware. These traps are normally passed along to the 485 * fpu_simulator, to see if it can run the unimplemented instruction or 486 * finish the unfinished instruction. Needless to say, this takes time. 487 */ 488 extern void fp_precise( 489 struct regs *rp); /* Pointer to PCB image of registers. */ 490 491 /* 492 * fpu_trap handles V9 floating point ieee and other floating point traps. 493 * It is called after fp_simulator or fp_emulator fail (return a non-zero ftt), 494 * and from the _fp_ieee_exception trap handler. 495 */ 496 extern void fpu_trap( 497 struct regs *rp, /* Pointer to PCB image of registers. */ 498 caddr_t addr, /* Address of trapping instruction. */ 499 uint32_t type, /* Type of trapping exception. */ 500 uint32_t code); /* Trap code -> si_code. */ 501 502 #endif /* __STDC__ */ 503 #endif /* _ASM */ 504 505 #ifdef __cplusplus 506 } 507 #endif 508 509 #endif /* _SYS_FPU_FPU_SIMULATOR_H */ 510