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.9 by gbeauche, 2000-09-05T16:53:47Z

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

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines