ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/uae_cpu/fpu_x86.cpp
Revision: 1.5
Committed: 2001-03-20T18:04:01Z (23 years, 8 months ago) by gbeauche
Branch: MAIN
CVS Tags: HEAD
Changes since 1.4: +0 -0 lines
State: FILE REMOVED
Error occurred while calculating annotation data.
Log Message:
Moved FPU emulation code sources to uae_cpu/fpu/

File Contents

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