ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/uae_cpu/fpp.cpp
(Generate patch)

Comparing BasiliskII/src/uae_cpu/fpp.cpp (file contents):
Revision 1.1 by cebix, 1999-10-03T14:16:26Z vs.
Revision 1.7 by cebix, 1999-11-03T10:56:38Z

# Line 1 | Line 1
1 < /*
2 <  * UAE - The Un*x Amiga Emulator
3 <  *
4 <  * MC68881 emulation
5 <  *
6 <  * Copyright 1996 Herman ten Brugge
7 <  */
1 > /*
2 > * UAE - The Un*x Amiga Emulator
3 > *
4 > * MC68881 emulation
5 > *
6 > * Copyright 1996 Herman ten Brugge
7 > *
8 > *
9 > * Following fixes by Lauri Pesonen, July 1999:
10 > *
11 > * FMOVEM list handling:
12 > *  The lookup tables did not work correctly, rewritten.
13 > * FINT:
14 > *  (int) cast does not work, fixed.
15 > *  Further, now honors the fpcr rounding modes.
16 > * FINTRZ:
17 > *  (int) cast cannot be used, fixed.
18 > * FGETEXP:
19 > *  Input argument value 0 returned erroneous value.
20 > * FMOD:
21 > *  (int) cast cannot be used. Replaced by proper rounding.
22 > *  Quotient byte handling was missing.
23 > * FREM:
24 > *  (int) cast cannot be used. Replaced by proper rounding.
25 > *  Quotient byte handling was missing.
26 > * FSCALE:
27 > *  Input argument value 0 was not handled correctly.
28 > * FMOVEM Control Registers to/from address registers An:
29 > *  A bug caused the code never been called.
30 > * FMOVEM Control Registers pre-decrement:
31 > *  Moving of control regs from memory to FPP was not handled properly,
32 > *  if not all of the three registers were moved.
33 > * Condition code "Not Greater Than or Equal":
34 > *  Returned erroneous value.
35 > * FSINCOS:
36 > *  Cosine must be loaded first if same register.
37 > * FMOVECR:
38 > *  Status register was not updated (yes, this affects it).
39 > * FMOVE <ea> -> reg:
40 > *  Status register was not updated (yes, this affects it).
41 > * FMOVE reg -> reg:
42 > *  Status register was not updated.
43 > * FDBcc:
44 > *  The loop termination condition was wrong.
45 > *  Possible leak from int16 to int32 fixed.
46 > * Now fpcr high 16 bits are always read as zeores, no matter what was
47 > * written to them.
48 > *
49 > * Other:
50 > * - Optimized single/double/extended to/from conversion functions.
51 > *   Huge speed boost, but not (necessarily) portable to other systems.
52 > *   Enabled/disabled by #define HAVE_IEEE_DOUBLE 1
53 > * - Optimized versions of FSCALE, FGETEXP, FGETMAN
54 > * - Conversion routines now handle NaN and infinity better.
55 > * - Some constants precalculated. Not all compilers can optimize the
56 > *   expressions previously used.
57 > *
58 > * TODO:
59 > * - Floating point exceptions.
60 > * - More Infinity/NaN/overflow/underflow checking.
61 > * - FPIAR (only needed when exceptions are implemented)
62 > * - Should be written in assembly to support long doubles.
63 > * - Precision rounding single/double
64 > */
65 >
66 > #include "sysdeps.h"
67  
68   #include <math.h>
69   #include <stdio.h>
70  
12 #include "sysdeps.h"
13
71   #include "memory.h"
72   #include "readcpu.h"
73   #include "newcpu.h"
74 + #include "main.h"
75 +
76 + #define DEBUG 0
77 + #include "debug.h"
78  
18 #if 1
79  
80 < #define DEBUG_FPP       0
80 > // Only define if you have IEEE 64 bit doubles.
81 > #define HAVE_IEEE_DOUBLE 1
82 >
83 > #ifdef WORDS_BIGENDIAN
84 > #define FLO 1
85 > #define FHI 0
86 > #else
87 > #define FLO 0
88 > #define FHI 1
89 > #endif
90 >
91 > // fpcr rounding modes
92 > #define ROUND_TO_NEAREST                        0
93 > #define ROUND_TO_ZERO                           0x10
94 > #define ROUND_TO_NEGATIVE_INFINITY      0x20
95 > #define ROUND_TO_POSITIVE_INFINITY      0x30
96  
97   /* single   : S  8*E 23*F */
98   /* double   : S 11*E 52*F */
# Line 27 | Line 102
102   /* E = MAX & F # 0 -> NotANumber */
103   /* E = biased by 127 (single) ,1023 (double) ,16383 (extended) */
104  
105 +
106 + #if DEBUG
107 +
108 + #define CONDRET(s,x) D(bug("fpp_cond %s = %d\r\n",s,(uint32)(x))); return (x)
109 +
110 + static void dump_fp_regs( char *s )
111 + {
112 +        char b[512];
113 +
114 +        sprintf(
115 +                b,
116 +                "%s: %.04f, %.04f, %.04f, %.04f, %.04f, %.04f, %.04f, %.04f\r\n",
117 +                s,
118 +                (float)regs.fp[0],
119 +                (float)regs.fp[1],
120 +                (float)regs.fp[2],
121 +                (float)regs.fp[3],
122 +                (float)regs.fp[4],
123 +                (float)regs.fp[5],
124 +                (float)regs.fp[6],
125 +                (float)regs.fp[7]
126 +        );
127 +        D(bug((char*)b));
128 + }
129 +
130 + static void dump_first_bytes( uint8 *buf, int32 actual )
131 + {
132 +        char b[256], bb[10];
133 +        int32 i, bytes = sizeof(b)/3-1-3;
134 +        if (actual < bytes)
135 +                bytes = actual;
136 +
137 +        *b = 0;
138 +        for (i=0; i<bytes; i++) {
139 +                sprintf( bb, "%02x ", (uint32)buf[i] );
140 +                strcat( b, bb );
141 +        }
142 +        strcat((char*)b,"\r\n");
143 +        D(bug((char*)b));
144 + }
145 + #else
146 + #define CONDRET(s,x) return (x)
147 + #define dump_fp_regs(s) {}
148 + #define dump_first_bytes(b,a) {}
149 + #endif
150 +
151 +
152 + static __inline__ double round_to_zero( double x )
153 + {
154 +        if(x < 0) {
155 +                return ceil(x);
156 +        } else {
157 +                return floor(x);
158 +        }
159 + }
160 +
161 + static __inline__ double round_to_nearest( double x )
162 + {
163 +        return floor(x + 0.5);
164 + }
165 +
166 +
167 + #define CLEAR_EX_STATUS() regs.fpsr &= 0xFFFF00FF
168 +
169 +
170 + #if HAVE_IEEE_DOUBLE
171 +
172 +
173 + // full words to avoid partial register stalls.
174 + typedef struct {
175 +        uae_u32 in_range;
176 +        uae_u32 zero;
177 +        uae_u32 infinity;
178 +        uae_u32 nan;
179 +        uae_u32 negative;
180 + } double_flags;
181 + double_flags fl_dest, fl_source;
182 +
183 + static __inline__ uae_u32 IS_NAN(uae_u32 *p)
184 + {
185 +        if( (p[FHI] & 0x7FF00000) == 0x7FF00000 ) {
186 +                // logical or is faster here.
187 +                if( (p[FHI] & 0x000FFFFF) || p[FLO] ) {
188 +                        return(1);
189 +                }
190 +        }
191 +        return(0);
192 + }
193 +
194 + static __inline__ uae_u32 IS_INFINITY(uae_u32 *p)
195 + {
196 +        if( ((p[FHI] & 0x7FF00000) == 0x7FF00000) && p[FLO] == 0 ) {
197 +                return(1);
198 +        }
199 +        return(0);
200 + }
201 +
202 + static __inline__ uae_u32 IS_NEGATIVE(uae_u32 *p)
203 + {
204 +        return( (p[FHI] & 0x80000000) != 0 );
205 + }
206 +
207 + static __inline__ uae_u32 IS_ZERO(uae_u32 *p)
208 + {
209 +        return( ((p[FHI] & 0x7FF00000) == 0) && p[FLO] == 0 );
210 + }
211 +
212 + // This should not touch the quotient.
213 + /*
214 + #define MAKE_FPSR(fpsr,r) \
215 +                                        fpsr = (fpsr & 0x00FFFFFF) | \
216 +                                                                 (r == 0 ? 0x4000000 : 0) | \
217 +                                                                 (r < 0 ? 0x8000000 : 0) | \
218 +                                                                 (IS_NAN((uae_u32 *)&r) ? 0x1000000 : 0) | \
219 +                                                                 (IS_INFINITY((uae_u32 *)&r) ? 0x2000000 : 0)
220 + */
221 + #define MAKE_FPSR(fpsr,r) \
222 +                                        fpsr = (fpsr & 0x00FFFFFF) | \
223 +                                                                 (IS_ZERO((uae_u32 *)&r) ? 0x4000000 : 0) | \
224 +                                                                 (IS_NEGATIVE((uae_u32 *)&r) ? 0x8000000 : 0) | \
225 +                                                                 (IS_NAN((uae_u32 *)&r) ? 0x1000000 : 0) | \
226 +                                                                 (IS_INFINITY((uae_u32 *)&r) ? 0x2000000 : 0)
227 +
228 + static __inline__ void GET_DEST_FLAGS(uae_u32 *p)
229 + {
230 +        fl_dest.negative = IS_NEGATIVE(p);
231 +        fl_dest.zero = IS_ZERO(p);
232 +        fl_dest.infinity = IS_INFINITY(p);
233 +        fl_dest.nan = IS_NAN(p);
234 +        fl_dest.in_range = !fl_dest.zero && !fl_dest.infinity && !fl_dest.nan;
235 + }
236 +
237 + static __inline__ void GET_SOURCE_FLAGS(uae_u32 *p)
238 + {
239 +        fl_source.negative = IS_NEGATIVE(p);
240 +        fl_source.zero = IS_ZERO(p);
241 +        fl_source.infinity = IS_INFINITY(p);
242 +        fl_source.nan = IS_NAN(p);
243 +        fl_source.in_range = !fl_source.zero && !fl_source.infinity && !fl_source.nan;
244 + }
245 +
246 + static __inline__ void MAKE_NAN(uae_u32 *p)
247 + {
248 +        p[FLO] = 0xFFFFFFFF;
249 +        p[FHI] = 0x7FFFFFFF;
250 + }
251 +
252 + static __inline__ void MAKE_ZERO_POSITIVE(uae_u32 *p)
253 + {
254 +        p[FLO] = p[FHI] = 0;
255 + }
256 +
257 + static __inline__ void MAKE_ZERO_NEGATIVE(uae_u32 *p)
258 + {
259 +        p[FLO] = 0;
260 +        p[FHI] = 0x80000000;
261 + }
262 +
263 + static __inline__ void MAKE_INF_POSITIVE(uae_u32 *p)
264 + {
265 +        p[FLO] = 0;
266 +        p[FHI] = 0x7FF00000;
267 + }
268 +
269 + static __inline__ void MAKE_INF_NEGATIVE(uae_u32 *p)
270 + {
271 +        p[FLO] = 0;
272 +        p[FHI] = 0xFFF00000;
273 + }
274 +
275 + static __inline__ void FAST_SCALE(uae_u32 *p, int add)
276 + {
277 +        int exp;
278 +
279 +        exp = (p[FHI] & 0x7FF00000) >> 20;
280 +        // TODO: overflow flags
281 +        exp += add;
282 +        if(exp >= 2047) {
283 +                MAKE_INF_POSITIVE(p);
284 +        } else if(exp < 0) {
285 +                // keep sign (+/- 0)
286 +                p[FHI] &= 0x80000000;
287 +        } else {
288 +                p[FHI] = (p[FHI] & 0x800FFFFF) | ((uae_u32)exp << 20);
289 +        }
290 + }
291 +
292 + static __inline__ double FAST_FGETEXP(uae_u32 *p)
293 + {
294 +        int exp = (p[FHI] & 0x7FF00000) >> 20;
295 +        return( exp - 1023 );
296 + }
297 +
298 + // Normalize to range 1..2
299 + static __inline__ void FAST_REMOVE_EXPONENT(uae_u32 *p)
300 + {
301 +        p[FHI] = (p[FHI] & 0x800FFFFF) | 0x3FF00000;
302 + }
303 +
304 + // The sign of the quotient is the exclusive-OR of the sign bits
305 + // of the source and destination operands.
306 + static __inline__ uae_u32 GET_QUOTIENT_SIGN(uae_u32 *a, uae_u32 *b)
307 + {
308 +        return( ((a[FHI] ^ b[FHI]) & 0x80000000) ? 0x800000 : 0);
309 + }
310 +
311 + // Quotient Byte is loaded with the sign and least significant
312 + // seven bits of the quotient.
313 + static __inline__ uae_u32 MAKE_QUOTIENT( uae_u32 fpsr, double quot, uae_u32 sign )
314 + {
315 +        uae_u32 lsb = (uae_u32)fabs(quot) & 0x7F;
316 +        return (fpsr & 0xFF00FFFF) | sign | (lsb << 16);
317 + }
318 +
319   static __inline__ double to_single (uae_u32 value)
320   {
321 <    double frac;
321 >        double result;
322 >        uae_u32 *p;
323 >
324 >        if ((value & 0x7fffffff) == 0) return (0.0);
325 >
326 >        p = (uae_u32 *)&result;
327  
328 <    if ((value & 0x7fffffff) == 0)
329 <        return (0.0);
330 <    frac = (double) ((value & 0x7fffff) | 0x800000) / 8388608.0;
331 <    if (value & 0x80000000)
332 <        frac = -frac;
333 <    return (ldexp (frac, ((value >> 23) & 0xff) - 127));
328 >        uae_u32 sign = (value & 0x80000000);
329 >        uae_u32 exp  = ((value & 0x7F800000) >> 23) + 1023 - 127;
330 >
331 >        p[FLO] = value << 29;
332 >        p[FHI] = sign | (exp << 20) | ((value & 0x007FFFFF) >> 3);
333 >
334 >        D(bug("to_single (%X) = %.04f\r\n",value,(float)result));
335 >
336 >        return(result);
337   }
338  
339   static __inline__ uae_u32 from_single (double src)
340   {
341 <    int expon;
342 <    uae_u32 tmp;
343 <    double frac;
344 <
345 <    if (src == 0.0)
346 <        return 0;
347 <    if (src < 0) {
348 <        tmp = 0x80000000;
349 <        src = -src;
350 <    } else {
351 <        tmp = 0;
352 <    }
353 <    frac = frexp (src, &expon);
354 <    frac += 0.5 / 16777216.0;
355 <    if (frac >= 1.0) {
356 <        frac /= 2.0;
357 <        expon++;
358 <    }
359 <    return (tmp | (((expon + 127 - 1) & 0xff) << 23) |
360 <            (((int) (frac * 16777216.0)) & 0x7fffff));
341 >        uae_u32 result;
342 >        uae_u32 *p = (uae_u32 *)&src;
343 >
344 >  if (src == 0.0) return 0;
345 >
346 >        uae_u32 sign = (p[FHI] & 0x80000000);
347 >        uae_u32 exp  = (p[FHI] & 0x7FF00000) >> 20;
348 >
349 >        if(exp + 127 < 1023) {
350 >                exp = 0;
351 >        } else if(exp > 1023 + 127) {
352 >                exp = 255;
353 >        } else {
354 >                exp = exp + 127 - 1023;
355 >        }
356 >
357 >        result = sign | (exp << 23) | ((p[FHI] & 0x000FFFFF) << 3) | (p[FLO] >> 29);
358 >
359 >        D(bug("from_single (%.04f) = %X\r\n",(float)src,result));
360 >
361 >  return (result);
362   }
363  
364   static __inline__ double to_exten(uae_u32 wrd1, uae_u32 wrd2, uae_u32 wrd3)
365   {
366 <    double frac;
366 >        double result;
367 >        uae_u32 *p = (uae_u32 *)&result;
368 >
369 >  if ((wrd1 & 0x7fff0000) == 0 && wrd2 == 0 && wrd3 == 0) return 0.0;
370 >
371 >        uae_u32 sign =  wrd1 & 0x80000000;
372 >        uae_u32 exp  = (wrd1 >> 16) & 0x7fff;
373 >
374 >        // The explicit integer bit is not set, must normalize.
375 >        if((wrd2 & 0x80000000) == 0) {
376 >                D(bug("to_exten denormalized mantissa (%X,%X,%X)\r\n",wrd1,wrd2,wrd3));
377 >                if( wrd2 | wrd3 ) {
378 >                        // mantissa, not fraction.
379 >                        uae_u64 man = ((uae_u64)wrd2 << 32) | wrd3;
380 >                        while( (man & UVAL64(0x8000000000000000)) == 0 ) {
381 >                                man <<= 1;
382 >                                exp--;
383 >                        }
384 >                        wrd2 = (uae_u32)( man >> 32 );
385 >                        wrd3 = (uae_u32)( man & 0xFFFFFFFF );
386 >                } else {
387 >                        if(exp == 0x7FFF) {
388 >                                // Infinity.
389 >                        } else {
390 >                                // Zero
391 >                                exp = 16383 - 1023;
392 >                        }
393 >                }
394 >        }
395  
396 <    if ((wrd1 & 0x7fff0000) == 0 && wrd2 == 0 && wrd3 == 0)
397 <        return 0.0;
398 <    frac = (double) wrd2 / 2147483648.0 +
399 <        (double) wrd3 / 9223372036854775808.0;
400 <    if (wrd1 & 0x80000000)
401 <        frac = -frac;
402 <    return ldexp (frac, ((wrd1 >> 16) & 0x7fff) - 16383);
396 >        if(exp < 16383 - 1023) {
397 >                // should set underflow.
398 >                exp = 0;
399 >        } else if(exp > 16383 + 1023) {
400 >                // should set overflow.
401 >                exp = 2047;
402 >        } else {
403 >                exp = exp + 1023 - 16383;
404 >        }
405 >
406 >        // drop the explicit integer bit.
407 >        p[FLO] = (wrd2 << 21) | (wrd3 >> 11);
408 >        p[FHI] = sign | (exp << 20) | ((wrd2 & 0x7FFFFFFF) >> 11);
409 >
410 >        D(bug("to_exten (%X,%X,%X) = %.04f\r\n",wrd1,wrd2,wrd3,(float)result));
411 >
412 >        return(result);
413   }
414  
415   static __inline__ void from_exten(double src, uae_u32 * wrd1, uae_u32 * wrd2, uae_u32 * wrd3)
416   {
417 <    int expon;
418 <    double frac;
417 >        uae_u32 *p = (uae_u32 *)&src;
418 >
419 >        if (src == 0.0) {
420 >                *wrd1 = *wrd2 = *wrd3 = 0;
421 >                return;
422 >  }
423 >
424 >        D(bug("from_exten (%X,%X)\r\n",p[FLO],p[FHI]));
425 >
426 >        uae_u32 sign =  p[FHI] & 0x80000000;
427 >
428 >        uae_u32 exp  = ((p[FHI] >> 20) & 0x7ff);
429 >        // Check for maximum
430 >        if(exp == 0x7FF) {
431 >                exp = 0x7FFF;
432 >        } else {
433 >                exp  += 16383 - 1023;
434 >        }
435 >
436 >        *wrd1 = sign | (exp << 16);
437 >        // always set the explicit integer bit.
438 >        *wrd2 = 0x80000000 | ((p[FHI] & 0x000FFFFF) << 11) | ((p[FLO] & 0xFFE00000) >> 21);
439 >        *wrd3 = p[FLO] << 11;
440  
441 <    if (src == 0.0) {
85 <        *wrd1 = 0;
86 <        *wrd2 = 0;
87 <        *wrd3 = 0;
88 <        return;
89 <    }
90 <    if (src < 0) {
91 <        *wrd1 = 0x80000000;
92 <        src = -src;
93 <    } else {
94 <        *wrd1 = 0;
95 <    }
96 <    frac = frexp (src, &expon);
97 <    frac += 0.5 / 18446744073709551616.0;
98 <    if (frac >= 1.0) {
99 <        frac /= 2.0;
100 <        expon++;
101 <    }
102 <    *wrd1 |= (((expon + 16383 - 1) & 0x7fff) << 16);
103 <    *wrd2 = (uae_u32) (frac * 4294967296.0);
104 <    *wrd3 = (uae_u32) (frac * 18446744073709551616.0 - *wrd2 * 4294967296.0);
441 >        D(bug("from_exten (%.04f) = %X,%X,%X\r\n",(float)src,*wrd1,*wrd2,*wrd3));
442   }
443  
444   static __inline__ double to_double(uae_u32 wrd1, uae_u32 wrd2)
445   {
446 <    double frac;
446 >        double result;
447 >        uae_u32 *p;
448 >
449 >  if ((wrd1 & 0x7fffffff) == 0 && wrd2 == 0) return 0.0;
450  
451 <    if ((wrd1 & 0x7fffffff) == 0 && wrd2 == 0)
452 <        return 0.0;
453 <    frac = (double) ((wrd1 & 0xfffff) | 0x100000) / 1048576.0 +
454 <        (double) wrd2 / 4503599627370496.0;
455 <    if (wrd1 & 0x80000000)
456 <        frac = -frac;
457 <    return ldexp (frac, ((wrd1 >> 20) & 0x7ff) - 1023);
451 >        p = (uae_u32 *)&result;
452 >        p[FLO] = wrd2;
453 >        p[FHI] = wrd1;
454 >
455 >        D(bug("to_double (%X,%X) = %.04f\r\n",wrd1,wrd2,(float)result));
456 >
457 >        return(result);
458   }
459  
460   static __inline__ void from_double(double src, uae_u32 * wrd1, uae_u32 * wrd2)
461   {
462 <    int expon;
463 <    int tmp;
464 <    double frac;
465 <
466 <    if (src == 0.0) {
467 <        *wrd1 = 0;
468 <        *wrd2 = 0;
469 <        return;
470 <    }
471 <    if (src < 0) {
472 <        *wrd1 = 0x80000000;
473 <        src = -src;
474 <    } else {
475 <        *wrd1 = 0;
476 <    }
477 <    frac = frexp (src, &expon);
478 <    frac += 0.5 / 9007199254740992.0;
479 <    if (frac >= 1.0) {
480 <        frac /= 2.0;
481 <        expon++;
482 <    }
483 <    tmp = (uae_u32) (frac * 2097152.0);
484 <    *wrd1 |= (((expon + 1023 - 1) & 0x7ff) << 20) | (tmp & 0xfffff);
485 <    *wrd2 = (uae_u32) (frac * 9007199254740992.0 - tmp * 4294967296.0);
462 >  if (src == 0.0) {
463 >                *wrd1 = *wrd2 = 0;
464 >                return;
465 >  }
466 >        uae_u32 *p = (uae_u32 *)&src;
467 >        *wrd2 = p[FLO];
468 >        *wrd1 = p[FHI];
469 >
470 >        D(bug("from_double (%.04f) = %X,%X\r\n",(float)src,*wrd1,*wrd2));
471 > }
472 >
473 >
474 >
475 > #else // !HAVE_IEEE_DOUBLE
476 >
477 >
478 > #define MAKE_FPSR(fpsr,r) fpsr = (fpsr & 0x00FFFFFF) | (r == 0 ? 0x4000000 : 0) | (r < 0 ? 0x8000000 : 0)
479 >
480 >
481 > static __inline__ double to_single (uae_u32 value)
482 > {
483 >        double frac, result;
484 >
485 >        if ((value & 0x7fffffff) == 0)
486 >                return (0.0);
487 >        frac = (double) ((value & 0x7fffff) | 0x800000) / 8388608.0;
488 >        if (value & 0x80000000)
489 >                frac = -frac;
490 >        result = ldexp (frac, (int)((value >> 23) & 0xff) - 127);
491 >
492 >        D(bug("to_single (%X) = %.04f\r\n",value,(float)result));
493 >
494 >        return (result);
495 > }
496 >
497 > static __inline__ uae_u32 from_single (double src)
498 > {
499 >        int expon;
500 >        uae_u32 tmp, result;
501 >        double frac;
502 > #if DEBUG
503 >        double src0 = src;
504 > #endif
505 >
506 >  if (src == 0.0)
507 >                return 0;
508 >  if (src < 0) {
509 >                tmp = 0x80000000;
510 >                src = -src;
511 >  } else {
512 >                tmp = 0;
513 >  }
514 >  frac = frexp (src, &expon);
515 >  frac += 0.5 / 16777216.0;
516 >  if (frac >= 1.0) {
517 >                frac /= 2.0;
518 >                expon++;
519 >  }
520 >        result = tmp | (((expon + 127 - 1) & 0xff) << 23) | (((int) (frac * 16777216.0)) & 0x7fffff);
521 >
522 >        // D(bug("from_single (%.04f) = %X\r\n",(float)src0,result));
523 >
524 >  return (result);
525 > }
526 >
527 > static __inline__ double to_exten(uae_u32 wrd1, uae_u32 wrd2, uae_u32 wrd3)
528 > {
529 >  double frac, result;
530 >
531 >  if ((wrd1 & 0x7fff0000) == 0 && wrd2 == 0 && wrd3 == 0)
532 >                return 0.0;
533 >  frac = (double) wrd2 / 2147483648.0 +
534 >                                        (double) wrd3 / 9223372036854775808.0;
535 >  if (wrd1 & 0x80000000)
536 >                frac = -frac;
537 >  result = ldexp (frac, (int)((wrd1 >> 16) & 0x7fff) - 16383);
538 >
539 >        D(bug("to_exten (%X,%X,%X) = %.04f\r\n",wrd1,wrd2,wrd3,(float)result));
540 >
541 >  return result;
542 > }
543 >
544 > static __inline__ void from_exten(double src, uae_u32 * wrd1, uae_u32 * wrd2, uae_u32 * wrd3)
545 > {
546 >  int expon;
547 >        double frac;
548 > #if DEBUG
549 >        double src0 = src;
550 > #endif
551 >
552 >  if (src == 0.0) {
553 >                *wrd1 = 0;
554 >                *wrd2 = 0;
555 >                *wrd3 = 0;
556 >                return;
557 >  }
558 >  if (src < 0) {
559 >                *wrd1 = 0x80000000;
560 >                src = -src;
561 >  } else {
562 >                *wrd1 = 0;
563 >  }
564 >  frac = frexp (src, &expon);
565 >  frac += 0.5 / 18446744073709551616.0;
566 >  if (frac >= 1.0) {
567 >                frac /= 2.0;
568 >                expon++;
569 >  }
570 >  *wrd1 |= (((expon + 16383 - 1) & 0x7fff) << 16);
571 >  *wrd2 = (uae_u32) (frac * 4294967296.0);
572 >  *wrd3 = (uae_u32) (frac * 18446744073709551616.0 - *wrd2 * 4294967296.0);
573 >
574 >        // D(bug("from_exten (%.04f) = %X,%X,%X\r\n",(float)src0,*wrd1,*wrd2,*wrd3));
575 > }
576 >
577 > static __inline__ double to_double(uae_u32 wrd1, uae_u32 wrd2)
578 > {
579 >  double frac, result;
580 >
581 >  if ((wrd1 & 0x7fffffff) == 0 && wrd2 == 0)
582 >                return 0.0;
583 >  frac = (double) ((wrd1 & 0xfffff) | 0x100000) / 1048576.0 +
584 >                                        (double) wrd2 / 4503599627370496.0;
585 >  if (wrd1 & 0x80000000)
586 >                frac = -frac;
587 >        result = ldexp (frac, (int)((wrd1 >> 20) & 0x7ff) - 1023);
588 >
589 >        D(bug("to_double (%X,%X) = %.04f\r\n",wrd1,wrd2,(float)result));
590 >
591 >  return result;
592   }
593  
594 + static __inline__ void from_double(double src, uae_u32 * wrd1, uae_u32 * wrd2)
595 + {
596 +  int expon;
597 +  int tmp;
598 +        double frac;
599 + #if DEBUG
600 +        double src0 = src;
601 + #endif
602 +
603 +  if (src == 0.0) {
604 +                *wrd1 = 0;
605 +                *wrd2 = 0;
606 +                return;
607 +  }
608 +  if (src < 0) {
609 +                *wrd1 = 0x80000000;
610 +                src = -src;
611 +  } else {
612 +                *wrd1 = 0;
613 +  }
614 +  frac = frexp (src, &expon);
615 +  frac += 0.5 / 9007199254740992.0;
616 +  if (frac >= 1.0) {
617 +                frac /= 2.0;
618 +                expon++;
619 +  }
620 +  tmp = (uae_u32) (frac * 2097152.0);
621 +  *wrd1 |= (((expon + 1023 - 1) & 0x7ff) << 20) | (tmp & 0xfffff);
622 +  *wrd2 = (uae_u32) (frac * 9007199254740992.0 - tmp * 4294967296.0);
623 +
624 +        // D(bug("from_double (%.04f) = %X,%X\r\n",(float)src0,*wrd1,*wrd2));
625 + }
626 + #endif // HAVE_IEEE_DOUBLE
627 +
628   static __inline__ double to_pack(uae_u32 wrd1, uae_u32 wrd2, uae_u32 wrd3)
629   {
630 <    double d;
631 <    char *cp;
632 <    char str[100];
633 <
634 <    cp = str;
635 <    if (wrd1 & 0x80000000)
636 <        *cp++ = '-';
637 <    *cp++ = (wrd1 & 0xf) + '0';
638 <    *cp++ = '.';
639 <    *cp++ = ((wrd2 >> 28) & 0xf) + '0';
640 <    *cp++ = ((wrd2 >> 24) & 0xf) + '0';
641 <    *cp++ = ((wrd2 >> 20) & 0xf) + '0';
642 <    *cp++ = ((wrd2 >> 16) & 0xf) + '0';
643 <    *cp++ = ((wrd2 >> 12) & 0xf) + '0';
644 <    *cp++ = ((wrd2 >> 8) & 0xf) + '0';
645 <    *cp++ = ((wrd2 >> 4) & 0xf) + '0';
646 <    *cp++ = ((wrd2 >> 0) & 0xf) + '0';
647 <    *cp++ = ((wrd3 >> 28) & 0xf) + '0';
648 <    *cp++ = ((wrd3 >> 24) & 0xf) + '0';
649 <    *cp++ = ((wrd3 >> 20) & 0xf) + '0';
650 <    *cp++ = ((wrd3 >> 16) & 0xf) + '0';
651 <    *cp++ = ((wrd3 >> 12) & 0xf) + '0';
652 <    *cp++ = ((wrd3 >> 8) & 0xf) + '0';
653 <    *cp++ = ((wrd3 >> 4) & 0xf) + '0';
654 <    *cp++ = ((wrd3 >> 0) & 0xf) + '0';
655 <    *cp++ = 'E';
656 <    if (wrd1 & 0x40000000)
657 <        *cp++ = '-';
658 <    *cp++ = ((wrd1 >> 24) & 0xf) + '0';
659 <    *cp++ = ((wrd1 >> 20) & 0xf) + '0';
660 <    *cp++ = ((wrd1 >> 16) & 0xf) + '0';
661 <    *cp = 0;
662 <    sscanf(str, "%le", &d);
663 <    return d;
630 >  double d;
631 >  char *cp;
632 >  char str[100];
633 >
634 >  cp = str;
635 >  if (wrd1 & 0x80000000)
636 >                *cp++ = '-';
637 >  *cp++ = (char)((wrd1 & 0xf) + '0');
638 >  *cp++ = '.';
639 >  *cp++ = (char)(((wrd2 >> 28) & 0xf) + '0');
640 >  *cp++ = (char)(((wrd2 >> 24) & 0xf) + '0');
641 >  *cp++ = (char)(((wrd2 >> 20) & 0xf) + '0');
642 >  *cp++ = (char)(((wrd2 >> 16) & 0xf) + '0');
643 >  *cp++ = (char)(((wrd2 >> 12) & 0xf) + '0');
644 >  *cp++ = (char)(((wrd2 >> 8) & 0xf) + '0');
645 >  *cp++ = (char)(((wrd2 >> 4) & 0xf) + '0');
646 >  *cp++ = (char)(((wrd2 >> 0) & 0xf) + '0');
647 >  *cp++ = (char)(((wrd3 >> 28) & 0xf) + '0');
648 >  *cp++ = (char)(((wrd3 >> 24) & 0xf) + '0');
649 >  *cp++ = (char)(((wrd3 >> 20) & 0xf) + '0');
650 >  *cp++ = (char)(((wrd3 >> 16) & 0xf) + '0');
651 >  *cp++ = (char)(((wrd3 >> 12) & 0xf) + '0');
652 >  *cp++ = (char)(((wrd3 >> 8) & 0xf) + '0');
653 >  *cp++ = (char)(((wrd3 >> 4) & 0xf) + '0');
654 >  *cp++ = (char)(((wrd3 >> 0) & 0xf) + '0');
655 >  *cp++ = 'E';
656 >  if (wrd1 & 0x40000000)
657 >                *cp++ = '-';
658 >  *cp++ = (char)(((wrd1 >> 24) & 0xf) + '0');
659 >  *cp++ = (char)(((wrd1 >> 20) & 0xf) + '0');
660 >  *cp++ = (char)(((wrd1 >> 16) & 0xf) + '0');
661 >  *cp = 0;
662 >  sscanf(str, "%le", &d);
663 >
664 >        D(bug("to_pack str = %s\r\n",str));
665 >
666 >        D(bug("to_pack(%X,%X,%X) = %.04f\r\n",wrd1,wrd2,wrd3,(float)d));
667 >  return d;
668   }
669  
670   static __inline__ void from_pack(double src, uae_u32 * wrd1, uae_u32 * wrd2, uae_u32 * wrd3)
671   {
672 <    int i;
673 <    int t;
674 <    char *cp;
675 <    char str[100];
676 <
677 <    sprintf(str, "%.16e", src);
678 <    cp = str;
679 <    *wrd1 = *wrd2 = *wrd3 = 0;
680 <    if (*cp == '-') {
681 <        cp++;
682 <        *wrd1 = 0x80000000;
683 <    }
684 <    if (*cp == '+')
685 <        cp++;
686 <    *wrd1 |= (*cp++ - '0');
687 <    if (*cp == '.')
688 <        cp++;
689 <    for (i = 0; i < 8; i++) {
690 <        *wrd2 <<= 4;
691 <        if (*cp >= '0' && *cp <= '9')
672 >  int i;
673 >  int t;
674 >  char *cp;
675 >  char str[100];
676 >
677 >  sprintf(str, "%.16e", src);
678 >
679 >        D(bug("from_pack(%.04f,%s)\r\n",(float)src,str));
680 >
681 >  cp = str;
682 >  *wrd1 = *wrd2 = *wrd3 = 0;
683 >  if (*cp == '-') {
684 >                cp++;
685 >                *wrd1 = 0x80000000;
686 >  }
687 >  if (*cp == '+')
688 >                cp++;
689 >  *wrd1 |= (*cp++ - '0');
690 >  if (*cp == '.')
691 >                cp++;
692 >  for (i = 0; i < 8; i++) {
693 >                *wrd2 <<= 4;
694 >                if (*cp >= '0' && *cp <= '9')
695              *wrd2 |= *cp++ - '0';
696 <    }
697 <    for (i = 0; i < 8; i++) {
698 <        *wrd3 <<= 4;
699 <        if (*cp >= '0' && *cp <= '9')
696 >  }
697 >  for (i = 0; i < 8; i++) {
698 >                *wrd3 <<= 4;
699 >                if (*cp >= '0' && *cp <= '9')
700              *wrd3 |= *cp++ - '0';
701 <    }
702 <    if (*cp == 'e' || *cp == 'E') {
703 <        cp++;
704 <        if (*cp == '-') {
705 <            cp++;
706 <            *wrd1 |= 0x40000000;
707 <        }
708 <        if (*cp == '+')
709 <            cp++;
710 <        t = 0;
711 <        for (i = 0; i < 3; i++) {
712 <            if (*cp >= '0' && *cp <= '9')
713 <                t = (t << 4) | (*cp++ - '0');
714 <        }
715 <        *wrd1 |= t << 16;
716 <    }
701 >  }
702 >  if (*cp == 'e' || *cp == 'E') {
703 >                cp++;
704 >                if (*cp == '-') {
705 >                        cp++;
706 >                        *wrd1 |= 0x40000000;
707 >                }
708 >                if (*cp == '+')
709 >                        cp++;
710 >                t = 0;
711 >                for (i = 0; i < 3; i++) {
712 >                        if (*cp >= '0' && *cp <= '9')
713 >                                t = (t << 4) | (*cp++ - '0');
714 >                }
715 >                *wrd1 |= t << 16;
716 >  }
717 >
718 >        D(bug("from_pack(%.04f) = %X,%X,%X\r\n",(float)src,*wrd1,*wrd2,*wrd3));
719   }
720  
721   static __inline__ int get_fp_value (uae_u32 opcode, uae_u16 extra, double *src)
722   {
723 <    uaecptr tmppc;
724 <    uae_u16 tmp;
725 <    int size;
726 <    int mode;
727 <    int reg;
728 <    uae_u32 ad = 0;
729 <    static int sz1[8] =
730 <    {4, 4, 12, 12, 2, 8, 1, 0};
731 <    static int sz2[8] =
732 <    {4, 4, 12, 12, 2, 8, 2, 0};
733 <
734 <    if ((extra & 0x4000) == 0) {
735 <        *src = regs.fp[(extra >> 10) & 7];
736 <        return 1;
737 <    }
738 <    mode = (opcode >> 3) & 7;
739 <    reg = opcode & 7;
740 <    size = (extra >> 10) & 7;
741 <    switch (mode) {
723 >  uaecptr tmppc;
724 >  uae_u16 tmp;
725 >  int size;
726 >  int mode;
727 >  int reg;
728 >  uae_u32 ad = 0;
729 >  static int sz1[8] = {4, 4, 12, 12, 2, 8, 1, 0};
730 >  static int sz2[8] = {4, 4, 12, 12, 2, 8, 2, 0};
731 >
732 >        // D(bug("get_fp_value(%X,%X)\r\n",(int)opcode,(int)extra));
733 >        // dump_first_bytes( regs.pc_p-4, 16 );
734 >
735 >  if ((extra & 0x4000) == 0) {
736 >                *src = regs.fp[(extra >> 10) & 7];
737 >                return 1;
738 >  }
739 >  mode = (opcode >> 3) & 7;
740 >  reg = opcode & 7;
741 >  size = (extra >> 10) & 7;
742 >
743 >        D(bug("get_fp_value mode=%d, reg=%d, size=%d\r\n",(int)mode,(int)reg,(int)size));
744 >
745 >  switch (mode) {
746      case 0:
747 <        switch (size) {
748 <        case 6:
749 <            *src = (double) (uae_s8) m68k_dreg (regs, reg);
750 <            break;
751 <        case 4:
752 <            *src = (double) (uae_s16) m68k_dreg (regs, reg);
753 <            break;
754 <        case 0:
755 <            *src = (double) (uae_s32) m68k_dreg (regs, reg);
756 <            break;
757 <        case 1:
758 <            *src = to_single(m68k_dreg (regs, reg));
759 <            break;
760 <        default:
761 <            return 0;
762 <        }
763 <        return 1;
747 >                        switch (size) {
748 >                                case 6:
749 >                                        *src = (double) (uae_s8) m68k_dreg (regs, reg);
750 >                                        break;
751 >                                case 4:
752 >                                        *src = (double) (uae_s16) m68k_dreg (regs, reg);
753 >                                        break;
754 >                                case 0:
755 >                                        *src = (double) (uae_s32) m68k_dreg (regs, reg);
756 >                                        break;
757 >                                case 1:
758 >                                        *src = to_single(m68k_dreg (regs, reg));
759 >                                        break;
760 >                                default:
761 >                                        return 0;
762 >                        }
763 >                        return 1;
764      case 1:
765 <        return 0;
765 >                        return 0;
766      case 2:
767 <        ad = m68k_areg (regs, reg);
768 <        break;
767 >                        ad = m68k_areg (regs, reg);
768 >                        break;
769      case 3:
770 <        ad = m68k_areg (regs, reg);
771 <        m68k_areg (regs, reg) += reg == 7 ? sz2[size] : sz1[size];
772 <        break;
770 >                        ad = m68k_areg (regs, reg);
771 >                        m68k_areg (regs, reg) += reg == 7 ? sz2[size] : sz1[size];
772 >                        break;
773      case 4:
774 <        m68k_areg (regs, reg) -= reg == 7 ? sz2[size] : sz1[size];
775 <        ad = m68k_areg (regs, reg);
776 <        break;
774 >                        m68k_areg (regs, reg) -= reg == 7 ? sz2[size] : sz1[size];
775 >                        ad = m68k_areg (regs, reg);
776 >                        break;
777      case 5:
778 <        ad = m68k_areg (regs, reg) + (uae_s32) (uae_s16) next_iword();
779 <        break;
778 >                        ad = m68k_areg (regs, reg) + (uae_s32) (uae_s16) next_iword();
779 >                        break;
780      case 6:
781 <        ad = get_disp_ea_020 (m68k_areg (regs, reg), next_iword());
782 <        break;
781 >                        ad = get_disp_ea_020 (m68k_areg (regs, reg), next_iword());
782 >                        break;
783      case 7:
784 <        switch (reg) {
785 <        case 0:
786 <            ad = (uae_s32) (uae_s16) next_iword();
787 <            break;
788 <        case 1:
789 <            ad = next_ilong();
790 <            break;
791 <        case 2:
792 <            ad = m68k_getpc ();
793 <            ad += (uae_s32) (uae_s16) next_iword();
794 <            break;
795 <        case 3:
796 <            tmppc = m68k_getpc ();
797 <            tmp = next_iword();
798 <            ad = get_disp_ea_020 (tmppc, tmp);
799 <            break;
800 <        case 4:
801 <            ad = m68k_getpc ();
802 <            m68k_setpc (ad + sz2[size]);
803 <            break;
804 <        default:
805 <            return 0;
806 <        }
807 <    }
808 <    switch (size) {
784 >                        switch (reg) {
785 >                                case 0:
786 >                            ad = (uae_s32) (uae_s16) next_iword();
787 >                                        break;
788 >                                case 1:
789 >                                        ad = next_ilong();
790 >                                        break;
791 >                                case 2:
792 >                                        ad = m68k_getpc ();
793 >                                        ad += (uae_s32) (uae_s16) next_iword();
794 >        D(bug("get_fp_value next_iword()=%X\r\n",ad-m68k_getpc()-2));
795 >                                        break;
796 >                                case 3:
797 >                                        tmppc = m68k_getpc ();
798 >                                        tmp = (uae_u16)next_iword();
799 >                                        ad = get_disp_ea_020 (tmppc, tmp);
800 >                                        break;
801 >                                case 4:
802 >                            ad = m68k_getpc ();
803 >                                        m68k_setpc (ad + sz2[size]);
804 >                                        break;
805 >                                default:
806 >                                        return 0;
807 >                        }
808 >  }
809 >
810 >        D(bug("get_fp_value m68k_getpc()=%X\r\n",m68k_getpc()));
811 >        D(bug("get_fp_value ad=%X\r\n",ad));
812 >        D(bug("get_fp_value get_long (ad)=%X\r\n",get_long (ad)));
813 >        dump_first_bytes( get_real_address(ad)-64, 64 );
814 >        dump_first_bytes( get_real_address(ad), 64 );
815 >
816 >  switch (size) {
817      case 0:
818 <        *src = (double) (uae_s32) get_long (ad);
819 <        break;
818 >                        *src = (double) (uae_s32) get_long (ad);
819 >                        break;
820      case 1:
821 <        *src = to_single(get_long (ad));
822 <        break;
821 >                        *src = to_single(get_long (ad));
822 >                        break;
823 >
824      case 2:{
825              uae_u32 wrd1, wrd2, wrd3;
826              wrd1 = get_long (ad);
# Line 327 | Line 829 | static __inline__ int get_fp_value (uae_
829              ad += 4;
830              wrd3 = get_long (ad);
831              *src = to_exten(wrd1, wrd2, wrd3);
832 <        }
833 <        break;
832 >                        }
833 >                        break;
834      case 3:{
835              uae_u32 wrd1, wrd2, wrd3;
836              wrd1 = get_long (ad);
# Line 337 | Line 839 | static __inline__ int get_fp_value (uae_
839              ad += 4;
840              wrd3 = get_long (ad);
841              *src = to_pack(wrd1, wrd2, wrd3);
842 <        }
843 <        break;
842 >                        }
843 >                        break;
844      case 4:
845 <        *src = (double) (uae_s16) get_word(ad);
846 <        break;
845 >                        *src = (double) (uae_s16) get_word(ad);
846 >                        break;
847      case 5:{
848              uae_u32 wrd1, wrd2;
849              wrd1 = get_long (ad);
850              ad += 4;
851              wrd2 = get_long (ad);
852              *src = to_double(wrd1, wrd2);
853 <        }
854 <        break;
853 >                        }
854 >                        break;
855      case 6:
856 <        *src = (double) (uae_s8) get_byte(ad);
857 <        break;
856 >                        *src = (double) (uae_s8) get_byte(ad);
857 >                        break;
858      default:
859 <        return 0;
860 <    }
861 <    return 1;
859 >                        return 0;
860 >  }
861 >
862 >        // D(bug("get_fp_value result = %.04f\r\n",(float)*src));
863 >
864 >  return 1;
865   }
866  
867   static __inline__ int put_fp_value (double value, uae_u32 opcode, uae_u16 extra)
868   {
869 <    uae_u16 tmp;
870 <    uaecptr tmppc;
871 <    int size;
872 <    int mode;
873 <    int reg;
874 <    uae_u32 ad;
875 <    static int sz1[8] =
876 <    {4, 4, 12, 12, 2, 8, 1, 0};
877 <    static int sz2[8] =
878 <    {4, 4, 12, 12, 2, 8, 2, 0};
879 <
880 <    if ((extra & 0x4000) == 0) {
881 <        regs.fp[(extra >> 10) & 7] = value;
882 <        return 1;
883 <    }
884 <    mode = (opcode >> 3) & 7;
885 <    reg = opcode & 7;
886 <    size = (extra >> 10) & 7;
887 <    ad = 0xffffffff;
888 <    switch (mode) {
869 >  uae_u16 tmp;
870 >  uaecptr tmppc;
871 >  int size;
872 >  int mode;
873 >  int reg;
874 >  uae_u32 ad;
875 >  static int sz1[8] = {4, 4, 12, 12, 2, 8, 1, 0};
876 >  static int sz2[8] = {4, 4, 12, 12, 2, 8, 2, 0};
877 >
878 >        // D(bug("put_fp_value(%.04f,%X,%X)\r\n",(float)value,(int)opcode,(int)extra));
879 >
880 >  if ((extra & 0x4000) == 0) {
881 >                int dest_reg = (extra >> 10) & 7;
882 >                regs.fp[dest_reg] = value;
883 >                MAKE_FPSR(regs.fpsr,regs.fp[dest_reg]);
884 >                return 1;
885 >  }
886 >  mode = (opcode >> 3) & 7;
887 >  reg = opcode & 7;
888 >  size = (extra >> 10) & 7;
889 >  ad = 0xffffffff;
890 >  switch (mode) {
891      case 0:
892 <        switch (size) {
893 <        case 6:
894 <            m68k_dreg (regs, reg) = (((int) value & 0xff)
892 >                        switch (size) {
893 >                                case 6:
894 >                                        m68k_dreg (regs, reg) = (((int) value & 0xff)
895                                      | (m68k_dreg (regs, reg) & ~0xff));
896 <            break;
897 <        case 4:
898 <            m68k_dreg (regs, reg) = (((int) value & 0xffff)
896 >                                        break;
897 >                                case 4:
898 >                                        m68k_dreg (regs, reg) = (((int) value & 0xffff)
899                                      | (m68k_dreg (regs, reg) & ~0xffff));
900 <            break;
901 <        case 0:
902 <            m68k_dreg (regs, reg) = (int) value;
903 <            break;
904 <        case 1:
905 <            m68k_dreg (regs, reg) = from_single(value);
906 <            break;
907 <        default:
908 <            return 0;
909 <        }
910 <        return 1;
911 <    case 1:
912 <        return 0;
900 >                                        break;
901 >                                case 0:
902 >                                        m68k_dreg (regs, reg) = (int) value;
903 >                                        break;
904 >                                case 1:
905 >                                        m68k_dreg (regs, reg) = from_single(value);
906 >                                        break;
907 >                                default:
908 >                                        return 0;
909 >                        }
910 >                        return 1;
911 >                case 1:
912 >                        return 0;
913      case 2:
914 <        ad = m68k_areg (regs, reg);
915 <        break;
914 >                        ad = m68k_areg (regs, reg);
915 >                        break;
916      case 3:
917 <        ad = m68k_areg (regs, reg);
918 <        m68k_areg (regs, reg) += reg == 7 ? sz2[size] : sz1[size];
919 <        break;
917 >                        ad = m68k_areg (regs, reg);
918 >                        m68k_areg (regs, reg) += reg == 7 ? sz2[size] : sz1[size];
919 >                        break;
920      case 4:
921 <        m68k_areg (regs, reg) -= reg == 7 ? sz2[size] : sz1[size];
922 <        ad = m68k_areg (regs, reg);
923 <        break;
921 >                        m68k_areg (regs, reg) -= reg == 7 ? sz2[size] : sz1[size];
922 >                        ad = m68k_areg (regs, reg);
923 >                        break;
924      case 5:
925 <        ad = m68k_areg (regs, reg) + (uae_s32) (uae_s16) next_iword();
926 <        break;
925 >                        ad = m68k_areg (regs, reg) + (uae_s32) (uae_s16) next_iword();
926 >                        break;
927      case 6:
928 <        ad = get_disp_ea_020 (m68k_areg (regs, reg), next_iword());
929 <        break;
928 >                        ad = get_disp_ea_020 (m68k_areg (regs, reg), next_iword());
929 >                        break;
930      case 7:
931 <        switch (reg) {
932 <        case 0:
933 <            ad = (uae_s32) (uae_s16) next_iword();
934 <            break;
935 <        case 1:
936 <            ad = next_ilong();
937 <            break;
938 <        case 2:
939 <            ad = m68k_getpc ();
940 <            ad += (uae_s32) (uae_s16) next_iword();
941 <            break;
942 <        case 3:
943 <            tmppc = m68k_getpc ();
944 <            tmp = next_iword();
945 <            ad = get_disp_ea_020 (tmppc, tmp);
946 <            break;
947 <        case 4:
948 <            ad = m68k_getpc ();
949 <            m68k_setpc (ad + sz2[size]);
950 <            break;
951 <        default:
952 <            return 0;
953 <        }
954 <    }
955 <    switch (size) {
931 >                        switch (reg) {
932 >                                case 0:
933 >                                        ad = (uae_s32) (uae_s16) next_iword();
934 >                                        break;
935 >                                case 1:
936 >                                        ad = next_ilong();
937 >                                        break;
938 >                                case 2:
939 >                                        ad = m68k_getpc ();
940 >                                        ad += (uae_s32) (uae_s16) next_iword();
941 >                                        break;
942 >                                case 3:
943 >                                        tmppc = m68k_getpc ();
944 >                                        tmp = (uae_u16)next_iword();
945 >                                        ad = get_disp_ea_020 (tmppc, tmp);
946 >                                        break;
947 >                                case 4:
948 >                                        ad = m68k_getpc ();
949 >                                        m68k_setpc (ad + sz2[size]);
950 >                                        break;
951 >                                default:
952 >                                        return 0;
953 >                        }
954 >  }
955 >  switch (size) {
956      case 0:
957 <        put_long (ad, (uae_s32) value);
958 <        break;
957 >                        put_long (ad, (uae_s32) value);
958 >                        break;
959      case 1:
960 <        put_long (ad, from_single(value));
961 <        break;
962 <    case 2:
963 <        {
964 <            uae_u32 wrd1, wrd2, wrd3;
965 <            from_exten(value, &wrd1, &wrd2, &wrd3);
966 <            put_long (ad, wrd1);
967 <            ad += 4;
968 <            put_long (ad, wrd2);
969 <            ad += 4;
970 <            put_long (ad, wrd3);
971 <        }
972 <        break;
960 >                        put_long (ad, from_single(value));
961 >                        break;
962 >                case 2:
963 >                        {
964 >                                        uae_u32 wrd1, wrd2, wrd3;
965 >                                        from_exten(value, &wrd1, &wrd2, &wrd3);
966 >                                        put_long (ad, wrd1);
967 >                                        ad += 4;
968 >                                        put_long (ad, wrd2);
969 >                                        ad += 4;
970 >                                        put_long (ad, wrd3);
971 >                        }
972 >                        break;
973      case 3:
974 <        {
975 <            uae_u32 wrd1, wrd2, wrd3;
976 <            from_pack(value, &wrd1, &wrd2, &wrd3);
977 <            put_long (ad, wrd1);
978 <            ad += 4;
979 <            put_long (ad, wrd2);
980 <            ad += 4;
981 <            put_long (ad, wrd3);
982 <        }
983 <        break;
984 <    case 4:
985 <        put_word(ad, (uae_s16) value);
986 <        break;
974 >                        {
975 >                                        uae_u32 wrd1, wrd2, wrd3;
976 >                                        from_pack(value, &wrd1, &wrd2, &wrd3);
977 >                                        put_long (ad, wrd1);
978 >                                        ad += 4;
979 >                                        put_long (ad, wrd2);
980 >                                        ad += 4;
981 >                                        put_long (ad, wrd3);
982 >                        }
983 >                        break;
984 >                case 4:
985 >                        put_word(ad, (uae_s16) value);
986 >                        break;
987      case 5:{
988              uae_u32 wrd1, wrd2;
989              from_double(value, &wrd1, &wrd2);
990              put_long (ad, wrd1);
991              ad += 4;
992              put_long (ad, wrd2);
993 <        }
994 <        break;
993 >                        }
994 >                        break;
995      case 6:
996 <        put_byte(ad, (uae_s8) value);
997 <        break;
996 >                        put_byte(ad, (uae_s8) value);
997 >                        break;
998      default:
999 <        return 0;
1000 <    }
1001 <    return 1;
999 >                        return 0;
1000 >  }
1001 >  return 1;
1002   }
1003  
1004   static __inline__ int get_fp_ad(uae_u32 opcode, uae_u32 * ad)
1005   {
1006 <    uae_u16 tmp;
1007 <    uaecptr tmppc;
1008 <    int mode;
1009 <    int reg;
1010 <
1011 <    mode = (opcode >> 3) & 7;
1012 <    reg = opcode & 7;
1013 <    switch (mode) {
1006 >  uae_u16 tmp;
1007 >  uaecptr tmppc;
1008 >  int mode;
1009 >  int reg;
1010 >
1011 >  mode = (opcode >> 3) & 7;
1012 >  reg = opcode & 7;
1013 >  switch (mode) {
1014      case 0:
1015      case 1:
1016 <        return 0;
1016 >                        return 0;
1017      case 2:
1018 <        *ad = m68k_areg (regs, reg);
1019 <        break;
1018 >                        *ad = m68k_areg (regs, reg);
1019 >                        break;
1020      case 3:
1021 <        *ad = m68k_areg (regs, reg);
1022 <        break;
1021 >                        *ad = m68k_areg (regs, reg);
1022 >                        break;
1023      case 4:
1024 <        *ad = m68k_areg (regs, reg);
1025 <        break;
1024 >                        *ad = m68k_areg (regs, reg);
1025 >                        break;
1026      case 5:
1027 <        *ad = m68k_areg (regs, reg) + (uae_s32) (uae_s16) next_iword();
1028 <        break;
1027 >                        *ad = m68k_areg (regs, reg) + (uae_s32) (uae_s16) next_iword();
1028 >                        break;
1029      case 6:
1030 <        *ad = get_disp_ea_020 (m68k_areg (regs, reg), next_iword());
1031 <        break;
1030 >                        *ad = get_disp_ea_020 (m68k_areg (regs, reg), next_iword());
1031 >                        break;
1032      case 7:
1033 <        switch (reg) {
1034 <        case 0:
1035 <            *ad = (uae_s32) (uae_s16) next_iword();
1036 <            break;
1037 <        case 1:
1038 <            *ad = next_ilong();
1039 <            break;
1040 <        case 2:
1041 <            *ad = m68k_getpc ();
1042 <            *ad += (uae_s32) (uae_s16) next_iword();
1043 <            break;
1044 <        case 3:
1045 <            tmppc = m68k_getpc ();
1046 <            tmp = next_iword();
1047 <            *ad = get_disp_ea_020 (tmppc, tmp);
1048 <            break;
1049 <        default:
1050 <            return 0;
1051 <        }
1052 <    }
1053 <    return 1;
1033 >                        switch (reg) {
1034 >                                case 0:
1035 >                                        *ad = (uae_s32) (uae_s16) next_iword();
1036 >                                        break;
1037 >                                case 1:
1038 >                                        *ad = next_ilong();
1039 >                                        break;
1040 >                                case 2:
1041 >                                        *ad = m68k_getpc ();
1042 >                                        *ad += (uae_s32) (uae_s16) next_iword();
1043 >                                        break;
1044 >                                case 3:
1045 >                                        tmppc = m68k_getpc ();
1046 >                                        tmp = (uae_u16)next_iword();
1047 >                                        *ad = get_disp_ea_020 (tmppc, tmp);
1048 >                                        break;
1049 >                                default:
1050 >                                        return 0;
1051 >                        }
1052 >  }
1053 >  return 1;
1054   }
1055  
1056   static __inline__ int fpp_cond(uae_u32 opcode, int contition)
1057   {
1058 <    int N = (regs.fpsr & 0x8000000) != 0;
1059 <    int Z = (regs.fpsr & 0x4000000) != 0;
1060 <    /* int I = (regs.fpsr & 0x2000000) != 0; */
1061 <    int NotANumber = (regs.fpsr & 0x1000000) != 0;
1058 >  int N = (regs.fpsr & 0x8000000) != 0;
1059 >  int Z = (regs.fpsr & 0x4000000) != 0;
1060 >  /* int I = (regs.fpsr & 0x2000000) != 0; */
1061 >  int NotANumber = (regs.fpsr & 0x1000000) != 0;
1062  
1063 <    switch (contition) {
1063 >  switch (contition) {
1064      case 0x00:
1065 <        return 0;
1065 >                        CONDRET("False",0);
1066      case 0x01:
1067 <        return Z;
1067 >                        CONDRET("Equal",Z);
1068      case 0x02:
1069 <        return !(NotANumber || Z || N);
1069 >                        CONDRET("Ordered Greater Than",!(NotANumber || Z || N));
1070      case 0x03:
1071 <        return Z || !(NotANumber || N);
1071 >                        CONDRET("Ordered Greater Than or Equal",Z || !(NotANumber || N));
1072      case 0x04:
1073 <        return N && !(NotANumber || Z);
1073 >                        CONDRET("Ordered Less Than",N && !(NotANumber || Z));
1074      case 0x05:
1075 <        return Z || (N && !NotANumber);
1075 >                        CONDRET("Ordered Less Than or Equal",Z || (N && !NotANumber));
1076      case 0x06:
1077 <        return !(NotANumber || Z);
1077 >                        CONDRET("Ordered Greater or Less Than",!(NotANumber || Z));
1078      case 0x07:
1079 <        return !NotANumber;
1079 >                        CONDRET("Ordered",!NotANumber);
1080      case 0x08:
1081 <        return NotANumber;
1081 >                        CONDRET("Unordered",NotANumber);
1082      case 0x09:
1083 <        return NotANumber || Z;
1083 >                        CONDRET("Unordered or Equal",NotANumber || Z);
1084      case 0x0a:
1085 <        return NotANumber || !(N || Z);
1085 >                        CONDRET("Unordered or Greater Than",NotANumber || !(N || Z));
1086      case 0x0b:
1087 <        return NotANumber || Z || !N;
1087 >                        CONDRET("Unordered or Greater or Equal",NotANumber || Z || !N);
1088      case 0x0c:
1089 <        return NotANumber || (N && !Z);
1089 >                        CONDRET("Unordered or Less Than",NotANumber || (N && !Z));
1090      case 0x0d:
1091 <        return NotANumber || Z || N;
1091 >                        CONDRET("Unordered or Less or Equal",NotANumber || Z || N);
1092      case 0x0e:
1093 <        return !Z;
1093 >                        CONDRET("Not Equal",!Z);
1094      case 0x0f:
1095 <        return 1;
1095 >                        CONDRET("True",1);
1096      case 0x10:
1097 <        return 0;
1097 >                        CONDRET("Signaling False",0);
1098      case 0x11:
1099 <        return Z;
1099 >                        CONDRET("Signaling Equal",Z);
1100      case 0x12:
1101 <        return !(NotANumber || Z || N);
1101 >                        CONDRET("Greater Than",!(NotANumber || Z || N));
1102      case 0x13:
1103 <        return Z || !(NotANumber || N);
1103 >                        CONDRET("Greater Than or Equal",Z || !(NotANumber || N));
1104      case 0x14:
1105 <        return N && !(NotANumber || Z);
1105 >                        CONDRET("Less Than",N && !(NotANumber || Z));
1106      case 0x15:
1107 <        return Z || (N && !NotANumber);
1107 >                        CONDRET("Less Than or Equal",Z || (N && !NotANumber));
1108      case 0x16:
1109 <        return !(NotANumber || Z);
1109 >                        CONDRET("Greater or Less Than",!(NotANumber || Z));
1110      case 0x17:
1111 <        return !NotANumber;
1111 >                        CONDRET("Greater, Less or Equal",!NotANumber);
1112      case 0x18:
1113 <        return NotANumber;
1113 >                        CONDRET("Not Greater, Less or Equal",NotANumber);
1114      case 0x19:
1115 <        return NotANumber || Z;
1115 >                        CONDRET("Not Greater or Less Than",NotANumber || Z);
1116      case 0x1a:
1117 <        return NotANumber || !(N || Z);
1117 >                        CONDRET("Not Less Than or Equal",NotANumber || !(N || Z));
1118      case 0x1b:
1119 <        return NotANumber || Z || !N;
1119 >                        CONDRET("Not Less Than",NotANumber || Z || !N);
1120      case 0x1c:
1121 <        return NotANumber || (Z && N);
1121 >                        // CONDRET("Not Greater Than or Equal",NotANumber || (Z && N));
1122 >                        CONDRET("Not Greater Than or Equal",!Z && (NotANumber || N));
1123      case 0x1d:
1124 <        return NotANumber || Z || N;
1124 >                        CONDRET("Not Greater Than",NotANumber || Z || N);
1125      case 0x1e:
1126 <        return !Z;
1126 >                        CONDRET("Signaling Not Equal",!Z);
1127      case 0x1f:
1128 <        return 1;
1129 <    }
1130 <    return -1;
1128 >                        CONDRET("Signaling True",1);
1129 >  }
1130 >        CONDRET("",-1);
1131   }
1132  
1133   void fdbcc_opp(uae_u32 opcode, uae_u16 extra)
1134   {
1135 <    uaecptr pc = (uae_u32) m68k_getpc ();
1136 <    uae_s32 disp = (uae_s32) (uae_s16) next_iword();
1137 <    int cc;
1138 <
1139 < #if DEBUG_FPP
1140 <    printf("fdbcc_opp at %08lx\n", m68k_getpc ());
1141 <    fflush(stdout);
1142 < #endif
1143 <    cc = fpp_cond(opcode, extra & 0x3f);
1144 <    if (cc == -1) {
1145 <        m68k_setpc (pc - 4);
1146 <        op_illg (opcode);
639 <    } else if (!cc) {
640 <        int reg = opcode & 0x7;
1135 >  uaecptr pc = (uae_u32) m68k_getpc ();
1136 >  uae_s32 disp = (uae_s32) (uae_s16) next_iword();
1137 >  int cc;
1138 >
1139 >  D(bug("fdbcc_opp %X, %X at %08lx\r\n", (uae_u32)opcode, (uae_u32)extra, m68k_getpc ()));
1140 >
1141 >  cc = fpp_cond(opcode, extra & 0x3f);
1142 >  if (cc == -1) {
1143 >                m68k_setpc (pc - 4);
1144 >                op_illg (opcode);
1145 >  } else if (!cc) {
1146 >                int reg = opcode & 0x7;
1147  
1148 <        m68k_dreg (regs, reg) = ((m68k_dreg (regs, reg) & ~0xffff)
1148 >                // this may have leaked.
1149 >                /*
1150 >                m68k_dreg (regs, reg) = ((m68k_dreg (regs, reg) & ~0xffff)
1151                                  | ((m68k_dreg (regs, reg) - 1) & 0xffff));
1152 <        if ((m68k_dreg (regs, reg) & 0xffff) == 0xffff)
1152 >                */
1153 >                m68k_dreg (regs, reg) = ((m68k_dreg (regs, reg) & 0xffff0000)
1154 >                                | (((m68k_dreg (regs, reg) & 0xffff) - 1) & 0xffff));
1155 >
1156 >                
1157 >                // condition reversed.
1158 >                // if ((m68k_dreg (regs, reg) & 0xffff) == 0xffff)
1159 >                if ((m68k_dreg (regs, reg) & 0xffff) != 0xffff)
1160              m68k_setpc (pc + disp);
1161 <    }
1161 >  }
1162   }
1163  
1164   void fscc_opp(uae_u32 opcode, uae_u16 extra)
1165   {
1166 <    uae_u32 ad;
1167 <    int cc;
1166 >  uae_u32 ad;
1167 >  int cc;
1168  
1169 < #if DEBUG_FPP
1170 <    printf("fscc_opp at %08lx\n", m68k_getpc ());
1171 <    fflush(stdout);
1172 < #endif
1173 <    cc = fpp_cond(opcode, extra & 0x3f);
1174 <    if (cc == -1) {
1175 <        m68k_setpc (m68k_getpc () - 4);
1176 <        op_illg (opcode);
662 <    } else if ((opcode & 0x38) == 0) {
663 <        m68k_dreg (regs, opcode & 7) = (m68k_dreg (regs, opcode & 7) & ~0xff) |
1169 >  D(bug("fscc_opp %X, %X at %08lx\r\n", (uae_u32)opcode, (uae_u32)extra, m68k_getpc ()));
1170 >
1171 >  cc = fpp_cond(opcode, extra & 0x3f);
1172 >  if (cc == -1) {
1173 >                m68k_setpc (m68k_getpc () - 4);
1174 >                op_illg (opcode);
1175 >  } else if ((opcode & 0x38) == 0) {
1176 >                m68k_dreg (regs, opcode & 7) = (m68k_dreg (regs, opcode & 7) & ~0xff) |
1177              (cc ? 0xff : 0x00);
1178 <    } else {
1179 <        if (get_fp_ad(opcode, &ad) == 0) {
1178 >  } else {
1179 >                if (get_fp_ad(opcode, &ad) == 0) {
1180              m68k_setpc (m68k_getpc () - 4);
1181              op_illg (opcode);
1182 <        } else
1182 >                } else
1183              put_byte(ad, cc ? 0xff : 0x00);
1184 <    }
1184 >  }
1185   }
1186  
1187   void ftrapcc_opp(uae_u32 opcode, uaecptr oldpc)
1188   {
1189 <    int cc;
1189 >  int cc;
1190  
1191 < #if DEBUG_FPP
1192 <    printf("ftrapcc_opp at %08lx\n", m68k_getpc ());
1193 <    fflush(stdout);
1194 < #endif
1195 <    cc = fpp_cond(opcode, opcode & 0x3f);
1196 <    if (cc == -1) {
1197 <        m68k_setpc (oldpc);
1198 <        op_illg (opcode);
1199 <    }
687 <    if (cc)
688 <        Exception(7, oldpc - 2);
1191 >  D(bug("ftrapcc_opp %X at %08lx\r\n", (uae_u32)opcode, m68k_getpc ()));
1192 >
1193 >  cc = fpp_cond(opcode, opcode & 0x3f);
1194 >  if (cc == -1) {
1195 >                m68k_setpc (oldpc);
1196 >                op_illg (opcode);
1197 >  }
1198 >  if (cc)
1199 >                Exception(7, oldpc - 2);
1200   }
1201  
1202 + // NOTE that we get here also when there is a FNOP (nontrapping false, displ 0)
1203   void fbcc_opp(uae_u32 opcode, uaecptr pc, uae_u32 extra)
1204   {
1205 <    int cc;
1205 >  int cc;
1206  
1207 < #if DEBUG_FPP
1208 <    printf("fbcc_opp at %08lx\n", m68k_getpc ());
1209 <    fflush(stdout);
1210 < #endif
1211 <    cc = fpp_cond(opcode, opcode & 0x3f);
1212 <    if (cc == -1) {
1213 <        m68k_setpc (pc);
1214 <        op_illg (opcode);
703 <    } else if (cc) {
704 <        if ((opcode & 0x40) == 0)
1207 >  D(bug("fbcc_opp %X, %X at %08lx, jumpto=%X\r\n", (uae_u32)opcode, (uae_u32)extra, m68k_getpc (), extra ));
1208 >
1209 >  cc = fpp_cond(opcode, opcode & 0x3f);
1210 >  if (cc == -1) {
1211 >                m68k_setpc (pc);
1212 >                op_illg (opcode);
1213 >  } else if (cc) {
1214 >                if ((opcode & 0x40) == 0)
1215              extra = (uae_s32) (uae_s16) extra;
1216 <        m68k_setpc (pc + extra);
1217 <    }
1216 >                m68k_setpc (pc + extra);
1217 >  }
1218   }
1219  
1220 + // FSAVE has no post-increment
1221 + // 0x1f180000 == IDLE state frame, coprocessor version number 1F
1222   void fsave_opp(uae_u32 opcode)
1223   {
1224 <    uae_u32 ad;
1225 <    int incr = (opcode & 0x38) == 0x20 ? -1 : 1;
1226 <    int i;
1227 <
1228 < #if DEBUG_FPP
1229 <    printf("fsave_opp at %08lx\n", m68k_getpc ());
1230 <    fflush(stdout);
1231 < #endif
1232 <    if (get_fp_ad(opcode, &ad) == 0) {
1233 <        m68k_setpc (m68k_getpc () - 2);
1234 <        op_illg (opcode);
1235 <        return;
1236 <    }
1237 <    if (incr < 0) {
1238 <        ad -= 4;
1239 <        put_long (ad, 0x70000000);
1240 <        for (i = 0; i < 5; i++) {
1241 <            ad -= 4;
1242 <            put_long (ad, 0x00000000);
1224 >  uae_u32 ad;
1225 >  int incr = (opcode & 0x38) == 0x20 ? -1 : 1;
1226 >  int i;
1227 >
1228 >  D(bug("fsave_opp at %08lx\r\n", m68k_getpc ()));
1229 >
1230 >  if (get_fp_ad(opcode, &ad) == 0) {
1231 >                m68k_setpc (m68k_getpc () - 2);
1232 >                op_illg (opcode);
1233 >                return;
1234 >  }
1235 >        
1236 >        if (CPUType == 4) {
1237 >                // Put 4 byte 68040 IDLE frame.
1238 >                if (incr < 0) {
1239 >                        ad -= 4;
1240 >                        put_long (ad, 0x41000000);
1241 >                } else {
1242 >                        put_long (ad, 0x41000000);
1243 >                        ad += 4;
1244 >                }
1245 >        } else {
1246 >                // Put 28 byte 68881 IDLE frame.
1247 >          if (incr < 0) {
1248 >                  D(bug("fsave_opp pre-decrement\r\n"));
1249 >                        ad -= 4;
1250 >                        // What's this? Some BIU flags, or (incorrectly placed) command/condition?
1251 >                        put_long (ad, 0x70000000);
1252 >                        for (i = 0; i < 5; i++) {
1253 >                    ad -= 4;
1254 >                    put_long (ad, 0x00000000);
1255 >                        }
1256 >                        ad -= 4;
1257 >                        put_long (ad, 0x1f180000); // IDLE, vers 1f
1258 >          } else {
1259 >                        put_long (ad, 0x1f180000); // IDLE, vers 1f
1260 >                        ad += 4;
1261 >                        for (i = 0; i < 5; i++) {
1262 >                    put_long (ad, 0x00000000);
1263 >                    ad += 4;
1264 >                        }
1265 >                        // What's this? Some BIU flags, or (incorrectly placed) command/condition?
1266 >                        put_long (ad, 0x70000000);
1267 >                        ad += 4;
1268 >          }
1269          }
1270 <        ad -= 4;
1271 <        put_long (ad, 0x1f180000);
1272 <    } else {
1273 <        put_long (ad, 0x1f180000);
1274 <        ad += 4;
1275 <        for (i = 0; i < 5; i++) {
1276 <            put_long (ad, 0x00000000);
739 <            ad += 4;
1270 >  if ((opcode & 0x38) == 0x18) {
1271 >                m68k_areg (regs, opcode & 7) = ad; // Never executed on a 68881
1272 >          D(bug("PROBLEM: fsave_opp post-increment\r\n"));
1273 >        }
1274 >  if ((opcode & 0x38) == 0x20) {
1275 >                m68k_areg (regs, opcode & 7) = ad;
1276 >          D(bug("fsave_opp pre-decrement %X -> A%d\r\n",ad,opcode & 7));
1277          }
741        put_long (ad, 0x70000000);
742        ad += 4;
743    }
744    if ((opcode & 0x38) == 0x18)
745        m68k_areg (regs, opcode & 7) = ad;
746    if ((opcode & 0x38) == 0x20)
747        m68k_areg (regs, opcode & 7) = ad;
1278   }
1279  
1280 + // FRESTORE has no pre-decrement
1281   void frestore_opp(uae_u32 opcode)
1282   {
1283 <    uae_u32 ad;
1284 <    uae_u32 d;
1285 <    int incr = (opcode & 0x38) == 0x20 ? -1 : 1;
1286 <
1287 < #if DEBUG_FPP
1288 <    printf("frestore_opp at %08lx\n", m68k_getpc ());
1289 <    fflush(stdout);
1290 < #endif
1291 <    if (get_fp_ad(opcode, &ad) == 0) {
1292 <        m68k_setpc (m68k_getpc () - 2);
1293 <        op_illg (opcode);
1294 <        return;
1295 <    }
1296 <    if (incr < 0) {
1297 <        ad -= 4;
1298 <        d = get_long (ad);
1299 <        if ((d & 0xff000000) != 0) {
1300 <            if ((d & 0x00ff0000) == 0x00180000)
1301 <                ad -= 6 * 4;
1302 <            else if ((d & 0x00ff0000) == 0x00380000)
1303 <                ad -= 14 * 4;
1304 <            else if ((d & 0x00ff0000) == 0x00b40000)
1305 <                ad -= 45 * 4;
1283 >  uae_u32 ad;
1284 >  uae_u32 d;
1285 >  int incr = (opcode & 0x38) == 0x20 ? -1 : 1;
1286 >
1287 >  D(bug("frestore_opp at %08lx\r\n", m68k_getpc ()));
1288 >
1289 >  if (get_fp_ad(opcode, &ad) == 0) {
1290 >                m68k_setpc (m68k_getpc () - 2);
1291 >                op_illg (opcode);
1292 >                return;
1293 >  }
1294 >
1295 >        if (CPUType == 4) {
1296 >                // 68040
1297 >                if (incr < 0) {
1298 >                  D(bug("PROBLEM: frestore_opp incr < 0\r\n"));
1299 >                        // this may be wrong, but it's never called.
1300 >                        ad -= 4;
1301 >                        d = get_long (ad);
1302 >                        if ((d & 0xff000000) != 0) { // Not a NULL frame?
1303 >                                if ((d & 0x00ff0000) == 0) { // IDLE
1304 >                                  D(bug("frestore_opp found IDLE frame at %X\r\n",ad-4));
1305 >                                } else if ((d & 0x00ff0000) == 0x00300000) { // UNIMP
1306 >                                  D(bug("PROBLEM: frestore_opp found UNIMP frame at %X\r\n",ad-4));
1307 >                                        ad -= 44;
1308 >                                } else if ((d & 0x00ff0000) == 0x00600000) { // BUSY
1309 >                                  D(bug("PROBLEM: frestore_opp found BUSY frame at %X\r\n",ad-4));
1310 >                                        ad -= 92;
1311 >                                }
1312 >                        }
1313 >                } else {
1314 >                        d = get_long (ad);
1315 >                  D(bug("frestore_opp frame at %X = %X\r\n",ad,d));
1316 >                        ad += 4;
1317 >                        if ((d & 0xff000000) != 0) { // Not a NULL frame?
1318 >                                if ((d & 0x00ff0000) == 0) { // IDLE
1319 >                                  D(bug("frestore_opp found IDLE frame at %X\r\n",ad-4));
1320 >                                } else if ((d & 0x00ff0000) == 0x00300000) { // UNIMP
1321 >                                  D(bug("PROBLEM: frestore_opp found UNIMP frame at %X\r\n",ad-4));
1322 >                                        ad += 44;
1323 >                                } else if ((d & 0x00ff0000) == 0x00600000) { // BUSY
1324 >                                  D(bug("PROBLEM: frestore_opp found BUSY frame at %X\r\n",ad-4));
1325 >                                        ad += 92;
1326 >                                }
1327 >                        }
1328 >                }
1329 >        } else {
1330 >                // 68881
1331 >          if (incr < 0) {
1332 >                  D(bug("PROBLEM: frestore_opp incr < 0\r\n"));
1333 >                        // this may be wrong, but it's never called.
1334 >                        ad -= 4;
1335 >                        d = get_long (ad);
1336 >                        if ((d & 0xff000000) != 0) {
1337 >                    if ((d & 0x00ff0000) == 0x00180000)
1338 >                                        ad -= 6 * 4;
1339 >                    else if ((d & 0x00ff0000) == 0x00380000)
1340 >                                        ad -= 14 * 4;
1341 >                    else if ((d & 0x00ff0000) == 0x00b40000)
1342 >                                        ad -= 45 * 4;
1343 >                        }
1344 >          } else {
1345 >                        d = get_long (ad);
1346 >                  D(bug("frestore_opp frame at %X = %X\r\n",ad,d));
1347 >                        ad += 4;
1348 >                        if ((d & 0xff000000) != 0) { // Not a NULL frame?
1349 >                    if ((d & 0x00ff0000) == 0x00180000) { // IDLE
1350 >                                  D(bug("frestore_opp found IDLE frame at %X\r\n",ad-4));
1351 >                                        ad += 6 * 4;
1352 >                    } else if ((d & 0x00ff0000) == 0x00380000) {// UNIMP? shouldn't it be 3C?
1353 >                                        ad += 14 * 4;
1354 >                                  D(bug("PROBLEM: frestore_opp found UNIMP? frame at %X\r\n",ad-4));
1355 >                    } else if ((d & 0x00ff0000) == 0x00b40000) {// BUSY
1356 >                                  D(bug("PROBLEM: frestore_opp found BUSY frame at %X\r\n",ad-4));
1357 >                                        ad += 45 * 4;
1358 >                                }
1359 >                        }
1360 >                }
1361 >  }
1362 >  if ((opcode & 0x38) == 0x18) {
1363 >                m68k_areg (regs, opcode & 7) = ad;
1364 >          D(bug("frestore_opp post-increment %X -> A%d\r\n",ad,opcode & 7));
1365          }
1366 <    } else {
1367 <        d = get_long (ad);
1368 <        ad += 4;
779 <        if ((d & 0xff000000) != 0) {
780 <            if ((d & 0x00ff0000) == 0x00180000)
781 <                ad += 6 * 4;
782 <            else if ((d & 0x00ff0000) == 0x00380000)
783 <                ad += 14 * 4;
784 <            else if ((d & 0x00ff0000) == 0x00b40000)
785 <                ad += 45 * 4;
1366 >  if ((opcode & 0x38) == 0x20) {
1367 >                m68k_areg (regs, opcode & 7) = ad; // Never executed on a 68881
1368 >          D(bug("PROBLEM: frestore_opp pre-decrement\r\n"));
1369          }
787    }
788    if ((opcode & 0x38) == 0x18)
789        m68k_areg (regs, opcode & 7) = ad;
790    if ((opcode & 0x38) == 0x20)
791        m68k_areg (regs, opcode & 7) = ad;
1370   }
1371  
1372   void fpp_opp(uae_u32 opcode, uae_u16 extra)
1373   {
1374 <    int reg;
1375 <    double src;
1374 >  int reg;
1375 >  double src;
1376  
1377 < #if DEBUG_FPP
1378 <    printf("FPP %04lx %04x at %08lx\n", opcode & 0xffff, extra & 0xffff,
1379 <           m68k_getpc () - 4);
1380 <    fflush(stdout);
1381 < #endif
1382 <    switch ((extra >> 13) & 0x7) {
1377 >  D(bug("FPP %04lx %04x at %08lx\r\n", opcode & 0xffff, extra & 0xffff,
1378 >         m68k_getpc () - 4));
1379 >
1380 >        dump_fp_regs( "START");
1381 >
1382 >  switch ((extra >> 13) & 0x7) {
1383      case 3:
1384 <        if (put_fp_value (regs.fp[(extra >> 7) & 7], opcode, extra) == 0) {
1385 <            m68k_setpc (m68k_getpc () - 4);
1386 <            op_illg (opcode);
1387 <        }
1388 <        return;
1384 >                        D(bug("FMOVE -> <ea>\r\n"));
1385 >                        if (put_fp_value (regs.fp[(extra >> 7) & 7], opcode, extra) == 0) {
1386 >                          m68k_setpc (m68k_getpc () - 4);
1387 >                                op_illg (opcode);
1388 >                        }
1389 >                        dump_fp_regs( "END  ");
1390 >                        return;
1391      case 4:
1392      case 5:
1393 <        if ((opcode & 0x38) == 0) {
1394 <            if (extra & 0x2000) {
1395 <                if (extra & 0x1000)
1396 <                    m68k_dreg (regs, opcode & 7) = regs.fpcr;
1397 <                if (extra & 0x0800)
1398 <                    m68k_dreg (regs, opcode & 7) = regs.fpsr;
1399 <                if (extra & 0x0400)
1400 <                    m68k_dreg (regs, opcode & 7) = regs.fpiar;
1401 <            } else {
1402 <                if (extra & 0x1000)
1403 <                    regs.fpcr = m68k_dreg (regs, opcode & 7);
1404 <                if (extra & 0x0800)
1405 <                    regs.fpsr = m68k_dreg (regs, opcode & 7);
1406 <                if (extra & 0x0400)
1407 <                    regs.fpiar = m68k_dreg (regs, opcode & 7);
1408 <            }
1409 <        } else if ((opcode & 0x38) == 1) {
1410 <            if (extra & 0x2000) {
1411 <                if (extra & 0x1000)
1412 <                    m68k_areg (regs, opcode & 7) = regs.fpcr;
1413 <                if (extra & 0x0800)
1414 <                    m68k_areg (regs, opcode & 7) = regs.fpsr;
1415 <                if (extra & 0x0400)
1416 <                    m68k_areg (regs, opcode & 7) = regs.fpiar;
1417 <            } else {
1418 <                if (extra & 0x1000)
1419 <                    regs.fpcr = m68k_areg (regs, opcode & 7);
1420 <                if (extra & 0x0800)
1421 <                    regs.fpsr = m68k_areg (regs, opcode & 7);
1422 <                if (extra & 0x0400)
1423 <                    regs.fpiar = m68k_areg (regs, opcode & 7);
1424 <            }
1425 <        } else if ((opcode & 0x3f) == 0x3c) {
1426 <            if ((extra & 0x2000) == 0) {
1427 <                if (extra & 0x1000)
1428 <                    regs.fpcr = next_ilong();
1429 <                if (extra & 0x0800)
1430 <                    regs.fpsr = next_ilong();
1431 <                if (extra & 0x0400)
1432 <                    regs.fpiar = next_ilong();
1433 <            }
1434 <        } else if (extra & 0x2000) {
1435 <            /* FMOVEM FPP->memory */
1436 <            uae_u32 ad;
1437 <            int incr = 0;
1438 <
1439 <            if (get_fp_ad(opcode, &ad) == 0) {
1440 <                m68k_setpc (m68k_getpc () - 4);
1441 <                op_illg (opcode);
1442 <                return;
1443 <            }
1444 <            if ((opcode & 0x38) == 0x20) {
1445 <                if (extra & 0x1000)
1446 <                    incr += 4;
1447 <                if (extra & 0x0800)
1448 <                    incr += 4;
1449 <                if (extra & 0x0400)
1450 <                    incr += 4;
1451 <            }
1452 <            ad -= incr;
1453 <            if (extra & 0x1000) {
1454 <                put_long (ad, regs.fpcr);
1455 <                ad += 4;
1456 <            }
1457 <            if (extra & 0x0800) {
1458 <                put_long (ad, regs.fpsr);
1459 <                ad += 4;
1460 <            }
1461 <            if (extra & 0x0400) {
1462 <                put_long (ad, regs.fpiar);
1463 <                ad += 4;
1464 <            }
1465 <            ad -= incr;
1466 <            if ((opcode & 0x38) == 0x18)
1467 <                m68k_areg (regs, opcode & 7) = ad;
1468 <            if ((opcode & 0x38) == 0x20)
1469 <                m68k_areg (regs, opcode & 7) = ad;
1470 <        } else {
1471 <            /* FMOVEM memory->FPP */
1472 <            uae_u32 ad;
1473 <
1474 <            if (get_fp_ad(opcode, &ad) == 0) {
1475 <                m68k_setpc (m68k_getpc () - 4);
1476 <                op_illg (opcode);
1477 <                return;
1478 <            }
1479 <            ad = (opcode & 0x38) == 0x20 ? ad - 12 : ad;
1480 <            if (extra & 0x1000) {
1481 <                regs.fpcr = get_long (ad);
1482 <                ad += 4;
1483 <            }
1484 <            if (extra & 0x0800) {
1485 <                regs.fpsr = get_long (ad);
1486 <                ad += 4;
1487 <            }
1488 <            if (extra & 0x0400) {
1489 <                regs.fpiar = get_long (ad);
1490 <                ad += 4;
1491 <            }
1492 <            if ((opcode & 0x38) == 0x18)
1493 <                m68k_areg (regs, opcode & 7) = ad;
1494 <            if ((opcode & 0x38) == 0x20)
1495 <                m68k_areg (regs, opcode & 7) = ad - 12;
1496 <        }
1497 <        return;
1393 >                        if ((opcode & 0x38) == 0) {
1394 >                                if (extra & 0x2000) { // dr bit
1395 >                                        if (extra & 0x1000) {
1396 >                                                // according to the manual, the msb bits are always zero.
1397 >                                                m68k_dreg (regs, opcode & 7) = regs.fpcr & 0xFFFF;
1398 >                                                D(bug("FMOVEM regs.fpcr (%X) -> D%d\r\n", regs.fpcr, opcode & 7));
1399 >                                        }
1400 >                                        if (extra & 0x0800) {
1401 >                                                m68k_dreg (regs, opcode & 7) = regs.fpsr;
1402 >                                                D(bug("FMOVEM regs.fpsr (%X) -> D%d\r\n", regs.fpsr, opcode & 7));
1403 >                                        }
1404 >                                        if (extra & 0x0400) {
1405 >                                                m68k_dreg (regs, opcode & 7) = regs.fpiar;
1406 >                                                D(bug("FMOVEM regs.fpiar (%X) -> D%d\r\n", regs.fpiar, opcode & 7));
1407 >                                        }
1408 >                                } else {
1409 >                                        if (extra & 0x1000) {
1410 >                                                regs.fpcr = m68k_dreg (regs, opcode & 7);
1411 >                                                D(bug("FMOVEM D%d (%X) -> regs.fpcr\r\n", opcode & 7, regs.fpcr));
1412 >                                        }
1413 >                                        if (extra & 0x0800) {
1414 >                                                regs.fpsr = m68k_dreg (regs, opcode & 7);
1415 >                                                D(bug("FMOVEM D%d (%X) -> regs.fpsr\r\n", opcode & 7, regs.fpsr));
1416 >                                        }
1417 >                                        if (extra & 0x0400) {
1418 >                                                regs.fpiar = m68k_dreg (regs, opcode & 7);
1419 >                                                D(bug("FMOVEM D%d (%X) -> regs.fpiar\r\n", opcode & 7, regs.fpiar));
1420 >                                        }
1421 >                                }
1422 >                        // } else if ((opcode & 0x38) == 1) {
1423 >                        } else if ((opcode & 0x38) == 8) {
1424 >                                if (extra & 0x2000) { // dr bit
1425 >                                        if (extra & 0x1000) {
1426 >                                                // according to the manual, the msb bits are always zero.
1427 >                                                m68k_areg (regs, opcode & 7) = regs.fpcr & 0xFFFF;
1428 >                                                D(bug("FMOVEM regs.fpcr (%X) -> A%d\r\n", regs.fpcr, opcode & 7));
1429 >                                        }
1430 >                                        if (extra & 0x0800) {
1431 >                                                m68k_areg (regs, opcode & 7) = regs.fpsr;
1432 >                                                D(bug("FMOVEM regs.fpsr (%X) -> A%d\r\n", regs.fpsr, opcode & 7));
1433 >                                        }
1434 >                                        if (extra & 0x0400) {
1435 >                                                m68k_areg (regs, opcode & 7) = regs.fpiar;
1436 >                                                D(bug("FMOVEM regs.fpiar (%X) -> A%d\r\n", regs.fpiar, opcode & 7));
1437 >                                        }
1438 >                                } else {
1439 >                                        if (extra & 0x1000) {
1440 >                                                regs.fpcr = m68k_areg (regs, opcode & 7);
1441 >                                                D(bug("FMOVEM A%d (%X) -> regs.fpcr\r\n", opcode & 7, regs.fpcr));
1442 >                                        }
1443 >                                        if (extra & 0x0800) {
1444 >                                                regs.fpsr = m68k_areg (regs, opcode & 7);
1445 >                                                D(bug("FMOVEM A%d (%X) -> regs.fpsr\r\n", opcode & 7, regs.fpsr));
1446 >                                        }
1447 >                                        if (extra & 0x0400) {
1448 >                                                regs.fpiar = m68k_areg (regs, opcode & 7);
1449 >                                                D(bug("FMOVEM A%d (%X) -> regs.fpiar\r\n", opcode & 7, regs.fpiar));
1450 >                                        }
1451 >                                }
1452 >                        } else if ((opcode & 0x3f) == 0x3c) {
1453 >                          if ((extra & 0x2000) == 0) {
1454 >                                        if (extra & 0x1000) {
1455 >                                                regs.fpcr = next_ilong();
1456 >                                                D(bug("FMOVEM #<%X> -> regs.fpcr\r\n", regs.fpcr));
1457 >                                        }
1458 >                                        if (extra & 0x0800) {
1459 >                                                regs.fpsr = next_ilong();
1460 >                                                D(bug("FMOVEM #<%X> -> regs.fpsr\r\n", regs.fpsr));
1461 >                                        }
1462 >                                        if (extra & 0x0400) {
1463 >                                                regs.fpiar = next_ilong();
1464 >                                                D(bug("FMOVEM #<%X> -> regs.fpiar\r\n", regs.fpiar));
1465 >                                        }
1466 >                                }
1467 >                        } else if (extra & 0x2000) {
1468 >                                /* FMOVEM FPP->memory */
1469 >
1470 >                                uae_u32 ad;
1471 >                                int incr = 0;
1472 >
1473 >                                if (get_fp_ad(opcode, &ad) == 0) {
1474 >                                        m68k_setpc (m68k_getpc () - 4);
1475 >                                        op_illg (opcode);
1476 >                                        dump_fp_regs( "END  ");
1477 >                                        return;
1478 >                    }
1479 >                                if ((opcode & 0x38) == 0x20) {
1480 >                                        if (extra & 0x1000)
1481 >                                                incr += 4;
1482 >                                        if (extra & 0x0800)
1483 >                                                incr += 4;
1484 >                                        if (extra & 0x0400)
1485 >                                                incr += 4;
1486 >                                }
1487 >                                ad -= incr;
1488 >                                if (extra & 0x1000) {
1489 >                                        // according to the manual, the msb bits are always zero.
1490 >                                        put_long (ad, regs.fpcr & 0xFFFF);
1491 >                                        D(bug("FMOVEM regs.fpcr (%X) -> mem %X\r\n", regs.fpcr, ad ));
1492 >                                        ad += 4;
1493 >                                }
1494 >                                if (extra & 0x0800) {
1495 >                                        put_long (ad, regs.fpsr);
1496 >                                        D(bug("FMOVEM regs.fpsr (%X) -> mem %X\r\n", regs.fpsr, ad ));
1497 >                                        ad += 4;
1498 >                                }
1499 >                                if (extra & 0x0400) {
1500 >                                        put_long (ad, regs.fpiar);
1501 >                                        D(bug("FMOVEM regs.fpiar (%X) -> mem %X\r\n", regs.fpiar, ad ));
1502 >                                        ad += 4;
1503 >                                }
1504 >                                ad -= incr;
1505 >                                if ((opcode & 0x38) == 0x18) // post-increment?
1506 >                                        m68k_areg (regs, opcode & 7) = ad;
1507 >                                if ((opcode & 0x38) == 0x20) // pre-decrement?
1508 >                                        m68k_areg (regs, opcode & 7) = ad;
1509 >                        } else {
1510 >                                /* FMOVEM memory->FPP */
1511 >
1512 >                                uae_u32 ad;
1513 >
1514 >                                if (get_fp_ad(opcode, &ad) == 0) {
1515 >                                        m68k_setpc (m68k_getpc () - 4);
1516 >                                        op_illg (opcode);
1517 >                                        dump_fp_regs( "END  ");
1518 >                                        return;
1519 >                                }
1520 >                                
1521 >                                // ad = (opcode & 0x38) == 0x20 ? ad - 12 : ad;
1522 >                                int incr = 0;
1523 >                                if((opcode & 0x38) == 0x20) {
1524 >                                        if (extra & 0x1000)
1525 >                                                incr += 4;
1526 >                                        if (extra & 0x0800)
1527 >                                                incr += 4;
1528 >                                        if (extra & 0x0400)
1529 >                                                incr += 4;
1530 >                                        ad = ad - incr;
1531 >                                }
1532 >
1533 >                                if (extra & 0x1000) {
1534 >                                        regs.fpcr = get_long (ad);
1535 >                                        D(bug("FMOVEM mem %X (%X) -> regs.fpcr\r\n", ad, regs.fpcr ));
1536 >                                        ad += 4;
1537 >                                }
1538 >                                if (extra & 0x0800) {
1539 >                                        regs.fpsr = get_long (ad);
1540 >                                        D(bug("FMOVEM mem %X (%X) -> regs.fpsr\r\n", ad, regs.fpsr ));
1541 >                                        ad += 4;
1542 >                                }
1543 >                                if (extra & 0x0400) {
1544 >                                        regs.fpiar = get_long (ad);
1545 >                                        D(bug("FMOVEM mem %X (%X) -> regs.fpiar\r\n", ad, regs.fpiar ));
1546 >                                        ad += 4;
1547 >                                }
1548 >                                if ((opcode & 0x38) == 0x18) // post-increment?
1549 >                                        m68k_areg (regs, opcode & 7) = ad;
1550 >                                if ((opcode & 0x38) == 0x20) // pre-decrement?
1551 >                                        // m68k_areg (regs, opcode & 7) = ad - 12;
1552 >                                        m68k_areg (regs, opcode & 7) = ad - incr;
1553 >                        }
1554 >                        dump_fp_regs( "END  ");
1555 >                        return;
1556      case 6:
1557      case 7:
1558 <        {
1558 >                        {
1559              uae_u32 ad, list = 0;
1560              int incr = 0;
1561              if (extra & 0x2000) {
1562 <                /* FMOVEM FPP->memory */
1563 <                if (get_fp_ad(opcode, &ad) == 0) {
1564 <                    m68k_setpc (m68k_getpc () - 4);
1565 <                    op_illg (opcode);
1566 <                    return;
1567 <                }
1568 <                switch ((extra >> 11) & 3) {
1569 <                case 0: /* static pred */
1570 <                    list = extra & 0xff;
1571 <                    incr = -1;
1572 <                    break;
1573 <                case 1: /* dynamic pred */
1574 <                    list = m68k_dreg (regs, (extra >> 4) & 3) & 0xff;
1575 <                    incr = -1;
1576 <                    break;
1577 <                case 2: /* static postinc */
1578 <                    list = extra & 0xff;
1579 <                    incr = 1;
1580 <                    break;
1581 <                case 3: /* dynamic postinc */
1582 <                    list = m68k_dreg (regs, (extra >> 4) & 3) & 0xff;
1583 <                    incr = 1;
1584 <                    break;
1585 <                }
1586 <                while (list) {
1587 <                    uae_u32 wrd1, wrd2, wrd3;
1588 <                    if (incr < 0) {
1589 <                        from_exten(regs.fp[fpp_movem_index2[list]],
1590 <                                   &wrd1, &wrd2, &wrd3);
1591 <                        ad -= 4;
1592 <                        put_long (ad, wrd3);
1593 <                        ad -= 4;
1594 <                        put_long (ad, wrd2);
1595 <                        ad -= 4;
1596 <                        put_long (ad, wrd1);
1597 <                    } else {
1598 <                        from_exten(regs.fp[fpp_movem_index1[list]],
1599 <                                   &wrd1, &wrd2, &wrd3);
1600 <                        put_long (ad, wrd1);
1601 <                        ad += 4;
1602 <                        put_long (ad, wrd2);
1603 <                        ad += 4;
1604 <                        put_long (ad, wrd3);
1605 <                        ad += 4;
1606 <                    }
1607 <                    list = fpp_movem_next[list];
1608 <                }
1609 <                if ((opcode & 0x38) == 0x18)
1610 <                    m68k_areg (regs, opcode & 7) = ad;
1611 <                if ((opcode & 0x38) == 0x20)
1612 <                    m68k_areg (regs, opcode & 7) = ad;
1613 <            } else {
1614 <                /* FMOVEM memory->FPP */
1615 <                if (get_fp_ad(opcode, &ad) == 0) {
1616 <                    m68k_setpc (m68k_getpc () - 4);
1617 <                    op_illg (opcode);
1618 <                    return;
1619 <                }
1620 <                switch ((extra >> 11) & 3) {
1621 <                case 0: /* static pred */
1622 <                    list = extra & 0xff;
1623 <                    incr = -1;
1624 <                    break;
1625 <                case 1: /* dynamic pred */
1626 <                    list = m68k_dreg (regs, (extra >> 4) & 3) & 0xff;
1627 <                    incr = -1;
1628 <                    break;
1629 <                case 2: /* static postinc */
1630 <                    list = extra & 0xff;
1631 <                    incr = 1;
1632 <                    break;
1633 <                case 3: /* dynamic postinc */
1634 <                    list = m68k_dreg (regs, (extra >> 4) & 3) & 0xff;
1635 <                    incr = 1;
1636 <                    break;
1637 <                }
1638 <                while (list) {
1639 <                    uae_u32 wrd1, wrd2, wrd3;
1640 <                    if (incr < 0) {
1641 <                        ad -= 4;
1642 <                        wrd3 = get_long (ad);
1643 <                        ad -= 4;
1644 <                        wrd2 = get_long (ad);
1645 <                        ad -= 4;
1646 <                        wrd1 = get_long (ad);
1647 <                        regs.fp[fpp_movem_index2[list]] = to_exten (wrd1, wrd2, wrd3);
1648 <                    } else {
1649 <                        wrd1 = get_long (ad);
1650 <                        ad += 4;
1651 <                        wrd2 = get_long (ad);
1652 <                        ad += 4;
1653 <                        wrd3 = get_long (ad);
1654 <                        ad += 4;
1655 <                        regs.fp[fpp_movem_index1[list]] = to_exten (wrd1, wrd2, wrd3);
1656 <                    }
1657 <                    list = fpp_movem_next[list];
1658 <                }
1659 <                if ((opcode & 0x38) == 0x18)
1660 <                    m68k_areg (regs, opcode & 7) = ad;
1661 <                if ((opcode & 0x38) == 0x20)
1662 <                    m68k_areg (regs, opcode & 7) = ad;
1562 >                                /* FMOVEM FPP->memory */
1563 >
1564 >                                D(bug("FMOVEM FPP->memory\r\n"));
1565 >
1566 >                                if (get_fp_ad(opcode, &ad) == 0) {
1567 >                                        m68k_setpc (m68k_getpc () - 4);
1568 >                                        op_illg (opcode);
1569 >                                        dump_fp_regs( "END  ");
1570 >                                        return;
1571 >                                }
1572 >                                switch ((extra >> 11) & 3) {
1573 >                                        case 0: /* static pred */
1574 >                                                list = extra & 0xff;
1575 >                                                incr = -1;
1576 >                                                break;
1577 >                                        case 1: /* dynamic pred */
1578 >                                                list = m68k_dreg (regs, (extra >> 4) & 3) & 0xff;
1579 >                                                incr = -1;
1580 >                                                break;
1581 >                                        case 2: /* static postinc */
1582 >                                                list = extra & 0xff;
1583 >                                                incr = 1;
1584 >                                                break;
1585 >                                        case 3: /* dynamic postinc */
1586 >                                                list = m68k_dreg (regs, (extra >> 4) & 3) & 0xff;
1587 >                                                incr = 1;
1588 >                                                break;
1589 >                                }
1590 >
1591 >                                if (incr < 0) {
1592 >                                        for(reg=7; reg>=0; reg--) {
1593 >                                                uae_u32 wrd1, wrd2, wrd3;
1594 >                                                if( list & 0x80 ) {
1595 >                                                        from_exten(regs.fp[reg],&wrd1, &wrd2, &wrd3);
1596 >                                                        ad -= 4;
1597 >                                                        put_long (ad, wrd3);
1598 >                                                        ad -= 4;
1599 >                                                        put_long (ad, wrd2);
1600 >                                                        ad -= 4;
1601 >                                                        put_long (ad, wrd1);
1602 >                                                }
1603 >                                                list <<= 1;
1604 >                                        }
1605 >                                } else {
1606 >                                        for(reg=0; reg<8; reg++) {
1607 >                                                uae_u32 wrd1, wrd2, wrd3;
1608 >                                                if( list & 0x80 ) {
1609 >                                                        from_exten(regs.fp[reg],&wrd1, &wrd2, &wrd3);
1610 >                                                        put_long (ad, wrd3);
1611 >                                                        ad += 4;
1612 >                                                        put_long (ad, wrd2);
1613 >                                                        ad += 4;
1614 >                                                        put_long (ad, wrd1);
1615 >                                                        ad += 4;
1616 >                                                }
1617 >                                                list <<= 1;
1618 >                                        }
1619 >                                }
1620 >
1621 >                                /*
1622 >                                while (list) {
1623 >                                        uae_u32 wrd1, wrd2, wrd3;
1624 >                                        if (incr < 0) {
1625 >                                                from_exten(regs.fp[fpp_movem_index2[list]],
1626 >                                                 &wrd1, &wrd2, &wrd3);
1627 >                                                ad -= 4;
1628 >                                                put_long (ad, wrd3);
1629 >                                                ad -= 4;
1630 >                                                put_long (ad, wrd2);
1631 >                                                ad -= 4;
1632 >                                                put_long (ad, wrd1);
1633 >                                        } else {
1634 >                                                from_exten(regs.fp[fpp_movem_index1[list]],
1635 >                                                 &wrd1, &wrd2, &wrd3);
1636 >                                                put_long (ad, wrd1);
1637 >                                                ad += 4;
1638 >                                                put_long (ad, wrd2);
1639 >                                                ad += 4;
1640 >                                                put_long (ad, wrd3);
1641 >                                                ad += 4;
1642 >                                        }
1643 >                                        list = fpp_movem_next[list];
1644 >                                }
1645 >                                */
1646 >                                if ((opcode & 0x38) == 0x18) // post-increment?
1647 >                                        m68k_areg (regs, opcode & 7) = ad;
1648 >                                if ((opcode & 0x38) == 0x20) // pre-decrement?
1649 >                                        m68k_areg (regs, opcode & 7) = ad;
1650 >                  } else {
1651 >                                /* FMOVEM memory->FPP */
1652 >
1653 >                                D(bug("FMOVEM memory->FPP\r\n"));
1654 >
1655 >                                if (get_fp_ad(opcode, &ad) == 0) {
1656 >                                        m68k_setpc (m68k_getpc () - 4);
1657 >                                        op_illg (opcode);
1658 >                                        dump_fp_regs( "END  ");
1659 >                                        return;
1660 >                                }
1661 >                                switch ((extra >> 11) & 3) {
1662 >                                        case 0: /* static pred */
1663 >                                                D(bug("memory->FMOVEM FPP not legal mode.\r\n"));
1664 >                                                list = extra & 0xff;
1665 >                                                incr = -1;
1666 >                                                break;
1667 >                                        case 1: /* dynamic pred */
1668 >                                                D(bug("memory->FMOVEM FPP not legal mode.\r\n"));
1669 >                                                list = m68k_dreg (regs, (extra >> 4) & 3) & 0xff;
1670 >                                                incr = -1;
1671 >                                    break;
1672 >                                        case 2: /* static postinc */
1673 >                                    list = extra & 0xff;
1674 >                                                incr = 1;
1675 >                                                break;
1676 >                                        case 3: /* dynamic postinc */
1677 >                                                list = m68k_dreg (regs, (extra >> 4) & 3) & 0xff;
1678 >                                                incr = 1;
1679 >                                                break;
1680 >                                }
1681 >
1682 >                                /**/
1683 >                                if (incr < 0) {
1684 >                                        // not reached
1685 >                                        for(reg=7; reg>=0; reg--) {
1686 >                                                uae_u32 wrd1, wrd2, wrd3;
1687 >                                                if( list & 0x80 ) {
1688 >                                                        wrd1 = get_long (ad);
1689 >                                                        ad -= 4;
1690 >                                                        wrd2 = get_long (ad);
1691 >                                                        ad -= 4;
1692 >                                                        wrd3 = get_long (ad);
1693 >                                                        ad -= 4;
1694 >                                                        regs.fp[reg] = to_exten (wrd1, wrd2, wrd3);
1695 >                                                }
1696 >                                                list <<= 1;
1697 >                                        }
1698 >                                } else {
1699 >                                        for(reg=0; reg<8; reg++) {
1700 >                                                uae_u32 wrd1, wrd2, wrd3;
1701 >                                                if( list & 0x80 ) {
1702 >                                                        wrd1 = get_long (ad);
1703 >                                                        ad += 4;
1704 >                                                        wrd2 = get_long (ad);
1705 >                                                        ad += 4;
1706 >                                                        wrd3 = get_long (ad);
1707 >                                                        ad += 4;
1708 >                                                        regs.fp[reg] = to_exten (wrd1, wrd2, wrd3);
1709 >                                                }
1710 >                                                list <<= 1;
1711 >                                        }
1712 >                                }
1713 >                                /**/
1714 >
1715 >                                /*
1716 >                                while (list) {
1717 >                                        uae_u32 wrd1, wrd2, wrd3;
1718 >                                        if (incr < 0) {
1719 >                                                ad -= 4;
1720 >                                                wrd3 = get_long (ad);
1721 >                                                ad -= 4;
1722 >                                                wrd2 = get_long (ad);
1723 >                                                ad -= 4;
1724 >                                                wrd1 = get_long (ad);
1725 >                                                regs.fp[fpp_movem_index2[list]] = to_exten (wrd1, wrd2, wrd3);
1726 >                            } else {
1727 >                                                wrd1 = get_long (ad);
1728 >                                                ad += 4;
1729 >                                                wrd2 = get_long (ad);
1730 >                                                ad += 4;
1731 >                                                wrd3 = get_long (ad);
1732 >                                                ad += 4;
1733 >                                                regs.fp[fpp_movem_index1[list]] = to_exten (wrd1, wrd2, wrd3);
1734 >                                        }
1735 >                                        list = fpp_movem_next[list];
1736 >                                }
1737 >                                */
1738 >                                if ((opcode & 0x38) == 0x18) // post-increment?
1739 >                            m68k_areg (regs, opcode & 7) = ad;
1740 >                                if ((opcode & 0x38) == 0x20) // pre-decrement?
1741 >                            m68k_areg (regs, opcode & 7) = ad;
1742              }
1743 <        }
1744 <        return;
1743 >                        }
1744 >                        dump_fp_regs( "END  ");
1745 >                        return;
1746      case 0:
1747      case 2:
1748 <        reg = (extra >> 7) & 7;
1749 <        if ((extra & 0xfc00) == 0x5c00) {
1750 <            switch (extra & 0x7f) {
1751 <            case 0x00:
1752 <                regs.fp[reg] = 4.0 * atan(1.0);
1753 <                break;
1754 <            case 0x0b:
1755 <                regs.fp[reg] = log10 (2.0);
1756 <                break;
1757 <            case 0x0c:
1758 <                regs.fp[reg] = exp (1.0);
1759 <                break;
1760 <            case 0x0d:
1761 <                regs.fp[reg] = log (exp (1.0)) / log (2.0);
1762 <                break;
1763 <            case 0x0e:
1764 <                regs.fp[reg] = log (exp (1.0)) / log (10.0);
1765 <                break;
1766 <            case 0x0f:
1767 <                regs.fp[reg] = 0.0;
1768 <                break;
1769 <            case 0x30:
1770 <                regs.fp[reg] = log (2.0);
1771 <                break;
1772 <            case 0x31:
1773 <                regs.fp[reg] = log (10.0);
1774 <                break;
1775 <            case 0x32:
1776 <                regs.fp[reg] = 1.0e0;
1777 <                break;
1778 <            case 0x33:
1779 <                regs.fp[reg] = 1.0e1;
1780 <                break;
1781 <            case 0x34:
1782 <                regs.fp[reg] = 1.0e2;
1783 <                break;
1784 <            case 0x35:
1785 <                regs.fp[reg] = 1.0e4;
1786 <                break;
1787 <            case 0x36:
1788 <                regs.fp[reg] = 1.0e8;
1789 <                break;
1790 <            case 0x37:
1791 <                regs.fp[reg] = 1.0e16;
1792 <                break;
1793 <            case 0x38:
1794 <                regs.fp[reg] = 1.0e32;
1795 <                break;
1796 <            case 0x39:
1797 <                regs.fp[reg] = 1.0e64;
1798 <                break;
1799 <            case 0x3a:
1800 <                regs.fp[reg] = 1.0e128;
1801 <                break;
1802 <            case 0x3b:
1803 <                regs.fp[reg] = 1.0e256;
1804 <                break;
1748 >                        reg = (extra >> 7) & 7;
1749 >                        if ((extra & 0xfc00) == 0x5c00) {
1750 >                                D(bug("FMOVECR memory->FPP\r\n"));
1751 >                                switch (extra & 0x7f) {
1752 >                                        case 0x00:
1753 >                                                // regs.fp[reg] = 4.0 * atan(1.0);
1754 >                                                regs.fp[reg] = 3.1415926535897932384626433832795;
1755 >                                                D(bug("FP const: Pi\r\n"));
1756 >                                                break;
1757 >                                        case 0x0b:
1758 >                                                // regs.fp[reg] = log10 (2.0);
1759 >                                                regs.fp[reg] = 0.30102999566398119521373889472449;
1760 >                                                D(bug("FP const: Log 10 (2)\r\n"));
1761 >                                                break;
1762 >                                        case 0x0c:
1763 >                                                // regs.fp[reg] = exp (1.0);
1764 >                                                regs.fp[reg] = 2.7182818284590452353602874713527;
1765 >                                                D(bug("FP const: e\r\n"));
1766 >                                                break;
1767 >                                        case 0x0d:
1768 >                                                // regs.fp[reg] = log (exp (1.0)) / log (2.0);
1769 >                                                regs.fp[reg] = 1.4426950408889634073599246810019;
1770 >                                                D(bug("FP const: Log 2 (e)\r\n"));
1771 >                                                break;
1772 >                                        case 0x0e:
1773 >                                                // regs.fp[reg] = log (exp (1.0)) / log (10.0);
1774 >                                                regs.fp[reg] = 0.43429448190325182765112891891661;
1775 >                                                D(bug("FP const: Log 10 (e)\r\n"));
1776 >                                                break;
1777 >                                        case 0x0f:
1778 >                                                regs.fp[reg] = 0.0;
1779 >                                                D(bug("FP const: zero\r\n"));
1780 >                                                break;
1781 >                                        case 0x30:
1782 >                                                // regs.fp[reg] = log (2.0);
1783 >                                                regs.fp[reg] = 0.69314718055994530941723212145818;
1784 >                                                D(bug("FP const: ln(2)\r\n"));
1785 >                                                break;
1786 >                                        case 0x31:
1787 >                                                // regs.fp[reg] = log (10.0);
1788 >                                                regs.fp[reg] = 2.3025850929940456840179914546844;
1789 >                                                D(bug("FP const: ln(10)\r\n"));
1790 >                                                break;
1791 >                                        case 0x32:
1792 >                                                // ??
1793 >                                                regs.fp[reg] = 1.0e0;
1794 >                                                D(bug("FP const: 1.0e0\r\n"));
1795 >                                                break;
1796 >                                        case 0x33:
1797 >                                                regs.fp[reg] = 1.0e1;
1798 >                                                D(bug("FP const: 1.0e1\r\n"));
1799 >                                                break;
1800 >                                        case 0x34:
1801 >                                                regs.fp[reg] = 1.0e2;
1802 >                                                D(bug("FP const: 1.0e2\r\n"));
1803 >                                                break;
1804 >                                        case 0x35:
1805 >                                                regs.fp[reg] = 1.0e4;
1806 >                                                D(bug("FP const: 1.0e4\r\n"));
1807 >                                                break;
1808 >                                        case 0x36:
1809 >                                                regs.fp[reg] = 1.0e8;
1810 >                                                D(bug("FP const: 1.0e8\r\n"));
1811 >                                                break;
1812 >                                        case 0x37:
1813 >                                                regs.fp[reg] = 1.0e16;
1814 >                                                D(bug("FP const: 1.0e16\r\n"));
1815 >                                                break;
1816 >                                        case 0x38:
1817 >                                                regs.fp[reg] = 1.0e32;
1818 >                                                D(bug("FP const: 1.0e32\r\n"));
1819 >                                                break;
1820 >                                        case 0x39:
1821 >                                                regs.fp[reg] = 1.0e64;
1822 >                                                D(bug("FP const: 1.0e64\r\n"));
1823 >                                                break;
1824 >                                        case 0x3a:
1825 >                                                regs.fp[reg] = 1.0e128;
1826 >                                                D(bug("FP const: 1.0e128\r\n"));
1827 >                                                break;
1828 >                                        case 0x3b:
1829 >                                                regs.fp[reg] = 1.0e256;
1830 >                                                D(bug("FP const: 1.0e256\r\n"));
1831 >                                                break;
1832 >                                        
1833 >                                        // Valid for 64 bits only (see fpu.cpp)
1834   #if 0
1835 <            case 0x3c:
1836 <                regs.fp[reg] = 1.0e512;
1837 <                break;
1838 <            case 0x3d:
1839 <                regs.fp[reg] = 1.0e1024;
1840 <                break;
1841 <            case 0x3e:
1842 <                regs.fp[reg] = 1.0e2048;
1843 <                break;
1844 <            case 0x3f:
1845 <                regs.fp[reg] = 1.0e4096;
1846 <                break;
1835 >                                        case 0x3c:
1836 >                                                regs.fp[reg] = 1.0e512;
1837 >                                                D(bug("FP const: 1.0e512\r\n"));
1838 >                                                break;
1839 >                                        case 0x3d:
1840 >                                                regs.fp[reg] = 1.0e1024;
1841 >                                                D(bug("FP const: 1.0e1024\r\n"));
1842 >                                                break;
1843 >                                        case 0x3e:
1844 >                                                regs.fp[reg] = 1.0e2048;
1845 >                                                D(bug("FP const: 1.0e2048\r\n"));
1846 >                                                break;
1847 >                                        case 0x3f:
1848 >                                                regs.fp[reg] = 1.0e4096;
1849 >                                                D(bug("FP const: 1.0e4096\r\n"));
1850 >                                                break;
1851   #endif
1852 <            default:
1853 <                m68k_setpc (m68k_getpc () - 4);
1854 <                op_illg (opcode);
1855 <                break;
1856 <            }
1857 <            return;
1858 <        }
1859 <        if (get_fp_value (opcode, extra, &src) == 0) {
1860 <            m68k_setpc (m68k_getpc () - 4);
1861 <            op_illg (opcode);
1862 <            return;
1863 <        }
1864 <        switch (extra & 0x7f) {
1865 <        case 0x00:              /* FMOVE */
1866 <            regs.fp[reg] = src;
1867 <            break;
1868 <        case 0x01:              /* FINT */
1869 <            regs.fp[reg] = (int) (src + 0.5);
1870 <            regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
1871 <                (regs.fp[reg] < 0 ? 0x8000000 : 0);
1872 <            break;
1873 <        case 0x02:              /* FSINH */
1874 <            regs.fp[reg] = sinh (src);
1875 <            regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
1876 <                (regs.fp[reg] < 0 ? 0x8000000 : 0);
1877 <            break;
1878 <        case 0x03:              /* FINTRZ */
1879 <            regs.fp[reg] = (int) src;
1880 <            regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
1881 <                (regs.fp[reg] < 0 ? 0x8000000 : 0);
1882 <            break;
1883 <        case 0x04:              /* FSQRT */
1884 <            regs.fp[reg] = sqrt (src);
1885 <            regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
1886 <                (regs.fp[reg] < 0 ? 0x8000000 : 0);
1887 <            break;
1888 <        case 0x06:              /* FLOGNP1 */
1889 <            regs.fp[reg] = log (src + 1.0);
1890 <            regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
1891 <                (regs.fp[reg] < 0 ? 0x8000000 : 0);
1892 <            break;
1893 <        case 0x08:              /* FETOXM1 */
1894 <            regs.fp[reg] = exp (src) - 1.0;
1895 <            regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
1896 <                (regs.fp[reg] < 0 ? 0x8000000 : 0);
1897 <            break;
1898 <        case 0x09:              /* FTANH */
1899 <            regs.fp[reg] = tanh (src);
1900 <            regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
1901 <                (regs.fp[reg] < 0 ? 0x8000000 : 0);
1902 <            break;
1903 <        case 0x0a:              /* FATAN */
1904 <            regs.fp[reg] = atan (src);
1905 <            regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
1906 <                (regs.fp[reg] < 0 ? 0x8000000 : 0);
1907 <            break;
1908 <        case 0x0c:              /* FASIN */
1909 <            regs.fp[reg] = asin (src);
1910 <            regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
1911 <                (regs.fp[reg] < 0 ? 0x8000000 : 0);
1912 <            break;
1913 <        case 0x0d:              /* FATANH */
1852 >                                        default:
1853 >                                                m68k_setpc (m68k_getpc () - 4);
1854 >                                                op_illg (opcode);
1855 >                                                break;
1856 >                                }
1857 >                                // these *do* affect the status reg
1858 >                                MAKE_FPSR(regs.fpsr,regs.fp[reg]);
1859 >                                dump_fp_regs( "END  ");
1860 >                                return;
1861 >                        }
1862 >                        if (get_fp_value (opcode, extra, &src) == 0) {
1863 >                                m68k_setpc (m68k_getpc () - 4);
1864 >                                op_illg (opcode);
1865 >                                dump_fp_regs( "END  ");
1866 >                                return;
1867 >                        }
1868 >
1869 >                        switch (extra & 0x7f) {
1870 >                                case 0x00:              /* FMOVE */
1871 >                                        D(bug("FMOVE %.04f\r\n",(float)src));
1872 >                                        regs.fp[reg] = src;
1873 >                                        // <ea> -> reg DOES affect the status reg
1874 >                                        MAKE_FPSR(regs.fpsr,regs.fp[reg]);
1875 >                                        break;
1876 >                                case 0x01:              /* FINT */
1877 >                                        D(bug("FINT %.04f\r\n",(float)src));
1878 >                                        // regs.fp[reg] = (int) (src + 0.5);
1879 >                                        switch(regs.fpcr & 0x30) {
1880 >                                                case ROUND_TO_ZERO:
1881 >                                                        regs.fp[reg] = round_to_zero(src);
1882 >                                                        break;
1883 >                                                case ROUND_TO_NEGATIVE_INFINITY:
1884 >                                                        regs.fp[reg] = floor(src);
1885 >                                                        break;
1886 >                                                case ROUND_TO_NEAREST:
1887 >                                                        regs.fp[reg] = round_to_nearest(src);
1888 >                                                        break;
1889 >                                                case ROUND_TO_POSITIVE_INFINITY:
1890 >                                                        regs.fp[reg] = ceil(src);
1891 >                                                        break;
1892 >                                        }
1893 >                                        MAKE_FPSR(regs.fpsr,regs.fp[reg]);
1894 >                                        break;
1895 >                                case 0x02:              /* FSINH */
1896 >                                        D(bug("FSINH %.04f\r\n",(float)src));
1897 >                                        regs.fp[reg] = sinh (src);
1898 >                                        MAKE_FPSR(regs.fpsr,regs.fp[reg]);
1899 >                                        break;
1900 >                                case 0x03:              /* FINTRZ */
1901 >                                        D(bug("FINTRZ %.04f\r\n",(float)src));
1902 >                                        // regs.fp[reg] = (int) src;
1903 >                                        regs.fp[reg] = round_to_zero(src);
1904 >                                        MAKE_FPSR(regs.fpsr,regs.fp[reg]);
1905 >                                        break;
1906 >                                case 0x04:              /* FSQRT */
1907 >                                        D(bug("FSQRT %.04f\r\n",(float)src));
1908 >                                        regs.fp[reg] = sqrt (src);
1909 >                                        MAKE_FPSR(regs.fpsr,regs.fp[reg]);
1910 >                                        break;
1911 >                                case 0x06:              /* FLOGNP1 */
1912 >                                        D(bug("FLOGNP1 %.04f\r\n",(float)src));
1913 >                                        regs.fp[reg] = log (src + 1.0);
1914 >                                        MAKE_FPSR(regs.fpsr,regs.fp[reg]);
1915 >                                        break;
1916 >                                case 0x08:              /* FETOXM1 */
1917 >                                        D(bug("FETOXM1 %.04f\r\n",(float)src));
1918 >                                        regs.fp[reg] = exp (src) - 1.0;
1919 >                                        MAKE_FPSR(regs.fpsr,regs.fp[reg]);
1920 >                                        break;
1921 >                                case 0x09:              /* FTANH */
1922 >                                        D(bug("FTANH %.04f\r\n",(float)src));
1923 >                                        regs.fp[reg] = tanh (src);
1924 >                                        MAKE_FPSR(regs.fpsr,regs.fp[reg]);
1925 >                                        break;
1926 >                                case 0x0a:              /* FATAN */
1927 >                                        D(bug("FATAN %.04f\r\n",(float)src));
1928 >                                        regs.fp[reg] = atan (src);
1929 >                                        MAKE_FPSR(regs.fpsr,regs.fp[reg]);
1930 >                                        break;
1931 >                                case 0x0c:              /* FASIN */
1932 >                                        D(bug("FASIN %.04f\r\n",(float)src));
1933 >                                        regs.fp[reg] = asin (src);
1934 >                                        MAKE_FPSR(regs.fpsr,regs.fp[reg]);
1935 >                                        break;
1936 >                                case 0x0d:              /* FATANH */
1937 >                                        D(bug("FATANH %.04f\r\n",(float)src));
1938   #if 1                           /* The BeBox doesn't have atanh, and it isn't in the HPUX libm either */
1939 <            regs.fp[reg] = log ((1 + src) / (1 - src)) / 2;
1939 >                                        regs.fp[reg] = log ((1 + src) / (1 - src)) / 2;
1940   #else
1941 <            regs.fp[reg] = atanh (src);
1941 >                                        regs.fp[reg] = atanh (src);
1942   #endif
1943 <            regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
1944 <                (regs.fp[reg] < 0 ? 0x8000000 : 0);
1945 <            break;
1946 <        case 0x0e:              /* FSIN */
1947 <            regs.fp[reg] = sin (src);
1948 <            regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
1949 <                (regs.fp[reg] < 0 ? 0x8000000 : 0);
1950 <            break;
1951 <        case 0x0f:              /* FTAN */
1952 <            regs.fp[reg] = tan (src);
1953 <            regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
1954 <                (regs.fp[reg] < 0 ? 0x8000000 : 0);
1955 <            break;
1956 <        case 0x10:              /* FETOX */
1957 <            regs.fp[reg] = exp (src);
1958 <            regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
1959 <                (regs.fp[reg] < 0 ? 0x8000000 : 0);
1960 <            break;
1961 <        case 0x11:              /* FTWOTOX */
1962 <            regs.fp[reg] = pow(2.0, src);
1963 <            regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
1964 <                (regs.fp[reg] < 0 ? 0x8000000 : 0);
1965 <            break;
1966 <        case 0x12:              /* FTENTOX */
1967 <            regs.fp[reg] = pow(10.0, src);
1968 <            regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
1969 <                (regs.fp[reg] < 0 ? 0x8000000 : 0);
1970 <            break;
1971 <        case 0x14:              /* FLOGN */
1972 <            regs.fp[reg] = log (src);
1973 <            regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
1974 <                (regs.fp[reg] < 0 ? 0x8000000 : 0);
1975 <            break;
1976 <        case 0x15:              /* FLOG10 */
1977 <            regs.fp[reg] = log10 (src);
1978 <            regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
1979 <                (regs.fp[reg] < 0 ? 0x8000000 : 0);
1980 <            break;
1981 <        case 0x16:              /* FLOG2 */
1982 <            regs.fp[reg] = log (src) / log (2.0);
1983 <            regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
1984 <                (regs.fp[reg] < 0 ? 0x8000000 : 0);
1985 <            break;
1986 <        case 0x18:              /* FABS */
1987 <            regs.fp[reg] = src < 0 ? -src : src;
1988 <            regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
1989 <                (regs.fp[reg] < 0 ? 0x8000000 : 0);
1990 <            break;
1991 <        case 0x19:              /* FCOSH */
1992 <            regs.fp[reg] = cosh(src);
1993 <            regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
1994 <                (regs.fp[reg] < 0 ? 0x8000000 : 0);
1995 <            break;
1996 <        case 0x1a:              /* FNEG */
1997 <            regs.fp[reg] = -src;
1998 <            regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
1999 <                (regs.fp[reg] < 0 ? 0x8000000 : 0);
2000 <            break;
2001 <        case 0x1c:              /* FACOS */
2002 <            regs.fp[reg] = acos(src);
2003 <            regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
2004 <                (regs.fp[reg] < 0 ? 0x8000000 : 0);
2005 <            break;
2006 <        case 0x1d:              /* FCOS */
2007 <            regs.fp[reg] = cos(src);
2008 <            regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
2009 <                (regs.fp[reg] < 0 ? 0x8000000 : 0);
2010 <            break;
2011 <        case 0x1e:              /* FGETEXP */
2012 <            {
2013 <                int expon;
2014 <                frexp (src, &expon);
2015 <                regs.fp[reg] = (double) (expon - 1);
2016 <                regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
2017 <                    (regs.fp[reg] < 0 ? 0x8000000 : 0);
2018 <            }
2019 <            break;
2020 <        case 0x1f:              /* FGETMAN */
2021 <            {
2022 <                int expon;
2023 <                regs.fp[reg] = frexp (src, &expon) * 2.0;
2024 <                regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
2025 <                    (regs.fp[reg] < 0 ? 0x8000000 : 0);
2026 <            }
2027 <            break;
2028 <        case 0x20:              /* FDIV */
2029 <            regs.fp[reg] /= src;
2030 <            regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
2031 <                (regs.fp[reg] < 0 ? 0x8000000 : 0);
2032 <            break;
2033 <        case 0x21:              /* FMOD */
2034 <            regs.fp[reg] = regs.fp[reg] -
2035 <                (double) ((int) (regs.fp[reg] / src)) * src;
2036 <            regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
2037 <                (regs.fp[reg] < 0 ? 0x8000000 : 0);
2038 <            break;
2039 <        case 0x22:              /* FADD */
2040 <            regs.fp[reg] += src;
2041 <            regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
2042 <                (regs.fp[reg] < 0 ? 0x8000000 : 0);
2043 <            break;
2044 <        case 0x23:              /* FMUL */
2045 <            regs.fp[reg] *= src;
2046 <            regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
2047 <                (regs.fp[reg] < 0 ? 0x8000000 : 0);
2048 <            break;
2049 <        case 0x24:              /* FSGLDIV */
2050 <            regs.fp[reg] /= src;
2051 <            regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
2052 <                (regs.fp[reg] < 0 ? 0x8000000 : 0);
2053 <            break;
2054 <        case 0x25:              /* FREM */
2055 <            regs.fp[reg] = regs.fp[reg] -
2056 <                (double) ((int) (regs.fp[reg] / src + 0.5)) * src;
2057 <            regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
2058 <                (regs.fp[reg] < 0 ? 0x8000000 : 0);
2059 <            break;
2060 <        case 0x26:              /* FSCALE */
2061 <            regs.fp[reg] *= exp (log (2.0) * src);
2062 <            regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
2063 <                (regs.fp[reg] < 0 ? 0x8000000 : 0);
2064 <            break;
2065 <        case 0x27:              /* FSGLMUL */
2066 <            regs.fp[reg] *= src;
2067 <            regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
2068 <                (regs.fp[reg] < 0 ? 0x8000000 : 0);
2069 <            break;
2070 <        case 0x28:              /* FSUB */
2071 <            regs.fp[reg] -= src;
2072 <            regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
2073 <                (regs.fp[reg] < 0 ? 0x8000000 : 0);
2074 <            break;
2075 <        case 0x30:              /* FSINCOS */
2076 <        case 0x31:
2077 <        case 0x32:
2078 <        case 0x33:
2079 <        case 0x34:
2080 <        case 0x35:
2081 <        case 0x36:
2082 <        case 0x37:
2083 <            regs.fp[reg] = sin (src);
2084 <            regs.fp[extra & 7] = cos(src);
2085 <            regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
2086 <                (regs.fp[reg] < 0 ? 0x8000000 : 0);
2087 <            break;
2088 <        case 0x38:              /* FCMP */
2089 <            {
2090 <                double tmp = regs.fp[reg] - src;
2091 <                regs.fpsr = (tmp == 0 ? 0x4000000 : 0) |
2092 <                    (tmp < 0 ? 0x8000000 : 0);
2093 <            }
2094 <            break;
2095 <        case 0x3a:              /* FTST */
2096 <            regs.fpsr = (src == 0 ? 0x4000000 : 0) |
2097 <                (src < 0 ? 0x8000000 : 0);
2098 <            break;
2099 <        default:
2100 <            m68k_setpc (m68k_getpc () - 4);
2101 <            op_illg (opcode);
2102 <            break;
2103 <        }
2104 <        return;
2105 <    }
2106 <    m68k_setpc (m68k_getpc () - 4);
2107 <    op_illg (opcode);
2108 < }
1943 >                                        MAKE_FPSR(regs.fpsr,regs.fp[reg]);
1944 >                                        break;
1945 >                                case 0x0e:              /* FSIN */
1946 >                                        D(bug("FSIN %.04f\r\n",(float)src));
1947 >                                        regs.fp[reg] = sin (src);
1948 >                                        MAKE_FPSR(regs.fpsr,regs.fp[reg]);
1949 >                                        break;
1950 >                                case 0x0f:              /* FTAN */
1951 >                                        D(bug("FTAN %.04f\r\n",(float)src));
1952 >                                        regs.fp[reg] = tan (src);
1953 >                                        MAKE_FPSR(regs.fpsr,regs.fp[reg]);
1954 >                                        break;
1955 >                                case 0x10:              /* FETOX */
1956 >                                        D(bug("FETOX %.04f\r\n",(float)src));
1957 >                                        regs.fp[reg] = exp (src);
1958 >                                        MAKE_FPSR(regs.fpsr,regs.fp[reg]);
1959 >                                        break;
1960 >                                case 0x11:              /* FTWOTOX */
1961 >                                        D(bug("FTWOTOX %.04f\r\n",(float)src));
1962 >                                        regs.fp[reg] = pow(2.0, src);
1963 >                                        MAKE_FPSR(regs.fpsr,regs.fp[reg]);
1964 >                                        break;
1965 >                                case 0x12:              /* FTENTOX */
1966 >                                        D(bug("FTENTOX %.04f\r\n",(float)src));
1967 >                                        regs.fp[reg] = pow(10.0, src);
1968 >                                        MAKE_FPSR(regs.fpsr,regs.fp[reg]);
1969 >                                        break;
1970 >                                case 0x14:              /* FLOGN */
1971 >                                        D(bug("FLOGN %.04f\r\n",(float)src));
1972 >                                        regs.fp[reg] = log (src);
1973 >                                        MAKE_FPSR(regs.fpsr,regs.fp[reg]);
1974 >                                        break;
1975 >                                case 0x15:              /* FLOG10 */
1976 >                                        D(bug("FLOG10 %.04f\r\n",(float)src));
1977 >                                        regs.fp[reg] = log10 (src);
1978 >                                        MAKE_FPSR(regs.fpsr,regs.fp[reg]);
1979 >                                        break;
1980 >                                case 0x16:              /* FLOG2 */
1981 >                                        D(bug("FLOG2 %.04f\r\n",(float)src));
1982 >                                        regs.fp[reg] = log (src) / log (2.0);
1983 >                                        MAKE_FPSR(regs.fpsr,regs.fp[reg]);
1984 >                                        break;
1985 >                                case 0x18:              /* FABS */
1986 >                                        D(bug("FABS %.04f\r\n",(float)src));
1987 >                                        regs.fp[reg] = src < 0 ? -src : src;
1988 >                                        MAKE_FPSR(regs.fpsr,regs.fp[reg]);
1989 >                                        break;
1990 >                                case 0x19:              /* FCOSH */
1991 >                                        D(bug("FCOSH %.04f\r\n",(float)src));
1992 >                                        regs.fp[reg] = cosh(src);
1993 >                                        MAKE_FPSR(regs.fpsr,regs.fp[reg]);
1994 >                                        break;
1995 >                                case 0x1a:              /* FNEG */
1996 >                                        D(bug("FNEG %.04f\r\n",(float)src));
1997 >                                        regs.fp[reg] = -src;
1998 >                                        MAKE_FPSR(regs.fpsr,regs.fp[reg]);
1999 >                                        break;
2000 >                                case 0x1c:              /* FACOS */
2001 >                                        D(bug("FACOS %.04f\r\n",(float)src));
2002 >                                        regs.fp[reg] = acos(src);
2003 >                                        MAKE_FPSR(regs.fpsr,regs.fp[reg]);
2004 >                                        break;
2005 >                                case 0x1d:              /* FCOS */
2006 >                                        D(bug("FCOS %.04f\r\n",(float)src));
2007 >                                        regs.fp[reg] = cos(src);
2008 >                                        MAKE_FPSR(regs.fpsr,regs.fp[reg]);
2009 >                                        break;
2010 >                                case 0x1e:              /* FGETEXP */
2011 >                                        D(bug("FGETEXP %.04f\r\n",(float)src));
2012 > #if HAVE_IEEE_DOUBLE
2013 >                                        if( IS_INFINITY((uae_u32 *)&src) ) {
2014 >                                                MAKE_NAN( (uae_u32 *)&regs.fp[reg] );
2015 >                                        } else {
2016 >                                                regs.fp[reg] = FAST_FGETEXP( (uae_u32 *)&src );
2017 >                                        }
2018 > #else
2019 >                                        if(src == 0) {
2020 >                                                regs.fp[reg] = (double)0;
2021 >                                        } else {
2022 >                                                int expon;
2023 >                                                frexp (src, &expon);
2024 >                                                regs.fp[reg] = (double) (expon - 1);
2025 >                                        }
2026 > #endif
2027 >                                        MAKE_FPSR(regs.fpsr,regs.fp[reg]);
2028 >                                        break;
2029 >                                case 0x1f:              /* FGETMAN */
2030 >                                        D(bug("FGETMAN %.04f\r\n",(float)src));
2031 > #if HAVE_IEEE_DOUBLE
2032 >                                        if( src == 0 ) {
2033 >                                                regs.fp[reg] = 0;
2034 >                                        } else if( IS_INFINITY((uae_u32 *)&src) ) {
2035 >                                                MAKE_NAN( (uae_u32 *)&regs.fp[reg] );
2036 >                                        } else {
2037 >                                                regs.fp[reg] = src;
2038 >                                                FAST_REMOVE_EXPONENT( (uae_u32 *)&regs.fp[reg] );
2039 >                                        }
2040 > #else
2041 >                                        {
2042 >                                                int expon;
2043 >                                                regs.fp[reg] = frexp (src, &expon) * 2.0;
2044 >                                        }
2045 > #endif
2046 >                                        MAKE_FPSR(regs.fpsr,regs.fp[reg]);
2047 >                                        break;
2048 >                        case 0x20:              /* FDIV */
2049 >                                D(bug("FDIV %.04f\r\n",(float)src));
2050 >                                regs.fp[reg] /= src;
2051 >                                MAKE_FPSR(regs.fpsr,regs.fp[reg]);
2052 >                                break;
2053 >                        case 0x21:              /* FMOD */
2054 >                                D(bug("FMOD %.04f\r\n",(float)src));
2055 >                                // regs.fp[reg] = regs.fp[reg] - (double) ((int) (regs.fp[reg] / src)) * src;
2056 >                                { double quot = round_to_zero(regs.fp[reg] / src);
2057 > #if HAVE_IEEE_DOUBLE
2058 >                                        uae_u32 sign = GET_QUOTIENT_SIGN((uae_u32 *)&regs.fp[reg],(uae_u32 *)&src);
2059 > #endif
2060 >                                        regs.fp[reg] = regs.fp[reg] - quot * src;
2061 >                                        MAKE_FPSR(regs.fpsr,regs.fp[reg]);
2062 > #if HAVE_IEEE_DOUBLE
2063 >                                        regs.fpsr = MAKE_QUOTIENT(regs.fpsr,quot,sign);
2064 > #endif
2065 >                                }
2066 >                                break;
2067 >                        case 0x22:              /* FADD */
2068 >                                D(bug("FADD %.04f\r\n",(float)src));
2069 >                                regs.fp[reg] += src;
2070 >                                MAKE_FPSR(regs.fpsr,regs.fp[reg]);
2071 >                                break;
2072 >                        case 0x23:              /* FMUL */
2073 >                                D(bug("FMUL %.04f\r\n",(float)src));
2074 > #if HAVE_IEEE_DOUBLE
2075 >                                GET_DEST_FLAGS((uae_u32 *)&regs.fp[reg]);
2076 >                                GET_SOURCE_FLAGS((uae_u32 *)&src);
2077 >                                if(fl_dest.in_range && fl_source.in_range) {
2078 >                                        regs.fp[reg] *= src;
2079 >                                } else if( fl_dest.nan || fl_source.nan ||
2080 >                                        fl_dest.zero && fl_source.infinity ||
2081 >                                        fl_dest.infinity && fl_source.zero )
2082 >                                {
2083 >                                        MAKE_NAN( (uae_u32 *)&regs.fp[reg] );
2084 >                                } else if( fl_dest.zero || fl_source.zero ) {
2085 >                                        if( fl_dest.negative && !fl_source.negative ||
2086 >                                            !fl_dest.negative && fl_source.negative)
2087 >                                        {
2088 >                                                MAKE_ZERO_NEGATIVE((uae_u32 *)&regs.fp[reg]);
2089 >                                        } else {
2090 >                                                MAKE_ZERO_POSITIVE((uae_u32 *)&regs.fp[reg]);
2091 >                                        }
2092 >                                } else {
2093 >                                        if( fl_dest.negative && !fl_source.negative ||
2094 >                                            !fl_dest.negative && fl_source.negative)
2095 >                                        {
2096 >                                                MAKE_INF_NEGATIVE((uae_u32 *)&regs.fp[reg]);
2097 >                                        } else {
2098 >                                                MAKE_INF_POSITIVE((uae_u32 *)&regs.fp[reg]);
2099 >                                        }
2100 >                                }
2101 > #else
2102 >                                D(bug("FMUL %.04f\r\n",(float)src));
2103 >                                regs.fp[reg] *= src;
2104 > #endif
2105 >                                MAKE_FPSR(regs.fpsr,regs.fp[reg]);
2106 >                                break;
2107 >                        case 0x24:              /* FSGLDIV */
2108 >                                D(bug("FSGLDIV %.04f\r\n",(float)src));
2109 >                                // TODO: round to float.
2110 >                                regs.fp[reg] /= src;
2111 >                                MAKE_FPSR(regs.fpsr,regs.fp[reg]);
2112 >                                break;
2113 >                        case 0x25:              /* FREM */
2114 >                                D(bug("FREM %.04f\r\n",(float)src));
2115 >                                // regs.fp[reg] = regs.fp[reg] - (double) ((int) (regs.fp[reg] / src + 0.5)) * src;
2116 >                                { double quot = round_to_nearest(regs.fp[reg] / src);
2117 > #if HAVE_IEEE_DOUBLE
2118 >                                        uae_u32 sign = GET_QUOTIENT_SIGN((uae_u32 *)&regs.fp[reg],(uae_u32 *)&src);
2119 > #endif
2120 >                                        regs.fp[reg] = regs.fp[reg] - quot * src;
2121 >                                        MAKE_FPSR(regs.fpsr,regs.fp[reg]);
2122 > #if HAVE_IEEE_DOUBLE
2123 >                                        regs.fpsr = MAKE_QUOTIENT(regs.fpsr,quot,sign);
2124 > #endif
2125 >                                }
2126 >                                break;
2127 >
2128 >                        case 0x26:              /* FSCALE */
2129 >                                D(bug("FSCALE %.04f\r\n",(float)src));
2130  
2131 +                                // TODO:
2132 +                                // Overflow, underflow
2133 +
2134 + #if HAVE_IEEE_DOUBLE
2135 +                                if( IS_INFINITY((uae_u32 *)&regs.fp[reg]) ) {
2136 +                                        MAKE_NAN( (uae_u32 *)&regs.fp[reg] );
2137 +                                } else {
2138 +                                        // When the absolute value of the source operand is >= 2^14,
2139 +                                        // an overflow or underflow always results.
2140 +                                        // Here (int) cast is okay.
2141 +                                        FAST_SCALE( (uae_u32 *)&regs.fp[reg], (int)round_to_zero(src) );
2142 +                                }
2143 + #else
2144 +                                if(src != 0) { // Manual says: src==0 -> FPn
2145 +                                        regs.fp[reg] *= exp (log (2.0) * src);
2146 +                                }
2147   #endif
2148 +                                MAKE_FPSR(regs.fpsr,regs.fp[reg]);
2149 +                                break;
2150 +                        case 0x27:              /* FSGLMUL */
2151 +                                D(bug("FSGLMUL %.04f\r\n",(float)src));
2152 +                                regs.fp[reg] *= src;
2153 +                                MAKE_FPSR(regs.fpsr,regs.fp[reg]);
2154 +                                break;
2155 +                        case 0x28:              /* FSUB */
2156 +                                D(bug("FSUB %.04f\r\n",(float)src));
2157 +                                regs.fp[reg] -= src;
2158 +                                MAKE_FPSR(regs.fpsr,regs.fp[reg]);
2159 +                                break;
2160 +                        case 0x30:              /* FSINCOS */
2161 +                        case 0x31:
2162 +                        case 0x32:
2163 +                        case 0x33:
2164 +                        case 0x34:
2165 +                        case 0x35:
2166 +                        case 0x36:
2167 +                        case 0x37:
2168 +                                D(bug("FSINCOS %.04f\r\n",(float)src));
2169 +                                // Cosine must be calculated first if same register
2170 +                                regs.fp[extra & 7] = cos(src);
2171 +                                regs.fp[reg] = sin (src);
2172 +                                // Set fpsr according to the sine result
2173 +                                MAKE_FPSR(regs.fpsr,regs.fp[reg]);
2174 +                                break;
2175 +                        case 0x38:              /* FCMP */
2176 +                                D(bug("FCMP %.04f\r\n",(float)src));
2177 +
2178 +                                // The infinity bit is always cleared by the FCMP
2179 +                                // instruction since it is not used by any of the
2180 +                                // conditional predicate equations.
2181 +
2182 + #if HAVE_IEEE_DOUBLE
2183 +                                if( IS_INFINITY((uae_u32 *)&src) ) {
2184 +                                        if( IS_NEGATIVE((uae_u32 *)&src) ) {
2185 +                                                // negative infinity
2186 +                                                if( IS_INFINITY((uae_u32 *)&regs.fp[reg]) && IS_NEGATIVE((uae_u32 *)&regs.fp[reg]) ) {
2187 +                                                        // Zero, Negative
2188 +                                                        regs.fpsr = (regs.fpsr & 0x00FFFFFF) | 0x4000000 | 0x8000000;
2189 +                                                        D(bug("-INF cmp -INF -> NZ\r\n"));
2190 +                                                } else {
2191 +                                                        // None
2192 +                                                        regs.fpsr = (regs.fpsr & 0x00FFFFFF);
2193 +                                                        D(bug("x cmp -INF -> None\r\n"));
2194 +                                                }
2195 +                                        } else {
2196 +                                                // positive infinity
2197 +                                                if( IS_INFINITY((uae_u32 *)&regs.fp[reg]) && !IS_NEGATIVE((uae_u32 *)&regs.fp[reg]) ) {
2198 +                                                        // Zero
2199 +                                                        regs.fpsr = (regs.fpsr & 0x00FFFFFF) | 0x4000000;
2200 +                                                        D(bug("+INF cmp +INF -> Z\r\n"));
2201 +                                                } else {
2202 +                                                        // Negative
2203 +                                                        regs.fpsr = (regs.fpsr & 0x00FFFFFF) | 0x8000000;
2204 +                                                        D(bug("X cmp +INF -> N\r\n"));
2205 +                                                }
2206 +                                        }
2207 +                                } else {
2208 +                                        double tmp = regs.fp[reg] - src;
2209 +                                        regs.fpsr = (regs.fpsr & 0x00FFFFFF) | (tmp == 0 ? 0x4000000 : 0) | (tmp < 0 ? 0x8000000 : 0);
2210 +                                }
2211 + #else
2212 +                                {
2213 +                                        double tmp = regs.fp[reg] - src;
2214 +                                        MAKE_FPSR(regs.fpsr,tmp);
2215 +                                }
2216 + #endif
2217 +                                break;
2218 +                        case 0x3a:              /* FTST */
2219 +                                D(bug("FTST %.04f\r\n",(float)src));
2220 +                                // MAKE_FPSR(regs.fpsr,regs.fp[reg]);
2221 +                                MAKE_FPSR(regs.fpsr,src);
2222 +                                break;
2223 +                        default:
2224 +                                D(bug("ILLEGAL F OP %X\r\n",opcode));
2225 +                                m68k_setpc (m68k_getpc () - 4);
2226 +                                op_illg (opcode);
2227 +                                break;
2228 +                }
2229 +                dump_fp_regs( "END  ");
2230 +                return;
2231 +  }
2232 +        D(bug("ILLEGAL F OP 2 %X\r\n",opcode));
2233 +  m68k_setpc (m68k_getpc () - 4);
2234 +  op_illg (opcode);
2235 +        dump_fp_regs( "END  ");
2236 + }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines