[BACK]Return to fpu_emulate.h CVS log [TXT][DIR] Up to [local] / sys / arch / m68k / fpe

Annotation of sys/arch/m68k/fpe/fpu_emulate.h, Revision 1.1.1.1

1.1       nbrk        1: /*     $OpenBSD: fpu_emulate.h,v 1.7 2006/06/11 20:43:28 miod Exp $    */
                      2: /*     $NetBSD: fpu_emulate.h,v 1.11 2005/08/13 05:38:45 he Exp $      */
                      3:
                      4: /*
                      5:  * Copyright (c) 1995 Gordon Ross
                      6:  * Copyright (c) 1995 Ken Nakata
                      7:  * All rights reserved.
                      8:  *
                      9:  * Redistribution and use in source and binary forms, with or without
                     10:  * modification, are permitted provided that the following conditions
                     11:  * are met:
                     12:  * 1. Redistributions of source code must retain the above copyright
                     13:  *    notice, this list of conditions and the following disclaimer.
                     14:  * 2. Redistributions in binary form must reproduce the above copyright
                     15:  *    notice, this list of conditions and the following disclaimer in the
                     16:  *    documentation and/or other materials provided with the distribution.
                     17:  * 3. The name of the author may not be used to endorse or promote products
                     18:  *    derived from this software without specific prior written permission.
                     19:  * 4. All advertising materials mentioning features or use of this software
                     20:  *    must display the following acknowledgement:
                     21:  *      This product includes software developed by Gordon Ross
                     22:  *
                     23:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
                     24:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
                     25:  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
                     26:  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
                     27:  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
                     28:  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
                     29:  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
                     30:  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
                     31:  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
                     32:  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
                     33:  */
                     34:
                     35: #ifndef _FPU_EMULATE_H_
                     36: #define _FPU_EMULATE_H_
                     37:
                     38: #include <sys/types.h>
                     39:
                     40: /*
                     41:  * Floating point emulator (tailored for SPARC/modified for m68k, but
                     42:  * structurally machine-independent).
                     43:  *
                     44:  * Floating point numbers are carried around internally in an `expanded'
                     45:  * or `unpacked' form consisting of:
                     46:  *     - sign
                     47:  *     - unbiased exponent
                     48:  *     - mantissa (`1.' + 80-bit fraction + guard + round)
                     49:  *     - sticky bit
                     50:  * Any implied `1' bit is inserted, giving a 81-bit mantissa that is
                     51:  * always nonzero.  Additional low-order `guard' and `round' bits are
                     52:  * scrunched in, making the entire mantissa 83 bits long.  This is divided
                     53:  * into three 32-bit words, with `spare' bits left over in the upper part
                     54:  * of the top word (the high bits of fp_mant[0]).  An internal `exploded'
                     55:  * number is thus kept within the half-open interval [1.0,2.0) (but see
                     56:  * the `number classes' below).  This holds even for denormalized numbers:
                     57:  * when we explode an external denorm, we normalize it, introducing low-order
                     58:  * zero bits, so that the rest of the code always sees normalized values.
                     59:  *
                     60:  * Note that a number of our algorithms use the `spare' bits at the top.
                     61:  * The most demanding algorithm---the one for sqrt---depends on two such
                     62:  * bits, so that it can represent values up to (but not including) 8.0,
                     63:  * and then it needs a carry on top of that, so that we need three `spares'.
                     64:  *
                     65:  * The sticky-word is 32 bits so that we can use `OR' operators to goosh
                     66:  * whole words from the mantissa into it.
                     67:  *
                     68:  * All operations are done in this internal extended precision.  According
                     69:  * to Hennesey & Patterson, Appendix A, rounding can be repeated---that is,
                     70:  * it is OK to do a+b in extended precision and then round the result to
                     71:  * single precision---provided single, double, and extended precisions are
                     72:  * `far enough apart' (they always are), but we will try to avoid any such
                     73:  * extra work where possible.
                     74:  */
                     75: struct fpn {
                     76:        int     fp_class;               /* see below */
                     77:        int     fp_sign;                /* 0 => positive, 1 => negative */
                     78:        int     fp_exp;                 /* exponent (unbiased) */
                     79:        int     fp_sticky;              /* nonzero bits lost at right end */
                     80:        u_int   fp_mant[3];             /* 83-bit mantissa */
                     81: };
                     82:
                     83: #define        FP_NMANT        83              /* total bits in mantissa (incl g,r) */
                     84: #define        FP_NG           2               /* number of low-order guard bits */
                     85: #define        FP_LG           ((FP_NMANT - 1) & 31)   /* log2(1.0) for fp_mant[0] */
                     86: #define        FP_QUIETBIT     (1 << (FP_LG - 1))      /* Quiet bit in NaNs (0.5) */
                     87: #define        FP_1            (1 << FP_LG)            /* 1.0 in fp_mant[0] */
                     88: #define        FP_2            (1 << (FP_LG + 1))      /* 2.0 in fp_mant[0] */
                     89:
                     90: #define CPYFPN(dst, src)                                               \
                     91: if ((dst) != (src)) {                                                  \
                     92:     (dst)->fp_class = (src)->fp_class;                                 \
                     93:     (dst)->fp_sign = (src)->fp_sign;                                   \
                     94:     (dst)->fp_exp = (src)->fp_exp;                                     \
                     95:     (dst)->fp_sticky = (src)->fp_sticky;                               \
                     96:     (dst)->fp_mant[0] = (src)->fp_mant[0];                             \
                     97:     (dst)->fp_mant[1] = (src)->fp_mant[1];                             \
                     98:     (dst)->fp_mant[2] = (src)->fp_mant[2];                             \
                     99: }
                    100:
                    101: /*
                    102:  * Number classes.  Since zero, Inf, and NaN cannot be represented using
                    103:  * the above layout, we distinguish these from other numbers via a class.
                    104:  */
                    105: #define        FPC_SNAN        -2              /* signalling NaN (sign irrelevant) */
                    106: #define        FPC_QNAN        -1              /* quiet NaN (sign irrelevant) */
                    107: #define        FPC_ZERO        0               /* zero (sign matters) */
                    108: #define        FPC_NUM         1               /* number (sign matters) */
                    109: #define        FPC_INF         2               /* infinity (sign matters) */
                    110:
                    111: #define        ISNAN(fp)       ((fp)->fp_class < 0)
                    112: #define        ISZERO(fp)      ((fp)->fp_class == 0)
                    113: #define        ISINF(fp)       ((fp)->fp_class == FPC_INF)
                    114:
                    115: /*
                    116:  * ORDER(x,y) `sorts' a pair of `fpn *'s so that the right operand (y) points
                    117:  * to the `more significant' operand for our purposes.  Appendix N says that
                    118:  * the result of a computation involving two numbers are:
                    119:  *
                    120:  *     If both are SNaN: operand 2, converted to Quiet
                    121:  *     If only one is SNaN: the SNaN operand, converted to Quiet
                    122:  *     If both are QNaN: operand 2
                    123:  *     If only one is QNaN: the QNaN operand
                    124:  *
                    125:  * In addition, in operations with an Inf operand, the result is usually
                    126:  * Inf.  The class numbers are carefully arranged so that if
                    127:  *     (unsigned)class(op1) > (unsigned)class(op2)
                    128:  * then op1 is the one we want; otherwise op2 is the one we want.
                    129:  */
                    130: #define        ORDER(x, y) { \
                    131:        if ((u_int)(x)->fp_class > (u_int)(y)->fp_class) \
                    132:                SWAP(x, y); \
                    133: }
                    134: #define        SWAP(x, y) {                            \
                    135:        struct fpn *swap;                       \
                    136:        swap = (x), (x) = (y), (y) = swap;      \
                    137: }
                    138:
                    139: /*
                    140:  * Emulator state.
                    141:  */
                    142: struct fpemu {
                    143:     struct     frame *fe_frame; /* integer regs, etc */
                    144:     struct     fpframe *fe_fpframe; /* FP registers, etc */
                    145:     u_int      fe_fpsr;        /* fpsr copy (modified during op) */
                    146:     u_int      fe_fpcr;        /* fpcr copy */
                    147:     struct     fpn fe_f1;      /* operand 1 */
                    148:     struct     fpn fe_f2;      /* operand 2, if required */
                    149:     struct     fpn fe_f3;      /* available storage for result */
                    150: };
                    151:
                    152: /*****************************************************************************
                    153:  * End of definitions derived from Sparc FPE
                    154:  *****************************************************************************/
                    155:
                    156: /*
                    157:  * Internal info about a decoded effective address.
                    158:  */
                    159: struct insn_ea {
                    160:     int        ea_regnum;
                    161:     int        ea_ext[3];              /* extension words if any */
                    162:     int        ea_flags;               /* flags == 0 means mode 2: An@ */
                    163: #define        EA_DIRECT       0x001   /* mode [01]: Dn or An */
                    164: #define EA_PREDECR     0x002   /* mode 4: An@- */
                    165: #define        EA_POSTINCR     0x004   /* mode 3: An@+ */
                    166: #define EA_OFFSET      0x008   /* mode 5 or (7,2): APC@(d16) */
                    167: #define        EA_INDEXED      0x010   /* mode 6 or (7,3): APC@(Xn:*:*,d8) etc */
                    168: #define EA_ABS         0x020   /* mode (7,[01]): abs */
                    169: #define EA_PC_REL      0x040   /* mode (7,[23]): PC@(d16) etc */
                    170: #define        EA_IMMED        0x080   /* mode (7,4): #immed */
                    171: #define EA_MEM_INDIR   0x100   /* mode 6 or (7,3): APC@(Xn:*:*,*)@(*) etc */
                    172: #define EA_BASE_SUPPRSS        0x200   /* mode 6 or (7,3): base register suppressed */
                    173: #define EA_FRAME_EA    0x400   /* MC68LC040 only: precalculated EA from
                    174:                                   format 4 stack frame */
                    175:     int        ea_moffs;               /* offset used for fmoveMulti */
                    176: };
                    177:
                    178: #define ea_offset      ea_ext[0]       /* mode 5: offset word */
                    179: #define ea_absaddr     ea_ext[0]       /* mode (7,[01]): absolute address */
                    180: #define ea_immed       ea_ext          /* mode (7,4): immediate value */
                    181: #define ea_basedisp    ea_ext[0]       /* mode 6: base displacement */
                    182: #define ea_outerdisp   ea_ext[1]       /* mode 6: outer displacement */
                    183: #define        ea_idxreg       ea_ext[2]       /* mode 6: index register number */
                    184: #define ea_fea         ea_ext[0]       /* MC68LC040 only: frame EA */
                    185:
                    186: struct instruction {
                    187:     u_int              is_pc;          /* insn's address */
                    188:     u_int              is_nextpc;      /* next PC */
                    189:     int                        is_advance;     /* length of instruction */
                    190:     int                        is_datasize;    /* size of memory operand */
                    191:     int                        is_opcode;      /* opcode word */
                    192:     int                        is_word1;       /* second word */
                    193:     struct insn_ea     is_ea;  /* decoded effective address mode */
                    194: };
                    195:
                    196: /*
                    197:  * FP data types
                    198:  */
                    199: #define FTYPE_LNG 0 /* Long Word Integer */
                    200: #define FTYPE_SNG 1 /* Single Prec */
                    201: #define FTYPE_EXT 2 /* Extended Prec */
                    202: #define FTYPE_BCD 3 /* Packed BCD */
                    203: #define FTYPE_WRD 4 /* Word Integer */
                    204: #define FTYPE_DBL 5 /* Double Prec */
                    205: #define FTYPE_BYT 6 /* Byte Integer */
                    206:
                    207: /*
                    208:  * MC68881/68882 FPcr bit definitions (should these go to <m68k/reg.h>
                    209:  * or <m68k/fpu.h> or something?)
                    210:  */
                    211:
                    212: /* fpsr */
                    213: #define FPSR_CCB    0xff000000
                    214: # define FPSR_NEG   0x08000000
                    215: # define FPSR_ZERO  0x04000000
                    216: # define FPSR_INF   0x02000000
                    217: # define FPSR_NAN   0x01000000
                    218: #define FPSR_QTT    0x00ff0000
                    219: # define FPSR_QSG   0x00800000
                    220: # define FPSR_QUO   0x007f0000
                    221: #define FPSR_EXCP   0x0000ff00
                    222: # define FPSR_BSUN  0x00008000
                    223: # define FPSR_SNAN  0x00004000
                    224: # define FPSR_OPERR 0x00002000
                    225: # define FPSR_OVFL  0x00001000
                    226: # define FPSR_UNFL  0x00000800
                    227: # define FPSR_DZ    0x00000400
                    228: # define FPSR_INEX2 0x00000200
                    229: # define FPSR_INEX1 0x00000100
                    230: #define FPSR_AEX    0x000000ff
                    231: # define FPSR_AIOP  0x00000080
                    232: # define FPSR_AOVFL 0x00000040
                    233: # define FPSR_AUNFL 0x00000020
                    234: # define FPSR_ADZ   0x00000010
                    235: # define FPSR_AINEX 0x00000008
                    236:
                    237: /* fpcr */
                    238: #define FPCR_EXCP   FPSR_EXCP
                    239: # define FPCR_BSUN  FPSR_BSUN
                    240: # define FPCR_SNAN  FPSR_SNAN
                    241: # define FPCR_OPERR FPSR_OPERR
                    242: # define FPCR_OVFL  FPSR_OVFL
                    243: # define FPCR_UNFL  FPSR_UNFL
                    244: # define FPCR_DZ    FPSR_DZ
                    245: # define FPCR_INEX2 FPSR_INEX2
                    246: # define FPCR_INEX1 FPSR_INEX1
                    247: #define FPCR_MODE   0x000000ff
                    248: # define FPCR_PREC  0x000000c0
                    249: #  define FPCR_EXTD 0x00000000
                    250: #  define FPCR_SNGL 0x00000040
                    251: #  define FPCR_DBL  0x00000080
                    252: # define FPCR_ROUND 0x00000030
                    253: #  define FPCR_NEAR 0x00000000
                    254: #  define FPCR_ZERO 0x00000010
                    255: #  define FPCR_MINF 0x00000020
                    256: #  define FPCR_PINF 0x00000030
                    257:
                    258: /*
                    259:  * Other functions.
                    260:  */
                    261:
                    262: /* Build a new Quiet NaN (sign=0, frac=all 1's). */
                    263: struct fpn *fpu_newnan(struct fpemu *fe);
                    264:
                    265: /*
                    266:  * Shift a number right some number of bits, taking care of round/sticky.
                    267:  * Note that the result is probably not a well-formed number (it will lack
                    268:  * the normal 1-bit mant[0]&FP_1).
                    269:  */
                    270: int    fpu_shr(struct fpn *fp, int shr);
                    271: /*
                    272:  * Round a number according to the round mode in FPCR
                    273:  */
                    274: int    fpu_round(struct fpemu *fe, struct fpn *fp);
                    275:
                    276: /* type conversion */
                    277: void   fpu_explode(struct fpemu *fe, struct fpn *fp, int t, u_int *src);
                    278: void   fpu_implode(struct fpemu *fe, struct fpn *fp, int t, u_int *dst);
                    279:
                    280: /*
                    281:  * non-static emulation functions
                    282:  */
                    283: /* type 0 */
                    284: int fpu_emul_fmovecr(struct fpemu *fe, struct instruction *insn, int *typ);
                    285: int fpu_emul_fstore(struct fpemu *fe, struct instruction *insn, int *typ);
                    286: int fpu_emul_fscale(struct fpemu *fe, struct instruction *insn, int *typ);
                    287:
                    288: /*
                    289:  * include function declarations of those which are called by fpu_emul_arith()
                    290:  */
                    291: #include <m68k/fpe/fpu_arith_proto.h>
                    292:
                    293: int fpu_emulate(struct frame *frame, struct fpframe *fpf, int *typ);
                    294:
                    295: /*
                    296:  * "helper" functions
                    297:  */
                    298: /* return values from constant rom */
                    299: struct fpn *fpu_const(struct fpn *fp, u_int offset);
                    300: /* update exceptions and FPSR */
                    301: int fpu_upd_excp(struct fpemu *fe);
                    302: u_int fpu_upd_fpsr(struct fpemu *fe, struct fpn *fp) ;
                    303:
                    304: /* address mode decoder, and load/store */
                    305: int fpu_decode_ea(struct frame *frame, struct instruction *insn,
                    306:                   struct insn_ea *ea, int modreg, int *typ);
                    307: int fpu_load_ea(struct frame *frame, struct instruction *insn,
                    308:                 struct insn_ea *ea, char *dst, int *typ);
                    309: int fpu_store_ea(struct frame *frame, struct instruction *insn,
                    310:                  struct insn_ea *ea, char *src);
                    311:
                    312: /* fpu_subr.c */
                    313: void fpu_norm(struct fpn *fp);
                    314:
                    315: #if !defined(FPE_DEBUG)
                    316: #  define FPE_DEBUG 0
                    317: #endif
                    318:
                    319: #endif /* _FPU_EMULATE_H_ */

CVSweb