ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/uae_cpu/fpu_x86.cpp
Revision: 1.2
Committed: 2001-01-11T13:19:30Z (23 years, 10 months ago) by gbeauche
Branch: MAIN
Changes since 1.1: +2 -0 lines
Log Message:
- From Lauri's ChangeLog: "Fixed a bug in FPU FTAN opcode (didn't pop the value
  1.0 that x86 partial tangent FPTAN always pushes to stack for 8087/287
  compatibility)."

File Contents

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