~ubuntu-branches/ubuntu/lucid/basilisk2/lucid

« back to all changes in this revision

Viewing changes to src/uae_cpu/fpu/fpu_x86.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Jonas Smedegaard
  • Date: 2003-07-24 00:48:57 UTC
  • Revision ID: james.westby@ubuntu.com-20030724004857-vnv33v6vf7a7u0z6
Tags: upstream-0.9.20030722
ImportĀ upstreamĀ versionĀ 0.9.20030722

Show diffs side-by-side

added added

removed removed

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