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.4 by cebix, 1999-10-28T09:31:41Z

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

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines