|
|
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_ */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.