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