ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/uae_cpu/fpu/fpu_x86.cpp
Revision: 1.7
Committed: 2008-01-01T09:40:36Z (16 years, 5 months ago) by gbeauche
Branch: MAIN
CVS Tags: HEAD
Changes since 1.6: +1 -1 lines
Log Message:
Happy New Year!

File Contents

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