home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 25 / AACD 25.iso / AACD / Utilities / BasiliskII / src / uae_cpu / fpu / fpu_x86.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2001-04-25  |  159.3 KB  |  6,463 lines

  1. /*
  2.  *  fpu_x86.cpp - 68881/68040 fpu code for x86/Windows an Linux/x86.
  3.  *
  4.  *  Basilisk II (C) 1997-2001 Christian Bauer
  5.  *
  6.  *  MC68881/68040 fpu emulation
  7.  *
  8.  *  Based on UAE FPU, original copyright 1996 Herman ten Brugge,
  9.  *  rewritten for x86 by Lauri Pesonen 1999-2000,
  10.  *  accomodated to GCC's Extended Asm syntax by Gwenole Beauchesne 2000.
  11.  *
  12.  *  This program is free software; you can redistribute it and/or modify
  13.  *  it under the terms of the GNU General Public License as published by
  14.  *  the Free Software Foundation; either version 2 of the License, or
  15.  *  (at your option) any later version.
  16.  *
  17.  *  This program is distributed in the hope that it will be useful,
  18.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  19.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  20.  *  GNU General Public License for more details.
  21.  *
  22.  *  You should have received a copy of the GNU General Public License
  23.  *  along with this program; if not, write to the Free Software
  24.  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  25.  *
  26.  *
  27.  *    Interface
  28.  *        Almost the same as original. Please see the comments in "fpu.h".
  29.  *        Call fpu_init() and fpu_set_integral_fpu() before cpu thread starts up.
  30.  *
  31.  *
  32.  *    Why assembly?
  33.  *        The reason is not really speed, but to get infinities,
  34.  *        NANs and flags finally working.
  35.  *
  36.  *
  37.  *    How to maintain Mac and x86 FPU flags -- plan B
  38.  *
  39.  *    regs.piar is not updated.
  40.  *
  41.  *    regs.fpcr always contains the real 68881/68040 control word.
  42.  *
  43.  *    regs.fpsr is not kept up-to-date, for efficiency reasons.
  44.  *    Most of the FPU commands update this in a way or another,
  45.  *    but it is not read nearly that often. Therefore, three host-specific
  46.  *    words hold the status byte and exception byte ("sw"), accrued exception
  47.  *    byte ("sw_accrued") and the quotient byte ("sw_quotient"), as explained below.
  48.  *
  49.  *    CONDITION CODE - QUOTIENT - EXCEPTION STATUS - ACCRUED EXCEPTION
  50.  *        CONDITION CODE (N,Z,I,NAN)
  51.  *            updated after each opcode, if needed.
  52.  *            x86 assembly opcodes call FXAM and store the status word to "sw".
  53.  *            When regs.fpsr is actually used, the value of "sw" is translated.
  54.  *        QUOTIENT BYTE
  55.  *            Updated by frem, fmod, frestore(null frame)
  56.  *            Stored in "sw_quotient" in correct bit position, combined when
  57.  *            regs.fpsr is actually used.
  58.  *        EXCEPTION STATUS (BSUN,SNAN,OPERR,OVFL,UNFL,DZ,INEX2,INEX1)
  59.  *            updated after each opcode, if needed.
  60.  *            Saved in x86 form in "sw".
  61.  *            When regs.fpsr is actually used, the value of "sw" is translated.
  62.  *            Only fcc_op can set BSUN
  63.  *        ACCRUED EXCEPTION (ACCR_IOP,ACCR_OVFL,ACCR_UNFL,ACCR_DZ,ACCR_INEX)
  64.  *            updated after each opcode, if needed.
  65.  *            Logically OR'ed in x86 form to "sw_accrued".
  66.  *            When regs.fpsr is actually used, the value of "sw_accrued" is translated.
  67.  *        
  68.  *        When "sw" and "sw_accrued" are stored, all pending x86 FPU
  69.  *        exceptions are cleared, if there are any.
  70.  *
  71.  *        Writing to "regs.fpsr" reverse-maps to x86 status/exception values
  72.  *        and stores the values in "sw", "sw_accrued" and "sw_quotient".
  73.  *
  74.  *        So, "sw" and "sw_accrued" are not in correct bit positions
  75.  *        and have x86 values, but "sw_quotient" is at correct position.
  76.  *
  77.  *        Note that it does not matter that the reverse-mapping is not exact
  78.  *        (both SW_IE and SW_DE are mapped to ACCR_IOP, but ACCR_IOP maps to SW_IE
  79.  *        only), the MacOS always sees the correct exception bits.
  80.  *
  81.  *        Also note the usage of the fake BSUN flag SW_FAKE_BSUN. If you change the
  82.  *        x86 FPU code, you must make sure that you don't generate any FPU stack faults.
  83.  *
  84.  *
  85.  *    x86 co-processor initialization:
  86.  *
  87.  *    Bit  Code   Use
  88.  *     0   IM     Invalid operation exception mask     1    Disabled
  89.  *     1   DM     Denormalized operand exception mask  1    Disabled
  90.  *     2   ZM     Zerodivide exception mask            1    Disabled
  91.  *     3   OM     Overflow exception mask              1    Disabled
  92.  *     4   UM     Underflow exception mask             1    Disabled
  93.  *     5   PM     Precision exception mask             1    Disabled
  94.  *     6   -      -                                    -    -
  95.  *     7   IEM    Interrupt enable mask                0    Enabled
  96.  *     8   PC     Precision control\                   1  - 64 bits
  97.  *     9   PC     Precision control/                   1  /
  98.  *    10   RC     Rounding control\                    0  - Nearest even
  99.  *    11   RC     Rounding control/                    0  /
  100.  *    12   IC     Infinity control                     1    Affine
  101.  *    13   -      -                                    -    -
  102.  *    14   -      -                                    -    -
  103.  *    15   -      -                                    -    -
  104.  *
  105.  *
  106.  *  TODO:
  107.  *    - Exceptions are not implemented.
  108.  *    - All tbyte variables should be aligned to 16-byte boundaries.
  109.  *          (for best efficiency).
  110.  *        - FTRAPcc code looks like broken.
  111.  *        - If USE_3_BIT_QUOTIENT is 0, exceptions should be checked after
  112.  *            float -> int rounding (frem,fmod).
  113.  *        - The speed can be greatly improved. Do this only after you are sure
  114.  *            that there are no major bugs.
  115.  *        - Support for big-endian byte order (but all assembly code needs to
  116.  *            be rewritten anyway)
  117.  *            I have some non-portable code like *((uae_u16 *)&m68k_dreg(regs, reg)) = newv;
  118.  *            Sorry about that, you need to change these. I could do it myself, but better
  119.  *            not, I would have no way to test them out.
  120.  *            I tried to mark all spots with a comment TODO_BIGENDIAN.
  121.  *        - to_double() may need renormalization code. Or then again, maybe not.
  122.  *        - Signaling NANs should be handled better. The current mapping of
  123.  *            signaling nan exception to denormalized operand exception is only
  124.  *            based on the idea that the (possible) handler sees that "something
  125.  *            seriously wrong" and takes the same action. Should not really get (m)any
  126.  *            of those since normalization is handled on to_exten()
  127.  *            
  128.  */
  129.  
  130. #include <math.h>
  131. #include <stdio.h>
  132. #include <string.h>
  133.  
  134. #include "sysdeps.h"
  135. #include "memory.h"
  136. #include "readcpu.h"
  137. #include "newcpu.h"
  138. #include "fpu/fpu_x86.h"
  139. #include "fpu/fpu_x86_asm.h"
  140.  
  141. /* ---------------------------- Compatibility ---------------------------- */
  142.  
  143. #define BYTE        uint8
  144. #define WORD        uint16
  145. #define DWORD        uint32
  146. #define _ASM        __asm__ __volatile__
  147. #define min(a, b)    (((a) < (b)) ? (a) : (b))
  148.  
  149. /* ---------------------------- Configuration ---------------------------- */
  150.  
  151. /*
  152. If USE_3_BIT_QUOTIENT is set to 1, FREM and FMOD use a faster version
  153. with only 3 quotient bits (those provided by the x86 FPU). If set to 0,
  154. they calculate the same 7 bits that m68k does. It seems (as for now) that
  155. 3 bits suffice for all Mac programs I have tried.
  156.  
  157. If you decide that you need all 7 bits (USE_3_BIT_QUOTIENT is 0),
  158. consider checking the host exception flags after FISTP (search for
  159. "TODO:Quotient". The result may be too large to fit into a dword.
  160. */
  161. /*
  162. gb-- I only tested the following configurations:
  163.         USE_3_BIT_QUOTIENT            1 -- still changes to apply if no 3-bit quotient
  164.         DEBUG                        1 or 0
  165.         USE_CONSISTENCY_CHECKING    0
  166.         I3_ON_ILLEGAL_FPU_OP        0 -- and this won't change
  167.         I3_ON_FTRAPCC                0 -- and this won't change
  168. */
  169. #define USE_3_BIT_QUOTIENT            1
  170.  
  171. #define DEBUG                        0
  172. #define USE_CONSISTENCY_CHECKING    0
  173.  
  174. #define I3_ON_ILLEGAL_FPU_OP        0
  175. #define I3_ON_FTRAPCC                0
  176.  
  177.  
  178. /* ---------------------------- Registers ---------------------------- */
  179.  
  180. // "regs.fp" is not used. regs.fpcr, regs.fpsr and regs.fpiar are used.
  181.  
  182. typedef BYTE *float80;
  183. typedef BYTE float80_s[10];
  184. typedef BYTE float80_s_aligned[16];
  185.  
  186. static float80_s_aligned fp_reg[8];
  187.  
  188.  
  189. /* ---------------------------- Debugging ---------------------------- */
  190.  
  191. #if DEBUG
  192. //#pragma optimize("",off)
  193. #endif
  194.  
  195. // extern "C" {int debugging_fpp = 0;}
  196.  
  197. #include "debug.h"
  198.  
  199. #if DEBUG
  200. #undef __inline__
  201. #define __inline__
  202. //#undef D
  203. //#define D(x) { if(debugging_fpp) { (x); } }
  204.  
  205. static void dump_first_bytes_buf( char *b, BYTE *buf, int32 actual )
  206. {
  207.     char bb[10];
  208.     int32 i, bytes = min(actual,100);
  209.  
  210.     *b = 0;
  211.     for (i=0; i<bytes; i++) {
  212.         sprintf( bb, "%02x ", (uint32)buf[i] );
  213.         strcat( b, bb );
  214.     }
  215.     strcat((char*)b,"\r\n");
  216. }
  217.  
  218. static void dump_first_bytes( BYTE *buf, int32 actual )
  219. {
  220.     char msg[256];
  221.     dump_first_bytes_buf( msg, buf, actual );
  222.     D(bug("%s\n", msg));
  223. }
  224.  
  225. #define CONDRET(s,x) D(bug("fpp_cond %s = %d\r\n",s,(uint32)(x))); return (x)
  226. static char * etos( float80 e ) REGPARAM;
  227. static char * etos( float80 e )
  228. {
  229.     static char _s[10][30];
  230.     static int _ix = 0;
  231.     float f;
  232.  
  233. /*    _asm {
  234.         MOV            EDI, [e]
  235.         FLD     TBYTE PTR [EDI]
  236.     FSTP    DWORD PTR f
  237.     } */
  238.     
  239.     _ASM(    "fldt    %1\n"
  240.             "fstp    %0\n"
  241.         :    "=m" (f)
  242.         :    "m" (*e)
  243.         );
  244.     
  245.     if(++_ix >= 10) _ix = 0;
  246.  
  247.     sprintf( _s[_ix], "%.04f", (float)f );
  248.     return( _s[_ix] );
  249. }
  250. static void dump_fp_regs( char *s )
  251. {
  252.     char b[512];
  253.  
  254.     sprintf(
  255.         b,
  256.         "%s: %s, %s, %s, %s, %s, %s, %s, %s\r\n",
  257.         s,
  258.         etos(fp_reg[0]),
  259.         etos(fp_reg[1]),
  260.         etos(fp_reg[2]),
  261.         etos(fp_reg[3]),
  262.         etos(fp_reg[4]),
  263.         etos(fp_reg[5]),
  264.         etos(fp_reg[6]),
  265.         etos(fp_reg[7])
  266.     );
  267.     D(bug((char*)b));
  268. }
  269.  
  270. #else
  271. #define CONDRET(s,x) return (x)
  272. #define dump_fp_regs(s) {}
  273. #endif
  274.  
  275.  
  276. /* ---------------------------- FPU consistency ---------------------------- */
  277.  
  278. #if USE_CONSISTENCY_CHECKING
  279. static uae_u16 checked_sw_atstart;
  280.  
  281. static void FPU_CONSISTENCY_CHECK_START()
  282. {
  283. /*    _asm {
  284.       FNSTSW checked_sw_atstart
  285.     } */
  286.     _ASM("fnstsw %0" : "=m" (checked_sw_atstart));
  287. }
  288.  
  289. static void FPU_CONSISTENCY_CHECK_STOP(char *name)
  290. {
  291.     uae_u16 checked_sw_atend;
  292. //    _asm FNSTSW checked_sw_atend
  293.     _ASM("fnstsw %0" : "=m" (checked_sw_attend));
  294.     char msg[256];
  295.  
  296.     // Check for FPU stack overflows/underflows.
  297.     if( (checked_sw_atend & 0x3800) != (checked_sw_atstart & 0x3800) ) {
  298.         wsprintf(
  299.             msg, 
  300.             "FPU stack leak at %s, %X, %X\r\n", 
  301.             name,
  302.             (int)(checked_sw_atstart & 0x3800) >> 11,
  303.             (int)(checked_sw_atend & 0x3800) >> 11
  304.         );
  305.         OutputDebugString(msg);
  306.     }
  307.  
  308.     // Observe status mapping.
  309.     /*
  310.     if(checked_sw_atstart != 0x400 || checked_sw_atend != 0x400) {
  311.         wsprintf(
  312.             msg, "Op %s, sw before=%X, sw after=%X\r\n", 
  313.             name, (int)checked_sw_atstart, (int)checked_sw_atend
  314.         );
  315.         OutputDebugString(msg);
  316.     }
  317.     */
  318. }
  319. #else
  320. #define FPU_CONSISTENCY_CHECK_START()
  321. #define FPU_CONSISTENCY_CHECK_STOP(name)
  322. #endif
  323.  
  324.  
  325. /* ---------------------------- FPU type ---------------------------- */
  326.  
  327. static uae_u32 is_integral_68040_fpu = 0;
  328.  
  329.  
  330. /* ---------------------------- Status byte ---------------------------- */
  331.  
  332. // Extend the SW_* codes
  333. #define SW_FAKE_BSUN            SW_SF
  334.  
  335. // Shorthand
  336. #define SW_EXCEPTION_MASK (SW_ES|SW_SF|SW_PE|SW_UE|SW_OE|SW_ZE|SW_DE|SW_IE)
  337. // #define SW_EXCEPTION_MASK (SW_SF|SW_PE|SW_UE|SW_OE|SW_ZE|SW_DE|SW_IE)
  338.  
  339. // Map x86 FXAM codes -> m68k fpu status byte
  340. #define SW_Z_I_NAN_MASK            (SW_C0|SW_C2|SW_C3)
  341. #define SW_Z                    (SW_C3)
  342. #define SW_I                    (SW_C0|SW_C2)
  343. #define SW_NAN                    (SW_C0)
  344. #define SW_FINITE                (SW_C2)
  345. #define SW_EMPTY_REGISTER        (SW_C0|SW_C3)
  346. #define SW_DENORMAL                (SW_C2|SW_C3)
  347. #define SW_UNSUPPORTED            (0)
  348. #define SW_N                    (SW_C1)
  349.  
  350. // Initial state after boot, reset and frestore(null frame)
  351. #define SW_INITIAL                SW_FINITE
  352.  
  353. // These hold the contents of the fpsr, in Intel values.
  354. static DWORD sw = SW_INITIAL;
  355. static DWORD sw_accrued = 0;
  356. static DWORD sw_quotient = 0;
  357.  
  358.  
  359. /* ---------------------------- Control word ---------------------------- */
  360.  
  361. // Initial state after boot, reset and frestore(null frame)
  362. #define CW_INITIAL    (CW_RESET|CW_X|CW_PC_EXTENDED|CW_RC_NEAR|CW_PM|CW_UM|CW_OM|CW_ZM|CW_DM|CW_IM)
  363.  
  364. static WORD cw = CW_INITIAL; 
  365.  
  366.  
  367. /* ---------------------------- FMOVECR constants ---------------------------- */
  368.  
  369. static float80_s
  370.     // Suported by x86 FPU
  371.     const_pi,
  372.     const_lg2,
  373.     const_l2e,
  374.     const_z,
  375.     const_ln2,
  376.     const_1,
  377.  
  378.     // Not suported by x86 FPU
  379.     const_e,
  380.     const_log_10_e,
  381.     const_ln_10,
  382.     const_1e1,
  383.     const_1e2,
  384.     const_1e4,
  385.     const_1e8,
  386.     const_1e16,
  387.     const_1e32,
  388.     const_1e64,
  389.     const_1e128,
  390.     const_1e256,
  391.     const_1e512,
  392.     const_1e1024,
  393.     const_1e2048,
  394.     const_1e4096;
  395.  
  396.  
  397. /* ---------------------------- Saved host FPU state ---------------------------- */
  398.  
  399. static BYTE m_fpu_state_original[108]; // 90/94/108
  400.  
  401.  
  402. /* ---------------------------- Map tables ---------------------------- */
  403.  
  404. typedef void REGPARAM2 fpuop_func( uae_u32, uae_u16 );
  405. extern "C" { fpuop_func *fpufunctbl[65536]; }
  406.  
  407. // Control word -- need only one-way mapping
  408. static const uae_u16 cw_rc_mac2host[] = {
  409.     CW_RC_NEAR,
  410.     CW_RC_ZERO,
  411.     CW_RC_DOWN,
  412.     CW_RC_UP
  413. };
  414. static const uae_u16 cw_pc_mac2host[] = {
  415.     CW_PC_EXTENDED,
  416.     CW_PC_SINGLE,
  417.     CW_PC_DOUBLE,
  418.     CW_PC_RESERVED
  419. };
  420.  
  421. // Status word -- need two-way mapping
  422. static uae_u32 sw_cond_host2mac[ 0x48 ];
  423. static uae_u16 sw_cond_mac2host[ 16 ];
  424.  
  425. static uae_u32 exception_host2mac[ 0x80 ];
  426. static uae_u32 exception_mac2host[ 0x100 ];
  427.  
  428. static uae_u32 accrued_exception_host2mac[ 0x40 ];
  429. static uae_u32 accrued_exception_mac2host[ 0x20 ];
  430.  
  431.  
  432. /* ---------------------------- Control functions ---------------------------- */
  433.  
  434. /*
  435.     Exception enable byte is ignored, but the same value is returned
  436.     that was previously set.
  437. */
  438. static void __inline__ set_host_fpu_control_word()
  439. {
  440.     cw = (cw & ~(X86_ROUND_CONTROL_MASK|X86_PRECISION_CONTROL_MASK)) | 
  441.                 cw_rc_mac2host[ (regs.fpcr & ROUND_CONTROL_MASK) >> 4 ] |
  442.                 cw_pc_mac2host[ (regs.fpcr & PRECISION_CONTROL_MASK) >> 6 ];
  443.     
  444.     // Writing to control register is very slow (no register renaming on
  445.     // ppro++, and most of all, it's one of those serializing commands).
  446. /*    _asm {
  447.     FLDCW   cw
  448.     } */
  449.     _ASM("fldcw %0" : : "m" (cw));
  450. }
  451.  
  452.  
  453. /* ---------------------------- Status functions ---------------------------- */
  454.  
  455. static void __inline__ SET_BSUN_ON_NAN()
  456. {
  457.     if( (sw & (SW_Z_I_NAN_MASK)) == SW_NAN ) {
  458.         sw |= SW_FAKE_BSUN;
  459.         sw_accrued |= SW_IE;
  460.     }
  461. }
  462.  
  463. static void __inline__ build_ex_status()
  464. {
  465.     if(sw & SW_EXCEPTION_MASK) {
  466. //        _asm FNCLEX
  467.         _ASM("fnclex");
  468.         sw_accrued |= sw;
  469.     }
  470. }
  471.  
  472. static void __inline__ to_fpsr()
  473. {
  474.     regs.fpsr = 
  475.             sw_cond_host2mac[ (sw & 0x4700) >> 8 ] |
  476.             sw_quotient |
  477.             exception_host2mac[ sw & (SW_FAKE_BSUN|SW_PE|SW_UE|SW_OE|SW_ZE|SW_DE|SW_IE) ] |
  478.             accrued_exception_host2mac[ sw_accrued & (SW_PE|SW_UE|SW_OE|SW_ZE|SW_DE|SW_IE) ]
  479.             ;
  480. }
  481.  
  482. static void __inline__ from_fpsr()
  483. {
  484.     sw = 
  485.             sw_cond_mac2host[ (regs.fpsr & 0x0F000000) >> 24 ] |
  486.             exception_mac2host[ (regs.fpsr & 0x0000FF00) >> 8 ];
  487.     sw_quotient = regs.fpsr & 0x00FF0000;
  488.     sw_accrued =  accrued_exception_mac2host[ (regs.fpsr & 0xF8) >> 3 ];
  489. }
  490.  
  491.  
  492. // TODO_BIGENDIAN; all of these.
  493. /* ---------------------------- Type functions ---------------------------- */
  494.  
  495. /*
  496. When the FPU creates a NAN, the NAN always contains the same bit pattern
  497. in the mantissa. All bits of the mantissa are ones for any precision.
  498. When the user creates a NAN, any nonzero bit pattern can be stored in the mantissa.
  499. */
  500. static __inline__ void MAKE_NAN(float80 p)
  501. {
  502.     // Make it non-signaling.
  503.     memset( p, 0xFF, sizeof(float80_s)-1 );
  504.     p[9] = 0x7F;
  505. }
  506.  
  507. /*
  508. For single- and double-precision infinities the fraction is a zero.
  509. For extended-precision infinities, the mantissa’s MSB, the explicit
  510. integer bit, can be either one or zero.
  511. */
  512. static __inline__ uae_u32 IS_INFINITY(float80 p)
  513. {
  514.     if( ((p[9] & 0x7F) == 0x7F) && p[8] == 0xFF ) {
  515.         if( *((uae_u32 *)p) == 0 &&
  516.                 ( *((uae_u32 *)&p[4]) & 0x7FFFFFFF ) == 0 )
  517.         {
  518.             return(1);
  519.         }
  520.     }
  521.     return(0);
  522. }
  523.  
  524. static __inline__ uae_u32 IS_NAN(float80 p)
  525. {
  526.     if( ((p[9] & 0x7F) == 0x7F) && p[8] == 0xFF ) {
  527.         if( *((uae_u32 *)p) != 0 ||
  528.                 ( *((uae_u32 *)&p[4]) & 0x7FFFFFFF ) != 0 )
  529.         {
  530.             return(1);
  531.         }
  532.     }
  533.     return(0);
  534. }
  535.  
  536. static __inline__ uae_u32 IS_ZERO(float80 p)
  537. {
  538.     return *((uae_u32 *)p) == 0 &&
  539.                  *((uae_u32 *)&p[4]) == 0 &&
  540.                  ( *((uae_u16 *)&p[8]) & 0x7FFF ) == 0;
  541. }
  542.  
  543. static __inline__ void MAKE_INF_POSITIVE(float80 p)
  544. {
  545.     memset( p, 0, sizeof(float80_s)-2 );
  546.     *((uae_u16 *)&p[8]) = 0x7FFF;
  547. }
  548.  
  549. static __inline__ void MAKE_INF_NEGATIVE(float80 p)
  550. {
  551.     memset( p, 0, sizeof(float80_s)-2 );
  552.     *((uae_u16 *)&p[8]) = 0xFFFF;
  553. }
  554.  
  555. static __inline__ void MAKE_ZERO_POSITIVE(float80 p)
  556. {
  557.     memset( p, 0, sizeof(float80_s) );
  558. }
  559.  
  560. static __inline__ void MAKE_ZERO_NEGATIVE(float80 *p)
  561. {
  562.     memset( p, 0, sizeof(float80_s) );
  563.     *((uae_u32 *)&p[4]) = 0x80000000;
  564. }
  565.  
  566. static __inline__ uae_u32 IS_NEGATIVE(float80 p)
  567. {
  568.     return( (p[9] & 0x80) != 0 );
  569. }
  570.  
  571.  
  572. /* ---------------------------- Conversions ---------------------------- */
  573.  
  574. static void signed_to_extended( uae_s32 x, float80 f ) REGPARAM;
  575. static void signed_to_extended( uae_s32 x, float80 f )
  576. {
  577.     FPU_CONSISTENCY_CHECK_START();
  578.     
  579. /*    _asm {
  580.         MOV            ESI, [f]
  581.     FILD    DWORD PTR [x]
  582.         FSTP    TBYTE PTR [ESI]
  583.     } */
  584.     
  585.     _ASM(    "fildl    %1\n"
  586.             "fstpt    %0\n"
  587.         :    "=m" (*f)
  588.         :    "m" (x)
  589.         );
  590.     
  591.     D(bug("signed_to_extended (%X) = %s\r\n",(int)x,etos(f)));
  592.     FPU_CONSISTENCY_CHECK_STOP("signed_to_extended");
  593. }
  594.  
  595. static uae_s32 extended_to_signed_32( float80 f ) REGPARAM;
  596. static uae_s32 extended_to_signed_32( float80 f )
  597. {
  598.     FPU_CONSISTENCY_CHECK_START();
  599.     volatile uae_s32 tmp;
  600.     volatile WORD sw_temp;
  601.     
  602. /*    _asm {
  603.         MOV            EDI, [f]
  604.         FLD     TBYTE PTR [EDI]
  605.     FISTP   DWORD PTR tmp
  606.     FNSTSW  sw_temp
  607.     } */
  608.  
  609.     _ASM(    "fldt    %2\n"
  610.             "fistpl    %0\n"
  611.             "fnstsw    %1\n"
  612.         :    "=m" (tmp), "=m" (sw_temp)
  613.         :    "m" (*f)
  614.         );
  615.     
  616.     if(sw_temp & SW_EXCEPTION_MASK) {
  617. //        _asm FNCLEX
  618.         _ASM("fnclex");
  619.         if(sw_temp & (SW_OE|SW_UE|SW_DE|SW_IE)) { // Map SW_OE to OPERR.
  620.             sw |= SW_IE;
  621.             sw_accrued |= SW_IE;
  622.             // Setting the value to zero might not be the right way to go,
  623.             // but I'll leave it like this for now.
  624.             tmp = 0;
  625.         }
  626.         if(sw_temp & SW_PE) {
  627.             sw |= SW_PE;
  628.             sw_accrued |= SW_PE;
  629.         }
  630.     }
  631.  
  632.     D(bug("extended_to_signed_32 (%s) = %X\r\n",etos(f),(int)tmp));
  633.     FPU_CONSISTENCY_CHECK_STOP("extended_to_signed_32");
  634.     return tmp;
  635. }
  636.  
  637. static uae_s16 extended_to_signed_16( float80 f ) REGPARAM;
  638. static uae_s16 extended_to_signed_16( float80 f )
  639. {
  640.     FPU_CONSISTENCY_CHECK_START();
  641.     volatile uae_s16 tmp;
  642.     volatile WORD sw_temp;
  643.  
  644. /*    _asm {
  645.         MOV            EDI, [f]
  646.         FLD     TBYTE PTR [EDI]
  647.     FISTP   WORD PTR tmp
  648.     FNSTSW  sw_temp
  649.     } */
  650.     
  651.     _ASM(    "fldt    %2\n"
  652.             "fistp    %0\n"
  653.             "fnstsw    %1\n"
  654.         :    "=m" (tmp), "=m" (sw_temp)
  655.         :    "m" (*f)
  656.         );
  657.  
  658.     if(sw_temp & SW_EXCEPTION_MASK) {
  659. //        _asm FNCLEX
  660.         _ASM("fnclex");
  661.         if(sw_temp & (SW_OE|SW_UE|SW_DE|SW_IE)) { // Map SW_OE to OPERR.
  662.             sw |= SW_IE;
  663.             sw_accrued |= SW_IE;
  664.             tmp = 0;
  665.         }
  666.         if(sw_temp & SW_PE) {
  667.             sw |= SW_PE;
  668.             sw_accrued |= SW_PE;
  669.         }
  670.     }
  671.  
  672.     D(bug("extended_to_signed_16 (%s) = %X\r\n",etos(f),(int)tmp));
  673.     FPU_CONSISTENCY_CHECK_STOP("extended_to_signed_16");
  674.     return tmp;
  675. }
  676.  
  677. static uae_s8 extended_to_signed_8( float80 f ) REGPARAM;
  678. static uae_s8 extended_to_signed_8( float80 f )
  679. {
  680.     FPU_CONSISTENCY_CHECK_START();
  681.     volatile uae_s16 tmp;
  682.     volatile WORD sw_temp;
  683.     
  684. /*    _asm {
  685.         MOV            EDI, [f]
  686.         FLD     TBYTE PTR [EDI]
  687.     FISTP   WORD PTR tmp
  688.     FNSTSW  sw_temp
  689.     } */
  690.     
  691.     _ASM(    "fldt    %2\n"
  692.             "fistp    %0\n"
  693.             "fnstsw    %1\n"
  694.         :    "=m" (tmp), "=m" (sw_temp)
  695.         :    "m" (*f)
  696.         );
  697.  
  698.     if(sw_temp & SW_EXCEPTION_MASK) {
  699. //        _asm FNCLEX
  700.         _ASM("fnclex");
  701.         if(sw_temp & (SW_OE|SW_UE|SW_DE|SW_IE)) { // Map SW_OE to OPERR.
  702.             sw |= SW_IE;
  703.             sw_accrued |= SW_IE;
  704.             tmp = 0;
  705.         }
  706.         if(sw_temp & SW_PE) {
  707.             sw |= SW_PE;
  708.             sw_accrued |= SW_PE;
  709.         }
  710.     }
  711.  
  712.     if(tmp > 127 || tmp < -128) { // OPERR
  713.         sw |= SW_IE;
  714.         sw_accrued |= SW_IE;
  715.     }
  716.  
  717.     D(bug("extended_to_signed_8 (%s) = %X\r\n",etos(f),(int)tmp));
  718.     FPU_CONSISTENCY_CHECK_STOP("extended_to_signed_8");
  719.     return (uae_s8)tmp;
  720. }
  721.  
  722. static void double_to_extended( double x, float80 f ) REGPARAM;
  723. static void double_to_extended( double x, float80 f )
  724. {
  725.     FPU_CONSISTENCY_CHECK_START();
  726.  
  727. /*    _asm {
  728.         MOV            EDI, [f]
  729.     FLD     QWORD PTR [x]
  730.         FSTP    TBYTE PTR [EDI]
  731.     } */
  732.     
  733.     _ASM(    "fldl    %1\n"
  734.             "fstpt    %0\n"
  735.         :    "=m" (*f)
  736.         :    "m" (x)
  737.         );
  738.     
  739.     FPU_CONSISTENCY_CHECK_STOP("double_to_extended");
  740. }
  741.  
  742. static double extended_to_double( float80 f ) REGPARAM;
  743. static double extended_to_double( float80 f )
  744. {
  745.     FPU_CONSISTENCY_CHECK_START();
  746.     volatile double result;
  747.  
  748. /*    _asm {
  749.         MOV            ESI, [f]
  750.         FLD     TBYTE PTR [ESI]
  751.     FSTP    QWORD PTR result
  752.     } */
  753.     
  754.     _ASM(    "fldt    %1\n"
  755.             "fstpl    %0\n"
  756.         :    "=m" (result)
  757.         :    "m" (*f)
  758.         );
  759.     
  760.     FPU_CONSISTENCY_CHECK_STOP("extended_to_double");
  761.     return result;
  762. }
  763.  
  764. static void to_single( uae_u32 src, float80 f ) REGPARAM;
  765. static void to_single( uae_u32 src, float80 f )
  766. {
  767.     FPU_CONSISTENCY_CHECK_START();
  768. /*    _asm {
  769.         MOV            ESI, [f]
  770.     FLD     DWORD PTR src
  771.         FSTP    TBYTE PTR [ESI]
  772.     } */
  773.     
  774.     _ASM(    "flds    %1\n"
  775.             "fstpt    %0\n"
  776.         :    "=m" (*f)
  777.         :    "m" (src)
  778.         );
  779.  
  780.     D(bug("to_single (%X) = %s\r\n",src,etos(f)));
  781.     FPU_CONSISTENCY_CHECK_STOP("to_single");
  782. }
  783.  
  784. // TODO_BIGENDIAN
  785. static void to_exten_no_normalize( uae_u32 wrd1, uae_u32 wrd2, uae_u32 wrd3, float80 f ) REGPARAM;
  786. static void to_exten_no_normalize( uae_u32 wrd1, uae_u32 wrd2, uae_u32 wrd3, float80 f )
  787. {
  788.     FPU_CONSISTENCY_CHECK_START();
  789.     uae_u32 *p = (uae_u32 *)f;
  790.  
  791.     uae_u32 sign =  (wrd1 & 0x80000000) >> 16;
  792.     uae_u32 exp  = (wrd1 >> 16) & 0x7fff;
  793.     p[0] = wrd3;
  794.     p[1] = wrd2;
  795.     *((uae_u16 *)&p[2]) = (uae_u16)(sign | exp);
  796.  
  797.     D(bug("to_exten_no_normalize (%X,%X,%X) = %s\r\n",wrd1,wrd2,wrd3,etos(f)));
  798.     FPU_CONSISTENCY_CHECK_STOP("to_exten_no_normalize");
  799. }
  800.  
  801. static void to_exten( uae_u32 wrd1, uae_u32 wrd2, uae_u32 wrd3, float80 f ) REGPARAM;
  802. static void to_exten( uae_u32 wrd1, uae_u32 wrd2, uae_u32 wrd3, float80 f )
  803. {
  804.     FPU_CONSISTENCY_CHECK_START();
  805.     uae_u32 *p = (uae_u32 *)f;
  806.  
  807.     uae_u32 sign =  (wrd1 & 0x80000000) >> 16;
  808.     uae_u32 exp  = (wrd1 >> 16) & 0x7fff;
  809.  
  810.     // The explicit integer bit is not set, must normalize.
  811.     // Don't do it for zeroes, infinities or nans.
  812.     if( (wrd2 & 0x80000000) == 0 && exp != 0 && exp != 0x7FFF ) {
  813.         D(bug("to_exten denormalized mantissa (%X,%X,%X)\r\n",wrd1,wrd2,wrd3));
  814.         if( wrd2 | wrd3 ) {
  815.             // mantissa, not fraction.
  816.             uae_u64 man = ((uae_u64)wrd2 << 32) | wrd3;
  817.             while( exp > 0 && (man & UVAL64(0x8000000000000000)) == 0 ) {
  818.                 man <<= 1;
  819.                 exp--;
  820.             }
  821.             wrd2 = (uae_u32)( man >> 32 );
  822.             wrd3 = (uae_u32)( man & 0xFFFFFFFF );
  823.             if( exp == 0 || (wrd2 & 0x80000000) == 0 ) {
  824.                 // underflow
  825.                 wrd2 = wrd3 = exp = 0;
  826.                 sign = 0;
  827.             }
  828.         } else {
  829.             if(exp != 0x7FFF && exp != 0) {
  830.                 // Make a non-signaling nan.
  831.                 exp = 0x7FFF;
  832.                 sign = 0;
  833.                 wrd2 = 0x80000000;
  834.             }
  835.         }
  836.     }
  837.  
  838.     p[0] = wrd3;
  839.     p[1] = wrd2;
  840.     *((uae_u16 *)&p[2]) = (uae_u16)(sign | exp);
  841.  
  842.     D(bug("to_exten (%X,%X,%X) = %s\r\n",wrd1,wrd2,wrd3,etos(f)));
  843.     FPU_CONSISTENCY_CHECK_STOP("to_exten");
  844. }
  845.  
  846. static void to_double( uae_u32 wrd1, uae_u32 wrd2, float80 f ) REGPARAM;
  847. static void to_double( uae_u32 wrd1, uae_u32 wrd2, float80 f )
  848. {
  849.     FPU_CONSISTENCY_CHECK_START();
  850.     
  851.     // gb-- make GCC happy
  852.     union {
  853.         uae_u64 q;
  854.         uae_u32 l[2];
  855.     } src;
  856.     
  857.     // Should renormalize if needed. I'm not sure that x86 and m68k FPU's
  858.     // do it the sama way. This should be extremely rare however.
  859.     // to_exten() is often called with denormalized values.
  860.  
  861.     src.l[0] = wrd2;
  862.     src.l[1] = wrd1;
  863.  
  864. /*    _asm {
  865.     FLD     QWORD PTR src
  866.         MOV            EDI, [f]
  867.         FSTP    TBYTE PTR [EDI]
  868.     } */
  869.     
  870.     _ASM(    "fldl    %1\n"
  871.             "fstpt    %0\n"
  872.         :    "=m" (*f)
  873.         :    "m" (src.q)
  874.         );
  875.  
  876.     D(bug("to_double (%X,%X) = %s\r\n",wrd1,wrd2,etos(f)));
  877.     FPU_CONSISTENCY_CHECK_STOP("to_double");
  878. }
  879.  
  880. static uae_u32 from_single( float80 f ) REGPARAM;
  881. static uae_u32 from_single( float80 f )
  882. {
  883.     FPU_CONSISTENCY_CHECK_START();
  884.     volatile uae_u32 dest;
  885.     volatile WORD sw_temp;
  886.  
  887. /*    _asm {
  888.         MOV            EDI, [f]
  889.     FLD     TBYTE PTR [EDI]
  890.         FSTP    DWORD PTR dest
  891.     FNSTSW  sw_temp
  892.     } */
  893.     
  894.     _ASM(    "fldt    %2\n"
  895.             "fstps    %0\n"
  896.             "fnstsw    %1\n"
  897.         :    "=m" (dest), "=m" (sw_temp)
  898.         :    "m" (*f)
  899.         );
  900.  
  901.     sw_temp &= SW_EXCEPTION_MASK;
  902.     if(sw_temp) {
  903. //        _asm FNCLEX
  904.         asm("fnclex");
  905.         sw = (sw & ~SW_EXCEPTION_MASK) | sw_temp;
  906.         sw_accrued |= sw_temp;
  907.     }
  908.  
  909.     D(bug("from_single (%s) = %X\r\n",etos(f),dest));
  910.     FPU_CONSISTENCY_CHECK_STOP("from_single");
  911.     return dest;
  912. }
  913.  
  914. // TODO_BIGENDIAN
  915. static void from_exten( float80 f, uae_u32 *wrd1, uae_u32 *wrd2, uae_u32 *wrd3 ) REGPARAM;
  916. static void from_exten( float80 f, uae_u32 *wrd1, uae_u32 *wrd2, uae_u32 *wrd3 )
  917. {
  918.     FPU_CONSISTENCY_CHECK_START();
  919.     uae_u32 *p = (uae_u32 *)f;
  920.     *wrd3 = p[0];
  921.     *wrd2 = p[1];
  922.     *wrd1 = ( (uae_u32)*((uae_u16 *)&p[2]) ) << 16;
  923.  
  924.     D(bug("from_exten (%s) = %X,%X,%X\r\n",etos(f),*wrd1,*wrd2,*wrd3));
  925.     FPU_CONSISTENCY_CHECK_STOP("from_exten");
  926. }
  927.  
  928. static void from_double( float80 f, uae_u32 *wrd1, uae_u32 *wrd2 ) REGPARAM;
  929. static void from_double( float80 f, uae_u32 *wrd1, uae_u32 *wrd2 )
  930. {
  931.     FPU_CONSISTENCY_CHECK_START();
  932.     volatile uae_u32 dest[2];
  933.     volatile WORD sw_temp;
  934.  
  935. /*    _asm {
  936.         MOV            EDI, [f]
  937.     FLD     TBYTE PTR [EDI]
  938.         FSTP    QWORD PTR dest
  939.     FNSTSW  sw_temp
  940.     } */
  941.     
  942.     _ASM(    "fldt    %2\n"
  943.             "fstpl    %0\n"
  944.             "fnstsw    %1\n"
  945.         :    "=m" (dest), "=m" (sw_temp)
  946.         :    "m" (*f)
  947.         );
  948.  
  949.     sw_temp &= SW_EXCEPTION_MASK;
  950.     if(sw_temp) {
  951. //        _asm FNCLEX
  952.         asm("fnclex");
  953.         sw = (sw & ~SW_EXCEPTION_MASK) | sw_temp;
  954.         sw_accrued |= sw_temp;
  955.     }
  956.  
  957.     // TODO: There is a partial memory stall, nothing happens until FSTP retires.
  958.     // On PIII, could use MMX move w/o any penalty.
  959.     *wrd2 = dest[0];
  960.     *wrd1 = dest[1];
  961.  
  962.     D(bug("from_double (%s) = %X,%X\r\n",etos(f),dest[1],dest[0]));
  963.     FPU_CONSISTENCY_CHECK_STOP("from_double");
  964. }
  965.  
  966. static void do_fmove( float80 dest, float80 src ) REGPARAM;
  967. static void do_fmove( float80 dest, float80 src )
  968. {
  969.     FPU_CONSISTENCY_CHECK_START();
  970. /*    _asm {
  971.         MOV            ESI, [src]
  972.         MOV            EDI, [dest]
  973.     FLD     TBYTE PTR [ESI]
  974.         FXAM
  975.     FNSTSW  sw
  976.         FSTP    TBYTE PTR [EDI]
  977.     } */
  978.     
  979.     _ASM(    "fldt    %2\n"
  980.             "fxam    \n"
  981.             "fnstsw    %0\n"
  982.             "fstpt    %1\n"
  983.         :    "=m" (sw), "=m" (*dest)
  984.         :    "m" (*src)
  985.         );
  986.     FPU_CONSISTENCY_CHECK_STOP("do_fmove");
  987. }
  988.  
  989. /*
  990. static void do_fmove_no_status( float80 dest, float80 src ) REGPARAM;
  991. static void do_fmove_no_status( float80 dest, float80 src )
  992. {
  993.     FPU_CONSISTENCY_CHECK_START();
  994.     _asm {
  995.         MOV            ESI, [src]
  996.         MOV            EDI, [dest]
  997.     FLD     TBYTE PTR [ESI]
  998.         FSTP    TBYTE PTR [EDI]
  999.     }
  1000.     FPU_CONSISTENCY_CHECK_STOP("do_fmove_no_status");
  1001. }
  1002. */
  1003.  
  1004.  
  1005. /* ---------------------------- Operations ---------------------------- */
  1006.  
  1007. static void do_fint( float80 dest, float80 src ) REGPARAM;
  1008. static void do_fint( float80 dest, float80 src )
  1009. {
  1010.     FPU_CONSISTENCY_CHECK_START();
  1011. /*    _asm {
  1012.         MOV            ESI, [src]
  1013.         MOV            EDI, [dest]
  1014.     FLD     TBYTE PTR [ESI]
  1015.         FRNDINT
  1016.         FXAM
  1017.     FNSTSW  sw
  1018.         FSTP    TBYTE PTR [EDI]
  1019.     } */
  1020.     _ASM(    "fldt    %2\n"
  1021.             "frndint\n"
  1022.             "fxam    \n"
  1023.             "fnstsw    %0\n"
  1024.             "fstpt    %1\n"
  1025.         :    "=m" (sw), "=m" (*dest)
  1026.         :    "m" (*src)
  1027.         );
  1028.     if(sw & SW_EXCEPTION_MASK) {
  1029. //        _asm FNCLEX
  1030.         _ASM("fnclex");
  1031.         sw &= ~(SW_EXCEPTION_MASK - SW_PE);
  1032.         sw_accrued |= sw;
  1033.     }
  1034.     FPU_CONSISTENCY_CHECK_STOP("do_fint");
  1035. }
  1036.  
  1037. static void do_fintrz( float80 dest, float80 src ) REGPARAM;
  1038. static void do_fintrz( float80 dest, float80 src )
  1039. {
  1040.     FPU_CONSISTENCY_CHECK_START();
  1041.     volatile WORD cw_temp;
  1042.  
  1043. /*    _asm {
  1044.         MOV            ESI, [src]
  1045.         MOV            EDI, [dest]
  1046.         FSTCW   cw_temp
  1047.         and            cw_temp, ~X86_ROUND_CONTROL_MASK
  1048.         or            cw_temp, CW_RC_ZERO
  1049.     FLDCW   cw_temp
  1050.     FLD     TBYTE PTR [ESI]
  1051.         FRNDINT
  1052.         FXAM
  1053.     FNSTSW  sw
  1054.     FLDCW   cw
  1055.         FSTP    TBYTE PTR [EDI]
  1056.     } */
  1057.     
  1058.     _ASM(    "fstcw    %0\n"
  1059.             "andl    $(~X86_ROUND_CONTROL_MASK), %0\n"
  1060.             "orl    $CW_RC_ZERO, %0\n"
  1061.             "fldcw    %0\n"
  1062.             "fldt    %3\n"
  1063.             "frndint\n"
  1064.             "fxam    \n"
  1065.             "fnstsw    %1\n"
  1066.             "fldcw    %4\n"
  1067.             "fstpt    %2\n"
  1068.         :    "+m" (cw_temp), "=m" (sw), "=m" (*dest)
  1069.         :    "m" (*src), "m" (cw)
  1070.         );
  1071.     
  1072.     if(sw & SW_EXCEPTION_MASK) {
  1073. //        _asm FNCLEX
  1074.         _ASM("fnclex");
  1075.         sw &= ~(SW_EXCEPTION_MASK - SW_PE);
  1076.         sw_accrued |= sw;
  1077.     }
  1078.     FPU_CONSISTENCY_CHECK_STOP("do_fintrz");
  1079. }
  1080.  
  1081. static void do_fsqrt( float80 dest, float80 src ) REGPARAM;
  1082. static void do_fsqrt( float80 dest, float80 src )
  1083. {
  1084.     FPU_CONSISTENCY_CHECK_START();
  1085. /*    _asm {
  1086.         MOV            ESI, [src]
  1087.         MOV            EDI, [dest]
  1088.     FLD     TBYTE PTR [ESI]
  1089.         FSQRT
  1090.         FXAM
  1091.     FNSTSW  sw
  1092.         FSTP    TBYTE PTR [EDI]
  1093.     } */
  1094.     
  1095.     _ASM(    "fldt    %2\n"
  1096.             "fsqrt    \n"
  1097.             "fxam    \n"
  1098.             "fnstsw    %0\n"
  1099.             "fstpt    %1\n"
  1100.         :    "=m" (sw), "=m" (*dest)
  1101.         :    "m" (*src)
  1102.         );
  1103.     
  1104.     if(sw & SW_EXCEPTION_MASK) {
  1105. //        _asm FNCLEX
  1106.         _ASM("fnclex");
  1107.         sw &= ~(SW_EXCEPTION_MASK - SW_IE - SW_PE);
  1108.         sw_accrued |= sw;
  1109.     }
  1110.     FPU_CONSISTENCY_CHECK_STOP("do_fsqrt");
  1111. }
  1112.  
  1113. static void do_ftst( float80 src ) REGPARAM;
  1114. static void do_ftst( float80 src )
  1115. {
  1116.     FPU_CONSISTENCY_CHECK_START();
  1117. /*    _asm {
  1118.         MOV            ESI, [src]
  1119.     FLD     TBYTE PTR [ESI]
  1120.         FXAM
  1121.     FNSTSW  sw
  1122.         FSTP    ST(0)
  1123.     } */
  1124.     
  1125.     _ASM(    "fldt    %1\n"
  1126.             "fxam    \n"
  1127.             "fnstsw    %0\n"
  1128.             "fstp    %%st(0)\n"
  1129.         :    "=m" (sw)
  1130.         :    "m" (*src)
  1131.         );
  1132.     
  1133.     if(sw & SW_EXCEPTION_MASK) {
  1134. //        _asm FNCLEX
  1135.         _ASM("fnclex");
  1136.         sw &= ~SW_EXCEPTION_MASK;
  1137.     }
  1138.     FPU_CONSISTENCY_CHECK_STOP("do_ftst");
  1139. }
  1140.  
  1141. // These functions are calculated in 53 bits accuracy only.
  1142. // Exception checking is not complete.
  1143. static void do_fsinh( float80 dest, float80 src ) REGPARAM;
  1144. static void do_fsinh( float80 dest, float80 src )
  1145. {
  1146.     FPU_CONSISTENCY_CHECK_START();
  1147.     double x, y;
  1148.     x = extended_to_double( src );
  1149.     y = sinh(x);
  1150.     double_to_extended( y, dest );
  1151.     do_ftst( dest );
  1152.     FPU_CONSISTENCY_CHECK_STOP("do_fsinh");
  1153. }
  1154.  
  1155. static void do_flognp1( float80 dest, float80 src ) REGPARAM;
  1156. static void do_flognp1( float80 dest, float80 src )
  1157. {
  1158.     FPU_CONSISTENCY_CHECK_START();
  1159.     double x, y;
  1160.     x = extended_to_double( src );
  1161.     y = log (x + 1.0);
  1162.     double_to_extended( y, dest );
  1163.     do_ftst( dest );
  1164.     FPU_CONSISTENCY_CHECK_STOP("do_flognp1");
  1165. }
  1166.  
  1167. static void do_fetoxm1( float80 dest, float80 src ) REGPARAM;
  1168. static void do_fetoxm1( float80 dest, float80 src )
  1169. {
  1170.     FPU_CONSISTENCY_CHECK_START();
  1171.     double x, y;
  1172.     x = extended_to_double( src );
  1173.     y = exp (x) - 1.0;
  1174.     double_to_extended( y, dest );
  1175.     do_ftst( dest );
  1176.     FPU_CONSISTENCY_CHECK_STOP("do_fetoxm1");
  1177. }
  1178.  
  1179. static void do_ftanh( float80 dest, float80 src ) REGPARAM;
  1180. static void do_ftanh( float80 dest, float80 src )
  1181. {
  1182.     FPU_CONSISTENCY_CHECK_START();
  1183.     double x, y;
  1184.     x = extended_to_double( src );
  1185.     y = tanh (x);
  1186.     double_to_extended( y, dest );
  1187.     do_ftst( dest );
  1188.     FPU_CONSISTENCY_CHECK_STOP("do_ftanh");
  1189. }
  1190.  
  1191. static void do_fatan( float80 dest, float80 src ) REGPARAM;
  1192. static void do_fatan( float80 dest, float80 src )
  1193. {
  1194.     FPU_CONSISTENCY_CHECK_START();
  1195.     double x, y;
  1196.     x = extended_to_double( src );
  1197.     y = atan (x);
  1198.     double_to_extended( y, dest );
  1199.     do_ftst( dest );
  1200.     FPU_CONSISTENCY_CHECK_STOP("do_fatan");
  1201. }
  1202.  
  1203. static void do_fasin( float80 dest, float80 src ) REGPARAM;
  1204. static void do_fasin( float80 dest, float80 src )
  1205. {
  1206.     FPU_CONSISTENCY_CHECK_START();
  1207.     double x, y;
  1208.     x = extended_to_double( src );
  1209.     y = asin (x);
  1210.     double_to_extended( y, dest );
  1211.     do_ftst( dest );
  1212.     FPU_CONSISTENCY_CHECK_STOP("do_fasin");
  1213. }
  1214.  
  1215. static void do_fatanh( float80 dest, float80 src ) REGPARAM;
  1216. static void do_fatanh( float80 dest, float80 src )
  1217. {
  1218.     FPU_CONSISTENCY_CHECK_START();
  1219.     double x, y;
  1220.     x = extended_to_double( src );
  1221.     y = log ((1 + x) / (1 - x)) / 2;
  1222.     double_to_extended( y, dest );
  1223.     do_ftst( dest );
  1224.     FPU_CONSISTENCY_CHECK_STOP("do_fatanh");
  1225. }
  1226.  
  1227. static void do_fetox( float80 dest, float80 src ) REGPARAM;
  1228. static void do_fetox( float80 dest, float80 src )
  1229. {
  1230.     FPU_CONSISTENCY_CHECK_START();
  1231.     double x, y;
  1232.     x = extended_to_double( src );
  1233.     y = exp (x);
  1234.     double_to_extended( y, dest );
  1235.     do_ftst( dest );
  1236.     FPU_CONSISTENCY_CHECK_STOP("do_fetox");
  1237. }
  1238.  
  1239. static void do_ftwotox( float80 dest, float80 src ) REGPARAM;
  1240. static void do_ftwotox( float80 dest, float80 src )
  1241. {
  1242.     FPU_CONSISTENCY_CHECK_START();
  1243.     double x, y;
  1244.     x = extended_to_double( src );
  1245.     y = pow(2.0, x);
  1246.     double_to_extended( y, dest );
  1247.     do_ftst( dest );
  1248.     FPU_CONSISTENCY_CHECK_STOP("do_ftwotox");
  1249. }
  1250.  
  1251. static void do_ftentox( float80 dest, float80 src ) REGPARAM;
  1252. static void do_ftentox( float80 dest, float80 src )
  1253. {
  1254.     FPU_CONSISTENCY_CHECK_START();
  1255.     double x, y;
  1256.     x = extended_to_double( src );
  1257.     y = pow(10.0, x);
  1258.     double_to_extended( y, dest );
  1259.     do_ftst( dest );
  1260.     FPU_CONSISTENCY_CHECK_STOP("do_ftentox");
  1261. }
  1262.  
  1263. static void do_flogn( float80 dest, float80 src ) REGPARAM;
  1264. static void do_flogn( float80 dest, float80 src )
  1265. {
  1266.     FPU_CONSISTENCY_CHECK_START();
  1267.     double x, y;
  1268.     x = extended_to_double( src );
  1269.     y = log (x);
  1270.     double_to_extended( y, dest );
  1271.     do_ftst( dest );
  1272.     FPU_CONSISTENCY_CHECK_STOP("do_flogn");
  1273. }
  1274.  
  1275. static void do_flog10( float80 dest, float80 src ) REGPARAM;
  1276. static void do_flog10( float80 dest, float80 src )
  1277. {
  1278.     FPU_CONSISTENCY_CHECK_START();
  1279.     double x, y;
  1280.     x = extended_to_double( src );
  1281.     y = log10 (x);
  1282.     double_to_extended( y, dest );
  1283.     do_ftst( dest );
  1284.     FPU_CONSISTENCY_CHECK_STOP("do_flog10");
  1285. }
  1286.  
  1287. static void do_flog2( float80 dest, float80 src ) REGPARAM;
  1288. static void do_flog2( float80 dest, float80 src )
  1289. {
  1290.     FPU_CONSISTENCY_CHECK_START();
  1291.     double x, y;
  1292.     x = extended_to_double( src );
  1293.     y = log (x) / log (2.0);
  1294.     double_to_extended( y, dest );
  1295.     do_ftst( dest );
  1296.     FPU_CONSISTENCY_CHECK_STOP("do_flog2");
  1297. }
  1298.  
  1299. static void do_facos( float80 dest, float80 src ) REGPARAM;
  1300. static void do_facos( float80 dest, float80 src )
  1301. {
  1302.     FPU_CONSISTENCY_CHECK_START();
  1303.     double x, y;
  1304.     x = extended_to_double( src );
  1305.     y = acos(x);
  1306.     double_to_extended( y, dest );
  1307.     do_ftst( dest );
  1308.     FPU_CONSISTENCY_CHECK_STOP("do_facos");
  1309. }
  1310.  
  1311. static void do_fcosh( float80 dest, float80 src ) REGPARAM;
  1312. static void do_fcosh( float80 dest, float80 src )
  1313. {
  1314.     FPU_CONSISTENCY_CHECK_START();
  1315.     double x, y;
  1316.     x = extended_to_double( src );
  1317.     y = cosh(x);
  1318.     double_to_extended( y, dest );
  1319.     do_ftst( dest );
  1320.     FPU_CONSISTENCY_CHECK_STOP("do_fcosh");
  1321. }
  1322.  
  1323. static void do_fsin( float80 dest, float80 src ) REGPARAM;
  1324. static void do_fsin( float80 dest, float80 src )
  1325. {
  1326.     FPU_CONSISTENCY_CHECK_START();
  1327. /*    _asm {
  1328.         MOV            ESI, [src]
  1329.         MOV            EDI, [dest]
  1330.     FLD     TBYTE PTR [ESI]
  1331.         FSIN
  1332.         FXAM
  1333.     FNSTSW  sw
  1334.         FSTP    TBYTE PTR [EDI]
  1335.     } */
  1336.     _ASM(    "fldt    %2\n"
  1337.             "fsin    \n"
  1338.             "fxam    \n"
  1339.             "fnstsw    %0\n"
  1340.             "fstpt    %1\n"
  1341.         :    "=m" (sw), "=m" (*dest)
  1342.         :    "m" (*src)
  1343.         );
  1344.     if(sw & SW_EXCEPTION_MASK) {
  1345. //        _asm FNCLEX
  1346.         _ASM("fnclex");
  1347.         sw &= ~(SW_EXCEPTION_MASK - SW_IE - SW_PE);
  1348.         sw_accrued |= sw;
  1349.     }
  1350.     FPU_CONSISTENCY_CHECK_STOP("do_fsin");
  1351. }
  1352.  
  1353. // TODO: Should check for out-of-range condition (partial tangent)
  1354. static void do_ftan( float80 dest, float80 src ) REGPARAM;
  1355. static void do_ftan( float80 dest, float80 src )
  1356. {
  1357.     FPU_CONSISTENCY_CHECK_START();
  1358. /*    _asm {
  1359.         MOV            ESI, [src]
  1360.         MOV            EDI, [dest]
  1361.     FLD     TBYTE PTR [ESI]
  1362.         FPTAN
  1363.         FSTP    ST(0)    ; pop 1.0 (the 8087/287 compatibility thing)
  1364.         FXAM
  1365.     FNSTSW  sw
  1366.         FSTP    TBYTE PTR [EDI]
  1367.     } */
  1368.     _ASM(    "fldt    %2\n"
  1369.             "fptan    \n"
  1370.             "fstp    %%st(0)\n"
  1371.             "fxam    \n"
  1372.             "fnstsw    %0\n"
  1373.             "fstpt    %1\n"
  1374.         :    "=m" (sw), "=m" (*dest)
  1375.         :    "m" (*src)
  1376.         );
  1377.     if(sw & SW_EXCEPTION_MASK) {
  1378. //        _asm FNCLEX
  1379.         _ASM("fnclex");
  1380.         sw &= ~(SW_EXCEPTION_MASK - SW_IE - SW_PE - SW_UE);
  1381.         sw_accrued |= sw;
  1382.     }
  1383.     FPU_CONSISTENCY_CHECK_STOP("do_ftan");
  1384. }
  1385.  
  1386. static void do_fabs( float80 dest, float80 src ) REGPARAM;
  1387. static void do_fabs( float80 dest, float80 src )
  1388. {
  1389.     FPU_CONSISTENCY_CHECK_START();
  1390. /*    _asm {
  1391.         MOV            ESI, [src]
  1392.         MOV            EDI, [dest]
  1393.     FLD     TBYTE PTR [ESI]
  1394.         FABS
  1395.         FXAM
  1396.     FNSTSW  sw
  1397.         FSTP    TBYTE PTR [EDI]
  1398.     } */
  1399.     _ASM(    "fldt    %2\n"
  1400.             "fabs    \n"
  1401.             "fxam    \n"
  1402.             "fnstsw    %0\n"
  1403.             "fstpt    %1\n"
  1404.         :    "=m" (sw), "=m" (*dest)
  1405.         :    "m" (*src)
  1406.         );
  1407.     // x86 fabs should not rise any exceptions (except stack underflow)
  1408.     if(sw & SW_EXCEPTION_MASK) {
  1409. //        _asm FNCLEX
  1410.         _ASM("fnclex");
  1411.         sw &= ~SW_EXCEPTION_MASK;
  1412.     }
  1413.     FPU_CONSISTENCY_CHECK_STOP("do_fabs");
  1414. }
  1415.  
  1416. static void do_fneg( float80 dest, float80 src ) REGPARAM;
  1417. static void do_fneg( float80 dest, float80 src )
  1418. {
  1419.     FPU_CONSISTENCY_CHECK_START();
  1420. /*    _asm {
  1421.         MOV            ESI, [src]
  1422.         MOV            EDI, [dest]
  1423.     FLD     TBYTE PTR [ESI]
  1424.         FCHS
  1425.         FXAM
  1426.     FNSTSW  sw
  1427.         FSTP    TBYTE PTR [EDI]
  1428.     } */
  1429.     _ASM(    "fldt    %2\n"
  1430.             "fchs    \n"
  1431.             "fxam    \n"
  1432.             "fnstsw    %0\n"
  1433.             "fstpt    %1\n"
  1434.         :    "=m" (sw), "=m" (*dest)
  1435.         :    "m" (*src)
  1436.         );
  1437.     // x86 fchs should not rise any exceptions (except stack underflow)
  1438.     if(sw & SW_EXCEPTION_MASK) {
  1439. //        _asm FNCLEX
  1440.         _ASM("fnclex");
  1441.         sw &= ~SW_EXCEPTION_MASK;
  1442.     }
  1443.     FPU_CONSISTENCY_CHECK_STOP("do_fneg");
  1444. }
  1445.  
  1446. static void do_fcos( float80 dest, float80 src ) REGPARAM;
  1447. static void do_fcos( float80 dest, float80 src )
  1448. {
  1449.     FPU_CONSISTENCY_CHECK_START();
  1450. /*    _asm {
  1451.         MOV            ESI, [src]
  1452.         MOV            EDI, [dest]
  1453.     FLD     TBYTE PTR [ESI]
  1454.         FCOS
  1455.         FXAM
  1456.     FNSTSW  sw
  1457.         FSTP    TBYTE PTR [EDI]
  1458.     } */
  1459.     _ASM(    "fldt    %2\n"
  1460.             "fcos    \n"
  1461.             "fxam    \n"
  1462.             "fnstsw    %0\n"
  1463.             "fstpt    %1\n"
  1464.         :    "=m" (sw), "=m" (*dest)
  1465.         :    "m" (*src)
  1466.         );
  1467.     if(sw & SW_EXCEPTION_MASK) {
  1468. //        _asm FNCLEX
  1469.         _ASM("fnclex");
  1470.         sw &= ~(SW_EXCEPTION_MASK - SW_IE - SW_PE);
  1471.         sw_accrued |= sw;
  1472.     }
  1473.     FPU_CONSISTENCY_CHECK_STOP("do_fcos");
  1474. }
  1475.  
  1476. static void do_fgetexp( float80 dest, float80 src ) REGPARAM;
  1477. static void do_fgetexp( float80 dest, float80 src )
  1478. {
  1479.     FPU_CONSISTENCY_CHECK_START();
  1480. /*    _asm {
  1481.         MOV            ESI, [src]
  1482.         MOV            EDI, [dest]
  1483.     FLD     TBYTE PTR [ESI]
  1484.         FXTRACT
  1485.         FSTP    ST(0)                        ; pop mantissa
  1486.         FXAM
  1487.     FNSTSW  sw
  1488.         FSTP    TBYTE PTR [EDI]
  1489.     } */
  1490.     _ASM(    "fldt    %2\n"
  1491.             "fxtract\n"
  1492.             "fstp    %%st(0)\n"
  1493.             "fxam    \n"
  1494.             "fnstsw    %0\n"
  1495.             "fstpt    %1\n"
  1496.         :    "=m" (sw), "=m" (*dest)
  1497.         :    "m" (*src)
  1498.         );
  1499.     if(sw & SW_EXCEPTION_MASK) {
  1500. //        _asm FNCLEX
  1501.         _ASM("fnclex");
  1502.         sw &= ~SW_EXCEPTION_MASK;
  1503.     }
  1504.     FPU_CONSISTENCY_CHECK_STOP("do_fgetexp");
  1505. }
  1506.  
  1507. static void do_fgetman( float80 dest, float80 src ) REGPARAM;
  1508. static void do_fgetman( float80 dest, float80 src )
  1509. {
  1510.     FPU_CONSISTENCY_CHECK_START();
  1511. /*    _asm {
  1512.         MOV            ESI, [src]
  1513.         MOV            EDI, [dest]
  1514.     FLD     TBYTE PTR [ESI]
  1515.         FXTRACT
  1516.         FXAM
  1517.     FNSTSW  sw
  1518.         FSTP    TBYTE PTR [EDI]
  1519.         FSTP    ST(0)                        ; pop exponent
  1520.     } */
  1521.     _ASM(    "fldt    %2\n"
  1522.             "fxtract\n"
  1523.             "fxam    \n"
  1524.             "fnstsw    %0\n"
  1525.             "fstpt    %1\n"
  1526.             "fstp    %%st(0)\n"
  1527.         :    "=m" (sw), "=m" (*dest)
  1528.         :    "m" (*src)
  1529.         );
  1530.     if(sw & SW_EXCEPTION_MASK) {
  1531. //        _asm FNCLEX
  1532.         _ASM("fnclex");
  1533.         sw &= ~SW_EXCEPTION_MASK;
  1534.     }
  1535.     FPU_CONSISTENCY_CHECK_STOP("do_fgetman");
  1536. }
  1537.  
  1538. static void do_fdiv( float80 dest, float80 src ) REGPARAM;
  1539. static void do_fdiv( float80 dest, float80 src )
  1540. {
  1541.     FPU_CONSISTENCY_CHECK_START();
  1542. /*    _asm {
  1543.         MOV            ESI, [src]
  1544.         MOV            EDI, [dest]
  1545.     FLD     TBYTE PTR [ESI]
  1546.     FLD     TBYTE PTR [EDI]
  1547.         FDIV        ST(0),ST(1)
  1548.         FXAM
  1549.     FNSTSW  sw
  1550.         FSTP    TBYTE PTR [EDI]
  1551.         FSTP    ST(0)
  1552.     } */
  1553.     _ASM(    "fldt    %2\n"
  1554.             "fldt    %1\n"
  1555.             "fdiv    %%st(1), %%st(0)\n"
  1556.             "fxam    \n"
  1557.             "fnstsw    %0\n"
  1558.             "fstpt    %1\n"
  1559.             "fstp    %%st(0)\n"
  1560.         :    "=m" (sw), "+m" (*dest)
  1561.         :    "m" (*src)
  1562.         );
  1563.     if(sw & SW_EXCEPTION_MASK) {
  1564. //        _asm FNCLEX
  1565.         _ASM("fnclex");
  1566.         sw_accrued |= sw;
  1567.     }
  1568.     FPU_CONSISTENCY_CHECK_STOP("do_fdiv");
  1569. }
  1570.  
  1571. // The sign of the quotient is the exclusive-OR of the sign bits
  1572. // of the source and destination operands.
  1573. // Quotient Byte is loaded with the sign and least significant
  1574. // seven bits of the quotient.
  1575.  
  1576. static void do_fmod( float80 dest, float80 src ) REGPARAM;
  1577. static void do_fmod( float80 dest, float80 src )
  1578. {
  1579.     FPU_CONSISTENCY_CHECK_START();
  1580.  
  1581.     volatile uint16 status;
  1582.     uae_u32 quot;
  1583. #if !USE_3_BIT_QUOTIENT
  1584.     WORD cw_temp;
  1585. #endif
  1586.  
  1587.     uae_u32 sign = (dest[9] ^ src[9]) & 0x80;
  1588.  
  1589. /*    _asm {
  1590.         MOV            ESI, [src]
  1591.         MOV            EDI, [dest]
  1592.  
  1593. #if !USE_3_BIT_QUOTIENT
  1594.         MOV            CX, cw
  1595.         AND            CX, ~X86_ROUND_CONTROL_MASK
  1596.         OR            CX, CW_RC_ZERO
  1597.         MOV            cw_temp, CX
  1598.     FLDCW   cw_temp
  1599.  
  1600.         FLD     TBYTE PTR [ESI]
  1601.         FLD     TBYTE PTR [EDI]
  1602.         FDIV        ST(0),ST(1)
  1603.         FABS
  1604.     FISTP   DWORD PTR quot
  1605.         FSTP    ST(0)
  1606.     FLDCW   cw
  1607.         // TODO:Quotient
  1608.         // Should clear any possible exceptions here
  1609. #endif
  1610.  
  1611.         FLD     TBYTE PTR [ESI]
  1612.         FLD     TBYTE PTR [EDI]
  1613.  
  1614. // loop until the remainder is not partial any more.
  1615. partial_loop:
  1616.         FPREM
  1617.         FNSTSW    status
  1618.         TEST        status, SW_C2
  1619.         JNE            partial_loop
  1620.  
  1621.  
  1622.         FXAM
  1623.     FNSTSW  sw
  1624.  
  1625.         FSTP    TBYTE PTR [EDI]
  1626.         FSTP    ST(0)
  1627.     } */
  1628.     
  1629. #if !USE_3_BIT_QUOTIENT
  1630.     
  1631.     _ASM(    "movl    %6, %%ecx\n"    // %6: cw        (read)
  1632.             "andl    $(~X86_ROUND_CONTROL_MASK), %%ecx\n"
  1633.             "orl    $CW_RC_ZERO, %%ecx\n"
  1634.             "movl    %%ecx, %0\n"    // %0: cw_temp    (read/write)
  1635.             "fldcw    %0\n"
  1636.             "fldt    %5\n"
  1637.             "fldt    %4\n"
  1638.             "fdiv    %%st(1), %%st(0)\n"
  1639.             "fabs    \n"
  1640.             "fistpl    %1\n"            // %1: quot        (read/write)
  1641.             "fstp    %%st(0)\n"
  1642.             "fldcw    %6\n"
  1643.             "fldt    %5\n"
  1644.             "fldt    %4\n"
  1645.             "0:\n"                    // partial_loop
  1646.             "fprem    \n"
  1647.             "fnstsw    %2\n"            // %2: status    (read/write)
  1648.             "testl    $SW_C2, %2\n"
  1649.             "jne    0b\n"
  1650.             "fxam    \n"
  1651.             "fnstsw    %3\n"            // %3: sw        (write)
  1652.             "fstpt    %4\n"
  1653.             "fstp    %%st(0)\n"
  1654.         :    "+m" (cw_temp), "+m" (quot), "+m" (status), "=m" (sw), "+m" (*dest)
  1655.         :    "m" (*src), "m" (cw)
  1656.         :    "ecx"
  1657.         );
  1658.     
  1659. #else
  1660.     
  1661.     _ASM(    "fldt    %3\n"
  1662.             "fldt    %2\n"
  1663.             "0:\n"                    // partial_loop
  1664.             "fprem    \n"
  1665.             "fnstsw    %0\n"            // %0: status    (read/write)
  1666.             "testl    $SW_C2, %0\n"
  1667.             "jne    0b\n"
  1668.             "fxam    \n"
  1669.             "fnstsw    %1\n"            // %1: sw        (write)
  1670.             "fstpt    %2\n"
  1671.             "fstp    %%st(0)\n"
  1672.         :    "+m" (status), "=m" (sw), "+m" (*dest)
  1673.         :    "m" (*src)
  1674.         );
  1675.     
  1676. #endif
  1677.     
  1678.     if(sw & SW_EXCEPTION_MASK) {
  1679. //        _asm FNCLEX
  1680.         _ASM("fnclex");
  1681.         sw &= ~(SW_EXCEPTION_MASK - SW_IE - SW_UE);
  1682.         sw_accrued |= sw;
  1683.     }
  1684.  
  1685. #if USE_3_BIT_QUOTIENT
  1686.     // SW_C1 Set to least significant bit of quotient (Q0).
  1687.     // SW_C3 Set to bit 1 (Q1) of the quotient.
  1688.     // SW_C0 Set to bit 2 (Q2) of the quotient.
  1689.     quot = ((status & SW_C0) >> 6) | ((status & SW_C3) >> 13) | ((status & SW_C1) >> 9);
  1690.     sw_quotient = (sign | quot) << 16;
  1691. #else
  1692.     sw_quotient = (sign | (quot&0x7F)) << 16;
  1693. #endif
  1694.  
  1695.     FPU_CONSISTENCY_CHECK_STOP("do_fmod");
  1696. }
  1697.  
  1698. static void do_frem( float80 dest, float80 src ) REGPARAM;
  1699. static void do_frem( float80 dest, float80 src )
  1700. {
  1701.     FPU_CONSISTENCY_CHECK_START();
  1702.  
  1703.     volatile uint16 status;
  1704.     uae_u32 quot;
  1705. #if !USE_3_BIT_QUOTIENT
  1706.     WORD cw_temp;
  1707. #endif
  1708.  
  1709.     uae_u32 sign = (dest[9] ^ src[9]) & 0x80;
  1710.  
  1711. /*    _asm {
  1712.         MOV            ESI, [src]
  1713.         MOV            EDI, [dest]
  1714.  
  1715. #if !USE_3_BIT_QUOTIENT
  1716.         MOV            CX, cw
  1717.         AND            CX, ~X86_ROUND_CONTROL_MASK
  1718.         OR            CX, CW_RC_NEAR
  1719.         MOV            cw_temp, CX
  1720.     FLDCW   cw_temp
  1721.  
  1722.         FLD     TBYTE PTR [ESI]
  1723.         FLD     TBYTE PTR [EDI]
  1724.         FDIV        ST(0),ST(1)
  1725.         FABS
  1726.     FISTP   DWORD PTR quot
  1727.         FSTP    ST(0)
  1728.     FLDCW   cw
  1729.         // TODO:Quotient
  1730.         // Should clear any possible exceptions here
  1731. #endif
  1732.  
  1733.         FLD     TBYTE PTR [ESI]
  1734.         FLD     TBYTE PTR [EDI]
  1735.  
  1736. // loop until the remainder is not partial any more.
  1737. partial_loop:
  1738.         FPREM1
  1739.         FNSTSW    status
  1740.         TEST        status, SW_C2
  1741.         JNE            partial_loop
  1742.  
  1743.         FXAM
  1744.     FNSTSW  sw
  1745.         FSTP    TBYTE PTR [EDI]
  1746.         FSTP    ST(0)
  1747.     } */
  1748.  
  1749. #if !USE_3_BIT_QUOTIENT
  1750.     
  1751.     _ASM(    "movl    %6, %%ecx\n"    // %6: cw        (read)
  1752.             "andl    $(~X86_ROUND_CONTROL_MASK), %%ecx\n"
  1753.             "orl    $CW_RC_NEAR, %%ecx\n"
  1754.             "movl    %%ecx, %0\n"    // %0: cw_temp    (read/write)
  1755.             "fldcw    %0\n"
  1756.             "fldt    %5\n"
  1757.             "fldt    %4\n"
  1758.             "fdiv    %%st(1), %%st(0)\n"
  1759.             "fabs    \n"
  1760.             "fistpl    %1\n"            // %1: quot        (read/write)
  1761.             "fstp    %%st(0)\n"
  1762.             "fldcw    %6\n"
  1763.             "fldt    %5\n"
  1764.             "fldt    %4\n"
  1765.             "0:\n"                    // partial_loop
  1766.             "fprem1    \n"
  1767.             "fnstsw    %2\n"            // %2: status    (read/write)
  1768.             "testl    $SW_C2, %2\n"
  1769.             "jne    0b\n"
  1770.             "fxam    \n"
  1771.             "fnstsw    %3\n"            // %3: sw        (write)
  1772.             "fstpt    %4\n"
  1773.             "fstp    %%st(0)\n"
  1774.         :    "+m" (cw_temp), "+m" (quot), "+m" (status), "=m" (sw), "+m" (*dest)
  1775.         :    "m" (*src), "m" (cw)
  1776.         :    "ecx"
  1777.         );
  1778.     
  1779. #else
  1780.     
  1781.     _ASM(    "fldt    %3\n"
  1782.             "fldt    %2\n"
  1783.             "0:\n"                    // partial_loop
  1784.             "fprem1    \n"
  1785.             "fnstsw    %0\n"            // %0: status    (read/write)
  1786.             "testl    $SW_C2, %0\n"
  1787.             "jne    0b\n"
  1788.             "fxam    \n"
  1789.             "fnstsw    %1\n"            // %1: sw        (write)
  1790.             "fstpt    %2\n"
  1791.             "fstp    %%st(0)\n"
  1792.         :    "+m" (status), "=m" (sw), "+m" (*dest)
  1793.         :    "m" (*src)
  1794.         );
  1795.     
  1796. #endif
  1797.     
  1798.     if(sw & SW_EXCEPTION_MASK) {
  1799. //        _asm FNCLEX
  1800.         _ASM("fnclex");
  1801.         sw &= ~(SW_EXCEPTION_MASK - SW_IE - SW_UE);
  1802.         sw_accrued |= sw;
  1803.     }
  1804.  
  1805. #if USE_3_BIT_QUOTIENT
  1806.     // SW_C1 Set to least significant bit of quotient (Q0).
  1807.     // SW_C3 Set to bit 1 (Q1) of the quotient.
  1808.     // SW_C0 Set to bit 2 (Q2) of the quotient.
  1809.     quot = ((status & SW_C0) >> 6) | ((status & SW_C3) >> 13) | ((status & SW_C1) >> 9);
  1810.     sw_quotient = (sign | quot) << 16;
  1811. #else
  1812.     sw_quotient = (sign | (quot&0x7F)) << 16;
  1813. #endif
  1814.  
  1815.     FPU_CONSISTENCY_CHECK_STOP("do_frem");
  1816. }
  1817.  
  1818. // Faster versions. The current rounding mode is already correct.
  1819. #if !USE_3_BIT_QUOTIENT
  1820. static void do_fmod_dont_set_cw( float80 dest, float80 src ) REGPARAM;
  1821. static void do_fmod_dont_set_cw( float80 dest, float80 src )
  1822. {
  1823.     FPU_CONSISTENCY_CHECK_START();
  1824.  
  1825.     volatile uint16 status;
  1826.     uae_u32 quot;
  1827.  
  1828.     uae_u32 sign = (dest[9] ^ src[9]) & 0x80;
  1829.  
  1830.     _asm {
  1831.         MOV            ESI, [src]
  1832.         MOV            EDI, [dest]
  1833.  
  1834.         FLD     TBYTE PTR [ESI]
  1835.         FLD     TBYTE PTR [EDI]
  1836.         FDIV        ST(0),ST(1)
  1837.         FABS
  1838.     FISTP   DWORD PTR quot
  1839.         FSTP    ST(0)
  1840.         // TODO:Quotient
  1841.         // Should clear any possible exceptions here
  1842.  
  1843.         FLD     TBYTE PTR [ESI]
  1844.         FLD     TBYTE PTR [EDI]
  1845.  
  1846. // loop until the remainder is not partial any more.
  1847. partial_loop:
  1848.         FPREM
  1849.         FNSTSW    status
  1850.         TEST        status, SW_C2
  1851.         JNE            partial_loop
  1852.  
  1853.         FXAM
  1854.     FNSTSW  sw
  1855.  
  1856.         FSTP    TBYTE PTR [EDI]
  1857.         FSTP    ST(0)
  1858.     }
  1859.     if(sw & SW_EXCEPTION_MASK) {
  1860.         _asm FNCLEX
  1861.         sw &= ~(SW_EXCEPTION_MASK - SW_IE - SW_UE);
  1862.         sw_accrued |= sw;
  1863.     }
  1864.     sw_quotient = (sign | (quot&0x7F)) << 16;
  1865.     FPU_CONSISTENCY_CHECK_STOP("do_fmod_dont_set_cw");
  1866. }
  1867.  
  1868. static void do_frem_dont_set_cw( float80 dest, float80 src ) REGPARAM;
  1869. static void do_frem_dont_set_cw( float80 dest, float80 src )
  1870. {
  1871.     FPU_CONSISTENCY_CHECK_START();
  1872.  
  1873.     volatile uint16 status;
  1874.     uae_u32 quot;
  1875.  
  1876.     uae_u32 sign = (dest[9] ^ src[9]) & 0x80;
  1877.  
  1878.     _asm {
  1879.         MOV            ESI, [src]
  1880.         MOV            EDI, [dest]
  1881.  
  1882.         FLD     TBYTE PTR [ESI]
  1883.         FLD     TBYTE PTR [EDI]
  1884.         FDIV        ST(0),ST(1)
  1885.         FABS
  1886.     FISTP   DWORD PTR quot
  1887.         FSTP    ST(0)
  1888.         // TODO:Quotient
  1889.         // Should clear any possible exceptions here
  1890.  
  1891.         FLD     TBYTE PTR [ESI]
  1892.         FLD     TBYTE PTR [EDI]
  1893.  
  1894. // loop until the remainder is not partial any more.
  1895. partial_loop:
  1896.         FPREM1
  1897.         FNSTSW    status
  1898.         TEST        status, SW_C2
  1899.         JNE            partial_loop
  1900.  
  1901.         FXAM
  1902.     FNSTSW  sw
  1903.         FSTP    TBYTE PTR [EDI]
  1904.         FSTP    ST(0)
  1905.     }
  1906.     if(sw & SW_EXCEPTION_MASK) {
  1907.         _asm FNCLEX
  1908.         sw &= ~(SW_EXCEPTION_MASK - SW_IE - SW_UE);
  1909.         sw_accrued |= sw;
  1910.     }
  1911.     sw_quotient = (sign | (quot&0x7F)) << 16;
  1912.     FPU_CONSISTENCY_CHECK_STOP("do_frem_dont_set_cw");
  1913. }
  1914. #endif //USE_3_BIT_QUOTIENT
  1915.  
  1916. static void do_fadd( float80 dest, float80 src ) REGPARAM;
  1917. static void do_fadd( float80 dest, float80 src )
  1918. {
  1919.     FPU_CONSISTENCY_CHECK_START();
  1920. /*    _asm {
  1921.         MOV            ESI, [src]
  1922.         MOV            EDI, [dest]
  1923.     FLD     TBYTE PTR [ESI]
  1924.     FLD     TBYTE PTR [EDI]
  1925.         FADD
  1926.         FXAM
  1927.     FNSTSW  sw
  1928.         FSTP    TBYTE PTR [EDI]
  1929.     } */
  1930.     _ASM(    "fldt    %2\n"
  1931.             "fldt    %1\n"
  1932.             "fadd    \n"
  1933.             "fxam    \n"
  1934.             "fnstsw    %0\n"
  1935.             "fstpt    %1\n"
  1936.         :    "=m" (sw), "+m" (*dest)
  1937.         :    "m" (*src)
  1938.         );
  1939.     if(sw & SW_EXCEPTION_MASK) {
  1940. //        _asm FNCLEX
  1941.         _ASM("fnclex");
  1942.         sw &= ~(SW_EXCEPTION_MASK - SW_IE - SW_UE - SW_OE - SW_PE);
  1943.         sw_accrued |= sw;
  1944.     }
  1945.     FPU_CONSISTENCY_CHECK_STOP("do_fadd");
  1946. }
  1947.  
  1948. static void do_fmul( float80 dest, float80 src ) REGPARAM;
  1949. static void do_fmul( float80 dest, float80 src )
  1950. {
  1951.     FPU_CONSISTENCY_CHECK_START();
  1952. /*    _asm {
  1953.         MOV            ESI, [src]
  1954.         MOV            EDI, [dest]
  1955.     FLD     TBYTE PTR [ESI]
  1956.     FLD     TBYTE PTR [EDI]
  1957.         FMUL
  1958.         FXAM
  1959.     FNSTSW  sw
  1960.         FSTP    TBYTE PTR [EDI]
  1961.     } */
  1962.     _ASM(    "fldt    %2\n"
  1963.             "fldt    %1\n"
  1964.             "fmul    \n"
  1965.             "fxam    \n"
  1966.             "fnstsw    %0\n"
  1967.             "fstpt    %1\n"
  1968.         :    "=m" (sw), "+m" (*dest)
  1969.         :    "m" (*src)
  1970.         );
  1971.     if(sw & SW_EXCEPTION_MASK) {
  1972. //        _asm FNCLEX
  1973.         _ASM("fnclex");
  1974.         sw_accrued |= sw;
  1975.     }
  1976.     FPU_CONSISTENCY_CHECK_STOP("do_fmul");
  1977. }
  1978.  
  1979. static void do_fsgldiv( float80 dest, float80 src ) REGPARAM;
  1980. static void do_fsgldiv( float80 dest, float80 src )
  1981. {
  1982.     FPU_CONSISTENCY_CHECK_START();
  1983.     volatile WORD cw_temp;
  1984. /*    _asm {
  1985.         FSTCW   cw_temp
  1986.         and            cw_temp, ~X86_PRECISION_CONTROL_MASK
  1987.         or            cw_temp, PRECISION_CONTROL_SINGLE
  1988.     FLDCW   cw_temp
  1989.  
  1990.         MOV            ESI, [src]
  1991.         MOV            EDI, [dest]
  1992.     FLD     TBYTE PTR [ESI]
  1993.     FLD     TBYTE PTR [EDI]
  1994.         FDIV        ST(0),ST(1)
  1995.         FXAM
  1996.     FNSTSW  sw
  1997.         FSTP    TBYTE PTR [EDI]
  1998.         FSTP    ST(0)
  1999.     FLDCW   cw
  2000.     } */
  2001.     _ASM(    "fstcw    %0\n"
  2002.             "andl    $(~X86_PRECISION_CONTROL_MASK), %0\n"
  2003.             "orl    $PRECISION_CONTROL_SINGLE, %0\n"
  2004.             "fldcw    %0\n"
  2005.             "fldt    %3\n"
  2006.             "fldt    %2\n"
  2007.             "fdiv    %%st(1), %%st(0)\n"
  2008.             "fxam    \n"
  2009.             "fnstsw    %1\n"
  2010.             "fstpt    %2\n"
  2011.             "fstp    %%st(0)\n"
  2012.             "fldcw    %4\n"
  2013.         :    "+m" (cw_temp), "=m" (sw), "+m" (*dest)
  2014.         :    "m" (*src), "m" (cw)
  2015.         );
  2016.     if(sw & SW_EXCEPTION_MASK) {
  2017. //        _asm FNCLEX
  2018.         _ASM("fnclex");
  2019.         sw_accrued |= sw;
  2020.     }
  2021.     FPU_CONSISTENCY_CHECK_STOP("do_fsgldiv");
  2022. }
  2023.  
  2024. static void do_fscale( float80 dest, float80 src ) REGPARAM;
  2025. static void do_fscale( float80 dest, float80 src )
  2026. {
  2027.     FPU_CONSISTENCY_CHECK_START();
  2028. /*    _asm {
  2029.         MOV            ESI, [src]
  2030.         MOV            EDI, [dest]
  2031.     FLD     TBYTE PTR [ESI]
  2032.     FLD     TBYTE PTR [EDI]
  2033.         FSCALE
  2034.         FXAM
  2035.     FNSTSW  sw
  2036.         FSTP    TBYTE PTR [EDI]
  2037.         FSTP    ST(0)
  2038.     } */
  2039.     _ASM(    "fldt    %2\n"
  2040.             "fldt    %1\n"
  2041.             "fscale    \n"
  2042.             "fxam    \n"
  2043.             "fnstsw    %0\n"
  2044.             "fstpt    %1\n"
  2045.             "fstp    %%st(0)\n"
  2046.         :    "=m" (sw), "+m" (*dest)
  2047.         :    "m" (*src)
  2048.         );
  2049.     if(sw & SW_EXCEPTION_MASK) {
  2050. //        _asm FNCLEX
  2051.         _ASM("fnclex");
  2052.         sw &= ~(SW_EXCEPTION_MASK - SW_UE - SW_OE);
  2053.         sw_accrued |= sw;
  2054.     }
  2055.     FPU_CONSISTENCY_CHECK_STOP("do_fscale");
  2056. }
  2057.  
  2058. static void do_fsglmul( float80 dest, float80 src ) REGPARAM;
  2059. static void do_fsglmul( float80 dest, float80 src )
  2060. {
  2061.     FPU_CONSISTENCY_CHECK_START();
  2062.     volatile WORD cw_temp;
  2063.  
  2064. /*    _asm {
  2065.         FSTCW   cw_temp
  2066.         and            cw_temp, ~X86_PRECISION_CONTROL_MASK
  2067.         or            cw_temp, PRECISION_CONTROL_SINGLE
  2068.     FLDCW   cw_temp
  2069.  
  2070.         MOV            ESI, [src]
  2071.         MOV            EDI, [dest]
  2072.     FLD     TBYTE PTR [ESI]
  2073.     FLD     TBYTE PTR [EDI]
  2074.         FMUL
  2075.         FXAM
  2076.     FNSTSW  sw
  2077.         FSTP    TBYTE PTR [EDI]
  2078.  
  2079.     FLDCW   cw
  2080.     } */
  2081.     _ASM(    "fstcw    %0\n"
  2082.             "andl    $(~X86_PRECISION_CONTROL_MASK), %0\n"
  2083.             "orl    $PRECISION_CONTROL_SINGLE, %0\n"
  2084.             "fldcw    %0\n"
  2085.             "fldt    %3\n"
  2086.             "fldt    %2\n"
  2087.             "fmul    \n"
  2088.             "fxam    \n"
  2089.             "fnstsw    %1\n"
  2090.             "fstpt    %2\n"
  2091.             "fldcw    %4\n"
  2092.         :    "+m" (cw_temp), "=m" (sw), "+m" (*dest)
  2093.         :    "m" (*src), "m" (sw)
  2094.         );
  2095.     if(sw & SW_EXCEPTION_MASK) {
  2096. //        _asm FNCLEX
  2097.         _ASM("fnclex");
  2098.         sw_accrued |= sw;
  2099.     }
  2100.     FPU_CONSISTENCY_CHECK_STOP("do_fsglmul");
  2101. }
  2102.  
  2103. static void do_fsub( float80 dest, float80 src ) REGPARAM;
  2104. static void do_fsub( float80 dest, float80 src )
  2105. {
  2106.     FPU_CONSISTENCY_CHECK_START();
  2107. /*    _asm {
  2108.         MOV            ESI, [src]
  2109.         MOV            EDI, [dest]
  2110.     FLD     TBYTE PTR [ESI]
  2111.     FLD     TBYTE PTR [EDI]
  2112.         FSUB        ST(0),ST(1)
  2113.         FXAM
  2114.     FNSTSW  sw
  2115.         FSTP    TBYTE PTR [EDI]
  2116.         FSTP    ST(0)
  2117.     } */
  2118.     _ASM(    "fldt    %2\n"
  2119.             "fldt    %1\n"
  2120.             "fsub    %%st(1), %%st(0)\n"
  2121.             "fxam    \n"
  2122.             "fnstsw    %0\n"
  2123.             "fstpt    %1\n"
  2124.             "fstp    %%st(0)\n"
  2125.         :    "=m" (sw), "+m" (*dest)
  2126.         :    "m" (*src)
  2127.         );
  2128.     if(sw & SW_EXCEPTION_MASK) {
  2129. //        _asm FNCLEX
  2130.         _ASM("fnclex");
  2131.         sw &= ~(SW_EXCEPTION_MASK - SW_IE - SW_UE - SW_OE - SW_PE);
  2132.         sw_accrued |= sw;
  2133.     }
  2134.     FPU_CONSISTENCY_CHECK_STOP("do_fsub");
  2135. }
  2136.  
  2137. static void do_fsincos( float80 dest_sin, float80 dest_cos, float80 src ) REGPARAM;
  2138. static void do_fsincos( float80 dest_sin, float80 dest_cos, float80 src )
  2139. {
  2140.     FPU_CONSISTENCY_CHECK_START();
  2141. /*    _asm {
  2142.         MOV            ESI, [src]
  2143.         MOV            EDI, [dest_cos]
  2144.     FLD     TBYTE PTR [ESI]
  2145.         FSINCOS
  2146.         FSTP    TBYTE PTR [EDI]
  2147.         FXAM
  2148.         MOV            EDI, [dest_sin]
  2149.     FNSTSW  sw
  2150.         FSTP    TBYTE PTR [EDI]
  2151.         FSTP    ST(0)
  2152.     } */
  2153.     _ASM(    "fldt    %3\n"
  2154.             "fsincos\n"
  2155.             "fstpt    %1\n"
  2156.             "fxam    \n"
  2157.             "fnstsw    %0\n"
  2158.             "fstpt    %2\n"
  2159.             "fstp    %%st(0)\n"
  2160.         :    "=m" (sw), "=m" (*dest_cos), "=m" (*dest_sin)
  2161.         :    "m" (*src)
  2162.         );
  2163.     if(sw & SW_EXCEPTION_MASK) {
  2164. //        _asm FNCLEX
  2165.         _ASM("fnclex");
  2166.         sw &= ~(SW_EXCEPTION_MASK - SW_IE - SW_UE - SW_PE);
  2167.         sw_accrued |= sw;
  2168.     }
  2169.     FPU_CONSISTENCY_CHECK_STOP("do_fsincos");
  2170. }
  2171.  
  2172. static void do_fcmp( float80 dest, float80 src ) REGPARAM;
  2173. static void do_fcmp( float80 dest, float80 src )
  2174. {
  2175.     FPU_CONSISTENCY_CHECK_START();
  2176. /*    _asm {
  2177.         MOV            ESI, [src]
  2178.         MOV            EDI, [dest]
  2179.     FLD     TBYTE PTR [ESI]
  2180.     FLD     TBYTE PTR [EDI]
  2181.         FSUB    ST(0),ST(1)
  2182.         FXAM
  2183.     FNSTSW  sw
  2184.         FSTP    ST(0)
  2185.         FSTP    ST(0)
  2186.     } */
  2187.     _ASM(    "fldt    %2\n"
  2188.             "fldt    %1\n"
  2189.             "fsub    %%st(1), %%st(0)\n"
  2190.             "fxam    \n"
  2191.             "fnstsw    %0\n"
  2192.             "fstp    %%st(0)\n"
  2193.             "fstp    %%st(0)\n"
  2194.         :    "=m" (sw)
  2195.         :    "m" (*dest), "m" (*src)
  2196.         );
  2197.     if(sw & SW_EXCEPTION_MASK) {
  2198. //        _asm FNCLEX
  2199.         _ASM("fnclex");
  2200.         sw &= ~SW_EXCEPTION_MASK;
  2201.     }
  2202.     FPU_CONSISTENCY_CHECK_STOP("do_fcmp");
  2203. }
  2204.  
  2205. // More or less original. Should be reviewed.
  2206. static double to_pack(uae_u32 wrd1, uae_u32 wrd2, uae_u32 wrd3) REGPARAM;
  2207. static double to_pack(uae_u32 wrd1, uae_u32 wrd2, uae_u32 wrd3)
  2208. {
  2209.     FPU_CONSISTENCY_CHECK_START();
  2210.  
  2211.   double d;
  2212.   char *cp;
  2213.   char str[100];
  2214.  
  2215.   cp = str;
  2216.   if (wrd1 & 0x80000000)
  2217.         *cp++ = '-';
  2218.   *cp++ = (char)((wrd1 & 0xf) + '0');
  2219.   *cp++ = '.';
  2220.   *cp++ = (char)(((wrd2 >> 28) & 0xf) + '0');
  2221.   *cp++ = (char)(((wrd2 >> 24) & 0xf) + '0');
  2222.   *cp++ = (char)(((wrd2 >> 20) & 0xf) + '0');
  2223.   *cp++ = (char)(((wrd2 >> 16) & 0xf) + '0');
  2224.   *cp++ = (char)(((wrd2 >> 12) & 0xf) + '0');
  2225.   *cp++ = (char)(((wrd2 >> 8) & 0xf) + '0');
  2226.   *cp++ = (char)(((wrd2 >> 4) & 0xf) + '0');
  2227.   *cp++ = (char)(((wrd2 >> 0) & 0xf) + '0');
  2228.   *cp++ = (char)(((wrd3 >> 28) & 0xf) + '0');
  2229.   *cp++ = (char)(((wrd3 >> 24) & 0xf) + '0');
  2230.   *cp++ = (char)(((wrd3 >> 20) & 0xf) + '0');
  2231.   *cp++ = (char)(((wrd3 >> 16) & 0xf) + '0');
  2232.   *cp++ = (char)(((wrd3 >> 12) & 0xf) + '0');
  2233.   *cp++ = (char)(((wrd3 >> 8) & 0xf) + '0');
  2234.   *cp++ = (char)(((wrd3 >> 4) & 0xf) + '0');
  2235.   *cp++ = (char)(((wrd3 >> 0) & 0xf) + '0');
  2236.   *cp++ = 'E';
  2237.   if (wrd1 & 0x40000000)
  2238.         *cp++ = '-';
  2239.   *cp++ = (char)(((wrd1 >> 24) & 0xf) + '0');
  2240.   *cp++ = (char)(((wrd1 >> 20) & 0xf) + '0');
  2241.   *cp++ = (char)(((wrd1 >> 16) & 0xf) + '0');
  2242.   *cp = 0;
  2243.   sscanf(str, "%le", &d);
  2244.  
  2245.     D(bug("to_pack str = %s\r\n",str));
  2246.  
  2247.     D(bug("to_pack(%X,%X,%X) = %.04f\r\n",wrd1,wrd2,wrd3,(float)d));
  2248.  
  2249.     FPU_CONSISTENCY_CHECK_STOP("to_pack");
  2250.  
  2251.   return d;
  2252. }
  2253.  
  2254. // More or less original. Should be reviewed.
  2255. static void from_pack(double src, uae_u32 * wrd1, uae_u32 * wrd2, uae_u32 * wrd3) REGPARAM;
  2256. static void from_pack(double src, uae_u32 * wrd1, uae_u32 * wrd2, uae_u32 * wrd3)
  2257. {
  2258.     FPU_CONSISTENCY_CHECK_START();
  2259.  
  2260.   int i;
  2261.   int t;
  2262.   char *cp;
  2263.   char str[100];
  2264.   int exponent_digit_count = 0;
  2265.  
  2266.   sprintf(str, "%.16e", src);
  2267.  
  2268.     D(bug("from_pack(%.04f,%s)\r\n",(float)src,str));
  2269.  
  2270.   cp = str;
  2271.   *wrd1 = *wrd2 = *wrd3 = 0;
  2272.   if (*cp == '-') {
  2273.         cp++;
  2274.         *wrd1 = 0x80000000;
  2275.   }
  2276.   if (*cp == '+')
  2277.         cp++;
  2278.   *wrd1 |= (*cp++ - '0');
  2279.   if (*cp == '.')
  2280.         cp++;
  2281.   for (i = 0; i < 8; i++) {
  2282.         *wrd2 <<= 4;
  2283.         if (*cp >= '0' && *cp <= '9')
  2284.         *wrd2 |= *cp++ - '0';
  2285.   }
  2286.   for (i = 0; i < 8; i++) {
  2287.         *wrd3 <<= 4;
  2288.         if (*cp >= '0' && *cp <= '9')
  2289.         *wrd3 |= *cp++ - '0';
  2290.   }
  2291.   if (*cp == 'e' || *cp == 'E') {
  2292.         cp++;
  2293.         if (*cp == '-') {
  2294.             cp++;
  2295.             *wrd1 |= 0x40000000;
  2296.         }
  2297.         if (*cp == '+')
  2298.             cp++;
  2299.         t = 0;
  2300.         for (i = 0; i < 3; i++) {
  2301.             if (*cp >= '0' && *cp <= '9') {
  2302.                 t = (t << 4) | (*cp++ - '0');
  2303.                 exponent_digit_count++;
  2304.             }
  2305.         }
  2306.         *wrd1 |= t << 16;
  2307.   }
  2308.  
  2309.     D(bug("from_pack(%.04f) = %X,%X,%X\r\n",(float)src,*wrd1,*wrd2,*wrd3));
  2310.  
  2311.     volatile WORD sw_temp;
  2312. //    _asm FNSTSW sw_temp
  2313.     _ASM("fnstsw %0" : "=m" (sw_temp));
  2314.     if(sw_temp & SW_EXCEPTION_MASK) {
  2315. //        _asm FNCLEX
  2316.         _ASM("fnclex");
  2317.         if(sw_temp & SW_PE) {
  2318.             sw |= SW_PE;
  2319.             sw_accrued |= SW_PE;
  2320.         }
  2321.     }
  2322.  
  2323.     /*
  2324.     OPERR is set if the k-factor > + 17 or the magnitude of
  2325.     the decimal exponent exceeds three digits;
  2326.     cleared otherwise.
  2327.     */
  2328.     if(exponent_digit_count > 3) {
  2329.         sw |= SW_IE;
  2330.         sw_accrued |= SW_IE;
  2331.     }
  2332.  
  2333.     FPU_CONSISTENCY_CHECK_STOP("from_pack");
  2334. }
  2335.  
  2336. static int sz1[8] = {4, 4, 12, 12, 2, 8, 1, 0};
  2337. static int sz2[8] = {4, 4, 12, 12, 2, 8, 2, 0};
  2338.  
  2339. static int get_fp_value (uae_u32 opcode, uae_u16 extra, float80 src) REGPARAM;
  2340. static int get_fp_value (uae_u32 opcode, uae_u16 extra, float80 src)
  2341. {
  2342.     // D(bug("get_fp_value(%X,%X)\r\n",(int)opcode,(int)extra));
  2343.     // dump_first_bytes( regs.pc_p-4, 16 );
  2344.  
  2345.   if ((extra & 0x4000) == 0) {
  2346.         memcpy( src, fp_reg[(extra >> 10) & 7], sizeof(float80_s) );
  2347.         // do_fmove_no_status( src, fp_reg[(extra >> 10) & 7] );
  2348.         return 1;
  2349.   }
  2350.  
  2351.     int mode = (opcode >> 3) & 7;
  2352.   int reg = opcode & 7;
  2353.   int size = (extra >> 10) & 7;
  2354.   uae_u32 ad = 0;
  2355.  
  2356.     // D(bug("get_fp_value mode=%d, reg=%d, size=%d\r\n",(int)mode,(int)reg,(int)size));
  2357.  
  2358.   switch ((uae_u8)mode) {
  2359.     case 0:
  2360.             switch ((uae_u8)size) {
  2361.                 case 6:
  2362.                     signed_to_extended( (uae_s32)(uae_s8) m68k_dreg (regs, reg), src );
  2363.                     break;
  2364.                 case 4:
  2365.                     signed_to_extended( (uae_s32)(uae_s16) m68k_dreg (regs, reg), src );
  2366.                     break;
  2367.                 case 0:
  2368.                     signed_to_extended( (uae_s32) m68k_dreg (regs, reg), src );
  2369.                     break;
  2370.                 case 1:
  2371.                     to_single( m68k_dreg (regs, reg), src );
  2372.                     break;
  2373.                 default:
  2374.                     return 0;
  2375.             }
  2376.             return 1;
  2377.     case 1:
  2378.             return 0;
  2379.     case 2:
  2380.             ad = m68k_areg (regs, reg);
  2381.             break;
  2382.     case 3:
  2383.             ad = m68k_areg (regs, reg);
  2384.             m68k_areg (regs, reg) += reg == 7 ? sz2[size] : sz1[size];
  2385.             break;
  2386.     case 4:
  2387.             m68k_areg (regs, reg) -= reg == 7 ? sz2[size] : sz1[size];
  2388.             ad = m68k_areg (regs, reg);
  2389.             break;
  2390.     case 5:
  2391.             ad = m68k_areg (regs, reg) + (uae_s32) (uae_s16) next_iword();
  2392.             break;
  2393.     case 6:
  2394.             ad = get_disp_ea_020 (m68k_areg (regs, reg), next_iword());
  2395.             break;
  2396.     case 7:
  2397.             switch ((uae_u8)reg) {
  2398.                 case 0:
  2399.                 ad = (uae_s32) (uae_s16) next_iword();
  2400.                     break;
  2401.                 case 1:
  2402.                     ad = next_ilong();
  2403.                     break;
  2404.                 case 2:
  2405.                     ad = m68k_getpc ();
  2406.                     ad += (uae_s32) (uae_s16) next_iword();
  2407.                     break;
  2408.                 case 3: {
  2409.                     uaecptr tmppc = m68k_getpc ();
  2410.                     uae_u16 tmp = (uae_u16)next_iword();
  2411.                     ad = get_disp_ea_020 (tmppc, tmp);
  2412.                     }
  2413.                     break;
  2414.                 case 4:
  2415.                     ad = m68k_getpc ();
  2416.                     m68k_setpc (ad + sz2[size]);
  2417.  
  2418.                     /*
  2419.                     +0000  000004  FSCALE.B   #$01,FP2     | F23C 5926 0001
  2420.                     F23C 1111001000111100
  2421.                     5926 0101100100100110
  2422.                     0001 0000000000000001
  2423.                     mode = 7
  2424.                     reg  = 4
  2425.                     size = 6
  2426.                     */
  2427.                     // Immediate addressing mode && Operation Length == Byte -> 
  2428.                     // Use the low-order byte of the extension word.
  2429.  
  2430.                     if(size == 6) ad++;
  2431.                     
  2432.                     // May be faster on a PII(I), sz2[size] is already in register
  2433.                     // ad += sz2[size] - sz1[size];
  2434.  
  2435.                     break;
  2436.                 default:
  2437.                     return 0;
  2438.             }
  2439.   }
  2440.  
  2441.   switch ((uae_u8)size) {
  2442.     case 0:
  2443.             signed_to_extended( (uae_s32) get_long (ad), src );
  2444.             break;
  2445.     case 1:
  2446.             to_single( get_long (ad), src );
  2447.             break;
  2448.  
  2449.     case 2:{
  2450.         uae_u32 wrd1, wrd2, wrd3;
  2451.         wrd1 = get_long (ad);
  2452.         ad += 4;
  2453.         wrd2 = get_long (ad);
  2454.         ad += 4;
  2455.         wrd3 = get_long (ad);
  2456.             to_exten( wrd1, wrd2, wrd3, src );
  2457.             }
  2458.             break;
  2459.     case 3:{
  2460.         uae_u32 wrd1, wrd2, wrd3;
  2461.         wrd1 = get_long (ad);
  2462.         ad += 4;
  2463.         wrd2 = get_long (ad);
  2464.         ad += 4;
  2465.         wrd3 = get_long (ad);
  2466.             double_to_extended( to_pack(wrd1, wrd2, wrd3), src );
  2467.             }
  2468.             break;
  2469.     case 4:
  2470.             signed_to_extended( (uae_s32)(uae_s16) get_word(ad), src );
  2471.             break;
  2472.     case 5:{
  2473.         uae_u32 wrd1, wrd2;
  2474.         wrd1 = get_long (ad);
  2475.         ad += 4;
  2476.         wrd2 = get_long (ad);
  2477.             to_double(wrd1, wrd2, src);
  2478.             }
  2479.             break;
  2480.     case 6:
  2481.             signed_to_extended( (uae_s32)(uae_s8) get_byte(ad), src );
  2482.             break;
  2483.     default:
  2484.             return 0;
  2485.   }
  2486.  
  2487.     // D(bug("get_fp_value result = %.04f\r\n",(float)*src));
  2488.  
  2489.   return 1;
  2490. }
  2491.  
  2492. static int put_fp_value (float80 value, uae_u32 opcode, uae_u16 extra) REGPARAM;
  2493. static int put_fp_value (float80 value, uae_u32 opcode, uae_u16 extra)
  2494. {
  2495.     // D(bug("put_fp_value(%.04f,%X,%X)\r\n",(float)value,(int)opcode,(int)extra));
  2496.  
  2497.   if ((extra & 0x4000) == 0) {
  2498.         int dest_reg = (extra >> 10) & 7;
  2499.         do_fmove( fp_reg[dest_reg], value );
  2500.         build_ex_status();
  2501.         return 1;
  2502.   }
  2503.  
  2504.   int mode = (opcode >> 3) & 7;
  2505.   int reg = opcode & 7;
  2506.   int size = (extra >> 10) & 7;
  2507.   uae_u32 ad = 0xffffffff;
  2508.  
  2509.     // Clear exception status
  2510.     sw &= ~SW_EXCEPTION_MASK;
  2511.  
  2512.   switch ((uae_u8)mode) {
  2513.     case 0:
  2514.             switch ((uae_u8)size) {
  2515.                 case 6:
  2516.                     *((uae_u8 *)&m68k_dreg(regs, reg)) = extended_to_signed_8(value);
  2517.                     break;
  2518.                 case 4:
  2519.                     // TODO_BIGENDIAN
  2520.                     *((uae_u16 *)&m68k_dreg(regs, reg)) = extended_to_signed_16(value);
  2521.                     break;
  2522.                 case 0:
  2523.                     m68k_dreg (regs, reg) = extended_to_signed_32(value);
  2524.                     break;
  2525.                 case 1:
  2526.                     m68k_dreg (regs, reg) = from_single(value);
  2527.                     break;
  2528.                 default:
  2529.                     return 0;
  2530.             }
  2531.             return 1;
  2532.         case 1:
  2533.             return 0;
  2534.     case 2:
  2535.             ad = m68k_areg (regs, reg);
  2536.             break;
  2537.     case 3:
  2538.             ad = m68k_areg (regs, reg);
  2539.             m68k_areg (regs, reg) += reg == 7 ? sz2[size] : sz1[size];
  2540.             break;
  2541.     case 4:
  2542.             m68k_areg (regs, reg) -= reg == 7 ? sz2[size] : sz1[size];
  2543.             ad = m68k_areg (regs, reg);
  2544.             break;
  2545.     case 5:
  2546.             ad = m68k_areg (regs, reg) + (uae_s32) (uae_s16) next_iword();
  2547.             break;
  2548.     case 6:
  2549.             ad = get_disp_ea_020 (m68k_areg (regs, reg), next_iword());
  2550.             break;
  2551.     case 7:
  2552.             switch ((uae_u8)reg) {
  2553.                 case 0:
  2554.                     ad = (uae_s32) (uae_s16) next_iword();
  2555.                     break;
  2556.                 case 1:
  2557.                     ad = next_ilong();
  2558.                     break;
  2559.                 case 2:
  2560.                     ad = m68k_getpc ();
  2561.                     ad += (uae_s32) (uae_s16) next_iword();
  2562.                     break;
  2563.                 case 3: {
  2564.                     uaecptr tmppc = m68k_getpc ();
  2565.                     uae_u16 tmp = (uae_u16)next_iword();
  2566.                     ad = get_disp_ea_020 (tmppc, tmp);
  2567.                     }
  2568.                     break;
  2569.                 case 4:
  2570.                     ad = m68k_getpc ();
  2571.                     m68k_setpc (ad + sz2[size]);
  2572.                     break;
  2573.                 default:
  2574.                     return 0;
  2575.             }
  2576.   }
  2577.   switch ((uae_u8)size) {
  2578.     case 0:
  2579.             put_long (ad, (uae_s32) extended_to_signed_32(value));
  2580.             break;
  2581.     case 1:
  2582.             put_long (ad, from_single(value));
  2583.             break;
  2584.         case 2: {
  2585.             uae_u32 wrd1, wrd2, wrd3;
  2586.             from_exten(value, &wrd1, &wrd2, &wrd3);
  2587.             
  2588.             sw &= ~SW_EXCEPTION_MASK;
  2589.             if(wrd3) { // TODO: not correct! Just a "smart" guess.
  2590.                 sw |= SW_PE;
  2591.                 sw_accrued |= SW_PE;
  2592.             }
  2593.  
  2594.             put_long (ad, wrd1);
  2595.             ad += 4;
  2596.             put_long (ad, wrd2);
  2597.             ad += 4;
  2598.             put_long (ad, wrd3);
  2599.             }
  2600.             break;
  2601.     case 3: {
  2602.             uae_u32 wrd1, wrd2, wrd3;
  2603.             from_pack(extended_to_double(value), &wrd1, &wrd2, &wrd3);
  2604.             put_long (ad, wrd1);
  2605.             ad += 4;
  2606.             put_long (ad, wrd2);
  2607.             ad += 4;
  2608.             put_long (ad, wrd3);
  2609.             }
  2610.             break;
  2611.         case 4:
  2612.             put_word(ad, extended_to_signed_16(value));
  2613.             break;
  2614.     case 5:{
  2615.         uae_u32 wrd1, wrd2;
  2616.         from_double(value, &wrd1, &wrd2);
  2617.         put_long (ad, wrd1);
  2618.         ad += 4;
  2619.         put_long (ad, wrd2);
  2620.             }
  2621.             break;
  2622.     case 6:
  2623.             put_byte(ad, extended_to_signed_8(value));
  2624.  
  2625.             break;
  2626.     default:
  2627.             return 0;
  2628.   }
  2629.   return 1;
  2630. }
  2631.  
  2632. static int get_fp_ad(uae_u32 opcode, uae_u32 * ad) REGPARAM;
  2633. static int get_fp_ad(uae_u32 opcode, uae_u32 * ad)
  2634. {
  2635.   int mode = (opcode >> 3) & 7;
  2636.   int reg = opcode & 7;
  2637.   switch ( (uae_u8)mode ) {
  2638.     case 0:
  2639.     case 1:
  2640.         if( (opcode & 0xFF00) == 0xF300 ) {
  2641.             // fsave, frestore
  2642.                 m68k_setpc (m68k_getpc () - 2);
  2643.         } else {
  2644.                 m68k_setpc (m68k_getpc () - 4);
  2645.         }
  2646.             op_illg (opcode);
  2647.             dump_fp_regs( "END  ");
  2648.             return 0;
  2649.     case 2:
  2650.             *ad = m68k_areg (regs, reg);
  2651.             break;
  2652.     case 3:
  2653.             *ad = m68k_areg (regs, reg);
  2654.             break;
  2655.     case 4:
  2656.             *ad = m68k_areg (regs, reg);
  2657.             break;
  2658.     case 5:
  2659.             *ad = m68k_areg (regs, reg) + (uae_s32) (uae_s16) next_iword();
  2660.             break;
  2661.     case 6:
  2662.             *ad = get_disp_ea_020 (m68k_areg (regs, reg), next_iword());
  2663.             break;
  2664.     case 7:
  2665.             switch ( (uae_u8)reg ) {
  2666.                 case 0:
  2667.                     *ad = (uae_s32) (uae_s16) next_iword();
  2668.                     break;
  2669.                 case 1:
  2670.                     *ad = next_ilong();
  2671.                     break;
  2672.                 case 2:
  2673.                     *ad = m68k_getpc ();
  2674.                     *ad += (uae_s32) (uae_s16) next_iword();
  2675.                     break;
  2676.                 case 3: {
  2677.                     uaecptr tmppc = m68k_getpc ();
  2678.                     uae_u16 tmp = (uae_u16)next_iword();
  2679.                     *ad = get_disp_ea_020 (tmppc, tmp);
  2680.                     }
  2681.                     break;
  2682.                 default:
  2683.                     if( (opcode & 0xFF00) == 0xF300 ) {
  2684.                         // fsave, frestore
  2685.                         m68k_setpc (m68k_getpc () - 2);
  2686.                     } else {
  2687.                         m68k_setpc (m68k_getpc () - 4);
  2688.                     }
  2689.                     op_illg (opcode);
  2690.                     dump_fp_regs( "END  ");
  2691.                     return 0;
  2692.             }
  2693.   }
  2694.   return 1;
  2695. }
  2696.  
  2697. static int fpp_cond(uae_u32 opcode, int condition) REGPARAM;
  2698. static int fpp_cond(uae_u32 opcode, int condition)
  2699. {
  2700.  
  2701. #define N                (sw & SW_N)
  2702. #define Z                ((sw & (SW_Z_I_NAN_MASK)) == SW_Z)
  2703. #define I                ((sw & (SW_Z_I_NAN_MASK)) == (SW_I))
  2704. #define NotANumber        ((sw & (SW_Z_I_NAN_MASK)) == SW_NAN)
  2705.  
  2706.   switch (condition) {
  2707.         // Common Tests, no BSUN
  2708.     case 0x01:
  2709.             CONDRET("Equal",Z);
  2710.     case 0x0e:
  2711.             CONDRET("Not Equal",!Z);
  2712.  
  2713.         // IEEE Nonaware Tests, BSUN
  2714.     case 0x12:
  2715.             SET_BSUN_ON_NAN();
  2716.             CONDRET("Greater Than",!(NotANumber || Z || N));
  2717.     case 0x1d:
  2718.             SET_BSUN_ON_NAN();
  2719.             CONDRET("Not Greater Than",NotANumber || Z || N);
  2720.     case 0x13:
  2721.             SET_BSUN_ON_NAN();
  2722.             CONDRET("Greater Than or Equal",Z || !(NotANumber || N));
  2723.     case 0x1c:
  2724.             SET_BSUN_ON_NAN();
  2725.             CONDRET("Not Greater Than or Equal",!Z && (NotANumber || N));
  2726.     case 0x14:
  2727.             SET_BSUN_ON_NAN();
  2728.             CONDRET("Less Than",N && !(NotANumber || Z));
  2729.     case 0x1b:
  2730.             SET_BSUN_ON_NAN();
  2731.             CONDRET("Not Less Than",NotANumber || Z || !N);
  2732.     case 0x15:
  2733.             SET_BSUN_ON_NAN();
  2734.             CONDRET("Less Than or Equal",Z || (N && !NotANumber));
  2735.     case 0x1a:
  2736.             SET_BSUN_ON_NAN();
  2737.             CONDRET("Not Less Than or Equal",NotANumber || !(N || Z));
  2738.     case 0x16:
  2739.             SET_BSUN_ON_NAN();
  2740.             CONDRET("Greater or Less Than",!(NotANumber || Z));
  2741.     case 0x19:
  2742.             SET_BSUN_ON_NAN();
  2743.             CONDRET("Not Greater or Less Than",NotANumber || Z);
  2744.     case 0x17:
  2745.             CONDRET("Greater, Less or Equal",!NotANumber);
  2746.     case 0x18:
  2747.             SET_BSUN_ON_NAN();
  2748.             CONDRET("Not Greater, Less or Equal",NotANumber);
  2749.  
  2750.         // IEEE Aware Tests, no BSUN
  2751.     case 0x02:
  2752.             CONDRET("Ordered Greater Than",!(NotANumber || Z || N));
  2753.     case 0x0d:
  2754.             CONDRET("Unordered or Less or Equal",NotANumber || Z || N);
  2755.     case 0x03:
  2756.             CONDRET("Ordered Greater Than or Equal",Z || !(NotANumber || N));
  2757.     case 0x0c:
  2758.             CONDRET("Unordered or Less Than",NotANumber || (N && !Z));
  2759.     case 0x04:
  2760.             CONDRET("Ordered Less Than",N && !(NotANumber || Z));
  2761.     case 0x0b:
  2762.             CONDRET("Unordered or Greater or Equal",NotANumber || Z || !N);
  2763.     case 0x05:
  2764.             CONDRET("Ordered Less Than or Equal",Z || (N && !NotANumber));
  2765.     case 0x0a:
  2766.             CONDRET("Unordered or Greater Than",NotANumber || !(N || Z));
  2767.     case 0x06:
  2768.             CONDRET("Ordered Greater or Less Than",!(NotANumber || Z));
  2769.     case 0x09:
  2770.             CONDRET("Unordered or Equal",NotANumber || Z);
  2771.     case 0x07:
  2772.             CONDRET("Ordered",!NotANumber);
  2773.     case 0x08:
  2774.             CONDRET("Unordered",NotANumber);
  2775.  
  2776.         // Miscellaneous Tests, no BSUN
  2777.     case 0x00:
  2778.             CONDRET("False",0);
  2779.     case 0x0f:
  2780.             CONDRET("True",1);
  2781.  
  2782.         // Miscellaneous Tests, BSUN
  2783.     case 0x10:
  2784.             SET_BSUN_ON_NAN();
  2785.             CONDRET("Signaling False",0);
  2786.     case 0x1f:
  2787.             SET_BSUN_ON_NAN();
  2788.             CONDRET("Signaling True",1);
  2789.     case 0x11:
  2790.             SET_BSUN_ON_NAN();
  2791.             CONDRET("Signaling Equal",Z);
  2792.     case 0x1e:
  2793.             SET_BSUN_ON_NAN();
  2794.             CONDRET("Signaling Not Equal",!Z);
  2795.   }
  2796.     CONDRET("",-1);
  2797.  
  2798. #undef N
  2799. #undef Z
  2800. #undef I
  2801. #undef NotANumber
  2802.  
  2803. }
  2804.  
  2805. void REGPARAM2 fdbcc_opp(uae_u32 opcode, uae_u16 extra)
  2806. {
  2807.   uaecptr pc = (uae_u32) m68k_getpc ();
  2808.   uae_s32 disp = (uae_s32) (uae_s16) next_iword();
  2809.   int cc;
  2810.  
  2811.   D(bug("fdbcc_opp %X, %X at %08lx\r\n", (uae_u32)opcode, (uae_u32)extra, m68k_getpc ()));
  2812.  
  2813.   cc = fpp_cond(opcode, extra & 0x3f);
  2814.   if (cc < 0) {
  2815.         m68k_setpc (pc - 4);
  2816.         op_illg (opcode);
  2817.   } else if (!cc) {
  2818.         int reg = opcode & 0x7;
  2819.  
  2820.         // TODO_BIGENDIAN
  2821.         uae_u16 newv = (uae_u16)(m68k_dreg (regs, reg) & 0xffff) - 1;
  2822.         *((uae_u16 *)&m68k_dreg(regs, reg)) = newv;
  2823.  
  2824.         if (newv != 0xffff)
  2825.         m68k_setpc (pc + disp);
  2826.   }
  2827. }
  2828.  
  2829. void REGPARAM2 fscc_opp(uae_u32 opcode, uae_u16 extra)
  2830. {
  2831.   uae_u32 ad;
  2832.   int cc;
  2833.  
  2834.   D(bug("fscc_opp %X, %X at %08lx\r\n", (uae_u32)opcode, (uae_u32)extra, m68k_getpc ()));
  2835.  
  2836.   cc = fpp_cond(opcode, extra & 0x3f);
  2837.   if (cc < 0) {
  2838.         m68k_setpc (m68k_getpc () - 4);
  2839.         op_illg (opcode);
  2840.   } else if ((opcode & 0x38) == 0) {
  2841.         // TODO_BIGENDIAN
  2842.         m68k_dreg (regs, opcode & 7) = (m68k_dreg (regs, opcode & 7) & ~0xff) |
  2843.         (cc ? 0xff : 0x00);
  2844.   } else {
  2845.         if (get_fp_ad(opcode, &ad)) {
  2846.         put_byte(ad, cc ? 0xff : 0x00);
  2847.       }
  2848.   }
  2849. }
  2850.  
  2851. void REGPARAM2 ftrapcc_opp(uae_u32 opcode, uaecptr oldpc)
  2852. {
  2853.   int cc;
  2854.  
  2855.   D(bug("ftrapcc_opp %X at %08lx\r\n", (uae_u32)opcode, m68k_getpc ()));
  2856.  
  2857. #if I3_ON_FTRAPCC
  2858. #error "FIXME: _asm int 3"
  2859.     _asm int 3
  2860. #endif
  2861.  
  2862.     // This must be broken.
  2863.   cc = fpp_cond(opcode, opcode & 0x3f);
  2864.  
  2865.   if (cc < 0) {
  2866.         m68k_setpc (oldpc);
  2867.         op_illg (opcode);
  2868.   } else if (cc)
  2869.         Exception(7, oldpc - 2);
  2870. }
  2871.  
  2872. // NOTE that we get here also when there is a FNOP (nontrapping false, displ 0)
  2873. void REGPARAM2 fbcc_opp(uae_u32 opcode, uaecptr pc, uae_u32 extra)
  2874. {
  2875.   int cc;
  2876.  
  2877.   D(bug("fbcc_opp %X, %X at %08lx, jumpto=%X\r\n", (uae_u32)opcode, (uae_u32)extra, m68k_getpc (), extra ));
  2878.  
  2879.   cc = fpp_cond(opcode, opcode & 0x3f);
  2880.   if (cc < 0) {
  2881.         m68k_setpc (pc);
  2882.         op_illg (opcode);
  2883.   } else if (cc) {
  2884.         if ((opcode & 0x40) == 0)
  2885.         extra = (uae_s32) (uae_s16) extra;
  2886.         m68k_setpc (pc + extra);
  2887.   }
  2888. }
  2889.  
  2890. // FSAVE has no post-increment
  2891. // 0x1f180000 == IDLE state frame, coprocessor version number 1F
  2892. void REGPARAM2 fsave_opp(uae_u32 opcode)
  2893. {
  2894.   uae_u32 ad;
  2895.   int incr = (opcode & 0x38) == 0x20 ? -1 : 1;
  2896.   int i;
  2897.  
  2898.   D(bug("fsave_opp at %08lx\r\n", m68k_getpc ()));
  2899.  
  2900.   if (get_fp_ad(opcode, &ad)) {
  2901.         if (is_integral_68040_fpu) {
  2902.             // Put 4 byte 68040 IDLE frame.
  2903.             if (incr < 0) {
  2904.                 ad -= 4;
  2905.                 put_long (ad, 0x41000000);
  2906.             } else {
  2907.                 put_long (ad, 0x41000000);
  2908.                 ad += 4;
  2909.             }
  2910.         } else {
  2911.             // Put 28 byte 68881 IDLE frame.
  2912.             if (incr < 0) {
  2913.                 D(bug("fsave_opp pre-decrement\r\n"));
  2914.                 ad -= 4;
  2915.                 // What's this? Some BIU flags, or (incorrectly placed) command/condition?
  2916.                 put_long (ad, 0x70000000);
  2917.                 for (i = 0; i < 5; i++) {
  2918.                     ad -= 4;
  2919.                     put_long (ad, 0x00000000);
  2920.                 }
  2921.                 ad -= 4;
  2922.                 put_long (ad, 0x1f180000); // IDLE, vers 1f
  2923.             } else {
  2924.                 put_long (ad, 0x1f180000); // IDLE, vers 1f
  2925.                 ad += 4;
  2926.                 for (i = 0; i < 5; i++) {
  2927.                     put_long (ad, 0x00000000);
  2928.                     ad += 4;
  2929.                 }
  2930.                 // What's this? Some BIU flags, or (incorrectly placed) command/condition?
  2931.                 put_long (ad, 0x70000000);
  2932.                 ad += 4;
  2933.             }
  2934.         }
  2935.         if ((opcode & 0x38) == 0x18) {
  2936.             m68k_areg (regs, opcode & 7) = ad; // Never executed on a 68881
  2937.             D(bug("PROBLEM: fsave_opp post-increment\r\n"));
  2938.         }
  2939.         if ((opcode & 0x38) == 0x20) {
  2940.             m68k_areg (regs, opcode & 7) = ad;
  2941.             D(bug("fsave_opp pre-decrement %X -> A%d\r\n",ad,opcode & 7));
  2942.         }
  2943.   }
  2944. }
  2945.  
  2946. static void do_null_frestore()
  2947. {
  2948.     // A null-restore operation sets FP7-FP0 positive, nonsignaling NANs.
  2949.     for( int i=0; i<8; i++ ) {
  2950.         MAKE_NAN( fp_reg[i] );
  2951.     }
  2952.  
  2953.     regs.fpiar = 0;
  2954.     regs.fpcr = 0;
  2955.     regs.fpsr = 0;
  2956.  
  2957.     sw = SW_INITIAL;
  2958.     sw_accrued = 0;
  2959.     sw_quotient = 0;
  2960.  
  2961.     cw = CW_INITIAL;
  2962. /*  _asm    FLDCW   cw
  2963.     _asm    FNCLEX */
  2964.     _ASM("fldcw %0\n\tfnclex" : : "m" (cw));
  2965. }
  2966.  
  2967. // FSAVE has no pre-decrement
  2968. void REGPARAM2 frestore_opp(uae_u32 opcode)
  2969. {
  2970.   uae_u32 ad;
  2971.   uae_u32 d;
  2972.   int incr = (opcode & 0x38) == 0x20 ? -1 : 1;
  2973.  
  2974.   D(bug("frestore_opp at %08lx\r\n", m68k_getpc ()));
  2975.  
  2976.   if (get_fp_ad(opcode, &ad)) {
  2977.         if (is_integral_68040_fpu) {
  2978.             // 68040
  2979.             if (incr < 0) {
  2980.                 D(bug("PROBLEM: frestore_opp incr < 0\r\n"));
  2981.                 // this may be wrong, but it's never called.
  2982.                 ad -= 4;
  2983.                 d = get_long (ad);
  2984.                 if ((d & 0xff000000) == 0) { // NULL
  2985.                     D(bug("frestore_opp found NULL frame at %X\r\n",ad-4));
  2986.                     do_null_frestore();
  2987.                 } else if ((d & 0x00ff0000) == 0) { // IDLE
  2988.                     D(bug("frestore_opp found IDLE frame at %X\r\n",ad-4));
  2989.                 } else if ((d & 0x00ff0000) == 0x00300000) { // UNIMP
  2990.                     D(bug("PROBLEM: frestore_opp found UNIMP frame at %X\r\n",ad-4));
  2991.                     ad -= 44;
  2992.                 } else if ((d & 0x00ff0000) == 0x00600000) { // BUSY
  2993.                     D(bug("PROBLEM: frestore_opp found BUSY frame at %X\r\n",ad-4));
  2994.                     ad -= 92;
  2995.                 } else {
  2996.                     D(bug("PROBLEM: frestore_opp did not find a frame at %X, d=%X\r\n",ad-4,d));
  2997.                 }
  2998.             } else {
  2999.                 d = get_long (ad);
  3000.                 D(bug("frestore_opp frame at %X = %X\r\n",ad,d));
  3001.                 ad += 4;
  3002.                 if ((d & 0xff000000) == 0) { // NULL
  3003.                     D(bug("frestore_opp found NULL frame at %X\r\n",ad-4));
  3004.                     do_null_frestore();
  3005.                 } else if ((d & 0x00ff0000) == 0) { // IDLE
  3006.                     D(bug("frestore_opp found IDLE frame at %X\r\n",ad-4));
  3007.                 } else if ((d & 0x00ff0000) == 0x00300000) { // UNIMP
  3008.                     D(bug("PROBLEM: frestore_opp found UNIMP frame at %X\r\n",ad-4));
  3009.                     ad += 44;
  3010.                 } else if ((d & 0x00ff0000) == 0x00600000) { // BUSY
  3011.                     D(bug("PROBLEM: frestore_opp found BUSY frame at %X\r\n",ad-4));
  3012.                     ad += 92;
  3013.                 } else {
  3014.                     D(bug("PROBLEM: frestore_opp did not find a frame at %X, d=%X\r\n",ad-4,d));
  3015.                 }
  3016.             }
  3017.         } else {
  3018.             // 68881
  3019.             if (incr < 0) {
  3020.                 D(bug("PROBLEM: frestore_opp incr < 0\r\n"));
  3021.                 // this may be wrong, but it's never called.
  3022.                 ad -= 4;
  3023.                 d = get_long (ad);
  3024.                 if ((d & 0xff000000) == 0) { // NULL
  3025.                     do_null_frestore();
  3026.                 } else if ((d & 0x00ff0000) == 0x00180000) {
  3027.                     ad -= 6 * 4;
  3028.                 } else if ((d & 0x00ff0000) == 0x00380000) {
  3029.                     ad -= 14 * 4;
  3030.                 } else if ((d & 0x00ff0000) == 0x00b40000) {
  3031.                     ad -= 45 * 4;
  3032.                 }
  3033.             } else {
  3034.                 d = get_long (ad);
  3035.                 D(bug("frestore_opp frame at %X = %X\r\n",ad,d));
  3036.                 ad += 4;
  3037.                 if ((d & 0xff000000) == 0) { // NULL
  3038.                     D(bug("frestore_opp found NULL frame at %X\r\n",ad-4));
  3039.                     do_null_frestore();
  3040.                 } else if ((d & 0x00ff0000) == 0x00180000) { // IDLE
  3041.                     D(bug("frestore_opp found IDLE frame at %X\r\n",ad-4));
  3042.                     ad += 6 * 4;
  3043.                 } else if ((d & 0x00ff0000) == 0x00380000) {// UNIMP? shouldn't it be 3C?
  3044.                     ad += 14 * 4;
  3045.                     D(bug("PROBLEM: frestore_opp found UNIMP? frame at %X\r\n",ad-4));
  3046.                 } else if ((d & 0x00ff0000) == 0x00b40000) {// BUSY
  3047.                     D(bug("PROBLEM: frestore_opp found BUSY frame at %X\r\n",ad-4));
  3048.                     ad += 45 * 4;
  3049.                 } else {
  3050.                     D(bug("PROBLEM: frestore_opp did not find a frame at %X, d=%X\r\n",ad-4,d));
  3051.                 }
  3052.             }
  3053.         }
  3054.  
  3055.         if ((opcode & 0x38) == 0x18) {
  3056.             m68k_areg (regs, opcode & 7) = ad;
  3057.             D(bug("frestore_opp post-increment %X -> A%d\r\n",ad,opcode & 7));
  3058.         }
  3059.         if ((opcode & 0x38) == 0x20) {
  3060.             m68k_areg (regs, opcode & 7) = ad; // Never executed on a 68881
  3061.             D(bug("PROBLEM: frestore_opp pre-decrement\r\n"));
  3062.         }
  3063.   }
  3064. }
  3065.  
  3066.  
  3067. /* ---------------------------- Old-style interface ---------------------------- */
  3068.  
  3069. // #ifndef OPTIMIZED_8BIT_MEMORY_ACCESS
  3070. void REGPARAM2 fpp_opp(uae_u32 opcode, uae_u16 extra)
  3071. {
  3072.     uae_u32 mask = (extra & 0xFC7F) | ((opcode & 0x0038) << 4);
  3073.     (*fpufunctbl[mask])(opcode,extra);
  3074. }
  3075. // #endif
  3076.  
  3077.  
  3078. /* ---------------------------- Illegal ---------------------------- */
  3079.  
  3080. void REGPARAM2 fpuop_illg( uae_u32 opcode, uae_u16 extra )
  3081. {
  3082.     D(bug("ILLEGAL F OP 2 %X\r\n",opcode));
  3083.  
  3084. #if I3_ON_ILLEGAL_FPU_OP
  3085. #error "FIXME: asm int 3"
  3086.     _asm int 3
  3087. #endif
  3088.  
  3089.     m68k_setpc (m68k_getpc () - 4);
  3090.     op_illg (opcode);
  3091.     dump_fp_regs( "END  ");
  3092. }
  3093.  
  3094.  
  3095. /* ---------------------------- FPP -> <ea> ---------------------------- */
  3096.  
  3097. void REGPARAM2 fpuop_fmove_2_ea( uae_u32 opcode, uae_u16 extra )
  3098. {
  3099.     D(bug("FMOVE -> <ea>\r\n"));
  3100.  
  3101.     if (put_fp_value (fp_reg[(extra >> 7) & 7], opcode, extra) == 0) {
  3102.         m68k_setpc (m68k_getpc () - 4);
  3103.         op_illg (opcode);
  3104.     }
  3105.  
  3106.     /*
  3107.     Needed (among other things) by some Pack5/Elems68k transcendental
  3108.     functions, they require the ACCR_INEX flag after a "MOVE.D, Dreg".
  3109.     However, now put_fp_value() is responsible of clearing the exceptions
  3110.     and merging statuses.
  3111.     */
  3112.  
  3113.     /*
  3114.     WORD sw_temp;
  3115.     _asm FNSTSW sw_temp
  3116.     if(sw_temp & SW_PE) {
  3117.         _asm FNCLEX
  3118.         sw |= SW_PE;
  3119.         sw_accrued |= SW_PE;
  3120.     }
  3121.     */
  3122.  
  3123.     dump_fp_regs( "END  ");
  3124. }
  3125.  
  3126.  
  3127. /* ---------------------------- CONTROL REGS -> Dreg ---------------------------- */
  3128.  
  3129. void REGPARAM2 fpuop_fmovem_none_2_Dreg( uae_u32 opcode, uae_u16 extra )
  3130. {
  3131.     D(bug("FMOVEM control(none) -> D%d\r\n", opcode & 7));
  3132.     dump_fp_regs( "END  ");
  3133. }
  3134.  
  3135. void REGPARAM2 fpuop_fmovem_fpiar_2_Dreg( uae_u32 opcode, uae_u16 extra )
  3136. {
  3137.     D(bug("FMOVEM regs.fpiar (%X) -> D%d\r\n", regs.fpiar, opcode & 7));
  3138.     m68k_dreg (regs, opcode & 7) = regs.fpiar;
  3139.     dump_fp_regs( "END  ");
  3140. }
  3141.  
  3142. void REGPARAM2 fpuop_fmovem_fpsr_2_Dreg( uae_u32 opcode, uae_u16 extra )
  3143. {
  3144.     to_fpsr();
  3145.     D(bug("FMOVEM regs.fpsr (%X) -> D%d\r\n", regs.fpsr, opcode & 7));
  3146.     m68k_dreg (regs, opcode & 7) = regs.fpsr;
  3147.     dump_fp_regs( "END  ");
  3148. }
  3149.  
  3150. void REGPARAM2 fpuop_fmovem_fpcr_2_Dreg( uae_u32 opcode, uae_u16 extra )
  3151. {
  3152.     D(bug("FMOVEM regs.fpcr (%X) -> D%d\r\n", regs.fpcr, opcode & 7));
  3153.     m68k_dreg (regs, opcode & 7) = regs.fpcr;
  3154.     dump_fp_regs( "END  ");
  3155. }
  3156.  
  3157. void REGPARAM2 fpuop_fmovem_fpsr_fpiar_2_Dreg( uae_u32 opcode, uae_u16 extra )
  3158. {
  3159.     to_fpsr();
  3160.     D(bug("FMOVEM regs.fpsr (%X) -> D%d\r\n", regs.fpsr, opcode & 7));
  3161.     m68k_dreg (regs, opcode & 7) = regs.fpsr;
  3162.     D(bug("FMOVEM regs.fpiar (%X) -> D%d\r\n", regs.fpiar, opcode & 7));
  3163.     m68k_dreg (regs, opcode & 7) = regs.fpiar;
  3164.     dump_fp_regs( "END  ");
  3165. }
  3166.  
  3167. void REGPARAM2 fpuop_fmovem_fpcr_fpiar_2_Dreg( uae_u32 opcode, uae_u16 extra )
  3168. {
  3169.     D(bug("FMOVEM regs.fpcr (%X) -> D%d\r\n", regs.fpcr, opcode & 7));
  3170.     m68k_dreg (regs, opcode & 7) = regs.fpcr;
  3171.     D(bug("FMOVEM regs.fpiar (%X) -> D%d\r\n", regs.fpiar, opcode & 7));
  3172.     m68k_dreg (regs, opcode & 7) = regs.fpiar;
  3173.     dump_fp_regs( "END  ");
  3174. }
  3175.  
  3176. void REGPARAM2 fpuop_fmovem_fpcr_fpsr_2_Dreg( uae_u32 opcode, uae_u16 extra )
  3177. {
  3178.     D(bug("FMOVEM regs.fpcr (%X) -> D%d\r\n", regs.fpcr, opcode & 7));
  3179.     m68k_dreg (regs, opcode & 7) = regs.fpcr;
  3180.     to_fpsr();
  3181.     D(bug("FMOVEM regs.fpsr (%X) -> D%d\r\n", regs.fpsr, opcode & 7));
  3182.     m68k_dreg (regs, opcode & 7) = regs.fpsr;
  3183.     dump_fp_regs( "END  ");
  3184. }
  3185.  
  3186. void REGPARAM2 fpuop_fmovem_fpcr_fpsr_fpiar_2_Dreg( uae_u32 opcode, uae_u16 extra )
  3187. {
  3188.     D(bug("FMOVEM regs.fpcr (%X) -> D%d\r\n", regs.fpcr, opcode & 7));
  3189.     m68k_dreg (regs, opcode & 7) = regs.fpcr;
  3190.     to_fpsr();
  3191.     D(bug("FMOVEM regs.fpsr (%X) -> D%d\r\n", regs.fpsr, opcode & 7));
  3192.     m68k_dreg (regs, opcode & 7) = regs.fpsr;
  3193.     D(bug("FMOVEM regs.fpiar (%X) -> D%d\r\n", regs.fpiar, opcode & 7));
  3194.     m68k_dreg (regs, opcode & 7) = regs.fpiar;
  3195.     dump_fp_regs( "END  ");
  3196. }
  3197.  
  3198.  
  3199. /* ---------------------------- Dreg -> CONTROL REGS ---------------------------- */
  3200.  
  3201. void REGPARAM2 fpuop_fmovem_Dreg_2_none( uae_u32 opcode, uae_u16 extra )
  3202. {
  3203.     D(bug("FMOVEM D%d -> control(none)\r\n", opcode & 7));
  3204.     dump_fp_regs( "END  ");
  3205. }
  3206.  
  3207. void REGPARAM2 fpuop_fmovem_Dreg_2_fpiar( uae_u32 opcode, uae_u16 extra )
  3208. {
  3209.     regs.fpiar = m68k_dreg (regs, opcode & 7);
  3210.     D(bug("FMOVEM D%d (%X) -> regs.fpiar\r\n", opcode & 7, regs.fpiar));
  3211.     dump_fp_regs( "END  ");
  3212. }
  3213.  
  3214. void REGPARAM2 fpuop_fmovem_Dreg_2_fpsr( uae_u32 opcode, uae_u16 extra )
  3215. {
  3216.     regs.fpsr = m68k_dreg (regs, opcode & 7);
  3217.     from_fpsr();
  3218.     D(bug("FMOVEM D%d (%X) -> regs.fpsr\r\n", opcode & 7, regs.fpsr));
  3219.     dump_fp_regs( "END  ");
  3220. }
  3221.  
  3222. void REGPARAM2 fpuop_fmovem_Dreg_2_fpsr_fpiar( uae_u32 opcode, uae_u16 extra )
  3223. {
  3224.     regs.fpsr = m68k_dreg (regs, opcode & 7);
  3225.     from_fpsr();
  3226.     D(bug("FMOVEM D%d (%X) -> regs.fpsr\r\n", opcode & 7, regs.fpsr));
  3227.     regs.fpiar = m68k_dreg (regs, opcode & 7);
  3228.     D(bug("FMOVEM D%d (%X) -> regs.fpiar\r\n", opcode & 7, regs.fpiar));
  3229.     dump_fp_regs( "END  ");
  3230. }
  3231.  
  3232. void REGPARAM2 fpuop_fmovem_Dreg_2_fpcr( uae_u32 opcode, uae_u16 extra )
  3233. {
  3234.     regs.fpcr = m68k_dreg (regs, opcode & 7);
  3235.     set_host_fpu_control_word();
  3236.     D(bug("FMOVEM D%d (%X) -> regs.fpcr\r\n", opcode & 7, regs.fpcr));
  3237.     dump_fp_regs( "END  ");
  3238. }
  3239.  
  3240. void REGPARAM2 fpuop_fmovem_Dreg_2_fpcr_fpiar( uae_u32 opcode, uae_u16 extra )
  3241. {
  3242.     regs.fpcr = m68k_dreg (regs, opcode & 7);
  3243.     set_host_fpu_control_word();
  3244.     D(bug("FMOVEM D%d (%X) -> regs.fpcr\r\n", opcode & 7, regs.fpcr));
  3245.     regs.fpiar = m68k_dreg (regs, opcode & 7);
  3246.     D(bug("FMOVEM D%d (%X) -> regs.fpiar\r\n", opcode & 7, regs.fpiar));
  3247.     dump_fp_regs( "END  ");
  3248. }
  3249.  
  3250. void REGPARAM2 fpuop_fmovem_Dreg_2_fpcr_fpsr( uae_u32 opcode, uae_u16 extra )
  3251. {
  3252.     regs.fpcr = m68k_dreg (regs, opcode & 7);
  3253.     set_host_fpu_control_word();
  3254.     D(bug("FMOVEM D%d (%X) -> regs.fpcr\r\n", opcode & 7, regs.fpcr));
  3255.     regs.fpsr = m68k_dreg (regs, opcode & 7);
  3256.     from_fpsr();
  3257.     D(bug("FMOVEM D%d (%X) -> regs.fpsr\r\n", opcode & 7, regs.fpsr));
  3258.     dump_fp_regs( "END  ");
  3259. }
  3260.  
  3261. void REGPARAM2 fpuop_fmovem_Dreg_2_fpcr_fpsr_fpiar( uae_u32 opcode, uae_u16 extra )
  3262. {
  3263.     regs.fpcr = m68k_dreg (regs, opcode & 7);
  3264.     set_host_fpu_control_word();
  3265.     D(bug("FMOVEM D%d (%X) -> regs.fpcr\r\n", opcode & 7, regs.fpcr));
  3266.     regs.fpsr = m68k_dreg (regs, opcode & 7);
  3267.     from_fpsr();
  3268.     D(bug("FMOVEM D%d (%X) -> regs.fpsr\r\n", opcode & 7, regs.fpsr));
  3269.     regs.fpiar = m68k_dreg (regs, opcode & 7);
  3270.     D(bug("FMOVEM D%d (%X) -> regs.fpiar\r\n", opcode & 7, regs.fpiar));
  3271.     dump_fp_regs( "END  ");
  3272. }
  3273.  
  3274.  
  3275. /* ---------------------------- CONTROL REGS -> Areg ---------------------------- */
  3276.  
  3277. void REGPARAM2 fpuop_fmovem_none_2_Areg( uae_u32 opcode, uae_u16 extra )
  3278. {
  3279.     D(bug("FMOVEM control(none) -> A%d\r\n", opcode & 7));
  3280.     dump_fp_regs( "END  ");
  3281. }
  3282.  
  3283. void REGPARAM2 fpuop_fmovem_fpiar_2_Areg( uae_u32 opcode, uae_u16 extra )
  3284. {
  3285.     D(bug("FMOVEM regs.fpiar (%X) -> A%d\r\n", regs.fpiar, opcode & 7));
  3286.     m68k_areg (regs, opcode & 7) = regs.fpiar;
  3287.     dump_fp_regs( "END  ");
  3288. }
  3289.  
  3290. void REGPARAM2 fpuop_fmovem_fpsr_2_Areg( uae_u32 opcode, uae_u16 extra )
  3291. {
  3292.     to_fpsr();
  3293.     D(bug("FMOVEM regs.fpsr (%X) -> A%d\r\n", regs.fpsr, opcode & 7));
  3294.     m68k_areg (regs, opcode & 7) = regs.fpsr;
  3295.     dump_fp_regs( "END  ");
  3296. }
  3297.  
  3298. void REGPARAM2 fpuop_fmovem_fpcr_2_Areg( uae_u32 opcode, uae_u16 extra )
  3299. {
  3300.     D(bug("FMOVEM regs.fpcr (%X) -> A%d\r\n", regs.fpcr, opcode & 7));
  3301.     m68k_areg (regs, opcode & 7) = regs.fpcr;
  3302.     dump_fp_regs( "END  ");
  3303. }
  3304.  
  3305. void REGPARAM2 fpuop_fmovem_fpsr_fpiar_2_Areg( uae_u32 opcode, uae_u16 extra )
  3306. {
  3307.     to_fpsr();
  3308.     D(bug("FMOVEM regs.fpsr (%X) -> A%d\r\n", regs.fpsr, opcode & 7));
  3309.     m68k_areg (regs, opcode & 7) = regs.fpsr;
  3310.     D(bug("FMOVEM regs.fpiar (%X) -> A%d\r\n", regs.fpiar, opcode & 7));
  3311.     m68k_areg (regs, opcode & 7) = regs.fpiar;
  3312.     dump_fp_regs( "END  ");
  3313. }
  3314.  
  3315. void REGPARAM2 fpuop_fmovem_fpcr_fpiar_2_Areg( uae_u32 opcode, uae_u16 extra )
  3316. {
  3317.     D(bug("FMOVEM regs.fpcr (%X) -> A%d\r\n", regs.fpcr, opcode & 7));
  3318.     m68k_areg (regs, opcode & 7) = regs.fpcr;
  3319.     D(bug("FMOVEM regs.fpiar (%X) -> A%d\r\n", regs.fpiar, opcode & 7));
  3320.     m68k_areg (regs, opcode & 7) = regs.fpiar;
  3321.     dump_fp_regs( "END  ");
  3322. }
  3323.  
  3324. void REGPARAM2 fpuop_fmovem_fpcr_fpsr_2_Areg( uae_u32 opcode, uae_u16 extra )
  3325. {
  3326.     D(bug("FMOVEM regs.fpcr (%X) -> A%d\r\n", regs.fpcr, opcode & 7));
  3327.     m68k_areg (regs, opcode & 7) = regs.fpcr;
  3328.     to_fpsr();
  3329.     D(bug("FMOVEM regs.fpsr (%X) -> A%d\r\n", regs.fpsr, opcode & 7));
  3330.     m68k_areg (regs, opcode & 7) = regs.fpsr;
  3331.     dump_fp_regs( "END  ");
  3332. }
  3333.  
  3334. void REGPARAM2 fpuop_fmovem_fpcr_fpsr_fpiar_2_Areg( uae_u32 opcode, uae_u16 extra )
  3335. {
  3336.     D(bug("FMOVEM regs.fpcr (%X) -> A%d\r\n", regs.fpcr, opcode & 7));
  3337.     m68k_areg (regs, opcode & 7) = regs.fpcr;
  3338.     to_fpsr();
  3339.     D(bug("FMOVEM regs.fpsr (%X) -> A%d\r\n", regs.fpsr, opcode & 7));
  3340.     m68k_areg (regs, opcode & 7) = regs.fpsr;
  3341.     D(bug("FMOVEM regs.fpiar (%X) -> A%d\r\n", regs.fpiar, opcode & 7));
  3342.     m68k_areg (regs, opcode & 7) = regs.fpiar;
  3343.     dump_fp_regs( "END  ");
  3344. }
  3345.  
  3346.  
  3347. /* ---------------------------- Areg -> CONTROL REGS ---------------------------- */
  3348.  
  3349. void REGPARAM2 fpuop_fmovem_Areg_2_none( uae_u32 opcode, uae_u16 extra )
  3350. {
  3351.     D(bug("FMOVEM A%d -> control(none)\r\n", opcode & 7));
  3352.     dump_fp_regs( "END  ");
  3353. }
  3354.  
  3355. void REGPARAM2 fpuop_fmovem_Areg_2_fpiar( uae_u32 opcode, uae_u16 extra )
  3356. {
  3357.     regs.fpiar = m68k_areg (regs, opcode & 7);
  3358.     D(bug("FMOVEM A%d (%X) -> regs.fpiar\r\n", opcode & 7, regs.fpiar));
  3359.     dump_fp_regs( "END  ");
  3360. }
  3361.  
  3362. void REGPARAM2 fpuop_fmovem_Areg_2_fpsr( uae_u32 opcode, uae_u16 extra )
  3363. {
  3364.     regs.fpsr = m68k_areg (regs, opcode & 7);
  3365.     from_fpsr();
  3366.     D(bug("FMOVEM A%d (%X) -> regs.fpsr\r\n", opcode & 7, regs.fpsr));
  3367.     dump_fp_regs( "END  ");
  3368. }
  3369.  
  3370. void REGPARAM2 fpuop_fmovem_Areg_2_fpsr_fpiar( uae_u32 opcode, uae_u16 extra )
  3371. {
  3372.     regs.fpsr = m68k_areg (regs, opcode & 7);
  3373.     from_fpsr();
  3374.     D(bug("FMOVEM A%d (%X) -> regs.fpsr\r\n", opcode & 7, regs.fpsr));
  3375.     regs.fpiar = m68k_areg (regs, opcode & 7);
  3376.     D(bug("FMOVEM A%d (%X) -> regs.fpiar\r\n", opcode & 7, regs.fpiar));
  3377.     dump_fp_regs( "END  ");
  3378. }
  3379.  
  3380. void REGPARAM2 fpuop_fmovem_Areg_2_fpcr( uae_u32 opcode, uae_u16 extra )
  3381. {
  3382.     regs.fpcr = m68k_areg (regs, opcode & 7);
  3383.     set_host_fpu_control_word();
  3384.     D(bug("FMOVEM A%d (%X) -> regs.fpcr\r\n", opcode & 7, regs.fpcr));
  3385.     dump_fp_regs( "END  ");
  3386. }
  3387.  
  3388. void REGPARAM2 fpuop_fmovem_Areg_2_fpcr_fpiar( uae_u32 opcode, uae_u16 extra )
  3389. {
  3390.     regs.fpcr = m68k_areg (regs, opcode & 7);
  3391.     set_host_fpu_control_word();
  3392.     D(bug("FMOVEM A%d (%X) -> regs.fpcr\r\n", opcode & 7, regs.fpcr));
  3393.     regs.fpiar = m68k_areg (regs, opcode & 7);
  3394.     D(bug("FMOVEM A%d (%X) -> regs.fpiar\r\n", opcode & 7, regs.fpiar));
  3395.     dump_fp_regs( "END  ");
  3396. }
  3397.  
  3398. void REGPARAM2 fpuop_fmovem_Areg_2_fpcr_fpsr( uae_u32 opcode, uae_u16 extra )
  3399. {
  3400.     regs.fpcr = m68k_areg (regs, opcode & 7);
  3401.     set_host_fpu_control_word();
  3402.     D(bug("FMOVEM A%d (%X) -> regs.fpcr\r\n", opcode & 7, regs.fpcr));
  3403.     regs.fpsr = m68k_areg (regs, opcode & 7);
  3404.     from_fpsr();
  3405.     D(bug("FMOVEM A%d (%X) -> regs.fpsr\r\n", opcode & 7, regs.fpsr));
  3406.     dump_fp_regs( "END  ");
  3407. }
  3408.  
  3409. void REGPARAM2 fpuop_fmovem_Areg_2_fpcr_fpsr_fpiar( uae_u32 opcode, uae_u16 extra )
  3410. {
  3411.     regs.fpcr = m68k_areg (regs, opcode & 7);
  3412.     set_host_fpu_control_word();
  3413.     D(bug("FMOVEM A%d (%X) -> regs.fpcr\r\n", opcode & 7, regs.fpcr));
  3414.     regs.fpsr = m68k_areg (regs, opcode & 7);
  3415.     from_fpsr();
  3416.     D(bug("FMOVEM A%d (%X) -> regs.fpsr\r\n", opcode & 7, regs.fpsr));
  3417.     regs.fpiar = m68k_areg (regs, opcode & 7);
  3418.     D(bug("FMOVEM A%d (%X) -> regs.fpiar\r\n", opcode & 7, regs.fpiar));
  3419.     dump_fp_regs( "END  ");
  3420. }
  3421.  
  3422.  
  3423. /* ---------------------------- CONTROL REGS -> --MEMORY---------------------------- */
  3424.  
  3425. void REGPARAM2 fpuop_fmovem_none_2_Mem_predecrement( uae_u32 opcode, uae_u16 extra )
  3426. {
  3427.     D(bug("FMOVEM Control regs (none) -> mem\r\n" ));
  3428.     dump_fp_regs( "END  ");
  3429. }
  3430.  
  3431. void REGPARAM2 fpuop_fmovem_fpiar_2_Mem_predecrement( uae_u32 opcode, uae_u16 extra )
  3432. {
  3433.     uae_u32 ad;
  3434.     if (get_fp_ad(opcode, &ad)) {
  3435.         ad -= 4;
  3436.         put_long (ad, regs.fpiar);
  3437.         D(bug("FMOVEM regs.fpiar (%X) -> mem %X\r\n", regs.fpiar, ad ));
  3438.         m68k_areg (regs, opcode & 7) = ad;
  3439.         dump_fp_regs( "END  ");
  3440.     }
  3441. }
  3442.  
  3443. void REGPARAM2 fpuop_fmovem_fpsr_2_Mem_predecrement( uae_u32 opcode, uae_u16 extra )
  3444. {
  3445.     uae_u32 ad;
  3446.     if (get_fp_ad(opcode, &ad)) {
  3447.         ad -= 4;
  3448.         to_fpsr();
  3449.         put_long (ad, regs.fpsr);
  3450.         D(bug("FMOVEM regs.fpsr (%X) -> mem %X\r\n", regs.fpsr, ad ));
  3451.         m68k_areg (regs, opcode & 7) = ad;
  3452.         dump_fp_regs( "END  ");
  3453.     }
  3454. }
  3455.  
  3456. void REGPARAM2 fpuop_fmovem_fpsr_fpiar_2_Mem_predecrement( uae_u32 opcode, uae_u16 extra )
  3457. {
  3458.     uae_u32 ad;
  3459.     if (get_fp_ad(opcode, &ad)) {
  3460.         ad -= 8;
  3461.         to_fpsr();
  3462.         put_long (ad, regs.fpsr);
  3463.         D(bug("FMOVEM regs.fpsr (%X) -> mem %X\r\n", regs.fpsr, ad ));
  3464.         put_long (ad+4, regs.fpiar);
  3465.         D(bug("FMOVEM regs.fpiar (%X) -> mem %X\r\n", regs.fpiar, ad+4 ));
  3466.         m68k_areg (regs, opcode & 7) = ad;
  3467.         dump_fp_regs( "END  ");
  3468.     }
  3469. }
  3470.  
  3471. void REGPARAM2 fpuop_fmovem_fpcr_2_Mem_predecrement( uae_u32 opcode, uae_u16 extra )
  3472. {
  3473.     uae_u32 ad;
  3474.     if (get_fp_ad(opcode, &ad)) {
  3475.         ad -= 4;
  3476.         put_long (ad, regs.fpcr);
  3477.         D(bug("FMOVEM regs.fpcr (%X) -> mem %X\r\n", regs.fpcr, ad ));
  3478.         m68k_areg (regs, opcode & 7) = ad;
  3479.         dump_fp_regs( "END  ");
  3480.     }
  3481. }
  3482.  
  3483. void REGPARAM2 fpuop_fmovem_fpcr_fpiar_2_Mem_predecrement( uae_u32 opcode, uae_u16 extra )
  3484. {
  3485.     uae_u32 ad;
  3486.     if (get_fp_ad(opcode, &ad)) {
  3487.         ad -= 8;
  3488.         put_long (ad, regs.fpcr);
  3489.         D(bug("FMOVEM regs.fpcr (%X) -> mem %X\r\n", regs.fpcr, ad ));
  3490.         put_long (ad+4, regs.fpiar);
  3491.         D(bug("FMOVEM regs.fpiar (%X) -> mem %X\r\n", regs.fpiar, ad+4 ));
  3492.         m68k_areg (regs, opcode & 7) = ad;
  3493.         dump_fp_regs( "END  ");
  3494.     }
  3495. }
  3496.  
  3497. void REGPARAM2 fpuop_fmovem_fpcr_fpsr_2_Mem_predecrement( uae_u32 opcode, uae_u16 extra )
  3498. {
  3499.     uae_u32 ad;
  3500.     if (get_fp_ad(opcode, &ad)) {
  3501.         ad -= 8;
  3502.         put_long (ad, regs.fpcr);
  3503.         D(bug("FMOVEM regs.fpcr (%X) -> mem %X\r\n", regs.fpcr, ad ));
  3504.         to_fpsr();
  3505.         put_long (ad+4, regs.fpsr);
  3506.         D(bug("FMOVEM regs.fpsr (%X) -> mem %X\r\n", regs.fpsr, ad+4 ));
  3507.         m68k_areg (regs, opcode & 7) = ad;
  3508.         dump_fp_regs( "END  ");
  3509.     }
  3510. }
  3511.  
  3512. void REGPARAM2 fpuop_fmovem_fpcr_fpsr_fpiar_2_Mem_predecrement( uae_u32 opcode, uae_u16 extra )
  3513. {
  3514.     uae_u32 ad;
  3515.     if (get_fp_ad(opcode, &ad)) {
  3516.         ad -= 12;
  3517.         put_long (ad, regs.fpcr);
  3518.         D(bug("FMOVEM regs.fpcr (%X) -> mem %X\r\n", regs.fpcr, ad ));
  3519.         to_fpsr();
  3520.         put_long (ad+4, regs.fpsr);
  3521.         D(bug("FMOVEM regs.fpsr (%X) -> mem %X\r\n", regs.fpsr, ad+4 ));
  3522.         put_long (ad+8, regs.fpiar);
  3523.         D(bug("FMOVEM regs.fpiar (%X) -> mem %X\r\n", regs.fpiar, ad+8 ));
  3524.         m68k_areg (regs, opcode & 7) = ad;
  3525.         dump_fp_regs( "END  ");
  3526.     }
  3527. }
  3528.  
  3529.  
  3530. /* ---------------------------- CONTROL REGS -> MEMORY++ ---------------------------- */
  3531.  
  3532. void REGPARAM2 fpuop_fmovem_none_2_Mem_postincrement( uae_u32 opcode, uae_u16 extra )
  3533. {
  3534.     D(bug("FMOVEM Control regs (none) -> mem\r\n" ));
  3535.     dump_fp_regs( "END  ");
  3536. }
  3537.  
  3538. void REGPARAM2 fpuop_fmovem_fpiar_2_Mem_postincrement( uae_u32 opcode, uae_u16 extra )
  3539. {
  3540.     uae_u32 ad;
  3541.     if (get_fp_ad(opcode, &ad)) {
  3542.         put_long (ad, regs.fpiar);
  3543.         D(bug("FMOVEM regs.fpiar (%X) -> mem %X\r\n", regs.fpiar, ad ));
  3544.         m68k_areg (regs, opcode & 7) = ad+4;
  3545.         dump_fp_regs( "END  ");
  3546.     }
  3547. }
  3548.  
  3549. void REGPARAM2 fpuop_fmovem_fpsr_2_Mem_postincrement( uae_u32 opcode, uae_u16 extra )
  3550. {
  3551.     uae_u32 ad;
  3552.     if (get_fp_ad(opcode, &ad)) {
  3553.         to_fpsr();
  3554.         put_long (ad, regs.fpsr);
  3555.         D(bug("FMOVEM regs.fpsr (%X) -> mem %X\r\n", regs.fpsr, ad ));
  3556.         m68k_areg (regs, opcode & 7) = ad+4;
  3557.         dump_fp_regs( "END  ");
  3558.     }
  3559. }
  3560.  
  3561. void REGPARAM2 fpuop_fmovem_fpsr_fpiar_2_Mem_postincrement( uae_u32 opcode, uae_u16 extra )
  3562. {
  3563.     uae_u32 ad;
  3564.     if (get_fp_ad(opcode, &ad)) {
  3565.         to_fpsr();
  3566.         put_long (ad, regs.fpsr);
  3567.         D(bug("FMOVEM regs.fpsr (%X) -> mem %X\r\n", regs.fpsr, ad ));
  3568.         put_long (ad+4, regs.fpiar);
  3569.         D(bug("FMOVEM regs.fpiar (%X) -> mem %X\r\n", regs.fpiar, ad+4 ));
  3570.         m68k_areg (regs, opcode & 7) = ad+8;
  3571.         dump_fp_regs( "END  ");
  3572.     }
  3573. }
  3574.  
  3575. void REGPARAM2 fpuop_fmovem_fpcr_2_Mem_postincrement( uae_u32 opcode, uae_u16 extra )
  3576. {
  3577.     uae_u32 ad;
  3578.     if (get_fp_ad(opcode, &ad)) {
  3579.         put_long (ad, regs.fpcr);
  3580.         D(bug("FMOVEM regs.fpcr (%X) -> mem %X\r\n", regs.fpcr, ad ));
  3581.         m68k_areg (regs, opcode & 7) = ad+4;
  3582.         dump_fp_regs( "END  ");
  3583.     }
  3584. }
  3585.  
  3586. void REGPARAM2 fpuop_fmovem_fpcr_fpiar_2_Mem_postincrement( uae_u32 opcode, uae_u16 extra )
  3587. {
  3588.     uae_u32 ad;
  3589.     if (get_fp_ad(opcode, &ad)) {
  3590.         put_long (ad, regs.fpcr);
  3591.         D(bug("FMOVEM regs.fpcr (%X) -> mem %X\r\n", regs.fpcr, ad ));
  3592.         put_long (ad+4, regs.fpiar);
  3593.         D(bug("FMOVEM regs.fpiar (%X) -> mem %X\r\n", regs.fpiar, ad+4 ));
  3594.         m68k_areg (regs, opcode & 7) = ad+8;
  3595.         dump_fp_regs( "END  ");
  3596.     }
  3597. }
  3598.  
  3599. void REGPARAM2 fpuop_fmovem_fpcr_fpsr_2_Mem_postincrement( uae_u32 opcode, uae_u16 extra )
  3600. {
  3601.     dump_fp_regs( "END  ");
  3602.     uae_u32 ad;
  3603.     if (get_fp_ad(opcode, &ad)) {
  3604.         put_long (ad, regs.fpcr);
  3605.         D(bug("FMOVEM regs.fpcr (%X) -> mem %X\r\n", regs.fpcr, ad ));
  3606.         to_fpsr();
  3607.         put_long (ad+4, regs.fpsr);
  3608.         D(bug("FMOVEM regs.fpsr (%X) -> mem %X\r\n", regs.fpsr, ad+4 ));
  3609.         m68k_areg (regs, opcode & 7) = ad+8;
  3610.     }
  3611. }
  3612.  
  3613. void REGPARAM2 fpuop_fmovem_fpcr_fpsr_fpiar_2_Mem_postincrement( uae_u32 opcode, uae_u16 extra )
  3614. {
  3615.     uae_u32 ad;
  3616.     if (get_fp_ad(opcode, &ad)) {
  3617.         put_long (ad, regs.fpcr);
  3618.         D(bug("FMOVEM regs.fpcr (%X) -> mem %X\r\n", regs.fpcr, ad ));
  3619.         to_fpsr();
  3620.         put_long (ad+4, regs.fpsr);
  3621.         D(bug("FMOVEM regs.fpsr (%X) -> mem %X\r\n", regs.fpsr, ad+4 ));
  3622.         put_long (ad+8, regs.fpiar);
  3623.         D(bug("FMOVEM regs.fpiar (%X) -> mem %X\r\n", regs.fpiar, ad+8 ));
  3624.         m68k_areg (regs, opcode & 7) = ad+12;
  3625.         dump_fp_regs( "END  ");
  3626.     }
  3627. }
  3628.  
  3629.  
  3630. /* ---------------------------- CONTROL REGS -> MEMORY ---------------------------- */
  3631.  
  3632. void REGPARAM2 fpuop_fmovem_none_2_Mem( uae_u32 opcode, uae_u16 extra )
  3633. {
  3634.     D(bug("FMOVEM Control regs (none) -> mem\r\n" ));
  3635.     dump_fp_regs( "END  ");
  3636. }
  3637.  
  3638. void REGPARAM2 fpuop_fmovem_fpiar_2_Mem( uae_u32 opcode, uae_u16 extra )
  3639. {
  3640.     uae_u32 ad;
  3641.     if (get_fp_ad(opcode, &ad)) {
  3642.         put_long (ad, regs.fpiar);
  3643.         D(bug("FMOVEM regs.fpiar (%X) -> mem %X\r\n", regs.fpiar, ad ));
  3644.         dump_fp_regs( "END  ");
  3645.     }
  3646. }
  3647.  
  3648. void REGPARAM2 fpuop_fmovem_fpsr_2_Mem( uae_u32 opcode, uae_u16 extra )
  3649. {
  3650.     uae_u32 ad;
  3651.     if (get_fp_ad(opcode, &ad)) {
  3652.         to_fpsr();
  3653.         put_long (ad, regs.fpsr);
  3654.         D(bug("FMOVEM regs.fpsr (%X) -> mem %X\r\n", regs.fpsr, ad ));
  3655.         dump_fp_regs( "END  ");
  3656.     }
  3657. }
  3658.  
  3659. void REGPARAM2 fpuop_fmovem_fpsr_fpiar_2_Mem( uae_u32 opcode, uae_u16 extra )
  3660. {
  3661.     uae_u32 ad;
  3662.     if (get_fp_ad(opcode, &ad)) {
  3663.         to_fpsr();
  3664.         put_long (ad, regs.fpsr);
  3665.         D(bug("FMOVEM regs.fpsr (%X) -> mem %X\r\n", regs.fpsr, ad ));
  3666.         put_long (ad+4, regs.fpiar);
  3667.         D(bug("FMOVEM regs.fpiar (%X) -> mem %X\r\n", regs.fpiar, ad+4 ));
  3668.         dump_fp_regs( "END  ");
  3669.     }
  3670. }
  3671.  
  3672. void REGPARAM2 fpuop_fmovem_fpcr_2_Mem( uae_u32 opcode, uae_u16 extra )
  3673. {
  3674.     uae_u32 ad;
  3675.     if (get_fp_ad(opcode, &ad)) {
  3676.         put_long (ad, regs.fpcr);
  3677.         D(bug("FMOVEM regs.fpcr (%X) -> mem %X\r\n", regs.fpcr, ad ));
  3678.         dump_fp_regs( "END  ");
  3679.     }
  3680. }
  3681.  
  3682. void REGPARAM2 fpuop_fmovem_fpcr_fpiar_2_Mem( uae_u32 opcode, uae_u16 extra )
  3683. {
  3684.     uae_u32 ad;
  3685.     if (get_fp_ad(opcode, &ad)) {
  3686.         put_long (ad, regs.fpcr);
  3687.         D(bug("FMOVEM regs.fpcr (%X) -> mem %X\r\n", regs.fpcr, ad ));
  3688.         put_long (ad+4, regs.fpiar);
  3689.         D(bug("FMOVEM regs.fpiar (%X) -> mem %X\r\n", regs.fpiar, ad+4 ));
  3690.         dump_fp_regs( "END  ");
  3691.     }
  3692. }
  3693.  
  3694. void REGPARAM2 fpuop_fmovem_fpcr_fpsr_2_Mem( uae_u32 opcode, uae_u16 extra )
  3695. {
  3696.     uae_u32 ad;
  3697.     if (get_fp_ad(opcode, &ad)) {
  3698.         put_long (ad, regs.fpcr);
  3699.         D(bug("FMOVEM regs.fpcr (%X) -> mem %X\r\n", regs.fpcr, ad ));
  3700.         to_fpsr();
  3701.         put_long (ad+4, regs.fpsr);
  3702.         D(bug("FMOVEM regs.fpsr (%X) -> mem %X\r\n", regs.fpsr, ad+4 ));
  3703.         dump_fp_regs( "END  ");
  3704.     }
  3705. }
  3706.  
  3707. void REGPARAM2 fpuop_fmovem_fpcr_fpsr_fpiar_2_Mem( uae_u32 opcode, uae_u16 extra )
  3708. {
  3709.     uae_u32 ad;
  3710.     if (get_fp_ad(opcode, &ad)) {
  3711.         put_long (ad, regs.fpcr);
  3712.         D(bug("FMOVEM regs.fpcr (%X) -> mem %X\r\n", regs.fpcr, ad ));
  3713.         to_fpsr();
  3714.         put_long (ad+4, regs.fpsr);
  3715.         D(bug("FMOVEM regs.fpsr (%X) -> mem %X\r\n", regs.fpsr, ad+4 ));
  3716.         put_long (ad+8, regs.fpiar);
  3717.         D(bug("FMOVEM regs.fpiar (%X) -> mem %X\r\n", regs.fpiar, ad+8 ));
  3718.         dump_fp_regs( "END  ");
  3719.     }
  3720. }
  3721.  
  3722.  
  3723. /* ---------------------------- --MEMORY -> CONTROL REGS ---------------------------- */
  3724.  
  3725. void REGPARAM2 fpuop_fmovem_Mem_2_none_predecrement( uae_u32 opcode, uae_u16 extra )
  3726. {
  3727.     D(bug("FMOVEM --Mem -> control(none)\r\n"));
  3728.     dump_fp_regs( "END  ");
  3729. }
  3730.  
  3731. void REGPARAM2 fpuop_fmovem_Mem_2_fpiar_predecrement( uae_u32 opcode, uae_u16 extra )
  3732. {
  3733.     uae_u32 ad;
  3734.     if (get_fp_ad(opcode, &ad)) {
  3735.         ad -= 4;
  3736.         regs.fpiar = get_long (ad);
  3737.         D(bug("FMOVEM mem %X (%X) -> regs.fpiar\r\n", ad, regs.fpiar ));
  3738.         m68k_areg (regs, opcode & 7) = ad;
  3739.         dump_fp_regs( "END  ");
  3740.     }
  3741. }
  3742.  
  3743. void REGPARAM2 fpuop_fmovem_Mem_2_fpsr_predecrement( uae_u32 opcode, uae_u16 extra )
  3744. {
  3745.     uae_u32 ad;
  3746.     if (get_fp_ad(opcode, &ad)) {
  3747.         ad -= 4;
  3748.         regs.fpsr = get_long (ad);
  3749.         from_fpsr();
  3750.         D(bug("FMOVEM mem %X (%X) -> regs.fpsr\r\n", ad, regs.fpsr ));
  3751.         m68k_areg (regs, opcode & 7) = ad;
  3752.         dump_fp_regs( "END  ");
  3753.     }
  3754. }
  3755.  
  3756. void REGPARAM2 fpuop_fmovem_Mem_2_fpsr_fpiar_predecrement( uae_u32 opcode, uae_u16 extra )
  3757. {
  3758.     uae_u32 ad;
  3759.     if (get_fp_ad(opcode, &ad)) {
  3760.         ad -= 8;
  3761.         regs.fpsr = get_long (ad);
  3762.         from_fpsr();
  3763.         D(bug("FMOVEM mem %X (%X) -> regs.fpsr\r\n", ad, regs.fpsr ));
  3764.         regs.fpiar = get_long (ad+4);
  3765.         D(bug("FMOVEM mem %X (%X) -> regs.fpiar\r\n", ad+4, regs.fpiar ));
  3766.         m68k_areg (regs, opcode & 7) = ad;
  3767.         dump_fp_regs( "END  ");
  3768.     }
  3769. }
  3770.  
  3771. void REGPARAM2 fpuop_fmovem_Mem_2_fpcr_predecrement( uae_u32 opcode, uae_u16 extra )
  3772. {
  3773.     uae_u32 ad;
  3774.     if (get_fp_ad(opcode, &ad)) {
  3775.         ad -= 4;
  3776.         regs.fpcr = get_long (ad);
  3777.         set_host_fpu_control_word();
  3778.         D(bug("FMOVEM mem %X (%X) -> regs.fpcr\r\n", ad, regs.fpcr ));
  3779.         m68k_areg (regs, opcode & 7) = ad;
  3780.         dump_fp_regs( "END  ");
  3781.     }
  3782. }
  3783.  
  3784. void REGPARAM2 fpuop_fmovem_Mem_2_fpcr_fpiar_predecrement( uae_u32 opcode, uae_u16 extra )
  3785. {
  3786.     uae_u32 ad;
  3787.     if (get_fp_ad(opcode, &ad)) {
  3788.         ad -= 8;
  3789.         regs.fpcr = get_long (ad);
  3790.         set_host_fpu_control_word();
  3791.         D(bug("FMOVEM mem %X (%X) -> regs.fpcr\r\n", ad, regs.fpcr ));
  3792.         regs.fpiar = get_long (ad+4);
  3793.         D(bug("FMOVEM mem %X (%X) -> regs.fpiar\r\n", ad+4, regs.fpiar ));
  3794.         m68k_areg (regs, opcode & 7) = ad;
  3795.         dump_fp_regs( "END  ");
  3796.     }
  3797. }
  3798.  
  3799. void REGPARAM2 fpuop_fmovem_Mem_2_fpcr_fpsr_predecrement( uae_u32 opcode, uae_u16 extra )
  3800. {
  3801.     uae_u32 ad;
  3802.     if (get_fp_ad(opcode, &ad)) {
  3803.         ad -= 8;
  3804.         regs.fpcr = get_long (ad);
  3805.         set_host_fpu_control_word();
  3806.         D(bug("FMOVEM mem %X (%X) -> regs.fpcr\r\n", ad, regs.fpcr ));
  3807.         regs.fpsr = get_long (ad+4);
  3808.         from_fpsr();
  3809.         D(bug("FMOVEM mem %X (%X) -> regs.fpsr\r\n", ad+4, regs.fpsr ));
  3810.         m68k_areg (regs, opcode & 7) = ad;
  3811.         dump_fp_regs( "END  ");
  3812.     }
  3813. }
  3814.  
  3815. void REGPARAM2 fpuop_fmovem_Mem_2_fpcr_fpsr_fpiar_predecrement( uae_u32 opcode, uae_u16 extra )
  3816. {
  3817.     uae_u32 ad;
  3818.     if (get_fp_ad(opcode, &ad)) {
  3819.         ad -= 12;
  3820.         regs.fpcr = get_long (ad);
  3821.         set_host_fpu_control_word();
  3822.         D(bug("FMOVEM mem %X (%X) -> regs.fpcr\r\n", ad, regs.fpcr ));
  3823.         regs.fpsr = get_long (ad+4);
  3824.         from_fpsr();
  3825.         D(bug("FMOVEM mem %X (%X) -> regs.fpsr\r\n", ad+4, regs.fpsr ));
  3826.         regs.fpiar = get_long (ad+8);
  3827.         D(bug("FMOVEM mem %X (%X) -> regs.fpiar\r\n", ad+8, regs.fpiar ));
  3828.         m68k_areg (regs, opcode & 7) = ad;
  3829.         dump_fp_regs( "END  ");
  3830.     }
  3831. }
  3832.  
  3833.  
  3834. /* ---------------------------- CONTROL REGS -> MEMORY++ ---------------------------- */
  3835.  
  3836. void REGPARAM2 fpuop_fmovem_Mem_2_none_postincrement( uae_u32 opcode, uae_u16 extra )
  3837. {
  3838.     D(bug("FMOVEM Mem++ -> control(none)\r\n"));
  3839.     dump_fp_regs( "END  ");
  3840. }
  3841.  
  3842. void REGPARAM2 fpuop_fmovem_Mem_2_fpiar_postincrement( uae_u32 opcode, uae_u16 extra )
  3843. {
  3844.     uae_u32 ad;
  3845.     if (get_fp_ad(opcode, &ad)) {
  3846.         regs.fpiar = get_long (ad);
  3847.         D(bug("FMOVEM mem %X (%X) -> regs.fpiar\r\n", ad, regs.fpiar ));
  3848.         m68k_areg (regs, opcode & 7) = ad+4;
  3849.         dump_fp_regs( "END  ");
  3850.     }
  3851. }
  3852.  
  3853. void REGPARAM2 fpuop_fmovem_Mem_2_fpsr_postincrement( uae_u32 opcode, uae_u16 extra )
  3854. {
  3855.     uae_u32 ad;
  3856.     if (get_fp_ad(opcode, &ad)) {
  3857.         regs.fpsr = get_long (ad);
  3858.         from_fpsr();
  3859.         D(bug("FMOVEM mem %X (%X) -> regs.fpsr\r\n", ad, regs.fpsr ));
  3860.         m68k_areg (regs, opcode & 7) = ad+4;
  3861.         dump_fp_regs( "END  ");
  3862.     }
  3863. }
  3864.  
  3865. void REGPARAM2 fpuop_fmovem_Mem_2_fpsr_fpiar_postincrement( uae_u32 opcode, uae_u16 extra )
  3866. {
  3867.     uae_u32 ad;
  3868.     if (get_fp_ad(opcode, &ad)) {
  3869.         regs.fpsr = get_long (ad);
  3870.         from_fpsr();
  3871.         D(bug("FMOVEM mem %X (%X) -> regs.fpsr\r\n", ad, regs.fpsr ));
  3872.         regs.fpiar = get_long (ad+4);
  3873.         D(bug("FMOVEM mem %X (%X) -> regs.fpiar\r\n", ad+4, regs.fpiar ));
  3874.         m68k_areg (regs, opcode & 7) = ad+8;
  3875.         dump_fp_regs( "END  ");
  3876.     }
  3877. }
  3878.  
  3879. void REGPARAM2 fpuop_fmovem_Mem_2_fpcr_postincrement( uae_u32 opcode, uae_u16 extra )
  3880. {
  3881.     uae_u32 ad;
  3882.     if (get_fp_ad(opcode, &ad)) {
  3883.         regs.fpcr = get_long (ad);
  3884.         set_host_fpu_control_word();
  3885.         D(bug("FMOVEM mem %X (%X) -> regs.fpcr\r\n", ad, regs.fpcr ));
  3886.         m68k_areg (regs, opcode & 7) = ad+4;
  3887.         dump_fp_regs( "END  ");
  3888.     }
  3889. }
  3890.  
  3891. void REGPARAM2 fpuop_fmovem_Mem_2_fpcr_fpiar_postincrement( uae_u32 opcode, uae_u16 extra )
  3892. {
  3893.     uae_u32 ad;
  3894.     if (get_fp_ad(opcode, &ad)) {
  3895.         regs.fpcr = get_long (ad);
  3896.         set_host_fpu_control_word();
  3897.         D(bug("FMOVEM mem %X (%X) -> regs.fpcr\r\n", ad, regs.fpcr ));
  3898.         regs.fpiar = get_long (ad+4);
  3899.         D(bug("FMOVEM mem %X (%X) -> regs.fpiar\r\n", ad+4, regs.fpiar ));
  3900.         m68k_areg (regs, opcode & 7) = ad+8;
  3901.         dump_fp_regs( "END  ");
  3902.     }
  3903. }
  3904.  
  3905. void REGPARAM2 fpuop_fmovem_Mem_2_fpcr_fpsr_postincrement( uae_u32 opcode, uae_u16 extra )
  3906. {
  3907.     uae_u32 ad;
  3908.     if (get_fp_ad(opcode, &ad)) {
  3909.         regs.fpcr = get_long (ad);
  3910.         set_host_fpu_control_word();
  3911.         D(bug("FMOVEM mem %X (%X) -> regs.fpcr\r\n", ad, regs.fpcr ));
  3912.         regs.fpsr = get_long (ad+4);
  3913.         from_fpsr();
  3914.         D(bug("FMOVEM mem %X (%X) -> regs.fpsr\r\n", ad+4, regs.fpsr ));
  3915.         m68k_areg (regs, opcode & 7) = ad+8;
  3916.         dump_fp_regs( "END  ");
  3917.     }
  3918. }
  3919.  
  3920. void REGPARAM2 fpuop_fmovem_Mem_2_fpcr_fpsr_fpiar_postincrement( uae_u32 opcode, uae_u16 extra )
  3921. {
  3922.     uae_u32 ad;
  3923.     if (get_fp_ad(opcode, &ad)) {
  3924.         regs.fpcr = get_long (ad);
  3925.         set_host_fpu_control_word();
  3926.         D(bug("FMOVEM mem %X (%X) -> regs.fpcr\r\n", ad, regs.fpcr ));
  3927.         regs.fpsr = get_long (ad+4);
  3928.         from_fpsr();
  3929.         D(bug("FMOVEM mem %X (%X) -> regs.fpsr\r\n", ad+4, regs.fpsr ));
  3930.         regs.fpiar = get_long (ad+8);
  3931.         D(bug("FMOVEM mem %X (%X) -> regs.fpiar\r\n", ad+8, regs.fpiar ));
  3932.         m68k_areg (regs, opcode & 7) = ad+12;
  3933.         dump_fp_regs( "END  ");
  3934.     }
  3935. }
  3936.  
  3937.  
  3938. /* ----------------------------   MEMORY -> CONTROL REGS  ---------------------------- */
  3939. /* ----------------------------            and            ---------------------------- */
  3940. /* ---------------------------- IMMEDIATE -> CONTROL REGS ---------------------------- */
  3941.  
  3942. void REGPARAM2 fpuop_fmovem_Mem_2_none_2_Mem( uae_u32 opcode, uae_u16 extra )
  3943. {
  3944.     D(bug("FMOVEM Mem -> control(none)\r\n"));
  3945.     dump_fp_regs( "END  ");
  3946. }
  3947.  
  3948. void REGPARAM2 fpuop_fmovem_Mem_2_fpiar_2_Mem( uae_u32 opcode, uae_u16 extra )
  3949. {
  3950.     if ((opcode & 0x3f) == 0x3c) {
  3951.         regs.fpiar = next_ilong();
  3952.         D(bug("FMOVEM #<%X> -> regs.fpiar\r\n", regs.fpiar));
  3953.     } else {
  3954.         uae_u32 ad;
  3955.         if (get_fp_ad(opcode, &ad)) {
  3956.             regs.fpiar = get_long (ad);
  3957.             D(bug("FMOVEM mem %X (%X) -> regs.fpiar\r\n", ad, regs.fpiar ));
  3958.         }
  3959.     }
  3960.     dump_fp_regs( "END  ");
  3961. }
  3962.  
  3963. void REGPARAM2 fpuop_fmovem_Mem_2_fpsr_2_Mem( uae_u32 opcode, uae_u16 extra )
  3964. {
  3965.     if ((opcode & 0x3f) == 0x3c) {
  3966.         regs.fpsr = next_ilong();
  3967.         from_fpsr();
  3968.         D(bug("FMOVEM #<%X> -> regs.fpsr\r\n", regs.fpsr));
  3969.     } else {
  3970.         uae_u32 ad;
  3971.         if (get_fp_ad(opcode, &ad)) {
  3972.             regs.fpsr = get_long (ad);
  3973.             from_fpsr();
  3974.             D(bug("FMOVEM mem %X (%X) -> regs.fpsr\r\n", ad, regs.fpsr ));
  3975.         }
  3976.     }
  3977.     dump_fp_regs( "END  ");
  3978. }
  3979.  
  3980. void REGPARAM2 fpuop_fmovem_Mem_2_fpsr_fpiar_2_Mem( uae_u32 opcode, uae_u16 extra )
  3981. {
  3982.     if ((opcode & 0x3f) == 0x3c) {
  3983.         regs.fpsr = next_ilong();
  3984.         from_fpsr();
  3985.         D(bug("FMOVEM #<%X> -> regs.fpsr\r\n", regs.fpsr));
  3986.         regs.fpiar = next_ilong();
  3987.         D(bug("FMOVEM #<%X> -> regs.fpiar\r\n", regs.fpiar));
  3988.     } else {
  3989.         uae_u32 ad;
  3990.         if (get_fp_ad(opcode, &ad)) {
  3991.             regs.fpsr = get_long (ad);
  3992.             from_fpsr();
  3993.             D(bug("FMOVEM mem %X (%X) -> regs.fpsr\r\n", ad, regs.fpsr ));
  3994.             regs.fpiar = get_long (ad+4);
  3995.             D(bug("FMOVEM mem %X (%X) -> regs.fpiar\r\n", ad+4, regs.fpiar ));
  3996.         }
  3997.     }
  3998.     dump_fp_regs( "END  ");
  3999. }
  4000.  
  4001. void REGPARAM2 fpuop_fmovem_Mem_2_fpcr_2_Mem( uae_u32 opcode, uae_u16 extra )
  4002. {
  4003.     if ((opcode & 0x3f) == 0x3c) {
  4004.         regs.fpcr = next_ilong();
  4005.         set_host_fpu_control_word();
  4006.         D(bug("FMOVEM #<%X> -> regs.fpcr\r\n", regs.fpcr));
  4007.     } else {
  4008.         uae_u32 ad;
  4009.         if (get_fp_ad(opcode, &ad)) {
  4010.             regs.fpcr = get_long (ad);
  4011.             set_host_fpu_control_word();
  4012.             D(bug("FMOVEM mem %X (%X) -> regs.fpcr\r\n", ad, regs.fpcr ));
  4013.         }
  4014.     }
  4015.     dump_fp_regs( "END  ");
  4016. }
  4017.  
  4018. void REGPARAM2 fpuop_fmovem_Mem_2_fpcr_fpiar_2_Mem( uae_u32 opcode, uae_u16 extra )
  4019. {
  4020.     if ((opcode & 0x3f) == 0x3c) {
  4021.         regs.fpcr = next_ilong();
  4022.         set_host_fpu_control_word();
  4023.         D(bug("FMOVEM #<%X> -> regs.fpcr\r\n", regs.fpcr));
  4024.         regs.fpiar = next_ilong();
  4025.         D(bug("FMOVEM #<%X> -> regs.fpiar\r\n", regs.fpiar));
  4026.     } else {
  4027.         uae_u32 ad;
  4028.         if (get_fp_ad(opcode, &ad)) {
  4029.             regs.fpcr = get_long (ad);
  4030.             set_host_fpu_control_word();
  4031.             D(bug("FMOVEM mem %X (%X) -> regs.fpcr\r\n", ad, regs.fpcr ));
  4032.             regs.fpiar = get_long (ad+4);
  4033.             D(bug("FMOVEM mem %X (%X) -> regs.fpiar\r\n", ad+4, regs.fpiar ));
  4034.         }
  4035.     }
  4036.     dump_fp_regs( "END  ");
  4037. }
  4038.  
  4039. void REGPARAM2 fpuop_fmovem_Mem_2_fpcr_fpsr_2_Mem( uae_u32 opcode, uae_u16 extra )
  4040. {
  4041.     if ((opcode & 0x3f) == 0x3c) {
  4042.         regs.fpcr = next_ilong();
  4043.         set_host_fpu_control_word();
  4044.         D(bug("FMOVEM #<%X> -> regs.fpcr\r\n", regs.fpcr));
  4045.         regs.fpsr = next_ilong();
  4046.         from_fpsr();
  4047.         D(bug("FMOVEM #<%X> -> regs.fpsr\r\n", regs.fpsr));
  4048.     } else {
  4049.         uae_u32 ad;
  4050.         if (get_fp_ad(opcode, &ad)) {
  4051.             regs.fpcr = get_long (ad);
  4052.             set_host_fpu_control_word();
  4053.             D(bug("FMOVEM mem %X (%X) -> regs.fpcr\r\n", ad, regs.fpcr ));
  4054.             regs.fpsr = get_long (ad+4);
  4055.             from_fpsr();
  4056.             D(bug("FMOVEM mem %X (%X) -> regs.fpsr\r\n", ad+4, regs.fpsr ));
  4057.         }
  4058.     }
  4059.     dump_fp_regs( "END  ");
  4060. }
  4061.  
  4062. void REGPARAM2 fpuop_fmovem_Mem_2_fpcr_fpsr_fpiar_2_Mem( uae_u32 opcode, uae_u16 extra )
  4063. {
  4064.     if ((opcode & 0x3f) == 0x3c) {
  4065.         regs.fpcr = next_ilong();
  4066.         set_host_fpu_control_word();
  4067.         D(bug("FMOVEM #<%X> -> regs.fpcr\r\n", regs.fpcr));
  4068.         regs.fpsr = next_ilong();
  4069.         from_fpsr();
  4070.         D(bug("FMOVEM #<%X> -> regs.fpsr\r\n", regs.fpsr));
  4071.         regs.fpiar = next_ilong();
  4072.         D(bug("FMOVEM #<%X> -> regs.fpiar\r\n", regs.fpiar));
  4073.     } else {
  4074.         uae_u32 ad;
  4075.         if (get_fp_ad(opcode, &ad)) {
  4076.             regs.fpcr = get_long (ad);
  4077.             set_host_fpu_control_word();
  4078.             D(bug("FMOVEM mem %X (%X) -> regs.fpcr\r\n", ad, regs.fpcr ));
  4079.             regs.fpsr = get_long (ad+4);
  4080.             from_fpsr();
  4081.             D(bug("FMOVEM mem %X (%X) -> regs.fpsr\r\n", ad+4, regs.fpsr ));
  4082.             regs.fpiar = get_long (ad+8);
  4083.             D(bug("FMOVEM mem %X (%X) -> regs.fpiar\r\n", ad+8, regs.fpiar ));
  4084.         }
  4085.     }
  4086.     dump_fp_regs( "END  ");
  4087. }
  4088.  
  4089.  
  4090. /* ---------------------------- FMOVEM MEMORY -> FPP ---------------------------- */
  4091.  
  4092. void REGPARAM2 fpuop_fmovem_Mem_2_fpp_static_pred_postincrement( uae_u32 opcode, uae_u16 extra )
  4093. {
  4094.     uae_u32 ad, list = extra & 0xff;
  4095.     D(bug("FMOVEM memory->FPP\r\n"));
  4096.     if (get_fp_ad(opcode, &ad)) {
  4097.         for( int reg=7; reg>=0; reg-- ) {
  4098.             uae_u32 wrd1, wrd2, wrd3;
  4099.             if( list & 0x80 ) {
  4100.                 ad -= 4;
  4101.                 wrd3 = get_long (ad);
  4102.                 ad -= 4;
  4103.                 wrd2 = get_long (ad);
  4104.                 ad -= 4;
  4105.                 wrd1 = get_long (ad);
  4106.                 to_exten_no_normalize (wrd1, wrd2, wrd3,fp_reg[reg]);
  4107.             }
  4108.             list <<= 1;
  4109.         }
  4110.         m68k_areg (regs, opcode & 7) = ad;
  4111.         dump_fp_regs( "END  ");
  4112.     }
  4113. }
  4114.  
  4115. void REGPARAM2 fpuop_fmovem_Mem_2_fpp_static_pred_predecrement( uae_u32 opcode, uae_u16 extra )
  4116. {
  4117.     uae_u32 ad, list = extra & 0xff;
  4118.     D(bug("FMOVEM memory->FPP\r\n"));
  4119.     if (get_fp_ad(opcode, &ad)) {
  4120.         for( int reg=7; reg>=0; reg-- ) {
  4121.             uae_u32 wrd1, wrd2, wrd3;
  4122.             if( list & 0x80 ) {
  4123.                 ad -= 4;
  4124.                 wrd3 = get_long (ad);
  4125.                 ad -= 4;
  4126.                 wrd2 = get_long (ad);
  4127.                 ad -= 4;
  4128.                 wrd1 = get_long (ad);
  4129.                 to_exten_no_normalize (wrd1, wrd2, wrd3,fp_reg[reg]);
  4130.             }
  4131.             list <<= 1;
  4132.         }
  4133.         m68k_areg (regs, opcode & 7) = ad;
  4134.         dump_fp_regs( "END  ");
  4135.     }
  4136. }
  4137.  
  4138. void REGPARAM2 fpuop_fmovem_Mem_2_fpp_static_pred( uae_u32 opcode, uae_u16 extra )
  4139. {
  4140.     uae_u32 ad, list = extra & 0xff;
  4141.     D(bug("FMOVEM memory->FPP\r\n"));
  4142.     if (get_fp_ad(opcode, &ad)) {
  4143.         for( int reg=7; reg>=0; reg-- ) {
  4144.             uae_u32 wrd1, wrd2, wrd3;
  4145.             if( list & 0x80 ) {
  4146.                 ad -= 4;
  4147.                 wrd3 = get_long (ad);
  4148.                 ad -= 4;
  4149.                 wrd2 = get_long (ad);
  4150.                 ad -= 4;
  4151.                 wrd1 = get_long (ad);
  4152.                 to_exten_no_normalize (wrd1, wrd2, wrd3,fp_reg[reg]);
  4153.             }
  4154.             list <<= 1;
  4155.         }
  4156.         dump_fp_regs( "END  ");
  4157.     }
  4158. }
  4159.  
  4160. void REGPARAM2 fpuop_fmovem_Mem_2_fpp_dynamic_pred_postincrement( uae_u32 opcode, uae_u16 extra )
  4161. {
  4162.     uae_u32 ad, list = m68k_dreg (regs, (extra >> 4) & 3) & 0xff;
  4163.     D(bug("FMOVEM memory->FPP\r\n"));
  4164.     if (get_fp_ad(opcode, &ad)) {
  4165.         for( int reg=7; reg>=0; reg-- ) {
  4166.             uae_u32 wrd1, wrd2, wrd3;
  4167.             if( list & 0x80 ) {
  4168.                 ad -= 4;
  4169.                 wrd3 = get_long (ad);
  4170.                 ad -= 4;
  4171.                 wrd2 = get_long (ad);
  4172.                 ad -= 4;
  4173.                 wrd1 = get_long (ad);
  4174.                 to_exten_no_normalize (wrd1, wrd2, wrd3,fp_reg[reg]);
  4175.             }
  4176.             list <<= 1;
  4177.         }
  4178.         m68k_areg (regs, opcode & 7) = ad;
  4179.         dump_fp_regs( "END  ");
  4180.     }
  4181. }
  4182.  
  4183. void REGPARAM2 fpuop_fmovem_Mem_2_fpp_dynamic_pred_predecrement( uae_u32 opcode, uae_u16 extra )
  4184. {
  4185.     uae_u32 ad, list = m68k_dreg (regs, (extra >> 4) & 3) & 0xff;
  4186.     D(bug("FMOVEM memory->FPP\r\n"));
  4187.     if (get_fp_ad(opcode, &ad)) {
  4188.         for( int reg=7; reg>=0; reg-- ) {
  4189.             uae_u32 wrd1, wrd2, wrd3;
  4190.             if( list & 0x80 ) {
  4191.                 ad -= 4;
  4192.                 wrd3 = get_long (ad);
  4193.                 ad -= 4;
  4194.                 wrd2 = get_long (ad);
  4195.                 ad -= 4;
  4196.                 wrd1 = get_long (ad);
  4197.                 to_exten_no_normalize (wrd1, wrd2, wrd3,fp_reg[reg]);
  4198.             }
  4199.             list <<= 1;
  4200.         }
  4201.         m68k_areg (regs, opcode & 7) = ad;
  4202.         dump_fp_regs( "END  ");
  4203.     }
  4204. }
  4205.  
  4206. void REGPARAM2 fpuop_fmovem_Mem_2_fpp_dynamic_pred( uae_u32 opcode, uae_u16 extra )
  4207. {
  4208.     uae_u32 ad, list = m68k_dreg (regs, (extra >> 4) & 3) & 0xff;
  4209.     D(bug("FMOVEM memory->FPP\r\n"));
  4210.     if (get_fp_ad(opcode, &ad)) {
  4211.         for( int reg=7; reg>=0; reg-- ) {
  4212.             uae_u32 wrd1, wrd2, wrd3;
  4213.             if( list & 0x80 ) {
  4214.                 ad -= 4;
  4215.                 wrd3 = get_long (ad);
  4216.                 ad -= 4;
  4217.                 wrd2 = get_long (ad);
  4218.                 ad -= 4;
  4219.                 wrd1 = get_long (ad);
  4220.                 to_exten_no_normalize (wrd1, wrd2, wrd3,fp_reg[reg]);
  4221.             }
  4222.             list <<= 1;
  4223.         }
  4224.         dump_fp_regs( "END  ");
  4225.     }
  4226. }
  4227.  
  4228. void REGPARAM2 fpuop_fmovem_Mem_2_fpp_static_postinc_postincrement( uae_u32 opcode, uae_u16 extra )
  4229. {
  4230.     uae_u32 ad, list = extra & 0xff;
  4231.     D(bug("FMOVEM memory->FPP\r\n"));
  4232.     if (get_fp_ad(opcode, &ad)) {
  4233.         for( int reg=0; reg<8; reg++ ) {
  4234.             uae_u32 wrd1, wrd2, wrd3;
  4235.             if( list & 0x80 ) {
  4236.                 wrd1 = get_long (ad);
  4237.                 ad += 4;
  4238.                 wrd2 = get_long (ad);
  4239.                 ad += 4;
  4240.                 wrd3 = get_long (ad);
  4241.                 ad += 4;
  4242.                 to_exten_no_normalize (wrd1, wrd2, wrd3,fp_reg[reg]);
  4243.             }
  4244.             list <<= 1;
  4245.         }
  4246.         m68k_areg (regs, opcode & 7) = ad;
  4247.         dump_fp_regs( "END  ");
  4248.     }
  4249. }
  4250.  
  4251. void REGPARAM2 fpuop_fmovem_Mem_2_fpp_static_postinc_predecrement( uae_u32 opcode, uae_u16 extra )
  4252. {
  4253.     uae_u32 ad, list = extra & 0xff;
  4254.     D(bug("FMOVEM memory->FPP\r\n"));
  4255.     if (get_fp_ad(opcode, &ad)) {
  4256.         for( int reg=0; reg<8; reg++ ) {
  4257.             uae_u32 wrd1, wrd2, wrd3;
  4258.             if( list & 0x80 ) {
  4259.                 wrd1 = get_long (ad);
  4260.                 ad += 4;
  4261.                 wrd2 = get_long (ad);
  4262.                 ad += 4;
  4263.                 wrd3 = get_long (ad);
  4264.                 ad += 4;
  4265.                 to_exten_no_normalize (wrd1, wrd2, wrd3,fp_reg[reg]);
  4266.             }
  4267.             list <<= 1;
  4268.         }
  4269.         m68k_areg (regs, opcode & 7) = ad;
  4270.         dump_fp_regs( "END  ");
  4271.     }
  4272. }
  4273.  
  4274. void REGPARAM2 fpuop_fmovem_Mem_2_fpp_static_postinc( uae_u32 opcode, uae_u16 extra )
  4275. {
  4276.     uae_u32 ad, list = extra & 0xff;
  4277.     D(bug("FMOVEM memory->FPP\r\n"));
  4278.     if (get_fp_ad(opcode, &ad)) {
  4279.         for( int reg=0; reg<8; reg++ ) {
  4280.             uae_u32 wrd1, wrd2, wrd3;
  4281.             if( list & 0x80 ) {
  4282.                 wrd1 = get_long (ad);
  4283.                 ad += 4;
  4284.                 wrd2 = get_long (ad);
  4285.                 ad += 4;
  4286.                 wrd3 = get_long (ad);
  4287.                 ad += 4;
  4288.                 to_exten_no_normalize (wrd1, wrd2, wrd3,fp_reg[reg]);
  4289.             }
  4290.             list <<= 1;
  4291.         }
  4292.         dump_fp_regs( "END  ");
  4293.     }
  4294. }
  4295.  
  4296. void REGPARAM2 fpuop_fmovem_Mem_2_fpp_dynamic_postinc_postincrement( uae_u32 opcode, uae_u16 extra )
  4297. {
  4298.     uae_u32 ad, list = m68k_dreg (regs, (extra >> 4) & 3) & 0xff;
  4299.     D(bug("FMOVEM memory->FPP\r\n"));
  4300.     if (get_fp_ad(opcode, &ad)) {
  4301.         for( int reg=0; reg<8; reg++ ) {
  4302.             uae_u32 wrd1, wrd2, wrd3;
  4303.             if( list & 0x80 ) {
  4304.                 wrd1 = get_long (ad);
  4305.                 ad += 4;
  4306.                 wrd2 = get_long (ad);
  4307.                 ad += 4;
  4308.                 wrd3 = get_long (ad);
  4309.                 ad += 4;
  4310.                 to_exten_no_normalize (wrd1, wrd2, wrd3,fp_reg[reg]);
  4311.             }
  4312.             list <<= 1;
  4313.         }
  4314.         m68k_areg (regs, opcode & 7) = ad;
  4315.         dump_fp_regs( "END  ");
  4316.     }
  4317. }
  4318.  
  4319. void REGPARAM2 fpuop_fmovem_Mem_2_fpp_dynamic_postinc_predecrement( uae_u32 opcode, uae_u16 extra )
  4320. {
  4321.     uae_u32 ad, list = m68k_dreg (regs, (extra >> 4) & 3) & 0xff;
  4322.     D(bug("FMOVEM memory->FPP\r\n"));
  4323.     if (get_fp_ad(opcode, &ad)) {
  4324.         for( int reg=0; reg<8; reg++ ) {
  4325.             uae_u32 wrd1, wrd2, wrd3;
  4326.             if( list & 0x80 ) {
  4327.                 wrd1 = get_long (ad);
  4328.                 ad += 4;
  4329.                 wrd2 = get_long (ad);
  4330.                 ad += 4;
  4331.                 wrd3 = get_long (ad);
  4332.                 ad += 4;
  4333.                 to_exten_no_normalize (wrd1, wrd2, wrd3,fp_reg[reg]);
  4334.             }
  4335.             list <<= 1;
  4336.         }
  4337.         m68k_areg (regs, opcode & 7) = ad;
  4338.         dump_fp_regs( "END  ");
  4339.     }
  4340. }
  4341.  
  4342. void REGPARAM2 fpuop_fmovem_Mem_2_fpp_dynamic_postinc( uae_u32 opcode, uae_u16 extra )
  4343. {
  4344.     uae_u32 ad, list = m68k_dreg (regs, (extra >> 4) & 3) & 0xff;
  4345.     D(bug("FMOVEM memory->FPP\r\n"));
  4346.     if (get_fp_ad(opcode, &ad)) {
  4347.         for( int reg=0; reg<8; reg++ ) {
  4348.             uae_u32 wrd1, wrd2, wrd3;
  4349.             if( list & 0x80 ) {
  4350.                 wrd1 = get_long (ad);
  4351.                 ad += 4;
  4352.                 wrd2 = get_long (ad);
  4353.                 ad += 4;
  4354.                 wrd3 = get_long (ad);
  4355.                 ad += 4;
  4356.                 to_exten_no_normalize (wrd1, wrd2, wrd3,fp_reg[reg]);
  4357.             }
  4358.             list <<= 1;
  4359.         }
  4360.         dump_fp_regs( "END  ");
  4361.     }
  4362. }
  4363.  
  4364.  
  4365. /* ---------------------------- FPP -> FMOVEM MEMORY ---------------------------- */
  4366.  
  4367. void REGPARAM2 fpuop_fmovem_fpp_2_Mem_static_pred_postincrement( uae_u32 opcode, uae_u16 extra )
  4368. {
  4369.     uae_u32 ad, list = extra & 0xff;
  4370.     D(bug("FMOVEM FPP->memory\r\n"));
  4371.     if (get_fp_ad(opcode, &ad)) {
  4372.         for( int reg=7; reg>=0; reg-- ) {
  4373.             uae_u32 wrd1, wrd2, wrd3;
  4374.             if( list & 0x80 ) {
  4375.                 from_exten(fp_reg[reg],&wrd1, &wrd2, &wrd3);
  4376.                 ad -= 4;
  4377.                 put_long (ad, wrd3);
  4378.                 ad -= 4;
  4379.                 put_long (ad, wrd2);
  4380.                 ad -= 4;
  4381.                 put_long (ad, wrd1);
  4382.             }
  4383.             list <<= 1;
  4384.         }
  4385.         m68k_areg (regs, opcode & 7) = ad;
  4386.         dump_fp_regs( "END  ");
  4387.     }
  4388. }
  4389. void REGPARAM2 fpuop_fmovem_fpp_2_Mem_static_pred_predecrement( uae_u32 opcode, uae_u16 extra )
  4390. {
  4391.     uae_u32 ad, list = extra & 0xff;
  4392.     D(bug("FMOVEM FPP->memory\r\n"));
  4393.     if (get_fp_ad(opcode, &ad)) {
  4394.         for( int reg=7; reg>=0; reg-- ) {
  4395.             uae_u32 wrd1, wrd2, wrd3;
  4396.             if( list & 0x80 ) {
  4397.                 from_exten(fp_reg[reg],&wrd1, &wrd2, &wrd3);
  4398.                 ad -= 4;
  4399.                 put_long (ad, wrd3);
  4400.                 ad -= 4;
  4401.                 put_long (ad, wrd2);
  4402.                 ad -= 4;
  4403.                 put_long (ad, wrd1);
  4404.             }
  4405.             list <<= 1;
  4406.         }
  4407.         m68k_areg (regs, opcode & 7) = ad;
  4408.         dump_fp_regs( "END  ");
  4409.     }
  4410. }
  4411. void REGPARAM2 fpuop_fmovem_fpp_2_Mem_static_pred( uae_u32 opcode, uae_u16 extra )
  4412. {
  4413.     uae_u32 ad, list = extra & 0xff;
  4414.     D(bug("FMOVEM FPP->memory\r\n"));
  4415.     if (get_fp_ad(opcode, &ad)) {
  4416.         for( int reg=7; reg>=0; reg-- ) {
  4417.             uae_u32 wrd1, wrd2, wrd3;
  4418.             if( list & 0x80 ) {
  4419.                 from_exten(fp_reg[reg],&wrd1, &wrd2, &wrd3);
  4420.                 ad -= 4;
  4421.                 put_long (ad, wrd3);
  4422.                 ad -= 4;
  4423.                 put_long (ad, wrd2);
  4424.                 ad -= 4;
  4425.                 put_long (ad, wrd1);
  4426.             }
  4427.             list <<= 1;
  4428.         }
  4429.         dump_fp_regs( "END  ");
  4430.     }
  4431. }
  4432. void REGPARAM2 fpuop_fmovem_fpp_2_Mem_dynamic_pred_postincrement( uae_u32 opcode, uae_u16 extra )
  4433. {
  4434.     uae_u32 ad, list = m68k_dreg (regs, (extra >> 4) & 3) & 0xff;
  4435.     D(bug("FMOVEM FPP->memory\r\n"));
  4436.     if (get_fp_ad(opcode, &ad)) {
  4437.         for( int reg=7; reg>=0; reg-- ) {
  4438.             uae_u32 wrd1, wrd2, wrd3;
  4439.             if( list & 0x80 ) {
  4440.                 from_exten(fp_reg[reg],&wrd1, &wrd2, &wrd3);
  4441.                 ad -= 4;
  4442.                 put_long (ad, wrd3);
  4443.                 ad -= 4;
  4444.                 put_long (ad, wrd2);
  4445.                 ad -= 4;
  4446.                 put_long (ad, wrd1);
  4447.             }
  4448.             list <<= 1;
  4449.         }
  4450.         m68k_areg (regs, opcode & 7) = ad;
  4451.         dump_fp_regs( "END  ");
  4452.     }
  4453. }
  4454. void REGPARAM2 fpuop_fmovem_fpp_2_Mem_dynamic_pred_predecrement( uae_u32 opcode, uae_u16 extra )
  4455. {
  4456.     uae_u32 ad, list = m68k_dreg (regs, (extra >> 4) & 3) & 0xff;
  4457.     D(bug("FMOVEM FPP->memory\r\n"));
  4458.     if (get_fp_ad(opcode, &ad)) {
  4459.         for( int reg=7; reg>=0; reg-- ) {
  4460.             uae_u32 wrd1, wrd2, wrd3;
  4461.             if( list & 0x80 ) {
  4462.                 from_exten(fp_reg[reg],&wrd1, &wrd2, &wrd3);
  4463.                 ad -= 4;
  4464.                 put_long (ad, wrd3);
  4465.                 ad -= 4;
  4466.                 put_long (ad, wrd2);
  4467.                 ad -= 4;
  4468.                 put_long (ad, wrd1);
  4469.             }
  4470.             list <<= 1;
  4471.         }
  4472.         m68k_areg (regs, opcode & 7) = ad;
  4473.         dump_fp_regs( "END  ");
  4474.     }
  4475. }
  4476. void REGPARAM2 fpuop_fmovem_fpp_2_Mem_dynamic_pred( uae_u32 opcode, uae_u16 extra )
  4477. {
  4478.     uae_u32 ad, list = m68k_dreg (regs, (extra >> 4) & 3) & 0xff;
  4479.     D(bug("FMOVEM FPP->memory\r\n"));
  4480.     if (get_fp_ad(opcode, &ad)) {
  4481.         for( int reg=7; reg>=0; reg-- ) {
  4482.             uae_u32 wrd1, wrd2, wrd3;
  4483.             if( list & 0x80 ) {
  4484.                 from_exten(fp_reg[reg],&wrd1, &wrd2, &wrd3);
  4485.                 ad -= 4;
  4486.                 put_long (ad, wrd3);
  4487.                 ad -= 4;
  4488.                 put_long (ad, wrd2);
  4489.                 ad -= 4;
  4490.                 put_long (ad, wrd1);
  4491.             }
  4492.             list <<= 1;
  4493.         }
  4494.         dump_fp_regs( "END  ");
  4495.     }
  4496. }
  4497. void REGPARAM2 fpuop_fmovem_fpp_2_Mem_static_postinc_postincrement( uae_u32 opcode, uae_u16 extra )
  4498. {
  4499.     uae_u32 ad, list = extra & 0xff;
  4500.     D(bug("FMOVEM FPP->memory\r\n"));
  4501.     if (get_fp_ad(opcode, &ad)) {
  4502.         for( int reg=0; reg<8; reg++ ) {
  4503.             uae_u32 wrd1, wrd2, wrd3;
  4504.             if( list & 0x80 ) {
  4505.                 from_exten(fp_reg[reg],&wrd1, &wrd2, &wrd3);
  4506.                 put_long (ad, wrd1);
  4507.                 ad += 4;
  4508.                 put_long (ad, wrd2);
  4509.                 ad += 4;
  4510.                 put_long (ad, wrd3);
  4511.                 ad += 4;
  4512.             }
  4513.             list <<= 1;
  4514.         }
  4515.         m68k_areg (regs, opcode & 7) = ad;
  4516.         dump_fp_regs( "END  ");
  4517.     }
  4518. }
  4519. void REGPARAM2 fpuop_fmovem_fpp_2_Mem_static_postinc_predecrement( uae_u32 opcode, uae_u16 extra )
  4520. {
  4521.     uae_u32 ad, list = extra & 0xff;
  4522.     D(bug("FMOVEM FPP->memory\r\n"));
  4523.     if (get_fp_ad(opcode, &ad)) {
  4524.         for( int reg=0; reg<8; reg++ ) {
  4525.             uae_u32 wrd1, wrd2, wrd3;
  4526.             if( list & 0x80 ) {
  4527.                 from_exten(fp_reg[reg],&wrd1, &wrd2, &wrd3);
  4528.                 put_long (ad, wrd1);
  4529.                 ad += 4;
  4530.                 put_long (ad, wrd2);
  4531.                 ad += 4;
  4532.                 put_long (ad, wrd3);
  4533.                 ad += 4;
  4534.             }
  4535.             list <<= 1;
  4536.         }
  4537.         m68k_areg (regs, opcode & 7) = ad;
  4538.         dump_fp_regs( "END  ");
  4539.     }
  4540. }
  4541. void REGPARAM2 fpuop_fmovem_fpp_2_Mem_static_postinc( uae_u32 opcode, uae_u16 extra )
  4542. {
  4543.     uae_u32 ad, list = extra & 0xff;
  4544.     D(bug("FMOVEM FPP->memory\r\n"));
  4545.     if (get_fp_ad(opcode, &ad)) {
  4546.         for( int reg=0; reg<8; reg++ ) {
  4547.             uae_u32 wrd1, wrd2, wrd3;
  4548.             if( list & 0x80 ) {
  4549.                 from_exten(fp_reg[reg],&wrd1, &wrd2, &wrd3);
  4550.                 put_long (ad, wrd1);
  4551.                 ad += 4;
  4552.                 put_long (ad, wrd2);
  4553.                 ad += 4;
  4554.                 put_long (ad, wrd3);
  4555.                 ad += 4;
  4556.             }
  4557.             list <<= 1;
  4558.         }
  4559.         dump_fp_regs( "END  ");
  4560.     }
  4561. }
  4562. void REGPARAM2 fpuop_fmovem_fpp_2_Mem_dynamic_postinc_postincrement( uae_u32 opcode, uae_u16 extra )
  4563. {
  4564.     uae_u32 ad, list = m68k_dreg (regs, (extra >> 4) & 3) & 0xff;
  4565.     D(bug("FMOVEM FPP->memory\r\n"));
  4566.     if (get_fp_ad(opcode, &ad)) {
  4567.         for( int reg=0; reg<8; reg++ ) {
  4568.             uae_u32 wrd1, wrd2, wrd3;
  4569.             if( list & 0x80 ) {
  4570.                 from_exten(fp_reg[reg],&wrd1, &wrd2, &wrd3);
  4571.                 put_long (ad, wrd1);
  4572.                 ad += 4;
  4573.                 put_long (ad, wrd2);
  4574.                 ad += 4;
  4575.                 put_long (ad, wrd3);
  4576.                 ad += 4;
  4577.             }
  4578.             list <<= 1;
  4579.         }
  4580.         m68k_areg (regs, opcode & 7) = ad;
  4581.         dump_fp_regs( "END  ");
  4582.     }
  4583. }
  4584. void REGPARAM2 fpuop_fmovem_fpp_2_Mem_dynamic_postinc_predecrement( uae_u32 opcode, uae_u16 extra )
  4585. {
  4586.     uae_u32 ad, list = m68k_dreg (regs, (extra >> 4) & 3) & 0xff;
  4587.     D(bug("FMOVEM FPP->memory\r\n"));
  4588.     if (get_fp_ad(opcode, &ad)) {
  4589.         for( int reg=0; reg<8; reg++ ) {
  4590.             uae_u32 wrd1, wrd2, wrd3;
  4591.             if( list & 0x80 ) {
  4592.                 from_exten(fp_reg[reg],&wrd1, &wrd2, &wrd3);
  4593.                 put_long (ad, wrd1);
  4594.                 ad += 4;
  4595.                 put_long (ad, wrd2);
  4596.                 ad += 4;
  4597.                 put_long (ad, wrd3);
  4598.                 ad += 4;
  4599.             }
  4600.             list <<= 1;
  4601.         }
  4602.         m68k_areg (regs, opcode & 7) = ad;
  4603.         dump_fp_regs( "END  ");
  4604.     }
  4605. }
  4606. void REGPARAM2 fpuop_fmovem_fpp_2_Mem_dynamic_postinc( uae_u32 opcode, uae_u16 extra )
  4607. {
  4608.     uae_u32 ad, list = m68k_dreg (regs, (extra >> 4) & 3) & 0xff;
  4609.     D(bug("FMOVEM FPP->memory\r\n"));
  4610.     if (get_fp_ad(opcode, &ad)) {
  4611.         for( int reg=0; reg<8; reg++ ) {
  4612.             uae_u32 wrd1, wrd2, wrd3;
  4613.             if( list & 0x80 ) {
  4614.                 from_exten(fp_reg[reg],&wrd1, &wrd2, &wrd3);
  4615.                 put_long (ad, wrd1);
  4616.                 ad += 4;
  4617.                 put_long (ad, wrd2);
  4618.                 ad += 4;
  4619.                 put_long (ad, wrd3);
  4620.                 ad += 4;
  4621.             }
  4622.             list <<= 1;
  4623.         }
  4624.         dump_fp_regs( "END  ");
  4625.     }
  4626. }
  4627.  
  4628.  
  4629. /* ---------------------------- FMOVEM CONSTANT ROM -> FPP ---------------------------- */
  4630.  
  4631. void REGPARAM2 fpuop_do_fldpi( uae_u32 opcode, uae_u16 extra )
  4632. {
  4633.     D(bug("FMOVECR memory->FPP FP const: Pi\r\n"));
  4634.     memcpy( fp_reg[(extra>>7) & 7], const_pi, sizeof(float80_s) );
  4635.     sw = SW_FINITE | INEX2;
  4636.     dump_fp_regs( "END  ");
  4637. }
  4638.  
  4639. void REGPARAM2 fpuop_do_fldlg2( uae_u32 opcode, uae_u16 extra )
  4640. {
  4641.     D(bug("FMOVECR memory->FPP FP const: Log 10 (2)\r\n"));
  4642.     memcpy( fp_reg[(extra>>7) & 7], const_lg2, sizeof(float80_s) );
  4643.     sw = SW_FINITE | INEX2;
  4644.     dump_fp_regs( "END  ");
  4645. }
  4646.  
  4647. void REGPARAM2 fpuop_do_load_const_e( uae_u32 opcode, uae_u16 extra )
  4648. {
  4649.     D(bug("FMOVECR memory->FPP FP const: e\r\n"));
  4650.     memcpy( fp_reg[(extra>>7) & 7], const_e, sizeof(float80_s) );
  4651.     sw = SW_FINITE | INEX2;
  4652.     dump_fp_regs( "END  ");
  4653. }
  4654.  
  4655. void REGPARAM2 fpuop_do_fldl2e( uae_u32 opcode, uae_u16 extra )
  4656. {
  4657.     D(bug("FMOVECR memory->FPP FP const: Log 2 (e)\r\n"));
  4658.     memcpy( fp_reg[(extra>>7) & 7], const_l2e, sizeof(float80_s) );
  4659.     sw = SW_FINITE | INEX2;
  4660.     dump_fp_regs( "END  ");
  4661. }
  4662.  
  4663. void REGPARAM2 fpuop_do_load_const_log_10_e( uae_u32 opcode, uae_u16 extra )
  4664. {
  4665.     D(bug("FMOVECR memory->FPP FP const: Log 10 (e)\r\n"));
  4666.     memcpy( fp_reg[(extra>>7) & 7], const_log_10_e, sizeof(float80_s) );
  4667.     sw = SW_FINITE | INEX2;
  4668.     dump_fp_regs( "END  ");
  4669. }
  4670.  
  4671. void REGPARAM2 fpuop_do_fldz( uae_u32 opcode, uae_u16 extra )
  4672. {
  4673.     D(bug("FMOVECR memory->FPP FP const: zero\r\n"));
  4674.     memcpy( fp_reg[(extra>>7) & 7], const_z, sizeof(float80_s) );
  4675.     sw = SW_Z;
  4676.     dump_fp_regs( "END  ");
  4677. }
  4678.  
  4679. void REGPARAM2 fpuop_do_fldln2( uae_u32 opcode, uae_u16 extra )
  4680. {
  4681.     D(bug("FMOVECR memory->FPP FP const: ln(2)\r\n"));
  4682.     memcpy( fp_reg[(extra>>7) & 7], const_ln2, sizeof(float80_s) );
  4683.     sw = SW_FINITE | INEX2;
  4684.     dump_fp_regs( "END  ");
  4685. }
  4686.  
  4687. void REGPARAM2 fpuop_do_load_const_ln_10( uae_u32 opcode, uae_u16 extra )
  4688. {
  4689.     D(bug("FMOVECR memory->FPP FP const: ln(10)\r\n"));
  4690.     memcpy( fp_reg[(extra>>7) & 7], const_ln_10, sizeof(float80_s) );
  4691.     sw = SW_FINITE | INEX2;
  4692.     dump_fp_regs( "END  ");
  4693. }
  4694.  
  4695. void REGPARAM2 fpuop_do_fld1( uae_u32 opcode, uae_u16 extra )
  4696. {
  4697.     D(bug("FMOVECR memory->FPP FP const: 1.0e0\r\n"));
  4698.     memcpy( fp_reg[(extra>>7) & 7], const_1, sizeof(float80_s) );
  4699.     sw = SW_FINITE;
  4700.     dump_fp_regs( "END  ");
  4701. }
  4702.  
  4703. void REGPARAM2 fpuop_do_load_const_1e1( uae_u32 opcode, uae_u16 extra )
  4704. {
  4705.     D(bug("FMOVECR memory->FPP FP const: 1.0e1\r\n"));
  4706.     memcpy( fp_reg[(extra>>7) & 7], const_1e1, sizeof(float80_s) );
  4707.     sw = SW_FINITE;
  4708.     dump_fp_regs( "END  ");
  4709. }
  4710.  
  4711. void REGPARAM2 fpuop_do_load_const_1e2( uae_u32 opcode, uae_u16 extra )
  4712. {
  4713.     D(bug("FMOVECR memory->FPP FP const: 1.0e2\r\n"));
  4714.     memcpy( fp_reg[(extra>>7) & 7], const_1e2, sizeof(float80_s) );
  4715.     sw = SW_FINITE;
  4716.     dump_fp_regs( "END  ");
  4717. }
  4718.  
  4719. void REGPARAM2 fpuop_do_load_const_1e4( uae_u32 opcode, uae_u16 extra )
  4720. {
  4721.     D(bug("FMOVECR memory->FPP FP const: 1.0e4\r\n"));
  4722.     memcpy( fp_reg[(extra>>7) & 7], const_1e4, sizeof(float80_s) );
  4723.     sw = SW_FINITE;
  4724.     dump_fp_regs( "END  ");
  4725. }
  4726.  
  4727. void REGPARAM2 fpuop_do_load_const_1e8( uae_u32 opcode, uae_u16 extra )
  4728. {
  4729.     D(bug("FMOVECR memory->FPP FP const: 1.0e8\r\n"));
  4730.     memcpy( fp_reg[(extra>>7) & 7], const_1e8, sizeof(float80_s) );
  4731.     sw = SW_FINITE | INEX2; // Is it really INEX2?
  4732.     dump_fp_regs( "END  ");
  4733. }
  4734.  
  4735. void REGPARAM2 fpuop_do_load_const_1e16( uae_u32 opcode, uae_u16 extra )
  4736. {
  4737.     D(bug("FMOVECR memory->FPP FP const: 1.0e16\r\n"));
  4738.     memcpy( fp_reg[(extra>>7) & 7], const_1e16, sizeof(float80_s) );
  4739.     sw = SW_FINITE | INEX2;
  4740.     dump_fp_regs( "END  ");
  4741. }
  4742.  
  4743. void REGPARAM2 fpuop_do_load_const_1e32( uae_u32 opcode, uae_u16 extra )
  4744. {
  4745.     D(bug("FMOVECR memory->FPP FP const: 1.0e32\r\n"));
  4746.     memcpy( fp_reg[(extra>>7) & 7], const_1e32, sizeof(float80_s) );
  4747.     sw = SW_FINITE | INEX2;
  4748.     dump_fp_regs( "END  ");
  4749. }
  4750.  
  4751. void REGPARAM2 fpuop_do_load_const_1e64( uae_u32 opcode, uae_u16 extra )
  4752. {
  4753.     D(bug("FMOVECR memory->FPP FP const: 1.0e64\r\n"));
  4754.     memcpy( fp_reg[(extra>>7) & 7], const_1e64, sizeof(float80_s) );
  4755.     sw = SW_FINITE | INEX2;
  4756.     dump_fp_regs( "END  ");
  4757. }
  4758.  
  4759. void REGPARAM2 fpuop_do_load_const_1e128( uae_u32 opcode, uae_u16 extra )
  4760. {
  4761.     D(bug("FMOVECR memory->FPP FP const: 1.0e128\r\n"));
  4762.     memcpy( fp_reg[(extra>>7) & 7], const_1e128, sizeof(float80_s) );
  4763.     sw = SW_FINITE | INEX2;
  4764.     dump_fp_regs( "END  ");
  4765. }
  4766.  
  4767. void REGPARAM2 fpuop_do_load_const_1e256( uae_u32 opcode, uae_u16 extra )
  4768. {
  4769.     D(bug("FMOVECR memory->FPP FP const: 1.0e256\r\n"));
  4770.     memcpy( fp_reg[(extra>>7) & 7], const_1e256, sizeof(float80_s) );
  4771.     sw = SW_FINITE | INEX2;
  4772.     dump_fp_regs( "END  ");
  4773. }
  4774.  
  4775. void REGPARAM2 fpuop_do_load_const_1e512( uae_u32 opcode, uae_u16 extra )
  4776. {
  4777.     D(bug("FMOVECR memory->FPP FP const: 1.0e512\r\n"));
  4778.     memcpy( fp_reg[(extra>>7) & 7], const_1e512, sizeof(float80_s) );
  4779.     sw = SW_FINITE | INEX2;
  4780.     dump_fp_regs( "END  ");
  4781. }
  4782.  
  4783. void REGPARAM2 fpuop_do_load_const_1e1024( uae_u32 opcode, uae_u16 extra )
  4784. {
  4785.     D(bug("FMOVECR memory->FPP FP const: 1.0e1024\r\n"));
  4786.     memcpy( fp_reg[(extra>>7) & 7], const_1e1024, sizeof(float80_s) );
  4787.     sw = SW_FINITE | INEX2;
  4788.     dump_fp_regs( "END  ");
  4789. }
  4790.  
  4791. void REGPARAM2 fpuop_do_load_const_1e2048( uae_u32 opcode, uae_u16 extra )
  4792. {
  4793.     D(bug("FMOVECR memory->FPP FP const: 1.0e2048\r\n"));
  4794.     memcpy( fp_reg[(extra>>7) & 7], const_1e2048, sizeof(float80_s) );
  4795.     sw = SW_FINITE | INEX2;
  4796.     dump_fp_regs( "END  ");
  4797. }
  4798.  
  4799. void REGPARAM2 fpuop_do_load_const_1e4096( uae_u32 opcode, uae_u16 extra )
  4800. {
  4801.     D(bug("FMOVECR memory->FPP FP const: 1.0e4096\r\n"));
  4802.     memcpy( fp_reg[(extra>>7) & 7], const_1e4096, sizeof(float80_s) );
  4803.     sw = SW_FINITE | INEX2;
  4804.     dump_fp_regs( "END  ");
  4805. }
  4806.  
  4807.  
  4808. /* ---------------------------- ALU ---------------------------- */
  4809.  
  4810. void REGPARAM2 fpuop_do_fmove( uae_u32 opcode, uae_u16 extra )
  4811. {
  4812.     int reg = (extra >> 7) & 7;
  4813.   float80_s src;
  4814.     if (get_fp_value (opcode, extra, src) == 0) {
  4815.         m68k_setpc (m68k_getpc () - 4);
  4816.         op_illg (opcode);
  4817.         dump_fp_regs( "END  ");
  4818.         return;
  4819.     }
  4820.     D(bug("FMOVE %s\r\n",etos(src)));
  4821.     do_fmove( fp_reg[reg], src );
  4822.     build_ex_status();
  4823.     dump_fp_regs( "END  ");
  4824. }
  4825.  
  4826. void REGPARAM2 fpuop_do_fint( uae_u32 opcode, uae_u16 extra )
  4827. {
  4828.     int reg = (extra >> 7) & 7;
  4829.   float80_s src;
  4830.     if (get_fp_value (opcode, extra, src) == 0) {
  4831.         m68k_setpc (m68k_getpc () - 4);
  4832.         op_illg (opcode);
  4833.         dump_fp_regs( "END  ");
  4834.         return;
  4835.     }
  4836.     D(bug("FINT %s, opcode=%X, extra=%X, ta %X\r\n",etos(src),opcode,extra,m68k_getpc()));
  4837.     do_fint( fp_reg[reg], src );
  4838.     dump_fp_regs( "END  ");
  4839. }
  4840.  
  4841. void REGPARAM2 fpuop_do_fsinh( uae_u32 opcode, uae_u16 extra )
  4842. {
  4843.     int reg = (extra >> 7) & 7;
  4844.   float80_s src;
  4845.     if (get_fp_value (opcode, extra, src) == 0) {
  4846.         m68k_setpc (m68k_getpc () - 4);
  4847.         op_illg (opcode);
  4848.         dump_fp_regs( "END  ");
  4849.         return;
  4850.     }
  4851.     D(bug("FSINH %s\r\n",etos(src)));
  4852.     do_fsinh( fp_reg[reg], src );
  4853.     build_ex_status();
  4854.     dump_fp_regs( "END  ");
  4855. }
  4856.  
  4857. void REGPARAM2 fpuop_do_fintrz( uae_u32 opcode, uae_u16 extra )
  4858. {
  4859.     int reg = (extra >> 7) & 7;
  4860.   float80_s src;
  4861.     if (get_fp_value (opcode, extra, src) == 0) {
  4862.         m68k_setpc (m68k_getpc () - 4);
  4863.         op_illg (opcode);
  4864.         dump_fp_regs( "END  ");
  4865.         return;
  4866.     }
  4867.     D(bug("FINTRZ %s\r\n",etos(src)));
  4868.     do_fintrz( fp_reg[reg], src );
  4869.     dump_fp_regs( "END  ");
  4870. }
  4871.  
  4872. void REGPARAM2 fpuop_do_fsqrt( uae_u32 opcode, uae_u16 extra )
  4873. {
  4874.     int reg = (extra >> 7) & 7;
  4875.   float80_s src;
  4876.     if (get_fp_value (opcode, extra, src) == 0) {
  4877.         m68k_setpc (m68k_getpc () - 4);
  4878.         op_illg (opcode);
  4879.         dump_fp_regs( "END  ");
  4880.         return;
  4881.     }
  4882.     D(bug("FSQRT %s\r\n",etos(src)));
  4883.     do_fsqrt( fp_reg[reg], src );
  4884.     dump_fp_regs( "END  ");
  4885. }
  4886.  
  4887. void REGPARAM2 fpuop_do_flognp1( uae_u32 opcode, uae_u16 extra )
  4888. {
  4889.     int reg = (extra >> 7) & 7;
  4890.   float80_s src;
  4891.     if (get_fp_value (opcode, extra, src) == 0) {
  4892.         m68k_setpc (m68k_getpc () - 4);
  4893.         op_illg (opcode);
  4894.         dump_fp_regs( "END  ");
  4895.         return;
  4896.     }
  4897.     D(bug("FLOGNP1 %s\r\n",etos(src)));
  4898.     do_flognp1( fp_reg[reg], src );
  4899.     build_ex_status();
  4900.     dump_fp_regs( "END  ");
  4901. }
  4902.  
  4903. void REGPARAM2 fpuop_do_fetoxm1( uae_u32 opcode, uae_u16 extra )
  4904. {
  4905.     int reg = (extra >> 7) & 7;
  4906.   float80_s src;
  4907.     if (get_fp_value (opcode, extra, src) == 0) {
  4908.         m68k_setpc (m68k_getpc () - 4);
  4909.         op_illg (opcode);
  4910.         dump_fp_regs( "END  ");
  4911.         return;
  4912.     }
  4913.     D(bug("FETOXM1 %s\r\n",etos(src)));
  4914.     do_fetoxm1( fp_reg[reg], src );
  4915.     build_ex_status();
  4916.     dump_fp_regs( "END  ");
  4917. }
  4918.  
  4919. void REGPARAM2 fpuop_do_ftanh( uae_u32 opcode, uae_u16 extra )
  4920. {
  4921.     int reg = (extra >> 7) & 7;
  4922.   float80_s src;
  4923.     if (get_fp_value (opcode, extra, src) == 0) {
  4924.         m68k_setpc (m68k_getpc () - 4);
  4925.         op_illg (opcode);
  4926.         dump_fp_regs( "END  ");
  4927.         return;
  4928.     }
  4929.     D(bug("FTANH %s\r\n",etos(src)));
  4930.     do_ftanh( fp_reg[reg], src );
  4931.     build_ex_status();
  4932.     dump_fp_regs( "END  ");
  4933. }
  4934.  
  4935. void REGPARAM2 fpuop_do_fatan( uae_u32 opcode, uae_u16 extra )
  4936. {
  4937.     int reg = (extra >> 7) & 7;
  4938.   float80_s src;
  4939.     if (get_fp_value (opcode, extra, src) == 0) {
  4940.         m68k_setpc (m68k_getpc () - 4);
  4941.         op_illg (opcode);
  4942.         dump_fp_regs( "END  ");
  4943.         return;
  4944.     }
  4945.     D(bug("FATAN %s\r\n",etos(src)));
  4946.     do_fatan( fp_reg[reg], src );
  4947.     build_ex_status();
  4948.     dump_fp_regs( "END  ");
  4949. }
  4950.  
  4951. void REGPARAM2 fpuop_do_fasin( uae_u32 opcode, uae_u16 extra )
  4952. {
  4953.     int reg = (extra >> 7) & 7;
  4954.   float80_s src;
  4955.     if (get_fp_value (opcode, extra, src) == 0) {
  4956.         m68k_setpc (m68k_getpc () - 4);
  4957.         op_illg (opcode);
  4958.         dump_fp_regs( "END  ");
  4959.         return;
  4960.     }
  4961.     D(bug("FASIN %s\r\n",etos(src)));
  4962.     do_fasin( fp_reg[reg], src );
  4963.     build_ex_status();
  4964.     dump_fp_regs( "END  ");
  4965. }
  4966.  
  4967. void REGPARAM2 fpuop_do_fatanh( uae_u32 opcode, uae_u16 extra )
  4968. {
  4969.     int reg = (extra >> 7) & 7;
  4970.   float80_s src;
  4971.     if (get_fp_value (opcode, extra, src) == 0) {
  4972.         m68k_setpc (m68k_getpc () - 4);
  4973.         op_illg (opcode);
  4974.         dump_fp_regs( "END  ");
  4975.         return;
  4976.     }
  4977.     D(bug("FATANH %s\r\n",etos(src)));
  4978.     do_fatanh( fp_reg[reg], src );
  4979.     build_ex_status();
  4980.     dump_fp_regs( "END  ");
  4981. }
  4982.  
  4983. void REGPARAM2 fpuop_do_fsin( uae_u32 opcode, uae_u16 extra )
  4984. {
  4985.     int reg = (extra >> 7) & 7;
  4986.   float80_s src;
  4987.     if (get_fp_value (opcode, extra, src) == 0) {
  4988.         m68k_setpc (m68k_getpc () - 4);
  4989.         op_illg (opcode);
  4990.         dump_fp_regs( "END  ");
  4991.         return;
  4992.     }
  4993.     D(bug("FSIN %s\r\n",etos(src)));
  4994.     do_fsin( fp_reg[reg], src );
  4995.     dump_fp_regs( "END  ");
  4996. }
  4997.  
  4998. void REGPARAM2 fpuop_do_ftan( uae_u32 opcode, uae_u16 extra )
  4999. {
  5000.     int reg = (extra >> 7) & 7;
  5001.   float80_s src;
  5002.     if (get_fp_value (opcode, extra, src) == 0) {
  5003.         m68k_setpc (m68k_getpc () - 4);
  5004.         op_illg (opcode);
  5005.         dump_fp_regs( "END  ");
  5006.         return;
  5007.     }
  5008.     D(bug("FTAN %s\r\n",etos(src)));
  5009.     do_ftan( fp_reg[reg], src );
  5010.     dump_fp_regs( "END  ");
  5011. }
  5012.  
  5013. void REGPARAM2 fpuop_do_fetox( uae_u32 opcode, uae_u16 extra )
  5014. {
  5015.     int reg = (extra >> 7) & 7;
  5016.   float80_s src;
  5017.     if (get_fp_value (opcode, extra, src) == 0) {
  5018.         m68k_setpc (m68k_getpc () - 4);
  5019.         op_illg (opcode);
  5020.         dump_fp_regs( "END  ");
  5021.         return;
  5022.     }
  5023.     D(bug("FETOX %s\r\n",etos(src)));
  5024.     do_fetox( fp_reg[reg], src );
  5025.     build_ex_status();
  5026.     dump_fp_regs( "END  ");
  5027. }
  5028.  
  5029. void REGPARAM2 fpuop_do_ftwotox( uae_u32 opcode, uae_u16 extra )
  5030. {
  5031.     int reg = (extra >> 7) & 7;
  5032.   float80_s src;
  5033.     if (get_fp_value (opcode, extra, src) == 0) {
  5034.         m68k_setpc (m68k_getpc () - 4);
  5035.         op_illg (opcode);
  5036.         dump_fp_regs( "END  ");
  5037.         return;
  5038.     }
  5039.     D(bug("FTWOTOX %s\r\n",etos(src)));
  5040.     do_ftwotox( fp_reg[reg], src );
  5041.     build_ex_status();
  5042.     dump_fp_regs( "END  ");
  5043. }
  5044.  
  5045. void REGPARAM2 fpuop_do_ftentox( uae_u32 opcode, uae_u16 extra )
  5046. {
  5047.     int reg = (extra >> 7) & 7;
  5048.   float80_s src;
  5049.     if (get_fp_value (opcode, extra, src) == 0) {
  5050.         m68k_setpc (m68k_getpc () - 4);
  5051.         op_illg (opcode);
  5052.         dump_fp_regs( "END  ");
  5053.         return;
  5054.     }
  5055.     D(bug("FTENTOX %s\r\n",etos(src)));
  5056.     do_ftentox( fp_reg[reg], src );
  5057.     build_ex_status();
  5058.     dump_fp_regs( "END  ");
  5059. }
  5060.  
  5061. void REGPARAM2 fpuop_do_flogn( uae_u32 opcode, uae_u16 extra )
  5062. {
  5063.     int reg = (extra >> 7) & 7;
  5064.   float80_s src;
  5065.     if (get_fp_value (opcode, extra, src) == 0) {
  5066.         m68k_setpc (m68k_getpc () - 4);
  5067.         op_illg (opcode);
  5068.         dump_fp_regs( "END  ");
  5069.         return;
  5070.     }
  5071.     D(bug("FLOGN %s\r\n",etos(src)));
  5072.     do_flogn( fp_reg[reg], src );
  5073.     build_ex_status();
  5074.     dump_fp_regs( "END  ");
  5075. }
  5076.  
  5077. void REGPARAM2 fpuop_do_flog10( uae_u32 opcode, uae_u16 extra )
  5078. {
  5079.     int reg = (extra >> 7) & 7;
  5080.   float80_s src;
  5081.     if (get_fp_value (opcode, extra, src) == 0) {
  5082.         m68k_setpc (m68k_getpc () - 4);
  5083.         op_illg (opcode);
  5084.         dump_fp_regs( "END  ");
  5085.         return;
  5086.     }
  5087.     D(bug("FLOG10 %s\r\n",etos(src)));
  5088.     do_flog10( fp_reg[reg], src );
  5089.     build_ex_status();
  5090.     dump_fp_regs( "END  ");
  5091. }
  5092.  
  5093. void REGPARAM2 fpuop_do_flog2( uae_u32 opcode, uae_u16 extra )
  5094. {
  5095.     int reg = (extra >> 7) & 7;
  5096.   float80_s src;
  5097.     if (get_fp_value (opcode, extra, src) == 0) {
  5098.         m68k_setpc (m68k_getpc () - 4);
  5099.         op_illg (opcode);
  5100.         dump_fp_regs( "END  ");
  5101.         return;
  5102.     }
  5103.     D(bug("FLOG2 %s\r\n",etos(src)));
  5104.     do_flog2( fp_reg[reg], src );
  5105.     build_ex_status();
  5106.     dump_fp_regs( "END  ");
  5107. }
  5108.  
  5109. void REGPARAM2 fpuop_do_fabs( uae_u32 opcode, uae_u16 extra )
  5110. {
  5111.     int reg = (extra >> 7) & 7;
  5112.   float80_s src;
  5113.     if (get_fp_value (opcode, extra, src) == 0) {
  5114.         m68k_setpc (m68k_getpc () - 4);
  5115.         op_illg (opcode);
  5116.         dump_fp_regs( "END  ");
  5117.         return;
  5118.     }
  5119.     D(bug("FABS %s\r\n",etos(src)));
  5120.     do_fabs( fp_reg[reg], src );
  5121.     dump_fp_regs( "END  ");
  5122. }
  5123.  
  5124. void REGPARAM2 fpuop_do_fcosh( uae_u32 opcode, uae_u16 extra )
  5125. {
  5126.     int reg = (extra >> 7) & 7;
  5127.   float80_s src;
  5128.     if (get_fp_value (opcode, extra, src) == 0) {
  5129.         m68k_setpc (m68k_getpc () - 4);
  5130.         op_illg (opcode);
  5131.         dump_fp_regs( "END  ");
  5132.         return;
  5133.     }
  5134.     D(bug("FCOSH %s\r\n",etos(src)));
  5135.     do_fcosh( fp_reg[reg], src );
  5136.     build_ex_status();
  5137.     dump_fp_regs( "END  ");
  5138. }
  5139.  
  5140. void REGPARAM2 fpuop_do_fneg( uae_u32 opcode, uae_u16 extra )
  5141. {
  5142.     int reg = (extra >> 7) & 7;
  5143.   float80_s src;
  5144.     if (get_fp_value (opcode, extra, src) == 0) {
  5145.         m68k_setpc (m68k_getpc () - 4);
  5146.         op_illg (opcode);
  5147.         dump_fp_regs( "END  ");
  5148.         return;
  5149.     }
  5150.     D(bug("FNEG %s\r\n",etos(src)));
  5151.     do_fneg( fp_reg[reg], src );
  5152.     dump_fp_regs( "END  ");
  5153. }
  5154.  
  5155. void REGPARAM2 fpuop_do_facos( uae_u32 opcode, uae_u16 extra )
  5156. {
  5157.     int reg = (extra >> 7) & 7;
  5158.   float80_s src;
  5159.     if (get_fp_value (opcode, extra, src) == 0) {
  5160.         m68k_setpc (m68k_getpc () - 4);
  5161.         op_illg (opcode);
  5162.         dump_fp_regs( "END  ");
  5163.         return;
  5164.     }
  5165.     D(bug("FACOS %s\r\n",etos(src)));
  5166.     do_facos( fp_reg[reg], src );
  5167.     build_ex_status();
  5168.     dump_fp_regs( "END  ");
  5169. }
  5170.  
  5171. void REGPARAM2 fpuop_do_fcos( uae_u32 opcode, uae_u16 extra )
  5172. {
  5173.     int reg = (extra >> 7) & 7;
  5174.   float80_s src;
  5175.     if (get_fp_value (opcode, extra, src) == 0) {
  5176.         m68k_setpc (m68k_getpc () - 4);
  5177.         op_illg (opcode);
  5178.         dump_fp_regs( "END  ");
  5179.         return;
  5180.     }
  5181.     D(bug("FCOS %s\r\n",etos(src)));
  5182.     do_fcos( fp_reg[reg], src );
  5183.     dump_fp_regs( "END  ");
  5184. }
  5185.  
  5186. void REGPARAM2 fpuop_do_fgetexp( uae_u32 opcode, uae_u16 extra )
  5187. {
  5188.     int reg = (extra >> 7) & 7;
  5189.   float80_s src;
  5190.     if (get_fp_value (opcode, extra, src) == 0) {
  5191.         m68k_setpc (m68k_getpc () - 4);
  5192.         op_illg (opcode);
  5193.         dump_fp_regs( "END  ");
  5194.         return;
  5195.     }
  5196.     D(bug("FGETEXP %s\r\n",etos(src)));
  5197.  
  5198.     if( IS_INFINITY(src) ) {
  5199.         MAKE_NAN( fp_reg[reg] );
  5200.         do_ftst( fp_reg[reg] );
  5201.         sw |= SW_IE;
  5202.     } else {
  5203.         do_fgetexp( fp_reg[reg], src );
  5204.     }
  5205.     dump_fp_regs( "END  ");
  5206. }
  5207.  
  5208. void REGPARAM2 fpuop_do_fgetman( uae_u32 opcode, uae_u16 extra )
  5209. {
  5210.     int reg = (extra >> 7) & 7;
  5211.   float80_s src;
  5212.     if (get_fp_value (opcode, extra, src) == 0) {
  5213.         m68k_setpc (m68k_getpc () - 4);
  5214.         op_illg (opcode);
  5215.         dump_fp_regs( "END  ");
  5216.         return;
  5217.     }
  5218.     D(bug("FGETMAN %s\r\n",etos(src)));
  5219.     if( IS_INFINITY(src) ) {
  5220.         MAKE_NAN( fp_reg[reg] );
  5221.         do_ftst( fp_reg[reg] );
  5222.         sw |= SW_IE;
  5223.     } else {
  5224.         do_fgetman( fp_reg[reg], src );
  5225.     }
  5226.     dump_fp_regs( "END  ");
  5227. }
  5228.  
  5229. void REGPARAM2 fpuop_do_fdiv( uae_u32 opcode, uae_u16 extra )
  5230. {
  5231.     int reg = (extra >> 7) & 7;
  5232.   float80_s src;
  5233.     if (get_fp_value (opcode, extra, src) == 0) {
  5234.         m68k_setpc (m68k_getpc () - 4);
  5235.         op_illg (opcode);
  5236.         dump_fp_regs( "END  ");
  5237.         return;
  5238.     }
  5239.     D(bug("FDIV %s\r\n",etos(src)));
  5240.     do_fdiv( fp_reg[reg], src );
  5241.     dump_fp_regs( "END  ");
  5242. }
  5243.  
  5244. void REGPARAM2 fpuop_do_fmod( uae_u32 opcode, uae_u16 extra )
  5245. {
  5246.     int reg = (extra >> 7) & 7;
  5247.   float80_s src;
  5248.     if (get_fp_value (opcode, extra, src) == 0) {
  5249.         m68k_setpc (m68k_getpc () - 4);
  5250.         op_illg (opcode);
  5251.         dump_fp_regs( "END  ");
  5252.         return;
  5253.     }
  5254.     D(bug("FMOD %s\r\n",etos(src)));
  5255.  
  5256. #if USE_3_BIT_QUOTIENT
  5257.     do_fmod( fp_reg[reg], src );
  5258. #else
  5259.     if( (cw & X86_ROUND_CONTROL_MASK) == CW_RC_ZERO ) {
  5260.         do_fmod_dont_set_cw( fp_reg[reg], src );
  5261.     } else {
  5262.         do_fmod( fp_reg[reg], src );
  5263.     }
  5264. #endif
  5265.     dump_fp_regs( "END  ");
  5266. }
  5267.  
  5268. void REGPARAM2 fpuop_do_frem( uae_u32 opcode, uae_u16 extra )
  5269. {
  5270.     int reg = (extra >> 7) & 7;
  5271.   float80_s src;
  5272.     if (get_fp_value (opcode, extra, src) == 0) {
  5273.         m68k_setpc (m68k_getpc () - 4);
  5274.         op_illg (opcode);
  5275.         dump_fp_regs( "END  ");
  5276.         return;
  5277.     }
  5278.     D(bug("FREM %s\r\n",etos(src)));
  5279. #if USE_3_BIT_QUOTIENT
  5280.     do_frem( fp_reg[reg], src );
  5281. #else
  5282.     if( (cw & X86_ROUND_CONTROL_MASK) == CW_RC_NEAR ) {
  5283.         do_frem_dont_set_cw( fp_reg[reg], src );
  5284.     } else {
  5285.         do_frem( fp_reg[reg], src );
  5286.     }
  5287. #endif
  5288.     dump_fp_regs( "END  ");
  5289. }
  5290.  
  5291. void REGPARAM2 fpuop_do_fadd( uae_u32 opcode, uae_u16 extra )
  5292. {
  5293.     int reg = (extra >> 7) & 7;
  5294.   float80_s src;
  5295.     if (get_fp_value (opcode, extra, src) == 0) {
  5296.         m68k_setpc (m68k_getpc () - 4);
  5297.         op_illg (opcode);
  5298.         dump_fp_regs( "END  ");
  5299.         return;
  5300.     }
  5301.     D(bug("FADD %s\r\n",etos(src)));
  5302.     do_fadd( fp_reg[reg], src );
  5303.     dump_fp_regs( "END  ");
  5304. }
  5305.  
  5306. void REGPARAM2 fpuop_do_fmul( uae_u32 opcode, uae_u16 extra )
  5307. {
  5308.     int reg = (extra >> 7) & 7;
  5309.   float80_s src;
  5310.     if (get_fp_value (opcode, extra, src) == 0) {
  5311.         m68k_setpc (m68k_getpc () - 4);
  5312.         op_illg (opcode);
  5313.         dump_fp_regs( "END  ");
  5314.         return;
  5315.     }
  5316.     D(bug("FMUL %s\r\n",etos(src)));
  5317.     do_fmul( fp_reg[reg], src );
  5318.     dump_fp_regs( "END  ");
  5319. }
  5320.  
  5321. void REGPARAM2 fpuop_do_fsgldiv( uae_u32 opcode, uae_u16 extra )
  5322. {
  5323.     int reg = (extra >> 7) & 7;
  5324.   float80_s src;
  5325.     if (get_fp_value (opcode, extra, src) == 0) {
  5326.         m68k_setpc (m68k_getpc () - 4);
  5327.         op_illg (opcode);
  5328.         dump_fp_regs( "END  ");
  5329.         return;
  5330.     }
  5331.     D(bug("FSGLDIV %s\r\n",etos(src)));
  5332.     do_fsgldiv( fp_reg[reg], src );
  5333.     dump_fp_regs( "END  ");
  5334. }
  5335.  
  5336. void REGPARAM2 fpuop_do_fscale( uae_u32 opcode, uae_u16 extra )
  5337. {
  5338.     int reg = (extra >> 7) & 7;
  5339.   float80_s src;
  5340.     if (get_fp_value (opcode, extra, src) == 0) {
  5341.         m68k_setpc (m68k_getpc () - 4);
  5342.         op_illg (opcode);
  5343.         dump_fp_regs( "END  ");
  5344.         return;
  5345.     }
  5346.     D(bug("FSCALE %s, opcode=%X, extra=%X, ta %X\r\n",etos(src),opcode,extra,m68k_getpc()));
  5347.     if( IS_INFINITY(fp_reg[reg]) ) {
  5348.         MAKE_NAN( fp_reg[reg] );
  5349.         do_ftst( fp_reg[reg] );
  5350.         sw |= SW_IE;
  5351.     } else {
  5352.         // When the absolute value of the source operand is >= 2^14,
  5353.         // an overflow or underflow always results.
  5354.         do_fscale( fp_reg[reg], src );
  5355.     }
  5356.     dump_fp_regs( "END  ");
  5357. }
  5358.  
  5359. void REGPARAM2 fpuop_do_fsglmul( uae_u32 opcode, uae_u16 extra )
  5360. {
  5361.     int reg = (extra >> 7) & 7;
  5362.   float80_s src;
  5363.     if (get_fp_value (opcode, extra, src) == 0) {
  5364.         m68k_setpc (m68k_getpc () - 4);
  5365.         op_illg (opcode);
  5366.         dump_fp_regs( "END  ");
  5367.         return;
  5368.     }
  5369.     D(bug("FSGLMUL %s\r\n",etos(src)));
  5370.     do_fsglmul( fp_reg[reg], src );
  5371.     dump_fp_regs( "END  ");
  5372. }
  5373.  
  5374. void REGPARAM2 fpuop_do_fsub( uae_u32 opcode, uae_u16 extra )
  5375. {
  5376.     int reg = (extra >> 7) & 7;
  5377.   float80_s src;
  5378.     if (get_fp_value (opcode, extra, src) == 0) {
  5379.         m68k_setpc (m68k_getpc () - 4);
  5380.         op_illg (opcode);
  5381.         dump_fp_regs( "END  ");
  5382.         return;
  5383.     }
  5384.     D(bug("FSUB %s\r\n",etos(src)));
  5385.     do_fsub( fp_reg[reg], src );
  5386.     dump_fp_regs( "END  ");
  5387. }
  5388.  
  5389. void REGPARAM2 fpuop_do_fsincos( uae_u32 opcode, uae_u16 extra )
  5390. {
  5391.     int reg = (extra >> 7) & 7;
  5392.   float80_s src;
  5393.     if (get_fp_value (opcode, extra, src) == 0) {
  5394.         m68k_setpc (m68k_getpc () - 4);
  5395.         op_illg (opcode);
  5396.         dump_fp_regs( "END  ");
  5397.         return;
  5398.     }
  5399.     D(bug("FSINCOS %s\r\n",etos(src)));
  5400.     do_fsincos( fp_reg[reg], fp_reg[extra & 7], src );
  5401.     dump_fp_regs( "END  ");
  5402. }
  5403.  
  5404. void REGPARAM2 fpuop_do_fcmp( uae_u32 opcode, uae_u16 extra )
  5405. {
  5406.     int reg = (extra >> 7) & 7;
  5407.   float80_s src;
  5408.     if (get_fp_value (opcode, extra, src) == 0) {
  5409.         m68k_setpc (m68k_getpc () - 4);
  5410.         op_illg (opcode);
  5411.         dump_fp_regs( "END  ");
  5412.         return;
  5413.     }
  5414.     D(bug("FCMP %s\r\n",etos(src)));
  5415.  
  5416.     if( IS_INFINITY(src) ) {
  5417.         if( IS_NEGATIVE(src) ) {
  5418.             if( IS_INFINITY(fp_reg[reg]) && IS_NEGATIVE(fp_reg[reg]) ) {
  5419.                 sw = SW_Z | SW_N;
  5420.                 D(bug("-INF FCMP -INF -> NZ\r\n"));
  5421.             } else {
  5422.                 sw = SW_FINITE;
  5423.                 D(bug("X FCMP -INF -> None\r\n"));
  5424.             }
  5425.         } else {
  5426.             if( IS_INFINITY(fp_reg[reg]) && !IS_NEGATIVE(fp_reg[reg]) ) {
  5427.                 sw = SW_Z;
  5428.                 D(bug("+INF FCMP +INF -> Z\r\n"));
  5429.             } else {
  5430.                 sw = SW_N;
  5431.                 D(bug("X FCMP +INF -> N\r\n"));
  5432.             }
  5433.         }
  5434.     } else if( IS_INFINITY(fp_reg[reg]) ) {
  5435.         if( IS_NEGATIVE(fp_reg[reg]) ) {
  5436.             sw = SW_N;
  5437.             D(bug("-INF FCMP X -> Negative\r\n"));
  5438.         } else {
  5439.             sw = SW_FINITE;
  5440.             D(bug("+INF FCMP X -> None\r\n"));
  5441.         }
  5442.     } else {
  5443.         do_fcmp( fp_reg[reg], src );
  5444.     }
  5445.  
  5446.     dump_fp_regs( "END  ");
  5447. }
  5448.  
  5449. void REGPARAM2 fpuop_do_ftst( uae_u32 opcode, uae_u16 extra )
  5450. {
  5451.     int reg = (extra >> 7) & 7;
  5452.   float80_s src;
  5453.     if (get_fp_value (opcode, extra, src) == 0) {
  5454.         m68k_setpc (m68k_getpc () - 4);
  5455.         op_illg (opcode);
  5456.         dump_fp_regs( "END  ");
  5457.         return;
  5458.     }
  5459.     D(bug("FTST %s\r\n",etos(src)));
  5460.     do_ftst( src );
  5461.     build_ex_status();
  5462.     dump_fp_regs( "END  ");
  5463. }
  5464.  
  5465.  
  5466.  
  5467. /* ---------------------------- SET FPU MODE ---------------------------- */
  5468.  
  5469. void fpu_set_integral_fpu( bool is_integral )
  5470. {
  5471.     is_integral_68040_fpu = (uae_u32)is_integral;
  5472. }
  5473.  
  5474.  
  5475. /* ---------------------------- SETUP TABLES ---------------------------- */
  5476.  
  5477. static void build_fpp_opp_lookup_table()
  5478. {
  5479.     for( uae_u32 opcode=0; opcode<=0x38; opcode+=8 ) {
  5480.         for( uae_u32 extra=0; extra<65536; extra++ ) {
  5481.             uae_u32 mask = (extra & 0xFC7F) | ((opcode & 0x0038) << 4);
  5482.             fpufunctbl[mask] = fpuop_illg;
  5483.  
  5484.             switch ((extra >> 13) & 0x7) {
  5485.                 case 3:
  5486.                     fpufunctbl[mask] = fpuop_fmove_2_ea;
  5487.                     break;
  5488.                 case 4:
  5489.                 case 5:
  5490.                     if ((opcode & 0x38) == 0) {
  5491.                         if (extra & 0x2000) { // dr bit
  5492.                             switch( extra & 0x1C00 ) {
  5493.                                 case 0x0000:
  5494.                                     fpufunctbl[mask] = fpuop_fmovem_none_2_Dreg;
  5495.                                     break;
  5496.                                 case 0x0400:
  5497.                                     fpufunctbl[mask] = fpuop_fmovem_fpiar_2_Dreg;
  5498.                                     break;
  5499.                                 case 0x0800:
  5500.                                     fpufunctbl[mask] = fpuop_fmovem_fpsr_2_Dreg;
  5501.                                     break;
  5502.                                 case 0x0C00:
  5503.                                     fpufunctbl[mask] = fpuop_fmovem_fpsr_fpiar_2_Dreg;
  5504.                                     break;
  5505.                                 case 0x1000:
  5506.                                     fpufunctbl[mask] = fpuop_fmovem_fpcr_2_Dreg;
  5507.                                     break;
  5508.                                 case 0x1400:
  5509.                                     fpufunctbl[mask] = fpuop_fmovem_fpcr_fpiar_2_Dreg;
  5510.                                     break;
  5511.                                 case 0x1800:
  5512.                                     fpufunctbl[mask] = fpuop_fmovem_fpcr_fpsr_2_Dreg;
  5513.                                     break;
  5514.                                 case 0x1C00:
  5515.                                     fpufunctbl[mask] = fpuop_fmovem_fpcr_fpsr_fpiar_2_Dreg;
  5516.                                     break;
  5517.                             }
  5518.                         } else {
  5519.                             switch( extra & 0x1C00 ) {
  5520.                                 case 0x0000:
  5521.                                     fpufunctbl[mask] = fpuop_fmovem_Dreg_2_none;
  5522.                                     break;
  5523.                                 case 0x0400:
  5524.                                     fpufunctbl[mask] = fpuop_fmovem_Dreg_2_fpiar;
  5525.                                     break;
  5526.                                 case 0x0800:
  5527.                                     fpufunctbl[mask] = fpuop_fmovem_Dreg_2_fpsr;
  5528.                                     break;
  5529.                                 case 0x0C00:
  5530.                                     fpufunctbl[mask] = fpuop_fmovem_Dreg_2_fpsr_fpiar;
  5531.                                     break;
  5532.                                 case 0x1000:
  5533.                                     fpufunctbl[mask] = fpuop_fmovem_Dreg_2_fpcr;
  5534.                                     break;
  5535.                                 case 0x1400:
  5536.                                     fpufunctbl[mask] = fpuop_fmovem_Dreg_2_fpcr_fpiar;
  5537.                                     break;
  5538.                                 case 0x1800:
  5539.                                     fpufunctbl[mask] = fpuop_fmovem_Dreg_2_fpcr_fpsr;
  5540.                                     break;
  5541.                                 case 0x1C00:
  5542.                                     fpufunctbl[mask] = fpuop_fmovem_Dreg_2_fpcr_fpsr_fpiar;
  5543.                                     break;
  5544.                             }
  5545.                         }
  5546.                     } else if ((opcode & 0x38) == 8) {
  5547.                         if (extra & 0x2000) { // dr bit
  5548.                             switch( extra & 0x1C00 ) {
  5549.                                 case 0x0000:
  5550.                                     fpufunctbl[mask] = fpuop_fmovem_none_2_Areg;
  5551.                                     break;
  5552.                                 case 0x0400:
  5553.                                     fpufunctbl[mask] = fpuop_fmovem_fpiar_2_Areg;
  5554.                                     break;
  5555.                                 case 0x0800:
  5556.                                     fpufunctbl[mask] = fpuop_fmovem_fpsr_2_Areg;
  5557.                                     break;
  5558.                                 case 0x0C00:
  5559.                                     fpufunctbl[mask] = fpuop_fmovem_fpsr_fpiar_2_Areg;
  5560.                                     break;
  5561.                                 case 0x1000:
  5562.                                     fpufunctbl[mask] = fpuop_fmovem_fpcr_2_Areg;
  5563.                                     break;
  5564.                                 case 0x1400:
  5565.                                     fpufunctbl[mask] = fpuop_fmovem_fpcr_fpiar_2_Areg;
  5566.                                     break;
  5567.                                 case 0x1800:
  5568.                                     fpufunctbl[mask] = fpuop_fmovem_fpcr_fpsr_2_Areg;
  5569.                                     break;
  5570.                                 case 0x1C00:
  5571.                                     fpufunctbl[mask] = fpuop_fmovem_fpcr_fpsr_fpiar_2_Areg;
  5572.                                     break;
  5573.                             }
  5574.                         } else {
  5575.                             switch( extra & 0x1C00 ) {
  5576.                                 case 0x0000:
  5577.                                     fpufunctbl[mask] = fpuop_fmovem_Areg_2_none;
  5578.                                     break;
  5579.                                 case 0x0400:
  5580.                                     fpufunctbl[mask] = fpuop_fmovem_Areg_2_fpiar;
  5581.                                     break;
  5582.                                 case 0x0800:
  5583.                                     fpufunctbl[mask] = fpuop_fmovem_Areg_2_fpsr;
  5584.                                     break;
  5585.                                 case 0x0C00:
  5586.                                     fpufunctbl[mask] = fpuop_fmovem_Areg_2_fpsr_fpiar;
  5587.                                     break;
  5588.                                 case 0x1000:
  5589.                                     fpufunctbl[mask] = fpuop_fmovem_Areg_2_fpcr;
  5590.                                     break;
  5591.                                 case 0x1400:
  5592.                                     fpufunctbl[mask] = fpuop_fmovem_Areg_2_fpcr_fpiar;
  5593.                                     break;
  5594.                                 case 0x1800:
  5595.                                     fpufunctbl[mask] = fpuop_fmovem_Areg_2_fpcr_fpsr;
  5596.                                     break;
  5597.                                 case 0x1C00:
  5598.                                     fpufunctbl[mask] = fpuop_fmovem_Areg_2_fpcr_fpsr_fpiar;
  5599.                                     break;
  5600.                             }
  5601.                         }
  5602.                     } else if (extra & 0x2000) {
  5603.                         if ((opcode & 0x38) == 0x20) {
  5604.                             switch( extra & 0x1C00 ) {
  5605.                                 case 0x0000:
  5606.                                     fpufunctbl[mask] = fpuop_fmovem_none_2_Mem_predecrement;
  5607.                                     break;
  5608.                                 case 0x0400:
  5609.                                     fpufunctbl[mask] = fpuop_fmovem_fpiar_2_Mem_predecrement;
  5610.                                     break;
  5611.                                 case 0x0800:
  5612.                                     fpufunctbl[mask] = fpuop_fmovem_fpsr_2_Mem_predecrement;
  5613.                                     break;
  5614.                                 case 0x0C00:
  5615.                                     fpufunctbl[mask] = fpuop_fmovem_fpsr_fpiar_2_Mem_predecrement;
  5616.                                     break;
  5617.                                 case 0x1000:
  5618.                                     fpufunctbl[mask] = fpuop_fmovem_fpcr_2_Mem_predecrement;
  5619.                                     break;
  5620.                                 case 0x1400:
  5621.                                     fpufunctbl[mask] = fpuop_fmovem_fpcr_fpiar_2_Mem_predecrement;
  5622.                                     break;
  5623.                                 case 0x1800:
  5624.                                     fpufunctbl[mask] = fpuop_fmovem_fpcr_fpsr_2_Mem_predecrement;
  5625.                                     break;
  5626.                                 case 0x1C00:
  5627.                                     fpufunctbl[mask] = fpuop_fmovem_fpcr_fpsr_fpiar_2_Mem_predecrement;
  5628.                                     break;
  5629.                             }
  5630.                         } else if ((opcode & 0x38) == 0x18) {
  5631.                             switch( extra & 0x1C00 ) {
  5632.                                 case 0x0000:
  5633.                                     fpufunctbl[mask] = fpuop_fmovem_none_2_Mem_postincrement;
  5634.                                     break;
  5635.                                 case 0x0400:
  5636.                                     fpufunctbl[mask] = fpuop_fmovem_fpiar_2_Mem_postincrement;
  5637.                                     break;
  5638.                                 case 0x0800:
  5639.                                     fpufunctbl[mask] = fpuop_fmovem_fpsr_2_Mem_postincrement;
  5640.                                     break;
  5641.                                 case 0x0C00:
  5642.                                     fpufunctbl[mask] = fpuop_fmovem_fpsr_fpiar_2_Mem_postincrement;
  5643.                                     break;
  5644.                                 case 0x1000:
  5645.                                     fpufunctbl[mask] = fpuop_fmovem_fpcr_2_Mem_postincrement;
  5646.                                     break;
  5647.                                 case 0x1400:
  5648.                                     fpufunctbl[mask] = fpuop_fmovem_fpcr_fpiar_2_Mem_postincrement;
  5649.                                     break;
  5650.                                 case 0x1800:
  5651.                                     fpufunctbl[mask] = fpuop_fmovem_fpcr_fpsr_2_Mem_postincrement;
  5652.                                     break;
  5653.                                 case 0x1C00:
  5654.                                     fpufunctbl[mask] = fpuop_fmovem_fpcr_fpsr_fpiar_2_Mem_postincrement;
  5655.                                     break;
  5656.                             }
  5657.                         } else {
  5658.                             switch( extra & 0x1C00 ) {
  5659.                                 case 0x0000:
  5660.                                     fpufunctbl[mask] = fpuop_fmovem_none_2_Mem;
  5661.                                     break;
  5662.                                 case 0x0400:
  5663.                                     fpufunctbl[mask] = fpuop_fmovem_fpiar_2_Mem;
  5664.                                     break;
  5665.                                 case 0x0800:
  5666.                                     fpufunctbl[mask] = fpuop_fmovem_fpsr_2_Mem;
  5667.                                     break;
  5668.                                 case 0x0C00:
  5669.                                     fpufunctbl[mask] = fpuop_fmovem_fpsr_fpiar_2_Mem;
  5670.                                     break;
  5671.                                 case 0x1000:
  5672.                                     fpufunctbl[mask] = fpuop_fmovem_fpcr_2_Mem;
  5673.                                     break;
  5674.                                 case 0x1400:
  5675.                                     fpufunctbl[mask] = fpuop_fmovem_fpcr_fpiar_2_Mem;
  5676.                                     break;
  5677.                                 case 0x1800:
  5678.                                     fpufunctbl[mask] = fpuop_fmovem_fpcr_fpsr_2_Mem;
  5679.                                     break;
  5680.                                 case 0x1C00:
  5681.                                     fpufunctbl[mask] = fpuop_fmovem_fpcr_fpsr_fpiar_2_Mem;
  5682.                                     break;
  5683.                             }
  5684.                         }
  5685.                     } else {
  5686.                         if ((opcode & 0x38) == 0x20) {
  5687.                             switch( extra & 0x1C00 ) {
  5688.                                 case 0x0000:
  5689.                                     fpufunctbl[mask] = fpuop_fmovem_Mem_2_none_predecrement;
  5690.                                     break;
  5691.                                 case 0x0400:
  5692.                                     fpufunctbl[mask] = fpuop_fmovem_Mem_2_fpiar_predecrement;
  5693.                                     break;
  5694.                                 case 0x0800:
  5695.                                     fpufunctbl[mask] = fpuop_fmovem_Mem_2_fpsr_predecrement;
  5696.                                     break;
  5697.                                 case 0x0C00:
  5698.                                     fpufunctbl[mask] = fpuop_fmovem_Mem_2_fpsr_fpiar_predecrement;
  5699.                                     break;
  5700.                                 case 0x1000:
  5701.                                     fpufunctbl[mask] = fpuop_fmovem_Mem_2_fpcr_predecrement;
  5702.                                     break;
  5703.                                 case 0x1400:
  5704.                                     fpufunctbl[mask] = fpuop_fmovem_Mem_2_fpcr_fpiar_predecrement;
  5705.                                     break;
  5706.                                 case 0x1800:
  5707.                                     fpufunctbl[mask] = fpuop_fmovem_Mem_2_fpcr_fpsr_predecrement;
  5708.                                     break;
  5709.                                 case 0x1C00:
  5710.                                     fpufunctbl[mask] = fpuop_fmovem_Mem_2_fpcr_fpsr_fpiar_predecrement;
  5711.                                     break;
  5712.                             }
  5713.                         } else if ((opcode & 0x38) == 0x18) {
  5714.                             switch( extra & 0x1C00 ) {
  5715.                                 case 0x0000:
  5716.                                     fpufunctbl[mask] = fpuop_fmovem_Mem_2_none_postincrement;
  5717.                                     break;
  5718.                                 case 0x0400:
  5719.                                     fpufunctbl[mask] = fpuop_fmovem_Mem_2_fpiar_postincrement;
  5720.                                     break;
  5721.                                 case 0x0800:
  5722.                                     fpufunctbl[mask] = fpuop_fmovem_Mem_2_fpsr_postincrement;
  5723.                                     break;
  5724.                                 case 0x0C00:
  5725.                                     fpufunctbl[mask] = fpuop_fmovem_Mem_2_fpsr_fpiar_postincrement;
  5726.                                     break;
  5727.                                 case 0x1000:
  5728.                                     fpufunctbl[mask] = fpuop_fmovem_Mem_2_fpcr_postincrement;
  5729.                                     break;
  5730.                                 case 0x1400:
  5731.                                     fpufunctbl[mask] = fpuop_fmovem_Mem_2_fpcr_fpiar_postincrement;
  5732.                                     break;
  5733.                                 case 0x1800:
  5734.                                     fpufunctbl[mask] = fpuop_fmovem_Mem_2_fpcr_fpsr_postincrement;
  5735.                                     break;
  5736.                                 case 0x1C00:
  5737.                                     fpufunctbl[mask] = fpuop_fmovem_Mem_2_fpcr_fpsr_fpiar_postincrement;
  5738.                                     break;
  5739.                             }
  5740.                         } else {
  5741.                             switch( extra & 0x1C00 ) {
  5742.                                 case 0x0000:
  5743.                                     fpufunctbl[mask] = fpuop_fmovem_Mem_2_none_2_Mem;
  5744.                                     break;
  5745.                                 case 0x0400:
  5746.                                     fpufunctbl[mask] = fpuop_fmovem_Mem_2_fpiar_2_Mem;
  5747.                                     break;
  5748.                                 case 0x0800:
  5749.                                     fpufunctbl[mask] = fpuop_fmovem_Mem_2_fpsr_2_Mem;
  5750.                                     break;
  5751.                                 case 0x0C00:
  5752.                                     fpufunctbl[mask] = fpuop_fmovem_Mem_2_fpsr_fpiar_2_Mem;
  5753.                                     break;
  5754.                                 case 0x1000:
  5755.                                     fpufunctbl[mask] = fpuop_fmovem_Mem_2_fpcr_2_Mem;
  5756.                                     break;
  5757.                                 case 0x1400:
  5758.                                     fpufunctbl[mask] = fpuop_fmovem_Mem_2_fpcr_fpiar_2_Mem;
  5759.                                     break;
  5760.                                 case 0x1800:
  5761.                                     fpufunctbl[mask] = fpuop_fmovem_Mem_2_fpcr_fpsr_2_Mem;
  5762.                                     break;
  5763.                                 case 0x1C00:
  5764.                                     fpufunctbl[mask] = fpuop_fmovem_Mem_2_fpcr_fpsr_fpiar_2_Mem;
  5765.                                     break;
  5766.                             }
  5767.                         }
  5768.                     break;
  5769.                 case 6:
  5770.                     switch ((extra >> 11) & 3) {
  5771.                         case 0:    /* static pred */
  5772.                             if ((opcode & 0x38) == 0x18) // post-increment?
  5773.                                 fpufunctbl[mask] = fpuop_fmovem_Mem_2_fpp_static_pred_postincrement;
  5774.                             else if ((opcode & 0x38) == 0x20) // pre-decrement?
  5775.                                 fpufunctbl[mask] = fpuop_fmovem_Mem_2_fpp_static_pred_predecrement;
  5776.                             else
  5777.                                 fpufunctbl[mask] = fpuop_fmovem_Mem_2_fpp_static_pred;
  5778.                             break;
  5779.                         case 1:    /* dynamic pred */
  5780.                             if ((opcode & 0x38) == 0x18) // post-increment?
  5781.                                 fpufunctbl[mask] = fpuop_fmovem_Mem_2_fpp_dynamic_pred_postincrement;
  5782.                             else if ((opcode & 0x38) == 0x20) // pre-decrement?
  5783.                                 fpufunctbl[mask] = fpuop_fmovem_Mem_2_fpp_dynamic_pred_predecrement;
  5784.                             else
  5785.                                 fpufunctbl[mask] = fpuop_fmovem_Mem_2_fpp_dynamic_pred;
  5786.                             break;
  5787.                         case 2:    /* static postinc */
  5788.                             if ((opcode & 0x38) == 0x18) // post-increment?
  5789.                                 fpufunctbl[mask] = fpuop_fmovem_Mem_2_fpp_static_postinc_postincrement;
  5790.                             else if ((opcode & 0x38) == 0x20) // pre-decrement?
  5791.                                 fpufunctbl[mask] = fpuop_fmovem_Mem_2_fpp_static_postinc_predecrement;
  5792.                             else
  5793.                                 fpufunctbl[mask] = fpuop_fmovem_Mem_2_fpp_static_postinc;
  5794.                             break;
  5795.                         case 3:    /* dynamic postinc */
  5796.                             if ((opcode & 0x38) == 0x18) // post-increment?
  5797.                                 fpufunctbl[mask] = fpuop_fmovem_Mem_2_fpp_dynamic_postinc_postincrement;
  5798.                             else if ((opcode & 0x38) == 0x20) // pre-decrement?
  5799.                                 fpufunctbl[mask] = fpuop_fmovem_Mem_2_fpp_dynamic_postinc_predecrement;
  5800.                             else
  5801.                                 fpufunctbl[mask] = fpuop_fmovem_Mem_2_fpp_dynamic_postinc;
  5802.                             break;
  5803.                     }
  5804.                     break;
  5805.                 case 7:
  5806.                     switch ((extra >> 11) & 3) {
  5807.                         case 0:    /* static pred */
  5808.                             if ((opcode & 0x38) == 0x18) // post-increment?
  5809.                                 fpufunctbl[mask] = fpuop_fmovem_fpp_2_Mem_static_pred_postincrement;
  5810.                             else if ((opcode & 0x38) == 0x20) // pre-decrement?
  5811.                                 fpufunctbl[mask] = fpuop_fmovem_fpp_2_Mem_static_pred_predecrement;
  5812.                             else
  5813.                                 fpufunctbl[mask] = fpuop_fmovem_fpp_2_Mem_static_pred;
  5814.                             break;
  5815.                         case 1:    /* dynamic pred */
  5816.                             if ((opcode & 0x38) == 0x18) // post-increment?
  5817.                                 fpufunctbl[mask] = fpuop_fmovem_fpp_2_Mem_dynamic_pred_postincrement;
  5818.                             else if ((opcode & 0x38) == 0x20) // pre-decrement?
  5819.                                 fpufunctbl[mask] = fpuop_fmovem_fpp_2_Mem_dynamic_pred_predecrement;
  5820.                             else
  5821.                                 fpufunctbl[mask] = fpuop_fmovem_fpp_2_Mem_dynamic_pred;
  5822.                             break;
  5823.                         case 2:    /* static postinc */
  5824.                             if ((opcode & 0x38) == 0x18) // post-increment?
  5825.                                 fpufunctbl[mask] = fpuop_fmovem_fpp_2_Mem_static_postinc_postincrement;
  5826.                             else if ((opcode & 0x38) == 0x20) // pre-decrement?
  5827.                                 fpufunctbl[mask] = fpuop_fmovem_fpp_2_Mem_static_postinc_predecrement;
  5828.                             else
  5829.                                 fpufunctbl[mask] = fpuop_fmovem_fpp_2_Mem_static_postinc;
  5830.                             break;
  5831.                         case 3:    /* dynamic postinc */
  5832.                             if ((opcode & 0x38) == 0x18) // post-increment?
  5833.                                 fpufunctbl[mask] = fpuop_fmovem_fpp_2_Mem_dynamic_postinc_postincrement;
  5834.                             else if ((opcode & 0x38) == 0x20) // pre-decrement?
  5835.                                 fpufunctbl[mask] = fpuop_fmovem_fpp_2_Mem_dynamic_postinc_predecrement;
  5836.                             else
  5837.                                 fpufunctbl[mask] = fpuop_fmovem_fpp_2_Mem_dynamic_postinc;
  5838.                             break;
  5839.                     }
  5840.                     break;
  5841.                 case 0:
  5842.                 case 2:
  5843.                     if ((extra & 0xfc00) == 0x5c00) {
  5844.                         switch (extra & 0x7f) {
  5845.                             case 0x00:
  5846.                                 fpufunctbl[mask] = fpuop_do_fldpi;
  5847.                                 break;
  5848.                             case 0x0b:
  5849.                                 fpufunctbl[mask] = fpuop_do_fldlg2;
  5850.                                 break;
  5851.                             case 0x0c:
  5852.                                 fpufunctbl[mask] = fpuop_do_load_const_e;
  5853.                                 break;
  5854.                             case 0x0d:
  5855.                                 fpufunctbl[mask] = fpuop_do_fldl2e;
  5856.                                 break;
  5857.                             case 0x0e:
  5858.                                 fpufunctbl[mask] = fpuop_do_load_const_log_10_e;
  5859.                                 break;
  5860.                             case 0x0f:
  5861.                                 fpufunctbl[mask] = fpuop_do_fldz;
  5862.                                 break;
  5863.                             case 0x30:
  5864.                                 fpufunctbl[mask] = fpuop_do_fldln2;
  5865.                                 break;
  5866.                             case 0x31:
  5867.                                 fpufunctbl[mask] = fpuop_do_load_const_ln_10;
  5868.                                 break;
  5869.                             case 0x32:
  5870.                                 fpufunctbl[mask] = fpuop_do_fld1;
  5871.                                 break;
  5872.                             case 0x33:
  5873.                                 fpufunctbl[mask] = fpuop_do_load_const_1e1;
  5874.                                 break;
  5875.                             case 0x34:
  5876.                                 fpufunctbl[mask] = fpuop_do_load_const_1e2;
  5877.                                 break;
  5878.                             case 0x35:
  5879.                                 fpufunctbl[mask] = fpuop_do_load_const_1e4;
  5880.                                 break;
  5881.                             case 0x36:
  5882.                                 fpufunctbl[mask] = fpuop_do_load_const_1e8;
  5883.                                 break;
  5884.                             case 0x37:
  5885.                                 fpufunctbl[mask] = fpuop_do_load_const_1e16;
  5886.                                 break;
  5887.                             case 0x38:
  5888.                                 fpufunctbl[mask] = fpuop_do_load_const_1e32;
  5889.                                 break;
  5890.                             case 0x39:
  5891.                                 fpufunctbl[mask] = fpuop_do_load_const_1e64;
  5892.                                 break;
  5893.                             case 0x3a:
  5894.                                 fpufunctbl[mask] = fpuop_do_load_const_1e128;
  5895.                                 break;
  5896.                             case 0x3b:
  5897.                                 fpufunctbl[mask] = fpuop_do_load_const_1e256;
  5898.                                 break;
  5899.                             case 0x3c:
  5900.                                 fpufunctbl[mask] = fpuop_do_load_const_1e512;
  5901.                                 break;
  5902.                             case 0x3d:
  5903.                                 fpufunctbl[mask] = fpuop_do_load_const_1e1024;
  5904.                                 break;
  5905.                             case 0x3e:
  5906.                                 fpufunctbl[mask] = fpuop_do_load_const_1e2048;
  5907.                                 break;
  5908.                             case 0x3f:
  5909.                                 fpufunctbl[mask] = fpuop_do_load_const_1e4096;
  5910.                                 break;
  5911.                         }
  5912.                         break;
  5913.                     }
  5914.                     
  5915.                     switch (extra & 0x7f) {
  5916.                         case 0x00:
  5917.                             fpufunctbl[mask] = fpuop_do_fmove;
  5918.                             break;
  5919.                         case 0x01:
  5920.                             fpufunctbl[mask] = fpuop_do_fint;
  5921.                             break;
  5922.                         case 0x02:
  5923.                             fpufunctbl[mask] = fpuop_do_fsinh;
  5924.                             break;
  5925.                         case 0x03:
  5926.                             fpufunctbl[mask] = fpuop_do_fintrz;
  5927.                             break;
  5928.                         case 0x04:
  5929.                             fpufunctbl[mask] = fpuop_do_fsqrt;
  5930.                             break;
  5931.                         case 0x06:
  5932.                             fpufunctbl[mask] = fpuop_do_flognp1;
  5933.                             break;
  5934.                         case 0x08:
  5935.                             fpufunctbl[mask] = fpuop_do_fetoxm1;
  5936.                             break;
  5937.                         case 0x09:
  5938.                             fpufunctbl[mask] = fpuop_do_ftanh;
  5939.                             break;
  5940.                         case 0x0a:
  5941.                             fpufunctbl[mask] = fpuop_do_fatan;
  5942.                             break;
  5943.                         case 0x0c:
  5944.                             fpufunctbl[mask] = fpuop_do_fasin;
  5945.                             break;
  5946.                         case 0x0d:
  5947.                             fpufunctbl[mask] = fpuop_do_fatanh;
  5948.                             break;
  5949.                         case 0x0e:
  5950.                             fpufunctbl[mask] = fpuop_do_fsin;
  5951.                             break;
  5952.                         case 0x0f:
  5953.                             fpufunctbl[mask] = fpuop_do_ftan;
  5954.                             break;
  5955.                         case 0x10:
  5956.                             fpufunctbl[mask] = fpuop_do_fetox;
  5957.                             break;
  5958.                         case 0x11:
  5959.                             fpufunctbl[mask] = fpuop_do_ftwotox;
  5960.                             break;
  5961.                         case 0x12:
  5962.                             fpufunctbl[mask] = fpuop_do_ftentox;
  5963.                             break;
  5964.                         case 0x14:
  5965.                             fpufunctbl[mask] = fpuop_do_flogn;
  5966.                             break;
  5967.                         case 0x15:
  5968.                             fpufunctbl[mask] = fpuop_do_flog10;
  5969.                             break;
  5970.                         case 0x16:
  5971.                             fpufunctbl[mask] = fpuop_do_flog2;
  5972.                             break;
  5973.                         case 0x18:
  5974.                             fpufunctbl[mask] = fpuop_do_fabs;
  5975.                             break;
  5976.                         case 0x19:
  5977.                             fpufunctbl[mask] = fpuop_do_fcosh;
  5978.                             break;
  5979.                         case 0x1a:
  5980.                             fpufunctbl[mask] = fpuop_do_fneg;
  5981.                             break;
  5982.                         case 0x1c:
  5983.                             fpufunctbl[mask] = fpuop_do_facos;
  5984.                             break;
  5985.                         case 0x1d:
  5986.                             fpufunctbl[mask] = fpuop_do_fcos;
  5987.                             break;
  5988.                         case 0x1e:
  5989.                             fpufunctbl[mask] = fpuop_do_fgetexp;
  5990.                             break;
  5991.                         case 0x1f:
  5992.                             fpufunctbl[mask] = fpuop_do_fgetman;
  5993.                             break;
  5994.                         case 0x20:
  5995.                             fpufunctbl[mask] = fpuop_do_fdiv;
  5996.                             break;
  5997.                         case 0x21:
  5998.                             fpufunctbl[mask] = fpuop_do_fmod;
  5999.                             break;
  6000.                         case 0x22:
  6001.                             fpufunctbl[mask] = fpuop_do_fadd;
  6002.                             break;
  6003.                         case 0x23:
  6004.                             fpufunctbl[mask] = fpuop_do_fmul;
  6005.                             break;
  6006.                         case 0x24:
  6007.                             fpufunctbl[mask] = fpuop_do_fsgldiv;
  6008.                             break;
  6009.                         case 0x25:
  6010.                             fpufunctbl[mask] = fpuop_do_frem;
  6011.                             break;
  6012.                         case 0x26:
  6013.                             fpufunctbl[mask] = fpuop_do_fscale;
  6014.                             break;
  6015.                         case 0x27:
  6016.                             fpufunctbl[mask] = fpuop_do_fsglmul;
  6017.                             break;
  6018.                         case 0x28:
  6019.                             fpufunctbl[mask] = fpuop_do_fsub;
  6020.                             break;
  6021.                         case 0x30:
  6022.                         case 0x31:
  6023.                         case 0x32:
  6024.                         case 0x33:
  6025.                         case 0x34:
  6026.                         case 0x35:
  6027.                         case 0x36:
  6028.                         case 0x37:
  6029.                             fpufunctbl[mask] = fpuop_do_fsincos;
  6030.                             break;
  6031.                         case 0x38:
  6032.                             fpufunctbl[mask] = fpuop_do_fcmp;
  6033.                             break;
  6034.                         case 0x3a:
  6035.                             fpufunctbl[mask] = fpuop_do_ftst;
  6036.                             break;
  6037.                     }
  6038.                 }
  6039.             }
  6040.         }
  6041.     }
  6042. }
  6043.  
  6044. static void build_fpsr_lookup_tables()
  6045. {
  6046.     uae_u32 i;
  6047.  
  6048.     // Mapping for "sw" -> fpsr condition code
  6049.     for( i=0; i<0x48; i++ ) {
  6050.         sw_cond_host2mac[i] = 0;
  6051.         switch( (i << 8) & (SW_Z_I_NAN_MASK) ) {
  6052.             case SW_UNSUPPORTED:
  6053.             case SW_NAN:
  6054.             case SW_EMPTY_REGISTER:
  6055.                 sw_cond_host2mac[i] |= 0x1000000;
  6056.                 break;
  6057.             case SW_FINITE:
  6058.             case SW_DENORMAL:
  6059.                 break;
  6060.             case SW_I:
  6061.                 sw_cond_host2mac[i] |= 0x2000000;
  6062.                 break;
  6063.             case SW_Z:
  6064.                 sw_cond_host2mac[i] |= 0x4000000;
  6065.                 break;
  6066.         }
  6067.         if( (i << 8) & SW_N ) {
  6068.             sw_cond_host2mac[i] |= 0x8000000;
  6069.         }
  6070.     }
  6071.  
  6072.     // Mapping for fpsr condition code -> "sw"
  6073.     for( i=0; i<16; i++ ) {
  6074.         if( (i << 24) & 0x1000000 ) {
  6075.             sw_cond_mac2host[i] = SW_NAN;
  6076.         } else if( (i << 24) & 0x4000000 ) {
  6077.             sw_cond_mac2host[i] = SW_Z;
  6078.         } else if( (i << 24) & 0x2000000 ) {
  6079.             sw_cond_mac2host[i] = SW_I;
  6080.         } else {
  6081.             sw_cond_mac2host[i] = SW_FINITE;
  6082.         }
  6083.         if( (i << 24) & 0x8000000 ) {
  6084.             sw_cond_mac2host[i] |= SW_N;
  6085.         }
  6086.     }
  6087.  
  6088.     // Mapping for "sw" -> fpsr exception byte
  6089.     for( i=0; i<0x80; i++ ) {
  6090.         exception_host2mac[i] = 0;
  6091.  
  6092.         if(i & SW_FAKE_BSUN) {
  6093.             exception_host2mac[i] |= BSUN;
  6094.         }
  6095.         // precision exception
  6096.         if(i & SW_PE) {
  6097.             exception_host2mac[i] |= INEX2;
  6098.         }
  6099.         // underflow exception
  6100.         if(i & SW_UE) {
  6101.             exception_host2mac[i] |= UNFL;
  6102.         }
  6103.         // overflow exception
  6104.         if(i & SW_OE) {
  6105.             exception_host2mac[i] |= OVFL;
  6106.         }
  6107.         // zero divide exception
  6108.         if(i & SW_ZE) {
  6109.             exception_host2mac[i] |= DZ;
  6110.         }
  6111.         // denormalized operand exception.
  6112.         // wrong, but should not get here, normalization is done in elsewhere
  6113.         if(i & SW_DE) {
  6114.             exception_host2mac[i] |= SNAN;
  6115.         }
  6116.         // invalid operation exception
  6117.         if(i & SW_IE) {
  6118.             exception_host2mac[i] |= OPERR;
  6119.         }
  6120.     }
  6121.  
  6122.     // Mapping for fpsr exception byte -> "sw"
  6123.     for( i=0; i<0x100; i++ ) {
  6124.         int fpsr = (i << 8);
  6125.         exception_mac2host[i] = 0;
  6126.  
  6127.         // BSUN; make sure that you don't generate FPU stack faults.
  6128.         if(fpsr & BSUN) {
  6129.             exception_mac2host[i] |= SW_FAKE_BSUN;
  6130.         }
  6131.         // precision exception
  6132.         if(fpsr & INEX2) {
  6133.             exception_mac2host[i] |= SW_PE;
  6134.         }
  6135.         // underflow exception
  6136.         if(fpsr & UNFL) {
  6137.             exception_mac2host[i] |= SW_UE;
  6138.         }
  6139.         // overflow exception
  6140.         if(fpsr & OVFL) {
  6141.             exception_mac2host[i] |= SW_OE;
  6142.         }
  6143.         // zero divide exception
  6144.         if(fpsr & DZ) {
  6145.             exception_mac2host[i] |= SW_ZE;
  6146.         }
  6147.         // denormalized operand exception
  6148.         if(fpsr & SNAN) {
  6149.             exception_mac2host[i] |= SW_DE; //Wrong
  6150.         }
  6151.         // invalid operation exception
  6152.         if(fpsr & OPERR) {
  6153.             exception_mac2host[i] |= SW_IE;
  6154.         }
  6155.     }
  6156.  
  6157.     /*
  6158.         68881/68040 accrued exceptions accumulate as follows:
  6159.             Accrued.IOP        |= (Exception.SNAN | Exception.OPERR)
  6160.             Accrued.OVFL    |= (Exception.OVFL)
  6161.             Accrued.UNFL    |= (Exception.UNFL | Exception.INEX2)
  6162.             Accrued.DZ        |= (Exception.DZ)
  6163.             Accrued.INEX    |= (Exception.INEX1 | Exception.INEX2 | Exception.OVFL)
  6164.     */
  6165.  
  6166.     // Mapping for "sw_accrued" -> fpsr accrued exception byte
  6167.     for( i=0; i<0x40; i++ ) {
  6168.         accrued_exception_host2mac[i] = 0;
  6169.  
  6170.         // precision exception
  6171.         if(i & SW_PE) {
  6172.             accrued_exception_host2mac[i] |= ACCR_INEX;
  6173.         }
  6174.         // underflow exception
  6175.         if(i & SW_UE) {
  6176.             accrued_exception_host2mac[i] |= ACCR_UNFL;
  6177.         }
  6178.         // overflow exception
  6179.         if(i & SW_OE) {
  6180.             accrued_exception_host2mac[i] |= ACCR_OVFL;
  6181.         }
  6182.         // zero divide exception
  6183.         if(i & SW_ZE) {
  6184.             accrued_exception_host2mac[i] |= ACCR_DZ;
  6185.         }
  6186.         // denormalized operand exception
  6187.         if(i & SW_DE) {
  6188.             accrued_exception_host2mac[i] |= ACCR_IOP; //??????
  6189.         }
  6190.         // invalid operation exception
  6191.         if(i & SW_IE) {
  6192.             accrued_exception_host2mac[i] |= ACCR_IOP;
  6193.         }
  6194.     }
  6195.  
  6196.     // Mapping for fpsr accrued exception byte -> "sw_accrued"
  6197.     for( i=0; i<0x20; i++ ) {
  6198.         int fpsr = (i << 3);
  6199.         accrued_exception_mac2host[i] = 0;
  6200.  
  6201.         // precision exception
  6202.         if(fpsr & ACCR_INEX) {
  6203.             accrued_exception_mac2host[i] |= SW_PE;
  6204.         }
  6205.         // underflow exception
  6206.         if(fpsr & ACCR_UNFL) {
  6207.             accrued_exception_mac2host[i] |= SW_UE;
  6208.         }
  6209.         // overflow exception
  6210.         if(fpsr & ACCR_OVFL) {
  6211.             accrued_exception_mac2host[i] |= SW_OE;
  6212.         }
  6213.         // zero divide exception
  6214.         if(fpsr & ACCR_DZ) {
  6215.             accrued_exception_mac2host[i] |= SW_ZE;
  6216.         }
  6217.         // What about SW_DE; //??????
  6218.         // invalid operation exception
  6219.         if(fpsr & ACCR_IOP) {
  6220.             accrued_exception_mac2host[i] |= SW_IE;
  6221.         }
  6222.     }
  6223. }
  6224.  
  6225. /* ---------------------------- CONSTANTS ---------------------------- */
  6226.  
  6227. static void set_constant( float80 f, char *name, double value, uae_s32 mult )
  6228. {
  6229.     FPU_CONSISTENCY_CHECK_START();
  6230.     if(mult == 1) {
  6231. /*        _asm {
  6232.             MOV            ESI, [f]
  6233.             FLD     QWORD PTR [value]
  6234.             FSTP    TBYTE PTR [ESI]
  6235.         } */
  6236.         _ASM(    "fldl    %1\n"
  6237.                 "fstpt    %0\n"
  6238.             :    "=m" (*f)
  6239.             :    "m" (value)
  6240.             );
  6241.     } else {
  6242. /*        _asm {
  6243.             MOV            ESI, [f]
  6244.             FILD    DWORD PTR [mult]
  6245.             FLD     QWORD PTR [value]
  6246.             FMUL
  6247.             FSTP    TBYTE PTR [ESI]
  6248.         } */
  6249.         _ASM(    "fildl    %2\n"
  6250.                 "fldl    %1\n"
  6251.                 "fmul    \n"
  6252.                 "fstpt    %0\n"
  6253.             :    "=m" (*f)
  6254.             :    "m" (value), "m" (mult)
  6255.             );
  6256.     }
  6257.     D(bug("set_constant (%s,%.04f) = %s\r\n",name,(float)value,etos(f)));
  6258.     FPU_CONSISTENCY_CHECK_STOP( mult==1 ? "set_constant(mult==1)" : "set_constant(mult>1)" );
  6259. }
  6260.  
  6261. static void do_fldpi( float80 dest ) REGPARAM;
  6262. static void do_fldpi( float80 dest )
  6263. {
  6264.     FPU_CONSISTENCY_CHECK_START();
  6265. /*    _asm {
  6266.         FLDPI
  6267.         FXAM
  6268.     FNSTSW  sw
  6269.         MOV            EDI, [dest]
  6270.         FSTP    TBYTE PTR [EDI]
  6271.     } */
  6272.     _ASM(    "fldpi    \n"
  6273.             "fxam    \n"
  6274.             "fnstsw    %0\n"
  6275.             "fstpt    %1\n"
  6276.         :    "=m" (sw), "=m" (*dest)
  6277.         );
  6278.     FPU_CONSISTENCY_CHECK_STOP("do_fldpi");
  6279. }
  6280.  
  6281. static void do_fldlg2( float80 dest ) REGPARAM;
  6282. static void do_fldlg2( float80 dest )
  6283. {
  6284.     FPU_CONSISTENCY_CHECK_START();
  6285. /*    _asm {
  6286.         FLDLG2
  6287.         FXAM
  6288.     FNSTSW  sw
  6289.         MOV            EDI, [dest]
  6290.         FSTP    TBYTE PTR [EDI]
  6291.     } */
  6292.     _ASM(    "fldlg2    \n"
  6293.             "fxam    \n"
  6294.             "fnstsw    %0\n"
  6295.             "fstpt    %1\n"
  6296.         :    "=m" (sw), "=m" (*dest)
  6297.         );
  6298.     FPU_CONSISTENCY_CHECK_STOP("do_fldlg2");
  6299. }
  6300.  
  6301. static void do_fldl2e( float80 dest ) REGPARAM;
  6302. static void do_fldl2e( float80 dest )
  6303. {
  6304.     FPU_CONSISTENCY_CHECK_START();
  6305. /*    _asm {
  6306.         FLDL2E
  6307.         FXAM
  6308.     FNSTSW  sw
  6309.         MOV            EDI, [dest]
  6310.         FSTP    TBYTE PTR [EDI]
  6311.     } */
  6312.     _ASM(    "fldl2e    \n"
  6313.             "fxam    \n"
  6314.             "fnstsw    %0\n"
  6315.             "fstpt    %1\n"
  6316.         :    "=m" (sw), "=m" (*dest)
  6317.         );
  6318.     FPU_CONSISTENCY_CHECK_STOP("do_fldl2e");
  6319. }
  6320.  
  6321. static void do_fldz( float80 dest ) REGPARAM;
  6322. static void do_fldz( float80 dest )
  6323. {
  6324.     FPU_CONSISTENCY_CHECK_START();
  6325. /*    _asm {
  6326.         FLDZ
  6327.         FXAM
  6328.     FNSTSW  sw
  6329.         MOV            EDI, [dest]
  6330.         FSTP    TBYTE PTR [EDI]
  6331.     } */
  6332.     _ASM(    "fldz    \n"
  6333.             "fxam    \n"
  6334.             "fnstsw    %0\n"
  6335.             "fstpt    %1\n"
  6336.         :    "=m" (sw), "=m" (*dest)
  6337.         );
  6338.     FPU_CONSISTENCY_CHECK_STOP("do_fldz");
  6339. }
  6340.  
  6341. static void do_fldln2( float80 dest ) REGPARAM;
  6342. static void do_fldln2( float80 dest )
  6343. {
  6344.     FPU_CONSISTENCY_CHECK_START();
  6345. /*    _asm {
  6346.         FLDLN2
  6347.         FXAM
  6348.     FNSTSW  sw
  6349.         MOV            EDI, [dest]
  6350.         FSTP    TBYTE PTR [EDI]
  6351.     } */
  6352.     _ASM(    "fldln2    \n"
  6353.             "fxam    \n"
  6354.             "fnstsw    %0\n"
  6355.             "fstpt    %1\n"
  6356.         :    "=m" (sw), "=m" (*dest)
  6357.         );
  6358.     FPU_CONSISTENCY_CHECK_STOP("do_fldln2");
  6359. }
  6360.  
  6361. static void do_fld1( float80 dest ) REGPARAM;
  6362. static void do_fld1( float80 dest )
  6363. {
  6364.     FPU_CONSISTENCY_CHECK_START();
  6365. /*    _asm {
  6366.         FLD1
  6367.         FXAM
  6368.     FNSTSW  sw
  6369.         MOV            EDI, [dest]
  6370.         FSTP    TBYTE PTR [EDI]
  6371.     } */
  6372.     _ASM(    "fld1    \n"
  6373.             "fxam    \n"
  6374.             "fnstsw    %0\n"
  6375.             "fstpt    %1\n"
  6376.         :    "=m" (sw), "=m" (*dest)
  6377.         );
  6378.     FPU_CONSISTENCY_CHECK_STOP("do_fld1");
  6379. }
  6380.  
  6381.  
  6382. /* ---------------------------- MAIN INIT ---------------------------- */
  6383.  
  6384. void fpu_init( void )
  6385. {
  6386. /*    _asm {
  6387.     FSAVE   m_fpu_state_original
  6388.     } */
  6389.     _ASM("fsave %0" : "=m" (m_fpu_state_original));
  6390.  
  6391.     regs.fpiar = 0;
  6392.     regs.fpcr = 0;
  6393.     regs.fpsr = 0;
  6394.  
  6395.     cw = CW_INITIAL; 
  6396.     sw = SW_INITIAL;
  6397.     sw_accrued = 0;
  6398.     sw_quotient = 0;
  6399.  
  6400.     for( int i=0; i<8; i++ ) {
  6401.         MAKE_NAN( fp_reg[i] );
  6402.     }
  6403.     
  6404.     build_fpsr_lookup_tables();
  6405.     build_fpp_opp_lookup_table();
  6406.  
  6407. /*    _asm {
  6408.         FNINIT
  6409.         FLDCW   cw
  6410.     } */
  6411.     _ASM("fninit\nfldcw %0" : : "m" (cw));
  6412.  
  6413.     do_fldpi( const_pi );
  6414.     do_fldlg2( const_lg2 );
  6415.     do_fldl2e( const_l2e );
  6416.     do_fldz( const_z );
  6417.     do_fldln2( const_ln2 );
  6418.     do_fld1( const_1 );
  6419.  
  6420.     set_constant( const_e,            "e",            exp (1.0), 1 );
  6421.     set_constant( const_log_10_e,    "Log 10 (e)",    log (exp (1.0)) / log (10.0), 1 );
  6422.     set_constant( const_ln_10,        "ln(10)",        log (10.0), 1 );
  6423.     set_constant( const_1e1,        "1.0e1",        1.0e1, 1 );
  6424.     set_constant( const_1e2,        "1.0e2",        1.0e2, 1 );
  6425.     set_constant( const_1e4,        "1.0e4",        1.0e4, 1 );
  6426.     set_constant( const_1e8,        "1.0e8",        1.0e8, 1 );
  6427.     set_constant( const_1e16,        "1.0e16",        1.0e16, 1 );
  6428.     set_constant( const_1e32,        "1.0e32",        1.0e32, 1 );
  6429.     set_constant( const_1e64,        "1.0e64",        1.0e64, 1 ) ;
  6430.     set_constant( const_1e128,        "1.0e128",        1.0e128, 1 );
  6431.     set_constant( const_1e256,        "1.0e256",        1.0e256, 1 );
  6432.     set_constant( const_1e512,        "1.0e512",        1.0e256, 10 );
  6433.     set_constant( const_1e1024,        "1.0e1024",        1.0e256, 100 );
  6434.     set_constant( const_1e2048,        "1.0e2048",        1.0e256, 1000 );
  6435.     set_constant( const_1e4096,        "1.0e4096",        1.0e256, 10000 );
  6436.     
  6437.     // Just in case.
  6438. /*    _asm {
  6439.         FNINIT
  6440.         FLDCW   cw
  6441.     } */
  6442.     _ASM("fninit\nfldcw %0" : : "m" (cw));
  6443. }
  6444.  
  6445. void fpu_exit( void )
  6446. {
  6447. /*    _asm {
  6448.     FRSTOR  m_fpu_state_original
  6449.         // FNINIT
  6450.     } */
  6451.     _ASM("frstor %0" : : "m" (m_fpu_state_original));
  6452. }
  6453.  
  6454. void fpu_reset( void )
  6455. {
  6456.     fpu_exit();
  6457.     fpu_init();
  6458. }
  6459.  
  6460. #if DEBUG
  6461. #pragma optimize("",on)
  6462. #endif
  6463.