ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/uae_cpu/fpu_x86.cpp
Revision: 1.4
Committed: 2001-02-09T20:04:15Z (23 years, 5 months ago) by cebix
Branch: MAIN
CVS Tags: snapshot-17022001
Changes since 1.3: +1 -0 lines
Log Message:
fixed compilation problems under BeOS

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