home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 6 / AACD06.ISO / AACD / Emulation / BasiliskII / src / uae_cpu / fpp.cpp < prev    next >
C/C++ Source or Header  |  1999-11-03  |  57KB  |  2,237 lines

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