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

File Contents

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