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