root/usr/src/lib/libc/sparc/fp/quad.h
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License, Version 1.0 only
 * (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 (c) 1994-1997, by Sun Microsystems, Inc.
 * All rights reserved.
 */

#ifndef _QUAD_H
#define _QUAD_H

#ifdef __cplusplus
extern "C" {
#endif

/*
 * Common definitions for quadruple precision emulation routines
 * (SPARC only)
 */

/* macros to simplify dealing with the diferences between V8 and V9 */
#ifdef __sparcv9

#define Z               (*pz)
#define QUAD_RETURN(x)  return

#else

#define Z               z
#define QUAD_RETURN(x)  return (x)

#endif

/* fsr definitions */

/* current exception bits */
#define FSR_NXC         0x1
#define FSR_DZC         0x2
#define FSR_UFC         0x4
#define FSR_OFC         0x8
#define FSR_NVC         0x10
#define FSR_CEXC        0x1f    /* mask for all cexc bits */

/* accrued exception bits */
#define FSR_NXA         0x20
#define FSR_DZA         0x40
#define FSR_UFA         0x80
#define FSR_OFA         0x100
#define FSR_NVA         0x200

/* trap enable bits */
#define FSR_NXM         0x00800000
#define FSR_DZM         0x01000000
#define FSR_UFM         0x02000000
#define FSR_OFM         0x04000000
#define FSR_NVM         0x08000000

/* rounding directions (shifted) */
#define FSR_RN          0
#define FSR_RZ          1
#define FSR_RP          2
#define FSR_RM          3

/*
 * in struct longdouble, msw implicitly consists of
 *      unsigned short  sign:1;
 *      unsigned short  exponent:15;
 *      unsigned short  frac1:16;
 */

/* structure used to access words within a quad */
union longdouble {
        struct {
                unsigned int    msw;
                unsigned int    frac2;
                unsigned int    frac3;
                unsigned int    frac4;
        } l;
        long double     d;      /* unused; just guarantees correct alignment */
};

/* macros used internally for readability */
#define QUAD_ISNAN(x) \
        (((x).l.msw & 0x7fff0000) == 0x7fff0000 && \
        (((x).l.msw & 0xffff) | (x).l.frac2 | (x).l.frac3 | (x).l.frac4))

#define QUAD_ISZERO(x) \
        (!(((x).l.msw & 0x7fffffff) | (x).l.frac2 | (x).l.frac3 | (x).l.frac4))

/* structure used to access words within a double */
union xdouble {
        struct {
                unsigned int    hi;
                unsigned int    lo;
        } l;
        double                  d;
};

/* relationships returned by _Q_cmp and _Q_cmpe */
enum fcc_type {
        fcc_equal       = 0,
        fcc_less        = 1,
        fcc_greater     = 2,
        fcc_unordered   = 3
};

/* internal routines */
extern void __quad_mag_add(const union longdouble *,
        const union longdouble *, union longdouble *, unsigned int *);
extern void __quad_mag_sub(const union longdouble *,
        const union longdouble *, union longdouble *, unsigned int *);

/* inline templates */
extern void __quad_getfsrp(unsigned int *);
extern void __quad_setfsrp(const unsigned int *);
extern double __quad_dp_sqrt(double *);
extern void __quad_faddq(const union longdouble *, const union longdouble *,
        union longdouble *);
extern void __quad_fsubq(const union longdouble *, const union longdouble *,
        union longdouble *);
extern void __quad_fmulq(const union longdouble *, const union longdouble *,
        union longdouble *);
extern void __quad_fdivq(const union longdouble *, const union longdouble *,
        union longdouble *);
extern void __quad_fsqrtq(const union longdouble *, union longdouble *);
extern void __quad_fcmpq(const union longdouble *, const union longdouble *,
        unsigned int *);
extern void __quad_fcmpeq(const union longdouble *, const union longdouble *,
        unsigned int *);
extern void __quad_fstoq(const float *, union longdouble *);
extern void __quad_fdtoq(const double *, union longdouble *);
extern void __quad_fqtoi(const union longdouble *, int *);
extern void __quad_fqtos(const union longdouble *, float *);
extern void __quad_fqtod(const union longdouble *, double *);
#ifdef __sparcv9
extern void __quad_fqtox(const union longdouble *, long *);
#endif

#ifdef __cplusplus
}
#endif

#endif  /* _QUAD_H */