fex_handler.h revision 25c28e83beb90e7c80452a7c818c5e6f73a07dc8
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2011 Nexenta Systems, Inc. All rights reserved.
*/
/*
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#ifndef _M9X_FEX_HANDLER_H
#define _M9X_FEX_HANDLER_H
/* the following enums must match the bit positions in fenv.h */
enum fex_exception {
fex_inexact = 0,
fex_division = 1,
fex_underflow = 2,
fex_overflow = 3,
fex_inv_zdz = 4,
fex_inv_idi = 5,
fex_inv_isi = 6,
fex_inv_zmi = 7,
fex_inv_sqrt = 8,
fex_inv_snan = 9,
fex_inv_int = 10,
fex_inv_cmp = 11
};
/* auxiliary functions in __fex_hdlr.c */
extern struct fex_handler_data *__fex_get_thr_handlers(void);
extern void __fex_update_te(void);
/* auxiliary functions in __fex_sym.c */
extern void __fex_sym_init(void);
extern char *__fex_sym(char *, char **);
/* auxiliary functions in fex_log.c */
extern void __fex_mklog(ucontext_t *, char *, int, enum fex_exception,
int, void *);
/* system-dependent auxiliary functions */
extern enum fex_exception __fex_get_invalid_type(siginfo_t *, ucontext_t *);
extern void __fex_get_op(siginfo_t *, ucontext_t *, fex_info_t *);
extern void __fex_st_result(siginfo_t *, ucontext_t *, fex_info_t *);
/* inline templates and macros for accessing fp state */
extern void __fenv_getfsr(unsigned long *);
extern void __fenv_setfsr(const unsigned long *);
#if defined(__sparc)
#define __fenv_get_rd(X) ((X>>30)&0x3)
#define __fenv_set_rd(X,Y) X=(X&~0xc0000000ul)|((Y)<<30)
#define __fenv_get_te(X) ((X>>23)&0x1f)
#define __fenv_set_te(X,Y) X=(X&~0x0f800000ul)|((Y)<<23)
#define __fenv_get_ex(X) ((X>>5)&0x1f)
#define __fenv_set_ex(X,Y) X=(X&~0x000003e0ul)|((Y)<<5)
#elif defined(__x86)
extern void __fenv_getcwsw(unsigned int *);
extern void __fenv_setcwsw(const unsigned int *);
extern void __fenv_getmxcsr(unsigned int *);
extern void __fenv_setmxcsr(const unsigned int *);
#define __fenv_get_rd(X) ((X>>26)&3)
#define __fenv_set_rd(X,Y) X=(X&~0x0c000000)|((Y)<<26)
#define __fenv_get_rp(X) ((X>>24)&3)
#define __fenv_set_rp(X,Y) X=(X&~0x03000000)|((Y)<<24)
#define __fenv_get_te(X) ((X>>16)&0x3d)
#define __fenv_set_te(X,Y) X=(X&~0x003d0000)|((Y)<<16)
#define __fenv_get_ex(X) (X&0x3d)
#define __fenv_set_ex(X,Y) X=(X&~0x0000003d)|(Y)
/*
* These macros define some useful distinctions between various
* SSE instructions. In some cases, distinctions are made for
* the purpose of simplifying the decoding of instructions, while
* in other cases, they are made for the purpose of simplying the
* emulation. Note that these values serve as bit flags within
* the enum values in sseinst_t.
*/
#define DOUBLE 0x100
#define SIMD 0x080
#define INTREG 0x040
typedef union {
double d[2];
long long l[2];
float f[4];
int i[4];
} sseoperand_t;
/* structure to hold a decoded SSE instruction */
typedef struct {
enum {
/* single precision scalar instructions */
cmpss = 0,
minss = 1,
maxss = 2,
addss = 3,
subss = 4,
mulss = 5,
divss = 6,
sqrtss = 7,
ucomiss = 16,
comiss = 17,
cvtss2sd = 32,
cvtsi2ss = INTREG + 0,
cvttss2si = INTREG + 1,
cvtss2si = INTREG + 2,
cvtsi2ssq = INTREG + 8,
cvttss2siq = INTREG + 9,
cvtss2siq = INTREG + 10,
/* single precision SIMD instructions */
cmpps = SIMD + 0,
minps = SIMD + 1,
maxps = SIMD + 2,
addps = SIMD + 3,
subps = SIMD + 4,
mulps = SIMD + 5,
divps = SIMD + 6,
sqrtps = SIMD + 7,
cvtps2pd = SIMD + 32,
cvtdq2ps = SIMD + 34,
cvttps2dq = SIMD + 35,
cvtps2dq = SIMD + 36,
cvtpi2ps = SIMD + INTREG + 0,
cvttps2pi = SIMD + INTREG + 1,
cvtps2pi = SIMD + INTREG + 2,
/* double precision scalar instructions */
cmpsd = DOUBLE + 0,
minsd = DOUBLE + 1,
maxsd = DOUBLE + 2,
addsd = DOUBLE + 3,
subsd = DOUBLE + 4,
mulsd = DOUBLE + 5,
divsd = DOUBLE + 6,
sqrtsd = DOUBLE + 7,
ucomisd = DOUBLE + 16,
comisd = DOUBLE + 17,
cvtsd2ss = DOUBLE + 32,
cvtsi2sd = DOUBLE + INTREG + 0,
cvttsd2si = DOUBLE + INTREG + 1,
cvtsd2si = DOUBLE + INTREG + 2,
cvtsi2sdq = DOUBLE + INTREG + 8,
cvttsd2siq = DOUBLE + INTREG + 9,
cvtsd2siq = DOUBLE + INTREG + 10,
/* double precision SIMD instructions */
cmppd = DOUBLE + SIMD + 0,
minpd = DOUBLE + SIMD + 1,
maxpd = DOUBLE + SIMD + 2,
addpd = DOUBLE + SIMD + 3,
subpd = DOUBLE + SIMD + 4,
mulpd = DOUBLE + SIMD + 5,
divpd = DOUBLE + SIMD + 6,
sqrtpd = DOUBLE + SIMD + 7,
cvtpd2ps = DOUBLE + SIMD + 32,
cvtdq2pd = DOUBLE + SIMD + 34,
cvttpd2dq = DOUBLE + SIMD + 35,
cvtpd2dq = DOUBLE + SIMD + 36,
cvtpi2pd = DOUBLE + SIMD + INTREG + 0,
cvttpd2pi = DOUBLE + SIMD + INTREG + 1,
cvtpd2pi = DOUBLE + SIMD + INTREG + 2,
} op;
int imm;
sseoperand_t *op1, *op2;
} sseinst_t;
/* x86-specific auxiliary functions */
extern int *__fex_accrued(void);
extern void __fex_get_x86_exc(siginfo_t *, ucontext_t *);
extern int __fex_parse_sse(ucontext_t *, sseinst_t *);
extern enum fex_exception __fex_get_sse_op(ucontext_t *, sseinst_t *,
fex_info_t *);
extern void __fex_get_simd_op(ucontext_t *, sseinst_t *,
enum fex_exception *, fex_info_t *);
extern void __fex_st_sse_result(ucontext_t *, sseinst_t *,
enum fex_exception, fex_info_t *);
extern void __fex_st_simd_result(ucontext_t *, sseinst_t *,
enum fex_exception *, fex_info_t *);
#else
#error Unknown architecture
#endif
#endif /* _M9X_FEX_HANDLER_H */