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 <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 */ 79 struct 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 uint32_t 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 94 static inline void CPYFPN(struct fpn *, const struct fpn *); 95 96 static inline void 97 CPYFPN(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 ((uint32_t)(x)->fp_class > (uint32_t)(y)->fp_class) \ 136 SWAP(x, y); \ 137 } 138 #define SWAP(x, y) { \ 139 struct fpn *swap; \ 140 swap = (x), (x) = (y), (y) = swap; \ 141 } 142 143 /* 144 * Emulator state. 145 */ 146 struct fpemu { 147 struct frame *fe_frame; /* integer regs, etc */ 148 struct fpframe *fe_fpframe; /* FP registers, etc */ 149 uint32_t fe_fpsr; /* fpsr copy (modified during op) */ 150 uint32_t 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 */ 163 struct 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 190 struct instruction { 191 uint32_t is_pc; /* insn's address */ 192 uint32_t 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). */ 216 struct 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 */ 223 int fpu_shr(struct fpn *, int); 224 /* 225 * Round a number according to the round mode in FPCR 226 */ 227 int fpu_round(struct fpemu *, struct fpn *); 228 229 /* type conversion */ 230 void fpu_explode(struct fpemu *, struct fpn *, int t, const uint32_t *); 231 void fpu_implode(struct fpemu *, struct fpn *, int t, uint32_t *); 232 233 /* 234 * non-static emulation functions 235 */ 236 /* type 0 */ 237 int fpu_emul_fmovecr(struct fpemu *, struct instruction *); 238 int fpu_emul_fstore(struct fpemu *, struct instruction *); 239 int 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 246 int fpu_emulate(struct frame *, struct fpframe *, ksiginfo_t *); 247 struct fpn *fpu_cmp(struct fpemu *); 248 249 /* fpu_cordic.c */ 250 extern const struct fpn fpu_cordic_inv_gain1; 251 void fpu_cordit1(struct fpemu *, 252 struct fpn *, struct fpn *, struct fpn *, const struct fpn *); 253 254 /* 255 * "helper" functions 256 */ 257 /* return values from constant rom */ 258 struct fpn *fpu_const(struct fpn *, uint32_t); 259 #define FPU_CONST_PI (0x00) /* pi */ 260 #define FPU_CONST_0 (0x0f) /* 0.0 */ 261 #define FPU_CONST_LN_2 (0x30) /* ln(2) */ 262 #define FPU_CONST_LN_10 (0x31) /* ln(10) */ 263 #define FPU_CONST_1 (0x32) /* 1.0 */ 264 265 /* update exceptions and FPSR */ 266 int fpu_upd_excp(struct fpemu *); 267 uint32_t fpu_upd_fpsr(struct fpemu *, struct fpn *); 268 269 /* address mode decoder, and load/store */ 270 int fpu_decode_ea(struct frame *, struct instruction *, 271 struct insn_ea *, int); 272 int fpu_load_ea(struct frame *, struct instruction *, 273 struct insn_ea *, char *); 274 int fpu_store_ea(struct frame *, struct instruction *, 275 struct insn_ea *, char *); 276 277 /* fpu_subr.c */ 278 void fpu_norm(struct fpn *); 279 280 #if !defined(FPE_DEBUG) 281 # define FPE_DEBUG 0 282 #endif 283 284 #endif /* _FPU_EMULATE_H_ */ 285