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.6 by cebix, 1999-10-31T23:18: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] =
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 >        // D(bug("put_fp_value(%.04f,%X,%X)\r\n",(float)value,(int)opcode,(int)extra));
881 >
882 >  if ((extra & 0x4000) == 0) {
883 >                int dest_reg = (extra >> 10) & 7;
884 >                regs.fp[dest_reg] = value;
885 >                MAKE_FPSR(regs.fpsr,regs.fp[dest_reg]);
886 >                return 1;
887 >  }
888 >  mode = (opcode >> 3) & 7;
889 >  reg = opcode & 7;
890 >  size = (extra >> 10) & 7;
891 >  ad = 0xffffffff;
892 >  switch (mode) {
893      case 0:
894 <        switch (size) {
895 <        case 6:
896 <            m68k_dreg (regs, reg) = (((int) value & 0xff)
894 >                        switch (size) {
895 >                                case 6:
896 >                                        m68k_dreg (regs, reg) = (((int) value & 0xff)
897                                      | (m68k_dreg (regs, reg) & ~0xff));
898 <            break;
899 <        case 4:
900 <            m68k_dreg (regs, reg) = (((int) value & 0xffff)
898 >                                        break;
899 >                                case 4:
900 >                                        m68k_dreg (regs, reg) = (((int) value & 0xffff)
901                                      | (m68k_dreg (regs, reg) & ~0xffff));
902 <            break;
903 <        case 0:
904 <            m68k_dreg (regs, reg) = (int) value;
905 <            break;
906 <        case 1:
907 <            m68k_dreg (regs, reg) = from_single(value);
908 <            break;
909 <        default:
910 <            return 0;
911 <        }
912 <        return 1;
913 <    case 1:
914 <        return 0;
902 >                                        break;
903 >                                case 0:
904 >                                        m68k_dreg (regs, reg) = (int) value;
905 >                                        break;
906 >                                case 1:
907 >                                        m68k_dreg (regs, reg) = from_single(value);
908 >                                        break;
909 >                                default:
910 >                                        return 0;
911 >                        }
912 >                        return 1;
913 >                case 1:
914 >                        return 0;
915      case 2:
916 <        ad = m68k_areg (regs, reg);
917 <        break;
916 >                        ad = m68k_areg (regs, reg);
917 >                        break;
918      case 3:
919 <        ad = m68k_areg (regs, reg);
920 <        m68k_areg (regs, reg) += reg == 7 ? sz2[size] : sz1[size];
921 <        break;
919 >                        ad = m68k_areg (regs, reg);
920 >                        m68k_areg (regs, reg) += reg == 7 ? sz2[size] : sz1[size];
921 >                        break;
922      case 4:
923 <        m68k_areg (regs, reg) -= reg == 7 ? sz2[size] : sz1[size];
924 <        ad = m68k_areg (regs, reg);
925 <        break;
923 >                        m68k_areg (regs, reg) -= reg == 7 ? sz2[size] : sz1[size];
924 >                        ad = m68k_areg (regs, reg);
925 >                        break;
926      case 5:
927 <        ad = m68k_areg (regs, reg) + (uae_s32) (uae_s16) next_iword();
928 <        break;
927 >                        ad = m68k_areg (regs, reg) + (uae_s32) (uae_s16) next_iword();
928 >                        break;
929      case 6:
930 <        ad = get_disp_ea_020 (m68k_areg (regs, reg), next_iword());
931 <        break;
930 >                        ad = get_disp_ea_020 (m68k_areg (regs, reg), next_iword());
931 >                        break;
932      case 7:
933 <        switch (reg) {
934 <        case 0:
935 <            ad = (uae_s32) (uae_s16) next_iword();
936 <            break;
937 <        case 1:
938 <            ad = next_ilong();
939 <            break;
940 <        case 2:
941 <            ad = m68k_getpc ();
942 <            ad += (uae_s32) (uae_s16) next_iword();
943 <            break;
944 <        case 3:
945 <            tmppc = m68k_getpc ();
946 <            tmp = next_iword();
947 <            ad = get_disp_ea_020 (tmppc, tmp);
948 <            break;
949 <        case 4:
950 <            ad = m68k_getpc ();
951 <            m68k_setpc (ad + sz2[size]);
952 <            break;
953 <        default:
954 <            return 0;
955 <        }
956 <    }
957 <    switch (size) {
933 >                        switch (reg) {
934 >                                case 0:
935 >                                        ad = (uae_s32) (uae_s16) next_iword();
936 >                                        break;
937 >                                case 1:
938 >                                        ad = next_ilong();
939 >                                        break;
940 >                                case 2:
941 >                                        ad = m68k_getpc ();
942 >                                        ad += (uae_s32) (uae_s16) next_iword();
943 >                                        break;
944 >                                case 3:
945 >                                        tmppc = m68k_getpc ();
946 >                                        tmp = (uae_u16)next_iword();
947 >                                        ad = get_disp_ea_020 (tmppc, tmp);
948 >                                        break;
949 >                                case 4:
950 >                                        ad = m68k_getpc ();
951 >                                        m68k_setpc (ad + sz2[size]);
952 >                                        break;
953 >                                default:
954 >                                        return 0;
955 >                        }
956 >  }
957 >  switch (size) {
958      case 0:
959 <        put_long (ad, (uae_s32) value);
960 <        break;
959 >                        put_long (ad, (uae_s32) value);
960 >                        break;
961      case 1:
962 <        put_long (ad, from_single(value));
963 <        break;
964 <    case 2:
965 <        {
966 <            uae_u32 wrd1, wrd2, wrd3;
967 <            from_exten(value, &wrd1, &wrd2, &wrd3);
968 <            put_long (ad, wrd1);
969 <            ad += 4;
970 <            put_long (ad, wrd2);
971 <            ad += 4;
972 <            put_long (ad, wrd3);
973 <        }
974 <        break;
962 >                        put_long (ad, from_single(value));
963 >                        break;
964 >                case 2:
965 >                        {
966 >                                        uae_u32 wrd1, wrd2, wrd3;
967 >                                        from_exten(value, &wrd1, &wrd2, &wrd3);
968 >                                        put_long (ad, wrd1);
969 >                                        ad += 4;
970 >                                        put_long (ad, wrd2);
971 >                                        ad += 4;
972 >                                        put_long (ad, wrd3);
973 >                        }
974 >                        break;
975      case 3:
976 <        {
977 <            uae_u32 wrd1, wrd2, wrd3;
978 <            from_pack(value, &wrd1, &wrd2, &wrd3);
979 <            put_long (ad, wrd1);
980 <            ad += 4;
981 <            put_long (ad, wrd2);
982 <            ad += 4;
983 <            put_long (ad, wrd3);
984 <        }
985 <        break;
986 <    case 4:
987 <        put_word(ad, (uae_s16) value);
988 <        break;
976 >                        {
977 >                                        uae_u32 wrd1, wrd2, wrd3;
978 >                                        from_pack(value, &wrd1, &wrd2, &wrd3);
979 >                                        put_long (ad, wrd1);
980 >                                        ad += 4;
981 >                                        put_long (ad, wrd2);
982 >                                        ad += 4;
983 >                                        put_long (ad, wrd3);
984 >                        }
985 >                        break;
986 >                case 4:
987 >                        put_word(ad, (uae_s16) value);
988 >                        break;
989      case 5:{
990              uae_u32 wrd1, wrd2;
991              from_double(value, &wrd1, &wrd2);
992              put_long (ad, wrd1);
993              ad += 4;
994              put_long (ad, wrd2);
995 <        }
996 <        break;
995 >                        }
996 >                        break;
997      case 6:
998 <        put_byte(ad, (uae_s8) value);
999 <        break;
998 >                        put_byte(ad, (uae_s8) value);
999 >                        break;
1000      default:
1001 <        return 0;
1002 <    }
1003 <    return 1;
1001 >                        return 0;
1002 >  }
1003 >  return 1;
1004   }
1005  
1006   static __inline__ int get_fp_ad(uae_u32 opcode, uae_u32 * ad)
1007   {
1008 <    uae_u16 tmp;
1009 <    uaecptr tmppc;
1010 <    int mode;
1011 <    int reg;
1012 <
1013 <    mode = (opcode >> 3) & 7;
1014 <    reg = opcode & 7;
1015 <    switch (mode) {
1008 >  uae_u16 tmp;
1009 >  uaecptr tmppc;
1010 >  int mode;
1011 >  int reg;
1012 >
1013 >  mode = (opcode >> 3) & 7;
1014 >  reg = opcode & 7;
1015 >  switch (mode) {
1016      case 0:
1017      case 1:
1018 <        return 0;
1018 >                        return 0;
1019      case 2:
1020 <        *ad = m68k_areg (regs, reg);
1021 <        break;
1020 >                        *ad = m68k_areg (regs, reg);
1021 >                        break;
1022      case 3:
1023 <        *ad = m68k_areg (regs, reg);
1024 <        break;
1023 >                        *ad = m68k_areg (regs, reg);
1024 >                        break;
1025      case 4:
1026 <        *ad = m68k_areg (regs, reg);
1027 <        break;
1026 >                        *ad = m68k_areg (regs, reg);
1027 >                        break;
1028      case 5:
1029 <        *ad = m68k_areg (regs, reg) + (uae_s32) (uae_s16) next_iword();
1030 <        break;
1029 >                        *ad = m68k_areg (regs, reg) + (uae_s32) (uae_s16) next_iword();
1030 >                        break;
1031      case 6:
1032 <        *ad = get_disp_ea_020 (m68k_areg (regs, reg), next_iword());
1033 <        break;
1032 >                        *ad = get_disp_ea_020 (m68k_areg (regs, reg), next_iword());
1033 >                        break;
1034      case 7:
1035 <        switch (reg) {
1036 <        case 0:
1037 <            *ad = (uae_s32) (uae_s16) next_iword();
1038 <            break;
1039 <        case 1:
1040 <            *ad = next_ilong();
1041 <            break;
1042 <        case 2:
1043 <            *ad = m68k_getpc ();
1044 <            *ad += (uae_s32) (uae_s16) next_iword();
1045 <            break;
1046 <        case 3:
1047 <            tmppc = m68k_getpc ();
1048 <            tmp = next_iword();
1049 <            *ad = get_disp_ea_020 (tmppc, tmp);
1050 <            break;
1051 <        default:
1052 <            return 0;
1053 <        }
1054 <    }
1055 <    return 1;
1035 >                        switch (reg) {
1036 >                                case 0:
1037 >                                        *ad = (uae_s32) (uae_s16) next_iword();
1038 >                                        break;
1039 >                                case 1:
1040 >                                        *ad = next_ilong();
1041 >                                        break;
1042 >                                case 2:
1043 >                                        *ad = m68k_getpc ();
1044 >                                        *ad += (uae_s32) (uae_s16) next_iword();
1045 >                                        break;
1046 >                                case 3:
1047 >                                        tmppc = m68k_getpc ();
1048 >                                        tmp = (uae_u16)next_iword();
1049 >                                        *ad = get_disp_ea_020 (tmppc, tmp);
1050 >                                        break;
1051 >                                default:
1052 >                                        return 0;
1053 >                        }
1054 >  }
1055 >  return 1;
1056   }
1057  
1058   static __inline__ int fpp_cond(uae_u32 opcode, int contition)
1059   {
1060 <    int N = (regs.fpsr & 0x8000000) != 0;
1061 <    int Z = (regs.fpsr & 0x4000000) != 0;
1062 <    /* int I = (regs.fpsr & 0x2000000) != 0; */
1063 <    int NotANumber = (regs.fpsr & 0x1000000) != 0;
1060 >  int N = (regs.fpsr & 0x8000000) != 0;
1061 >  int Z = (regs.fpsr & 0x4000000) != 0;
1062 >  /* int I = (regs.fpsr & 0x2000000) != 0; */
1063 >  int NotANumber = (regs.fpsr & 0x1000000) != 0;
1064  
1065 <    switch (contition) {
1065 >  switch (contition) {
1066      case 0x00:
1067 <        return 0;
1067 >                        CONDRET("False",0);
1068      case 0x01:
1069 <        return Z;
1069 >                        CONDRET("Equal",Z);
1070      case 0x02:
1071 <        return !(NotANumber || Z || N);
1071 >                        CONDRET("Ordered Greater Than",!(NotANumber || Z || N));
1072      case 0x03:
1073 <        return Z || !(NotANumber || N);
1073 >                        CONDRET("Ordered Greater Than or Equal",Z || !(NotANumber || N));
1074      case 0x04:
1075 <        return N && !(NotANumber || Z);
1075 >                        CONDRET("Ordered Less Than",N && !(NotANumber || Z));
1076      case 0x05:
1077 <        return Z || (N && !NotANumber);
1077 >                        CONDRET("Ordered Less Than or Equal",Z || (N && !NotANumber));
1078      case 0x06:
1079 <        return !(NotANumber || Z);
1079 >                        CONDRET("Ordered Greater or Less Than",!(NotANumber || Z));
1080      case 0x07:
1081 <        return !NotANumber;
1081 >                        CONDRET("Ordered",!NotANumber);
1082      case 0x08:
1083 <        return NotANumber;
1083 >                        CONDRET("Unordered",NotANumber);
1084      case 0x09:
1085 <        return NotANumber || Z;
1085 >                        CONDRET("Unordered or Equal",NotANumber || Z);
1086      case 0x0a:
1087 <        return NotANumber || !(N || Z);
1087 >                        CONDRET("Unordered or Greater Than",NotANumber || !(N || Z));
1088      case 0x0b:
1089 <        return NotANumber || Z || !N;
1089 >                        CONDRET("Unordered or Greater or Equal",NotANumber || Z || !N);
1090      case 0x0c:
1091 <        return NotANumber || (N && !Z);
1091 >                        CONDRET("Unordered or Less Than",NotANumber || (N && !Z));
1092      case 0x0d:
1093 <        return NotANumber || Z || N;
1093 >                        CONDRET("Unordered or Less or Equal",NotANumber || Z || N);
1094      case 0x0e:
1095 <        return !Z;
1095 >                        CONDRET("Not Equal",!Z);
1096      case 0x0f:
1097 <        return 1;
1097 >                        CONDRET("True",1);
1098      case 0x10:
1099 <        return 0;
1099 >                        CONDRET("Signaling False",0);
1100      case 0x11:
1101 <        return Z;
1101 >                        CONDRET("Signaling Equal",Z);
1102      case 0x12:
1103 <        return !(NotANumber || Z || N);
1103 >                        CONDRET("Greater Than",!(NotANumber || Z || N));
1104      case 0x13:
1105 <        return Z || !(NotANumber || N);
1105 >                        CONDRET("Greater Than or Equal",Z || !(NotANumber || N));
1106      case 0x14:
1107 <        return N && !(NotANumber || Z);
1107 >                        CONDRET("Less Than",N && !(NotANumber || Z));
1108      case 0x15:
1109 <        return Z || (N && !NotANumber);
1109 >                        CONDRET("Less Than or Equal",Z || (N && !NotANumber));
1110      case 0x16:
1111 <        return !(NotANumber || Z);
1111 >                        CONDRET("Greater or Less Than",!(NotANumber || Z));
1112      case 0x17:
1113 <        return !NotANumber;
1113 >                        CONDRET("Greater, Less or Equal",!NotANumber);
1114      case 0x18:
1115 <        return NotANumber;
1115 >                        CONDRET("Not Greater, Less or Equal",NotANumber);
1116      case 0x19:
1117 <        return NotANumber || Z;
1117 >                        CONDRET("Not Greater or Less Than",NotANumber || Z);
1118      case 0x1a:
1119 <        return NotANumber || !(N || Z);
1119 >                        CONDRET("Not Less Than or Equal",NotANumber || !(N || Z));
1120      case 0x1b:
1121 <        return NotANumber || Z || !N;
1121 >                        CONDRET("Not Less Than",NotANumber || Z || !N);
1122      case 0x1c:
1123 <        return NotANumber || (Z && N);
1123 >                        // CONDRET("Not Greater Than or Equal",NotANumber || (Z && N));
1124 >                        CONDRET("Not Greater Than or Equal",!Z && (NotANumber || N));
1125      case 0x1d:
1126 <        return NotANumber || Z || N;
1126 >                        CONDRET("Not Greater Than",NotANumber || Z || N);
1127      case 0x1e:
1128 <        return !Z;
1128 >                        CONDRET("Signaling Not Equal",!Z);
1129      case 0x1f:
1130 <        return 1;
1131 <    }
1132 <    return -1;
1130 >                        CONDRET("Signaling True",1);
1131 >  }
1132 >        CONDRET("",-1);
1133   }
1134  
1135   void fdbcc_opp(uae_u32 opcode, uae_u16 extra)
1136   {
1137 <    uaecptr pc = (uae_u32) m68k_getpc ();
1138 <    uae_s32 disp = (uae_s32) (uae_s16) next_iword();
1139 <    int cc;
1140 <
1141 < #if DEBUG_FPP
1142 <    printf("fdbcc_opp at %08lx\n", m68k_getpc ());
1143 <    fflush(stdout);
1144 < #endif
1145 <    cc = fpp_cond(opcode, extra & 0x3f);
1146 <    if (cc == -1) {
1147 <        m68k_setpc (pc - 4);
1148 <        op_illg (opcode);
639 <    } else if (!cc) {
640 <        int reg = opcode & 0x7;
1137 >  uaecptr pc = (uae_u32) m68k_getpc ();
1138 >  uae_s32 disp = (uae_s32) (uae_s16) next_iword();
1139 >  int cc;
1140 >
1141 >  D(bug("fdbcc_opp %X, %X at %08lx\r\n", (uae_u32)opcode, (uae_u32)extra, m68k_getpc ()));
1142 >
1143 >  cc = fpp_cond(opcode, extra & 0x3f);
1144 >  if (cc == -1) {
1145 >                m68k_setpc (pc - 4);
1146 >                op_illg (opcode);
1147 >  } else if (!cc) {
1148 >                int reg = opcode & 0x7;
1149  
1150 <        m68k_dreg (regs, reg) = ((m68k_dreg (regs, reg) & ~0xffff)
1150 >                // this may have leaked.
1151 >                /*
1152 >                m68k_dreg (regs, reg) = ((m68k_dreg (regs, reg) & ~0xffff)
1153                                  | ((m68k_dreg (regs, reg) - 1) & 0xffff));
1154 <        if ((m68k_dreg (regs, reg) & 0xffff) == 0xffff)
1154 >                */
1155 >                m68k_dreg (regs, reg) = ((m68k_dreg (regs, reg) & 0xffff0000)
1156 >                                | (((m68k_dreg (regs, reg) & 0xffff) - 1) & 0xffff));
1157 >
1158 >                
1159 >                // condition reversed.
1160 >                // if ((m68k_dreg (regs, reg) & 0xffff) == 0xffff)
1161 >                if ((m68k_dreg (regs, reg) & 0xffff) != 0xffff)
1162              m68k_setpc (pc + disp);
1163 <    }
1163 >  }
1164   }
1165  
1166   void fscc_opp(uae_u32 opcode, uae_u16 extra)
1167   {
1168 <    uae_u32 ad;
1169 <    int cc;
1168 >  uae_u32 ad;
1169 >  int cc;
1170  
1171 < #if DEBUG_FPP
1172 <    printf("fscc_opp at %08lx\n", m68k_getpc ());
1173 <    fflush(stdout);
1174 < #endif
1175 <    cc = fpp_cond(opcode, extra & 0x3f);
1176 <    if (cc == -1) {
1177 <        m68k_setpc (m68k_getpc () - 4);
1178 <        op_illg (opcode);
662 <    } else if ((opcode & 0x38) == 0) {
663 <        m68k_dreg (regs, opcode & 7) = (m68k_dreg (regs, opcode & 7) & ~0xff) |
1171 >  D(bug("fscc_opp %X, %X at %08lx\r\n", (uae_u32)opcode, (uae_u32)extra, m68k_getpc ()));
1172 >
1173 >  cc = fpp_cond(opcode, extra & 0x3f);
1174 >  if (cc == -1) {
1175 >                m68k_setpc (m68k_getpc () - 4);
1176 >                op_illg (opcode);
1177 >  } else if ((opcode & 0x38) == 0) {
1178 >                m68k_dreg (regs, opcode & 7) = (m68k_dreg (regs, opcode & 7) & ~0xff) |
1179              (cc ? 0xff : 0x00);
1180 <    } else {
1181 <        if (get_fp_ad(opcode, &ad) == 0) {
1180 >  } else {
1181 >                if (get_fp_ad(opcode, &ad) == 0) {
1182              m68k_setpc (m68k_getpc () - 4);
1183              op_illg (opcode);
1184 <        } else
1184 >                } else
1185              put_byte(ad, cc ? 0xff : 0x00);
1186 <    }
1186 >  }
1187   }
1188  
1189   void ftrapcc_opp(uae_u32 opcode, uaecptr oldpc)
1190   {
1191 <    int cc;
1191 >  int cc;
1192  
1193 < #if DEBUG_FPP
1194 <    printf("ftrapcc_opp at %08lx\n", m68k_getpc ());
1195 <    fflush(stdout);
1196 < #endif
1197 <    cc = fpp_cond(opcode, opcode & 0x3f);
1198 <    if (cc == -1) {
1199 <        m68k_setpc (oldpc);
1200 <        op_illg (opcode);
1201 <    }
687 <    if (cc)
688 <        Exception(7, oldpc - 2);
1193 >  D(bug("ftrapcc_opp %X at %08lx\r\n", (uae_u32)opcode, m68k_getpc ()));
1194 >
1195 >  cc = fpp_cond(opcode, opcode & 0x3f);
1196 >  if (cc == -1) {
1197 >                m68k_setpc (oldpc);
1198 >                op_illg (opcode);
1199 >  }
1200 >  if (cc)
1201 >                Exception(7, oldpc - 2);
1202   }
1203  
1204 + // NOTE that we get here also when there is a FNOP (nontrapping false, displ 0)
1205   void fbcc_opp(uae_u32 opcode, uaecptr pc, uae_u32 extra)
1206   {
1207 <    int cc;
1207 >  int cc;
1208  
1209 < #if DEBUG_FPP
1210 <    printf("fbcc_opp at %08lx\n", m68k_getpc ());
1211 <    fflush(stdout);
1212 < #endif
1213 <    cc = fpp_cond(opcode, opcode & 0x3f);
1214 <    if (cc == -1) {
1215 <        m68k_setpc (pc);
1216 <        op_illg (opcode);
703 <    } else if (cc) {
704 <        if ((opcode & 0x40) == 0)
1209 >  D(bug("fbcc_opp %X, %X at %08lx, jumpto=%X\r\n", (uae_u32)opcode, (uae_u32)extra, m68k_getpc (), extra ));
1210 >
1211 >  cc = fpp_cond(opcode, opcode & 0x3f);
1212 >  if (cc == -1) {
1213 >                m68k_setpc (pc);
1214 >                op_illg (opcode);
1215 >  } else if (cc) {
1216 >                if ((opcode & 0x40) == 0)
1217              extra = (uae_s32) (uae_s16) extra;
1218 <        m68k_setpc (pc + extra);
1219 <    }
1218 >                m68k_setpc (pc + extra);
1219 >  }
1220   }
1221  
1222 + // FSAVE has no post-increment
1223 + // 0x1f180000 == IDLE state frame, coprocessor version number 1F
1224   void fsave_opp(uae_u32 opcode)
1225   {
1226 <    uae_u32 ad;
1227 <    int incr = (opcode & 0x38) == 0x20 ? -1 : 1;
1228 <    int i;
1229 <
1230 < #if DEBUG_FPP
1231 <    printf("fsave_opp at %08lx\n", m68k_getpc ());
1232 <    fflush(stdout);
1233 < #endif
1234 <    if (get_fp_ad(opcode, &ad) == 0) {
1235 <        m68k_setpc (m68k_getpc () - 2);
1236 <        op_illg (opcode);
1237 <        return;
1238 <    }
1239 <    if (incr < 0) {
1240 <        ad -= 4;
1241 <        put_long (ad, 0x70000000);
1242 <        for (i = 0; i < 5; i++) {
1243 <            ad -= 4;
1244 <            put_long (ad, 0x00000000);
1226 >  uae_u32 ad;
1227 >  int incr = (opcode & 0x38) == 0x20 ? -1 : 1;
1228 >  int i;
1229 >
1230 >  D(bug("fsave_opp at %08lx\r\n", m68k_getpc ()));
1231 >
1232 >  if (get_fp_ad(opcode, &ad) == 0) {
1233 >                m68k_setpc (m68k_getpc () - 2);
1234 >                op_illg (opcode);
1235 >                return;
1236 >  }
1237 >        
1238 >        if (CPUType == 4) {
1239 >                // Put 4 byte 68040 IDLE frame.
1240 >                if (incr < 0) {
1241 >                        ad -= 4;
1242 >                        put_long (ad, 0x41000000);
1243 >                } else {
1244 >                        put_long (ad, 0x41000000);
1245 >                        ad += 4;
1246 >                }
1247 >        } else {
1248 >                // Put 28 byte 68881 IDLE frame.
1249 >          if (incr < 0) {
1250 >                  D(bug("fsave_opp pre-decrement\r\n"));
1251 >                        ad -= 4;
1252 >                        // What's this? Some BIU flags, or (incorrectly placed) command/condition?
1253 >                        put_long (ad, 0x70000000);
1254 >                        for (i = 0; i < 5; i++) {
1255 >                    ad -= 4;
1256 >                    put_long (ad, 0x00000000);
1257 >                        }
1258 >                        ad -= 4;
1259 >                        put_long (ad, 0x1f180000); // IDLE, vers 1f
1260 >          } else {
1261 >                        put_long (ad, 0x1f180000); // IDLE, vers 1f
1262 >                        ad += 4;
1263 >                        for (i = 0; i < 5; i++) {
1264 >                    put_long (ad, 0x00000000);
1265 >                    ad += 4;
1266 >                        }
1267 >                        // What's this? Some BIU flags, or (incorrectly placed) command/condition?
1268 >                        put_long (ad, 0x70000000);
1269 >                        ad += 4;
1270 >          }
1271          }
1272 <        ad -= 4;
1273 <        put_long (ad, 0x1f180000);
1274 <    } else {
1275 <        put_long (ad, 0x1f180000);
1276 <        ad += 4;
1277 <        for (i = 0; i < 5; i++) {
1278 <            put_long (ad, 0x00000000);
739 <            ad += 4;
1272 >  if ((opcode & 0x38) == 0x18) {
1273 >                m68k_areg (regs, opcode & 7) = ad; // Never executed on a 68881
1274 >          D(bug("PROBLEM: fsave_opp post-increment\r\n"));
1275 >        }
1276 >  if ((opcode & 0x38) == 0x20) {
1277 >                m68k_areg (regs, opcode & 7) = ad;
1278 >          D(bug("fsave_opp pre-decrement %X -> A%d\r\n",ad,opcode & 7));
1279          }
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;
1280   }
1281  
1282 + // FRESTORE has no pre-decrement
1283   void frestore_opp(uae_u32 opcode)
1284   {
1285 <    uae_u32 ad;
1286 <    uae_u32 d;
1287 <    int incr = (opcode & 0x38) == 0x20 ? -1 : 1;
1288 <
1289 < #if DEBUG_FPP
1290 <    printf("frestore_opp at %08lx\n", m68k_getpc ());
1291 <    fflush(stdout);
1292 < #endif
1293 <    if (get_fp_ad(opcode, &ad) == 0) {
1294 <        m68k_setpc (m68k_getpc () - 2);
1295 <        op_illg (opcode);
1296 <        return;
1297 <    }
1298 <    if (incr < 0) {
1299 <        ad -= 4;
1300 <        d = get_long (ad);
1301 <        if ((d & 0xff000000) != 0) {
1302 <            if ((d & 0x00ff0000) == 0x00180000)
1303 <                ad -= 6 * 4;
1304 <            else if ((d & 0x00ff0000) == 0x00380000)
1305 <                ad -= 14 * 4;
1306 <            else if ((d & 0x00ff0000) == 0x00b40000)
1307 <                ad -= 45 * 4;
1285 >  uae_u32 ad;
1286 >  uae_u32 d;
1287 >  int incr = (opcode & 0x38) == 0x20 ? -1 : 1;
1288 >
1289 >  D(bug("frestore_opp at %08lx\r\n", m68k_getpc ()));
1290 >
1291 >  if (get_fp_ad(opcode, &ad) == 0) {
1292 >                m68k_setpc (m68k_getpc () - 2);
1293 >                op_illg (opcode);
1294 >                return;
1295 >  }
1296 >
1297 >        if (CPUType == 4) {
1298 >                // 68040
1299 >                if (incr < 0) {
1300 >                  D(bug("PROBLEM: frestore_opp incr < 0\r\n"));
1301 >                        // this may be wrong, but it's never called.
1302 >                        ad -= 4;
1303 >                        d = get_long (ad);
1304 >                        if ((d & 0xff000000) != 0) { // Not a NULL frame?
1305 >                                if ((d & 0x00ff0000) == 0) { // IDLE
1306 >                                  D(bug("frestore_opp found IDLE frame at %X\r\n",ad-4));
1307 >                                } else if ((d & 0x00ff0000) == 0x00300000) { // UNIMP
1308 >                                  D(bug("PROBLEM: frestore_opp found UNIMP frame at %X\r\n",ad-4));
1309 >                                        ad -= 44;
1310 >                                } else if ((d & 0x00ff0000) == 0x00600000) { // BUSY
1311 >                                  D(bug("PROBLEM: frestore_opp found BUSY frame at %X\r\n",ad-4));
1312 >                                        ad -= 92;
1313 >                                }
1314 >                        }
1315 >                } else {
1316 >                        d = get_long (ad);
1317 >                  D(bug("frestore_opp frame at %X = %X\r\n",ad,d));
1318 >                        ad += 4;
1319 >                        if ((d & 0xff000000) != 0) { // Not a NULL frame?
1320 >                                if ((d & 0x00ff0000) == 0) { // IDLE
1321 >                                  D(bug("frestore_opp found IDLE frame at %X\r\n",ad-4));
1322 >                                } else if ((d & 0x00ff0000) == 0x00300000) { // UNIMP
1323 >                                  D(bug("PROBLEM: frestore_opp found UNIMP frame at %X\r\n",ad-4));
1324 >                                        ad += 44;
1325 >                                } else if ((d & 0x00ff0000) == 0x00600000) { // BUSY
1326 >                                  D(bug("PROBLEM: frestore_opp found BUSY frame at %X\r\n",ad-4));
1327 >                                        ad += 92;
1328 >                                }
1329 >                        }
1330 >                }
1331 >        } else {
1332 >                // 68881
1333 >          if (incr < 0) {
1334 >                  D(bug("PROBLEM: frestore_opp incr < 0\r\n"));
1335 >                        // this may be wrong, but it's never called.
1336 >                        ad -= 4;
1337 >                        d = get_long (ad);
1338 >                        if ((d & 0xff000000) != 0) {
1339 >                    if ((d & 0x00ff0000) == 0x00180000)
1340 >                                        ad -= 6 * 4;
1341 >                    else if ((d & 0x00ff0000) == 0x00380000)
1342 >                                        ad -= 14 * 4;
1343 >                    else if ((d & 0x00ff0000) == 0x00b40000)
1344 >                                        ad -= 45 * 4;
1345 >                        }
1346 >          } else {
1347 >                        d = get_long (ad);
1348 >                  D(bug("frestore_opp frame at %X = %X\r\n",ad,d));
1349 >                        ad += 4;
1350 >                        if ((d & 0xff000000) != 0) { // Not a NULL frame?
1351 >                    if ((d & 0x00ff0000) == 0x00180000) { // IDLE
1352 >                                  D(bug("frestore_opp found IDLE frame at %X\r\n",ad-4));
1353 >                                        ad += 6 * 4;
1354 >                    } else if ((d & 0x00ff0000) == 0x00380000) {// UNIMP? shouldn't it be 3C?
1355 >                                        ad += 14 * 4;
1356 >                                  D(bug("PROBLEM: frestore_opp found UNIMP? frame at %X\r\n",ad-4));
1357 >                    } else if ((d & 0x00ff0000) == 0x00b40000) {// BUSY
1358 >                                  D(bug("PROBLEM: frestore_opp found BUSY frame at %X\r\n",ad-4));
1359 >                                        ad += 45 * 4;
1360 >                                }
1361 >                        }
1362 >                }
1363 >  }
1364 >  if ((opcode & 0x38) == 0x18) {
1365 >                m68k_areg (regs, opcode & 7) = ad;
1366 >          D(bug("frestore_opp post-increment %X -> A%d\r\n",ad,opcode & 7));
1367          }
1368 <    } else {
1369 <        d = get_long (ad);
1370 <        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;
1368 >  if ((opcode & 0x38) == 0x20) {
1369 >                m68k_areg (regs, opcode & 7) = ad; // Never executed on a 68881
1370 >          D(bug("PROBLEM: frestore_opp pre-decrement\r\n"));
1371          }
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;
1372   }
1373  
1374   void fpp_opp(uae_u32 opcode, uae_u16 extra)
1375   {
1376 <    int reg;
1377 <    double src;
1376 >  int reg;
1377 >  double src;
1378  
1379 < #if DEBUG_FPP
1380 <    printf("FPP %04lx %04x at %08lx\n", opcode & 0xffff, extra & 0xffff,
1381 <           m68k_getpc () - 4);
1382 <    fflush(stdout);
1383 < #endif
1384 <    switch ((extra >> 13) & 0x7) {
1379 >  D(bug("FPP %04lx %04x at %08lx\r\n", opcode & 0xffff, extra & 0xffff,
1380 >         m68k_getpc () - 4));
1381 >
1382 >        dump_fp_regs( "START");
1383 >
1384 >  switch ((extra >> 13) & 0x7) {
1385      case 3:
1386 <        if (put_fp_value (regs.fp[(extra >> 7) & 7], opcode, extra) == 0) {
1387 <            m68k_setpc (m68k_getpc () - 4);
1388 <            op_illg (opcode);
1389 <        }
1390 <        return;
1386 >                        D(bug("FMOVE -> <ea>\r\n"));
1387 >                        if (put_fp_value (regs.fp[(extra >> 7) & 7], opcode, extra) == 0) {
1388 >                          m68k_setpc (m68k_getpc () - 4);
1389 >                                op_illg (opcode);
1390 >                        }
1391 >                        dump_fp_regs( "END  ");
1392 >                        return;
1393      case 4:
1394      case 5:
1395 <        if ((opcode & 0x38) == 0) {
1396 <            if (extra & 0x2000) {
1397 <                if (extra & 0x1000)
1398 <                    m68k_dreg (regs, opcode & 7) = regs.fpcr;
1399 <                if (extra & 0x0800)
1400 <                    m68k_dreg (regs, opcode & 7) = regs.fpsr;
1401 <                if (extra & 0x0400)
1402 <                    m68k_dreg (regs, opcode & 7) = regs.fpiar;
1403 <            } else {
1404 <                if (extra & 0x1000)
1405 <                    regs.fpcr = m68k_dreg (regs, opcode & 7);
1406 <                if (extra & 0x0800)
1407 <                    regs.fpsr = m68k_dreg (regs, opcode & 7);
1408 <                if (extra & 0x0400)
1409 <                    regs.fpiar = m68k_dreg (regs, opcode & 7);
1410 <            }
1411 <        } else if ((opcode & 0x38) == 1) {
1412 <            if (extra & 0x2000) {
1413 <                if (extra & 0x1000)
1414 <                    m68k_areg (regs, opcode & 7) = regs.fpcr;
1415 <                if (extra & 0x0800)
1416 <                    m68k_areg (regs, opcode & 7) = regs.fpsr;
1417 <                if (extra & 0x0400)
1418 <                    m68k_areg (regs, opcode & 7) = regs.fpiar;
1419 <            } else {
1420 <                if (extra & 0x1000)
1421 <                    regs.fpcr = m68k_areg (regs, opcode & 7);
1422 <                if (extra & 0x0800)
1423 <                    regs.fpsr = m68k_areg (regs, opcode & 7);
1424 <                if (extra & 0x0400)
1425 <                    regs.fpiar = m68k_areg (regs, opcode & 7);
1426 <            }
1427 <        } else if ((opcode & 0x3f) == 0x3c) {
1428 <            if ((extra & 0x2000) == 0) {
1429 <                if (extra & 0x1000)
1430 <                    regs.fpcr = next_ilong();
1431 <                if (extra & 0x0800)
1432 <                    regs.fpsr = next_ilong();
1433 <                if (extra & 0x0400)
1434 <                    regs.fpiar = next_ilong();
1435 <            }
1436 <        } else if (extra & 0x2000) {
1437 <            /* FMOVEM FPP->memory */
1438 <            uae_u32 ad;
1439 <            int incr = 0;
1440 <
1441 <            if (get_fp_ad(opcode, &ad) == 0) {
1442 <                m68k_setpc (m68k_getpc () - 4);
1443 <                op_illg (opcode);
1444 <                return;
1445 <            }
1446 <            if ((opcode & 0x38) == 0x20) {
1447 <                if (extra & 0x1000)
1448 <                    incr += 4;
1449 <                if (extra & 0x0800)
1450 <                    incr += 4;
1451 <                if (extra & 0x0400)
1452 <                    incr += 4;
1453 <            }
1454 <            ad -= incr;
1455 <            if (extra & 0x1000) {
1456 <                put_long (ad, regs.fpcr);
1457 <                ad += 4;
1458 <            }
1459 <            if (extra & 0x0800) {
1460 <                put_long (ad, regs.fpsr);
1461 <                ad += 4;
1462 <            }
1463 <            if (extra & 0x0400) {
1464 <                put_long (ad, regs.fpiar);
1465 <                ad += 4;
1466 <            }
1467 <            ad -= incr;
1468 <            if ((opcode & 0x38) == 0x18)
1469 <                m68k_areg (regs, opcode & 7) = ad;
1470 <            if ((opcode & 0x38) == 0x20)
1471 <                m68k_areg (regs, opcode & 7) = ad;
1472 <        } else {
1473 <            /* FMOVEM memory->FPP */
1474 <            uae_u32 ad;
1475 <
1476 <            if (get_fp_ad(opcode, &ad) == 0) {
1477 <                m68k_setpc (m68k_getpc () - 4);
1478 <                op_illg (opcode);
1479 <                return;
1480 <            }
1481 <            ad = (opcode & 0x38) == 0x20 ? ad - 12 : ad;
1482 <            if (extra & 0x1000) {
1483 <                regs.fpcr = get_long (ad);
1484 <                ad += 4;
1485 <            }
1486 <            if (extra & 0x0800) {
1487 <                regs.fpsr = get_long (ad);
1488 <                ad += 4;
1489 <            }
1490 <            if (extra & 0x0400) {
1491 <                regs.fpiar = get_long (ad);
1492 <                ad += 4;
1493 <            }
1494 <            if ((opcode & 0x38) == 0x18)
1495 <                m68k_areg (regs, opcode & 7) = ad;
1496 <            if ((opcode & 0x38) == 0x20)
1497 <                m68k_areg (regs, opcode & 7) = ad - 12;
1498 <        }
1499 <        return;
1395 >                        if ((opcode & 0x38) == 0) {
1396 >                                if (extra & 0x2000) { // dr bit
1397 >                                        if (extra & 0x1000) {
1398 >                                                // according to the manual, the msb bits are always zero.
1399 >                                                m68k_dreg (regs, opcode & 7) = regs.fpcr & 0xFFFF;
1400 >                                                D(bug("FMOVEM regs.fpcr (%X) -> D%d\r\n", regs.fpcr, opcode & 7));
1401 >                                        }
1402 >                                        if (extra & 0x0800) {
1403 >                                                m68k_dreg (regs, opcode & 7) = regs.fpsr;
1404 >                                                D(bug("FMOVEM regs.fpsr (%X) -> D%d\r\n", regs.fpsr, opcode & 7));
1405 >                                        }
1406 >                                        if (extra & 0x0400) {
1407 >                                                m68k_dreg (regs, opcode & 7) = regs.fpiar;
1408 >                                                D(bug("FMOVEM regs.fpiar (%X) -> D%d\r\n", regs.fpiar, opcode & 7));
1409 >                                        }
1410 >                                } else {
1411 >                                        if (extra & 0x1000) {
1412 >                                                regs.fpcr = m68k_dreg (regs, opcode & 7);
1413 >                                                D(bug("FMOVEM D%d (%X) -> regs.fpcr\r\n", opcode & 7, regs.fpcr));
1414 >                                        }
1415 >                                        if (extra & 0x0800) {
1416 >                                                regs.fpsr = m68k_dreg (regs, opcode & 7);
1417 >                                                D(bug("FMOVEM D%d (%X) -> regs.fpsr\r\n", opcode & 7, regs.fpsr));
1418 >                                        }
1419 >                                        if (extra & 0x0400) {
1420 >                                                regs.fpiar = m68k_dreg (regs, opcode & 7);
1421 >                                                D(bug("FMOVEM D%d (%X) -> regs.fpiar\r\n", opcode & 7, regs.fpiar));
1422 >                                        }
1423 >                                }
1424 >                        // } else if ((opcode & 0x38) == 1) {
1425 >                        } else if ((opcode & 0x38) == 8) {
1426 >                                if (extra & 0x2000) { // dr bit
1427 >                                        if (extra & 0x1000) {
1428 >                                                // according to the manual, the msb bits are always zero.
1429 >                                                m68k_areg (regs, opcode & 7) = regs.fpcr & 0xFFFF;
1430 >                                                D(bug("FMOVEM regs.fpcr (%X) -> A%d\r\n", regs.fpcr, opcode & 7));
1431 >                                        }
1432 >                                        if (extra & 0x0800) {
1433 >                                                m68k_areg (regs, opcode & 7) = regs.fpsr;
1434 >                                                D(bug("FMOVEM regs.fpsr (%X) -> A%d\r\n", regs.fpsr, opcode & 7));
1435 >                                        }
1436 >                                        if (extra & 0x0400) {
1437 >                                                m68k_areg (regs, opcode & 7) = regs.fpiar;
1438 >                                                D(bug("FMOVEM regs.fpiar (%X) -> A%d\r\n", regs.fpiar, opcode & 7));
1439 >                                        }
1440 >                                } else {
1441 >                                        if (extra & 0x1000) {
1442 >                                                regs.fpcr = m68k_areg (regs, opcode & 7);
1443 >                                                D(bug("FMOVEM A%d (%X) -> regs.fpcr\r\n", opcode & 7, regs.fpcr));
1444 >                                        }
1445 >                                        if (extra & 0x0800) {
1446 >                                                regs.fpsr = m68k_areg (regs, opcode & 7);
1447 >                                                D(bug("FMOVEM A%d (%X) -> regs.fpsr\r\n", opcode & 7, regs.fpsr));
1448 >                                        }
1449 >                                        if (extra & 0x0400) {
1450 >                                                regs.fpiar = m68k_areg (regs, opcode & 7);
1451 >                                                D(bug("FMOVEM A%d (%X) -> regs.fpiar\r\n", opcode & 7, regs.fpiar));
1452 >                                        }
1453 >                                }
1454 >                        } else if ((opcode & 0x3f) == 0x3c) {
1455 >                          if ((extra & 0x2000) == 0) {
1456 >                                        if (extra & 0x1000) {
1457 >                                                regs.fpcr = next_ilong();
1458 >                                                D(bug("FMOVEM #<%X> -> regs.fpcr\r\n", regs.fpcr));
1459 >                                        }
1460 >                                        if (extra & 0x0800) {
1461 >                                                regs.fpsr = next_ilong();
1462 >                                                D(bug("FMOVEM #<%X> -> regs.fpsr\r\n", regs.fpsr));
1463 >                                        }
1464 >                                        if (extra & 0x0400) {
1465 >                                                regs.fpiar = next_ilong();
1466 >                                                D(bug("FMOVEM #<%X> -> regs.fpiar\r\n", regs.fpiar));
1467 >                                        }
1468 >                                }
1469 >                        } else if (extra & 0x2000) {
1470 >                                /* FMOVEM FPP->memory */
1471 >
1472 >                                uae_u32 ad;
1473 >                                int incr = 0;
1474 >
1475 >                                if (get_fp_ad(opcode, &ad) == 0) {
1476 >                                        m68k_setpc (m68k_getpc () - 4);
1477 >                                        op_illg (opcode);
1478 >                                        dump_fp_regs( "END  ");
1479 >                                        return;
1480 >                    }
1481 >                                if ((opcode & 0x38) == 0x20) {
1482 >                                        if (extra & 0x1000)
1483 >                                                incr += 4;
1484 >                                        if (extra & 0x0800)
1485 >                                                incr += 4;
1486 >                                        if (extra & 0x0400)
1487 >                                                incr += 4;
1488 >                                }
1489 >                                ad -= incr;
1490 >                                if (extra & 0x1000) {
1491 >                                        // according to the manual, the msb bits are always zero.
1492 >                                        put_long (ad, regs.fpcr & 0xFFFF);
1493 >                                        D(bug("FMOVEM regs.fpcr (%X) -> mem %X\r\n", regs.fpcr, ad ));
1494 >                                        ad += 4;
1495 >                                }
1496 >                                if (extra & 0x0800) {
1497 >                                        put_long (ad, regs.fpsr);
1498 >                                        D(bug("FMOVEM regs.fpsr (%X) -> mem %X\r\n", regs.fpsr, ad ));
1499 >                                        ad += 4;
1500 >                                }
1501 >                                if (extra & 0x0400) {
1502 >                                        put_long (ad, regs.fpiar);
1503 >                                        D(bug("FMOVEM regs.fpiar (%X) -> mem %X\r\n", regs.fpiar, ad ));
1504 >                                        ad += 4;
1505 >                                }
1506 >                                ad -= incr;
1507 >                                if ((opcode & 0x38) == 0x18) // post-increment?
1508 >                                        m68k_areg (regs, opcode & 7) = ad;
1509 >                                if ((opcode & 0x38) == 0x20) // pre-decrement?
1510 >                                        m68k_areg (regs, opcode & 7) = ad;
1511 >                        } else {
1512 >                                /* FMOVEM memory->FPP */
1513 >
1514 >                                uae_u32 ad;
1515 >
1516 >                                if (get_fp_ad(opcode, &ad) == 0) {
1517 >                                        m68k_setpc (m68k_getpc () - 4);
1518 >                                        op_illg (opcode);
1519 >                                        dump_fp_regs( "END  ");
1520 >                                        return;
1521 >                                }
1522 >                                
1523 >                                // ad = (opcode & 0x38) == 0x20 ? ad - 12 : ad;
1524 >                                int incr = 0;
1525 >                                if((opcode & 0x38) == 0x20) {
1526 >                                        if (extra & 0x1000)
1527 >                                                incr += 4;
1528 >                                        if (extra & 0x0800)
1529 >                                                incr += 4;
1530 >                                        if (extra & 0x0400)
1531 >                                                incr += 4;
1532 >                                        ad = ad - incr;
1533 >                                }
1534 >
1535 >                                if (extra & 0x1000) {
1536 >                                        regs.fpcr = get_long (ad);
1537 >                                        D(bug("FMOVEM mem %X (%X) -> regs.fpcr\r\n", ad, regs.fpcr ));
1538 >                                        ad += 4;
1539 >                                }
1540 >                                if (extra & 0x0800) {
1541 >                                        regs.fpsr = get_long (ad);
1542 >                                        D(bug("FMOVEM mem %X (%X) -> regs.fpsr\r\n", ad, regs.fpsr ));
1543 >                                        ad += 4;
1544 >                                }
1545 >                                if (extra & 0x0400) {
1546 >                                        regs.fpiar = get_long (ad);
1547 >                                        D(bug("FMOVEM mem %X (%X) -> regs.fpiar\r\n", ad, regs.fpiar ));
1548 >                                        ad += 4;
1549 >                                }
1550 >                                if ((opcode & 0x38) == 0x18) // post-increment?
1551 >                                        m68k_areg (regs, opcode & 7) = ad;
1552 >                                if ((opcode & 0x38) == 0x20) // pre-decrement?
1553 >                                        // m68k_areg (regs, opcode & 7) = ad - 12;
1554 >                                        m68k_areg (regs, opcode & 7) = ad - incr;
1555 >                        }
1556 >                        dump_fp_regs( "END  ");
1557 >                        return;
1558      case 6:
1559      case 7:
1560 <        {
1560 >                        {
1561              uae_u32 ad, list = 0;
1562              int incr = 0;
1563              if (extra & 0x2000) {
1564 <                /* FMOVEM FPP->memory */
1565 <                if (get_fp_ad(opcode, &ad) == 0) {
1566 <                    m68k_setpc (m68k_getpc () - 4);
1567 <                    op_illg (opcode);
1568 <                    return;
1569 <                }
1570 <                switch ((extra >> 11) & 3) {
1571 <                case 0: /* static pred */
1572 <                    list = extra & 0xff;
1573 <                    incr = -1;
1574 <                    break;
1575 <                case 1: /* dynamic pred */
1576 <                    list = m68k_dreg (regs, (extra >> 4) & 3) & 0xff;
1577 <                    incr = -1;
1578 <                    break;
1579 <                case 2: /* static postinc */
1580 <                    list = extra & 0xff;
1581 <                    incr = 1;
1582 <                    break;
1583 <                case 3: /* dynamic postinc */
1584 <                    list = m68k_dreg (regs, (extra >> 4) & 3) & 0xff;
1585 <                    incr = 1;
1586 <                    break;
1587 <                }
1588 <                while (list) {
1589 <                    uae_u32 wrd1, wrd2, wrd3;
1590 <                    if (incr < 0) {
1591 <                        from_exten(regs.fp[fpp_movem_index2[list]],
1592 <                                   &wrd1, &wrd2, &wrd3);
1593 <                        ad -= 4;
1594 <                        put_long (ad, wrd3);
1595 <                        ad -= 4;
1596 <                        put_long (ad, wrd2);
1597 <                        ad -= 4;
1598 <                        put_long (ad, wrd1);
1599 <                    } else {
1600 <                        from_exten(regs.fp[fpp_movem_index1[list]],
1601 <                                   &wrd1, &wrd2, &wrd3);
1602 <                        put_long (ad, wrd1);
1603 <                        ad += 4;
1604 <                        put_long (ad, wrd2);
1605 <                        ad += 4;
1606 <                        put_long (ad, wrd3);
1607 <                        ad += 4;
1608 <                    }
1609 <                    list = fpp_movem_next[list];
1610 <                }
1611 <                if ((opcode & 0x38) == 0x18)
1612 <                    m68k_areg (regs, opcode & 7) = ad;
1613 <                if ((opcode & 0x38) == 0x20)
1614 <                    m68k_areg (regs, opcode & 7) = ad;
1615 <            } else {
1616 <                /* FMOVEM memory->FPP */
1617 <                if (get_fp_ad(opcode, &ad) == 0) {
1618 <                    m68k_setpc (m68k_getpc () - 4);
1619 <                    op_illg (opcode);
1620 <                    return;
1621 <                }
1622 <                switch ((extra >> 11) & 3) {
1623 <                case 0: /* static pred */
1624 <                    list = extra & 0xff;
1625 <                    incr = -1;
1626 <                    break;
1627 <                case 1: /* dynamic pred */
1628 <                    list = m68k_dreg (regs, (extra >> 4) & 3) & 0xff;
1629 <                    incr = -1;
1630 <                    break;
1631 <                case 2: /* static postinc */
1632 <                    list = extra & 0xff;
1633 <                    incr = 1;
1634 <                    break;
1635 <                case 3: /* dynamic postinc */
1636 <                    list = m68k_dreg (regs, (extra >> 4) & 3) & 0xff;
1637 <                    incr = 1;
1638 <                    break;
1639 <                }
1640 <                while (list) {
1641 <                    uae_u32 wrd1, wrd2, wrd3;
1642 <                    if (incr < 0) {
1643 <                        ad -= 4;
1644 <                        wrd3 = get_long (ad);
1645 <                        ad -= 4;
1646 <                        wrd2 = get_long (ad);
1647 <                        ad -= 4;
1648 <                        wrd1 = get_long (ad);
1649 <                        regs.fp[fpp_movem_index2[list]] = to_exten (wrd1, wrd2, wrd3);
1650 <                    } else {
1651 <                        wrd1 = get_long (ad);
1652 <                        ad += 4;
1653 <                        wrd2 = get_long (ad);
1654 <                        ad += 4;
1655 <                        wrd3 = get_long (ad);
1656 <                        ad += 4;
1657 <                        regs.fp[fpp_movem_index1[list]] = to_exten (wrd1, wrd2, wrd3);
1658 <                    }
1659 <                    list = fpp_movem_next[list];
1660 <                }
1661 <                if ((opcode & 0x38) == 0x18)
1662 <                    m68k_areg (regs, opcode & 7) = ad;
1663 <                if ((opcode & 0x38) == 0x20)
1664 <                    m68k_areg (regs, opcode & 7) = ad;
1564 >                                /* FMOVEM FPP->memory */
1565 >
1566 >                                D(bug("FMOVEM FPP->memory\r\n"));
1567 >
1568 >                                if (get_fp_ad(opcode, &ad) == 0) {
1569 >                                        m68k_setpc (m68k_getpc () - 4);
1570 >                                        op_illg (opcode);
1571 >                                        dump_fp_regs( "END  ");
1572 >                                        return;
1573 >                                }
1574 >                                switch ((extra >> 11) & 3) {
1575 >                                        case 0: /* static pred */
1576 >                                                list = extra & 0xff;
1577 >                                                incr = -1;
1578 >                                                break;
1579 >                                        case 1: /* dynamic pred */
1580 >                                                list = m68k_dreg (regs, (extra >> 4) & 3) & 0xff;
1581 >                                                incr = -1;
1582 >                                                break;
1583 >                                        case 2: /* static postinc */
1584 >                                                list = extra & 0xff;
1585 >                                                incr = 1;
1586 >                                                break;
1587 >                                        case 3: /* dynamic postinc */
1588 >                                                list = m68k_dreg (regs, (extra >> 4) & 3) & 0xff;
1589 >                                                incr = 1;
1590 >                                                break;
1591 >                                }
1592 >
1593 >                                if (incr < 0) {
1594 >                                        for(reg=7; reg>=0; reg--) {
1595 >                                                uae_u32 wrd1, wrd2, wrd3;
1596 >                                                if( list & 0x80 ) {
1597 >                                                        from_exten(regs.fp[reg],&wrd1, &wrd2, &wrd3);
1598 >                                                        ad -= 4;
1599 >                                                        put_long (ad, wrd3);
1600 >                                                        ad -= 4;
1601 >                                                        put_long (ad, wrd2);
1602 >                                                        ad -= 4;
1603 >                                                        put_long (ad, wrd1);
1604 >                                                }
1605 >                                                list <<= 1;
1606 >                                        }
1607 >                                } else {
1608 >                                        for(reg=0; reg<8; reg++) {
1609 >                                                uae_u32 wrd1, wrd2, wrd3;
1610 >                                                if( list & 0x80 ) {
1611 >                                                        from_exten(regs.fp[reg],&wrd1, &wrd2, &wrd3);
1612 >                                                        put_long (ad, wrd3);
1613 >                                                        ad += 4;
1614 >                                                        put_long (ad, wrd2);
1615 >                                                        ad += 4;
1616 >                                                        put_long (ad, wrd1);
1617 >                                                        ad += 4;
1618 >                                                }
1619 >                                                list <<= 1;
1620 >                                        }
1621 >                                }
1622 >
1623 >                                /*
1624 >                                while (list) {
1625 >                                        uae_u32 wrd1, wrd2, wrd3;
1626 >                                        if (incr < 0) {
1627 >                                                from_exten(regs.fp[fpp_movem_index2[list]],
1628 >                                                 &wrd1, &wrd2, &wrd3);
1629 >                                                ad -= 4;
1630 >                                                put_long (ad, wrd3);
1631 >                                                ad -= 4;
1632 >                                                put_long (ad, wrd2);
1633 >                                                ad -= 4;
1634 >                                                put_long (ad, wrd1);
1635 >                                        } else {
1636 >                                                from_exten(regs.fp[fpp_movem_index1[list]],
1637 >                                                 &wrd1, &wrd2, &wrd3);
1638 >                                                put_long (ad, wrd1);
1639 >                                                ad += 4;
1640 >                                                put_long (ad, wrd2);
1641 >                                                ad += 4;
1642 >                                                put_long (ad, wrd3);
1643 >                                                ad += 4;
1644 >                                        }
1645 >                                        list = fpp_movem_next[list];
1646 >                                }
1647 >                                */
1648 >                                if ((opcode & 0x38) == 0x18) // post-increment?
1649 >                                        m68k_areg (regs, opcode & 7) = ad;
1650 >                                if ((opcode & 0x38) == 0x20) // pre-decrement?
1651 >                                        m68k_areg (regs, opcode & 7) = ad;
1652 >                  } else {
1653 >                                /* FMOVEM memory->FPP */
1654 >
1655 >                                D(bug("FMOVEM memory->FPP\r\n"));
1656 >
1657 >                                if (get_fp_ad(opcode, &ad) == 0) {
1658 >                                        m68k_setpc (m68k_getpc () - 4);
1659 >                                        op_illg (opcode);
1660 >                                        dump_fp_regs( "END  ");
1661 >                                        return;
1662 >                                }
1663 >                                switch ((extra >> 11) & 3) {
1664 >                                        case 0: /* static pred */
1665 >                                                D(bug("memory->FMOVEM FPP not legal mode.\r\n"));
1666 >                                                list = extra & 0xff;
1667 >                                                incr = -1;
1668 >                                                break;
1669 >                                        case 1: /* dynamic pred */
1670 >                                                D(bug("memory->FMOVEM FPP not legal mode.\r\n"));
1671 >                                                list = m68k_dreg (regs, (extra >> 4) & 3) & 0xff;
1672 >                                                incr = -1;
1673 >                                    break;
1674 >                                        case 2: /* static postinc */
1675 >                                    list = extra & 0xff;
1676 >                                                incr = 1;
1677 >                                                break;
1678 >                                        case 3: /* dynamic postinc */
1679 >                                                list = m68k_dreg (regs, (extra >> 4) & 3) & 0xff;
1680 >                                                incr = 1;
1681 >                                                break;
1682 >                                }
1683 >
1684 >                                /**/
1685 >                                if (incr < 0) {
1686 >                                        // not reached
1687 >                                        for(reg=7; reg>=0; reg--) {
1688 >                                                uae_u32 wrd1, wrd2, wrd3;
1689 >                                                if( list & 0x80 ) {
1690 >                                                        wrd1 = get_long (ad);
1691 >                                                        ad -= 4;
1692 >                                                        wrd2 = get_long (ad);
1693 >                                                        ad -= 4;
1694 >                                                        wrd3 = get_long (ad);
1695 >                                                        ad -= 4;
1696 >                                                        regs.fp[reg] = to_exten (wrd1, wrd2, wrd3);
1697 >                                                }
1698 >                                                list <<= 1;
1699 >                                        }
1700 >                                } else {
1701 >                                        for(reg=0; reg<8; reg++) {
1702 >                                                uae_u32 wrd1, wrd2, wrd3;
1703 >                                                if( list & 0x80 ) {
1704 >                                                        wrd1 = get_long (ad);
1705 >                                                        ad += 4;
1706 >                                                        wrd2 = get_long (ad);
1707 >                                                        ad += 4;
1708 >                                                        wrd3 = get_long (ad);
1709 >                                                        ad += 4;
1710 >                                                        regs.fp[reg] = to_exten (wrd1, wrd2, wrd3);
1711 >                                                }
1712 >                                                list <<= 1;
1713 >                                        }
1714 >                                }
1715 >                                /**/
1716 >
1717 >                                /*
1718 >                                while (list) {
1719 >                                        uae_u32 wrd1, wrd2, wrd3;
1720 >                                        if (incr < 0) {
1721 >                                                ad -= 4;
1722 >                                                wrd3 = get_long (ad);
1723 >                                                ad -= 4;
1724 >                                                wrd2 = get_long (ad);
1725 >                                                ad -= 4;
1726 >                                                wrd1 = get_long (ad);
1727 >                                                regs.fp[fpp_movem_index2[list]] = to_exten (wrd1, wrd2, wrd3);
1728 >                            } else {
1729 >                                                wrd1 = get_long (ad);
1730 >                                                ad += 4;
1731 >                                                wrd2 = get_long (ad);
1732 >                                                ad += 4;
1733 >                                                wrd3 = get_long (ad);
1734 >                                                ad += 4;
1735 >                                                regs.fp[fpp_movem_index1[list]] = to_exten (wrd1, wrd2, wrd3);
1736 >                                        }
1737 >                                        list = fpp_movem_next[list];
1738 >                                }
1739 >                                */
1740 >                                if ((opcode & 0x38) == 0x18) // post-increment?
1741 >                            m68k_areg (regs, opcode & 7) = ad;
1742 >                                if ((opcode & 0x38) == 0x20) // pre-decrement?
1743 >                            m68k_areg (regs, opcode & 7) = ad;
1744              }
1745 <        }
1746 <        return;
1745 >                        }
1746 >                        dump_fp_regs( "END  ");
1747 >                        return;
1748      case 0:
1749      case 2:
1750 <        reg = (extra >> 7) & 7;
1751 <        if ((extra & 0xfc00) == 0x5c00) {
1752 <            switch (extra & 0x7f) {
1753 <            case 0x00:
1754 <                regs.fp[reg] = 4.0 * atan(1.0);
1755 <                break;
1756 <            case 0x0b:
1757 <                regs.fp[reg] = log10 (2.0);
1758 <                break;
1759 <            case 0x0c:
1760 <                regs.fp[reg] = exp (1.0);
1761 <                break;
1762 <            case 0x0d:
1763 <                regs.fp[reg] = log (exp (1.0)) / log (2.0);
1764 <                break;
1765 <            case 0x0e:
1766 <                regs.fp[reg] = log (exp (1.0)) / log (10.0);
1767 <                break;
1768 <            case 0x0f:
1769 <                regs.fp[reg] = 0.0;
1770 <                break;
1771 <            case 0x30:
1772 <                regs.fp[reg] = log (2.0);
1773 <                break;
1774 <            case 0x31:
1775 <                regs.fp[reg] = log (10.0);
1776 <                break;
1777 <            case 0x32:
1778 <                regs.fp[reg] = 1.0e0;
1779 <                break;
1780 <            case 0x33:
1781 <                regs.fp[reg] = 1.0e1;
1782 <                break;
1783 <            case 0x34:
1784 <                regs.fp[reg] = 1.0e2;
1785 <                break;
1786 <            case 0x35:
1787 <                regs.fp[reg] = 1.0e4;
1788 <                break;
1789 <            case 0x36:
1790 <                regs.fp[reg] = 1.0e8;
1791 <                break;
1792 <            case 0x37:
1793 <                regs.fp[reg] = 1.0e16;
1794 <                break;
1795 <            case 0x38:
1796 <                regs.fp[reg] = 1.0e32;
1797 <                break;
1798 <            case 0x39:
1799 <                regs.fp[reg] = 1.0e64;
1800 <                break;
1801 <            case 0x3a:
1802 <                regs.fp[reg] = 1.0e128;
1803 <                break;
1804 <            case 0x3b:
1805 <                regs.fp[reg] = 1.0e256;
1806 <                break;
1750 >                        reg = (extra >> 7) & 7;
1751 >                        if ((extra & 0xfc00) == 0x5c00) {
1752 >                                D(bug("FMOVECR memory->FPP\r\n"));
1753 >                                switch (extra & 0x7f) {
1754 >                                        case 0x00:
1755 >                                                // regs.fp[reg] = 4.0 * atan(1.0);
1756 >                                                regs.fp[reg] = 3.1415926535897932384626433832795;
1757 >                                                D(bug("FP const: Pi\r\n"));
1758 >                                                break;
1759 >                                        case 0x0b:
1760 >                                                // regs.fp[reg] = log10 (2.0);
1761 >                                                regs.fp[reg] = 0.30102999566398119521373889472449;
1762 >                                                D(bug("FP const: Log 10 (2)\r\n"));
1763 >                                                break;
1764 >                                        case 0x0c:
1765 >                                                // regs.fp[reg] = exp (1.0);
1766 >                                                regs.fp[reg] = 2.7182818284590452353602874713527;
1767 >                                                D(bug("FP const: e\r\n"));
1768 >                                                break;
1769 >                                        case 0x0d:
1770 >                                                // regs.fp[reg] = log (exp (1.0)) / log (2.0);
1771 >                                                regs.fp[reg] = 1.4426950408889634073599246810019;
1772 >                                                D(bug("FP const: Log 2 (e)\r\n"));
1773 >                                                break;
1774 >                                        case 0x0e:
1775 >                                                // regs.fp[reg] = log (exp (1.0)) / log (10.0);
1776 >                                                regs.fp[reg] = 0.43429448190325182765112891891661;
1777 >                                                D(bug("FP const: Log 10 (e)\r\n"));
1778 >                                                break;
1779 >                                        case 0x0f:
1780 >                                                regs.fp[reg] = 0.0;
1781 >                                                D(bug("FP const: zero\r\n"));
1782 >                                                break;
1783 >                                        case 0x30:
1784 >                                                // regs.fp[reg] = log (2.0);
1785 >                                                regs.fp[reg] = 0.69314718055994530941723212145818;
1786 >                                                D(bug("FP const: ln(2)\r\n"));
1787 >                                                break;
1788 >                                        case 0x31:
1789 >                                                // regs.fp[reg] = log (10.0);
1790 >                                                regs.fp[reg] = 2.3025850929940456840179914546844;
1791 >                                                D(bug("FP const: ln(10)\r\n"));
1792 >                                                break;
1793 >                                        case 0x32:
1794 >                                                // ??
1795 >                                                regs.fp[reg] = 1.0e0;
1796 >                                                D(bug("FP const: 1.0e0\r\n"));
1797 >                                                break;
1798 >                                        case 0x33:
1799 >                                                regs.fp[reg] = 1.0e1;
1800 >                                                D(bug("FP const: 1.0e1\r\n"));
1801 >                                                break;
1802 >                                        case 0x34:
1803 >                                                regs.fp[reg] = 1.0e2;
1804 >                                                D(bug("FP const: 1.0e2\r\n"));
1805 >                                                break;
1806 >                                        case 0x35:
1807 >                                                regs.fp[reg] = 1.0e4;
1808 >                                                D(bug("FP const: 1.0e4\r\n"));
1809 >                                                break;
1810 >                                        case 0x36:
1811 >                                                regs.fp[reg] = 1.0e8;
1812 >                                                D(bug("FP const: 1.0e8\r\n"));
1813 >                                                break;
1814 >                                        case 0x37:
1815 >                                                regs.fp[reg] = 1.0e16;
1816 >                                                D(bug("FP const: 1.0e16\r\n"));
1817 >                                                break;
1818 >                                        case 0x38:
1819 >                                                regs.fp[reg] = 1.0e32;
1820 >                                                D(bug("FP const: 1.0e32\r\n"));
1821 >                                                break;
1822 >                                        case 0x39:
1823 >                                                regs.fp[reg] = 1.0e64;
1824 >                                                D(bug("FP const: 1.0e64\r\n"));
1825 >                                                break;
1826 >                                        case 0x3a:
1827 >                                                regs.fp[reg] = 1.0e128;
1828 >                                                D(bug("FP const: 1.0e128\r\n"));
1829 >                                                break;
1830 >                                        case 0x3b:
1831 >                                                regs.fp[reg] = 1.0e256;
1832 >                                                D(bug("FP const: 1.0e256\r\n"));
1833 >                                                break;
1834 >                                        
1835 >                                        // Valid for 64 bits only (see fpu.cpp)
1836   #if 0
1837 <            case 0x3c:
1838 <                regs.fp[reg] = 1.0e512;
1839 <                break;
1840 <            case 0x3d:
1841 <                regs.fp[reg] = 1.0e1024;
1842 <                break;
1843 <            case 0x3e:
1844 <                regs.fp[reg] = 1.0e2048;
1845 <                break;
1846 <            case 0x3f:
1847 <                regs.fp[reg] = 1.0e4096;
1848 <                break;
1837 >                                        case 0x3c:
1838 >                                                regs.fp[reg] = 1.0e512;
1839 >                                                D(bug("FP const: 1.0e512\r\n"));
1840 >                                                break;
1841 >                                        case 0x3d:
1842 >                                                regs.fp[reg] = 1.0e1024;
1843 >                                                D(bug("FP const: 1.0e1024\r\n"));
1844 >                                                break;
1845 >                                        case 0x3e:
1846 >                                                regs.fp[reg] = 1.0e2048;
1847 >                                                D(bug("FP const: 1.0e2048\r\n"));
1848 >                                                break;
1849 >                                        case 0x3f:
1850 >                                                regs.fp[reg] = 1.0e4096;
1851 >                                                D(bug("FP const: 1.0e4096\r\n"));
1852 >                                                break;
1853   #endif
1854 <            default:
1855 <                m68k_setpc (m68k_getpc () - 4);
1856 <                op_illg (opcode);
1857 <                break;
1858 <            }
1859 <            return;
1860 <        }
1861 <        if (get_fp_value (opcode, extra, &src) == 0) {
1862 <            m68k_setpc (m68k_getpc () - 4);
1863 <            op_illg (opcode);
1864 <            return;
1865 <        }
1866 <        switch (extra & 0x7f) {
1867 <        case 0x00:              /* FMOVE */
1868 <            regs.fp[reg] = src;
1869 <            break;
1870 <        case 0x01:              /* FINT */
1871 <            regs.fp[reg] = (int) (src + 0.5);
1872 <            regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
1873 <                (regs.fp[reg] < 0 ? 0x8000000 : 0);
1874 <            break;
1875 <        case 0x02:              /* FSINH */
1876 <            regs.fp[reg] = sinh (src);
1877 <            regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
1878 <                (regs.fp[reg] < 0 ? 0x8000000 : 0);
1879 <            break;
1880 <        case 0x03:              /* FINTRZ */
1881 <            regs.fp[reg] = (int) src;
1882 <            regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
1883 <                (regs.fp[reg] < 0 ? 0x8000000 : 0);
1884 <            break;
1885 <        case 0x04:              /* FSQRT */
1886 <            regs.fp[reg] = sqrt (src);
1887 <            regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
1888 <                (regs.fp[reg] < 0 ? 0x8000000 : 0);
1889 <            break;
1890 <        case 0x06:              /* FLOGNP1 */
1891 <            regs.fp[reg] = log (src + 1.0);
1892 <            regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
1893 <                (regs.fp[reg] < 0 ? 0x8000000 : 0);
1894 <            break;
1895 <        case 0x08:              /* FETOXM1 */
1896 <            regs.fp[reg] = exp (src) - 1.0;
1897 <            regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
1898 <                (regs.fp[reg] < 0 ? 0x8000000 : 0);
1899 <            break;
1900 <        case 0x09:              /* FTANH */
1901 <            regs.fp[reg] = tanh (src);
1902 <            regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
1903 <                (regs.fp[reg] < 0 ? 0x8000000 : 0);
1904 <            break;
1905 <        case 0x0a:              /* FATAN */
1906 <            regs.fp[reg] = atan (src);
1907 <            regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
1908 <                (regs.fp[reg] < 0 ? 0x8000000 : 0);
1909 <            break;
1910 <        case 0x0c:              /* FASIN */
1911 <            regs.fp[reg] = asin (src);
1912 <            regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
1913 <                (regs.fp[reg] < 0 ? 0x8000000 : 0);
1914 <            break;
1915 <        case 0x0d:              /* FATANH */
1854 >                                        default:
1855 >                                                m68k_setpc (m68k_getpc () - 4);
1856 >                                                op_illg (opcode);
1857 >                                                break;
1858 >                                }
1859 >                                // these *do* affect the status reg
1860 >                                MAKE_FPSR(regs.fpsr,regs.fp[reg]);
1861 >                                dump_fp_regs( "END  ");
1862 >                                return;
1863 >                        }
1864 >                        if (get_fp_value (opcode, extra, &src) == 0) {
1865 >                                m68k_setpc (m68k_getpc () - 4);
1866 >                                op_illg (opcode);
1867 >                                dump_fp_regs( "END  ");
1868 >                                return;
1869 >                        }
1870 >
1871 >                        switch (extra & 0x7f) {
1872 >                                case 0x00:              /* FMOVE */
1873 >                                        D(bug("FMOVE %.04f\r\n",(float)src));
1874 >                                        regs.fp[reg] = src;
1875 >                                        // <ea> -> reg DOES affect the status reg
1876 >                                        MAKE_FPSR(regs.fpsr,regs.fp[reg]);
1877 >                                        break;
1878 >                                case 0x01:              /* FINT */
1879 >                                        D(bug("FINT %.04f\r\n",(float)src));
1880 >                                        // regs.fp[reg] = (int) (src + 0.5);
1881 >                                        switch(regs.fpcr & 0x30) {
1882 >                                                case ROUND_TO_ZERO:
1883 >                                                        regs.fp[reg] = round_to_zero(src);
1884 >                                                        break;
1885 >                                                case ROUND_TO_NEGATIVE_INFINITY:
1886 >                                                        regs.fp[reg] = floor(src);
1887 >                                                        break;
1888 >                                                case ROUND_TO_NEAREST:
1889 >                                                        regs.fp[reg] = round_to_nearest(src);
1890 >                                                        break;
1891 >                                                case ROUND_TO_POSITIVE_INFINITY:
1892 >                                                        regs.fp[reg] = ceil(src);
1893 >                                                        break;
1894 >                                        }
1895 >                                        MAKE_FPSR(regs.fpsr,regs.fp[reg]);
1896 >                                        break;
1897 >                                case 0x02:              /* FSINH */
1898 >                                        D(bug("FSINH %.04f\r\n",(float)src));
1899 >                                        regs.fp[reg] = sinh (src);
1900 >                                        MAKE_FPSR(regs.fpsr,regs.fp[reg]);
1901 >                                        break;
1902 >                                case 0x03:              /* FINTRZ */
1903 >                                        D(bug("FINTRZ %.04f\r\n",(float)src));
1904 >                                        // regs.fp[reg] = (int) src;
1905 >                                        regs.fp[reg] = round_to_zero(src);
1906 >                                        MAKE_FPSR(regs.fpsr,regs.fp[reg]);
1907 >                                        break;
1908 >                                case 0x04:              /* FSQRT */
1909 >                                        D(bug("FSQRT %.04f\r\n",(float)src));
1910 >                                        regs.fp[reg] = sqrt (src);
1911 >                                        MAKE_FPSR(regs.fpsr,regs.fp[reg]);
1912 >                                        break;
1913 >                                case 0x06:              /* FLOGNP1 */
1914 >                                        D(bug("FLOGNP1 %.04f\r\n",(float)src));
1915 >                                        regs.fp[reg] = log (src + 1.0);
1916 >                                        MAKE_FPSR(regs.fpsr,regs.fp[reg]);
1917 >                                        break;
1918 >                                case 0x08:              /* FETOXM1 */
1919 >                                        D(bug("FETOXM1 %.04f\r\n",(float)src));
1920 >                                        regs.fp[reg] = exp (src) - 1.0;
1921 >                                        MAKE_FPSR(regs.fpsr,regs.fp[reg]);
1922 >                                        break;
1923 >                                case 0x09:              /* FTANH */
1924 >                                        D(bug("FTANH %.04f\r\n",(float)src));
1925 >                                        regs.fp[reg] = tanh (src);
1926 >                                        MAKE_FPSR(regs.fpsr,regs.fp[reg]);
1927 >                                        break;
1928 >                                case 0x0a:              /* FATAN */
1929 >                                        D(bug("FATAN %.04f\r\n",(float)src));
1930 >                                        regs.fp[reg] = atan (src);
1931 >                                        MAKE_FPSR(regs.fpsr,regs.fp[reg]);
1932 >                                        break;
1933 >                                case 0x0c:              /* FASIN */
1934 >                                        D(bug("FASIN %.04f\r\n",(float)src));
1935 >                                        regs.fp[reg] = asin (src);
1936 >                                        MAKE_FPSR(regs.fpsr,regs.fp[reg]);
1937 >                                        break;
1938 >                                case 0x0d:              /* FATANH */
1939 >                                        D(bug("FATANH %.04f\r\n",(float)src));
1940   #if 1                           /* The BeBox doesn't have atanh, and it isn't in the HPUX libm either */
1941 <            regs.fp[reg] = log ((1 + src) / (1 - src)) / 2;
1941 >                                        regs.fp[reg] = log ((1 + src) / (1 - src)) / 2;
1942   #else
1943 <            regs.fp[reg] = atanh (src);
1943 >                                        regs.fp[reg] = atanh (src);
1944   #endif
1945 <            regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
1946 <                (regs.fp[reg] < 0 ? 0x8000000 : 0);
1947 <            break;
1948 <        case 0x0e:              /* FSIN */
1949 <            regs.fp[reg] = sin (src);
1950 <            regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
1951 <                (regs.fp[reg] < 0 ? 0x8000000 : 0);
1952 <            break;
1953 <        case 0x0f:              /* FTAN */
1954 <            regs.fp[reg] = tan (src);
1955 <            regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
1956 <                (regs.fp[reg] < 0 ? 0x8000000 : 0);
1957 <            break;
1958 <        case 0x10:              /* FETOX */
1959 <            regs.fp[reg] = exp (src);
1960 <            regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
1961 <                (regs.fp[reg] < 0 ? 0x8000000 : 0);
1962 <            break;
1963 <        case 0x11:              /* FTWOTOX */
1964 <            regs.fp[reg] = pow(2.0, src);
1965 <            regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
1966 <                (regs.fp[reg] < 0 ? 0x8000000 : 0);
1967 <            break;
1968 <        case 0x12:              /* FTENTOX */
1969 <            regs.fp[reg] = pow(10.0, src);
1970 <            regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
1971 <                (regs.fp[reg] < 0 ? 0x8000000 : 0);
1972 <            break;
1973 <        case 0x14:              /* FLOGN */
1974 <            regs.fp[reg] = log (src);
1975 <            regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
1976 <                (regs.fp[reg] < 0 ? 0x8000000 : 0);
1977 <            break;
1978 <        case 0x15:              /* FLOG10 */
1979 <            regs.fp[reg] = log10 (src);
1980 <            regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
1981 <                (regs.fp[reg] < 0 ? 0x8000000 : 0);
1982 <            break;
1983 <        case 0x16:              /* FLOG2 */
1984 <            regs.fp[reg] = log (src) / log (2.0);
1985 <            regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
1986 <                (regs.fp[reg] < 0 ? 0x8000000 : 0);
1987 <            break;
1988 <        case 0x18:              /* FABS */
1989 <            regs.fp[reg] = src < 0 ? -src : src;
1990 <            regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
1991 <                (regs.fp[reg] < 0 ? 0x8000000 : 0);
1992 <            break;
1993 <        case 0x19:              /* FCOSH */
1994 <            regs.fp[reg] = cosh(src);
1995 <            regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
1996 <                (regs.fp[reg] < 0 ? 0x8000000 : 0);
1997 <            break;
1998 <        case 0x1a:              /* FNEG */
1999 <            regs.fp[reg] = -src;
2000 <            regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
2001 <                (regs.fp[reg] < 0 ? 0x8000000 : 0);
2002 <            break;
2003 <        case 0x1c:              /* FACOS */
2004 <            regs.fp[reg] = acos(src);
2005 <            regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
2006 <                (regs.fp[reg] < 0 ? 0x8000000 : 0);
2007 <            break;
2008 <        case 0x1d:              /* FCOS */
2009 <            regs.fp[reg] = cos(src);
2010 <            regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
2011 <                (regs.fp[reg] < 0 ? 0x8000000 : 0);
2012 <            break;
2013 <        case 0x1e:              /* FGETEXP */
2014 <            {
2015 <                int expon;
2016 <                frexp (src, &expon);
2017 <                regs.fp[reg] = (double) (expon - 1);
2018 <                regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
2019 <                    (regs.fp[reg] < 0 ? 0x8000000 : 0);
2020 <            }
2021 <            break;
2022 <        case 0x1f:              /* FGETMAN */
2023 <            {
2024 <                int expon;
2025 <                regs.fp[reg] = frexp (src, &expon) * 2.0;
2026 <                regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
2027 <                    (regs.fp[reg] < 0 ? 0x8000000 : 0);
2028 <            }
2029 <            break;
2030 <        case 0x20:              /* FDIV */
2031 <            regs.fp[reg] /= src;
2032 <            regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
2033 <                (regs.fp[reg] < 0 ? 0x8000000 : 0);
2034 <            break;
2035 <        case 0x21:              /* FMOD */
2036 <            regs.fp[reg] = regs.fp[reg] -
2037 <                (double) ((int) (regs.fp[reg] / src)) * src;
2038 <            regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
2039 <                (regs.fp[reg] < 0 ? 0x8000000 : 0);
2040 <            break;
2041 <        case 0x22:              /* FADD */
2042 <            regs.fp[reg] += src;
2043 <            regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
2044 <                (regs.fp[reg] < 0 ? 0x8000000 : 0);
2045 <            break;
2046 <        case 0x23:              /* FMUL */
2047 <            regs.fp[reg] *= src;
2048 <            regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
2049 <                (regs.fp[reg] < 0 ? 0x8000000 : 0);
2050 <            break;
2051 <        case 0x24:              /* FSGLDIV */
2052 <            regs.fp[reg] /= src;
2053 <            regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
2054 <                (regs.fp[reg] < 0 ? 0x8000000 : 0);
2055 <            break;
2056 <        case 0x25:              /* FREM */
2057 <            regs.fp[reg] = regs.fp[reg] -
2058 <                (double) ((int) (regs.fp[reg] / src + 0.5)) * src;
2059 <            regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
2060 <                (regs.fp[reg] < 0 ? 0x8000000 : 0);
2061 <            break;
2062 <        case 0x26:              /* FSCALE */
2063 <            regs.fp[reg] *= exp (log (2.0) * src);
2064 <            regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
2065 <                (regs.fp[reg] < 0 ? 0x8000000 : 0);
2066 <            break;
2067 <        case 0x27:              /* FSGLMUL */
2068 <            regs.fp[reg] *= src;
2069 <            regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
2070 <                (regs.fp[reg] < 0 ? 0x8000000 : 0);
2071 <            break;
2072 <        case 0x28:              /* FSUB */
2073 <            regs.fp[reg] -= src;
2074 <            regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
2075 <                (regs.fp[reg] < 0 ? 0x8000000 : 0);
2076 <            break;
2077 <        case 0x30:              /* FSINCOS */
2078 <        case 0x31:
2079 <        case 0x32:
2080 <        case 0x33:
2081 <        case 0x34:
2082 <        case 0x35:
2083 <        case 0x36:
2084 <        case 0x37:
2085 <            regs.fp[reg] = sin (src);
2086 <            regs.fp[extra & 7] = cos(src);
2087 <            regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
2088 <                (regs.fp[reg] < 0 ? 0x8000000 : 0);
2089 <            break;
2090 <        case 0x38:              /* FCMP */
2091 <            {
2092 <                double tmp = regs.fp[reg] - src;
2093 <                regs.fpsr = (tmp == 0 ? 0x4000000 : 0) |
2094 <                    (tmp < 0 ? 0x8000000 : 0);
2095 <            }
2096 <            break;
2097 <        case 0x3a:              /* FTST */
2098 <            regs.fpsr = (src == 0 ? 0x4000000 : 0) |
2099 <                (src < 0 ? 0x8000000 : 0);
2100 <            break;
2101 <        default:
2102 <            m68k_setpc (m68k_getpc () - 4);
2103 <            op_illg (opcode);
2104 <            break;
2105 <        }
2106 <        return;
2107 <    }
2108 <    m68k_setpc (m68k_getpc () - 4);
2109 <    op_illg (opcode);
2110 < }
1945 >                                        MAKE_FPSR(regs.fpsr,regs.fp[reg]);
1946 >                                        break;
1947 >                                case 0x0e:              /* FSIN */
1948 >                                        D(bug("FSIN %.04f\r\n",(float)src));
1949 >                                        regs.fp[reg] = sin (src);
1950 >                                        MAKE_FPSR(regs.fpsr,regs.fp[reg]);
1951 >                                        break;
1952 >                                case 0x0f:              /* FTAN */
1953 >                                        D(bug("FTAN %.04f\r\n",(float)src));
1954 >                                        regs.fp[reg] = tan (src);
1955 >                                        MAKE_FPSR(regs.fpsr,regs.fp[reg]);
1956 >                                        break;
1957 >                                case 0x10:              /* FETOX */
1958 >                                        D(bug("FETOX %.04f\r\n",(float)src));
1959 >                                        regs.fp[reg] = exp (src);
1960 >                                        MAKE_FPSR(regs.fpsr,regs.fp[reg]);
1961 >                                        break;
1962 >                                case 0x11:              /* FTWOTOX */
1963 >                                        D(bug("FTWOTOX %.04f\r\n",(float)src));
1964 >                                        regs.fp[reg] = pow(2.0, src);
1965 >                                        MAKE_FPSR(regs.fpsr,regs.fp[reg]);
1966 >                                        break;
1967 >                                case 0x12:              /* FTENTOX */
1968 >                                        D(bug("FTENTOX %.04f\r\n",(float)src));
1969 >                                        regs.fp[reg] = pow(10.0, src);
1970 >                                        MAKE_FPSR(regs.fpsr,regs.fp[reg]);
1971 >                                        break;
1972 >                                case 0x14:              /* FLOGN */
1973 >                                        D(bug("FLOGN %.04f\r\n",(float)src));
1974 >                                        regs.fp[reg] = log (src);
1975 >                                        MAKE_FPSR(regs.fpsr,regs.fp[reg]);
1976 >                                        break;
1977 >                                case 0x15:              /* FLOG10 */
1978 >                                        D(bug("FLOG10 %.04f\r\n",(float)src));
1979 >                                        regs.fp[reg] = log10 (src);
1980 >                                        MAKE_FPSR(regs.fpsr,regs.fp[reg]);
1981 >                                        break;
1982 >                                case 0x16:              /* FLOG2 */
1983 >                                        D(bug("FLOG2 %.04f\r\n",(float)src));
1984 >                                        regs.fp[reg] = log (src) / log (2.0);
1985 >                                        MAKE_FPSR(regs.fpsr,regs.fp[reg]);
1986 >                                        break;
1987 >                                case 0x18:              /* FABS */
1988 >                                        D(bug("FABS %.04f\r\n",(float)src));
1989 >                                        regs.fp[reg] = src < 0 ? -src : src;
1990 >                                        MAKE_FPSR(regs.fpsr,regs.fp[reg]);
1991 >                                        break;
1992 >                                case 0x19:              /* FCOSH */
1993 >                                        D(bug("FCOSH %.04f\r\n",(float)src));
1994 >                                        regs.fp[reg] = cosh(src);
1995 >                                        MAKE_FPSR(regs.fpsr,regs.fp[reg]);
1996 >                                        break;
1997 >                                case 0x1a:              /* FNEG */
1998 >                                        D(bug("FNEG %.04f\r\n",(float)src));
1999 >                                        regs.fp[reg] = -src;
2000 >                                        MAKE_FPSR(regs.fpsr,regs.fp[reg]);
2001 >                                        break;
2002 >                                case 0x1c:              /* FACOS */
2003 >                                        D(bug("FACOS %.04f\r\n",(float)src));
2004 >                                        regs.fp[reg] = acos(src);
2005 >                                        MAKE_FPSR(regs.fpsr,regs.fp[reg]);
2006 >                                        break;
2007 >                                case 0x1d:              /* FCOS */
2008 >                                        D(bug("FCOS %.04f\r\n",(float)src));
2009 >                                        regs.fp[reg] = cos(src);
2010 >                                        MAKE_FPSR(regs.fpsr,regs.fp[reg]);
2011 >                                        break;
2012 >                                case 0x1e:              /* FGETEXP */
2013 >                                        D(bug("FGETEXP %.04f\r\n",(float)src));
2014 > #if HAVE_IEEE_DOUBLE
2015 >                                        if( IS_INFINITY((uae_u32 *)&src) ) {
2016 >                                                MAKE_NAN( (uae_u32 *)&regs.fp[reg] );
2017 >                                        } else {
2018 >                                                regs.fp[reg] = FAST_FGETEXP( (uae_u32 *)&src );
2019 >                                        }
2020 > #else
2021 >                                        if(src == 0) {
2022 >                                                regs.fp[reg] = (double)0;
2023 >                                        } else {
2024 >                                                int expon;
2025 >                                                frexp (src, &expon);
2026 >                                                regs.fp[reg] = (double) (expon - 1);
2027 >                                        }
2028 > #endif
2029 >                                        MAKE_FPSR(regs.fpsr,regs.fp[reg]);
2030 >                                        break;
2031 >                                case 0x1f:              /* FGETMAN */
2032 >                                        D(bug("FGETMAN %.04f\r\n",(float)src));
2033 > #if HAVE_IEEE_DOUBLE
2034 >                                        if( src == 0 ) {
2035 >                                                regs.fp[reg] = 0;
2036 >                                        } else if( IS_INFINITY((uae_u32 *)&src) ) {
2037 >                                                MAKE_NAN( (uae_u32 *)&regs.fp[reg] );
2038 >                                        } else {
2039 >                                                regs.fp[reg] = src;
2040 >                                                FAST_REMOVE_EXPONENT( (uae_u32 *)&regs.fp[reg] );
2041 >                                        }
2042 > #else
2043 >                                        {
2044 >                                                int expon;
2045 >                                                regs.fp[reg] = frexp (src, &expon) * 2.0;
2046 >                                        }
2047 > #endif
2048 >                                        MAKE_FPSR(regs.fpsr,regs.fp[reg]);
2049 >                                        break;
2050 >                        case 0x20:              /* FDIV */
2051 >                                D(bug("FDIV %.04f\r\n",(float)src));
2052 >                                regs.fp[reg] /= src;
2053 >                                MAKE_FPSR(regs.fpsr,regs.fp[reg]);
2054 >                                break;
2055 >                        case 0x21:              /* FMOD */
2056 >                                D(bug("FMOD %.04f\r\n",(float)src));
2057 >                                // regs.fp[reg] = regs.fp[reg] - (double) ((int) (regs.fp[reg] / src)) * src;
2058 >                                { double quot = round_to_zero(regs.fp[reg] / src);
2059 > #if HAVE_IEEE_DOUBLE
2060 >                                        uae_u32 sign = GET_QUOTIENT_SIGN((uae_u32 *)&regs.fp[reg],(uae_u32 *)&src);
2061 > #endif
2062 >                                        regs.fp[reg] = regs.fp[reg] - quot * src;
2063 >                                        MAKE_FPSR(regs.fpsr,regs.fp[reg]);
2064 > #if HAVE_IEEE_DOUBLE
2065 >                                        regs.fpsr = MAKE_QUOTIENT(regs.fpsr,quot,sign);
2066 > #endif
2067 >                                }
2068 >                                break;
2069 >                        case 0x22:              /* FADD */
2070 >                                D(bug("FADD %.04f\r\n",(float)src));
2071 >                                regs.fp[reg] += src;
2072 >                                MAKE_FPSR(regs.fpsr,regs.fp[reg]);
2073 >                                break;
2074 >                        case 0x23:              /* FMUL */
2075 >                                D(bug("FMUL %.04f\r\n",(float)src));
2076 > #if HAVE_IEEE_DOUBLE
2077 >                                GET_DEST_FLAGS((uae_u32 *)&regs.fp[reg]);
2078 >                                GET_SOURCE_FLAGS((uae_u32 *)&src);
2079 >                                if(fl_dest.in_range && fl_source.in_range) {
2080 >                                        regs.fp[reg] *= src;
2081 >                                } else if( fl_dest.nan || fl_source.nan ||
2082 >                                        fl_dest.zero && fl_source.infinity ||
2083 >                                        fl_dest.infinity && fl_source.zero )
2084 >                                {
2085 >                                        MAKE_NAN( (uae_u32 *)&regs.fp[reg] );
2086 >                                } else if( fl_dest.zero || fl_source.zero ) {
2087 >                                        if( fl_dest.negative && !fl_source.negative ||
2088 >                                            !fl_dest.negative && fl_source.negative)
2089 >                                        {
2090 >                                                MAKE_ZERO_NEGATIVE((uae_u32 *)&regs.fp[reg]);
2091 >                                        } else {
2092 >                                                MAKE_ZERO_POSITIVE((uae_u32 *)&regs.fp[reg]);
2093 >                                        }
2094 >                                } else {
2095 >                                        if( fl_dest.negative && !fl_source.negative ||
2096 >                                            !fl_dest.negative && fl_source.negative)
2097 >                                        {
2098 >                                                MAKE_INF_NEGATIVE((uae_u32 *)&regs.fp[reg]);
2099 >                                        } else {
2100 >                                                MAKE_INF_POSITIVE((uae_u32 *)&regs.fp[reg]);
2101 >                                        }
2102 >                                }
2103 > #else
2104 >                                D(bug("FMUL %.04f\r\n",(float)src));
2105 >                                regs.fp[reg] *= src;
2106 > #endif
2107 >                                MAKE_FPSR(regs.fpsr,regs.fp[reg]);
2108 >                                break;
2109 >                        case 0x24:              /* FSGLDIV */
2110 >                                D(bug("FSGLDIV %.04f\r\n",(float)src));
2111 >                                // TODO: round to float.
2112 >                                regs.fp[reg] /= src;
2113 >                                MAKE_FPSR(regs.fpsr,regs.fp[reg]);
2114 >                                break;
2115 >                        case 0x25:              /* FREM */
2116 >                                D(bug("FREM %.04f\r\n",(float)src));
2117 >                                // regs.fp[reg] = regs.fp[reg] - (double) ((int) (regs.fp[reg] / src + 0.5)) * src;
2118 >                                { double quot = round_to_nearest(regs.fp[reg] / src);
2119 > #if HAVE_IEEE_DOUBLE
2120 >                                        uae_u32 sign = GET_QUOTIENT_SIGN((uae_u32 *)&regs.fp[reg],(uae_u32 *)&src);
2121 > #endif
2122 >                                        regs.fp[reg] = regs.fp[reg] - quot * src;
2123 >                                        MAKE_FPSR(regs.fpsr,regs.fp[reg]);
2124 > #if HAVE_IEEE_DOUBLE
2125 >                                        regs.fpsr = MAKE_QUOTIENT(regs.fpsr,quot,sign);
2126 > #endif
2127 >                                }
2128 >                                break;
2129 >
2130 >                        case 0x26:              /* FSCALE */
2131 >                                D(bug("FSCALE %.04f\r\n",(float)src));
2132  
2133 +                                // TODO:
2134 +                                // Overflow, underflow
2135 +
2136 + #if HAVE_IEEE_DOUBLE
2137 +                                if( IS_INFINITY((uae_u32 *)&regs.fp[reg]) ) {
2138 +                                        MAKE_NAN( (uae_u32 *)&regs.fp[reg] );
2139 +                                } else {
2140 +                                        // When the absolute value of the source operand is >= 2^14,
2141 +                                        // an overflow or underflow always results.
2142 +                                        // Here (int) cast is okay.
2143 +                                        FAST_SCALE( (uae_u32 *)&regs.fp[reg], (int)round_to_zero(src) );
2144 +                                }
2145 + #else
2146 +                                if(src != 0) { // Manual says: src==0 -> FPn
2147 +                                        regs.fp[reg] *= exp (log (2.0) * src);
2148 +                                }
2149   #endif
2150 +                                MAKE_FPSR(regs.fpsr,regs.fp[reg]);
2151 +                                break;
2152 +                        case 0x27:              /* FSGLMUL */
2153 +                                D(bug("FSGLMUL %.04f\r\n",(float)src));
2154 +                                regs.fp[reg] *= src;
2155 +                                MAKE_FPSR(regs.fpsr,regs.fp[reg]);
2156 +                                break;
2157 +                        case 0x28:              /* FSUB */
2158 +                                D(bug("FSUB %.04f\r\n",(float)src));
2159 +                                regs.fp[reg] -= src;
2160 +                                MAKE_FPSR(regs.fpsr,regs.fp[reg]);
2161 +                                break;
2162 +                        case 0x30:              /* FSINCOS */
2163 +                        case 0x31:
2164 +                        case 0x32:
2165 +                        case 0x33:
2166 +                        case 0x34:
2167 +                        case 0x35:
2168 +                        case 0x36:
2169 +                        case 0x37:
2170 +                                D(bug("FSINCOS %.04f\r\n",(float)src));
2171 +                                // Cosine must be calculated first if same register
2172 +                                regs.fp[extra & 7] = cos(src);
2173 +                                regs.fp[reg] = sin (src);
2174 +                                // Set fpsr according to the sine result
2175 +                                MAKE_FPSR(regs.fpsr,regs.fp[reg]);
2176 +                                break;
2177 +                        case 0x38:              /* FCMP */
2178 +                                D(bug("FCMP %.04f\r\n",(float)src));
2179 +
2180 +                                // The infinity bit is always cleared by the FCMP
2181 +                                // instruction since it is not used by any of the
2182 +                                // conditional predicate equations.
2183 +
2184 + #if HAVE_IEEE_DOUBLE
2185 +                                if( IS_INFINITY((uae_u32 *)&src) ) {
2186 +                                        if( IS_NEGATIVE((uae_u32 *)&src) ) {
2187 +                                                // negative infinity
2188 +                                                if( IS_INFINITY((uae_u32 *)&regs.fp[reg]) && IS_NEGATIVE((uae_u32 *)&regs.fp[reg]) ) {
2189 +                                                        // Zero, Negative
2190 +                                                        regs.fpsr = (regs.fpsr & 0x00FFFFFF) | 0x4000000 | 0x8000000;
2191 +                                                        D(bug("-INF cmp -INF -> NZ\r\n"));
2192 +                                                } else {
2193 +                                                        // None
2194 +                                                        regs.fpsr = (regs.fpsr & 0x00FFFFFF);
2195 +                                                        D(bug("x cmp -INF -> None\r\n"));
2196 +                                                }
2197 +                                        } else {
2198 +                                                // positive infinity
2199 +                                                if( IS_INFINITY((uae_u32 *)&regs.fp[reg]) && !IS_NEGATIVE((uae_u32 *)&regs.fp[reg]) ) {
2200 +                                                        // Zero
2201 +                                                        regs.fpsr = (regs.fpsr & 0x00FFFFFF) | 0x4000000;
2202 +                                                        D(bug("+INF cmp +INF -> Z\r\n"));
2203 +                                                } else {
2204 +                                                        // Negative
2205 +                                                        regs.fpsr = (regs.fpsr & 0x00FFFFFF) | 0x8000000;
2206 +                                                        D(bug("X cmp +INF -> N\r\n"));
2207 +                                                }
2208 +                                        }
2209 +                                } else {
2210 +                                        double tmp = regs.fp[reg] - src;
2211 +                                        regs.fpsr = (regs.fpsr & 0x00FFFFFF) | (tmp == 0 ? 0x4000000 : 0) | (tmp < 0 ? 0x8000000 : 0);
2212 +                                }
2213 + #else
2214 +                                {
2215 +                                        double tmp = regs.fp[reg] - src;
2216 +                                        MAKE_FPSR(regs.fpsr,tmp);
2217 +                                }
2218 + #endif
2219 +                                break;
2220 +                        case 0x3a:              /* FTST */
2221 +                                D(bug("FTST %.04f\r\n",(float)src));
2222 +                                // MAKE_FPSR(regs.fpsr,regs.fp[reg]);
2223 +                                MAKE_FPSR(regs.fpsr,src);
2224 +                                break;
2225 +                        default:
2226 +                                D(bug("ILLEGAL F OP %X\r\n",opcode));
2227 +                                m68k_setpc (m68k_getpc () - 4);
2228 +                                op_illg (opcode);
2229 +                                break;
2230 +                }
2231 +                dump_fp_regs( "END  ");
2232 +                return;
2233 +  }
2234 +        D(bug("ILLEGAL F OP 2 %X\r\n",opcode));
2235 +  m68k_setpc (m68k_getpc () - 4);
2236 +  op_illg (opcode);
2237 +        dump_fp_regs( "END  ");
2238 + }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines