2
* fpu_x86.cpp - 68881/68040 fpu code for x86/Windows an Linux/x86.
4
* Basilisk II (C) 1997-1999 Christian Bauer
6
* MC68881/68040 fpu emulation
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.
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.
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.
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
28
* Almost the same as original. Please see the comments in "fpu.h".
32
* The reason is not really speed, but to get infinities,
33
* NANs and flags finally working.
36
* How to maintain Mac and x86 FPU flags -- plan B
38
* regs.piar is not updated.
40
* regs.FPU fpcr always contains the real 68881/68040 control word.
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"),
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
54
* - When regs.FPU fpsr is actually used, the value of "x86_status_word"
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"
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.
72
* When "x86_status_word" and "x86_status_word_accrued" are stored,
73
* all pending x86 FPU exceptions are cleared, if there are any.
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".
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
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.
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
92
* x86 co-processor initialization:
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
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
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()
145
#define FPU_IMPLEMENTATION
147
#include "fpu/fpu_x86.h"
148
#include "fpu/fpu_x86_asm.h"
150
/* Global FPU context */
153
/* -------------------------------------------------------------------------- */
154
/* --- Native Support --- */
155
/* -------------------------------------------------------------------------- */
157
#include "fpu/flags.h"
158
#include "fpu/exceptions.h"
159
#include "fpu/rounding.h"
160
#include "fpu/impl.h"
162
#include "fpu/flags.cpp"
163
#include "fpu/exceptions.cpp"
164
#include "fpu/rounding.cpp"
166
/* -------------------------------------------------------------------------- */
167
/* --- Scopes Definition --- */
168
/* -------------------------------------------------------------------------- */
174
#define PRIVATE static
182
/* ---------------------------- Compatibility ---------------------------- */
187
#define min(a, b) (((a) < (b)) ? (a) : (b))
189
/* ---------------------------- Configuration ---------------------------- */
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.
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.
202
gb-- I only tested the following configurations:
203
USE_3_BIT_QUOTIENT 1 -- still changes to apply if no 3-bit quotient
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
209
#define USE_3_BIT_QUOTIENT 1
211
//#define FPU_DEBUG 0 -- now defined in "fpu/fpu.h"
212
#define USE_CONSISTENCY_CHECKING 0
214
#define I3_ON_ILLEGAL_FPU_OP 0
215
#define I3_ON_FTRAPCC 0
217
/* ---------------------------- Debugging ---------------------------- */
219
PUBLIC void FFPU fpu_dump_registers(void)
221
for (int i = 0; i < 8; i++){
222
printf ("FP%d: %g ", i, fpu_get_register(i));
228
PUBLIC void FFPU fpu_dump_flags(void)
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);
243
PRIVATE void FFPU dump_first_bytes_buf(char *b, uae_u8* buf, uae_s32 actual)
246
int32 i, bytes = min(actual,100);
249
for (i=0; i<bytes; i++) {
250
sprintf( bb, "%02x ", (uint32)buf[i] );
253
strcat((char*)b,"\r\n");
256
PUBLIC void FFPU dump_first_bytes(uae_u8 * buf, uae_s32 actual)
259
dump_first_bytes_buf( msg, buf, actual );
263
PRIVATE char * FFPU etos(fpu_register const & e)
265
static char _s[10][30];
275
__asm__ __volatile__(
282
if(++_ix >= 10) _ix = 0;
284
sprintf( _s[_ix], "%.04f", (float)f );
288
PUBLIC void FFPU dump_registers(const char *s)
294
"%s: %s, %s, %s, %s, %s, %s, %s, %s\r\n",
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])
310
PUBLIC void FFPU dump_registers(const char *)
314
PUBLIC void FFPU dump_first_bytes(uae_u8 *, uae_s32)
321
/* ---------------------------- FPU consistency ---------------------------- */
323
#if USE_CONSISTENCY_CHECKING
324
PRIVATE void FFPU FPU_CONSISTENCY_CHECK_START(void)
327
FNSTSW checked_sw_atstart
329
__asm__ __volatile__("fnstsw %0" : "=m" (checked_sw_atstart));
332
PRIVATE void FFPU FPU_CONSISTENCY_CHECK_STOP(const char *name)
334
uae_u16 checked_sw_atend;
335
// _asm FNSTSW checked_sw_atend
336
__asm__ __volatile__("fnstsw %0" : "=m" (checked_sw_attend));
339
// Check for FPU stack overflows/underflows.
340
if( (checked_sw_atend & 0x3800) != (checked_sw_atstart & 0x3800) ) {
343
"FPU stack leak at %s, %X, %X\r\n",
345
(int)(checked_sw_atstart & 0x3800) >> 11,
346
(int)(checked_sw_atend & 0x3800) >> 11
348
OutputDebugString(msg);
351
// Observe status mapping.
353
if(checked_sw_atstart != 0x400 || checked_sw_atend != 0x400) {
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
358
OutputDebugString(msg);
363
PRIVATE void FFPU FPU_CONSISTENCY_CHECK_START(void)
367
PRIVATE void FFPU FPU_CONSISTENCY_CHECK_STOP(const char *)
373
/* ---------------------------- Status byte ---------------------------- */
375
// Map x86 FXAM codes -> m68k fpu status byte
376
#define SW_Z_I_NAN_MASK (SW_C0|SW_C2|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)
386
// Initial state after boot, reset and frestore(null frame)
387
#define SW_INITIAL SW_FINITE
390
/* ---------------------------- Status functions ---------------------------- */
392
PRIVATE void __inline__ FFPU SET_BSUN_ON_NAN ()
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;
400
PRIVATE void __inline__ FFPU build_ex_status ()
402
if(x86_status_word & SW_EXCEPTION_MASK) {
404
__asm__ __volatile__("fnclex");
405
x86_status_word_accrued |= x86_status_word;
409
// TODO_BIGENDIAN; all of these.
410
/* ---------------------------- Type functions ---------------------------- */
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.
417
PRIVATE __inline__ void FFPU MAKE_NAN (fpu_register & f)
419
// Make it non-signaling.
420
uae_u8 * p = (uae_u8 *) &f;
421
memset( p, 0xFF, sizeof(fpu_register) - 1 );
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.
430
PRIVATE __inline__ uae_u32 FFPU IS_INFINITY (fpu_register const & f)
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))
441
PRIVATE __inline__ uae_u32 FFPU IS_NAN (fpu_register const & f)
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))
452
PRIVATE __inline__ uae_u32 FFPU IS_ZERO (fpu_register const & f)
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;
460
PRIVATE __inline__ void FFPU MAKE_INF_POSITIVE (fpu_register & f)
462
uae_u8 * p = (uae_u8 *) &f;
463
memset( p, 0, sizeof(fpu_register)-2 );
464
*((uae_u16 *)&p[8]) = 0x7FFF;
467
PRIVATE __inline__ void FFPU MAKE_INF_NEGATIVE (fpu_register & f)
469
uae_u8 * p = (uae_u8 *) &f;
470
memset( p, 0, sizeof(fpu_register)-2 );
471
*((uae_u16 *)&p[8]) = 0xFFFF;
474
PRIVATE __inline__ void FFPU MAKE_ZERO_POSITIVE (fpu_register & f)
476
uae_u32 * const p = (uae_u32 *) &f;
477
memset( p, 0, sizeof(fpu_register) );
480
PRIVATE __inline__ void FFPU MAKE_ZERO_NEGATIVE (fpu_register & f)
482
uae_u32 * const p = (uae_u32 *) &f;
483
memset( p, 0, sizeof(fpu_register) );
484
*((uae_u32 *)&p[4]) = 0x80000000;
487
PRIVATE __inline__ uae_u32 FFPU IS_NEGATIVE (fpu_register const & f)
489
uae_u8 * p = (uae_u8 *) &f;
490
return( (p[9] & 0x80) != 0 );
494
/* ---------------------------- Conversions ---------------------------- */
496
PRIVATE void FFPU signed_to_extended ( uae_s32 x, fpu_register & f )
498
FPU_CONSISTENCY_CHECK_START();
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");
511
PRIVATE uae_s32 FFPU extended_to_signed_32 ( fpu_register const & f )
513
FPU_CONSISTENCY_CHECK_START();
514
volatile uae_s32 tmp;
515
volatile WORD sw_temp;
524
__asm__ __volatile__(
528
: "=m" (tmp), "=m" (sw_temp)
532
if(sw_temp & SW_EXCEPTION_MASK) {
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.
542
if(sw_temp & SW_PE) {
543
x86_status_word |= SW_PE;
544
x86_status_word_accrued |= SW_PE;
548
D(bug("extended_to_signed_32 (%s) = %X\r\n",etos(f),(int)tmp));
549
FPU_CONSISTENCY_CHECK_STOP("extended_to_signed_32");
553
PRIVATE uae_s16 FFPU extended_to_signed_16 ( fpu_register const & f )
555
FPU_CONSISTENCY_CHECK_START();
556
volatile uae_s16 tmp;
557
volatile WORD sw_temp;
566
__asm__ __volatile__(
570
: "=m" (tmp), "=m" (sw_temp)
574
if(sw_temp & SW_EXCEPTION_MASK) {
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;
582
if(sw_temp & SW_PE) {
583
x86_status_word |= SW_PE;
584
x86_status_word_accrued |= SW_PE;
588
D(bug("extended_to_signed_16 (%s) = %X\r\n",etos(f),(int)tmp));
589
FPU_CONSISTENCY_CHECK_STOP("extended_to_signed_16");
593
PRIVATE uae_s8 FFPU extended_to_signed_8 ( fpu_register const & f )
595
FPU_CONSISTENCY_CHECK_START();
596
volatile uae_s16 tmp;
597
volatile WORD sw_temp;
606
__asm__ __volatile__(
610
: "=m" (tmp), "=m" (sw_temp)
614
if(sw_temp & SW_EXCEPTION_MASK) {
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;
622
if(sw_temp & SW_PE) {
623
x86_status_word |= SW_PE;
624
x86_status_word_accrued |= SW_PE;
628
if(tmp > 127 || tmp < -128) { // OPERR
629
x86_status_word |= SW_IE;
630
x86_status_word_accrued |= SW_IE;
633
D(bug("extended_to_signed_8 (%s) = %X\r\n",etos(f),(int)tmp));
634
FPU_CONSISTENCY_CHECK_STOP("extended_to_signed_8");
638
PRIVATE void FFPU double_to_extended ( double x, fpu_register & f )
640
FPU_CONSISTENCY_CHECK_START();
648
__asm__ __volatile__(
655
FPU_CONSISTENCY_CHECK_STOP("double_to_extended");
658
PRIVATE fpu_double FFPU extended_to_double( fpu_register const & f )
660
FPU_CONSISTENCY_CHECK_START();
666
FSTP QWORD PTR result
669
__asm__ __volatile__(
676
FPU_CONSISTENCY_CHECK_STOP("extended_to_double");
680
PRIVATE void FFPU to_single ( uae_u32 src, fpu_register & f )
682
FPU_CONSISTENCY_CHECK_START();
689
__asm__ __volatile__(
696
D(bug("to_single (%X) = %s\r\n",src,etos(f)));
697
FPU_CONSISTENCY_CHECK_STOP("to_single");
701
PRIVATE void FFPU to_exten_no_normalize ( uae_u32 wrd1, uae_u32 wrd2, uae_u32 wrd3, fpu_register & f )
703
FPU_CONSISTENCY_CHECK_START();
704
uae_u32 *p = (uae_u32 *)&f;
706
uae_u32 sign = (wrd1 & 0x80000000) >> 16;
707
uae_u32 exp = (wrd1 >> 16) & 0x7fff;
710
*((uae_u16 *)&p[2]) = (uae_u16)(sign | exp);
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");
716
PRIVATE void FFPU to_exten ( uae_u32 wrd1, uae_u32 wrd2, uae_u32 wrd3, fpu_register & f )
718
FPU_CONSISTENCY_CHECK_START();
719
uae_u32 *p = (uae_u32 *)&f;
721
uae_u32 sign = (wrd1 & 0x80000000) >> 16;
722
uae_u32 exp = (wrd1 >> 16) & 0x7fff;
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));
729
// mantissa, not fraction.
730
uae_u64 man = ((uae_u64)wrd2 << 32) | wrd3;
731
while( exp > 0 && (man & UVAL64(0x8000000000000000)) == 0 ) {
735
wrd2 = (uae_u32)( man >> 32 );
736
wrd3 = (uae_u32)( man & 0xFFFFFFFF );
737
if( exp == 0 || (wrd2 & 0x80000000) == 0 ) {
739
wrd2 = wrd3 = exp = 0;
743
if(exp != 0x7FFF && exp != 0) {
744
// Make a non-signaling nan.
754
*((uae_u16 *)&p[2]) = (uae_u16)(sign | exp);
756
D(bug("to_exten (%X,%X,%X) = %s\r\n",wrd1,wrd2,wrd3,etos(f)));
757
FPU_CONSISTENCY_CHECK_STOP("to_exten");
760
PRIVATE void FFPU to_double ( uae_u32 wrd1, uae_u32 wrd2, fpu_register & f )
762
FPU_CONSISTENCY_CHECK_START();
764
// gb-- make GCC happy
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.
783
__asm__ __volatile__(
790
D(bug("to_double (%X,%X) = %s\r\n",wrd1,wrd2,etos(f)));
791
FPU_CONSISTENCY_CHECK_STOP("to_double");
794
PRIVATE uae_u32 FFPU from_single ( fpu_register const & f )
796
FPU_CONSISTENCY_CHECK_START();
797
volatile uae_u32 dest;
798
volatile WORD sw_temp;
807
__asm__ __volatile__(
811
: "=m" (dest), "=m" (sw_temp)
815
sw_temp &= SW_EXCEPTION_MASK;
819
x86_status_word = (x86_status_word & ~SW_EXCEPTION_MASK) | sw_temp;
820
x86_status_word_accrued |= sw_temp;
823
D(bug("from_single (%s) = %X\r\n",etos(f),dest));
824
FPU_CONSISTENCY_CHECK_STOP("from_single");
829
PRIVATE void FFPU from_exten ( fpu_register const & f, uae_u32 *wrd1, uae_u32 *wrd2, uae_u32 *wrd3 )
831
FPU_CONSISTENCY_CHECK_START();
832
uae_u32 *p = (uae_u32 *)&f;
835
*wrd1 = ( (uae_u32)*((uae_u16 *)&p[2]) ) << 16;
837
D(bug("from_exten (%s) = %X,%X,%X\r\n",etos(f),*wrd1,*wrd2,*wrd3));
838
FPU_CONSISTENCY_CHECK_STOP("from_exten");
841
PRIVATE void FFPU from_double ( fpu_register const & f, uae_u32 *wrd1, uae_u32 *wrd2 )
843
FPU_CONSISTENCY_CHECK_START();
844
volatile uae_u32 dest[2];
845
volatile WORD sw_temp;
854
__asm__ __volatile__(
858
: "=m" (dest), "=m" (sw_temp)
862
sw_temp &= SW_EXCEPTION_MASK;
866
x86_status_word = (x86_status_word & ~SW_EXCEPTION_MASK) | sw_temp;
867
x86_status_word_accrued |= sw_temp;
870
// TODO: There is a partial memory stall, nothing happens until FSTP retires.
871
// On PIII, could use MMX move w/o any penalty.
875
D(bug("from_double (%s) = %X,%X\r\n",etos(f),dest[1],dest[0]));
876
FPU_CONSISTENCY_CHECK_STOP("from_double");
879
PRIVATE void FFPU do_fmove ( fpu_register & dest, fpu_register const & src )
881
FPU_CONSISTENCY_CHECK_START();
887
FNSTSW x86_status_word
891
__asm__ __volatile__(
896
: "=m" (x86_status_word), "=m" (dest)
899
FPU_CONSISTENCY_CHECK_STOP("do_fmove");
903
PRIVATE void FFPU do_fmove_no_status ( fpu_register & dest, fpu_register const & src )
905
FPU_CONSISTENCY_CHECK_START();
912
FPU_CONSISTENCY_CHECK_STOP("do_fmove_no_status");
917
/* ---------------------------- Operations ---------------------------- */
919
PRIVATE void FFPU do_fint ( fpu_register & dest, fpu_register const & src )
921
FPU_CONSISTENCY_CHECK_START();
928
FNSTSW x86_status_word
931
__asm__ __volatile__(
937
: "=m" (x86_status_word), "=m" (dest)
940
if(x86_status_word & SW_EXCEPTION_MASK) {
942
__asm__ __volatile__("fnclex");
943
x86_status_word &= ~(SW_EXCEPTION_MASK - SW_PE);
944
x86_status_word_accrued |= x86_status_word;
946
FPU_CONSISTENCY_CHECK_STOP("do_fint");
949
PRIVATE void FFPU do_fintrz ( fpu_register & dest, fpu_register const & src )
951
FPU_CONSISTENCY_CHECK_START();
958
and cw_temp, ~X86_ROUNDING_MODE
959
or cw_temp, CW_RC_ZERO
964
FNSTSW x86_status_word
965
FLDCW x86_control_word
969
__asm__ __volatile__(
971
"andl $(~X86_ROUNDING_MODE), %0\n"
972
"orl $CW_RC_ZERO, %0\n"
980
: "+m" (cw_temp), "=m" (x86_status_word), "=m" (dest)
981
: "m" (src), "m" (x86_control_word)
984
if(x86_status_word & SW_EXCEPTION_MASK) {
986
__asm__ __volatile__("fnclex");
987
x86_status_word &= ~(SW_EXCEPTION_MASK - SW_PE);
988
x86_status_word_accrued |= x86_status_word;
990
FPU_CONSISTENCY_CHECK_STOP("do_fintrz");
993
PRIVATE void FFPU do_fsqrt ( fpu_register & dest, fpu_register const & src )
995
FPU_CONSISTENCY_CHECK_START();
1002
FNSTSW x86_status_word
1003
FSTP TBYTE PTR [EDI]
1006
__asm__ __volatile__(
1012
: "=m" (x86_status_word), "=m" (dest)
1016
if(x86_status_word & SW_EXCEPTION_MASK) {
1018
__asm__ __volatile__("fnclex");
1019
x86_status_word &= ~(SW_EXCEPTION_MASK - SW_IE - SW_PE);
1020
x86_status_word_accrued |= x86_status_word;
1022
FPU_CONSISTENCY_CHECK_STOP("do_fsqrt");
1025
PRIVATE void FFPU do_ftst ( fpu_register const & src )
1027
FPU_CONSISTENCY_CHECK_START();
1032
FNSTSW x86_status_word
1036
__asm__ __volatile__(
1041
: "=m" (x86_status_word)
1045
if(x86_status_word & SW_EXCEPTION_MASK) {
1047
__asm__ __volatile__("fnclex");
1048
x86_status_word &= ~SW_EXCEPTION_MASK;
1050
FPU_CONSISTENCY_CHECK_STOP("do_ftst");
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 )
1057
FPU_CONSISTENCY_CHECK_START();
1059
x = extended_to_double( src );
1061
double_to_extended( y, dest );
1063
FPU_CONSISTENCY_CHECK_STOP("do_fsinh");
1066
PRIVATE void FFPU do_flognp1 ( fpu_register & dest, fpu_register const & src )
1068
FPU_CONSISTENCY_CHECK_START();
1070
x = extended_to_double( src );
1072
double_to_extended( y, dest );
1074
FPU_CONSISTENCY_CHECK_STOP("do_flognp1");
1077
PRIVATE void FFPU do_fetoxm1 ( fpu_register & dest, fpu_register const & src )
1079
FPU_CONSISTENCY_CHECK_START();
1081
x = extended_to_double( src );
1083
double_to_extended( y, dest );
1085
FPU_CONSISTENCY_CHECK_STOP("do_fetoxm1");
1088
PRIVATE void FFPU do_ftanh ( fpu_register & dest, fpu_register const & src )
1090
FPU_CONSISTENCY_CHECK_START();
1092
x = extended_to_double( src );
1094
double_to_extended( y, dest );
1096
FPU_CONSISTENCY_CHECK_STOP("do_ftanh");
1099
PRIVATE void FFPU do_fatan ( fpu_register & dest, fpu_register const & src )
1101
FPU_CONSISTENCY_CHECK_START();
1103
x = extended_to_double( src );
1105
double_to_extended( y, dest );
1107
FPU_CONSISTENCY_CHECK_STOP("do_fatan");
1110
PRIVATE void FFPU do_fasin ( fpu_register & dest, fpu_register const & src )
1112
FPU_CONSISTENCY_CHECK_START();
1114
x = extended_to_double( src );
1116
double_to_extended( y, dest );
1118
FPU_CONSISTENCY_CHECK_STOP("do_fasin");
1121
PRIVATE void FFPU do_fatanh ( fpu_register & dest, fpu_register const & src )
1123
FPU_CONSISTENCY_CHECK_START();
1125
x = extended_to_double( src );
1126
y = log ((1 + x) / (1 - x)) / 2;
1127
double_to_extended( y, dest );
1129
FPU_CONSISTENCY_CHECK_STOP("do_fatanh");
1132
PRIVATE void FFPU do_fetox ( fpu_register & dest, fpu_register const & src )
1134
FPU_CONSISTENCY_CHECK_START();
1136
x = extended_to_double( src );
1138
double_to_extended( y, dest );
1140
FPU_CONSISTENCY_CHECK_STOP("do_fetox");
1143
PRIVATE void FFPU do_ftwotox ( fpu_register & dest, fpu_register const & src )
1145
FPU_CONSISTENCY_CHECK_START();
1147
x = extended_to_double( src );
1149
double_to_extended( y, dest );
1151
FPU_CONSISTENCY_CHECK_STOP("do_ftwotox");
1154
PRIVATE void FFPU do_ftentox ( fpu_register & dest, fpu_register const & src )
1156
FPU_CONSISTENCY_CHECK_START();
1158
x = extended_to_double( src );
1160
double_to_extended( y, dest );
1162
FPU_CONSISTENCY_CHECK_STOP("do_ftentox");
1165
PRIVATE void FFPU do_flogn ( fpu_register & dest, fpu_register const & src )
1167
FPU_CONSISTENCY_CHECK_START();
1169
x = extended_to_double( src );
1171
double_to_extended( y, dest );
1173
FPU_CONSISTENCY_CHECK_STOP("do_flogn");
1176
PRIVATE void FFPU do_flog10 ( fpu_register & dest, fpu_register const & src )
1178
FPU_CONSISTENCY_CHECK_START();
1180
x = extended_to_double( src );
1182
double_to_extended( y, dest );
1184
FPU_CONSISTENCY_CHECK_STOP("do_flog10");
1187
PRIVATE void FFPU do_flog2 ( fpu_register & dest, fpu_register const & src )
1189
FPU_CONSISTENCY_CHECK_START();
1191
x = extended_to_double( src );
1192
y = log (x) / log (2.0);
1193
double_to_extended( y, dest );
1195
FPU_CONSISTENCY_CHECK_STOP("do_flog2");
1198
PRIVATE void FFPU do_facos ( fpu_register & dest, fpu_register const & src )
1200
FPU_CONSISTENCY_CHECK_START();
1202
x = extended_to_double( src );
1204
double_to_extended( y, dest );
1206
FPU_CONSISTENCY_CHECK_STOP("do_facos");
1209
PRIVATE void FFPU do_fcosh ( fpu_register & dest, fpu_register const & src )
1211
FPU_CONSISTENCY_CHECK_START();
1213
x = extended_to_double( src );
1215
double_to_extended( y, dest );
1217
FPU_CONSISTENCY_CHECK_STOP("do_fcosh");
1220
PRIVATE void FFPU do_fsin ( fpu_register & dest, fpu_register const & src )
1222
FPU_CONSISTENCY_CHECK_START();
1229
FNSTSW x86_status_word
1230
FSTP TBYTE PTR [EDI]
1232
__asm__ __volatile__(
1238
: "=m" (x86_status_word), "=m" (dest)
1241
if(x86_status_word & SW_EXCEPTION_MASK) {
1243
__asm__ __volatile__("fnclex");
1244
x86_status_word &= ~(SW_EXCEPTION_MASK - SW_IE - SW_PE);
1245
x86_status_word_accrued |= x86_status_word;
1247
FPU_CONSISTENCY_CHECK_STOP("do_fsin");
1250
// TODO: Should check for out-of-range condition (partial tangent)
1251
PRIVATE void FFPU do_ftan ( fpu_register & dest, fpu_register const & src )
1253
FPU_CONSISTENCY_CHECK_START();
1259
FSTP ST(0) ; pop 1.0 (the 8087/287 compatibility thing)
1261
FNSTSW x86_status_word
1262
FSTP TBYTE PTR [EDI]
1264
__asm__ __volatile__(
1271
: "=m" (x86_status_word), "=m" (dest)
1274
if(x86_status_word & SW_EXCEPTION_MASK) {
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;
1280
FPU_CONSISTENCY_CHECK_STOP("do_ftan");
1283
PRIVATE void FFPU do_fabs ( fpu_register & dest, fpu_register const & src )
1285
FPU_CONSISTENCY_CHECK_START();
1292
FNSTSW x86_status_word
1293
FSTP TBYTE PTR [EDI]
1295
__asm__ __volatile__(
1301
: "=m" (x86_status_word), "=m" (dest)
1304
// x86 fabs should not rise any exceptions (except stack underflow)
1305
if(x86_status_word & SW_EXCEPTION_MASK) {
1307
__asm__ __volatile__("fnclex");
1308
x86_status_word &= ~SW_EXCEPTION_MASK;
1310
FPU_CONSISTENCY_CHECK_STOP("do_fabs");
1313
PRIVATE void FFPU do_fneg ( fpu_register & dest, fpu_register const & src )
1315
FPU_CONSISTENCY_CHECK_START();
1322
FNSTSW x86_status_word
1323
FSTP TBYTE PTR [EDI]
1325
__asm__ __volatile__(
1331
: "=m" (x86_status_word), "=m" (dest)
1334
// x86 fchs should not rise any exceptions (except stack underflow)
1335
if(x86_status_word & SW_EXCEPTION_MASK) {
1337
__asm__ __volatile__("fnclex");
1338
x86_status_word &= ~SW_EXCEPTION_MASK;
1340
FPU_CONSISTENCY_CHECK_STOP("do_fneg");
1343
PRIVATE void FFPU do_fcos ( fpu_register & dest, fpu_register const & src )
1345
FPU_CONSISTENCY_CHECK_START();
1352
FNSTSW x86_status_word
1353
FSTP TBYTE PTR [EDI]
1355
__asm__ __volatile__(
1361
: "=m" (x86_status_word), "=m" (dest)
1364
if(x86_status_word & SW_EXCEPTION_MASK) {
1366
__asm__ __volatile__("fnclex");
1367
x86_status_word &= ~(SW_EXCEPTION_MASK - SW_IE - SW_PE);
1368
x86_status_word_accrued |= x86_status_word;
1370
FPU_CONSISTENCY_CHECK_STOP("do_fcos");
1373
PRIVATE void FFPU do_fgetexp ( fpu_register & dest, fpu_register const & src )
1375
FPU_CONSISTENCY_CHECK_START();
1381
FSTP ST(0) ; pop mantissa
1383
FNSTSW x86_status_word
1384
FSTP TBYTE PTR [EDI]
1386
__asm__ __volatile__(
1393
: "=m" (x86_status_word), "=m" (dest)
1396
if(x86_status_word & SW_EXCEPTION_MASK) {
1398
__asm__ __volatile__("fnclex");
1399
x86_status_word &= ~SW_EXCEPTION_MASK;
1401
FPU_CONSISTENCY_CHECK_STOP("do_fgetexp");
1404
PRIVATE void FFPU do_fgetman ( fpu_register & dest, fpu_register const & src )
1406
FPU_CONSISTENCY_CHECK_START();
1413
FNSTSW x86_status_word
1414
FSTP TBYTE PTR [EDI]
1415
FSTP ST(0) ; pop exponent
1417
__asm__ __volatile__(
1424
: "=m" (x86_status_word), "=m" (dest)
1427
if(x86_status_word & SW_EXCEPTION_MASK) {
1429
__asm__ __volatile__("fnclex");
1430
x86_status_word &= ~SW_EXCEPTION_MASK;
1432
FPU_CONSISTENCY_CHECK_STOP("do_fgetman");
1435
PRIVATE void FFPU do_fdiv ( fpu_register & dest, fpu_register const & src )
1437
FPU_CONSISTENCY_CHECK_START();
1445
FNSTSW x86_status_word
1446
FSTP TBYTE PTR [EDI]
1449
__asm__ __volatile__(
1452
"fdiv %%st(1), %%st(0)\n"
1457
: "=m" (x86_status_word), "+m" (dest)
1460
if(x86_status_word & SW_EXCEPTION_MASK) {
1462
__asm__ __volatile__("fnclex");
1463
x86_status_word_accrued |= x86_status_word;
1465
FPU_CONSISTENCY_CHECK_STOP("do_fdiv");
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.
1473
PRIVATE void FFPU do_fmod ( fpu_register & dest, fpu_register const & src )
1475
FPU_CONSISTENCY_CHECK_START();
1477
volatile uint16 status;
1479
#if !USE_3_BIT_QUOTIENT
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;
1491
#if !USE_3_BIT_QUOTIENT
1492
MOV CX, x86_control_word
1493
AND CX, ~X86_ROUNDING_MODE
1502
FISTP DWORD PTR quot
1504
FLDCW x86_control_word
1506
// Should clear any possible exceptions here
1512
// loop until the remainder is not partial any more.
1521
FNSTSW x86_status_word
1523
FSTP TBYTE PTR [EDI]
1527
#if !USE_3_BIT_QUOTIENT
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)
1537
"fdiv %%st(1), %%st(0)\n"
1539
"fistpl %1\n" // %1: quot (read/write)
1544
"0:\n" // partial_loop
1546
"fnstsw %2\n" // %2: status (read/write)
1547
"testl $SW_C2, %2\n"
1550
"fnstsw %3\n" // %3: x86_status_word (write)
1553
: "+m" (cw_temp), "+m" (quot), "+m" (status), "=m" (x86_status_word), "+m" (dest)
1554
: "m" (src), "m" (x86_control_word)
1560
__asm__ __volatile__(
1563
"0:\n" // partial_loop
1565
"fnstsw %0\n" // %0: status (read/write)
1566
"testl $SW_C2, %0\n"
1569
"fnstsw %1\n" // %1: x86_status_word (write)
1572
: "+m" (status), "=m" (x86_status_word), "+m" (dest)
1578
if(x86_status_word & SW_EXCEPTION_MASK) {
1580
__asm__ __volatile__("fnclex");
1581
x86_status_word &= ~(SW_EXCEPTION_MASK - SW_IE - SW_UE);
1582
x86_status_word_accrued |= x86_status_word;
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;
1592
FPU fpsr.quotient = (sign | (quot&0x7F)) << 16;
1595
FPU_CONSISTENCY_CHECK_STOP("do_fmod");
1598
PRIVATE void FFPU do_frem ( fpu_register & dest, fpu_register const & src )
1600
FPU_CONSISTENCY_CHECK_START();
1602
volatile uint16 status;
1604
#if !USE_3_BIT_QUOTIENT
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;
1616
#if !USE_3_BIT_QUOTIENT
1617
MOV CX, x86_control_word
1618
AND CX, ~X86_ROUNDING_MODE
1627
FISTP DWORD PTR quot
1629
FLDCW x86_control_word
1631
// Should clear any possible exceptions here
1637
// loop until the remainder is not partial any more.
1645
FNSTSW x86_status_word
1646
FSTP TBYTE PTR [EDI]
1650
#if !USE_3_BIT_QUOTIENT
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)
1660
"fdiv %%st(1), %%st(0)\n"
1662
"fistpl %1\n" // %1: quot (read/write)
1667
"0:\n" // partial_loop
1669
"fnstsw %2\n" // %2: status (read/write)
1670
"testl $SW_C2, %2\n"
1673
"fnstsw %3\n" // %3: x86_status_word (write)
1676
: "+m" (cw_temp), "+m" (quot), "+m" (status), "=m" (x86_status_word), "+m" (dest)
1677
: "m" (src), "m" (x86_control_word)
1683
__asm__ __volatile__(
1686
"0:\n" // partial_loop
1688
"fnstsw %0\n" // %0: status (read/write)
1689
"testl $SW_C2, %0\n"
1692
"fnstsw %1\n" // %1: x86_status_word (write)
1695
: "+m" (status), "=m" (x86_status_word), "+m" (dest)
1701
if(x86_status_word & SW_EXCEPTION_MASK) {
1703
__asm__ __volatile__("fnclex");
1704
x86_status_word &= ~(SW_EXCEPTION_MASK - SW_IE - SW_UE);
1705
x86_status_word_accrued |= x86_status_word;
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;
1715
FPU fpsr.quotient = (sign | (quot&0x7F)) << 16;
1718
FPU_CONSISTENCY_CHECK_STOP("do_frem");
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 )
1725
FPU_CONSISTENCY_CHECK_START();
1727
volatile uint16 status;
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;
1742
FISTP DWORD PTR quot
1745
// Should clear any possible exceptions here
1750
// loop until the remainder is not partial any more.
1758
FNSTSW x86_status_word
1760
FSTP TBYTE PTR [EDI]
1763
if(x86_status_word & SW_EXCEPTION_MASK) {
1765
x86_status_word &= ~(SW_EXCEPTION_MASK - SW_IE - SW_UE);
1766
x86_status_word_accrued |= x86_status_word;
1768
FPU fpsr.quotient = (sign | (quot&0x7F)) << 16;
1769
FPU_CONSISTENCY_CHECK_STOP("do_fmod_dont_set_cw");
1772
PRIVATE void FFPU do_frem_dont_set_cw ( fpu_register & dest, fpu_register const & src )
1774
FPU_CONSISTENCY_CHECK_START();
1776
volatile uint16 status;
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;
1791
FISTP DWORD PTR quot
1794
// Should clear any possible exceptions here
1799
// loop until the remainder is not partial any more.
1807
FNSTSW x86_status_word
1808
FSTP TBYTE PTR [EDI]
1811
if(x86_status_word & SW_EXCEPTION_MASK) {
1813
x86_status_word &= ~(SW_EXCEPTION_MASK - SW_IE - SW_UE);
1814
x86_status_word_accrued |= x86_status_word;
1816
FPU fpsr.quotient = (sign | (quot&0x7F)) << 16;
1817
FPU_CONSISTENCY_CHECK_STOP("do_frem_dont_set_cw");
1819
#endif //USE_3_BIT_QUOTIENT
1821
PRIVATE void FFPU do_fadd ( fpu_register & dest, fpu_register const & src )
1823
FPU_CONSISTENCY_CHECK_START();
1831
FNSTSW x86_status_word
1832
FSTP TBYTE PTR [EDI]
1834
__asm__ __volatile__(
1841
: "=m" (x86_status_word), "+m" (dest)
1844
if(x86_status_word & SW_EXCEPTION_MASK) {
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;
1850
FPU_CONSISTENCY_CHECK_STOP("do_fadd");
1853
PRIVATE void FFPU do_fmul ( fpu_register & dest, fpu_register const & src )
1855
FPU_CONSISTENCY_CHECK_START();
1863
FNSTSW x86_status_word
1864
FSTP TBYTE PTR [EDI]
1866
__asm__ __volatile__(
1873
: "=m" (x86_status_word), "+m" (dest)
1876
if(x86_status_word & SW_EXCEPTION_MASK) {
1878
__asm__ __volatile__("fnclex");
1879
x86_status_word_accrued |= x86_status_word;
1881
FPU_CONSISTENCY_CHECK_STOP("do_fmul");
1884
PRIVATE void FFPU do_fsgldiv ( fpu_register & dest, fpu_register const & src )
1886
FPU_CONSISTENCY_CHECK_START();
1890
and cw_temp, ~X86_ROUNDING_PRECISION
1891
or cw_temp, PRECISION_CONTROL_SINGLE
1900
FNSTSW x86_status_word
1901
FSTP TBYTE PTR [EDI]
1903
FLDCW x86_control_word
1905
__asm__ __volatile__(
1907
"andl $(~X86_ROUNDING_PRECISION), %0\n"
1908
"orl $PRECISION_CONTROL_SINGLE, %0\n"
1912
"fdiv %%st(1), %%st(0)\n"
1918
: "+m" (cw_temp), "=m" (x86_status_word), "+m" (dest)
1919
: "m" (src), "m" (x86_control_word)
1921
if(x86_status_word & SW_EXCEPTION_MASK) {
1923
__asm__ __volatile__("fnclex");
1924
x86_status_word_accrued |= x86_status_word;
1926
FPU_CONSISTENCY_CHECK_STOP("do_fsgldiv");
1929
PRIVATE void FFPU do_fscale ( fpu_register & dest, fpu_register const & src )
1931
FPU_CONSISTENCY_CHECK_START();
1939
FNSTSW x86_status_word
1940
FSTP TBYTE PTR [EDI]
1943
__asm__ __volatile__(
1951
: "=m" (x86_status_word), "+m" (dest)
1954
if(x86_status_word & SW_EXCEPTION_MASK) {
1956
__asm__ __volatile__("fnclex");
1957
x86_status_word &= ~(SW_EXCEPTION_MASK - SW_UE - SW_OE);
1958
x86_status_word_accrued |= x86_status_word;
1960
FPU_CONSISTENCY_CHECK_STOP("do_fscale");
1963
PRIVATE void FFPU do_fsglmul ( fpu_register & dest, fpu_register const & src )
1965
FPU_CONSISTENCY_CHECK_START();
1970
and cw_temp, ~X86_ROUNDING_PRECISION
1971
or cw_temp, PRECISION_CONTROL_SINGLE
1980
FNSTSW x86_status_word
1981
FSTP TBYTE PTR [EDI]
1983
FLDCW x86_control_word
1985
__asm__ __volatile__(
1987
"andl $(~X86_ROUNDING_PRECISION), %0\n"
1988
"orl $PRECISION_CONTROL_SINGLE, %0\n"
1997
: "+m" (cw_temp), "=m" (x86_status_word), "+m" (dest)
1998
: "m" (src), "m" (x86_status_word)
2000
if(x86_status_word & SW_EXCEPTION_MASK) {
2002
__asm__ __volatile__("fnclex");
2003
x86_status_word_accrued |= x86_status_word;
2005
FPU_CONSISTENCY_CHECK_STOP("do_fsglmul");
2008
PRIVATE void FFPU do_fsub ( fpu_register & dest, fpu_register const & src )
2010
FPU_CONSISTENCY_CHECK_START();
2018
FNSTSW x86_status_word
2019
FSTP TBYTE PTR [EDI]
2022
__asm__ __volatile__(
2025
"fsub %%st(1), %%st(0)\n"
2030
: "=m" (x86_status_word), "+m" (dest)
2033
if(x86_status_word & SW_EXCEPTION_MASK) {
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;
2039
FPU_CONSISTENCY_CHECK_STOP("do_fsub");
2042
PRIVATE void FFPU do_fsincos ( fpu_register & dest_sin, fpu_register & dest_cos, fpu_register const & src )
2044
FPU_CONSISTENCY_CHECK_START();
2050
FSTP TBYTE PTR [EDI]
2053
FNSTSW x86_status_word
2054
FSTP TBYTE PTR [EDI]
2057
__asm__ __volatile__(
2065
: "=m" (x86_status_word), "=m" (dest_cos), "=m" (dest_sin)
2068
if(x86_status_word & SW_EXCEPTION_MASK) {
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;
2074
FPU_CONSISTENCY_CHECK_STOP("do_fsincos");
2077
PRIVATE void FFPU do_fcmp ( fpu_register & dest, fpu_register const & src )
2079
FPU_CONSISTENCY_CHECK_START();
2087
FNSTSW x86_status_word
2091
__asm__ __volatile__(
2094
"fsub %%st(1), %%st(0)\n"
2099
: "=m" (x86_status_word)
2100
: "m" (dest), "m" (src)
2102
if(x86_status_word & SW_EXCEPTION_MASK) {
2104
__asm__ __volatile__("fnclex");
2105
x86_status_word &= ~SW_EXCEPTION_MASK;
2107
FPU_CONSISTENCY_CHECK_STOP("do_fcmp");
2110
// More or less original. Should be reviewed.
2111
PRIVATE fpu_double FFPU to_pack(uae_u32 wrd1, uae_u32 wrd2, uae_u32 wrd3)
2113
FPU_CONSISTENCY_CHECK_START();
2120
if (wrd1 & 0x80000000)
2122
*cp++ = (char)((wrd1 & 0xf) + '0');
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');
2141
if (wrd1 & 0x40000000)
2143
*cp++ = (char)(((wrd1 >> 24) & 0xf) + '0');
2144
*cp++ = (char)(((wrd1 >> 20) & 0xf) + '0');
2145
*cp++ = (char)(((wrd1 >> 16) & 0xf) + '0');
2147
sscanf(str, "%le", &d);
2149
D(bug("to_pack str = %s\r\n",str));
2151
D(bug("to_pack(%X,%X,%X) = %.04f\r\n",wrd1,wrd2,wrd3,(float)d));
2153
FPU_CONSISTENCY_CHECK_STOP("to_pack");
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)
2161
FPU_CONSISTENCY_CHECK_START();
2167
int exponent_digit_count = 0;
2169
sprintf(str, "%.16e", src);
2171
D(bug("from_pack(%.04f,%s)\r\n",(float)src,str));
2174
*wrd1 = *wrd2 = *wrd3 = 0;
2181
*wrd1 |= (*cp++ - '0');
2184
for (i = 0; i < 8; i++) {
2186
if (*cp >= '0' && *cp <= '9')
2187
*wrd2 |= *cp++ - '0';
2189
for (i = 0; i < 8; i++) {
2191
if (*cp >= '0' && *cp <= '9')
2192
*wrd3 |= *cp++ - '0';
2194
if (*cp == 'e' || *cp == 'E') {
2198
*wrd1 |= 0x40000000;
2203
for (i = 0; i < 3; i++) {
2204
if (*cp >= '0' && *cp <= '9') {
2205
t = (t << 4) | (*cp++ - '0');
2206
exponent_digit_count++;
2212
D(bug("from_pack(%.04f) = %X,%X,%X\r\n",(float)src,*wrd1,*wrd2,*wrd3));
2215
// _asm FNSTSW sw_temp
2216
__asm__ __volatile__("fnstsw %0" : "=m" (sw_temp));
2217
if(sw_temp & SW_EXCEPTION_MASK) {
2219
__asm__ __volatile__("fnclex");
2220
if(sw_temp & SW_PE) {
2221
x86_status_word |= SW_PE;
2222
x86_status_word_accrued |= SW_PE;
2227
OPERR is set if the k-factor > + 17 or the magnitude of
2228
the decimal exponent exceeds three digits;
2231
if(exponent_digit_count > 3) {
2232
x86_status_word |= SW_IE;
2233
x86_status_word_accrued |= SW_IE;
2236
FPU_CONSISTENCY_CHECK_STOP("from_pack");
2239
PRIVATE int FFPU get_fp_value (uae_u32 opcode, uae_u32 extra, fpu_register & src)
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};
2244
// D(bug("get_fp_value(%X,%X)\r\n",(int)opcode,(int)extra));
2245
// dump_first_bytes( regs.pc_p-4, 16 );
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] );
2253
int mode = (opcode >> 3) & 7;
2254
int reg = opcode & 7;
2255
int size = (extra >> 10) & 7;
2258
// D(bug("get_fp_value mode=%d, reg=%d, size=%d\r\n",(int)mode,(int)reg,(int)size));
2260
switch ((uae_u8)mode) {
2262
switch ((uae_u8)size) {
2264
signed_to_extended( (uae_s32)(uae_s8) m68k_dreg (regs, reg), src );
2267
signed_to_extended( (uae_s32)(uae_s16) m68k_dreg (regs, reg), src );
2270
signed_to_extended( (uae_s32) m68k_dreg (regs, reg), src );
2273
to_single( m68k_dreg (regs, reg), src );
2282
ad = m68k_areg (regs, reg);
2285
ad = m68k_areg (regs, reg);
2286
m68k_areg (regs, reg) += reg == 7 ? sz2[size] : sz1[size];
2289
m68k_areg (regs, reg) -= reg == 7 ? sz2[size] : sz1[size];
2290
ad = m68k_areg (regs, reg);
2293
ad = m68k_areg (regs, reg) + (uae_s32) (uae_s16) next_iword();
2296
ad = get_disp_ea_020 (m68k_areg (regs, reg), next_iword());
2299
switch ((uae_u8)reg) {
2301
ad = (uae_s32) (uae_s16) next_iword();
2308
ad += (uae_s32) (uae_s16) next_iword();
2311
uaecptr tmppc = m68k_getpc ();
2312
uae_u16 tmp = (uae_u16)next_iword();
2313
ad = get_disp_ea_020 (tmppc, tmp);
2318
m68k_setpc (ad + sz2[size]);
2321
+0000 000004 FSCALE.B #$01,FP2 | F23C 5926 0001
2322
F23C 1111001000111100
2323
5926 0101100100100110
2324
0001 0000000000000001
2329
// Immediate addressing mode && Operation Length == Byte ->
2330
// Use the low-order byte of the extension word.
2334
// May be faster on a PII(I), sz2[size] is already in register
2335
// ad += sz2[size] - sz1[size];
2343
switch ((uae_u8)size) {
2345
signed_to_extended( (uae_s32) get_long (ad), src );
2348
to_single( get_long (ad), src );
2352
uae_u32 wrd1, wrd2, wrd3;
2353
wrd1 = get_long (ad);
2355
wrd2 = get_long (ad);
2357
wrd3 = get_long (ad);
2358
to_exten( wrd1, wrd2, wrd3, src );
2362
uae_u32 wrd1, wrd2, wrd3;
2363
wrd1 = get_long (ad);
2365
wrd2 = get_long (ad);
2367
wrd3 = get_long (ad);
2368
double_to_extended( to_pack(wrd1, wrd2, wrd3), src );
2372
signed_to_extended( (uae_s32)(uae_s16) get_word(ad), src );
2376
wrd1 = get_long (ad);
2378
wrd2 = get_long (ad);
2379
to_double(wrd1, wrd2, src);
2383
signed_to_extended( (uae_s32)(uae_s8) get_byte(ad), src );
2389
// D(bug("get_fp_value result = %.04f\r\n",(float)src));
2394
PRIVATE int FFPU put_fp_value (fpu_register const & value, uae_u32 opcode, uae_u32 extra)
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};
2399
// D(bug("put_fp_value(%.04f,%X,%X)\r\n",(float)value,(int)opcode,(int)extra));
2401
if ((extra & 0x4000) == 0) {
2402
int dest_reg = (extra >> 10) & 7;
2403
do_fmove( FPU registers[dest_reg], value );
2408
int mode = (opcode >> 3) & 7;
2409
int reg = opcode & 7;
2410
int size = (extra >> 10) & 7;
2411
uae_u32 ad = 0xffffffff;
2413
// Clear exception status
2414
x86_status_word &= ~SW_EXCEPTION_MASK;
2416
switch ((uae_u8)mode) {
2418
switch ((uae_u8)size) {
2420
*((uae_u8 *)&m68k_dreg(regs, reg)) = extended_to_signed_8(value);
2424
*((uae_u16 *)&m68k_dreg(regs, reg)) = extended_to_signed_16(value);
2427
m68k_dreg (regs, reg) = extended_to_signed_32(value);
2430
m68k_dreg (regs, reg) = from_single(value);
2439
ad = m68k_areg (regs, reg);
2442
ad = m68k_areg (regs, reg);
2443
m68k_areg (regs, reg) += reg == 7 ? sz2[size] : sz1[size];
2446
m68k_areg (regs, reg) -= reg == 7 ? sz2[size] : sz1[size];
2447
ad = m68k_areg (regs, reg);
2450
ad = m68k_areg (regs, reg) + (uae_s32) (uae_s16) next_iword();
2453
ad = get_disp_ea_020 (m68k_areg (regs, reg), next_iword());
2456
switch ((uae_u8)reg) {
2458
ad = (uae_s32) (uae_s16) next_iword();
2465
ad += (uae_s32) (uae_s16) next_iword();
2468
uaecptr tmppc = m68k_getpc ();
2469
uae_u16 tmp = (uae_u16)next_iword();
2470
ad = get_disp_ea_020 (tmppc, tmp);
2475
m68k_setpc (ad + sz2[size]);
2481
switch ((uae_u8)size) {
2483
put_long (ad, (uae_s32) extended_to_signed_32(value));
2486
put_long (ad, from_single(value));
2489
uae_u32 wrd1, wrd2, wrd3;
2490
from_exten(value, &wrd1, &wrd2, &wrd3);
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;
2498
put_long (ad, wrd1);
2500
put_long (ad, wrd2);
2502
put_long (ad, wrd3);
2506
uae_u32 wrd1, wrd2, wrd3;
2507
from_pack(extended_to_double(value), &wrd1, &wrd2, &wrd3);
2508
put_long (ad, wrd1);
2510
put_long (ad, wrd2);
2512
put_long (ad, wrd3);
2516
put_word(ad, extended_to_signed_16(value));
2520
from_double(value, &wrd1, &wrd2);
2521
put_long (ad, wrd1);
2523
put_long (ad, wrd2);
2527
put_byte(ad, extended_to_signed_8(value));
2536
PRIVATE int FFPU get_fp_ad(uae_u32 opcode, uae_u32 * ad)
2538
int mode = (opcode >> 3) & 7;
2539
int reg = opcode & 7;
2540
switch ( (uae_u8)mode ) {
2543
if( (opcode & 0xFF00) == 0xF300 ) {
2545
m68k_setpc (m68k_getpc () - 2);
2547
m68k_setpc (m68k_getpc () - 4);
2550
dump_registers( "END ");
2553
*ad = m68k_areg (regs, reg);
2556
*ad = m68k_areg (regs, reg);
2559
*ad = m68k_areg (regs, reg);
2562
*ad = m68k_areg (regs, reg) + (uae_s32) (uae_s16) next_iword();
2565
*ad = get_disp_ea_020 (m68k_areg (regs, reg), next_iword());
2568
switch ( (uae_u8)reg ) {
2570
*ad = (uae_s32) (uae_s16) next_iword();
2576
*ad = m68k_getpc ();
2577
*ad += (uae_s32) (uae_s16) next_iword();
2580
uaecptr tmppc = m68k_getpc ();
2581
uae_u16 tmp = (uae_u16)next_iword();
2582
*ad = get_disp_ea_020 (tmppc, tmp);
2586
if( (opcode & 0xFF00) == 0xF300 ) {
2588
m68k_setpc (m68k_getpc () - 2);
2590
m68k_setpc (m68k_getpc () - 4);
2593
dump_registers( "END ");
2601
#define CONDRET(s,x) D(bug("fpp_cond %s = %d\r\n",s,(uint32)(x))); return (x)
2603
#define CONDRET(s,x) return (x)
2606
PRIVATE int FFPU fpp_cond(uae_u32 opcode, int condition)
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)
2614
switch (condition) {
2615
// Common Tests, no BSUN
2619
CONDRET("Not Equal",!Z);
2621
// IEEE Nonaware Tests, BSUN
2624
CONDRET("Greater Than",!(NotANumber || Z || N));
2627
CONDRET("Not Greater Than",NotANumber || Z || N);
2630
CONDRET("Greater Than or Equal",Z || !(NotANumber || N));
2633
CONDRET("Not Greater Than or Equal",!Z && (NotANumber || N));
2636
CONDRET("Less Than",N && !(NotANumber || Z));
2639
CONDRET("Not Less Than",NotANumber || Z || !N);
2642
CONDRET("Less Than or Equal",Z || (N && !NotANumber));
2645
CONDRET("Not Less Than or Equal",NotANumber || !(N || Z));
2648
CONDRET("Greater or Less Than",!(NotANumber || Z));
2651
CONDRET("Not Greater or Less Than",NotANumber || Z);
2653
CONDRET("Greater, Less or Equal",!NotANumber);
2656
CONDRET("Not Greater, Less or Equal",NotANumber);
2658
// IEEE Aware Tests, no BSUN
2660
CONDRET("Ordered Greater Than",!(NotANumber || Z || N));
2662
CONDRET("Unordered or Less or Equal",NotANumber || Z || N);
2664
CONDRET("Ordered Greater Than or Equal",Z || !(NotANumber || N));
2666
CONDRET("Unordered or Less Than",NotANumber || (N && !Z));
2668
CONDRET("Ordered Less Than",N && !(NotANumber || Z));
2670
CONDRET("Unordered or Greater or Equal",NotANumber || Z || !N);
2672
CONDRET("Ordered Less Than or Equal",Z || (N && !NotANumber));
2674
CONDRET("Unordered or Greater Than",NotANumber || !(N || Z));
2676
CONDRET("Ordered Greater or Less Than",!(NotANumber || Z));
2678
CONDRET("Unordered or Equal",NotANumber || Z);
2680
CONDRET("Ordered",!NotANumber);
2682
CONDRET("Unordered",NotANumber);
2684
// Miscellaneous Tests, no BSUN
2690
// Miscellaneous Tests, BSUN
2693
CONDRET("Signaling False",0);
2696
CONDRET("Signaling True",1);
2699
CONDRET("Signaling Equal",Z);
2702
CONDRET("Signaling Not Equal",!Z);
2713
PUBLIC void REGPARAM2 FFPU fpuop_dbcc(uae_u32 opcode, uae_u32 extra)
2715
uaecptr pc = (uae_u32) m68k_getpc ();
2716
uae_s32 disp = (uae_s32) (uae_s16) next_iword();
2719
D(bug("fdbcc_opp %X, %X at %08lx\r\n", (uae_u32)opcode, (uae_u32)extra, m68k_getpc ()));
2721
cc = fpp_cond(opcode, extra & 0x3f);
2723
m68k_setpc (pc - 4);
2726
int reg = opcode & 0x7;
2729
uae_u16 newv = (uae_u16)(m68k_dreg (regs, reg) & 0xffff) - 1;
2730
*((uae_u16 *)&m68k_dreg(regs, reg)) = newv;
2733
m68k_setpc (pc + disp);
2737
PUBLIC void REGPARAM2 FFPU fpuop_scc(uae_u32 opcode, uae_u32 extra)
2742
D(bug("fscc_opp %X, %X at %08lx\r\n", (uae_u32)opcode, (uae_u32)extra, m68k_getpc ()));
2744
cc = fpp_cond(opcode, extra & 0x3f);
2746
m68k_setpc (m68k_getpc () - 4);
2748
} else if ((opcode & 0x38) == 0) {
2750
m68k_dreg (regs, opcode & 7) = (m68k_dreg (regs, opcode & 7) & ~0xff) |
2753
if (get_fp_ad(opcode, &ad)) {
2754
put_byte(ad, cc ? 0xff : 0x00);
2759
PUBLIC void REGPARAM2 FFPU fpuop_trapcc(uae_u32 opcode, uaecptr oldpc)
2763
D(bug("ftrapcc_opp %X at %08lx\r\n", (uae_u32)opcode, m68k_getpc ()));
2766
#error "FIXME: _asm int 3"
2770
// This must be broken.
2771
cc = fpp_cond(opcode, opcode & 0x3f);
2777
Exception(7, oldpc - 2);
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)
2785
D(bug("fbcc_opp %X, %X at %08lx, jumpto=%X\r\n", (uae_u32)opcode, (uae_u32)extra, m68k_getpc (), extra ));
2787
cc = fpp_cond(opcode, opcode & 0x3f);
2792
if ((opcode & 0x40) == 0)
2793
extra = (uae_s32) (uae_s16) extra;
2794
m68k_setpc (pc + extra);
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)
2803
int incr = (opcode & 0x38) == 0x20 ? -1 : 1;
2806
D(bug("fsave_opp at %08lx\r\n", m68k_getpc ()));
2808
if (get_fp_ad(opcode, &ad)) {
2809
if (FPU is_integral) {
2810
// Put 4 byte 68040 IDLE frame.
2813
put_long (ad, 0x41000000);
2815
put_long (ad, 0x41000000);
2819
// Put 28 byte 68881 IDLE frame.
2821
D(bug("fsave_opp pre-decrement\r\n"));
2823
// What's this? Some BIU flags, or (incorrectly placed) command/condition?
2824
put_long (ad, 0x70000000);
2825
for (i = 0; i < 5; i++) {
2827
put_long (ad, 0x00000000);
2830
put_long (ad, 0x1f180000); // IDLE, vers 1f
2832
put_long (ad, 0x1f180000); // IDLE, vers 1f
2834
for (i = 0; i < 5; i++) {
2835
put_long (ad, 0x00000000);
2838
// What's this? Some BIU flags, or (incorrectly placed) command/condition?
2839
put_long (ad, 0x70000000);
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"));
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));
2854
PRIVATE void FFPU do_null_frestore ()
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] );
2861
FPU instruction_address = 0;
2865
x86_status_word = SW_INITIAL;
2866
x86_status_word_accrued = 0;
2867
FPU fpsr.quotient = 0;
2869
x86_control_word = CW_INITIAL;
2870
/* _asm FLDCW x86_control_word
2872
__asm__ __volatile__("fldcw %0\n\tfnclex" : : "m" (x86_control_word));
2875
// FSAVE has no pre-decrement
2876
PUBLIC void REGPARAM2 FFPU fpuop_restore(uae_u32 opcode)
2880
int incr = (opcode & 0x38) == 0x20 ? -1 : 1;
2882
D(bug("frestore_opp at %08lx\r\n", m68k_getpc ()));
2884
if (get_fp_ad(opcode, &ad)) {
2885
if (FPU is_integral) {
2888
D(bug("PROBLEM: frestore_opp incr < 0\r\n"));
2889
// this may be wrong, but it's never called.
2892
if ((d & 0xff000000) == 0) { // NULL
2893
D(bug("frestore_opp found NULL frame at %X\r\n",ad-4));
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));
2900
} else if ((d & 0x00ff0000) == 0x00600000) { // BUSY
2901
D(bug("PROBLEM: frestore_opp found BUSY frame at %X\r\n",ad-4));
2904
D(bug("PROBLEM: frestore_opp did not find a frame at %X, d=%X\r\n",ad-4,d));
2908
D(bug("frestore_opp frame at %X = %X\r\n",ad,d));
2910
if ((d & 0xff000000) == 0) { // NULL
2911
D(bug("frestore_opp found NULL frame at %X\r\n",ad-4));
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));
2918
} else if ((d & 0x00ff0000) == 0x00600000) { // BUSY
2919
D(bug("PROBLEM: frestore_opp found BUSY frame at %X\r\n",ad-4));
2922
D(bug("PROBLEM: frestore_opp did not find a frame at %X, d=%X\r\n",ad-4,d));
2928
D(bug("PROBLEM: frestore_opp incr < 0\r\n"));
2929
// this may be wrong, but it's never called.
2932
if ((d & 0xff000000) == 0) { // NULL
2934
} else if ((d & 0x00ff0000) == 0x00180000) {
2936
} else if ((d & 0x00ff0000) == 0x00380000) {
2938
} else if ((d & 0x00ff0000) == 0x00b40000) {
2943
D(bug("frestore_opp frame at %X = %X\r\n",ad,d));
2945
if ((d & 0xff000000) == 0) { // NULL
2946
D(bug("frestore_opp found NULL frame at %X\r\n",ad-4));
2948
} else if ((d & 0x00ff0000) == 0x00180000) { // IDLE
2949
D(bug("frestore_opp found IDLE frame at %X\r\n",ad-4));
2951
} else if ((d & 0x00ff0000) == 0x00380000) {// UNIMP? shouldn't it be 3C?
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));
2958
D(bug("PROBLEM: frestore_opp did not find a frame at %X, d=%X\r\n",ad-4,d));
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));
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"));
2975
/* ---------------------------- Old-style interface ---------------------------- */
2977
// #ifndef OPTIMIZED_8BIT_MEMORY_ACCESS
2978
PUBLIC void REGPARAM2 FFPU fpuop_arithmetic(uae_u32 opcode, uae_u32 extra)
2980
uae_u32 mask = (extra & 0xFC7F) | ((opcode & 0x0038) << 4);
2981
(*fpufunctbl[mask])(opcode,extra);
2986
/* ---------------------------- Illegal ---------------------------- */
2988
PRIVATE void REGPARAM2 FFPU fpuop_illg( uae_u32 opcode, uae_u32 extra )
2990
D(bug("ILLEGAL F OP 2 %X\r\n",opcode));
2992
#if I3_ON_ILLEGAL_FPU_OP
2993
#error "FIXME: asm int 3"
2997
m68k_setpc (m68k_getpc () - 4);
2999
dump_registers( "END ");
3003
/* ---------------------------- FPP -> <ea> ---------------------------- */
3005
PRIVATE void REGPARAM2 FFPU fpuop_fmove_2_ea( uae_u32 opcode, uae_u32 extra )
3007
D(bug("FMOVE -> <ea>\r\n"));
3009
if (put_fp_value (FPU registers[(extra >> 7) & 7], opcode, extra) == 0) {
3010
m68k_setpc (m68k_getpc () - 4);
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.
3024
if(sw_temp & SW_PE) {
3026
x86_status_word |= SW_PE;
3027
x86_status_word_accrued |= SW_PE;
3031
dump_registers( "END ");
3035
/* ---------------------------- CONTROL REGS -> Dreg ---------------------------- */
3037
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_none_2_Dreg( uae_u32 opcode, uae_u32 extra )
3039
D(bug("FMOVEM control(none) -> D%d\r\n", opcode & 7));
3040
dump_registers( "END ");
3043
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpiar_2_Dreg( uae_u32 opcode, uae_u32 extra )
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 ");
3050
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpsr_2_Dreg( uae_u32 opcode, uae_u32 extra )
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 ");
3057
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_2_Dreg( uae_u32 opcode, uae_u32 extra )
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 ");
3064
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpsr_fpiar_2_Dreg( uae_u32 opcode, uae_u32 extra )
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 ");
3073
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_fpiar_2_Dreg( uae_u32 opcode, uae_u32 extra )
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 ");
3082
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_fpsr_2_Dreg( uae_u32 opcode, uae_u32 extra )
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 ");
3091
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_fpsr_fpiar_2_Dreg( uae_u32 opcode, uae_u32 extra )
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 ");
3103
/* ---------------------------- Dreg -> CONTROL REGS ---------------------------- */
3105
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Dreg_2_none( uae_u32 opcode, uae_u32 extra )
3107
D(bug("FMOVEM D%d -> control(none)\r\n", opcode & 7));
3108
dump_registers( "END ");
3111
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Dreg_2_fpiar( uae_u32 opcode, uae_u32 extra )
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 ");
3118
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Dreg_2_fpsr( uae_u32 opcode, uae_u32 extra )
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 ");
3125
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Dreg_2_fpsr_fpiar( uae_u32 opcode, uae_u32 extra )
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 ");
3134
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Dreg_2_fpcr( uae_u32 opcode, uae_u32 extra )
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 ");
3141
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Dreg_2_fpcr_fpiar( uae_u32 opcode, uae_u32 extra )
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 ");
3150
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Dreg_2_fpcr_fpsr( uae_u32 opcode, uae_u32 extra )
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 ");
3159
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Dreg_2_fpcr_fpsr_fpiar( uae_u32 opcode, uae_u32 extra )
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 ");
3171
/* ---------------------------- CONTROL REGS -> Areg ---------------------------- */
3173
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_none_2_Areg( uae_u32 opcode, uae_u32 extra )
3175
D(bug("FMOVEM control(none) -> A%d\r\n", opcode & 7));
3176
dump_registers( "END ");
3179
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpiar_2_Areg( uae_u32 opcode, uae_u32 extra )
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 ");
3186
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpsr_2_Areg( uae_u32 opcode, uae_u32 extra )
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 ");
3193
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_2_Areg( uae_u32 opcode, uae_u32 extra )
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 ");
3200
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpsr_fpiar_2_Areg( uae_u32 opcode, uae_u32 extra )
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 ");
3209
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_fpiar_2_Areg( uae_u32 opcode, uae_u32 extra )
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 ");
3218
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_fpsr_2_Areg( uae_u32 opcode, uae_u32 extra )
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 ");
3227
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_fpsr_fpiar_2_Areg( uae_u32 opcode, uae_u32 extra )
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 ");
3239
/* ---------------------------- Areg -> CONTROL REGS ---------------------------- */
3241
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Areg_2_none( uae_u32 opcode, uae_u32 extra )
3243
D(bug("FMOVEM A%d -> control(none)\r\n", opcode & 7));
3244
dump_registers( "END ");
3247
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Areg_2_fpiar( uae_u32 opcode, uae_u32 extra )
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 ");
3254
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Areg_2_fpsr( uae_u32 opcode, uae_u32 extra )
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 ");
3261
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Areg_2_fpsr_fpiar( uae_u32 opcode, uae_u32 extra )
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 ");
3270
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Areg_2_fpcr( uae_u32 opcode, uae_u32 extra )
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 ");
3277
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Areg_2_fpcr_fpiar( uae_u32 opcode, uae_u32 extra )
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 ");
3286
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Areg_2_fpcr_fpsr( uae_u32 opcode, uae_u32 extra )
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 ");
3295
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Areg_2_fpcr_fpsr_fpiar( uae_u32 opcode, uae_u32 extra )
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 ");
3307
/* ---------------------------- CONTROL REGS -> --MEMORY---------------------------- */
3309
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_none_2_Mem_predecrement( uae_u32 opcode, uae_u32 extra )
3311
D(bug("FMOVEM Control regs (none) -> mem\r\n" ));
3312
dump_registers( "END ");
3315
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpiar_2_Mem_predecrement( uae_u32 opcode, uae_u32 extra )
3318
if (get_fp_ad(opcode, &ad)) {
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 ");
3327
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpsr_2_Mem_predecrement( uae_u32 opcode, uae_u32 extra )
3330
if (get_fp_ad(opcode, &ad)) {
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 ");
3339
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpsr_fpiar_2_Mem_predecrement( uae_u32 opcode, uae_u32 extra )
3342
if (get_fp_ad(opcode, &ad)) {
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 ");
3353
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_2_Mem_predecrement( uae_u32 opcode, uae_u32 extra )
3356
if (get_fp_ad(opcode, &ad)) {
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 ");
3365
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_fpiar_2_Mem_predecrement( uae_u32 opcode, uae_u32 extra )
3368
if (get_fp_ad(opcode, &ad)) {
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 ");
3379
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_fpsr_2_Mem_predecrement( uae_u32 opcode, uae_u32 extra )
3382
if (get_fp_ad(opcode, &ad)) {
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 ");
3393
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_fpsr_fpiar_2_Mem_predecrement( uae_u32 opcode, uae_u32 extra )
3396
if (get_fp_ad(opcode, &ad)) {
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 ");
3410
/* ---------------------------- CONTROL REGS -> MEMORY++ ---------------------------- */
3412
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_none_2_Mem_postincrement( uae_u32 opcode, uae_u32 extra )
3414
D(bug("FMOVEM Control regs (none) -> mem\r\n" ));
3415
dump_registers( "END ");
3418
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpiar_2_Mem_postincrement( uae_u32 opcode, uae_u32 extra )
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 ");
3429
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpsr_2_Mem_postincrement( uae_u32 opcode, uae_u32 extra )
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 ");
3440
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpsr_fpiar_2_Mem_postincrement( uae_u32 opcode, uae_u32 extra )
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 ");
3453
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_2_Mem_postincrement( uae_u32 opcode, uae_u32 extra )
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 ");
3464
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_fpiar_2_Mem_postincrement( uae_u32 opcode, uae_u32 extra )
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 ");
3477
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_fpsr_2_Mem_postincrement( uae_u32 opcode, uae_u32 extra )
3479
dump_registers( "END ");
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;
3490
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_fpsr_fpiar_2_Mem_postincrement( uae_u32 opcode, uae_u32 extra )
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 ");
3506
/* ---------------------------- CONTROL REGS -> MEMORY ---------------------------- */
3508
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_none_2_Mem( uae_u32 opcode, uae_u32 extra )
3510
D(bug("FMOVEM Control regs (none) -> mem\r\n" ));
3511
dump_registers( "END ");
3514
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpiar_2_Mem( uae_u32 opcode, uae_u32 extra )
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 ");
3524
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpsr_2_Mem( uae_u32 opcode, uae_u32 extra )
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 ");
3534
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpsr_fpiar_2_Mem( uae_u32 opcode, uae_u32 extra )
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 ");
3546
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_2_Mem( uae_u32 opcode, uae_u32 extra )
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 ");
3556
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_fpiar_2_Mem( uae_u32 opcode, uae_u32 extra )
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 ");
3568
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_fpsr_2_Mem( uae_u32 opcode, uae_u32 extra )
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 ");
3580
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_fpsr_fpiar_2_Mem( uae_u32 opcode, uae_u32 extra )
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 ");
3595
/* ---------------------------- --MEMORY -> CONTROL REGS ---------------------------- */
3597
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_none_predecrement( uae_u32 opcode, uae_u32 extra )
3599
D(bug("FMOVEM --Mem -> control(none)\r\n"));
3600
dump_registers( "END ");
3603
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpiar_predecrement( uae_u32 opcode, uae_u32 extra )
3606
if (get_fp_ad(opcode, &ad)) {
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 ");
3615
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpsr_predecrement( uae_u32 opcode, uae_u32 extra )
3618
if (get_fp_ad(opcode, &ad)) {
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 ");
3627
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpsr_fpiar_predecrement( uae_u32 opcode, uae_u32 extra )
3630
if (get_fp_ad(opcode, &ad)) {
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 ");
3641
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpcr_predecrement( uae_u32 opcode, uae_u32 extra )
3644
if (get_fp_ad(opcode, &ad)) {
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 ");
3653
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpcr_fpiar_predecrement( uae_u32 opcode, uae_u32 extra )
3656
if (get_fp_ad(opcode, &ad)) {
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 ");
3667
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpcr_fpsr_predecrement( uae_u32 opcode, uae_u32 extra )
3670
if (get_fp_ad(opcode, &ad)) {
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 ");
3681
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpcr_fpsr_fpiar_predecrement( uae_u32 opcode, uae_u32 extra )
3684
if (get_fp_ad(opcode, &ad)) {
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 ");
3698
/* ---------------------------- CONTROL REGS -> MEMORY++ ---------------------------- */
3700
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_none_postincrement( uae_u32 opcode, uae_u32 extra )
3702
D(bug("FMOVEM Mem++ -> control(none)\r\n"));
3703
dump_registers( "END ");
3706
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpiar_postincrement( uae_u32 opcode, uae_u32 extra )
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 ");
3717
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpsr_postincrement( uae_u32 opcode, uae_u32 extra )
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 ");
3728
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpsr_fpiar_postincrement( uae_u32 opcode, uae_u32 extra )
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 ");
3741
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpcr_postincrement( uae_u32 opcode, uae_u32 extra )
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 ");
3752
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpcr_fpiar_postincrement( uae_u32 opcode, uae_u32 extra )
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 ");
3765
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpcr_fpsr_postincrement( uae_u32 opcode, uae_u32 extra )
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 ");
3778
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpcr_fpsr_fpiar_postincrement( uae_u32 opcode, uae_u32 extra )
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 ");
3794
/* ---------------------------- MEMORY -> CONTROL REGS ---------------------------- */
3795
/* ---------------------------- and ---------------------------- */
3796
/* ---------------------------- IMMEDIATE -> CONTROL REGS ---------------------------- */
3798
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_none_2_Mem( uae_u32 opcode, uae_u32 extra )
3800
D(bug("FMOVEM Mem -> control(none)\r\n"));
3801
dump_registers( "END ");
3804
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpiar_2_Mem( uae_u32 opcode, uae_u32 extra )
3806
if ((opcode & 0x3f) == 0x3c) {
3807
FPU instruction_address = next_ilong();
3808
D(bug("FMOVEM #<%X> -> FPU instruction_address\r\n", FPU instruction_address));
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 ));
3816
dump_registers( "END ");
3819
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpsr_2_Mem( uae_u32 opcode, uae_u32 extra )
3821
if ((opcode & 0x3f) == 0x3c) {
3822
set_fpsr( next_ilong() );
3823
D(bug("FMOVEM #<%X> -> regs.FPU fpsr\r\n", get_fpsr()));
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() ));
3831
dump_registers( "END ");
3834
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpsr_fpiar_2_Mem( uae_u32 opcode, uae_u32 extra )
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));
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 ));
3850
dump_registers( "END ");
3853
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpcr_2_Mem( uae_u32 opcode, uae_u32 extra )
3855
if ((opcode & 0x3f) == 0x3c) {
3856
set_fpcr( next_ilong() );
3857
D(bug("FMOVEM #<%X> -> regs.FPU fpcr\r\n", get_fpcr()));
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() ));
3865
dump_registers( "END ");
3868
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpcr_fpiar_2_Mem( uae_u32 opcode, uae_u32 extra )
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));
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 ));
3884
dump_registers( "END ");
3887
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpcr_fpsr_2_Mem( uae_u32 opcode, uae_u32 extra )
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()));
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() ));
3903
dump_registers( "END ");
3906
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpcr_fpsr_fpiar_2_Mem( uae_u32 opcode, uae_u32 extra )
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));
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 ));
3926
dump_registers( "END ");
3930
/* ---------------------------- FMOVEM MEMORY -> FPP ---------------------------- */
3932
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpp_static_pred_postincrement( uae_u32 opcode, uae_u32 extra )
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;
3941
wrd3 = get_long (ad);
3943
wrd2 = get_long (ad);
3945
wrd1 = get_long (ad);
3946
to_exten_no_normalize (wrd1, wrd2, wrd3,FPU registers[reg]);
3950
m68k_areg (regs, opcode & 7) = ad;
3951
dump_registers( "END ");
3955
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpp_static_pred_predecrement( uae_u32 opcode, uae_u32 extra )
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;
3964
wrd3 = get_long (ad);
3966
wrd2 = get_long (ad);
3968
wrd1 = get_long (ad);
3969
to_exten_no_normalize (wrd1, wrd2, wrd3,FPU registers[reg]);
3973
m68k_areg (regs, opcode & 7) = ad;
3974
dump_registers( "END ");
3978
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpp_static_pred( uae_u32 opcode, uae_u32 extra )
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;
3987
wrd3 = get_long (ad);
3989
wrd2 = get_long (ad);
3991
wrd1 = get_long (ad);
3992
to_exten_no_normalize (wrd1, wrd2, wrd3,FPU registers[reg]);
3996
dump_registers( "END ");
4000
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpp_dynamic_pred_postincrement( uae_u32 opcode, uae_u32 extra )
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;
4009
wrd3 = get_long (ad);
4011
wrd2 = get_long (ad);
4013
wrd1 = get_long (ad);
4014
to_exten_no_normalize (wrd1, wrd2, wrd3,FPU registers[reg]);
4018
m68k_areg (regs, opcode & 7) = ad;
4019
dump_registers( "END ");
4023
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpp_dynamic_pred_predecrement( uae_u32 opcode, uae_u32 extra )
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;
4032
wrd3 = get_long (ad);
4034
wrd2 = get_long (ad);
4036
wrd1 = get_long (ad);
4037
to_exten_no_normalize (wrd1, wrd2, wrd3,FPU registers[reg]);
4041
m68k_areg (regs, opcode & 7) = ad;
4042
dump_registers( "END ");
4046
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpp_dynamic_pred( uae_u32 opcode, uae_u32 extra )
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;
4055
wrd3 = get_long (ad);
4057
wrd2 = get_long (ad);
4059
wrd1 = get_long (ad);
4060
to_exten_no_normalize (wrd1, wrd2, wrd3,FPU registers[reg]);
4064
dump_registers( "END ");
4068
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpp_static_postinc_postincrement( uae_u32 opcode, uae_u32 extra )
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;
4076
wrd1 = get_long (ad);
4078
wrd2 = get_long (ad);
4080
wrd3 = get_long (ad);
4082
to_exten_no_normalize (wrd1, wrd2, wrd3,FPU registers[reg]);
4086
m68k_areg (regs, opcode & 7) = ad;
4087
dump_registers( "END ");
4091
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpp_static_postinc_predecrement( uae_u32 opcode, uae_u32 extra )
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;
4099
wrd1 = get_long (ad);
4101
wrd2 = get_long (ad);
4103
wrd3 = get_long (ad);
4105
to_exten_no_normalize (wrd1, wrd2, wrd3,FPU registers[reg]);
4109
m68k_areg (regs, opcode & 7) = ad;
4110
dump_registers( "END ");
4114
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpp_static_postinc( uae_u32 opcode, uae_u32 extra )
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;
4122
wrd1 = get_long (ad);
4124
wrd2 = get_long (ad);
4126
wrd3 = get_long (ad);
4128
to_exten_no_normalize (wrd1, wrd2, wrd3,FPU registers[reg]);
4132
dump_registers( "END ");
4136
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpp_dynamic_postinc_postincrement( uae_u32 opcode, uae_u32 extra )
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;
4144
wrd1 = get_long (ad);
4146
wrd2 = get_long (ad);
4148
wrd3 = get_long (ad);
4150
to_exten_no_normalize (wrd1, wrd2, wrd3,FPU registers[reg]);
4154
m68k_areg (regs, opcode & 7) = ad;
4155
dump_registers( "END ");
4159
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpp_dynamic_postinc_predecrement( uae_u32 opcode, uae_u32 extra )
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;
4167
wrd1 = get_long (ad);
4169
wrd2 = get_long (ad);
4171
wrd3 = get_long (ad);
4173
to_exten_no_normalize (wrd1, wrd2, wrd3,FPU registers[reg]);
4177
m68k_areg (regs, opcode & 7) = ad;
4178
dump_registers( "END ");
4182
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpp_dynamic_postinc( uae_u32 opcode, uae_u32 extra )
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;
4190
wrd1 = get_long (ad);
4192
wrd2 = get_long (ad);
4194
wrd3 = get_long (ad);
4196
to_exten_no_normalize (wrd1, wrd2, wrd3,FPU registers[reg]);
4200
dump_registers( "END ");
4205
/* ---------------------------- FPP -> FMOVEM MEMORY ---------------------------- */
4207
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpp_2_Mem_static_pred_postincrement( uae_u32 opcode, uae_u32 extra )
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;
4215
from_exten(FPU registers[reg],&wrd1, &wrd2, &wrd3);
4217
put_long (ad, wrd3);
4219
put_long (ad, wrd2);
4221
put_long (ad, wrd1);
4225
m68k_areg (regs, opcode & 7) = ad;
4226
dump_registers( "END ");
4229
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpp_2_Mem_static_pred_predecrement( uae_u32 opcode, uae_u32 extra )
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;
4237
from_exten(FPU registers[reg],&wrd1, &wrd2, &wrd3);
4239
put_long (ad, wrd3);
4241
put_long (ad, wrd2);
4243
put_long (ad, wrd1);
4247
m68k_areg (regs, opcode & 7) = ad;
4248
dump_registers( "END ");
4251
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpp_2_Mem_static_pred( uae_u32 opcode, uae_u32 extra )
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;
4259
from_exten(FPU registers[reg],&wrd1, &wrd2, &wrd3);
4261
put_long (ad, wrd3);
4263
put_long (ad, wrd2);
4265
put_long (ad, wrd1);
4269
dump_registers( "END ");
4272
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpp_2_Mem_dynamic_pred_postincrement( uae_u32 opcode, uae_u32 extra )
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;
4280
from_exten(FPU registers[reg],&wrd1, &wrd2, &wrd3);
4282
put_long (ad, wrd3);
4284
put_long (ad, wrd2);
4286
put_long (ad, wrd1);
4290
m68k_areg (regs, opcode & 7) = ad;
4291
dump_registers( "END ");
4294
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpp_2_Mem_dynamic_pred_predecrement( uae_u32 opcode, uae_u32 extra )
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;
4302
from_exten(FPU registers[reg],&wrd1, &wrd2, &wrd3);
4304
put_long (ad, wrd3);
4306
put_long (ad, wrd2);
4308
put_long (ad, wrd1);
4312
m68k_areg (regs, opcode & 7) = ad;
4313
dump_registers( "END ");
4316
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpp_2_Mem_dynamic_pred( uae_u32 opcode, uae_u32 extra )
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;
4324
from_exten(FPU registers[reg],&wrd1, &wrd2, &wrd3);
4326
put_long (ad, wrd3);
4328
put_long (ad, wrd2);
4330
put_long (ad, wrd1);
4334
dump_registers( "END ");
4337
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpp_2_Mem_static_postinc_postincrement( uae_u32 opcode, uae_u32 extra )
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;
4345
from_exten(FPU registers[reg],&wrd1, &wrd2, &wrd3);
4346
put_long (ad, wrd1);
4348
put_long (ad, wrd2);
4350
put_long (ad, wrd3);
4355
m68k_areg (regs, opcode & 7) = ad;
4356
dump_registers( "END ");
4359
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpp_2_Mem_static_postinc_predecrement( uae_u32 opcode, uae_u32 extra )
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;
4367
from_exten(FPU registers[reg],&wrd1, &wrd2, &wrd3);
4368
put_long (ad, wrd1);
4370
put_long (ad, wrd2);
4372
put_long (ad, wrd3);
4377
m68k_areg (regs, opcode & 7) = ad;
4378
dump_registers( "END ");
4381
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpp_2_Mem_static_postinc( uae_u32 opcode, uae_u32 extra )
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;
4389
from_exten(FPU registers[reg],&wrd1, &wrd2, &wrd3);
4390
put_long (ad, wrd1);
4392
put_long (ad, wrd2);
4394
put_long (ad, wrd3);
4399
dump_registers( "END ");
4402
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpp_2_Mem_dynamic_postinc_postincrement( uae_u32 opcode, uae_u32 extra )
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;
4410
from_exten(FPU registers[reg],&wrd1, &wrd2, &wrd3);
4411
put_long (ad, wrd1);
4413
put_long (ad, wrd2);
4415
put_long (ad, wrd3);
4420
m68k_areg (regs, opcode & 7) = ad;
4421
dump_registers( "END ");
4424
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpp_2_Mem_dynamic_postinc_predecrement( uae_u32 opcode, uae_u32 extra )
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;
4432
from_exten(FPU registers[reg],&wrd1, &wrd2, &wrd3);
4433
put_long (ad, wrd1);
4435
put_long (ad, wrd2);
4437
put_long (ad, wrd3);
4442
m68k_areg (regs, opcode & 7) = ad;
4443
dump_registers( "END ");
4446
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpp_2_Mem_dynamic_postinc( uae_u32 opcode, uae_u32 extra )
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;
4454
from_exten(FPU registers[reg],&wrd1, &wrd2, &wrd3);
4455
put_long (ad, wrd1);
4457
put_long (ad, wrd2);
4459
put_long (ad, wrd3);
4464
dump_registers( "END ");
4469
/* ---------------------------- FMOVEM CONSTANT ROM -> FPP ---------------------------- */
4471
PRIVATE void REGPARAM2 FFPU fpuop_do_fldpi( uae_u32 opcode, uae_u32 extra )
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 ");
4479
PRIVATE void REGPARAM2 FFPU fpuop_do_fldlg2( uae_u32 opcode, uae_u32 extra )
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 ");
4487
PRIVATE void REGPARAM2 FFPU fpuop_do_load_const_e( uae_u32 opcode, uae_u32 extra )
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 ");
4495
PRIVATE void REGPARAM2 FFPU fpuop_do_fldl2e( uae_u32 opcode, uae_u32 extra )
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 ");
4503
PRIVATE void REGPARAM2 FFPU fpuop_do_load_const_log_10_e( uae_u32 opcode, uae_u32 extra )
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 ");
4511
PRIVATE void REGPARAM2 FFPU fpuop_do_fldz( uae_u32 opcode, uae_u32 extra )
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 ");
4519
PRIVATE void REGPARAM2 FFPU fpuop_do_fldln2( uae_u32 opcode, uae_u32 extra )
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 ");
4527
PRIVATE void REGPARAM2 FFPU fpuop_do_load_const_ln_10( uae_u32 opcode, uae_u32 extra )
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 ");
4535
PRIVATE void REGPARAM2 FFPU fpuop_do_fld1( uae_u32 opcode, uae_u32 extra )
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 ");
4543
PRIVATE void REGPARAM2 FFPU fpuop_do_load_const_1e1( uae_u32 opcode, uae_u32 extra )
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 ");
4551
PRIVATE void REGPARAM2 FFPU fpuop_do_load_const_1e2( uae_u32 opcode, uae_u32 extra )
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 ");
4559
PRIVATE void REGPARAM2 FFPU fpuop_do_load_const_1e4( uae_u32 opcode, uae_u32 extra )
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 ");
4567
PRIVATE void REGPARAM2 FFPU fpuop_do_load_const_1e8( uae_u32 opcode, uae_u32 extra )
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 ");
4575
PRIVATE void REGPARAM2 FFPU fpuop_do_load_const_1e16( uae_u32 opcode, uae_u32 extra )
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 ");
4583
PRIVATE void REGPARAM2 FFPU fpuop_do_load_const_1e32( uae_u32 opcode, uae_u32 extra )
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 ");
4591
PRIVATE void REGPARAM2 FFPU fpuop_do_load_const_1e64( uae_u32 opcode, uae_u32 extra )
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 ");
4599
PRIVATE void REGPARAM2 FFPU fpuop_do_load_const_1e128( uae_u32 opcode, uae_u32 extra )
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 ");
4607
PRIVATE void REGPARAM2 FFPU fpuop_do_load_const_1e256( uae_u32 opcode, uae_u32 extra )
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 ");
4615
PRIVATE void REGPARAM2 FFPU fpuop_do_load_const_1e512( uae_u32 opcode, uae_u32 extra )
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 ");
4623
PRIVATE void REGPARAM2 FFPU fpuop_do_load_const_1e1024( uae_u32 opcode, uae_u32 extra )
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 ");
4631
PRIVATE void REGPARAM2 FFPU fpuop_do_load_const_1e2048( uae_u32 opcode, uae_u32 extra )
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 ");
4639
PRIVATE void REGPARAM2 FFPU fpuop_do_load_const_1e4096( uae_u32 opcode, uae_u32 extra )
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 ");
4648
/* ---------------------------- ALU ---------------------------- */
4650
PRIVATE void REGPARAM2 FFPU fpuop_do_fmove( uae_u32 opcode, uae_u32 extra )
4652
int reg = (extra >> 7) & 7;
4654
if (get_fp_value (opcode, extra, src) == 0) {
4655
m68k_setpc (m68k_getpc () - 4);
4657
dump_registers( "END ");
4660
D(bug("FMOVE %s\r\n",etos(src)));
4661
do_fmove( FPU registers[reg], src );
4663
dump_registers( "END ");
4666
PRIVATE void REGPARAM2 FFPU fpuop_do_fint( uae_u32 opcode, uae_u32 extra )
4668
int reg = (extra >> 7) & 7;
4670
if (get_fp_value (opcode, extra, src) == 0) {
4671
m68k_setpc (m68k_getpc () - 4);
4673
dump_registers( "END ");
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 ");
4681
PRIVATE void REGPARAM2 FFPU fpuop_do_fsinh( uae_u32 opcode, uae_u32 extra )
4683
int reg = (extra >> 7) & 7;
4685
if (get_fp_value (opcode, extra, src) == 0) {
4686
m68k_setpc (m68k_getpc () - 4);
4688
dump_registers( "END ");
4691
D(bug("FSINH %s\r\n",etos(src)));
4692
do_fsinh( FPU registers[reg], src );
4694
dump_registers( "END ");
4697
PRIVATE void REGPARAM2 FFPU fpuop_do_fintrz( uae_u32 opcode, uae_u32 extra )
4699
int reg = (extra >> 7) & 7;
4701
if (get_fp_value (opcode, extra, src) == 0) {
4702
m68k_setpc (m68k_getpc () - 4);
4704
dump_registers( "END ");
4707
D(bug("FINTRZ %s\r\n",etos(src)));
4708
do_fintrz( FPU registers[reg], src );
4709
dump_registers( "END ");
4712
PRIVATE void REGPARAM2 FFPU fpuop_do_fsqrt( uae_u32 opcode, uae_u32 extra )
4714
int reg = (extra >> 7) & 7;
4716
if (get_fp_value (opcode, extra, src) == 0) {
4717
m68k_setpc (m68k_getpc () - 4);
4719
dump_registers( "END ");
4722
D(bug("FSQRT %s\r\n",etos(src)));
4723
do_fsqrt( FPU registers[reg], src );
4724
dump_registers( "END ");
4727
PRIVATE void REGPARAM2 FFPU fpuop_do_flognp1( uae_u32 opcode, uae_u32 extra )
4729
int reg = (extra >> 7) & 7;
4731
if (get_fp_value (opcode, extra, src) == 0) {
4732
m68k_setpc (m68k_getpc () - 4);
4734
dump_registers( "END ");
4737
D(bug("FLOGNP1 %s\r\n",etos(src)));
4738
do_flognp1( FPU registers[reg], src );
4740
dump_registers( "END ");
4743
PRIVATE void REGPARAM2 FFPU fpuop_do_fetoxm1( uae_u32 opcode, uae_u32 extra )
4745
int reg = (extra >> 7) & 7;
4747
if (get_fp_value (opcode, extra, src) == 0) {
4748
m68k_setpc (m68k_getpc () - 4);
4750
dump_registers( "END ");
4753
D(bug("FETOXM1 %s\r\n",etos(src)));
4754
do_fetoxm1( FPU registers[reg], src );
4756
dump_registers( "END ");
4759
PRIVATE void REGPARAM2 FFPU fpuop_do_ftanh( uae_u32 opcode, uae_u32 extra )
4761
int reg = (extra >> 7) & 7;
4763
if (get_fp_value (opcode, extra, src) == 0) {
4764
m68k_setpc (m68k_getpc () - 4);
4766
dump_registers( "END ");
4769
D(bug("FTANH %s\r\n",etos(src)));
4770
do_ftanh( FPU registers[reg], src );
4772
dump_registers( "END ");
4775
PRIVATE void REGPARAM2 FFPU fpuop_do_fatan( uae_u32 opcode, uae_u32 extra )
4777
int reg = (extra >> 7) & 7;
4779
if (get_fp_value (opcode, extra, src) == 0) {
4780
m68k_setpc (m68k_getpc () - 4);
4782
dump_registers( "END ");
4785
D(bug("FATAN %s\r\n",etos(src)));
4786
do_fatan( FPU registers[reg], src );
4788
dump_registers( "END ");
4791
PRIVATE void REGPARAM2 FFPU fpuop_do_fasin( uae_u32 opcode, uae_u32 extra )
4793
int reg = (extra >> 7) & 7;
4795
if (get_fp_value (opcode, extra, src) == 0) {
4796
m68k_setpc (m68k_getpc () - 4);
4798
dump_registers( "END ");
4801
D(bug("FASIN %s\r\n",etos(src)));
4802
do_fasin( FPU registers[reg], src );
4804
dump_registers( "END ");
4807
PRIVATE void REGPARAM2 FFPU fpuop_do_fatanh( uae_u32 opcode, uae_u32 extra )
4809
int reg = (extra >> 7) & 7;
4811
if (get_fp_value (opcode, extra, src) == 0) {
4812
m68k_setpc (m68k_getpc () - 4);
4814
dump_registers( "END ");
4817
D(bug("FATANH %s\r\n",etos(src)));
4818
do_fatanh( FPU registers[reg], src );
4820
dump_registers( "END ");
4823
PRIVATE void REGPARAM2 FFPU fpuop_do_fsin( uae_u32 opcode, uae_u32 extra )
4825
int reg = (extra >> 7) & 7;
4827
if (get_fp_value (opcode, extra, src) == 0) {
4828
m68k_setpc (m68k_getpc () - 4);
4830
dump_registers( "END ");
4833
D(bug("FSIN %s\r\n",etos(src)));
4834
do_fsin( FPU registers[reg], src );
4835
dump_registers( "END ");
4838
PRIVATE void REGPARAM2 FFPU fpuop_do_ftan( uae_u32 opcode, uae_u32 extra )
4840
int reg = (extra >> 7) & 7;
4842
if (get_fp_value (opcode, extra, src) == 0) {
4843
m68k_setpc (m68k_getpc () - 4);
4845
dump_registers( "END ");
4848
D(bug("FTAN %s\r\n",etos(src)));
4849
do_ftan( FPU registers[reg], src );
4850
dump_registers( "END ");
4853
PRIVATE void REGPARAM2 FFPU fpuop_do_fetox( uae_u32 opcode, uae_u32 extra )
4855
int reg = (extra >> 7) & 7;
4857
if (get_fp_value (opcode, extra, src) == 0) {
4858
m68k_setpc (m68k_getpc () - 4);
4860
dump_registers( "END ");
4863
D(bug("FETOX %s\r\n",etos(src)));
4864
do_fetox( FPU registers[reg], src );
4866
dump_registers( "END ");
4869
PRIVATE void REGPARAM2 FFPU fpuop_do_ftwotox( uae_u32 opcode, uae_u32 extra )
4871
int reg = (extra >> 7) & 7;
4873
if (get_fp_value (opcode, extra, src) == 0) {
4874
m68k_setpc (m68k_getpc () - 4);
4876
dump_registers( "END ");
4879
D(bug("FTWOTOX %s\r\n",etos(src)));
4880
do_ftwotox( FPU registers[reg], src );
4882
dump_registers( "END ");
4885
PRIVATE void REGPARAM2 FFPU fpuop_do_ftentox( uae_u32 opcode, uae_u32 extra )
4887
int reg = (extra >> 7) & 7;
4889
if (get_fp_value (opcode, extra, src) == 0) {
4890
m68k_setpc (m68k_getpc () - 4);
4892
dump_registers( "END ");
4895
D(bug("FTENTOX %s\r\n",etos(src)));
4896
do_ftentox( FPU registers[reg], src );
4898
dump_registers( "END ");
4901
PRIVATE void REGPARAM2 FFPU fpuop_do_flogn( uae_u32 opcode, uae_u32 extra )
4903
int reg = (extra >> 7) & 7;
4905
if (get_fp_value (opcode, extra, src) == 0) {
4906
m68k_setpc (m68k_getpc () - 4);
4908
dump_registers( "END ");
4911
D(bug("FLOGN %s\r\n",etos(src)));
4912
do_flogn( FPU registers[reg], src );
4914
dump_registers( "END ");
4917
PRIVATE void REGPARAM2 FFPU fpuop_do_flog10( uae_u32 opcode, uae_u32 extra )
4919
int reg = (extra >> 7) & 7;
4921
if (get_fp_value (opcode, extra, src) == 0) {
4922
m68k_setpc (m68k_getpc () - 4);
4924
dump_registers( "END ");
4927
D(bug("FLOG10 %s\r\n",etos(src)));
4928
do_flog10( FPU registers[reg], src );
4930
dump_registers( "END ");
4933
PRIVATE void REGPARAM2 FFPU fpuop_do_flog2( uae_u32 opcode, uae_u32 extra )
4935
int reg = (extra >> 7) & 7;
4937
if (get_fp_value (opcode, extra, src) == 0) {
4938
m68k_setpc (m68k_getpc () - 4);
4940
dump_registers( "END ");
4943
D(bug("FLOG2 %s\r\n",etos(src)));
4944
do_flog2( FPU registers[reg], src );
4946
dump_registers( "END ");
4949
PRIVATE void REGPARAM2 FFPU fpuop_do_fabs( uae_u32 opcode, uae_u32 extra )
4951
int reg = (extra >> 7) & 7;
4953
if (get_fp_value (opcode, extra, src) == 0) {
4954
m68k_setpc (m68k_getpc () - 4);
4956
dump_registers( "END ");
4959
D(bug("FABS %s\r\n",etos(src)));
4960
do_fabs( FPU registers[reg], src );
4961
dump_registers( "END ");
4964
PRIVATE void REGPARAM2 FFPU fpuop_do_fcosh( uae_u32 opcode, uae_u32 extra )
4966
int reg = (extra >> 7) & 7;
4968
if (get_fp_value (opcode, extra, src) == 0) {
4969
m68k_setpc (m68k_getpc () - 4);
4971
dump_registers( "END ");
4974
D(bug("FCOSH %s\r\n",etos(src)));
4975
do_fcosh( FPU registers[reg], src );
4977
dump_registers( "END ");
4980
PRIVATE void REGPARAM2 FFPU fpuop_do_fneg( uae_u32 opcode, uae_u32 extra )
4982
int reg = (extra >> 7) & 7;
4984
if (get_fp_value (opcode, extra, src) == 0) {
4985
m68k_setpc (m68k_getpc () - 4);
4987
dump_registers( "END ");
4990
D(bug("FNEG %s\r\n",etos(src)));
4991
do_fneg( FPU registers[reg], src );
4992
dump_registers( "END ");
4995
PRIVATE void REGPARAM2 FFPU fpuop_do_facos( uae_u32 opcode, uae_u32 extra )
4997
int reg = (extra >> 7) & 7;
4999
if (get_fp_value (opcode, extra, src) == 0) {
5000
m68k_setpc (m68k_getpc () - 4);
5002
dump_registers( "END ");
5005
D(bug("FACOS %s\r\n",etos(src)));
5006
do_facos( FPU registers[reg], src );
5008
dump_registers( "END ");
5011
PRIVATE void REGPARAM2 FFPU fpuop_do_fcos( uae_u32 opcode, uae_u32 extra )
5013
int reg = (extra >> 7) & 7;
5015
if (get_fp_value (opcode, extra, src) == 0) {
5016
m68k_setpc (m68k_getpc () - 4);
5018
dump_registers( "END ");
5021
D(bug("FCOS %s\r\n",etos(src)));
5022
do_fcos( FPU registers[reg], src );
5023
dump_registers( "END ");
5026
PRIVATE void REGPARAM2 FFPU fpuop_do_fgetexp( uae_u32 opcode, uae_u32 extra )
5028
int reg = (extra >> 7) & 7;
5030
if (get_fp_value (opcode, extra, src) == 0) {
5031
m68k_setpc (m68k_getpc () - 4);
5033
dump_registers( "END ");
5036
D(bug("FGETEXP %s\r\n",etos(src)));
5038
if( IS_INFINITY(src) ) {
5039
MAKE_NAN( FPU registers[reg] );
5040
do_ftst( FPU registers[reg] );
5041
x86_status_word |= SW_IE;
5043
do_fgetexp( FPU registers[reg], src );
5045
dump_registers( "END ");
5048
PRIVATE void REGPARAM2 FFPU fpuop_do_fgetman( uae_u32 opcode, uae_u32 extra )
5050
int reg = (extra >> 7) & 7;
5052
if (get_fp_value (opcode, extra, src) == 0) {
5053
m68k_setpc (m68k_getpc () - 4);
5055
dump_registers( "END ");
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;
5064
do_fgetman( FPU registers[reg], src );
5066
dump_registers( "END ");
5069
PRIVATE void REGPARAM2 FFPU fpuop_do_fdiv( uae_u32 opcode, uae_u32 extra )
5071
int reg = (extra >> 7) & 7;
5073
if (get_fp_value (opcode, extra, src) == 0) {
5074
m68k_setpc (m68k_getpc () - 4);
5076
dump_registers( "END ");
5079
D(bug("FDIV %s\r\n",etos(src)));
5080
do_fdiv( FPU registers[reg], src );
5081
dump_registers( "END ");
5084
PRIVATE void REGPARAM2 FFPU fpuop_do_fmod( uae_u32 opcode, uae_u32 extra )
5086
int reg = (extra >> 7) & 7;
5088
if (get_fp_value (opcode, extra, src) == 0) {
5089
m68k_setpc (m68k_getpc () - 4);
5091
dump_registers( "END ");
5094
D(bug("FMOD %s\r\n",etos(src)));
5096
#if USE_3_BIT_QUOTIENT
5097
do_fmod( FPU registers[reg], src );
5099
if( (x86_control_word & X86_ROUNDING_MODE) == CW_RC_ZERO ) {
5100
do_fmod_dont_set_cw( FPU registers[reg], src );
5102
do_fmod( FPU registers[reg], src );
5105
dump_registers( "END ");
5108
PRIVATE void REGPARAM2 FFPU fpuop_do_frem( uae_u32 opcode, uae_u32 extra )
5110
int reg = (extra >> 7) & 7;
5112
if (get_fp_value (opcode, extra, src) == 0) {
5113
m68k_setpc (m68k_getpc () - 4);
5115
dump_registers( "END ");
5118
D(bug("FREM %s\r\n",etos(src)));
5119
#if USE_3_BIT_QUOTIENT
5120
do_frem( FPU registers[reg], src );
5122
if( (x86_control_word & X86_ROUNDING_MODE) == CW_RC_NEAR ) {
5123
do_frem_dont_set_cw( FPU registers[reg], src );
5125
do_frem( FPU registers[reg], src );
5128
dump_registers( "END ");
5131
PRIVATE void REGPARAM2 FFPU fpuop_do_fadd( uae_u32 opcode, uae_u32 extra )
5133
int reg = (extra >> 7) & 7;
5135
if (get_fp_value (opcode, extra, src) == 0) {
5136
m68k_setpc (m68k_getpc () - 4);
5138
dump_registers( "END ");
5141
D(bug("FADD %s\r\n",etos(src)));
5142
do_fadd( FPU registers[reg], src );
5143
dump_registers( "END ");
5146
PRIVATE void REGPARAM2 FFPU fpuop_do_fmul( uae_u32 opcode, uae_u32 extra )
5148
int reg = (extra >> 7) & 7;
5150
if (get_fp_value (opcode, extra, src) == 0) {
5151
m68k_setpc (m68k_getpc () - 4);
5153
dump_registers( "END ");
5156
D(bug("FMUL %s\r\n",etos(src)));
5157
do_fmul( FPU registers[reg], src );
5158
dump_registers( "END ");
5161
PRIVATE void REGPARAM2 FFPU fpuop_do_fsgldiv( uae_u32 opcode, uae_u32 extra )
5163
int reg = (extra >> 7) & 7;
5165
if (get_fp_value (opcode, extra, src) == 0) {
5166
m68k_setpc (m68k_getpc () - 4);
5168
dump_registers( "END ");
5171
D(bug("FSGLDIV %s\r\n",etos(src)));
5172
do_fsgldiv( FPU registers[reg], src );
5173
dump_registers( "END ");
5176
PRIVATE void REGPARAM2 FFPU fpuop_do_fscale( uae_u32 opcode, uae_u32 extra )
5178
int reg = (extra >> 7) & 7;
5180
if (get_fp_value (opcode, extra, src) == 0) {
5181
m68k_setpc (m68k_getpc () - 4);
5183
dump_registers( "END ");
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;
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 );
5196
dump_registers( "END ");
5199
PRIVATE void REGPARAM2 FFPU fpuop_do_fsglmul( uae_u32 opcode, uae_u32 extra )
5201
int reg = (extra >> 7) & 7;
5203
if (get_fp_value (opcode, extra, src) == 0) {
5204
m68k_setpc (m68k_getpc () - 4);
5206
dump_registers( "END ");
5209
D(bug("FSGLMUL %s\r\n",etos(src)));
5210
do_fsglmul( FPU registers[reg], src );
5211
dump_registers( "END ");
5214
PRIVATE void REGPARAM2 FFPU fpuop_do_fsub( uae_u32 opcode, uae_u32 extra )
5216
int reg = (extra >> 7) & 7;
5218
if (get_fp_value (opcode, extra, src) == 0) {
5219
m68k_setpc (m68k_getpc () - 4);
5221
dump_registers( "END ");
5224
D(bug("FSUB %s\r\n",etos(src)));
5225
do_fsub( FPU registers[reg], src );
5226
dump_registers( "END ");
5229
PRIVATE void REGPARAM2 FFPU fpuop_do_fsincos( uae_u32 opcode, uae_u32 extra )
5231
int reg = (extra >> 7) & 7;
5233
if (get_fp_value (opcode, extra, src) == 0) {
5234
m68k_setpc (m68k_getpc () - 4);
5236
dump_registers( "END ");
5239
D(bug("FSINCOS %s\r\n",etos(src)));
5240
do_fsincos( FPU registers[reg], FPU registers[extra & 7], src );
5241
dump_registers( "END ");
5244
PRIVATE void REGPARAM2 FFPU fpuop_do_fcmp( uae_u32 opcode, uae_u32 extra )
5246
int reg = (extra >> 7) & 7;
5248
if (get_fp_value (opcode, extra, src) == 0) {
5249
m68k_setpc (m68k_getpc () - 4);
5251
dump_registers( "END ");
5254
D(bug("FCMP %s\r\n",etos(src)));
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"));
5262
x86_status_word = SW_FINITE;
5263
D(bug("X FCMP -INF -> None\r\n"));
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"));
5270
x86_status_word = SW_N;
5271
D(bug("X FCMP +INF -> N\r\n"));
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"));
5279
x86_status_word = SW_FINITE;
5280
D(bug("+INF FCMP X -> None\r\n"));
5283
do_fcmp( FPU registers[reg], src );
5286
dump_registers( "END ");
5289
PRIVATE void REGPARAM2 FFPU fpuop_do_ftst( uae_u32 opcode, uae_u32 extra )
5291
int reg = (extra >> 7) & 7;
5293
if (get_fp_value (opcode, extra, src) == 0) {
5294
m68k_setpc (m68k_getpc () - 4);
5296
dump_registers( "END ");
5299
D(bug("FTST %s\r\n",etos(src)));
5302
dump_registers( "END ");
5307
/* ---------------------------- SETUP TABLES ---------------------------- */
5309
PRIVATE void FFPU build_fpp_opp_lookup_table ()
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;
5316
switch ((extra >> 13) & 0x7) {
5318
fpufunctbl[mask] = & FFPU fpuop_fmove_2_ea;
5322
if ((opcode & 0x38) == 0) {
5323
if (extra & 0x2000) { // dr bit
5324
switch( extra & 0x1C00 ) {
5326
fpufunctbl[mask] = & FFPU fpuop_fmovem_none_2_Dreg;
5329
fpufunctbl[mask] = & FFPU fpuop_fmovem_fpiar_2_Dreg;
5332
fpufunctbl[mask] = & FFPU fpuop_fmovem_fpsr_2_Dreg;
5335
fpufunctbl[mask] = & FFPU fpuop_fmovem_fpsr_fpiar_2_Dreg;
5338
fpufunctbl[mask] = & FFPU fpuop_fmovem_fpcr_2_Dreg;
5341
fpufunctbl[mask] = & FFPU fpuop_fmovem_fpcr_fpiar_2_Dreg;
5344
fpufunctbl[mask] = & FFPU fpuop_fmovem_fpcr_fpsr_2_Dreg;
5347
fpufunctbl[mask] = & FFPU fpuop_fmovem_fpcr_fpsr_fpiar_2_Dreg;
5351
switch( extra & 0x1C00 ) {
5353
fpufunctbl[mask] = & FFPU fpuop_fmovem_Dreg_2_none;
5356
fpufunctbl[mask] = & FFPU fpuop_fmovem_Dreg_2_fpiar;
5359
fpufunctbl[mask] = & FFPU fpuop_fmovem_Dreg_2_fpsr;
5362
fpufunctbl[mask] = & FFPU fpuop_fmovem_Dreg_2_fpsr_fpiar;
5365
fpufunctbl[mask] = & FFPU fpuop_fmovem_Dreg_2_fpcr;
5368
fpufunctbl[mask] = & FFPU fpuop_fmovem_Dreg_2_fpcr_fpiar;
5371
fpufunctbl[mask] = & FFPU fpuop_fmovem_Dreg_2_fpcr_fpsr;
5374
fpufunctbl[mask] = & FFPU fpuop_fmovem_Dreg_2_fpcr_fpsr_fpiar;
5378
} else if ((opcode & 0x38) == 8) {
5379
if (extra & 0x2000) { // dr bit
5380
switch( extra & 0x1C00 ) {
5382
fpufunctbl[mask] = & FFPU fpuop_fmovem_none_2_Areg;
5385
fpufunctbl[mask] = & FFPU fpuop_fmovem_fpiar_2_Areg;
5388
fpufunctbl[mask] = & FFPU fpuop_fmovem_fpsr_2_Areg;
5391
fpufunctbl[mask] = & FFPU fpuop_fmovem_fpsr_fpiar_2_Areg;
5394
fpufunctbl[mask] = & FFPU fpuop_fmovem_fpcr_2_Areg;
5397
fpufunctbl[mask] = & FFPU fpuop_fmovem_fpcr_fpiar_2_Areg;
5400
fpufunctbl[mask] = & FFPU fpuop_fmovem_fpcr_fpsr_2_Areg;
5403
fpufunctbl[mask] = & FFPU fpuop_fmovem_fpcr_fpsr_fpiar_2_Areg;
5407
switch( extra & 0x1C00 ) {
5409
fpufunctbl[mask] = & FFPU fpuop_fmovem_Areg_2_none;
5412
fpufunctbl[mask] = & FFPU fpuop_fmovem_Areg_2_fpiar;
5415
fpufunctbl[mask] = & FFPU fpuop_fmovem_Areg_2_fpsr;
5418
fpufunctbl[mask] = & FFPU fpuop_fmovem_Areg_2_fpsr_fpiar;
5421
fpufunctbl[mask] = & FFPU fpuop_fmovem_Areg_2_fpcr;
5424
fpufunctbl[mask] = & FFPU fpuop_fmovem_Areg_2_fpcr_fpiar;
5427
fpufunctbl[mask] = & FFPU fpuop_fmovem_Areg_2_fpcr_fpsr;
5430
fpufunctbl[mask] = & FFPU fpuop_fmovem_Areg_2_fpcr_fpsr_fpiar;
5434
} else if (extra & 0x2000) {
5435
if ((opcode & 0x38) == 0x20) {
5436
switch( extra & 0x1C00 ) {
5438
fpufunctbl[mask] = & FFPU fpuop_fmovem_none_2_Mem_predecrement;
5441
fpufunctbl[mask] = & FFPU fpuop_fmovem_fpiar_2_Mem_predecrement;
5444
fpufunctbl[mask] = & FFPU fpuop_fmovem_fpsr_2_Mem_predecrement;
5447
fpufunctbl[mask] = & FFPU fpuop_fmovem_fpsr_fpiar_2_Mem_predecrement;
5450
fpufunctbl[mask] = & FFPU fpuop_fmovem_fpcr_2_Mem_predecrement;
5453
fpufunctbl[mask] = & FFPU fpuop_fmovem_fpcr_fpiar_2_Mem_predecrement;
5456
fpufunctbl[mask] = & FFPU fpuop_fmovem_fpcr_fpsr_2_Mem_predecrement;
5459
fpufunctbl[mask] = & FFPU fpuop_fmovem_fpcr_fpsr_fpiar_2_Mem_predecrement;
5462
} else if ((opcode & 0x38) == 0x18) {
5463
switch( extra & 0x1C00 ) {
5465
fpufunctbl[mask] = & FFPU fpuop_fmovem_none_2_Mem_postincrement;
5468
fpufunctbl[mask] = & FFPU fpuop_fmovem_fpiar_2_Mem_postincrement;
5471
fpufunctbl[mask] = & FFPU fpuop_fmovem_fpsr_2_Mem_postincrement;
5474
fpufunctbl[mask] = & FFPU fpuop_fmovem_fpsr_fpiar_2_Mem_postincrement;
5477
fpufunctbl[mask] = & FFPU fpuop_fmovem_fpcr_2_Mem_postincrement;
5480
fpufunctbl[mask] = & FFPU fpuop_fmovem_fpcr_fpiar_2_Mem_postincrement;
5483
fpufunctbl[mask] = & FFPU fpuop_fmovem_fpcr_fpsr_2_Mem_postincrement;
5486
fpufunctbl[mask] = & FFPU fpuop_fmovem_fpcr_fpsr_fpiar_2_Mem_postincrement;
5490
switch( extra & 0x1C00 ) {
5492
fpufunctbl[mask] = & FFPU fpuop_fmovem_none_2_Mem;
5495
fpufunctbl[mask] = & FFPU fpuop_fmovem_fpiar_2_Mem;
5498
fpufunctbl[mask] = & FFPU fpuop_fmovem_fpsr_2_Mem;
5501
fpufunctbl[mask] = & FFPU fpuop_fmovem_fpsr_fpiar_2_Mem;
5504
fpufunctbl[mask] = & FFPU fpuop_fmovem_fpcr_2_Mem;
5507
fpufunctbl[mask] = & FFPU fpuop_fmovem_fpcr_fpiar_2_Mem;
5510
fpufunctbl[mask] = & FFPU fpuop_fmovem_fpcr_fpsr_2_Mem;
5513
fpufunctbl[mask] = & FFPU fpuop_fmovem_fpcr_fpsr_fpiar_2_Mem;
5518
if ((opcode & 0x38) == 0x20) {
5519
switch( extra & 0x1C00 ) {
5521
fpufunctbl[mask] = & FFPU fpuop_fmovem_Mem_2_none_predecrement;
5524
fpufunctbl[mask] = & FFPU fpuop_fmovem_Mem_2_fpiar_predecrement;
5527
fpufunctbl[mask] = & FFPU fpuop_fmovem_Mem_2_fpsr_predecrement;
5530
fpufunctbl[mask] = & FFPU fpuop_fmovem_Mem_2_fpsr_fpiar_predecrement;
5533
fpufunctbl[mask] = & FFPU fpuop_fmovem_Mem_2_fpcr_predecrement;
5536
fpufunctbl[mask] = & FFPU fpuop_fmovem_Mem_2_fpcr_fpiar_predecrement;
5539
fpufunctbl[mask] = & FFPU fpuop_fmovem_Mem_2_fpcr_fpsr_predecrement;
5542
fpufunctbl[mask] = & FFPU fpuop_fmovem_Mem_2_fpcr_fpsr_fpiar_predecrement;
5545
} else if ((opcode & 0x38) == 0x18) {
5546
switch( extra & 0x1C00 ) {
5548
fpufunctbl[mask] = & FFPU fpuop_fmovem_Mem_2_none_postincrement;
5551
fpufunctbl[mask] = & FFPU fpuop_fmovem_Mem_2_fpiar_postincrement;
5554
fpufunctbl[mask] = & FFPU fpuop_fmovem_Mem_2_fpsr_postincrement;
5557
fpufunctbl[mask] = & FFPU fpuop_fmovem_Mem_2_fpsr_fpiar_postincrement;
5560
fpufunctbl[mask] = & FFPU fpuop_fmovem_Mem_2_fpcr_postincrement;
5563
fpufunctbl[mask] = & FFPU fpuop_fmovem_Mem_2_fpcr_fpiar_postincrement;
5566
fpufunctbl[mask] = & FFPU fpuop_fmovem_Mem_2_fpcr_fpsr_postincrement;
5569
fpufunctbl[mask] = & FFPU fpuop_fmovem_Mem_2_fpcr_fpsr_fpiar_postincrement;
5573
switch( extra & 0x1C00 ) {
5575
fpufunctbl[mask] = & FFPU fpuop_fmovem_Mem_2_none_2_Mem;
5578
fpufunctbl[mask] = & FFPU fpuop_fmovem_Mem_2_fpiar_2_Mem;
5581
fpufunctbl[mask] = & FFPU fpuop_fmovem_Mem_2_fpsr_2_Mem;
5584
fpufunctbl[mask] = & FFPU fpuop_fmovem_Mem_2_fpsr_fpiar_2_Mem;
5587
fpufunctbl[mask] = & FFPU fpuop_fmovem_Mem_2_fpcr_2_Mem;
5590
fpufunctbl[mask] = & FFPU fpuop_fmovem_Mem_2_fpcr_fpiar_2_Mem;
5593
fpufunctbl[mask] = & FFPU fpuop_fmovem_Mem_2_fpcr_fpsr_2_Mem;
5596
fpufunctbl[mask] = & FFPU fpuop_fmovem_Mem_2_fpcr_fpsr_fpiar_2_Mem;
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;
5609
fpufunctbl[mask] = & FFPU fpuop_fmovem_Mem_2_fpp_static_pred;
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;
5617
fpufunctbl[mask] = & FFPU fpuop_fmovem_Mem_2_fpp_dynamic_pred;
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;
5625
fpufunctbl[mask] = & FFPU fpuop_fmovem_Mem_2_fpp_static_postinc;
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;
5633
fpufunctbl[mask] = & FFPU fpuop_fmovem_Mem_2_fpp_dynamic_postinc;
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;
5645
fpufunctbl[mask] = & FFPU fpuop_fmovem_fpp_2_Mem_static_pred;
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;
5653
fpufunctbl[mask] = & FFPU fpuop_fmovem_fpp_2_Mem_dynamic_pred;
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;
5661
fpufunctbl[mask] = & FFPU fpuop_fmovem_fpp_2_Mem_static_postinc;
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;
5669
fpufunctbl[mask] = & FFPU fpuop_fmovem_fpp_2_Mem_dynamic_postinc;
5675
if ((extra & 0xfc00) == 0x5c00) {
5676
switch (extra & 0x7f) {
5678
fpufunctbl[mask] = & FFPU fpuop_do_fldpi;
5681
fpufunctbl[mask] = & FFPU fpuop_do_fldlg2;
5684
fpufunctbl[mask] = & FFPU fpuop_do_load_const_e;
5687
fpufunctbl[mask] = & FFPU fpuop_do_fldl2e;
5690
fpufunctbl[mask] = & FFPU fpuop_do_load_const_log_10_e;
5693
fpufunctbl[mask] = & FFPU fpuop_do_fldz;
5696
fpufunctbl[mask] = & FFPU fpuop_do_fldln2;
5699
fpufunctbl[mask] = & FFPU fpuop_do_load_const_ln_10;
5702
fpufunctbl[mask] = & FFPU fpuop_do_fld1;
5705
fpufunctbl[mask] = & FFPU fpuop_do_load_const_1e1;
5708
fpufunctbl[mask] = & FFPU fpuop_do_load_const_1e2;
5711
fpufunctbl[mask] = & FFPU fpuop_do_load_const_1e4;
5714
fpufunctbl[mask] = & FFPU fpuop_do_load_const_1e8;
5717
fpufunctbl[mask] = & FFPU fpuop_do_load_const_1e16;
5720
fpufunctbl[mask] = & FFPU fpuop_do_load_const_1e32;
5723
fpufunctbl[mask] = & FFPU fpuop_do_load_const_1e64;
5726
fpufunctbl[mask] = & FFPU fpuop_do_load_const_1e128;
5729
fpufunctbl[mask] = & FFPU fpuop_do_load_const_1e256;
5732
fpufunctbl[mask] = & FFPU fpuop_do_load_const_1e512;
5735
fpufunctbl[mask] = & FFPU fpuop_do_load_const_1e1024;
5738
fpufunctbl[mask] = & FFPU fpuop_do_load_const_1e2048;
5741
fpufunctbl[mask] = & FFPU fpuop_do_load_const_1e4096;
5747
switch (extra & 0x7f) {
5749
fpufunctbl[mask] = & FFPU fpuop_do_fmove;
5752
fpufunctbl[mask] = & FFPU fpuop_do_fint;
5755
fpufunctbl[mask] = & FFPU fpuop_do_fsinh;
5758
fpufunctbl[mask] = & FFPU fpuop_do_fintrz;
5761
fpufunctbl[mask] = & FFPU fpuop_do_fsqrt;
5764
fpufunctbl[mask] = & FFPU fpuop_do_flognp1;
5767
fpufunctbl[mask] = & FFPU fpuop_do_fetoxm1;
5770
fpufunctbl[mask] = & FFPU fpuop_do_ftanh;
5773
fpufunctbl[mask] = & FFPU fpuop_do_fatan;
5776
fpufunctbl[mask] = & FFPU fpuop_do_fasin;
5779
fpufunctbl[mask] = & FFPU fpuop_do_fatanh;
5782
fpufunctbl[mask] = & FFPU fpuop_do_fsin;
5785
fpufunctbl[mask] = & FFPU fpuop_do_ftan;
5788
fpufunctbl[mask] = & FFPU fpuop_do_fetox;
5791
fpufunctbl[mask] = & FFPU fpuop_do_ftwotox;
5794
fpufunctbl[mask] = & FFPU fpuop_do_ftentox;
5797
fpufunctbl[mask] = & FFPU fpuop_do_flogn;
5800
fpufunctbl[mask] = & FFPU fpuop_do_flog10;
5803
fpufunctbl[mask] = & FFPU fpuop_do_flog2;
5806
fpufunctbl[mask] = & FFPU fpuop_do_fabs;
5809
fpufunctbl[mask] = & FFPU fpuop_do_fcosh;
5812
fpufunctbl[mask] = & FFPU fpuop_do_fneg;
5815
fpufunctbl[mask] = & FFPU fpuop_do_facos;
5818
fpufunctbl[mask] = & FFPU fpuop_do_fcos;
5821
fpufunctbl[mask] = & FFPU fpuop_do_fgetexp;
5824
fpufunctbl[mask] = & FFPU fpuop_do_fgetman;
5827
fpufunctbl[mask] = & FFPU fpuop_do_fdiv;
5830
fpufunctbl[mask] = & FFPU fpuop_do_fmod;
5833
fpufunctbl[mask] = & FFPU fpuop_do_fadd;
5836
fpufunctbl[mask] = & FFPU fpuop_do_fmul;
5839
fpufunctbl[mask] = & FFPU fpuop_do_fsgldiv;
5842
fpufunctbl[mask] = & FFPU fpuop_do_frem;
5845
fpufunctbl[mask] = & FFPU fpuop_do_fscale;
5848
fpufunctbl[mask] = & FFPU fpuop_do_fsglmul;
5851
fpufunctbl[mask] = & FFPU fpuop_do_fsub;
5861
fpufunctbl[mask] = & FFPU fpuop_do_fsincos;
5864
fpufunctbl[mask] = & FFPU fpuop_do_fcmp;
5867
fpufunctbl[mask] = & FFPU fpuop_do_ftst;
5876
/* ---------------------------- CONSTANTS ---------------------------- */
5878
PRIVATE void FFPU set_constant ( fpu_register & f, char *name, double value, uae_s32 mult )
5880
FPU_CONSISTENCY_CHECK_START();
5884
FLD QWORD PTR [value]
5885
FSTP TBYTE PTR [ESI]
5887
__asm__ __volatile__(
5896
FILD DWORD PTR [mult]
5897
FLD QWORD PTR [value]
5899
FSTP TBYTE PTR [ESI]
5901
__asm__ __volatile__(
5907
: "m" (value), "m" (mult)
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)" );
5914
PRIVATE void FFPU do_fldpi ( fpu_register & dest )
5916
FPU_CONSISTENCY_CHECK_START();
5920
FNSTSW x86_status_word
5922
FSTP TBYTE PTR [EDI]
5924
__asm__ __volatile__(
5929
: "=m" (x86_status_word), "=m" (dest)
5931
FPU_CONSISTENCY_CHECK_STOP("do_fldpi");
5934
PRIVATE void FFPU do_fldlg2 ( fpu_register & dest )
5936
FPU_CONSISTENCY_CHECK_START();
5940
FNSTSW x86_status_word
5942
FSTP TBYTE PTR [EDI]
5944
__asm__ __volatile__(
5949
: "=m" (x86_status_word), "=m" (dest)
5951
FPU_CONSISTENCY_CHECK_STOP("do_fldlg2");
5954
PRIVATE void FFPU do_fldl2e ( fpu_register & dest )
5956
FPU_CONSISTENCY_CHECK_START();
5960
FNSTSW x86_status_word
5962
FSTP TBYTE PTR [EDI]
5964
__asm__ __volatile__(
5969
: "=m" (x86_status_word), "=m" (dest)
5971
FPU_CONSISTENCY_CHECK_STOP("do_fldl2e");
5974
PRIVATE void FFPU do_fldz ( fpu_register & dest )
5976
FPU_CONSISTENCY_CHECK_START();
5980
FNSTSW x86_status_word
5982
FSTP TBYTE PTR [EDI]
5984
__asm__ __volatile__(
5989
: "=m" (x86_status_word), "=m" (dest)
5991
FPU_CONSISTENCY_CHECK_STOP("do_fldz");
5994
PRIVATE void FFPU do_fldln2 ( fpu_register & dest )
5996
FPU_CONSISTENCY_CHECK_START();
6000
FNSTSW x86_status_word
6002
FSTP TBYTE PTR [EDI]
6004
__asm__ __volatile__(
6009
: "=m" (x86_status_word), "=m" (dest)
6011
FPU_CONSISTENCY_CHECK_STOP("do_fldln2");
6014
PRIVATE void FFPU do_fld1 ( fpu_register & dest )
6016
FPU_CONSISTENCY_CHECK_START();
6020
FNSTSW x86_status_word
6022
FSTP TBYTE PTR [EDI]
6024
__asm__ __volatile__(
6029
: "=m" (x86_status_word), "=m" (dest)
6031
FPU_CONSISTENCY_CHECK_STOP("do_fld1");
6035
/* ---------------------------- MAIN INIT ---------------------------- */
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 *)
6044
if (code == SIGFPE && sip->si_code == FPE_FLTINV) {
6045
fprintf(stderr, "Invalid floating point operation\n");
6051
PUBLIC void FFPU fpu_init( bool integral_68040 )
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);
6065
done_first_time_initialization = true;
6068
__asm__ __volatile__("fsave %0" : "=m" (m_fpu_state_original));
6070
FPU is_integral = integral_68040;
6071
FPU instruction_address = 0;
6075
x86_control_word = CW_INITIAL;
6076
x86_status_word = SW_INITIAL;
6077
x86_status_word_accrued = 0;
6078
FPU fpsr.quotient = 0;
6080
for( int i=0; i<8; i++ ) {
6081
MAKE_NAN( FPU registers[i] );
6084
build_fpp_opp_lookup_table();
6086
__asm__ __volatile__("fninit\nfldcw %0" : : "m" (x86_control_word));
6088
do_fldpi( const_pi );
6089
do_fldlg2( const_lg2 );
6090
do_fldl2e( const_l2e );
6092
do_fldln2( const_ln2 );
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 );
6113
__asm__ __volatile__("fninit\nfldcw %0" : : "m" (x86_control_word));
6116
PUBLIC void FFPU fpu_exit( void )
6118
__asm__ __volatile__("frstor %0" : : "m" (m_fpu_state_original));
6121
PUBLIC void FFPU fpu_reset( void )
6124
fpu_init(FPU is_integral);