1 /* $Id: m6888x.c,v 1.4 2007/08/25 20:37:30 fredette Exp $ */
2 
3 /* ic/m68k/m6888x.c - m68k floating-point implementation */
4 
5 /*
6  * Copyright (c) 2004 Matt Fredette
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  * 3. All advertising materials mentioning features or use of this software
18  *    must display the following acknowledgement:
19  *      This product includes software developed by Matt Fredette.
20  * 4. The name of the author may not be used to endorse or promote products
21  *    derived from this software without specific prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
24  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
25  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
27  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
28  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
29  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
31  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
32  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33  * POSSIBILITY OF SUCH DAMAGE.
34  */
35 
36 #include <tme/common.h>
37 _TME_RCSID("$Id: m6888x.c,v 1.4 2007/08/25 20:37:30 fredette Exp $");
38 
39 /* includes: */
40 #include "m68k-impl.h"
41 
42 /* macros: */
43 
44 /* m6888x FPCR bits: */
45 #define TME_M6888X_FPCR_RND_MASK	(0x00000030)
46 #define  TME_M6888X_FPCR_RND_RN		 (0x00000000)
47 #define  TME_M6888X_FPCR_RND_RZ		 (0x00000010)
48 #define  TME_M6888X_FPCR_RND_RM		 (0x00000020)
49 #define  TME_M6888X_FPCR_RND_RP		 (0x00000030)
50 #define TME_M6888X_FPCR_PREC_MASK	(0x000000c0)
51 #define  TME_M6888X_FPCR_PREC_X		 (0x00000000)
52 #define  TME_M6888X_FPCR_PREC_S		 (0x00000040)
53 #define  TME_M6888X_FPCR_PREC_D		 (0x00000080)
54 #define  TME_M6888X_FPCR_PREC_UNDEF	 (0x000000c0)
55 #define TME_M6888X_FPCR_ENABLE_INEX1	TME_BIT(8)
56 #define TME_M6888X_FPCR_ENABLE_INEX2	TME_BIT(9)
57 #define TME_M6888X_FPCR_ENABLE_DZ	TME_BIT(10)
58 #define TME_M6888X_FPCR_ENABLE_UNFL	TME_BIT(11)
59 #define TME_M6888X_FPCR_ENABLE_OVFL	TME_BIT(12)
60 #define TME_M6888X_FPCR_ENABLE_OPERR	TME_BIT(13)
61 #define TME_M6888X_FPCR_ENABLE_SNAN	TME_BIT(14)
62 #define TME_M6888X_FPCR_ENABLE_BSUN	TME_BIT(15)
63 
64 /* m6888x FPSR bits: */
65 #define TME_M6888X_FPSR_AEXC_INEX	TME_BIT(3)
66 #define TME_M6888X_FPSR_AEXC_DZ		TME_BIT(4)
67 #define TME_M6888X_FPSR_AEXC_UNFL	TME_BIT(5)
68 #define TME_M6888X_FPSR_AEXC_OVFL	TME_BIT(6)
69 #define TME_M6888X_FPSR_AEXC_IOP	TME_BIT(7)
70 #define TME_M6888X_FPSR_EXC_INEX1	TME_M6888X_FPCR_ENABLE_INEX1
71 #define TME_M6888X_FPSR_EXC_INEX2	TME_M6888X_FPCR_ENABLE_INEX2
72 #define TME_M6888X_FPSR_EXC_DZ		TME_M6888X_FPCR_ENABLE_DZ
73 #define TME_M6888X_FPSR_EXC_UNFL	TME_M6888X_FPCR_ENABLE_UNFL
74 #define TME_M6888X_FPSR_EXC_OVFL	TME_M6888X_FPCR_ENABLE_OVFL
75 #define TME_M6888X_FPSR_EXC_OPERR	TME_M6888X_FPCR_ENABLE_OPERR
76 #define TME_M6888X_FPSR_EXC_SNAN	TME_M6888X_FPCR_ENABLE_SNAN
77 #define TME_M6888X_FPSR_EXC_BSUN	TME_M6888X_FPCR_ENABLE_BSUN
78 #define TME_M6888X_FPSR_QUOTIENT	(0x00ff0000)
79 #define TME_M6888X_FPSR_CC_NAN		TME_BIT(24)
80 #define TME_M6888X_FPSR_CC_I		TME_BIT(25)
81 #define TME_M6888X_FPSR_CC_Z		TME_BIT(26)
82 #define TME_M6888X_FPSR_CC_N		TME_BIT(27)
83 
84 /* m6888x exceptions: */
85 #define TME_M6888X_VECTOR_BSUN		(0x30)
86 #define TME_M6888X_VECTOR_INEX		(0x31)
87 #define TME_M6888X_VECTOR_DZ		(0x32)
88 #define TME_M6888X_VECTOR_UNFL		(0x33)
89 #define TME_M6888X_VECTOR_OPERR		(0x34)
90 #define TME_M6888X_VECTOR_OVFL		(0x35)
91 #define TME_M6888X_VECTOR_SNAN		(0x36)
92 
93 /* m6888x frame versions: */
94 #define TME_M6888X_FRAME_VERSION_NULL		(0x00)
95 #define TME_M6888X_FRAME_VERSION_IDLE_M68881	(0x1f)
96 #define TME_M6888X_FRAME_VERSION_IDLE_M68882	(0x21)
97 #define TME_M6888X_FRAME_VERSION_IDLE_M68040	(0x23)
98 
99 /* m6888x frame sizes: */
100 #define TME_M6888X_FRAME_SIZE_NULL		(0x00)
101 #define TME_M6888X_FRAME_SIZE_IDLE_M68881	(0x18)
102 #define TME_M6888X_FRAME_SIZE_IDLE_M68882	(0x38)
103 #define TME_M6888X_FRAME_SIZE_IDLE_M68040	(0x00)
104 
105 /* bits in a packed decimal real: */
106 #define TME_M6888X_PACKEDDEC_SM		TME_BIT(31)
107 #define TME_M6888X_PACKEDDEC_SE		TME_BIT(30)
108 #define TME_M6888X_PACKEDDEC_YY		(TME_BIT(29) | TME_BIT(28))
109 
110 /* rounding precisions: */
111 #define TME_M6888X_ROUNDING_PRECISION_CTL		(0)
112 #define TME_M6888X_ROUNDING_PRECISION_SINGLE		(32)
113 #define TME_M6888X_ROUNDING_PRECISION_DOUBLE		(64)
114 #define TME_M6888X_ROUNDING_PRECISION_EXTENDED80	(80)
115 
116 /* operation types: */
117 #define TME_M6888X_OPTYPE_MONADIC		(0)
118 #define TME_M6888X_OPTYPE_DYADIC_SRC_DST	(1)
119 #define TME_M6888X_OPTYPE_DYADIC_DST_SRC	(2)
120 
121 /* special opmodes: */
122 #define TME_M6888X_FPGEN_OPMODE_FCMP	(0x38)
123 #define TME_M6888X_FPGEN_OPMODE_FTST	(0x3a)
124 #define TME_M6888X_FPGEN_OPMODE_OTHER	(0xff)
125 
126 /* this causes an exception if there is no FPU, or if it isn't enabled: */
127 #define TME_M68K_INSN_FPU				\
128 do {							\
129   if (!ic->tme_m68k_fpu_enabled) {			\
130     TME_M68K_INSN_EXCEPTION(TME_M68K_EXCEPTION_ILL);	\
131   }							\
132 } while (/* CONSTCOND */ 0)
133 
134 /* these declare an m68k FPgen function: */
135 #define TME_M6888X_FPGEN_DECL(name)		\
136   static void name _TME_P((struct tme_m68k *, const struct tme_float *, struct tme_float *))
137 #ifdef __STDC__
138 #define TME_M6888X_FPGEN(name)			\
139   static void name(struct tme_m68k *ic, const struct tme_float *src, struct tme_float *dst)
140 #else  /* !__STDC__ */
141 #define TME_M6888X_FPGEN(name)			\
142   static void name(ic, src, dst)		\
143   struct tme_m68k *ic;				\
144   const struct tme_float *src;	\
145   struct tme_float *dst;
146 #endif /* !__STDC__ */
147 
148 /* this gets the offset of a function in the IEEE 754 operations structure: */
149 #define TME_M6888X_IEEE754_OP(func)	((unsigned long) ((char *) &((struct tme_ieee754_ops *) 0)->func))
150 
151 /* these invoke an IEEE 754 operation: */
152 #define _TME_M6888X_IEEE754_OP(func, x)			\
153 do {							\
154   if ((func) == NULL) {					\
155     if (ic->tme_m68k_fpu_incomplete_abort) {		\
156       abort();						\
157     }							\
158     TME_M68K_INSN_EXCEPTION(TME_M68K_EXCEPTION_ILL);	\
159   }							\
160   (*(func)) x;						\
161 } while (/* CONSTCOND */ 0)
162 #define TME_M6888X_IEEE754_OP_MONADIC(func, src, dst) \
163   _TME_M6888X_IEEE754_OP(ic->tme_m68k_fpu_ieee754_ops->func, (&ic->tme_m68k_fpu_ieee754_ctl, src, dst))
164 #define TME_M6888X_IEEE754_OP_DYADIC(func, src0, src1, dst) \
165   _TME_M6888X_IEEE754_OP(ic->tme_m68k_fpu_ieee754_ops->func, (&ic->tme_m68k_fpu_ieee754_ctl, src0, src1, dst))
166 #define TME_M6888X_IEEE754_OP_FUNC(ops_offset) \
167   (*((void **) (((char *) ic->tme_m68k_fpu_ieee754_ops) + (ops_offset))))
168 #define TME_M6888X_IEEE754_OP_RUN(ops_offset, t, x) \
169   _TME_M6888X_IEEE754_OP(((void (*) _TME_P(t)) TME_M6888X_IEEE754_OP_FUNC(ops_offset)), x)
170 
171 /* this gets the Nth raw unsigned 32-bit word from an EA operand: */
172 #define TME_M6888X_EA_OP32(n)   (ic->tme_m68k_ireg_uint32(op1_ireg32 + (n)))
173 
174 /* this gets the Nth raw digit from a packed decimal operand: */
175 #define TME_M6888X_PD_DIGIT(n)  ((TME_M6888X_EA_OP32((n) / 8) >> (4 * ((n) % 8))) & 0xf)
176 
177 /* types: */
178 
179 /* the FPgen opmode table: */
180 struct tme_m6888x_fpgen {
181 
182   /* any m6888x-specific function.  this is normally NULL: */
183   void (*tme_m6888x_fpgen_func) _TME_P((struct tme_m68k *,
184 					const struct tme_float *,
185 					struct tme_float *));
186 
187   /* unless there is an m6888x-specific function, this is the offset
188      in the IEEE 754 operations struct of the function: */
189   unsigned long tme_m6888x_fpgen_func_ops_offset;
190 
191   /* the FPU types that have this function: */
192   tme_uint8_t tme_m6888x_fpgen_fpu_types;
193 
194   /* the operation type: */
195   tme_uint8_t tme_m6888x_fpgen_optype;
196 
197   /* the rounding mode used by the function: */
198   tme_uint8_t tme_m6888x_fpgen_rounding_mode;
199 
200   /* the rounding precision used by the function: */
201   tme_uint8_t tme_m6888x_fpgen_rounding_precision;
202 };
203 
204 /* an m6888x frame: */
205 struct tme_m6888x_frame {
206 
207   /* the frame version: */
208   tme_uint8_t tme_m6888x_frame_version;
209 
210   /* the frame size: */
211   tme_uint8_t tme_m6888x_frame_size;
212 
213   /* reserved: */
214   tme_uint16_t tme_m6888x_frame_reserved2;
215 
216   /* the command/condition register for an IDLE frame: */
217   tme_uint16_t tme_m6888x_frame_ccr;
218 
219   /* reserved: */
220   tme_uint16_t tme_m6888x_frame_reserved6;
221 
222   /* additional words: */
223   tme_uint32_t tme_m6888x_frame_words[(TME_M6888X_FRAME_SIZE_IDLE_M68882 / sizeof(tme_uint32_t)) - 1];
224 };
225 
226 /* prototypes: */
227 TME_M6888X_FPGEN_DECL(_tme_m6888x_fmovecr);
228 TME_M6888X_FPGEN_DECL(_tme_m6888x_fsincos);
229 TME_M6888X_FPGEN_DECL(_tme_m6888x_fcmp);
230 TME_M6888X_FPGEN_DECL(_tme_m6888x_ftst);
231 TME_M6888X_FPGEN_DECL(_tme_m6888x_ftwotox);
232 TME_M6888X_FPGEN_DECL(_tme_m6888x_ftentox);
233 TME_M6888X_FPGEN_DECL(_tme_m6888x_flog2);
234 TME_M6888X_FPGEN_DECL(_tme_m6888x_fmod);
235 TME_M6888X_FPGEN_DECL(_tme_m6888x_frem);
236 TME_M6888X_FPGEN_DECL(_tme_m6888x_fsgldiv);
237 TME_M6888X_FPGEN_DECL(_tme_m6888x_fsglmul);
238 
239 /* globals: */
240 
241 /* special fpgen structures: */
242 static const struct tme_m6888x_fpgen _tme_m6888x_fpgen_fmovecr = {
243   _tme_m6888x_fmovecr,
244   0,
245   TME_M68K_FPU_ANY,
246   TME_M6888X_OPTYPE_MONADIC,
247   TME_FLOAT_ROUND_NULL,
248   TME_M6888X_ROUNDING_PRECISION_CTL
249 };
250 static const struct tme_m6888x_fpgen _tme_m6888x_fpgen_fmove_rm = {
251   NULL,
252   0,
253   TME_M68K_FPU_ANY,
254   TME_M6888X_OPTYPE_MONADIC,
255   TME_FLOAT_ROUND_NULL,
256   TME_M6888X_ROUNDING_PRECISION_CTL
257 };
258 
259 /* include the automatically generated code: */
260 #include "m6888x-auto.c"
261 
262 /* this resets the FPU: */
263 void
tme_m68k_fpu_reset(struct tme_m68k * ic)264 tme_m68k_fpu_reset(struct tme_m68k *ic)
265 {
266   unsigned int fp_i;
267 
268   /* put nonsignaling NaNs in the floating-point data registers: */
269   for (fp_i = 0;
270        fp_i < (sizeof(ic->tme_m68k_fpu_fpreg) / sizeof(ic->tme_m68k_fpu_fpreg[0]));
271        fp_i++) {
272     ic->tme_m68k_fpu_fpreg[fp_i].tme_float_format = TME_FLOAT_FORMAT_IEEE754_EXTENDED80;
273     ic->tme_m68k_fpu_fpreg[fp_i].tme_float_value_ieee754_extended80 = ic->tme_m68k_fpu_ieee754_ctl.tme_ieee754_ctl_default_nan_extended80;
274   }
275 
276   /* put zeroes in the floating-point control register, status
277      register, and instruction address register: */
278   ic->tme_m68k_fpu_fpcr = 0;
279   ic->tme_m68k_fpu_fpsr = 0;
280   ic->tme_m68k_fpu_fpiar = 0;
281 }
282 
283 /* this handles an exception: */
284 static void
_tme_m6888x_exception(struct tme_m68k * ic,tme_uint32_t exceptions)285 _tme_m6888x_exception(struct tme_m68k *ic, tme_uint32_t exceptions)
286 {
287   tme_uint8_t vector;
288 
289   /* update the EXC byte in the FPSR: */
290   ic->tme_m68k_fpu_fpsr |= exceptions;
291 
292   /* update the AEXC byte in the FPSR: */
293   if (exceptions & (TME_M6888X_FPSR_EXC_SNAN | TME_M6888X_FPSR_EXC_OPERR | TME_M6888X_FPSR_EXC_BSUN)) {
294     ic->tme_m68k_fpu_fpsr |= TME_M6888X_FPSR_AEXC_IOP;
295   }
296   if (exceptions & TME_M6888X_FPSR_EXC_OVFL) {
297     ic->tme_m68k_fpu_fpsr |= TME_M6888X_FPSR_AEXC_OVFL;
298   }
299   if (exceptions & (TME_M6888X_FPSR_EXC_UNFL | TME_M6888X_FPSR_EXC_INEX2)) {
300     ic->tme_m68k_fpu_fpsr |= TME_M6888X_FPSR_AEXC_UNFL;
301   }
302   if (exceptions & TME_M6888X_FPSR_EXC_DZ) {
303     ic->tme_m68k_fpu_fpsr |= TME_M6888X_FPSR_AEXC_DZ;
304   }
305   if (exceptions & (TME_M6888X_FPSR_EXC_INEX1 | TME_M6888X_FPSR_EXC_INEX2 | TME_M6888X_FPSR_EXC_OVFL)) {
306     ic->tme_m68k_fpu_fpsr |= TME_M6888X_FPSR_AEXC_INEX;
307   }
308 
309   /* if any of the new exceptions are unmasked, take the exception: */
310   if ((ic->tme_m68k_fpu_fpcr & exceptions)) {
311 
312     /* because it's possible for an instruction to cause multiple
313        exceptions, the exceptions are prioritized: */
314     /* XXX FIXME - when the predecrement or postincrement addressing
315        modes are used, are the address registers updated before or
316        after any exceptions are generated? */
317     if (exceptions & TME_M6888X_FPSR_EXC_BSUN) {
318       vector = TME_M6888X_VECTOR_BSUN;
319     }
320     else if (exceptions & TME_M6888X_FPSR_EXC_SNAN) {
321       vector = TME_M6888X_VECTOR_SNAN;
322     }
323     else if (exceptions & TME_M6888X_FPSR_EXC_OPERR) {
324       vector = TME_M6888X_VECTOR_OPERR;
325     }
326     else if (exceptions & TME_M6888X_FPSR_EXC_OVFL) {
327       vector = TME_M6888X_VECTOR_OVFL;
328     }
329     else if (exceptions & TME_M6888X_FPSR_EXC_UNFL) {
330       vector = TME_M6888X_VECTOR_UNFL;
331     }
332     else if (exceptions & TME_M6888X_FPSR_EXC_DZ) {
333       vector = TME_M6888X_VECTOR_DZ;
334     }
335     else {
336       assert (exceptions & (TME_M6888X_FPSR_EXC_INEX2 | TME_M6888X_FPSR_EXC_INEX1));
337       vector = TME_M6888X_VECTOR_INEX;
338     }
339 
340     /* unlock any lock: */
341     if (ic->tme_m68k_fpu_ieee754_ctl.tme_ieee754_ctl_lock_unlock != NULL) {
342       (*ic->tme_m68k_fpu_ieee754_ctl.tme_ieee754_ctl_lock_unlock)();
343       ic->tme_m68k_fpu_ieee754_ctl.tme_ieee754_ctl_lock_unlock = NULL;
344     }
345 
346     /* take the exception: */
347     /* XXX FIXME - we signal all m6888x exceptions as cp
348        Postinstruction exceptions.  exceptions generated by a cpGEN
349        instruction are probably supposed to be cp Preinstruction
350        exceptions, signaled at the time of the next cpGEN instruction: */
351     ic->tme_m68k_ireg_pc_last = ic->tme_m68k_ireg_pc;
352     ic->tme_m68k_ireg_pc = ic->tme_m68k_ireg_pc_next;
353     TME_M68K_INSN_EXCEPTION(TME_M68K_EXCEPTION_INST(vector));
354   }
355 }
356 
357 /* the IEEE 754 exception handler: */
358 static void
_tme_m6888x_exception_ieee754(struct tme_ieee754_ctl * ctl,tme_int8_t exceptions_ieee754)359 _tme_m6888x_exception_ieee754(struct tme_ieee754_ctl *ctl, tme_int8_t exceptions_ieee754)
360 {
361   tme_uint32_t exceptions_m6888x;
362 
363   /* map the exceptions: */
364   exceptions_m6888x = 0;
365   if (exceptions_ieee754 & TME_FLOAT_EXCEPTION_GENERIC) {
366     exceptions_m6888x |= TME_M6888X_FPSR_EXC_OPERR;
367   }
368   if (exceptions_ieee754 & TME_FLOAT_EXCEPTION_INVALID) {
369     exceptions_m6888x |= TME_M6888X_FPSR_EXC_OPERR;
370   }
371   if (exceptions_ieee754 & TME_FLOAT_EXCEPTION_DIVBYZERO) {
372     exceptions_m6888x |= TME_M6888X_FPSR_EXC_DZ;
373   }
374   if (exceptions_ieee754 & TME_FLOAT_EXCEPTION_OVERFLOW) {
375     exceptions_m6888x |= TME_M6888X_FPSR_EXC_OVFL;
376   }
377   if (exceptions_ieee754 & TME_FLOAT_EXCEPTION_UNDERFLOW) {
378     exceptions_m6888x |= TME_M6888X_FPSR_EXC_UNFL;
379   }
380   if (exceptions_ieee754 & TME_FLOAT_EXCEPTION_INEXACT) {
381     exceptions_m6888x |= TME_M6888X_FPSR_EXC_INEX2;
382   }
383   if (exceptions_ieee754 & TME_FLOAT_EXCEPTION_OVERFLOW_INT) {
384     exceptions_m6888x |= TME_M6888X_FPSR_EXC_OVFL;
385   }
386   /* XXX FIXME - do denormals count as INEX2? */
387   if (exceptions_ieee754 & TME_FLOAT_EXCEPTION_DENORMAL) {
388     exceptions_m6888x |= TME_M6888X_FPSR_EXC_INEX2;
389   }
390 
391   _tme_m6888x_exception((struct tme_m68k *) ctl->tme_ieee754_ctl_private, exceptions_m6888x);
392 }
393 
394 /* signaling NaN tests: */
395 #define _TME_M6888X_IS_SNAN(a) (((a)->tme_float_ieee754_extended80_significand.tme_value64_uint32_hi & TME_BIT(30)) == 0)
396 static tme_int8_t
_tme_m6888x_is_snan_extended80(struct tme_float_ieee754_extended80 * value)397 _tme_m6888x_is_snan_extended80(struct tme_float_ieee754_extended80 *value)
398 {
399   return (_TME_M6888X_IS_SNAN(value));
400 }
401 
402 /* NaN propagation: */
403 static void
_tme_m6888x_nan_from_nans_extended80(struct tme_ieee754_ctl * ctl,const struct tme_float_ieee754_extended80 * a,const struct tme_float_ieee754_extended80 * b,struct tme_float_ieee754_extended80 * z)404 _tme_m6888x_nan_from_nans_extended80(struct tme_ieee754_ctl *ctl,
405 				     const struct tme_float_ieee754_extended80 *a,
406 				     const struct tme_float_ieee754_extended80 *b,
407 				     struct tme_float_ieee754_extended80 *z)
408 {
409   struct tme_m68k *ic;
410   int a_is_snan;
411   int b_is_snan;
412 
413   /* recover the m68k: */
414   ic = ctl->tme_ieee754_ctl_private;
415 
416   /* see if any of the NaNs are signaling NaNs: */
417   a_is_snan = _TME_M6888X_IS_SNAN(a);
418   b_is_snan = _TME_M6888X_IS_SNAN(b);
419 
420   /* if either operand is a signaling NaN: */
421   if (a_is_snan || b_is_snan) {
422 
423     /* signal the signaling NaN: */
424     _tme_m6888x_exception(ic, TME_M6888X_FPSR_EXC_SNAN);
425   }
426 
427   /* if a and b are different NaNs: */
428   if ((a->tme_float_ieee754_extended80_sexp
429        != b->tme_float_ieee754_extended80_sexp)
430       || (a->tme_float_ieee754_extended80_significand.tme_value64_uint32_hi
431 	  != b->tme_float_ieee754_extended80_significand.tme_value64_uint32_hi)
432       || (a->tme_float_ieee754_extended80_significand.tme_value64_uint32_lo
433 	  != b->tme_float_ieee754_extended80_significand.tme_value64_uint32_lo)) {
434 
435     /* we need to return the NaN that is the destination operand: */
436     switch (_tme_m6888x_fpgen_opmode_table[TME_FIELD_EXTRACTU(TME_M68K_INSN_SPECOP, 0, 7)].tme_m6888x_fpgen_optype) {
437     default:
438     case TME_M6888X_OPTYPE_MONADIC: assert(FALSE);
439     case TME_M6888X_OPTYPE_DYADIC_SRC_DST: a = b; break;
440     case TME_M6888X_OPTYPE_DYADIC_DST_SRC: break;
441     }
442   }
443 
444   /* return a as the NaN, but make sure it's nonsignaling: */
445   *z = *a;
446   z->tme_float_ieee754_extended80_significand.tme_value64_uint32_hi |= TME_BIT(30);
447 }
448 
449 /* this prepares to run an fpgen instruction: */
450 static void inline
_tme_m6888x_fpgen_enter(struct tme_m68k * ic,const struct tme_m6888x_fpgen * fpgen)451 _tme_m6888x_fpgen_enter(struct tme_m68k *ic, const struct tme_m6888x_fpgen *fpgen)
452 {
453   tme_int8_t rounding_mode;
454   tme_int8_t rounding_precision;
455 
456   /* set the rounding mode: */
457   rounding_mode = fpgen->tme_m6888x_fpgen_rounding_mode;
458   if (__tme_predict_true(rounding_mode == TME_FLOAT_ROUND_NULL)) {
459     switch (ic->tme_m68k_fpu_fpcr & TME_M6888X_FPCR_RND_MASK) {
460     default: assert(FALSE);
461     case TME_M6888X_FPCR_RND_RN: rounding_mode = TME_FLOAT_ROUND_NEAREST_EVEN; break;
462     case TME_M6888X_FPCR_RND_RZ: rounding_mode = TME_FLOAT_ROUND_TO_ZERO; break;
463     case TME_M6888X_FPCR_RND_RM: rounding_mode = TME_FLOAT_ROUND_DOWN; break;
464     case TME_M6888X_FPCR_RND_RP: rounding_mode = TME_FLOAT_ROUND_UP; break;
465     }
466   }
467   ic->tme_m68k_fpu_ieee754_ctl.tme_ieee754_ctl_rounding_mode = rounding_mode;
468 
469   /* set the rounding precision: */
470   rounding_precision = fpgen->tme_m6888x_fpgen_rounding_precision;
471   if (__tme_predict_true(rounding_precision == TME_M6888X_ROUNDING_PRECISION_CTL)) {
472     switch (ic->tme_m68k_fpu_fpcr & TME_M6888X_FPCR_PREC_MASK) {
473     default: assert(FALSE); /* FALLTHROUGH */
474     case TME_M6888X_FPCR_PREC_UNDEF: /* FALLTHROUGH */
475     case TME_M6888X_FPCR_PREC_X: rounding_precision = TME_M6888X_ROUNDING_PRECISION_EXTENDED80; break;
476     case TME_M6888X_FPCR_PREC_S: rounding_precision = TME_M6888X_ROUNDING_PRECISION_SINGLE; break;
477     case TME_M6888X_FPCR_PREC_D: rounding_precision = TME_M6888X_ROUNDING_PRECISION_DOUBLE; break;
478     }
479   }
480   ic->tme_m68k_fpu_ieee754_ctl.tme_ieee754_ctl_extended80_rounding_precision = rounding_precision;
481 
482   /* clear the exception status byte in the FPSR: */
483   ic->tme_m68k_fpu_fpsr
484     &= ~(TME_M6888X_FPSR_EXC_INEX1
485 	 | TME_M6888X_FPSR_EXC_INEX2
486 	 | TME_M6888X_FPSR_EXC_DZ
487 	 | TME_M6888X_FPSR_EXC_UNFL
488 	 | TME_M6888X_FPSR_EXC_OVFL
489 	 | TME_M6888X_FPSR_EXC_OPERR
490 	 | TME_M6888X_FPSR_EXC_SNAN
491 	 | TME_M6888X_FPSR_EXC_BSUN);
492 
493   /* set the FPIAR: */
494   ic->tme_m68k_fpu_fpiar = ic->tme_m68k_ireg_pc;
495 }
496 
497 /* this sets the floating-point condition codes: */
498 static void inline
_tme_m6888x_fpcc(struct tme_m68k * ic,const struct tme_float * dst,unsigned int dst_formats)499 _tme_m6888x_fpcc(struct tme_m68k *ic, const struct tme_float *dst, unsigned int dst_formats)
500 {
501   tme_uint32_t fpcc;
502 
503   /* start with no floating-point condition codes: */
504   fpcc = 0;
505 
506   /* set N: */
507   if (tme_float_is_negative(dst, dst_formats)) {
508     fpcc |= TME_M6888X_FPSR_CC_N;
509   }
510 
511   /* set NAN or I or Z: */
512   if (tme_float_is_nan(dst, dst_formats)) {
513     fpcc |= TME_M6888X_FPSR_CC_NAN;
514   }
515   else if (tme_float_is_inf(dst, dst_formats)) {
516     fpcc |= TME_M6888X_FPSR_CC_I;
517   }
518   else if (tme_float_is_zero(dst, dst_formats)) {
519     fpcc |= TME_M6888X_FPSR_CC_Z;
520   }
521 
522   /* set the floating-point condition codes: */
523   ic->tme_m68k_fpu_fpsr
524     = ((ic->tme_m68k_fpu_fpsr
525 	& ~(TME_M6888X_FPSR_CC_N
526 	    | TME_M6888X_FPSR_CC_NAN
527 	    | TME_M6888X_FPSR_CC_I
528 	    | TME_M6888X_FPSR_CC_Z))
529        | fpcc);
530 }
531 
TME_M68K_INSN(tme_m68k_fpgen)532 TME_M68K_INSN(tme_m68k_fpgen)
533 {
534   struct tme_ieee754_ctl *ieee754_ctl;
535   tme_uint16_t command;
536   tme_uint16_t opmode;
537   const struct tme_m6888x_fpgen *fpgen;
538   unsigned int src_ea;
539   const struct tme_float *src;
540   struct tme_float *dst;
541   struct tme_float src_buffer;
542   struct tme_float dst_buffer;
543   struct tme_float conv_buffer;
544   union tme_value64 value64_buffer;
545   struct tme_float_ieee754_extended80 extended80_buffer;
546   unsigned int ea_mode;
547   unsigned int ea_reg;
548   unsigned int ea_size;
549   unsigned int op1_ireg32;
550   unsigned int src_specifier;
551   unsigned int digit_i;
552   tme_int32_t packed_value_int32;
553   struct tme_float packed_value_float;
554   tme_int32_t exponent;
555 
556   /* get the IEEE 754 ctl: */
557   ieee754_ctl = &ic->tme_m68k_fpu_ieee754_ctl;
558 
559   /* this is an FPU instruction: */
560   TME_M68K_INSN_FPU;
561 
562   /* get the coprocessor-dependent command word: */
563   command = TME_M68K_INSN_SPECOP;
564 
565   /* if this is an FMOVECR instruction
566      (command word pattern 0101 11dd dooo oooo): */
567   if ((command & 0xfc00) == 0x5c00
568       && TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 0, 6) == 0) {
569 
570     /* use the FMOVECR opmode and FPgen structure: */
571     opmode = TME_M6888X_FPGEN_OPMODE_OTHER;
572     fpgen = &_tme_m6888x_fpgen_fmovecr;
573 
574     /* the source operand does not use the EA: */
575     src_ea = FALSE;
576   }
577 
578   /* otherwise, this is a generic FPgen instruction: */
579   else {
580 
581     /* get the opmode: */
582     opmode = TME_FIELD_EXTRACTU(command, 0, 7);
583 
584     /* decode this instruction: */
585     fpgen = &_tme_m6888x_fpgen_opmode_table[opmode];
586 
587     /* the source operand uses the EA if this is an EA-to-register
588        operation: */
589     src_ea = (command & TME_BIT(14)) != 0;
590   }
591 
592   /* catch illegal instructions: */
593   switch (fpgen->tme_m6888x_fpgen_fpu_types) {
594 
595   case TME_M68K_FPU_M6888X:
596     /* instructions not supported in hardware by the m68040 are caught
597        later: */
598   case TME_M68K_FPU_ANY:
599     break;
600 
601   case TME_M68K_FPU_M68040:
602     if (ic->tme_m68k_fpu_type == TME_M68K_FPU_M68040) {
603       break;
604     }
605     /* FALLTHROUGH */
606   case TME_M68K_FPU_NONE:
607     TME_M68K_INSN_EXCEPTION(TME_M68K_EXCEPTION_ILL);
608     break;
609   default:
610     abort();
611   }
612 
613   /* get the source specifier: */
614   src_specifier = TME_FIELD_EXTRACTU(command, 10, 3);
615 
616   /* if the source operand uses the EA: */
617   if (src_ea) {
618 
619     /* assume that the most-significant first 32-bit part of the
620        source operand will end up in the internal memx register: */
621     op1_ireg32 = TME_M68K_IREG_MEMX32;
622 
623     /* get the EA mode and register fields: */
624     ea_mode = TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 3, 3);
625     ea_reg = TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 0, 3);
626 
627     /* if this is a data register direct EA: */
628     if (ea_mode == 0) {
629 
630       /* dispatch on the source specifier, since we need to
631 	 sign-extend a byte or word to long, and we need to check that
632 	 only a byte, word, long, or single precision source is
633 	 specified: */
634       switch (src_specifier) {
635       case TME_M6888X_TYPE_LONG:
636       case TME_M6888X_TYPE_SINGLE:
637 	op1_ireg32 = TME_M68K_IREG_D0 + ea_reg;
638 	break;
639       case TME_M6888X_TYPE_WORD:
640 	ic->tme_m68k_ireg_int32(TME_M68K_IREG_MEMX32) = (tme_int16_t) TME_M68K_INSN_OP1(tme_int32_t);
641 	break;
642       case TME_M6888X_TYPE_BYTE:
643 	ic->tme_m68k_ireg_int32(TME_M68K_IREG_MEMX32) = (tme_int8_t) TME_M68K_INSN_OP1(tme_int32_t);
644 	break;
645       default:
646 	TME_M68K_INSN_EXCEPTION(TME_M68K_EXCEPTION_ILL);
647 	break;
648       }
649     }
650 
651     /* otherwise, if this is an address register direct EA: */
652     else if (ea_mode == 1) {
653       TME_M68K_INSN_EXCEPTION(TME_M68K_EXCEPTION_ILL);
654     }
655 
656     /* otherwise, if this is an immediate EA: */
657     else if (ea_mode == 7
658 	     && ea_reg == 4) {
659 
660       /* _op1 already points to the operand as one or more 32-bit
661          words: */
662       assert (_op1 == &ic->tme_m68k_ireg_uint32(TME_M68K_IREG_IMM32 + 0));
663       op1_ireg32 = TME_M68K_IREG_IMM32;
664     }
665 
666     /* otherwise, this is a memory EA: */
667     else {
668 
669       /* this instruction can fault: */
670       TME_M68K_INSN_CANFAULT;
671 
672       /* adjust ea_reg to reference the address register: */
673       ea_reg += TME_M68K_IREG_A0;
674 
675       /* dispatch on the source specifier to size the operand: */
676       switch (src_specifier) {
677       case TME_M6888X_TYPE_LONG:
678       case TME_M6888X_TYPE_SINGLE:
679 	ea_size = TME_M68K_SIZE_32;
680 	break;
681 
682       case TME_M6888X_TYPE_PACKEDDEC:
683       case TME_M6888X_TYPE_EXTENDED80:
684 	ea_size = TME_M68K_SIZE_96;
685 	break;
686 
687       case TME_M6888X_TYPE_WORD:
688 	ea_size = TME_M68K_SIZE_16;
689 	break;
690 
691       case TME_M6888X_TYPE_DOUBLE:
692 	ea_size = TME_M68K_SIZE_64;
693 	break;
694 
695       case TME_M6888X_TYPE_BYTE:
696 	ea_size = TME_M68K_SIZE_8;
697 	break;
698 
699       default:
700 	abort();
701       }
702 
703       /* for the effective address predecrement and postincrement
704 	 modes, we require that these size macros correspond exactly
705 	 to the number of bytes: */
706 #if TME_M68K_SIZE_8 != 1
707 #error "TME_M68K_SIZE_8 must be 1"
708 #endif
709 #if TME_M68K_SIZE_16 != 2
710 #error "TME_M68K_SIZE_16 must be 2"
711 #endif
712 #if TME_M68K_SIZE_32 != 4
713 #error "TME_M68K_SIZE_32 must be 4"
714 #endif
715 #if TME_M68K_SIZE_64 != 8
716 #error "TME_M68K_SIZE_64 must be 8"
717 #endif
718 #if TME_M68K_SIZE_96 != 12
719 #error "TME_M68K_SIZE_96 must be 12"
720 #endif
721 #define TME_M68K_AREG_INCREMENT(areg, size) \
722   ((size) + (((size) == TME_M68K_SIZE_8 && (areg) == TME_M68K_IREG_A7) ? 1 : 0))
723 
724       /* address register indirect postincrement: */
725       if (ea_mode == 3) {
726 	/* if we are not restarting, set the effective address: */
727 	if (!TME_M68K_SEQUENCE_RESTARTING) {
728 	  ic->_tme_m68k_ea_address = ic->tme_m68k_ireg_uint32(ea_reg);
729 	  ic->tme_m68k_ireg_uint32(ea_reg) += TME_M68K_AREG_INCREMENT(ea_reg, ea_size);
730 	}
731       }
732 
733       /* address register indirect predecrement: */
734       else if (ea_mode == 4) {
735 	/* if we are not restarting, set the effective address: */
736 	if (!TME_M68K_SEQUENCE_RESTARTING) {
737 	  ic->tme_m68k_ireg_uint32(ea_reg) -= TME_M68K_AREG_INCREMENT(ea_reg, ea_size);
738 	  ic->_tme_m68k_ea_address = ic->tme_m68k_ireg_uint32(ea_reg);
739 	}
740       }
741 
742       /* dispatch on the operand size to read in the operand as one or
743          more 32-bit words.  we will read up to three 32-bit words
744          into memx, memy, and memz: */
745       assert ((TME_M68K_IREG_MEMX32 + 1) == TME_M68K_IREG_MEMY32
746 	      && (TME_M68K_IREG_MEMY32 + 1) == TME_M68K_IREG_MEMZ32);
747       switch (ea_size) {
748 
749 	/* this can only happen when the source operand is a byte.  we
750 	   sign-extend the byte to a long: */
751       case TME_M68K_SIZE_8:
752 	tme_m68k_read_memx8(ic);
753 	assert (!TME_M68K_SEQUENCE_RESTARTING);
754 	ic->tme_m68k_ireg_memx32 = TME_EXT_S8_S32((tme_int8_t) ic->tme_m68k_ireg_memx8);
755 	break;
756 
757 	/* this can only happen when the source operand is a word.  we
758 	   sign-extend the word to a long: */
759       case TME_M68K_SIZE_16:
760 	tme_m68k_read_memx16(ic);
761 	assert (!TME_M68K_SEQUENCE_RESTARTING);
762 	ic->tme_m68k_ireg_memx32 = TME_EXT_S16_S32((tme_int16_t) ic->tme_m68k_ireg_memx16);
763 	break;
764 
765 	/* everything else is one or more 32-bit words: */
766       default:
767 
768 	/* read the first 32 bits into the memx register: */
769 	tme_m68k_read_memx32(ic);
770 	if (ea_size == TME_M68K_SIZE_32) {
771 	  break;
772 	}
773 
774 	/* read the second 32 bits into the memy register: */
775 	if (!TME_M68K_SEQUENCE_RESTARTING) {
776 	  ic->_tme_m68k_ea_address += TME_M68K_SIZE_32;
777 	}
778 	tme_m68k_read_mem32(ic, TME_M68K_IREG_MEMY32);
779 	if (ea_size == TME_M68K_SIZE_64) {
780 	  break;
781 	}
782 
783 	/* read the third 32 bits into the memz register: */
784 	if (!TME_M68K_SEQUENCE_RESTARTING) {
785 	  ic->_tme_m68k_ea_address += TME_M68K_SIZE_32;
786 	}
787 	tme_m68k_read_mem32(ic, TME_M68K_IREG_MEMZ32);
788 	break;
789       }
790     }
791 
792     /* convert the operand from one or more raw 32-bit words into the
793        internal extended precision format: */
794     switch (src_specifier) {
795 
796       /* convert a 32-bit integral value.  all of these integral types
797 	 have already been converted into 32-bit signed integers: */
798     case TME_M6888X_TYPE_BYTE:
799     case TME_M6888X_TYPE_WORD:
800     case TME_M6888X_TYPE_LONG:
801       tme_ieee754_extended80_from_int32((tme_int32_t) TME_M6888X_EA_OP32(0), &src_buffer);
802       break;
803 
804       /* convert a single-precision value: */
805     case TME_M6888X_TYPE_SINGLE:
806       tme_ieee754_single_value_set(&conv_buffer, TME_M6888X_EA_OP32(0));
807       TME_M6888X_IEEE754_OP_MONADIC(tme_ieee754_ops_extended80_from_single,
808 				    &conv_buffer,
809 				    &src_buffer);
810       break;
811 
812       /* convert a double-precision value: */
813     case TME_M6888X_TYPE_DOUBLE:
814       /* NB that TME_M6888X_EA_OP32(0) is always the most significant
815 	 32 bits of the double, regardless of the endianness of the
816 	 host.  this is how both the executer fetches an immediate
817 	 double, and how the memory code above reads a double: */
818       value64_buffer.tme_value64_uint32_hi = TME_M6888X_EA_OP32(0);
819       value64_buffer.tme_value64_uint32_lo = TME_M6888X_EA_OP32(1);
820       tme_ieee754_double_value_set(&conv_buffer, value64_buffer);
821       TME_M6888X_IEEE754_OP_MONADIC(tme_ieee754_ops_extended80_from_double,
822 				    &conv_buffer,
823 				    &src_buffer);
824       break;
825 
826       /* assign an extended-precision value: */
827     case TME_M6888X_TYPE_EXTENDED80:
828       /* NB that TME_M6888X_EA_OP32(0) is always the most significant
829 	 32 bits of the extended80, regardless of the endianness of
830 	 the host.  this is how both the executer fetches an immediate
831 	 extended80, and how the memory code above reads a extended80: */
832       extended80_buffer.tme_float_ieee754_extended80_sexp = TME_M6888X_EA_OP32(0) >> 16;
833       extended80_buffer.tme_float_ieee754_extended80_significand.tme_value64_uint32_hi = TME_M6888X_EA_OP32(1);
834       extended80_buffer.tme_float_ieee754_extended80_significand.tme_value64_uint32_lo = TME_M6888X_EA_OP32(2);
835       tme_ieee754_extended80_value_set(&src_buffer, extended80_buffer);
836       break;
837 
838     case TME_M6888X_TYPE_PACKEDDEC:
839 
840       /* if this value's SE and YY bits are all set, and the exponent
841 	 is 0xFFF, the value is either an infinity or a NaN: */
842       if ((TME_M6888X_EA_OP32(0)
843 	   & (TME_M6888X_PACKEDDEC_SE
844 	      | TME_M6888X_PACKEDDEC_YY))
845 	  == (TME_M6888X_PACKEDDEC_SE
846 	      | TME_M6888X_PACKEDDEC_YY)
847 	  && TME_M6888X_PD_DIGIT(22) == 0xf
848 	  && TME_M6888X_PD_DIGIT(21) == 0xf
849 	  && TME_M6888X_PD_DIGIT(20) == 0xf) {
850 
851 	/* "A packed decimal real data format with the SE and both Y
852 	   bits set, an exponent of $FFF and a nonzero 16-bit [sic]
853 	   decimal fraction is a NAN.  When the FPU uses this format,
854 	   the fraction of the NAN is moved bit- by-bit into the
855 	   extended-precision mantissa of a floating-point data
856 	   register."
857 
858 	   moving the fraction bit-by-bit works for the infinities,
859 	   too, since both the packed decimal and the extended
860 	   precision infinities have all-bits-zero fractions: */
861 	extended80_buffer.tme_float_ieee754_extended80_significand.tme_value64_uint32_hi = TME_M6888X_EA_OP32(1);
862 	extended80_buffer.tme_float_ieee754_extended80_significand.tme_value64_uint32_lo = TME_M6888X_EA_OP32(2);
863 
864 	/* "The exponent of the register is set to signify a NAN,
865 	   and no conversion occurs.  The MSB of the most
866 	   significant digit in the decimal fraction (the MSB of
867 	   digit 15) is a don't care, as in extended-precision NANs,
868 	   and the MSB of minus one of digit 15 is the SNAN bit. If
869 	   the NAN bit is a zero, then it is an SNAN."
870 
871 	   the biased exponent for NaNs and infinities is the same,
872 	   and the sign bit is a don't care for a NaN: */
873 	extended80_buffer.tme_float_ieee754_extended80_sexp
874 	  = (0x7fff
875 	     | (TME_M6888X_EA_OP32(0) & TME_M6888X_PACKEDDEC_SM
876 		? 0x8000
877 		: 0));
878 
879 	/* finally create the source operand: */
880 	tme_ieee754_extended80_value_set(&src_buffer, extended80_buffer);
881       }
882 
883       /* otherwise, this should be an in-range value: */
884       else {
885 
886 	/* "The FPU does not detect non-decimal digits in the exponent,
887 	   integer, or fraction digits of an in-range packed decimal real data
888 	   format.  These non-decimal digits are converted to binary in the
889 	   same manner as decimal digits; however, the result is probably
890 	   useless although it is repeatable." */
891 
892 	/* convert the significand: */
893 	tme_ieee754_extended80_from_int32(TME_M6888X_PD_DIGIT(16), &src_buffer);
894 	tme_ieee754_extended80_from_int32(100000000, &conv_buffer);
895 	packed_value_int32 = 0;
896 	digit_i = 15;
897 	do {
898 	  packed_value_int32 = (packed_value_int32 * 10) + TME_M6888X_PD_DIGIT(digit_i);
899 	  if ((digit_i % 8) == 0) {
900 	    TME_M6888X_IEEE754_OP_DYADIC(tme_ieee754_ops_extended80_mul,
901 					 &src_buffer,
902 					 &conv_buffer,
903 					 &src_buffer);
904 	    tme_ieee754_extended80_from_int32(packed_value_int32, &packed_value_float);
905 	    TME_M6888X_IEEE754_OP_DYADIC(tme_ieee754_ops_extended80_add,
906 					 &src_buffer,
907 					 &packed_value_float,
908 					 &src_buffer);
909 	    packed_value_int32 = 0;
910 	  }
911 	} while (digit_i-- > 0);
912 	if (TME_M6888X_EA_OP32(0) & TME_M6888X_PACKEDDEC_SM) {
913 	  tme_ieee754_extended80_from_int32(-1, &conv_buffer);
914 	  TME_M6888X_IEEE754_OP_DYADIC(tme_ieee754_ops_extended80_mul,
915 				       &src_buffer,
916 				       &conv_buffer,
917 				       &src_buffer);
918 	}
919 
920 	/* convert the exponent: */
921 	exponent = 0;
922 	digit_i = 22;
923 	do {
924 	  exponent = (exponent * 10) + TME_M6888X_PD_DIGIT(digit_i);
925 	} while (digit_i-- > 21);
926 	if (TME_M6888X_EA_OP32(0) & TME_M6888X_PACKEDDEC_SE) {
927 	  exponent = -exponent;
928 	}
929 
930 	/* adjust the exponent, since we ignored the implicit decimal
931 	   point when converting the significand: */
932 	exponent -= 16;
933 
934 	/* scale the significand: */
935 	tme_ieee754_extended80_from_int32(exponent, &conv_buffer);
936 	tme_ieee754_extended80_radix10_scale(&ic->tme_m68k_fpu_ieee754_ctl, &src_buffer, &conv_buffer, &src_buffer);
937       }
938       break;
939 
940     default:
941       abort();
942     }
943 
944     /* the source operand is in the buffer: */
945     src = &src_buffer;
946   }
947 
948   /* otherwise, the source operand is in a register: */
949   else {
950     src = &ic->tme_m68k_fpu_fpreg[src_specifier];
951   }
952 
953   /* XXX FIXME - a check for operand types not implemented on the
954      m68040 would go here: */
955 
956   /* do the common fpgen setup: */
957   _tme_m6888x_fpgen_enter(ic, fpgen);
958 
959   /* get the destination operand: */
960   dst = &ic->tme_m68k_fpu_fpreg[TME_FIELD_EXTRACTU(command, 7, 3)];
961 
962   /* dispatch on the opmode to handle any special cases: */
963   switch (opmode) {
964 
965     /* these instructions don't modify the destination register: */
966   case TME_M6888X_FPGEN_OPMODE_FCMP:
967   case TME_M6888X_FPGEN_OPMODE_FTST:
968     dst_buffer = *dst;
969     dst = &dst_buffer;
970     break;
971 
972   default:
973     break;
974   }
975 
976   /* if this instruction is m6888x specific: */
977   if (fpgen->tme_m6888x_fpgen_func != NULL) {
978 
979     /* run the function: */
980     (*fpgen->tme_m6888x_fpgen_func)(ic, src, dst);
981   }
982 
983   /* otherwise, this instruction has an IEEE 754 operation: */
984   else {
985 
986     /* run the function: */
987     switch (fpgen->tme_m6888x_fpgen_optype) {
988     default: assert(FALSE);
989     case TME_M6888X_OPTYPE_MONADIC:
990       TME_M6888X_IEEE754_OP_RUN(fpgen->tme_m6888x_fpgen_func_ops_offset, (struct tme_ieee754_ctl *, const struct tme_float *, struct tme_float *), (&ic->tme_m68k_fpu_ieee754_ctl, src, dst));
991       break;
992     case TME_M6888X_OPTYPE_DYADIC_SRC_DST:
993       TME_M6888X_IEEE754_OP_RUN(fpgen->tme_m6888x_fpgen_func_ops_offset, (struct tme_ieee754_ctl *, const struct tme_float *, const struct tme_float *, struct tme_float *), (&ic->tme_m68k_fpu_ieee754_ctl, src, dst, dst));
994       break;
995     case TME_M6888X_OPTYPE_DYADIC_DST_SRC:
996       TME_M6888X_IEEE754_OP_RUN(fpgen->tme_m6888x_fpgen_func_ops_offset, (struct tme_ieee754_ctl *, const struct tme_float *, const struct tme_float *, struct tme_float *), (&ic->tme_m68k_fpu_ieee754_ctl, dst, src, dst));
997       break;
998     }
999   }
1000 
1001   /* set the floating-point condition codes: */
1002   _tme_m6888x_fpcc(ic, dst, TME_FLOAT_FORMAT_IEEE754_EXTENDED80 | TME_FLOAT_FORMAT_IEEE754_EXTENDED80_BUILTIN);
1003 
1004 #undef TME_M68K_AREG_INCREMENT
1005 }
1006 
TME_M6888X_FPGEN(_tme_m6888x_fsincos)1007 TME_M6888X_FPGEN(_tme_m6888x_fsincos)
1008 {
1009   /* "If FPs and FPc are specified to be the same register, the cosine
1010      result is first loaded into the register and then is overwritten
1011      with the sine result." */
1012   TME_M6888X_IEEE754_OP_MONADIC(tme_ieee754_ops_extended80_cos,
1013 				src,
1014 				&ic->tme_m68k_fpu_fpreg[TME_FIELD_EXTRACTU(TME_M68K_INSN_SPECOP, 0, 3)]);
1015   TME_M6888X_IEEE754_OP_MONADIC(tme_ieee754_ops_extended80_sin,
1016 				src,
1017 				dst);
1018 }
1019 
TME_M6888X_FPGEN(_tme_m6888x_fcmp)1020 TME_M6888X_FPGEN(_tme_m6888x_fcmp)
1021 {
1022   int dst_is_negative;
1023   int src_is_negative;
1024 
1025   /* check for a NaN operand: */
1026   if (__tme_predict_false(tme_ieee754_extended80_check_nan_dyadic(&ic->tme_m68k_fpu_ieee754_ctl, src, dst, dst))) {
1027     return;
1028   }
1029 
1030   /* see if the destination is negative: */
1031   dst_is_negative
1032     = (tme_float_is_negative(dst,
1033 			     (TME_FLOAT_FORMAT_IEEE754_EXTENDED80
1034 			      | TME_FLOAT_FORMAT_IEEE754_EXTENDED80_BUILTIN))
1035        != 0);
1036 
1037   /* if the source operand is an infinity: */
1038   if (tme_ieee754_extended80_is_inf(src)) {
1039 
1040     /* see if the source operand is negative infinity: */
1041     src_is_negative
1042       = (tme_float_is_negative(src,
1043 			       (TME_FLOAT_FORMAT_IEEE754_EXTENDED80
1044 				| TME_FLOAT_FORMAT_IEEE754_EXTENDED80_BUILTIN))
1045 	 != 0);
1046 
1047     /* if the destination operand is the same infinity as the source operand: */
1048     if (tme_ieee754_extended80_is_inf(dst)
1049 	&& dst_is_negative == src_is_negative) {
1050 
1051       /* return a zero, to set Z, with the same sign as the source
1052 	 operand, to set N appropriately: */
1053       tme_ieee754_extended80_value_set_constant(dst, &tme_ieee754_extended80_constant_zero);
1054       if (src_is_negative) {
1055 	assert (dst->tme_float_format == TME_FLOAT_FORMAT_IEEE754_EXTENDED80);
1056 	dst->tme_float_value_ieee754_extended80.tme_float_ieee754_extended80_sexp |= 0x8000;
1057       }
1058     }
1059 
1060     /* otherwise, either the destination operand is not an infinity
1061        or it is the other infinity: */
1062     else {
1063 
1064       /* return a one with the opposite sign as the source operand, to
1065 	 set N appropriately: */
1066       tme_ieee754_extended80_value_set_constant(dst, &tme_ieee754_extended80_constant_one);
1067       if (!src_is_negative) {
1068 	assert (dst->tme_float_format == TME_FLOAT_FORMAT_IEEE754_EXTENDED80);
1069 	dst->tme_float_value_ieee754_extended80.tme_float_ieee754_extended80_sexp |= 0x8000;
1070       }
1071     }
1072     return;
1073   }
1074 
1075   /* otherwise, if the destination operand is an infinity: */
1076   else if (tme_ieee754_extended80_is_inf(dst)) {
1077 
1078     /* return a one with the same sign as the destination operand, to
1079        set N appropriately: */
1080     tme_ieee754_extended80_value_set_constant(dst, &tme_ieee754_extended80_constant_one);
1081     if (dst_is_negative) {
1082       assert (dst->tme_float_format == TME_FLOAT_FORMAT_IEEE754_EXTENDED80);
1083       dst->tme_float_value_ieee754_extended80.tme_float_ieee754_extended80_sexp |= 0x8000;
1084     }
1085     return;
1086   }
1087 
1088   /* do the subtraction: */
1089   TME_M6888X_IEEE754_OP_DYADIC(tme_ieee754_ops_extended80_sub,
1090 			       dst,
1091 			       src,
1092 			       dst);
1093 }
1094 
TME_M6888X_FPGEN(_tme_m6888x_ftst)1095 TME_M6888X_FPGEN(_tme_m6888x_ftst)
1096 {
1097   *dst = *src;
1098 }
1099 
TME_M6888X_FPGEN(_tme_m6888x_ftwotox)1100 TME_M6888X_FPGEN(_tme_m6888x_ftwotox)
1101 {
1102   struct tme_float two;
1103 
1104   tme_ieee754_extended80_value_set_constant(&two, &tme_ieee754_extended80_constant_2e2ex[0]);
1105   TME_M6888X_IEEE754_OP_DYADIC(tme_ieee754_ops_extended80_pow,
1106 			       src,
1107 			       &two,
1108 			       dst);
1109 }
1110 
TME_M6888X_FPGEN(_tme_m6888x_ftentox)1111 TME_M6888X_FPGEN(_tme_m6888x_ftentox)
1112 {
1113   struct tme_float ten;
1114 
1115   tme_ieee754_extended80_value_set_constant(&ten, &tme_ieee754_extended80_constant_10e2ex[0]);
1116   TME_M6888X_IEEE754_OP_DYADIC(tme_ieee754_ops_extended80_pow,
1117 			       src,
1118 			       &ten,
1119 			       dst);
1120 }
1121 
TME_M6888X_FPGEN(_tme_m6888x_flog2)1122 TME_M6888X_FPGEN(_tme_m6888x_flog2)
1123 {
1124   struct tme_float log_two;
1125 
1126   /* 2^log2(x) = e^log(x) */
1127   /* log(2^log2(x)) = log(e^log(x)) */
1128   /* log2(x) * log(2) = log(x) * log(e) */
1129   /* log2(x) = log(x) / log(2) */
1130 
1131   TME_M6888X_IEEE754_OP_MONADIC(tme_ieee754_ops_extended80_log,
1132 				src,
1133 				dst);
1134   tme_ieee754_extended80_value_set_constant(&log_two, &tme_ieee754_extended80_constant_ln_2);
1135   TME_M6888X_IEEE754_OP_DYADIC(tme_ieee754_ops_extended80_div,
1136 			       dst,
1137 			       &log_two,
1138 			       dst);
1139 }
1140 
1141 /* this internal function handles fmod and frem: */
1142 static void
_tme_m6888x_fmodrem(struct tme_m68k * ic,const struct tme_float * src,struct tme_float * dst,int rounding)1143 _tme_m6888x_fmodrem(struct tme_m68k *ic, const struct tme_float *src, struct tme_float *dst, int rounding)
1144 {
1145   struct tme_float quotient;
1146   struct tme_float quotient_divisor;
1147   tme_int32_t quotient_byte;
1148   struct tme_float two_hundred_fifty_six;
1149 
1150   /* check for a NaN operand: */
1151   if (__tme_predict_false(tme_ieee754_extended80_check_nan_dyadic(&ic->tme_m68k_fpu_ieee754_ctl, src, dst, dst))) {
1152     return;
1153   }
1154 
1155   /* if the source operand is zero, or if the destination operand is infinity: */
1156   if (tme_ieee754_extended80_is_zero(src)
1157       || tme_ieee754_extended80_is_inf(dst)) {
1158 
1159     /* return a NaN: */
1160     dst->tme_float_format = TME_FLOAT_FORMAT_IEEE754_EXTENDED80;
1161     dst->tme_float_value_ieee754_extended80 = ic->tme_m68k_fpu_ieee754_ctl.tme_ieee754_ctl_default_nan_extended80;
1162     return;
1163   }
1164 
1165   /* do the division.  the quotient must not be a NaN: */
1166   ic->tme_m68k_fpu_ieee754_ctl.tme_ieee754_ctl_rounding_mode = rounding;
1167   TME_M6888X_IEEE754_OP_DYADIC(tme_ieee754_ops_extended80_div, dst, src, &quotient);
1168   assert (!tme_ieee754_extended80_is_nan(&quotient));
1169 
1170   /* round the quotient to an integer: */
1171   /* XXX FIXME we assume that the rounding mode is the same as the division: */
1172   TME_M6888X_IEEE754_OP_MONADIC(tme_ieee754_ops_extended80_rint, &quotient, &quotient);
1173 
1174   /* get the remainder: */
1175   TME_M6888X_IEEE754_OP_DYADIC(tme_ieee754_ops_extended80_mul, src, &quotient, &quotient_divisor);
1176   TME_M6888X_IEEE754_OP_DYADIC(tme_ieee754_ops_extended80_sub, dst, &quotient_divisor, dst);
1177 
1178   /* get the quotient's least significant eight bits, eventually
1179      truncating them to seven: */
1180   tme_ieee754_extended80_from_int32(256, &two_hundred_fifty_six);
1181   TME_M6888X_IEEE754_OP_DYADIC(tme_ieee754_ops_extended80_rem, &quotient, &two_hundred_fifty_six, &quotient);
1182   quotient_byte = tme_ieee754_extended80_value_builtin_get(&quotient);
1183   if (quotient_byte >= 0) {
1184     quotient_byte &= 0x7f;
1185   }
1186   else {
1187     quotient_byte = ((-quotient_byte) & 0x7f) | 0x80;
1188   }
1189 
1190   /* update the quotient byte in the FPSR: */
1191   TME_FIELD_MASK_DEPOSITU(ic->tme_m68k_fpu_fpsr, TME_M6888X_FPSR_QUOTIENT, ((tme_uint32_t) quotient_byte));
1192 }
1193 
TME_M6888X_FPGEN(_tme_m6888x_fmod)1194 TME_M6888X_FPGEN(_tme_m6888x_fmod)
1195 {
1196   _tme_m6888x_fmodrem(ic, src, dst, TME_FLOAT_ROUND_TO_ZERO);
1197 }
1198 
TME_M6888X_FPGEN(_tme_m6888x_frem)1199 TME_M6888X_FPGEN(_tme_m6888x_frem)
1200 {
1201   _tme_m6888x_fmodrem(ic, src, dst, TME_FLOAT_ROUND_NEAREST_EVEN);
1202 }
1203 
TME_M6888X_FPGEN(_tme_m6888x_fsgldiv)1204 TME_M6888X_FPGEN(_tme_m6888x_fsgldiv)
1205 {
1206   struct tme_float src_trunc, dst_trunc;
1207   struct tme_float_ieee754_extended80 src_buffer, dst_buffer;
1208 
1209   /* check for a NaN operand: */
1210   if (__tme_predict_false(tme_ieee754_extended80_check_nan_dyadic(&ic->tme_m68k_fpu_ieee754_ctl, src, dst, dst))) {
1211     return;
1212   }
1213 
1214   /* if the source and destination operands are both zero or both
1215      infinity: */
1216   if ((tme_ieee754_extended80_is_zero(src)
1217        && tme_ieee754_extended80_is_zero(dst))
1218       || (tme_ieee754_extended80_is_inf(src)
1219 	  && tme_ieee754_extended80_is_inf(dst))) {
1220 
1221     /* return a NaN: */
1222     dst->tme_float_format = TME_FLOAT_FORMAT_IEEE754_EXTENDED80;
1223     dst->tme_float_value_ieee754_extended80 = ic->tme_m68k_fpu_ieee754_ctl.tme_ieee754_ctl_default_nan_extended80;
1224 
1225     /* set OPERR: */
1226     _tme_m6888x_exception(ic, TME_M6888X_FPSR_EXC_OPERR);
1227     return;
1228   }
1229 
1230   /* truncate the significands of the source and destination to no
1231      more than 24 bits to the right of the point.  24 becomes 25
1232      because the extended80 format includes the explicit integer bit: */
1233   tme_ieee754_extended80_value_set(&src_trunc, *tme_ieee754_extended80_value_get(src, &src_buffer));
1234   src_trunc.tme_float_value_ieee754_extended80.tme_float_ieee754_extended80_significand.tme_value64_uint32_hi &= 0xffff8000;
1235   src_trunc.tme_float_value_ieee754_extended80.tme_float_ieee754_extended80_significand.tme_value64_uint32_lo = 0x00000000;
1236   tme_ieee754_extended80_value_set(&dst_trunc, *tme_ieee754_extended80_value_get(dst, &dst_buffer));
1237   dst_trunc.tme_float_value_ieee754_extended80.tme_float_ieee754_extended80_significand.tme_value64_uint32_hi &= 0xffff8000;
1238   dst_trunc.tme_float_value_ieee754_extended80.tme_float_ieee754_extended80_significand.tme_value64_uint32_lo = 0x00000000;
1239 
1240   /* do the division: */
1241   ic->tme_m68k_fpu_ieee754_ctl.tme_ieee754_ctl_extended80_rounding_precision = 32;
1242   TME_M6888X_IEEE754_OP_DYADIC(tme_ieee754_ops_extended80_div, &dst_trunc, &src_trunc, dst);
1243 }
1244 
TME_M6888X_FPGEN(_tme_m6888x_fsglmul)1245 TME_M6888X_FPGEN(_tme_m6888x_fsglmul)
1246 {
1247   struct tme_float src_trunc, dst_trunc;
1248   struct tme_float_ieee754_extended80 src_buffer, dst_buffer;
1249 
1250   /* check for a NaN operand: */
1251   if (__tme_predict_false(tme_ieee754_extended80_check_nan_dyadic(&ic->tme_m68k_fpu_ieee754_ctl, src, dst, dst))) {
1252     return;
1253   }
1254 
1255   /* if the source is a zero and the destination is a NaN, or vice
1256      versa: */
1257   if ((tme_ieee754_extended80_is_zero(src)
1258        && tme_ieee754_extended80_is_inf(dst))
1259       || (tme_ieee754_extended80_is_inf(src)
1260 	  && tme_ieee754_extended80_is_zero(dst))) {
1261 
1262     /* return a NaN: */
1263     dst->tme_float_format = TME_FLOAT_FORMAT_IEEE754_EXTENDED80;
1264     dst->tme_float_value_ieee754_extended80 = ic->tme_m68k_fpu_ieee754_ctl.tme_ieee754_ctl_default_nan_extended80;
1265 
1266     /* if the destination is a zero, set OPERR: */
1267     if (tme_ieee754_extended80_is_zero(dst)) {
1268       _tme_m6888x_exception(ic, TME_M6888X_FPSR_EXC_OPERR);
1269     }
1270     return;
1271   }
1272 
1273   /* truncate the significands of the source and destination to no
1274      more than 24 bits to the right of the point.  24 becomes 25
1275      because the extended80 format includes the explicit integer bit: */
1276   tme_ieee754_extended80_value_set(&src_trunc, *tme_ieee754_extended80_value_get(src, &src_buffer));
1277   src_trunc.tme_float_value_ieee754_extended80.tme_float_ieee754_extended80_significand.tme_value64_uint32_hi &= 0xffff8000;
1278   src_trunc.tme_float_value_ieee754_extended80.tme_float_ieee754_extended80_significand.tme_value64_uint32_lo = 0x00000000;
1279   tme_ieee754_extended80_value_set(&dst_trunc, *tme_ieee754_extended80_value_get(dst, &dst_buffer));
1280   dst_trunc.tme_float_value_ieee754_extended80.tme_float_ieee754_extended80_significand.tme_value64_uint32_hi &= 0xffff8000;
1281   dst_trunc.tme_float_value_ieee754_extended80.tme_float_ieee754_extended80_significand.tme_value64_uint32_lo = 0x00000000;
1282 
1283   /* do the multiplication: */
1284   ic->tme_m68k_fpu_ieee754_ctl.tme_ieee754_ctl_extended80_rounding_precision = 32;
1285   TME_M6888X_IEEE754_OP_DYADIC(tme_ieee754_ops_extended80_mul, &src_trunc, &dst_trunc, dst);
1286 }
1287 
TME_M6888X_FPGEN(_tme_m6888x_fmovecr)1288 TME_M6888X_FPGEN(_tme_m6888x_fmovecr)
1289 {
1290   const struct tme_ieee754_extended80_constant *constant;
1291   tme_uint16_t offset;
1292 
1293   offset = TME_FIELD_EXTRACTU(TME_M68K_INSN_SPECOP, 0, 7);
1294 
1295   /* the binary powers of 10 offsets: */
1296   if (offset >= 0x33
1297       && offset <= 0x3f) {
1298     constant = &tme_ieee754_extended80_constant_10e2ex[offset - 0x33];
1299   }
1300 
1301   /* anything else: */
1302   else {
1303     switch (offset) {
1304     case 0x00: constant = &tme_ieee754_extended80_constant_pi; break;
1305     case 0x0b: constant = &tme_ieee754_extended80_constant_log10_2; break;
1306     case 0x0c: constant = &tme_ieee754_extended80_constant_e; break;
1307     case 0x0d: constant = &tme_ieee754_extended80_constant_log2_e; break;
1308     case 0x0e: constant = &tme_ieee754_extended80_constant_log10_e; break;
1309     default:
1310     case 0x0f: constant = &tme_ieee754_extended80_constant_zero; break;
1311     case 0x30: constant = &tme_ieee754_extended80_constant_ln_2; break;
1312     case 0x31: constant = &tme_ieee754_extended80_constant_ln_10; break;
1313     case 0x32: constant = &tme_ieee754_extended80_constant_one; break;
1314     }
1315   }
1316 
1317   /* return the result: */
1318   tme_ieee754_extended80_value_set_constant(dst, constant);
1319 }
1320 
1321 /* this can fault: */
TME_M68K_INSN(tme_m68k_fmove_rm)1322 TME_M68K_INSN(tme_m68k_fmove_rm)
1323 {
1324   unsigned int ea_mode;
1325   unsigned int ea_reg;
1326   unsigned int ea_size;
1327   unsigned int destination_format;
1328   const struct tme_float *src;
1329   struct tme_float src_buffer;
1330   const struct tme_float *dst;
1331   struct tme_float dst_buffer;
1332   unsigned int dst_formats;
1333   int src_is_nan;
1334   tme_int32_t value_int32_raw;
1335   tme_int32_t value_int32;
1336   tme_uint32_t single_buffer;
1337   const union tme_value64 *value64;
1338   union tme_value64 value64_buffer;
1339   const struct tme_float_ieee754_extended80 *extended80;
1340   struct tme_float_ieee754_extended80 extended80_buffer;
1341 
1342   /* get the EA mode and register fields: */
1343   ea_mode = TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 3, 3);
1344   ea_reg = TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 0, 3);
1345 
1346   /* get the destination format: */
1347   destination_format = TME_FIELD_EXTRACTU(TME_M68K_INSN_SPECOP, 10, 3);
1348 
1349   /* if this is an address register direct EA, or this is a data
1350      register direct EA and the destination format isn't byte, word,
1351      long, or single, this is an illegal instruction: */
1352   if (ea_mode == 1
1353       || (ea_mode == 0
1354 	  && destination_format != TME_M6888X_TYPE_BYTE
1355 	  && destination_format != TME_M6888X_TYPE_WORD
1356 	  && destination_format != TME_M6888X_TYPE_LONG
1357 	  && destination_format != TME_M6888X_TYPE_SINGLE)) {
1358     TME_M68K_INSN_EXCEPTION(TME_M68K_EXCEPTION_ILL);
1359   }
1360 
1361   /* for the effective address predecrement and postincrement modes,
1362      and for the integer conversions, we require that these size
1363      macros correspond exactly to the number of bytes: */
1364 #if TME_M68K_SIZE_8 != 1
1365 #error "TME_M68K_SIZE_8 must be 1"
1366 #endif
1367 #if TME_M68K_SIZE_16 != 2
1368 #error "TME_M68K_SIZE_16 must be 2"
1369 #endif
1370 #if TME_M68K_SIZE_32 != 4
1371 #error "TME_M68K_SIZE_32 must be 4"
1372 #endif
1373 #if TME_M68K_SIZE_64 != 8
1374 #error "TME_M68K_SIZE_64 must be 8"
1375 #endif
1376 #if TME_M68K_SIZE_96 != 12
1377 #error "TME_M68K_SIZE_96 must be 12"
1378 #endif
1379 #define TME_M68K_AREG_INCREMENT(areg, size) \
1380   ((size) + (((size) == TME_M68K_SIZE_8 && (areg) == TME_M68K_IREG_A7) ? 1 : 0))
1381 
1382   /* dispatch on the destination format to get the size of the destination: */
1383   switch (destination_format) {
1384   case TME_M6888X_TYPE_BYTE: ea_size = TME_M68K_SIZE_8; break;
1385   case TME_M6888X_TYPE_WORD: ea_size = TME_M68K_SIZE_16; break;
1386   case TME_M6888X_TYPE_LONG: /* FALLTHROUGH */
1387   case TME_M6888X_TYPE_SINGLE: ea_size = TME_M68K_SIZE_32; break;
1388   case TME_M6888X_TYPE_DOUBLE: ea_size = TME_M68K_SIZE_64; break;
1389   default: assert(FALSE);
1390   case TME_M6888X_TYPE_PACKEDDEC: /* FALLTHROUGH */
1391   case TME_M6888X_TYPE_PACKEDDEC_DK: /* FALLTHROUGH */
1392   case TME_M6888X_TYPE_EXTENDED80: ea_size = TME_M68K_SIZE_96; break;
1393   }
1394 
1395   /* if we're not restarting: */
1396   if (!TME_M68K_SEQUENCE_RESTARTING) {
1397 
1398     /* do the common fpgen setup: */
1399     _tme_m6888x_fpgen_enter(ic, &_tme_m6888x_fpgen_fmove_rm);
1400 
1401     /* get the source register: */
1402     src = &ic->tme_m68k_fpu_fpreg[TME_FIELD_EXTRACTU(TME_M68K_INSN_SPECOP, 7, 3)];
1403 
1404     /* check for a NaN operand: */
1405     src_is_nan = tme_ieee754_extended80_check_nan_monadic(&ic->tme_m68k_fpu_ieee754_ctl, src, &src_buffer);
1406     if (src_is_nan) {
1407       src = &src_buffer;
1408     }
1409 
1410     /* assume that the source is the destination: */
1411     dst = src;
1412     dst_formats = TME_FLOAT_FORMAT_IEEE754_EXTENDED80 | TME_FLOAT_FORMAT_IEEE754_EXTENDED80_BUILTIN;
1413 
1414     /* dispatch on the destination format: */
1415     switch (destination_format) {
1416 
1417     case TME_M6888X_TYPE_BYTE:
1418     case TME_M6888X_TYPE_WORD:
1419     case TME_M6888X_TYPE_LONG:
1420       if (src_is_nan) {
1421 	/* XXX how is a NaN converted into an integer? */
1422 	value_int32 = -1;
1423 	_tme_m6888x_exception(ic, TME_M6888X_FPSR_EXC_OPERR);
1424       }
1425       else {
1426 	TME_M6888X_IEEE754_OP_MONADIC(tme_ieee754_ops_extended80_to_int32, src, &value_int32_raw);
1427 	value_int32 = TME_MIN(value_int32_raw, (2147483647 / (1L << (8 * (TME_M68K_SIZE_32 - ea_size)))));
1428 	value_int32 = TME_MAX(value_int32, ((-1073741824 * 2) / (1L << (8 * (TME_M68K_SIZE_32 - ea_size)))));
1429 	if (tme_ieee754_extended80_is_inf(src)
1430 	    || value_int32 != value_int32_raw) {
1431 	  _tme_m6888x_exception(ic, TME_M6888X_FPSR_EXC_OPERR);
1432 	}
1433       }
1434       ic->tme_m68k_ireg_memx32 = value_int32;
1435       break;
1436 
1437     case TME_M6888X_TYPE_SINGLE:
1438       TME_M6888X_IEEE754_OP_MONADIC(tme_ieee754_ops_single_from_extended80, src, &dst_buffer);
1439       ic->tme_m68k_ireg_memx32 = *tme_ieee754_single_value_get(&dst_buffer, &single_buffer);
1440       dst = &dst_buffer;
1441       dst_formats = TME_FLOAT_FORMAT_IEEE754_SINGLE | TME_FLOAT_FORMAT_IEEE754_SINGLE_BUILTIN;
1442       break;
1443 
1444     case TME_M6888X_TYPE_DOUBLE:
1445       TME_M6888X_IEEE754_OP_MONADIC(tme_ieee754_ops_double_from_extended80, src, &dst_buffer);
1446       value64 = tme_ieee754_double_value_get(&dst_buffer, &value64_buffer);
1447       ic->tme_m68k_ireg_memx32 = value64->tme_value64_uint32_hi;
1448       ic->tme_m68k_ireg_memy32 = value64->tme_value64_uint32_lo;
1449       dst = &dst_buffer;
1450       dst_formats = TME_FLOAT_FORMAT_IEEE754_DOUBLE | TME_FLOAT_FORMAT_IEEE754_DOUBLE_BUILTIN;
1451       break;
1452 
1453     case TME_M6888X_TYPE_EXTENDED80:
1454       extended80 = tme_ieee754_extended80_value_get(src, &extended80_buffer);
1455       ic->tme_m68k_ireg_memx32 = extended80->tme_float_ieee754_extended80_sexp << 16;
1456       ic->tme_m68k_ireg_memy32 = extended80->tme_float_ieee754_extended80_significand.tme_value64_uint32_hi;
1457       ic->tme_m68k_ireg_memz32 = extended80->tme_float_ieee754_extended80_significand.tme_value64_uint32_lo;
1458       break;
1459 
1460     default:
1461       assert(FALSE);
1462       /* FALLTHROUGH */
1463 
1464     case TME_M6888X_TYPE_PACKEDDEC:
1465     case TME_M6888X_TYPE_PACKEDDEC_DK:
1466 
1467       /* we punt on the packed-decimal format for now: */
1468       TME_M68K_INSN_EXCEPTION(TME_M68K_EXCEPTION_ILL);
1469       break;
1470     }
1471 
1472     /* set the floating-point condition codes: */
1473     _tme_m6888x_fpcc(ic, dst, dst_formats);
1474   }
1475 
1476   /* if this is a data register direct EA: */
1477   if (ea_mode == 0) {
1478 
1479     switch (ea_size) {
1480     case TME_M68K_SIZE_8:
1481       ic->tme_m68k_ireg_uint8(ea_reg << 2) = ic->tme_m68k_ireg_memx32;
1482       break;
1483 
1484     case TME_M68K_SIZE_16:
1485       ic->tme_m68k_ireg_uint8(ea_reg << 1) = ic->tme_m68k_ireg_memx32;
1486       break;
1487 
1488     default:
1489       assert (FALSE);
1490       /* FALLTHROUGH */
1491 
1492     case TME_M68K_SIZE_32:
1493       ic->tme_m68k_ireg_uint32(ea_reg) = ic->tme_m68k_ireg_memx32;
1494       break;
1495     }
1496   }
1497 
1498   /* otherwise, this is a memory EA: */
1499   else {
1500 
1501     /* this instruction can fault: */
1502     TME_M68K_INSN_CANFAULT;
1503 
1504     /* adjust ea_reg to reference the address register: */
1505     ea_reg += TME_M68K_IREG_A0;
1506 
1507     /* address register indirect postincrement: */
1508     if (ea_mode == 3) {
1509       /* if we are not restarting, set the effective address: */
1510       if (!TME_M68K_SEQUENCE_RESTARTING) {
1511 	ic->_tme_m68k_ea_address = ic->tme_m68k_ireg_uint32(ea_reg);
1512 	ic->tme_m68k_ireg_uint32(ea_reg) += TME_M68K_AREG_INCREMENT(ea_reg, ea_size);
1513       }
1514     }
1515 
1516     /* address register indirect predecrement: */
1517     else if (ea_mode == 4) {
1518       /* if we are not restarting, set the effective address: */
1519       if (!TME_M68K_SEQUENCE_RESTARTING) {
1520 	ic->tme_m68k_ireg_uint32(ea_reg) -= TME_M68K_AREG_INCREMENT(ea_reg, ea_size);
1521 	ic->_tme_m68k_ea_address = ic->tme_m68k_ireg_uint32(ea_reg);
1522       }
1523     }
1524 
1525     /* dispatch on the operand size to write in the destination as one
1526        or more 32-bit words.  we will write up to three 32-bit words
1527        from memx, memy, and memz: */
1528     switch (ea_size) {
1529 
1530       /* this can only happen when the source operand is a byte: */
1531     case TME_M68K_SIZE_8:
1532       tme_m68k_write_memx8(ic);
1533       assert (!TME_M68K_SEQUENCE_RESTARTING);
1534       break;
1535 
1536       /* this can only happen when the source operand is a word: */
1537     case TME_M68K_SIZE_16:
1538       tme_m68k_write_memx16(ic);
1539       assert (!TME_M68K_SEQUENCE_RESTARTING);
1540       break;
1541 
1542       /* everything else is one or more 32-bit words: */
1543     default:
1544 
1545       /* write the first 32 bits from the memx register: */
1546       tme_m68k_write_memx32(ic);
1547       if (ea_size == TME_M68K_SIZE_32) {
1548 	break;
1549       }
1550 
1551       /* write the second 32 bits from the memy register: */
1552       if (!TME_M68K_SEQUENCE_RESTARTING) {
1553 	ic->_tme_m68k_ea_address += TME_M68K_SIZE_32;
1554       }
1555       tme_m68k_write_mem32(ic, TME_M68K_IREG_MEMY32);
1556       if (ea_size == TME_M68K_SIZE_64) {
1557 	break;
1558       }
1559 
1560       /* write the third 32 bits from the memz register: */
1561       if (!TME_M68K_SEQUENCE_RESTARTING) {
1562 	ic->_tme_m68k_ea_address += TME_M68K_SIZE_32;
1563       }
1564       tme_m68k_write_mem32(ic, TME_M68K_IREG_MEMZ32);
1565       break;
1566     }
1567   }
1568 
1569   TME_M68K_INSN_OK;
1570 
1571 #undef TME_M68K_AREG_INCREMENT
1572 }
1573 
1574 /* this can fault: */
TME_M68K_INSN(tme_m68k_fmovem)1575 TME_M68K_INSN(tme_m68k_fmovem)
1576 {
1577   unsigned int ea_mode;
1578   unsigned int ea_reg;
1579   unsigned int register_to_memory;
1580   tme_uint16_t mask;
1581   unsigned int bit;
1582   unsigned int first_register;
1583   struct tme_float *fpreg;
1584   const struct tme_float_ieee754_extended80 *extended80;
1585   struct tme_float_ieee754_extended80 extended80_buffer;
1586 
1587   TME_M68K_INSN_FPU;
1588 
1589   /* get the EA mode and register fields: */
1590   ea_mode = TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 3, 3);
1591   ea_reg = TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 0, 3);
1592 
1593   /* get the register-to-memory flag: */
1594   register_to_memory = (TME_M68K_INSN_SPECOP & TME_BIT(13)) != 0;
1595 
1596   /* immediate EAs must have already been caught as illegal instructions: */
1597   assert (!(ea_mode == 7 && ea_reg == 4));
1598 
1599   /* if this is a data register direct EA or an address register
1600      direct EA, or if this is a predecrement EA and this is a
1601      memory-to-register operation, or if this is a postincrement EA
1602      and this is a register-to-memory operation, this is an illegal
1603      instruction: */
1604   if (ea_mode == 0
1605       || ea_mode == 1
1606       || (ea_mode == 4
1607 	  && !register_to_memory)
1608       || (ea_mode == 3
1609 	  && register_to_memory)) {
1610     TME_M68K_INSN_EXCEPTION(TME_M68K_EXCEPTION_ILL);
1611   }
1612 
1613   /* get the register list: */
1614   mask = TME_FIELD_EXTRACTU(TME_M68K_INSN_SPECOP, 0, 8);
1615 
1616   /* if the register list is dynamic: */
1617   if (TME_M68K_INSN_SPECOP & TME_BIT(11)) {
1618 
1619     /* the mask field is supposed to contain only a data register
1620        number: */
1621     if (mask & 0x8f) {
1622       TME_M68K_INSN_EXCEPTION(TME_M68K_EXCEPTION_ILL);
1623     }
1624 
1625     /* get the dynamic register list: */
1626     mask = ic->tme_m68k_ireg_uint32(TME_M68K_IREG_D0 + TME_FIELD_EXTRACTU(mask, 4, 3));
1627   }
1628 
1629   /* get the FP register corresponding to bit 7 in the mask: */
1630   if (TME_M68K_INSN_SPECOP & TME_BIT(12)) {
1631     first_register = 0;
1632   }
1633   else {
1634 
1635     /* this must be a predecrement EA: */
1636     if (ea_mode != 4) {
1637       TME_M68K_INSN_EXCEPTION(TME_M68K_EXCEPTION_ILL);
1638     }
1639 
1640     first_register = 7;
1641   }
1642 
1643   /* if the mask is empty, return now: */
1644   if (mask == 0) {
1645     TME_M68K_INSN_OK;
1646   }
1647 
1648   /* this instruction can fault: */
1649   TME_M68K_INSN_CANFAULT;
1650 
1651   /* we require that TME_M68K_SIZE_96 be 12: */
1652 #if TME_M68K_SIZE_96 != 12
1653 #error "TME_M68K_SIZE_96 must be 12"
1654 #endif
1655 
1656   /* loop over the bits in the mask: */
1657   for (bit = 0; bit < 8; bit++, mask <<= 1) {
1658 
1659     /* skip this register if its bit isn't set in the mask: */
1660     if (!(mask & 0x80)) {
1661       continue;
1662     }
1663 
1664     /* get this register: */
1665     fpreg = &ic->tme_m68k_fpu_fpreg[bit ^ first_register];
1666 
1667     /* if this is a register-to-memory operation: */
1668     if (register_to_memory) {
1669 
1670       /* if this is a predecrement EA, and we're not restarting,
1671          predecrement the EA: */
1672       if (!TME_M68K_SEQUENCE_RESTARTING
1673 	  && ea_mode == 4) {
1674 	ic->_tme_m68k_ea_address = (ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0 + ea_reg) -= TME_M68K_SIZE_96);
1675       }
1676 
1677       /* write out the register: */
1678       extended80 = tme_ieee754_extended80_value_get(fpreg, &extended80_buffer);
1679       if (!TME_M68K_SEQUENCE_RESTARTING) {
1680 	ic->tme_m68k_ireg_memx32 = extended80->tme_float_ieee754_extended80_sexp << 16;
1681       }
1682       tme_m68k_write_memx32(ic);
1683       if (!TME_M68K_SEQUENCE_RESTARTING) {
1684 	ic->_tme_m68k_ea_address += TME_M68K_SIZE_32;
1685 	ic->tme_m68k_ireg_memx32 = extended80->tme_float_ieee754_extended80_significand.tme_value64_uint32_hi;
1686       }
1687       tme_m68k_write_memx32(ic);
1688       if (!TME_M68K_SEQUENCE_RESTARTING) {
1689 	ic->_tme_m68k_ea_address += TME_M68K_SIZE_32;
1690 	ic->tme_m68k_ireg_memx32 = extended80->tme_float_ieee754_extended80_significand.tme_value64_uint32_lo;
1691       }
1692       tme_m68k_write_memx32(ic);
1693       if (!TME_M68K_SEQUENCE_RESTARTING) {
1694 	ic->_tme_m68k_ea_address += TME_M68K_SIZE_32;
1695       }
1696     }
1697 
1698     /* otherwise, this is a memory-to-register operation: */
1699     else {
1700 
1701       /* read in this register: */
1702       tme_m68k_read_memx32(ic);
1703       if (!TME_M68K_SEQUENCE_RESTARTING) {
1704 	fpreg->tme_float_value_ieee754_extended80.tme_float_ieee754_extended80_sexp = (ic->tme_m68k_ireg_memx32 >> 16);
1705 	ic->_tme_m68k_ea_address += TME_M68K_SIZE_32;
1706       }
1707       tme_m68k_read_memx32(ic);
1708       if (!TME_M68K_SEQUENCE_RESTARTING) {
1709 	fpreg->tme_float_value_ieee754_extended80.tme_float_ieee754_extended80_significand.tme_value64_uint32_hi = ic->tme_m68k_ireg_memx32;
1710 	ic->_tme_m68k_ea_address += TME_M68K_SIZE_32;
1711       }
1712       tme_m68k_read_memx32(ic);
1713       if (!TME_M68K_SEQUENCE_RESTARTING) {
1714 	fpreg->tme_float_value_ieee754_extended80.tme_float_ieee754_extended80_significand.tme_value64_uint32_lo = ic->tme_m68k_ireg_memx32;
1715 	ic->_tme_m68k_ea_address += TME_M68K_SIZE_32;
1716 	fpreg->tme_float_format = TME_FLOAT_FORMAT_IEEE754_EXTENDED80;
1717       }
1718     }
1719   }
1720 
1721   /* if this is the postincrement addressing mode: */
1722   if (ea_mode == 3) {
1723 
1724     /* update the address register: */
1725     assert (!TME_M68K_SEQUENCE_RESTARTING);
1726     ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0 + ea_reg) = ic->_tme_m68k_ea_address;
1727   }
1728 
1729   TME_M68K_INSN_OK;
1730 }
1731 
1732 /* this can fault: */
TME_M68K_INSN(tme_m68k_fmovemctl)1733 TME_M68K_INSN(tme_m68k_fmovemctl)
1734 {
1735   tme_uint16_t mask;
1736   unsigned int ea_mode;
1737   unsigned int ea_reg;
1738   unsigned int register_to_memory;
1739   unsigned int bit;
1740   tme_uint32_t *value;
1741 
1742   TME_M68K_INSN_FPU;
1743 
1744   /* get the register mask: */
1745   mask = TME_FIELD_EXTRACTU(TME_M68K_INSN_SPECOP, 10, 3);
1746 
1747   /* get the EA mode and register fields: */
1748   ea_mode = TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 3, 3);
1749   ea_reg = TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 0, 3);
1750 
1751   /* get the register-to-memory flag: */
1752   register_to_memory = (TME_M68K_INSN_SPECOP & TME_BIT(13)) != 0;
1753 
1754   /* if no registers have been selected, or if this is a data register
1755      direct EA and multiple registers have been selected, or if this
1756      is an address register direct EA and the floating point
1757      instruction address register is not the single register selected,
1758      this is an illegal instruction: */
1759   if (mask == 0
1760       || (ea_mode == 0
1761 	  && ((mask & (mask - 1)) != 0))
1762       || (ea_mode == 1
1763 	  && mask != 1)) {
1764     TME_M68K_INSN_EXCEPTION(TME_M68K_EXCEPTION_ILL);
1765   }
1766 
1767   /* if this isn't a data register direct EA or an address register
1768      direct EA, this instruction can fault: */
1769   if (ea_mode != 0
1770       && ea_mode != 1) {
1771     TME_M68K_INSN_CANFAULT;
1772   }
1773 
1774   /* if we're not restarting, and this is the predecrement addressing mode: */
1775   if (!TME_M68K_SEQUENCE_RESTARTING
1776       && ea_mode == 4) {
1777 
1778     /* update the effective address: */
1779     for (; mask != 0; ic->_tme_m68k_ea_address -= sizeof(tme_uint32_t), mask &= (mask - 1));
1780 
1781     /* update the address register: */
1782     ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0 + ea_reg) = ic->_tme_m68k_ea_address;
1783   }
1784 
1785   /* get the register mask: */
1786   mask = TME_FIELD_EXTRACTU(TME_M68K_INSN_SPECOP, 10, 3);
1787 
1788   /* loop over the register mask bits: */
1789   for (bit = 3; bit-- > 0; ) {
1790 
1791     /* ignore this register if its bit isn't set: */
1792     if (!(mask & (1 << bit))) {
1793       continue;
1794     }
1795 
1796     /* get a pointer to this register's value: */
1797     value = (bit == 2
1798 	     ? &ic->tme_m68k_fpu_fpcr
1799 	     : bit == 1
1800 	     ? &ic->tme_m68k_fpu_fpsr
1801 	     : &ic->tme_m68k_fpu_fpiar);
1802 
1803     /* transfer this register's value: */
1804 
1805     /* if this is a data register direct EA: */
1806     if (ea_mode == 0) {
1807       if (register_to_memory) {
1808 	ic->tme_m68k_ireg_uint32(TME_M68K_IREG_D0 + ea_reg) = *value;
1809       }
1810       else {
1811 	*value = ic->tme_m68k_ireg_uint32(TME_M68K_IREG_D0 + ea_reg);
1812       }
1813     }
1814 
1815     /* if this is an address register direct EA: */
1816     else if (ea_mode == 1) {
1817       if (register_to_memory) {
1818 	ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0 + ea_reg) = *value;
1819       }
1820       else {
1821 	*value = ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0 + ea_reg);
1822       }
1823     }
1824 
1825     /* otherwise, this is a memory EA: */
1826     else {
1827       if (register_to_memory) {
1828 	if (!TME_M68K_SEQUENCE_RESTARTING) {
1829 	  ic->tme_m68k_ireg_memx32 = *value;
1830 	}
1831 	tme_m68k_write_memx32(ic);
1832 	if (!TME_M68K_SEQUENCE_RESTARTING) {
1833 	  ic->_tme_m68k_ea_address += sizeof(tme_uint32_t);
1834 	}
1835       }
1836       else {
1837 	tme_m68k_read_memx32(ic);
1838 	if (!TME_M68K_SEQUENCE_RESTARTING) {
1839 	  *value = ic->tme_m68k_ireg_memx32;
1840 	  ic->_tme_m68k_ea_address += sizeof(tme_uint32_t);
1841 	}
1842       }
1843     }
1844   }
1845 
1846   /* if this is the postincrement addressing mode: */
1847   if (ea_mode == 3) {
1848 
1849     /* update the address register: */
1850     assert (!TME_M68K_SEQUENCE_RESTARTING);
1851     ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0 + ea_reg) = ic->_tme_m68k_ea_address;
1852   }
1853 
1854   TME_M68K_INSN_OK;
1855 }
1856 
1857 /* this evaluates a floating-point predicate: */
1858 static int
_tme_m6888x_predicate_true(struct tme_m68k * ic,tme_uint16_t predicate)1859 _tme_m6888x_predicate_true(struct tme_m68k *ic, tme_uint16_t predicate)
1860 {
1861   unsigned int cc_nan;
1862   unsigned int cc_i;
1863   unsigned int cc_z;
1864   unsigned int cc_n;
1865 
1866   /* get the condition codes: */
1867   cc_nan = (ic->tme_m68k_fpu_fpsr & TME_M6888X_FPSR_CC_NAN) != 0;
1868   cc_i = (ic->tme_m68k_fpu_fpsr & TME_M6888X_FPSR_CC_I) != 0;
1869   cc_z = (ic->tme_m68k_fpu_fpsr & TME_M6888X_FPSR_CC_Z) != 0;
1870   cc_n = (ic->tme_m68k_fpu_fpsr & TME_M6888X_FPSR_CC_N) != 0;
1871 
1872   /* if this predicate is greater than 0x1f, this is an illegal instruction: */
1873   if (predicate > 0x1f) {
1874     TME_M68K_INSN_EXCEPTION(TME_M68K_EXCEPTION_ILL);
1875   }
1876 
1877   /* if this predicate sets BSUN when NaN is set: */
1878   if (predicate > 0x0f) {
1879 
1880     /* if NaN is set, set BSUN: */
1881     if (cc_nan) {
1882       _tme_m6888x_exception(ic, TME_M6888X_FPSR_EXC_BSUN);
1883     }
1884 
1885     /* adjust predicate to be its non-BSUN-setting version: */
1886     predicate -= 0x10;
1887   }
1888 
1889   /* dispatch on the predicate: */
1890   switch (predicate) {
1891   default: assert(FALSE);
1892   case 0x00: predicate = FALSE; break;				/* F, SF */
1893   case 0x01: predicate =  cc_z; break;				/* EQ, SEQ */
1894   case 0x02: predicate = !(cc_nan || cc_z || cc_n); break;	/* OGT, GT */
1895   case 0x03: predicate = cc_z || !(cc_nan || cc_n); break;	/* OGE, GE */
1896   case 0x04: predicate = cc_n && !(cc_nan || cc_z); break;	/* OLT, LT */
1897   case 0x05: predicate = cc_z || (cc_n && !cc_nan); break;	/* OLE, LE */
1898   case 0x06: predicate = !(cc_nan || cc_z); break;		/* OGL, GL */
1899   case 0x07: predicate = !cc_nan; break;			/* OR, GLE */
1900   case 0x08: predicate =  cc_nan; break;			/* UN, NGLE */
1901   case 0x09: predicate =  (cc_nan || cc_z); break;		/* UEQ, NGL */
1902   case 0x0a: predicate = cc_nan || !(cc_n || cc_z); break;	/* UGT, NLE */
1903   case 0x0b: predicate = cc_nan || cc_z || !cc_n; break;	/* UGE, NLT */
1904   case 0x0c: predicate = cc_nan || (cc_n && !cc_z); break;	/* ULT, NGE */
1905   case 0x0d: predicate =  (cc_nan || cc_z || cc_n); break;	/* ULE, NGT */
1906   case 0x0e: predicate = !cc_z; break;				/* NE, SNE */
1907   case 0x0f: predicate = FALSE; break;				/* T, ST */
1908   }
1909 
1910   return (predicate);
1911 }
1912 
1913 /* this cannot fault: */
TME_M68K_INSN(tme_m68k_fdbcc)1914 TME_M68K_INSN(tme_m68k_fdbcc)
1915 {
1916   TME_M68K_INSN_FPU;
1917 
1918   if (_tme_m6888x_predicate_true(ic, TME_FIELD_EXTRACTU(TME_M68K_INSN_SPECOP, 0, 6))) {
1919     if (--TME_M68K_INSN_OP0(tme_int16_t) != -1) {
1920       TME_M68K_INSN_BRANCH(ic->tme_m68k_ireg_pc
1921 			   + 4
1922 			   + TME_EXT_S16_U32(TME_M68K_INSN_OP1(tme_int16_t)));
1923     }
1924   }
1925   TME_M68K_INSN_OK;
1926 }
1927 
1928 /* this cannot fault: */
TME_M68K_INSN(tme_m68k_ftrapcc)1929 TME_M68K_INSN(tme_m68k_ftrapcc)
1930 {
1931   TME_M68K_INSN_FPU;
1932   if (_tme_m6888x_predicate_true(ic, TME_FIELD_EXTRACTU(TME_M68K_INSN_SPECOP, 0, 6))) {
1933     ic->tme_m68k_ireg_pc_last = ic->tme_m68k_ireg_pc;
1934     ic->tme_m68k_ireg_pc = ic->tme_m68k_ireg_pc_next;
1935     TME_M68K_INSN_EXCEPTION(TME_M68K_EXCEPTION_INST(TME_M68K_VECTOR_TRAP));
1936   }
1937   TME_M68K_INSN_OK;
1938 }
1939 
1940 /* this cannot fault: */
TME_M68K_INSN(tme_m68k_fscc)1941 TME_M68K_INSN(tme_m68k_fscc)
1942 {
1943   TME_M68K_INSN_FPU;
1944   TME_M68K_INSN_OP1(tme_uint8_t) =
1945     (_tme_m6888x_predicate_true(ic, TME_FIELD_EXTRACTU(TME_M68K_INSN_SPECOP, 0, 6))
1946      ? 0xff
1947      : 0x00);
1948   TME_M68K_INSN_OK;
1949 }
1950 
1951 /* this cannot fault: */
TME_M68K_INSN(tme_m68k_fbcc)1952 TME_M68K_INSN(tme_m68k_fbcc)
1953 {
1954   TME_M68K_INSN_FPU;
1955 
1956   if (_tme_m6888x_predicate_true(ic, TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 0, 6))) {
1957     TME_M68K_INSN_BRANCH(ic->tme_m68k_ireg_pc
1958 			 + sizeof(tme_uint16_t)
1959 			 + TME_M68K_INSN_OP0(tme_uint32_t));
1960   }
1961   TME_M68K_INSN_OK;
1962 }
1963 
1964 /* this can fault: */
TME_M68K_INSN(tme_m68k_fsave)1965 TME_M68K_INSN(tme_m68k_fsave)
1966 {
1967   struct tme_m6888x_frame frame;
1968   tme_uint32_t frame_size;
1969 
1970   TME_M68K_INSN_FPU;
1971   TME_M68K_INSN_PRIV;
1972   TME_M68K_INSN_CANFAULT;
1973 
1974   /* zero the frame: */
1975   memset(&frame, 0, sizeof(frame));
1976 
1977   /* dispatch on the FPU type: */
1978   switch (ic->tme_m68k_fpu_type) {
1979   default: assert (FALSE);
1980   case TME_M68K_FPU_M68881:
1981     frame.tme_m6888x_frame_version = TME_M6888X_FRAME_VERSION_IDLE_M68881;
1982     frame.tme_m6888x_frame_size = TME_M6888X_FRAME_SIZE_IDLE_M68881;
1983     break;
1984   case TME_M68K_FPU_M68882:
1985     frame.tme_m6888x_frame_version = TME_M6888X_FRAME_VERSION_IDLE_M68882;
1986     frame.tme_m6888x_frame_size = TME_M6888X_FRAME_SIZE_IDLE_M68882;
1987     break;
1988   case TME_M68K_FPU_M68040:
1989     frame.tme_m6888x_frame_version = TME_M6888X_FRAME_VERSION_IDLE_M68040;
1990     frame.tme_m6888x_frame_size = TME_M6888X_FRAME_SIZE_IDLE_M68040;
1991     break;
1992   }
1993 
1994   /* if this is the m68881 or m68882: */
1995   if (ic->tme_m68k_fpu_type & TME_M68K_FPU_M6888X) {
1996 
1997     /* fill in a minimal BIU flags field: */
1998     frame.tme_m6888x_frame_words[(frame.tme_m6888x_frame_size / sizeof(tme_uint32_t)) - 2] = tme_htobe_u32(0x70000000);
1999   }
2000 
2001   /* get the total size of the frame: */
2002   frame_size
2003     = (sizeof(frame.tme_m6888x_frame_version)
2004        + sizeof(frame.tme_m6888x_frame_size)
2005        + sizeof(frame.tme_m6888x_frame_reserved2)
2006        + frame.tme_m6888x_frame_size);
2007 
2008   /* if we're not restarting, and this is the predecrement addressing
2009      mode, update the effective address and the address register: */
2010   if (!TME_M68K_SEQUENCE_RESTARTING
2011       && TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 3, 3) == 4) {
2012     ic->_tme_m68k_ea_address -= frame_size;
2013     ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0
2014 			     + TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 0, 3))
2015       = ic->_tme_m68k_ea_address;
2016   }
2017 
2018   /* write out the saved frame: */
2019   tme_m68k_write_mem(ic, (tme_uint8_t *) &frame, frame_size);
2020 }
2021 
2022 /* this can fault: */
TME_M68K_INSN(tme_m68k_frestore)2023 TME_M68K_INSN(tme_m68k_frestore)
2024 {
2025   tme_uint8_t frame_version;
2026   tme_uint8_t frame_size;
2027   int format_error;
2028 
2029   TME_M68K_INSN_FPU;
2030   TME_M68K_INSN_PRIV;
2031   TME_M68K_INSN_CANFAULT;
2032 
2033   /* read in the format word: */
2034   tme_m68k_read_memx32(ic);
2035   frame_version = (ic->tme_m68k_ireg_memx32 >> 24) & 0xff;
2036   frame_size = (ic->tme_m68k_ireg_memx32 >> 16) & 0xff;
2037 
2038   /* determine if we have a format error: */
2039   if (frame_version == TME_M6888X_FRAME_VERSION_NULL) {
2040     format_error = (frame_size != TME_M6888X_FRAME_SIZE_NULL);
2041   }
2042   else {
2043     switch (ic->tme_m68k_fpu_type) {
2044     default: assert (FALSE);
2045     case TME_M68K_FPU_M68881:
2046       format_error = (frame_version != TME_M6888X_FRAME_VERSION_IDLE_M68881
2047 		      || frame_size != TME_M6888X_FRAME_SIZE_IDLE_M68881);
2048       break;
2049     case TME_M68K_FPU_M68882:
2050       format_error = (frame_version != TME_M6888X_FRAME_VERSION_IDLE_M68882
2051 		      || frame_size != TME_M6888X_FRAME_SIZE_IDLE_M68882);
2052       break;
2053     case TME_M68K_FPU_M68040:
2054       format_error = (frame_version != TME_M6888X_FRAME_VERSION_IDLE_M68040
2055 		      || frame_size != TME_M6888X_FRAME_SIZE_IDLE_M68040);
2056       break;
2057     }
2058   }
2059 
2060   /* if we have a format error: */
2061   if (format_error) {
2062     TME_M68K_INSN_EXCEPTION(TME_M68K_EXCEPTION_INST(TME_M68K_VECTOR_FORMAT));
2063   }
2064 
2065   /* XXX FIXME - we don't bother reading in the rest of the frame.
2066      this gives an incomplete emulation: */
2067 
2068   /* if this is the postincrement addressing mode, update the address
2069      register: */
2070   if (TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 3, 3) == 3) {
2071     ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0
2072 			     + TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 0, 3))
2073       += (sizeof(ic->tme_m68k_ireg_memx32)
2074 	  + frame_size);
2075   }
2076 
2077   /* if this was a NULL frame, reset the FPU: */
2078   if (frame_version == TME_M6888X_FRAME_VERSION_NULL) {
2079     tme_m68k_fpu_reset(ic);
2080   }
2081 }
2082 
2083 /* this checks for an FPU argument: */
2084 int
tme_m68k_fpu_new(struct tme_m68k * ic,const char * const * args,int * _arg_i,int * _usage,char ** _output)2085 tme_m68k_fpu_new(struct tme_m68k *ic, const char * const *args, int *_arg_i, int *_usage, char **_output)
2086 {
2087   int arg_i;
2088   int fpu_type;
2089   const char *compliance;
2090   int complete;
2091   unsigned int opmode_i;
2092   struct tme_ieee754_ctl *ctl;
2093 
2094   /* get the argument index: */
2095   arg_i = *_arg_i;
2096 
2097   /* if this is not an FPU type, this is not an m6888x argument: */
2098   if (!TME_ARG_IS(args[arg_i + 0], "fpu-type")) {
2099     return (FALSE);
2100   }
2101 
2102   /* you can't specify more than one FPU type: */
2103   if (ic->tme_m68k_fpu_type != TME_M68K_FPU_NONE) {
2104     tme_output_append_error(_output,
2105 			    "%s fpu-type %s",
2106 			    _("multiple"),
2107 			    _("unexpected"));
2108     *_usage = TRUE;
2109     return (TRUE);
2110   }
2111 
2112   /* get the FPU type: */
2113   if (args[arg_i + 1] == NULL) {
2114     *_usage = TRUE;
2115     return (TRUE);
2116   }
2117   if (TME_ARG_IS(args[arg_i + 1], "m68881")) {
2118     fpu_type = TME_M68K_FPU_M68881;
2119   }
2120   else if (TME_ARG_IS(args[arg_i + 1], "m68882")) {
2121     fpu_type = TME_M68K_FPU_M68882;
2122   }
2123   else if (TME_ARG_IS(args[arg_i + 1], "m68040")) {
2124     fpu_type = TME_M68K_FPU_M68040;
2125   }
2126   else {
2127     tme_output_append_error(_output,
2128 			    "%s fpu-type %s",
2129 			    _("bad"),
2130 			    args[arg_i + 1]);
2131     *_usage = TRUE;
2132     return (TRUE);
2133   }
2134   ic->tme_m68k_fpu_type = fpu_type;
2135   arg_i += 2;
2136 
2137   /* the next argument must be a compliance level: */
2138   compliance = args[arg_i + 1];
2139   if (!TME_ARG_IS(args[arg_i + 0], "fpu-compliance")
2140       || compliance == NULL) {
2141     *_usage = TRUE;
2142     return (TRUE);
2143   }
2144   ic->tme_m68k_fpu_ieee754_ops = tme_ieee754_ops_lookup(compliance);
2145   if (ic->tme_m68k_fpu_ieee754_ops == NULL) {
2146     tme_output_append_error(_output,
2147 			    "%s fpu-compliance %s",
2148 			    _("bad"),
2149 			    compliance);
2150     *_usage = TRUE;
2151     return (TRUE);
2152   }
2153   arg_i += 2;
2154 
2155   /* see if the operations for this compliance level are complete: */
2156   complete = TRUE;
2157   for (opmode_i = 0;
2158        opmode_i < (sizeof(_tme_m6888x_fpgen_opmode_table) / sizeof(_tme_m6888x_fpgen_opmode_table[0]));
2159        opmode_i++) {
2160     if (_tme_m6888x_fpgen_opmode_table[opmode_i].tme_m6888x_fpgen_func_ops_offset != 0
2161 	&& TME_M6888X_IEEE754_OP_FUNC(_tme_m6888x_fpgen_opmode_table[opmode_i].tme_m6888x_fpgen_func_ops_offset) == NULL) {
2162       complete = FALSE;
2163       break;
2164     }
2165   }
2166 
2167   /* if the next argument is an incomplete disposition: */
2168   if (TME_ARG_IS(args[arg_i + 0], "fpu-incomplete")) {
2169 
2170     if (TME_ARG_IS(args[arg_i + 1], "abort")) {
2171       ic->tme_m68k_fpu_incomplete_abort = TRUE;
2172     }
2173     else if (TME_ARG_IS(args[arg_i + 1], "line-f")) {
2174       ic->tme_m68k_fpu_incomplete_abort = FALSE;
2175     }
2176     else {
2177       tme_output_append_error(_output,
2178 			      "%s fpu-incomplete %s",
2179 			      _("bad"),
2180 			      args[arg_i + 1]);
2181       *_usage = TRUE;
2182       return (TRUE);
2183     }
2184     arg_i += 2;
2185   }
2186 
2187   /* otherwise, no incomplete disposition is given.  if this
2188      compliance is incomplete: */
2189   else if (!complete) {
2190     tme_output_append_error(_output,
2191 			    "%s %s %s fpu-incomplete",
2192 			    _("compliance"),
2193 			    compliance,
2194 			    _("is incomplete, needs"));
2195     *_usage = TRUE;
2196     return (TRUE);
2197   }
2198 
2199   /* initialize the IEEE 754 control: */
2200   ctl = &ic->tme_m68k_fpu_ieee754_ctl;
2201 
2202   /* a private data structure: */
2203   ctl->tme_ieee754_ctl_private = ic;
2204 
2205   /* the underflow tininess-detection mode: */
2206   /* XXX FIXME - is this right for the m6888x? */
2207   ctl->tme_ieee754_ctl_detect_tininess = TME_IEEE754_CTL_DETECT_TININESS_BEFORE_ROUNDING;
2208 
2209   /* the exception function: */
2210   ctl->tme_ieee754_ctl_exception = _tme_m6888x_exception_ieee754;
2211 
2212   /* we don't check whether or not a value is a NaN when converting it
2213      from one precision to another: */
2214   ctl->tme_ieee754_ctl_check_snan_on_conversion = FALSE;
2215 
2216   /* the default generated NaN patterns: */
2217   ctl->tme_ieee754_ctl_default_nan_single = 0x7fffffff;
2218   ctl->tme_ieee754_ctl_default_nan_double.tme_value64_uint32_hi = 0x7fffffff;
2219   ctl->tme_ieee754_ctl_default_nan_double.tme_value64_uint32_lo = 0xffffffff;
2220   ctl->tme_ieee754_ctl_default_nan_extended80.tme_float_ieee754_extended80_sexp = 0x7fff;
2221   ctl->tme_ieee754_ctl_default_nan_extended80.tme_float_ieee754_extended80_significand.tme_value64_uint32_hi = 0xffffffff;
2222   ctl->tme_ieee754_ctl_default_nan_extended80.tme_float_ieee754_extended80_significand.tme_value64_uint32_lo = 0xffffffff;
2223 
2224   /* NaN tests: */
2225   ctl->tme_ieee754_ctl_is_snan_extended80 = _tme_m6888x_is_snan_extended80;
2226 
2227   /* NaN canonicalization: */
2228   ctl->tme_ieee754_ctl_nan_single_to_common = tme_ieee754_default_nan_single_to_common;
2229   ctl->tme_ieee754_ctl_nan_common_to_single = tme_ieee754_default_nan_common_to_single;
2230   ctl->tme_ieee754_ctl_nan_double_to_common = tme_ieee754_default_nan_double_to_common;
2231   ctl->tme_ieee754_ctl_nan_common_to_double = tme_ieee754_default_nan_common_to_double;
2232   ctl->tme_ieee754_ctl_nan_extended80_to_common = tme_ieee754_default_nan_extended80_to_common;
2233   ctl->tme_ieee754_ctl_nan_common_to_extended80 = tme_ieee754_default_nan_common_to_extended80;
2234 
2235   /* NaN propagation: */
2236   ctl->tme_ieee754_ctl_nan_from_nans_extended80 = _tme_m6888x_nan_from_nans_extended80;
2237 
2238   /* done: */
2239   *_arg_i = arg_i;
2240   return (TRUE);
2241 }
2242 
2243 /* this returns the FPU usage: */
2244 void
tme_m68k_fpu_usage(char ** _output)2245 tme_m68k_fpu_usage(char **_output)
2246 {
2247   tme_output_append_error(_output,
2248 			  "[ fpu-type { m68881 | m68882 | m68040 } fpu-compliance %s [ fpu-incomplete { abort | line-f } ] ]",
2249 			  tme_ieee754_compliance_options);
2250 }
2251