|
|
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); ! 348: #endif ! 349: ! 350: /* address mode decoder, and load/store */ ! 351: int fpu_decode_ea(struct frame *, struct instruction *, ! 352: struct insn_ea *, int); ! 353: int fpu_load_ea(struct frame *, struct instruction *, ! 354: struct insn_ea *, char *); ! 355: int fpu_store_ea(struct frame *, struct instruction *, ! 356: struct insn_ea *, char *); ! 357: ! 358: #if defined(XM6i_FPE) ! 359: /* fpu_rem.c */ ! 360: struct fpn *fpu_modrem(struct fpemu *, int); ! 361: #endif ! 362: ! 363: /* fpu_subr.c */ ! 364: void fpu_norm(struct fpn *); ! 365: ! 366: #if !defined(FPE_DEBUG) ! 367: # define FPE_DEBUG 0 ! 368: #endif ! 369: ! 370: #include "host.h" ! 371: ! 372: #ifdef LOCAL ! 373: #include "debug.h" ! 374: #else ! 375: #define PRINTF(x...) /**/ ! 376: #define DUMPFP(x...) /**/ ! 377: #define DUMPFPN(x...) /**/ ! 378: #endif ! 379: ! 380: #endif /* _FPU_EMULATE_H_ */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.