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.3 by cebix, 1999-10-27T17:50:08Z

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

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines