ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/uae_cpu/fpu_x86.cpp
Revision: 1.3
Committed: 2001-02-02T20:53:00Z (23 years, 6 months ago) by cebix
Branch: MAIN
Changes since 1.2: +1 -1 lines
Log Message:
- bumped version number to 0.9
- updated copyright dates

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