1/* $NetBSD: fpu_emulate.h,v 1.18 2011/10/15 15:14:30 tsutsui 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 <sys/types.h> 38#include <sys/signal.h> 39#include <sys/time.h> 40#include <sys/signalvar.h> 41#include <sys/siginfo.h> 42#include <m68k/fpreg.h> 43 44/* 45 * Floating point emulator (tailored for SPARC/modified for m68k, but 46 * structurally machine-independent). 47 * 48 * Floating point numbers are carried around internally in an `expanded' 49 * or `unpacked' form consisting of: 50 * - sign 51 * - unbiased exponent 52 * - mantissa (`1.' + 80-bit fraction + guard + round) 53 * - sticky bit 54 * Any implied `1' bit is inserted, giving a 81-bit mantissa that is 55 * always nonzero. Additional low-order `guard' and `round' bits are 56 * scrunched in, making the entire mantissa 83 bits long. This is divided 57 * into three 32-bit words, with `spare' bits left over in the upper part 58 * of the top word (the high bits of fp_mant[0]). An internal `exploded' 59 * number is thus kept within the half-open interval [1.0,2.0) (but see 60 * the `number classes' below). This holds even for denormalized numbers: 61 * when we explode an external denorm, we normalize it, introducing low-order 62 * zero bits, so that the rest of the code always sees normalized values. 63 * 64 * Note that a number of our algorithms use the `spare' bits at the top. 65 * The most demanding algorithm---the one for sqrt---depends on two such 66 * bits, so that it can represent values up to (but not including) 8.0, 67 * and then it needs a carry on top of that, so that we need three `spares'. 68 * 69 * The sticky-word is 32 bits so that we can use `OR' operators to goosh 70 * whole words from the mantissa into it. 71 * 72 * All operations are done in this internal extended precision. According 73 * to Hennesey & Patterson, Appendix A, rounding can be repeated---that is, 74 * it is OK to do a+b in extended precision and then round the result to 75 * single precision---provided single, double, and extended precisions are 76 * `far enough apart' (they always are), but we will try to avoid any such 77 * extra work where possible. 78 */ 79struct fpn { 80 int fp_class; /* see below */ 81 int fp_sign; /* 0 => positive, 1 => negative */ 82 int fp_exp; /* exponent (unbiased) */ 83 int fp_sticky; /* nonzero bits lost at right end */ 84 u_int fp_mant[3]; /* 83-bit mantissa */ 85}; 86 87#define FP_NMANT 83 /* total bits in mantissa (incl g,r) */ 88#define FP_NG 2 /* number of low-order guard bits */ 89#define FP_LG ((FP_NMANT - 1) & 31) /* log2(1.0) for fp_mant[0] */ 90#define FP_QUIETBIT (1 << (FP_LG - 1)) /* Quiet bit in NaNs (0.5) */ 91#define FP_1 (1 << FP_LG) /* 1.0 in fp_mant[0] */ 92#define FP_2 (1 << (FP_LG + 1)) /* 2.0 in fp_mant[0] */ 93 94static inline void CPYFPN(struct fpn *, const struct fpn *); 95 96static inline void 97CPYFPN(struct fpn *dst, const struct fpn *src) 98{ 99 100 if (dst != src) { 101 *dst = *src; 102 } 103} 104 105/* 106 * Number classes. Since zero, Inf, and NaN cannot be represented using 107 * the above layout, we distinguish these from other numbers via a class. 108 */ 109#define FPC_SNAN -2 /* signalling NaN (sign irrelevant) */ 110#define FPC_QNAN -1 /* quiet NaN (sign irrelevant) */ 111#define FPC_ZERO 0 /* zero (sign matters) */ 112#define FPC_NUM 1 /* number (sign matters) */ 113#define FPC_INF 2 /* infinity (sign matters) */ 114 115#define ISNAN(fp) ((fp)->fp_class < 0) 116#define ISZERO(fp) ((fp)->fp_class == 0) 117#define ISINF(fp) ((fp)->fp_class == FPC_INF) 118 119/* 120 * ORDER(x,y) `sorts' a pair of `fpn *'s so that the right operand (y) points 121 * to the `more significant' operand for our purposes. Appendix N says that 122 * the result of a computation involving two numbers are: 123 * 124 * If both are SNaN: operand 2, converted to Quiet 125 * If only one is SNaN: the SNaN operand, converted to Quiet 126 * If both are QNaN: operand 2 127 * If only one is QNaN: the QNaN operand 128 * 129 * In addition, in operations with an Inf operand, the result is usually 130 * Inf. The class numbers are carefully arranged so that if 131 * (unsigned)class(op1) > (unsigned)class(op2) 132 * then op1 is the one we want; otherwise op2 is the one we want. 133 */ 134#define ORDER(x, y) { \ 135 if ((u_int)(x)->fp_class > (u_int)(y)->fp_class) \ 136 SWAP(x, y); \ 137} 138#define SWAP(x, y) { \ 139 register struct fpn *swap; \ 140 swap = (x), (x) = (y), (y) = swap; \ 141} 142 143/* 144 * Emulator state. 145 */ 146struct fpemu { 147 struct frame *fe_frame; /* integer regs, etc */ 148 struct fpframe *fe_fpframe; /* FP registers, etc */ 149 u_int fe_fpsr; /* fpsr copy (modified during op) */ 150 u_int fe_fpcr; /* fpcr copy */ 151 struct fpn fe_f1; /* operand 1 */ 152 struct fpn fe_f2; /* operand 2, if required */ 153 struct fpn fe_f3; /* available storage for result */ 154}; 155 156/***************************************************************************** 157 * End of definitions derived from Sparc FPE 158 *****************************************************************************/ 159 160/* 161 * Internal info about a decoded effective address. 162 */ 163struct insn_ea { 164 int ea_regnum; 165 int ea_ext[3]; /* extension words if any */ 166 int ea_flags; /* flags == 0 means mode 2: An@ */ 167#define EA_DIRECT 0x001 /* mode [01]: Dn or An */ 168#define EA_PREDECR 0x002 /* mode 4: An@- */ 169#define EA_POSTINCR 0x004 /* mode 3: An@+ */ 170#define EA_OFFSET 0x008 /* mode 5 or (7,2): APC@(d16) */ 171#define EA_INDEXED 0x010 /* mode 6 or (7,3): APC@(Xn:*:*,d8) etc */ 172#define EA_ABS 0x020 /* mode (7,[01]): abs */ 173#define EA_PC_REL 0x040 /* mode (7,[23]): PC@(d16) etc */ 174#define EA_IMMED 0x080 /* mode (7,4): #immed */ 175#define EA_MEM_INDIR 0x100 /* mode 6 or (7,3): APC@(Xn:*:*,*)@(*) etc */ 176#define EA_BASE_SUPPRSS 0x200 /* mode 6 or (7,3): base register suppressed */ 177#define EA_FRAME_EA 0x400 /* MC68LC040 only: precalculated EA from 178 format 4 stack frame */ 179 int ea_moffs; /* offset used for fmoveMulti */ 180}; 181 182#define ea_offset ea_ext[0] /* mode 5: offset word */ 183#define ea_absaddr ea_ext[0] /* mode (7,[01]): absolute address */ 184#define ea_immed ea_ext /* mode (7,4): immediate value */ 185#define ea_basedisp ea_ext[0] /* mode 6: base displacement */ 186#define ea_outerdisp ea_ext[1] /* mode 6: outer displacement */ 187#define ea_idxreg ea_ext[2] /* mode 6: index register number */ 188#define ea_fea ea_ext[0] /* MC68LC040 only: frame EA */ 189 190struct instruction { 191 u_int is_pc; /* insn's address */ 192 u_int is_nextpc; /* next PC */ 193 int is_advance; /* length of instruction */ 194 int is_datasize; /* size of memory operand */ 195 int is_opcode; /* opcode word */ 196 int is_word1; /* second word */ 197 struct insn_ea is_ea; /* decoded effective address mode */ 198}; 199 200/* 201 * FP data types 202 */ 203#define FTYPE_LNG 0 /* Long Word Integer */ 204#define FTYPE_SNG 1 /* Single Prec */ 205#define FTYPE_EXT 2 /* Extended Prec */ 206#define FTYPE_BCD 3 /* Packed BCD */ 207#define FTYPE_WRD 4 /* Word Integer */ 208#define FTYPE_DBL 5 /* Double Prec */ 209#define FTYPE_BYT 6 /* Byte Integer */ 210 211/* 212 * Other functions. 213 */ 214 215/* Build a new Quiet NaN (sign=0, frac=all 1's). */ 216struct fpn *fpu_newnan(struct fpemu *); 217 218/* 219 * Shift a number right some number of bits, taking care of round/sticky. 220 * Note that the result is probably not a well-formed number (it will lack 221 * the normal 1-bit mant[0]&FP_1). 222 */ 223int fpu_shr(struct fpn *, int); 224/* 225 * Round a number according to the round mode in FPCR 226 */ 227int fpu_round(register struct fpemu *, register struct fpn *); 228 229/* type conversion */ 230void fpu_explode(struct fpemu *, struct fpn *, int t, u_int *); 231void fpu_implode(struct fpemu *, struct fpn *, int t, u_int *); 232 233/* 234 * non-static emulation functions 235 */ 236/* type 0 */ 237int fpu_emul_fmovecr(struct fpemu *, struct instruction *); 238int fpu_emul_fstore(struct fpemu *, struct instruction *); 239int fpu_emul_fscale(struct fpemu *, struct instruction *); 240 241/* 242 * include function declarations of those which are called by fpu_emul_arith() 243 */ 244#include "fpu_arith_proto.h" 245 246int fpu_emulate(struct frame *, struct fpframe *, ksiginfo_t *); 247struct fpn *fpu_cmp(struct fpemu *); 248 249struct fpn *fpu_sincos_taylor(struct fpemu *, struct fpn *, u_int, int); 250 251/* 252 * "helper" functions 253 */ 254/* return values from constant rom */ 255struct fpn *fpu_const(struct fpn *, u_int); 256/* update exceptions and FPSR */ 257int fpu_upd_excp(struct fpemu *); 258u_int fpu_upd_fpsr(struct fpemu *, struct fpn *); 259 260/* address mode decoder, and load/store */ 261int fpu_decode_ea(struct frame *, struct instruction *, 262 struct insn_ea *, int); 263int fpu_load_ea(struct frame *, struct instruction *, 264 struct insn_ea *, char *); 265int fpu_store_ea(struct frame *, struct instruction *, 266 struct insn_ea *, char *); 267 268/* fpu_subr.c */ 269void fpu_norm(register struct fpn *); 270 271#if !defined(FPE_DEBUG) 272# define FPE_DEBUG 0 273#endif 274 275#endif /* _FPU_EMULATE_H_ */ 276