Annotation of nono/fpe/fpu_emulate.h, revision 1.1.1.2

1.1       root        1: /*     $NetBSD: fpu_emulate.h,v 1.26 2016/12/06 05:58:19 isaki Exp $   */
                      2: 
                      3: /*
                      4:  * Copyright (c) 1995 Gordon Ross
                      5:  * Copyright (c) 1995 Ken Nakata
                      6:  * All rights reserved.
                      7:  *
                      8:  * Redistribution and use in source and binary forms, with or without
                      9:  * modification, are permitted provided that the following conditions
                     10:  * are met:
                     11:  * 1. Redistributions of source code must retain the above copyright
                     12:  *    notice, this list of conditions and the following disclaimer.
                     13:  * 2. Redistributions in binary form must reproduce the above copyright
                     14:  *    notice, this list of conditions and the following disclaimer in the
                     15:  *    documentation and/or other materials provided with the distribution.
                     16:  * 3. The name of the author may not be used to endorse or promote products
                     17:  *    derived from this software without specific prior written permission.
                     18:  * 4. All advertising materials mentioning features or use of this software
                     19:  *    must display the following acknowledgement:
                     20:  *      This product includes software developed by Gordon Ross
                     21:  *
                     22:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
                     23:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
                     24:  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
                     25:  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
                     26:  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
                     27:  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
                     28:  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
                     29:  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
                     30:  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
                     31:  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
                     32:  */
                     33: 
                     34: #ifndef _FPU_EMULATE_H_
                     35: #define _FPU_EMULATE_H_
                     36: 
                     37: #include <stdint.h>
                     38: #include <sys/types.h>
                     39: 
                     40: /*
                     41:  * XM6i glue
                     42:  */
                     43: /* NetBSD/m68k FPE に対する XM6i 固有の変更点を区別しやすくするため */
                     44: #define XM6i_FPE
                     45: 
                     46: #if defined(XM6i_FPE)
                     47: #include "fpreg.h"
                     48: 
                     49: /* from NetBSD:src/sys/sys/ieee754.h */
                     50: #define SNG_EXPBITS            (8)
                     51: #define SNG_FRACBITS   (23)
                     52: #define SNG_EXP_INFNAN (255)
                     53: #define SNG_EXP_BIAS   (127)
                     54: 
                     55: #define DBL_EXPBITS            (11)
                     56: #define DBL_FRACBITS   (20 + 32)
                     57: #define DBL_EXP_INFNAN (2047)
                     58: #define DBL_EXP_BIAS   (1023)
                     59: 
                     60: /* from NetBSD:src/sys/arch/m68k/include/ieee.h */
                     61: #define EXT_EXPBITS            (15)
                     62: #define EXT_FRACBITS   (32 + 32)
                     63: #define EXT_EXP_INFNAN (0x7fff)
                     64: #define EXT_EXP_BIAS   (16383)
                     65: 
                     66: /* derived from NetBSD:src/sys/arch/m68k/include/cpuframe.h */
                     67: struct fpframe {
                     68:        uint32_t fpf_regs[8 * 3];
                     69:        uint32_t fpf_fpcr;
                     70:        uint32_t fpf_fpsr;
                     71:        uint32_t fpf_fpiar;
                     72: };
                     73: #endif /* XM6i_FPE */
                     74: 
                     75: /*
                     76:  * Floating point emulator (tailored for SPARC/modified for m68k, but
                     77:  * structurally machine-independent).
                     78:  *
                     79:  * Floating point numbers are carried around internally in an `expanded'
                     80:  * or `unpacked' form consisting of:
                     81:  *     - sign
                     82:  *     - unbiased exponent
                     83:  *     - mantissa (`1.' + 80-bit fraction + guard + round)
                     84:  *     - sticky bit
                     85:  * Any implied `1' bit is inserted, giving a 81-bit mantissa that is
                     86:  * always nonzero.  Additional low-order `guard' and `round' bits are
                     87:  * scrunched in, making the entire mantissa 83 bits long.  This is divided
                     88:  * into three 32-bit words, with `spare' bits left over in the upper part
                     89:  * of the top word (the high bits of fp_mant[0]).  An internal `exploded'
                     90:  * number is thus kept within the half-open interval [1.0,2.0) (but see
                     91:  * the `number classes' below).  This holds even for denormalized numbers:
                     92:  * when we explode an external denorm, we normalize it, introducing low-order
                     93:  * zero bits, so that the rest of the code always sees normalized values.
                     94:  *
                     95:  * Note that a number of our algorithms use the `spare' bits at the top.
                     96:  * The most demanding algorithm---the one for sqrt---depends on two such
                     97:  * bits, so that it can represent values up to (but not including) 8.0,
                     98:  * and then it needs a carry on top of that, so that we need three `spares'.
                     99:  *
                    100:  * The sticky-word is 32 bits so that we can use `OR' operators to goosh
                    101:  * whole words from the mantissa into it.
                    102:  *
                    103:  * All operations are done in this internal extended precision.  According
                    104:  * to Hennesey & Patterson, Appendix A, rounding can be repeated---that is,
                    105:  * it is OK to do a+b in extended precision and then round the result to
                    106:  * single precision---provided single, double, and extended precisions are
                    107:  * `far enough apart' (they always are), but we will try to avoid any such
                    108:  * extra work where possible.
                    109:  */
                    110: struct fpn {
                    111:        int     fp_class;               /* see below */
                    112:        int     fp_sign;                /* 0 => positive, 1 => negative */
                    113:        int     fp_exp;                 /* exponent (unbiased) */
                    114:        int     fp_sticky;              /* nonzero bits lost at right end */
                    115:        uint32_t fp_mant[3];            /* 83-bit mantissa */
                    116: };
                    117: 
                    118: // fp_mant[0]                          fp_mant[2]
                    119: //  3         2         1               3         2         1
                    120: // 10987654321098765432109876543210 .. 10987654321098765432109876543210
                    121: // ............IIMMMMMMMMMMMMMMMMMM .. MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMGR
                    122: //
                    123: //              0         1            5       6    |
                    124: //     extended 0123456789012345678 .. 1234567890123   (I + M = 64bits)
                    125: //
                    126: // M は小数部(81ビット)。Guard, Round と合わせて83ビット。
                    127: // I は整数部。通常1ビットだが fpu_round() で 0x1.FFF..FFF G=1,R=1 を
                    128: // RN でラウンドすると 2.0 になる。
                    129: // fp_mant[0]の上位12ビットは空きのはず。
                    130: //
                    131: #define        FP_NMANT        83              /* total bits in mantissa (incl g,r) */
                    132: #define        FP_NG           2               /* number of low-order guard bits */
                    133: #define        FP_LG           ((FP_NMANT - 1) & 31)   /* log2(1.0) for fp_mant[0] */
                    134: #define        FP_QUIETBIT     (1 << (FP_LG - 1))      /* Quiet bit in NaNs (0.5) */
                    135: #define        FP_1            (1 << FP_LG)            /* 1.0 in fp_mant[0] */
                    136: #define        FP_2            (1 << (FP_LG + 1))      /* 2.0 in fp_mant[0] */
                    137: 
                    138: static inline void CPYFPN(struct fpn *, const struct fpn *);
                    139: 
                    140: static inline void
                    141: CPYFPN(struct fpn *dst, const struct fpn *src)
                    142: {
                    143: 
                    144:        if (dst != src) {
                    145:                *dst = *src;
                    146:        }
                    147: }
                    148: 
                    149: /*
                    150:  * Number classes.  Since zero, Inf, and NaN cannot be represented using
                    151:  * the above layout, we distinguish these from other numbers via a class.
                    152:  */
                    153: #define        FPC_SNAN        -2              /* signalling NaN (sign irrelevant) */
                    154: #define        FPC_QNAN        -1              /* quiet NaN (sign irrelevant) */
                    155: #define        FPC_ZERO        0               /* zero (sign matters) */
                    156: #define        FPC_NUM         1               /* number (sign matters) */
                    157: #define        FPC_INF         2               /* infinity (sign matters) */
                    158: 
                    159: #define        ISNAN(fp)       ((fp)->fp_class < 0)
                    160: #define        ISZERO(fp)      ((fp)->fp_class == 0)
                    161: #define        ISINF(fp)       ((fp)->fp_class == FPC_INF)
                    162: 
                    163: /*
                    164:  * ORDER(x,y) `sorts' a pair of `fpn *'s so that the right operand (y) points
                    165:  * to the `more significant' operand for our purposes.  Appendix N says that
                    166:  * the result of a computation involving two numbers are:
                    167:  *
                    168:  *     If both are SNaN: operand 2, converted to Quiet
                    169:  *     If only one is SNaN: the SNaN operand, converted to Quiet
                    170:  *     If both are QNaN: operand 2
                    171:  *     If only one is QNaN: the QNaN operand
                    172:  *
                    173:  * In addition, in operations with an Inf operand, the result is usually
                    174:  * Inf.  The class numbers are carefully arranged so that if
                    175:  *     (unsigned)class(op1) > (unsigned)class(op2)
                    176:  * then op1 is the one we want; otherwise op2 is the one we want.
                    177:  */
                    178: #define        ORDER(x, y) { \
                    179:        if ((uint32_t)(x)->fp_class > (uint32_t)(y)->fp_class) \
                    180:                SWAP(x, y); \
                    181: }
                    182: #define        SWAP(x, y) {                            \
                    183:        struct fpn *swap;                       \
                    184:        swap = (x), (x) = (y), (y) = swap;      \
                    185: }
                    186: 
                    187: /*
                    188:  * Emulator state.
                    189:  */
                    190: struct fpemu {
                    191:        struct frame *fe_frame; /* integer regs, etc */
                    192:        struct fpframe *fe_fpframe; /* FP registers, etc */
                    193:        uint32_t fe_fpsr;       /* fpsr copy (modified during op) */
                    194:        uint32_t fe_fpcr;       /* fpcr copy */
                    195:        struct fpn fe_f1;       /* operand 1 */
                    196:        struct fpn fe_f2;       /* operand 2, if required */
                    197:        struct fpn fe_f3;       /* available storage for result */
                    198: 
                    199: #if defined(XM6i_FPE)
                    200:        int has_fpu;            /* XM6i; FPU type/mode */
                    201: #endif
                    202: };
                    203: 
                    204: #if defined(XM6i_FPE)
                    205: #define FPU_TYPE_MASK          (0x0003)
                    206: #define FPU_TYPE_NONE          (0x0000)        /* no FPU */
                    207: #define FPU_TYPE_68881         (0x0001)        /* 68881 */
                    208: #define FPU_TYPE_68882         (0x0002)        /* 68882 (reserved) */
                    209: #define FPU_HOSTMODE           (0x0004)        /* host mode */
                    210: 
                    211: #define FPU_TYPE(fe)           ((fe)->has_fpu & FPU_TYPE_MASK)
                    212: #define HAS_FPU(fe)                    (FPU_TYPE(fe) != FPU_TYPE_NONE)
                    213: #define FPU_IS_HOST(fe)                ((fe)->has_fpu & FPU_HOSTMODE)
                    214: #endif /* XM6i_FPE */
                    215: 
                    216: /*****************************************************************************
                    217:  * End of definitions derived from Sparc FPE
                    218:  *****************************************************************************/
                    219: 
                    220: /*
                    221:  * Internal info about a decoded effective address.
                    222:  */
                    223: struct insn_ea {
                    224:        int     ea_regnum;
                    225:        int     ea_ext[3];      /* extension words if any */
                    226:        int     ea_flags;       /* flags == 0 means mode 2: An@ */
                    227: #define        EA_DIRECT       0x001   /* mode [01]: Dn or An */
                    228: #define EA_PREDECR     0x002   /* mode 4: An@- */
                    229: #define        EA_POSTINCR     0x004   /* mode 3: An@+ */
                    230: #define EA_OFFSET      0x008   /* mode 5 or (7,2): APC@(d16) */
                    231: #define        EA_INDEXED      0x010   /* mode 6 or (7,3): APC@(Xn:*:*,d8) etc */
                    232: #define EA_ABS         0x020   /* mode (7,[01]): abs */
                    233: #define EA_PC_REL      0x040   /* mode (7,[23]): PC@(d16) etc */
                    234: #define        EA_IMMED        0x080   /* mode (7,4): #immed */
                    235: #define EA_MEM_INDIR   0x100   /* mode 6 or (7,3): APC@(Xn:*:*,*)@(*) etc */
                    236: #define EA_BASE_SUPPRSS        0x200   /* mode 6 or (7,3): base register suppressed */
                    237: #define EA_FRAME_EA    0x400   /* MC68LC040 only: precalculated EA from
                    238:                                   format 4 stack frame */
                    239:        int     ea_moffs;       /* offset used for fmoveMulti */
                    240: };
                    241: 
                    242: #define ea_offset      ea_ext[0]       /* mode 5: offset word */
                    243: #define ea_absaddr     ea_ext[0]       /* mode (7,[01]): absolute address */
                    244: #define ea_immed       ea_ext          /* mode (7,4): immediate value */
                    245: #define ea_basedisp    ea_ext[0]       /* mode 6: base displacement */
                    246: #define ea_outerdisp   ea_ext[1]       /* mode 6: outer displacement */
                    247: #define        ea_idxreg       ea_ext[2]       /* mode 6: index register number */
                    248: #define ea_fea         ea_ext[0]       /* MC68LC040 only: frame EA */
                    249: 
                    250: struct instruction {
                    251:        uint32_t is_pc;         /* insn's address */
                    252:        uint32_t is_nextpc;     /* next PC */
                    253:        int     is_advance;     /* length of instruction */
                    254:        int     is_datasize;    /* size of memory operand */
                    255:        int     is_opcode;      /* opcode word */
                    256:        int     is_word1;       /* second word */
                    257:        struct insn_ea  is_ea;  /* decoded effective address mode */
                    258: };
                    259: 
                    260: /*
                    261:  * FP data types
                    262:  */
                    263: #define FTYPE_LNG 0 /* Long Word Integer */
                    264: #define FTYPE_SNG 1 /* Single Prec */
                    265: #define FTYPE_EXT 2 /* Extended Prec */
                    266: #define FTYPE_BCD 3 /* Packed BCD */
                    267: #define FTYPE_WRD 4 /* Word Integer */
                    268: #define FTYPE_DBL 5 /* Double Prec */
                    269: #define FTYPE_BYT 6 /* Byte Integer */
                    270: 
                    271: /*
                    272:  * Other functions.
                    273:  */
                    274: 
                    275: /* Build a new Quiet NaN (sign=0, frac=all 1's). */
                    276: struct fpn *fpu_newnan(struct fpemu *);
                    277: 
                    278: /*
                    279:  * Shift a number right some number of bits, taking care of round/sticky.
                    280:  * Note that the result is probably not a well-formed number (it will lack
                    281:  * the normal 1-bit mant[0]&FP_1).
                    282:  */
                    283: int    fpu_shr(struct fpn *, int);
                    284: /*
                    285:  * Round a number according to the round mode in FPCR
                    286:  */
                    287: int    fpu_round(struct fpemu *, struct fpn *);
                    288: #if defined(XM6i_FPE)
                    289: void   fpu_round_prec(struct fpemu *, struct fpn *);
                    290: #endif
                    291: 
                    292: /* type conversion */
                    293: void   fpu_explode(struct fpemu *, struct fpn *, int t, const uint32_t *);
                    294: void   fpu_implode(struct fpemu *, struct fpn *, int t, uint32_t *);
                    295: #if defined(XM6i_FPE)
                    296: void   fpu_ftop(struct fpemu *, struct fpn *, uint32_t *, int);
                    297: #endif
                    298: 
                    299: /*
                    300:  * non-static emulation functions
                    301:  */
                    302: /* type 0 */
                    303: int fpu_emul_fmovecr(struct fpemu *, struct instruction *);
                    304: int fpu_emul_fstore(struct fpemu *, struct instruction *);
                    305: #if defined(XM6i_FPE)
                    306: int fpu_emul_fscale(struct fpemu *, uint32_t);
                    307: #else
                    308: int fpu_emul_fscale(struct fpemu *, struct instruction *);
                    309: #endif
                    310: 
                    311: /*
                    312:  * include function declarations of those which are called by fpu_emul_arith()
                    313:  */
                    314: #include "fpu_arith_proto.h"
                    315: 
                    316: #if !defined(XM6i_FPE)
                    317: int fpu_emulate(struct frame *, struct fpframe *, ksiginfo_t *);
                    318: #endif
                    319: struct fpn *fpu_cmp(struct fpemu *);
                    320: #if defined(XM6i_FPE)
                    321: struct fpn *fpu_sglmul(struct fpemu *);
                    322: struct fpn *fpu_sgldiv(struct fpemu *);
                    323: #endif
                    324: 
                    325: /* fpu_cordic.c */
                    326: extern const struct fpn fpu_cordic_inv_gain1;
                    327: void fpu_cordit1(struct fpemu *,
                    328:        struct fpn *, struct fpn *, struct fpn *, const struct fpn *);
                    329: 
                    330: /*
                    331:  * "helper" functions
                    332:  */
                    333: /* return values from constant rom */
                    334: struct fpn *fpu_const(struct fpn *, uint32_t);
                    335: #define FPU_CONST_PI   (0x00)  /* pi */
                    336: #define FPU_CONST_E    (0x0c)  /* e */
                    337: #define FPU_CONST_0    (0x0f)  /* 0.0 */
                    338: #define FPU_CONST_LN_2 (0x30)  /* ln(2) */
                    339: #define FPU_CONST_LN_10        (0x31)  /* ln(10) */
                    340: #define FPU_CONST_1    (0x32)  /* 1.0 */
                    341: #define FPU_CONST_10   (0x33)  /* 10 */
                    342: 
                    343: /* update exceptions and FPSR */
                    344: int fpu_upd_excp(struct fpemu *);
                    345: uint32_t fpu_upd_fpsr(struct fpemu *, struct fpn *);
                    346: #if defined(XM6i_FPE)
                    347: int test_cc(struct fpemu *, int);
1.1.1.2 ! root      348: int fpu_gettag(const struct fpn *);
1.1       root      349: #endif
                    350: 
                    351: /* address mode decoder, and load/store */
                    352: int fpu_decode_ea(struct frame *, struct instruction *,
                    353:                   struct insn_ea *, int);
                    354: int fpu_load_ea(struct frame *, struct instruction *,
                    355:                 struct insn_ea *, char *);
                    356: int fpu_store_ea(struct frame *, struct instruction *,
                    357:                  struct insn_ea *, char *);
                    358: 
                    359: #if defined(XM6i_FPE)
                    360: /* fpu_rem.c */
                    361: struct fpn *fpu_modrem(struct fpemu *, int);
                    362: #endif
                    363: 
                    364: /* fpu_subr.c */
                    365: void fpu_norm(struct fpn *);
                    366: 
                    367: #if !defined(FPE_DEBUG)
                    368: #  define FPE_DEBUG 0
                    369: #endif
                    370: 
                    371: #include "host.h"
                    372: 
                    373: #ifdef LOCAL
                    374: #include "debug.h"
                    375: #else
                    376: #define PRINTF(x...)   /**/
                    377: #define DUMPFP(x...)   /**/
                    378: #define DUMPFPN(x...)  /**/
                    379: #endif
                    380: 
                    381: #endif /* _FPU_EMULATE_H_ */

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.