home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 25 / AACD 25.iso / AACD / Utilities / BasiliskII / src / uae_cpu / fpu / fpu_uae.cpp next >
Encoding:
C/C++ Source or Header  |  2001-03-20  |  56.5 KB  |  2,281 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.  * 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.  
  74. #include "memory.h"
  75. #include "readcpu.h"
  76. #include "newcpu.h"
  77. #include "main.h"
  78.  
  79. #define DEBUG 0
  80. #include "debug.h"
  81.  
  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 */
  102. /* extended : S 15*E 64*F */
  103. /* E = 0 & F = 0 -> 0 */
  104. /* E = MAX & F = 0 -> Infin */
  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, 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.     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, 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, 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.   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;
  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);
  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, 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.     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. #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++ = (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.  
  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')
  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.   }
  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] = {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;
  816.     case 1:
  817.             return 0;
  818.     case 2:
  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;
  825.     case 4:
  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;
  832.     case 6:
  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.     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;
  875.     case 1:
  876.             *src = to_single(get_long (ad));
  877.             break;
  878.  
  879.     case 2:{
  880.         uae_u32 wrd1, wrd2, wrd3;
  881.         wrd1 = get_long (ad);
  882.         ad += 4;
  883.         wrd2 = get_long (ad);
  884.         ad += 4;
  885.         wrd3 = get_long (ad);
  886.         *src = to_exten(wrd1, wrd2, wrd3);
  887.             }
  888.             break;
  889.     case 3:{
  890.         uae_u32 wrd1, wrd2, wrd3;
  891.         wrd1 = get_long (ad);
  892.         ad += 4;
  893.         wrd2 = get_long (ad);
  894.         ad += 4;
  895.         wrd3 = get_long (ad);
  896.         *src = to_pack(wrd1, wrd2, wrd3);
  897.             }
  898.             break;
  899.     case 4:
  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;
  910.     case 6:
  911.             *src = (double) (uae_s8) get_byte(ad);
  912.             break;
  913.     default:
  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] = {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)
  950.                     | (m68k_dreg (regs, reg) & ~0xff));
  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;
  968.     case 2:
  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;
  975.     case 4:
  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;
  982.     case 6:
  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 = (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;
  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;
  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;
  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;
  1050.     case 6:
  1051.             put_byte(ad, (uae_s8) value);
  1052.             break;
  1053.     default:
  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) {
  1069.     case 0:
  1070.     case 1:
  1071.             return 0;
  1072.     case 2:
  1073.             *ad = m68k_areg (regs, reg);
  1074.             break;
  1075.     case 3:
  1076.             *ad = m68k_areg (regs, reg);
  1077.             break;
  1078.     case 4:
  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;
  1084.     case 6:
  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 = (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 condition)
  1112. {
  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 (condition) {
  1119.     case 0x00:
  1120.             CONDRET("False",0);
  1121.     case 0x01:
  1122.             CONDRET("Equal",Z);
  1123.     case 0x02:
  1124.             CONDRET("Ordered Greater Than",!(NotANumber || Z || N));
  1125.     case 0x03:
  1126.             CONDRET("Ordered Greater Than or Equal",Z || !(NotANumber || N));
  1127.     case 0x04:
  1128.             CONDRET("Ordered Less Than",N && !(NotANumber || Z));
  1129.     case 0x05:
  1130.             CONDRET("Ordered Less Than or Equal",Z || (N && !NotANumber));
  1131.     case 0x06:
  1132.             CONDRET("Ordered Greater or Less Than",!(NotANumber || Z));
  1133.     case 0x07:
  1134.             CONDRET("Ordered",!NotANumber);
  1135.     case 0x08:
  1136.             CONDRET("Unordered",NotANumber);
  1137.     case 0x09:
  1138.             CONDRET("Unordered or Equal",NotANumber || Z);
  1139.     case 0x0a:
  1140.             CONDRET("Unordered or Greater Than",NotANumber || !(N || Z));
  1141.     case 0x0b:
  1142.             CONDRET("Unordered or Greater or Equal",NotANumber || Z || !N);
  1143.     case 0x0c:
  1144.             CONDRET("Unordered or Less Than",NotANumber || (N && !Z));
  1145.     case 0x0d:
  1146.             CONDRET("Unordered or Less or Equal",NotANumber || Z || N);
  1147.     case 0x0e:
  1148.             CONDRET("Not Equal",!Z);
  1149.     case 0x0f:
  1150.             CONDRET("True",1);
  1151.     case 0x10:
  1152.             CONDRET("Signaling False",0);
  1153.     case 0x11:
  1154.             CONDRET("Signaling Equal",Z);
  1155.     case 0x12:
  1156.             CONDRET("Greater Than",!(NotANumber || Z || N));
  1157.     case 0x13:
  1158.             CONDRET("Greater Than or Equal",Z || !(NotANumber || N));
  1159.     case 0x14:
  1160.             CONDRET("Less Than",N && !(NotANumber || Z));
  1161.     case 0x15:
  1162.             CONDRET("Less Than or Equal",Z || (N && !NotANumber));
  1163.     case 0x16:
  1164.             CONDRET("Greater or Less Than",!(NotANumber || Z));
  1165.     case 0x17:
  1166.             CONDRET("Greater, Less or Equal",!NotANumber);
  1167.     case 0x18:
  1168.             CONDRET("Not Greater, Less or Equal",NotANumber);
  1169.     case 0x19:
  1170.             CONDRET("Not Greater or Less Than",NotANumber || Z);
  1171.     case 0x1a:
  1172.             CONDRET("Not Less Than or Equal",NotANumber || !(N || Z));
  1173.     case 0x1b:
  1174.             CONDRET("Not Less Than",NotANumber || Z || !N);
  1175.     case 0x1c:
  1176.             // CONDRET("Not Greater Than or Equal",NotANumber || (Z && N));
  1177.             CONDRET("Not Greater Than or Equal",!Z && (NotANumber || N));
  1178.     case 0x1d:
  1179.             CONDRET("Not Greater Than",NotANumber || Z || N);
  1180.     case 0x1e:
  1181.             CONDRET("Signaling Not Equal",!Z);
  1182.     case 0x1f:
  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 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.   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.         // this may have leaked.
  1209.         /*
  1210.         m68k_dreg (regs, reg) = ((m68k_dreg (regs, reg) & ~0xffff)
  1211.                 | ((m68k_dreg (regs, reg) - 1) & 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.   }
  1222. }
  1223.  
  1224. void REGPARAM2 fscc_opp(uae_u32 opcode, uae_u16 extra)
  1225. {
  1226.   uae_u32 ad;
  1227.   int cc;
  1228.  
  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) {
  1240.         m68k_setpc (m68k_getpc () - 4);
  1241.         op_illg (opcode);
  1242.         } else
  1243.         put_byte(ad, cc ? 0xff : 0x00);
  1244.   }
  1245. }
  1246.  
  1247. void REGPARAM2 ftrapcc_opp(uae_u32 opcode, uaecptr oldpc)
  1248. {
  1249.   int cc;
  1250.  
  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.   }
  1278. }
  1279.  
  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;
  1287.  
  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.   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.   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.     }
  1338. }
  1339.  
  1340. // FRESTORE has no pre-decrement
  1341. void REGPARAM2 frestore_opp(uae_u32 opcode)
  1342. {
  1343.   uae_u32 ad;
  1344.   uae_u32 d;
  1345.   int incr = (opcode & 0x38) == 0x20 ? -1 : 1;
  1346.  
  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 () - 2);
  1351.         op_illg (opcode);
  1352.         return;
  1353.   }
  1354.  
  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.       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. }
  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.             {
  1619.         uae_u32 ad, list = 0;
  1620.         int incr = 0;
  1621.         if (extra & 0x2000) {
  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 *)®s.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 *)®s.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.             dump_fp_regs( "END  ");
  1757.             return;
  1758.     case 0:
  1759.     case 2:
  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.                         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.                 // 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;
  1953. #else
  1954.                     regs.fp[reg] = atanh (src);
  1955. #endif
  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 *)®s.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 *)®s.fp[reg] );
  2051.                     } else {
  2052.                         regs.fp[reg] = src;
  2053.                         FAST_REMOVE_EXPONENT( (uae_u32 *)®s.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 *)®s.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 *)®s.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 *)®s.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 *)®s.fp[reg]);
  2106.                     } else {
  2107.                         MAKE_ZERO_POSITIVE((uae_u32 *)®s.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 *)®s.fp[reg]);
  2114.                     } else {
  2115.                         MAKE_INF_POSITIVE((uae_u32 *)®s.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 *)®s.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 *)®s.fp[reg]) ) {
  2153.                     MAKE_NAN( (uae_u32 *)®s.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 *)®s.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 *)®s.fp[reg]) && IS_NEGATIVE((uae_u32 *)®s.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 *)®s.fp[reg]) && !IS_NEGATIVE((uae_u32 *)®s.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. }
  2281.