ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/uae_cpu/fpu_x86.cpp
Revision: 1.1
Committed: 2000-09-05T16:54:40Z (24 years, 1 month ago) by gbeauche
Branch: MAIN
Log Message:
Ported Lauri's FPU core to GCC/i386

File Contents

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