ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/uae_cpu/fpu/fpu_x86.cpp
Revision: 1.5
Committed: 2004-01-12T15:29:31Z (20 years, 8 months ago) by cebix
Branch: MAIN
CVS Tags: nigel-build-16, nigel-build-15
Changes since 1.4: +1 -1 lines
Log Message:
Happy New Year! :)

File Contents

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