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