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 /* 23 * Copyright 2011 Nexenta Systems, Inc. All rights reserved. 24 */ 25 /* 26 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 27 * Use is subject to license terms. 28 */ 29 30 /* #include <sys/isa_defs.h> */ 31 32 /* the following enums must match the bit positions in fenv.h */ 33 enum fex_exception { 34 fex_inexact = 0, 35 fex_division = 1, 36 fex_underflow = 2, 37 fex_overflow = 3, 38 fex_inv_zdz = 4, 39 fex_inv_idi = 5, 40 fex_inv_isi = 6, 41 fex_inv_zmi = 7, 42 fex_inv_sqrt = 8, 43 fex_inv_snan = 9, 44 fex_inv_int = 10, 45 fex_inv_cmp = 11 46 }; 47 48 49 /* auxiliary functions in __fex_hdlr.c */ 50 extern struct fex_handler_data *__fex_get_thr_handlers(void); 51 extern void __fex_update_te(void); 52 53 /* auxiliary functions in __fex_sym.c */ 54 extern void __fex_sym_init(void); 55 extern char *__fex_sym(char *, char **); 56 57 /* auxiliary functions in fex_log.c */ 58 extern void __fex_mklog(ucontext_t *, char *, int, enum fex_exception, 59 int, void *); 60 61 /* system-dependent auxiliary functions */ 62 extern enum fex_exception __fex_get_invalid_type(siginfo_t *, ucontext_t *); 63 extern void __fex_get_op(siginfo_t *, ucontext_t *, fex_info_t *); 64 extern void __fex_st_result(siginfo_t *, ucontext_t *, fex_info_t *); 65 66 /* inline templates and macros for accessing fp state */ 67 extern void __fenv_getfsr(unsigned long *); 68 extern void __fenv_setfsr(unsigned const long *); 69 70 #if defined(__sparc) 71 72 #define __fenv_get_rd(X) ((X>>30)&0x3) 73 #define __fenv_set_rd(X,Y) X=(X&~0xc0000000ul)|((Y)<<30) 74 75 #define __fenv_get_te(X) ((X>>23)&0x1f) 76 #define __fenv_set_te(X,Y) X=(X&~0x0f800000ul)|((Y)<<23) 77 78 #define __fenv_get_ex(X) ((X>>5)&0x1f) 79 #define __fenv_set_ex(X,Y) X=(X&~0x000003e0ul)|((Y)<<5) 80 81 #elif defined(__x86) 82 83 extern void __fenv_getcwsw(unsigned int *); 84 extern void __fenv_setcwsw(const unsigned int *); 85 86 extern void __fenv_getmxcsr(unsigned int *); 87 extern void __fenv_setmxcsr(const unsigned int *); 88 89 #define __fenv_get_rd(X) ((X>>26)&3) 90 #define __fenv_set_rd(X,Y) X=(X&~0x0c000000)|((Y)<<26) 91 92 #define __fenv_get_rp(X) ((X>>24)&3) 93 #define __fenv_set_rp(X,Y) X=(X&~0x03000000)|((Y)<<24) 94 95 #define __fenv_get_te(X) ((X>>16)&0x3d) 96 #define __fenv_set_te(X,Y) X=(X&~0x003d0000)|((Y)<<16) 97 98 #define __fenv_get_ex(X) (X&0x3d) 99 #define __fenv_set_ex(X,Y) X=(X&~0x0000003d)|(Y) 100 101 /* 102 * These macros define some useful distinctions between various 103 * SSE instructions. In some cases, distinctions are made for 104 * the purpose of simplifying the decoding of instructions, while 105 * in other cases, they are made for the purpose of simplying the 106 * emulation. Note that these values serve as bit flags within 107 * the enum values in sseinst_t. 108 */ 109 #define DOUBLE 0x100 110 #define SIMD 0x080 111 #define INTREG 0x040 112 113 typedef union { 114 double d[2]; 115 long long l[2]; 116 float f[4]; 117 int i[4]; 118 } sseoperand_t; 119 120 /* structure to hold a decoded SSE instruction */ 121 typedef struct { 122 enum { 123 /* single precision scalar instructions */ 124 cmpss = 0, 125 minss = 1, 126 maxss = 2, 127 addss = 3, 128 subss = 4, 129 mulss = 5, 130 divss = 6, 131 sqrtss = 7, 132 ucomiss = 16, 133 comiss = 17, 134 cvtss2sd = 32, 135 cvtsi2ss = INTREG + 0, 136 cvttss2si = INTREG + 1, 137 cvtss2si = INTREG + 2, 138 cvtsi2ssq = INTREG + 8, 139 cvttss2siq = INTREG + 9, 140 cvtss2siq = INTREG + 10, 141 142 /* single precision SIMD instructions */ 143 cmpps = SIMD + 0, 144 minps = SIMD + 1, 145 maxps = SIMD + 2, 146 addps = SIMD + 3, 147 subps = SIMD + 4, 148 mulps = SIMD + 5, 149 divps = SIMD + 6, 150 sqrtps = SIMD + 7, 151 cvtps2pd = SIMD + 32, 152 cvtdq2ps = SIMD + 34, 153 cvttps2dq = SIMD + 35, 154 cvtps2dq = SIMD + 36, 155 cvtpi2ps = SIMD + INTREG + 0, 156 cvttps2pi = SIMD + INTREG + 1, 157 cvtps2pi = SIMD + INTREG + 2, 158 159 /* double precision scalar instructions */ 160 cmpsd = DOUBLE + 0, 161 minsd = DOUBLE + 1, 162 maxsd = DOUBLE + 2, 163 addsd = DOUBLE + 3, 164 subsd = DOUBLE + 4, 165 mulsd = DOUBLE + 5, 166 divsd = DOUBLE + 6, 167 sqrtsd = DOUBLE + 7, 168 ucomisd = DOUBLE + 16, 169 comisd = DOUBLE + 17, 170 cvtsd2ss = DOUBLE + 32, 171 cvtsi2sd = DOUBLE + INTREG + 0, 172 cvttsd2si = DOUBLE + INTREG + 1, 173 cvtsd2si = DOUBLE + INTREG + 2, 174 cvtsi2sdq = DOUBLE + INTREG + 8, 175 cvttsd2siq = DOUBLE + INTREG + 9, 176 cvtsd2siq = DOUBLE + INTREG + 10, 177 178 /* double precision SIMD instructions */ 179 cmppd = DOUBLE + SIMD + 0, 180 minpd = DOUBLE + SIMD + 1, 181 maxpd = DOUBLE + SIMD + 2, 182 addpd = DOUBLE + SIMD + 3, 183 subpd = DOUBLE + SIMD + 4, 184 mulpd = DOUBLE + SIMD + 5, 185 divpd = DOUBLE + SIMD + 6, 186 sqrtpd = DOUBLE + SIMD + 7, 187 cvtpd2ps = DOUBLE + SIMD + 32, 188 cvtdq2pd = DOUBLE + SIMD + 34, 189 cvttpd2dq = DOUBLE + SIMD + 35, 190 cvtpd2dq = DOUBLE + SIMD + 36, 191 cvtpi2pd = DOUBLE + SIMD + INTREG + 0, 192 cvttpd2pi = DOUBLE + SIMD + INTREG + 1, 193 cvtpd2pi = DOUBLE + SIMD + INTREG + 2, 194 } op; 195 int imm; 196 sseoperand_t *op1, *op2; 197 } sseinst_t; 198 199 /* x86-specific auxiliary functions */ 200 extern int *__fex_accrued(void); 201 extern void __fex_get_x86_exc(siginfo_t *, ucontext_t *); 202 extern int __fex_parse_sse(ucontext_t *, sseinst_t *); 203 extern enum fex_exception __fex_get_sse_op(ucontext_t *, sseinst_t *, 204 fex_info_t *); 205 extern void __fex_get_simd_op(ucontext_t *, sseinst_t *, 206 enum fex_exception *, fex_info_t *); 207 extern void __fex_st_sse_result(ucontext_t *, sseinst_t *, 208 enum fex_exception, fex_info_t *); 209 extern void __fex_st_simd_result(ucontext_t *, sseinst_t *, 210 enum fex_exception *, fex_info_t *); 211 212 #else 213 #error Unknown architecture 214 #endif