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